Commit b7600dba authored by David Woodhouse's avatar David Woodhouse

[JFFS2] Fix allocation of summary buffer

We can't use vmalloc for the buffer we use for writing summaries,
because some drivers may want to DMA from it. So limit the size to 64KiB
and use kmalloc for it instead.
Signed-off-by: default avatarDavid Woodhouse <David.Woodhouse@intel.com>
parent f6ed6f78
...@@ -23,6 +23,8 @@ ...@@ -23,6 +23,8 @@
int jffs2_sum_init(struct jffs2_sb_info *c) int jffs2_sum_init(struct jffs2_sb_info *c)
{ {
uint32_t sum_size = max_t(uint32_t, c->sector_size, MAX_SUMMARY_SIZE);
c->summary = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL); c->summary = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
if (!c->summary) { if (!c->summary) {
...@@ -30,7 +32,7 @@ int jffs2_sum_init(struct jffs2_sb_info *c) ...@@ -30,7 +32,7 @@ int jffs2_sum_init(struct jffs2_sb_info *c)
return -ENOMEM; return -ENOMEM;
} }
c->summary->sum_buf = vmalloc(c->sector_size); c->summary->sum_buf = kmalloc(sum_size, GFP_KERNEL);
if (!c->summary->sum_buf) { if (!c->summary->sum_buf) {
JFFS2_WARNING("Can't allocate buffer for writing out summary information!\n"); JFFS2_WARNING("Can't allocate buffer for writing out summary information!\n");
...@@ -49,7 +51,7 @@ void jffs2_sum_exit(struct jffs2_sb_info *c) ...@@ -49,7 +51,7 @@ void jffs2_sum_exit(struct jffs2_sb_info *c)
jffs2_sum_disable_collecting(c->summary); jffs2_sum_disable_collecting(c->summary);
vfree(c->summary->sum_buf); kfree(c->summary->sum_buf);
c->summary->sum_buf = NULL; c->summary->sum_buf = NULL;
kfree(c->summary); kfree(c->summary);
...@@ -665,7 +667,7 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb ...@@ -665,7 +667,7 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
/* Write summary data to flash - helper function for jffs2_sum_write_sumnode() */ /* Write summary data to flash - helper function for jffs2_sum_write_sumnode() */
static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
uint32_t infosize, uint32_t datasize, int padsize) uint32_t infosize, uint32_t datasize, int padsize)
{ {
struct jffs2_raw_summary isum; struct jffs2_raw_summary isum;
union jffs2_sum_mem *temp; union jffs2_sum_mem *temp;
...@@ -676,6 +678,26 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock ...@@ -676,6 +678,26 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock
int ret; int ret;
size_t retlen; size_t retlen;
if (padsize + datasize > MAX_SUMMARY_SIZE) {
/* It won't fit in the buffer. Abort summary for this jeb */
jffs2_sum_disable_collecting(c->summary);
JFFS2_WARNING("Summary too big (%d data, %d pad) in eraseblock at %08x\n",
datasize, padsize, jeb->offset);
/* Non-fatal */
return 0;
}
/* Is there enough space for summary? */
if (padsize < 0) {
/* don't try to write out summary for this jeb */
jffs2_sum_disable_collecting(c->summary);
JFFS2_WARNING("Not enough space for summary, padsize = %d\n",
padsize);
/* Non-fatal */
return 0;
}
memset(c->summary->sum_buf, 0xff, datasize); memset(c->summary->sum_buf, 0xff, datasize);
memset(&isum, 0, sizeof(isum)); memset(&isum, 0, sizeof(isum));
...@@ -821,7 +843,7 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) ...@@ -821,7 +843,7 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
{ {
int datasize, infosize, padsize; int datasize, infosize, padsize;
struct jffs2_eraseblock *jeb; struct jffs2_eraseblock *jeb;
int ret; int ret = 0;
dbg_summary("called\n"); dbg_summary("called\n");
...@@ -841,16 +863,6 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) ...@@ -841,16 +863,6 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c)
infosize += padsize; infosize += padsize;
datasize += padsize; datasize += padsize;
/* Is there enough space for summary? */
if (padsize < 0) {
/* don't try to write out summary for this jeb */
jffs2_sum_disable_collecting(c->summary);
JFFS2_WARNING("Not enough space for summary, padsize = %d\n", padsize);
spin_lock(&c->erase_completion_lock);
return 0;
}
ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize); ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize);
spin_lock(&c->erase_completion_lock); spin_lock(&c->erase_completion_lock);
return ret; return ret;
......
...@@ -13,6 +13,12 @@ ...@@ -13,6 +13,12 @@
#ifndef JFFS2_SUMMARY_H #ifndef JFFS2_SUMMARY_H
#define JFFS2_SUMMARY_H #define JFFS2_SUMMARY_H
/* Limit summary size to 64KiB so that we can kmalloc it. If the summary
is larger than that, we have to just ditch it and avoid using summary
for the eraseblock in question... and it probably doesn't hurt us much
anyway. */
#define MAX_SUMMARY_SIZE 65536
#include <linux/uio.h> #include <linux/uio.h>
#include <linux/jffs2.h> #include <linux/jffs2.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment