diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index 629af01e5ade..6caf1e1ee26d 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -23,6 +23,8 @@ 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); if (!c->summary) { @@ -30,7 +32,7 @@ int jffs2_sum_init(struct jffs2_sb_info *c) return -ENOMEM; } - c->summary->sum_buf = vmalloc(c->sector_size); + c->summary->sum_buf = kmalloc(sum_size, GFP_KERNEL); if (!c->summary->sum_buf) { 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) jffs2_sum_disable_collecting(c->summary); - vfree(c->summary->sum_buf); + kfree(c->summary->sum_buf); c->summary->sum_buf = NULL; kfree(c->summary); @@ -665,7 +667,7 @@ crc_err: /* 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, - uint32_t infosize, uint32_t datasize, int padsize) + uint32_t infosize, uint32_t datasize, int padsize) { struct jffs2_raw_summary isum; union jffs2_sum_mem *temp; @@ -676,6 +678,26 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock int ret; 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(&isum, 0, sizeof(isum)); @@ -821,7 +843,7 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) { int datasize, infosize, padsize; struct jffs2_eraseblock *jeb; - int ret; + int ret = 0; dbg_summary("called\n"); @@ -841,16 +863,6 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) infosize += 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); spin_lock(&c->erase_completion_lock); return ret; diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h index 8bf34f2fa5ce..60207a2ae952 100644 --- a/fs/jffs2/summary.h +++ b/fs/jffs2/summary.h @@ -13,6 +13,12 @@ #ifndef 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 #include