Commit b7600dba6d4fbf3897e517b322d006986cce831a

Authored by David Woodhouse
1 parent f6ed6f78d4

[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: David Woodhouse <David.Woodhouse@intel.com>

Showing 2 changed files with 32 additions and 14 deletions Side-by-side Diff

... ... @@ -23,6 +23,8 @@
23 23  
24 24 int jffs2_sum_init(struct jffs2_sb_info *c)
25 25 {
  26 + uint32_t sum_size = max_t(uint32_t, c->sector_size, MAX_SUMMARY_SIZE);
  27 +
26 28 c->summary = kzalloc(sizeof(struct jffs2_summary), GFP_KERNEL);
27 29  
28 30 if (!c->summary) {
... ... @@ -30,7 +32,7 @@
30 32 return -ENOMEM;
31 33 }
32 34  
33   - c->summary->sum_buf = vmalloc(c->sector_size);
  35 + c->summary->sum_buf = kmalloc(sum_size, GFP_KERNEL);
34 36  
35 37 if (!c->summary->sum_buf) {
36 38 JFFS2_WARNING("Can't allocate buffer for writing out summary information!\n");
... ... @@ -49,7 +51,7 @@
49 51  
50 52 jffs2_sum_disable_collecting(c->summary);
51 53  
52   - vfree(c->summary->sum_buf);
  54 + kfree(c->summary->sum_buf);
53 55 c->summary->sum_buf = NULL;
54 56  
55 57 kfree(c->summary);
... ... @@ -665,7 +667,7 @@
665 667 /* Write summary data to flash - helper function for jffs2_sum_write_sumnode() */
666 668  
667 669 static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
668   - uint32_t infosize, uint32_t datasize, int padsize)
  670 + uint32_t infosize, uint32_t datasize, int padsize)
669 671 {
670 672 struct jffs2_raw_summary isum;
671 673 union jffs2_sum_mem *temp;
... ... @@ -676,6 +678,26 @@
676 678 int ret;
677 679 size_t retlen;
678 680  
  681 + if (padsize + datasize > MAX_SUMMARY_SIZE) {
  682 + /* It won't fit in the buffer. Abort summary for this jeb */
  683 + jffs2_sum_disable_collecting(c->summary);
  684 +
  685 + JFFS2_WARNING("Summary too big (%d data, %d pad) in eraseblock at %08x\n",
  686 + datasize, padsize, jeb->offset);
  687 + /* Non-fatal */
  688 + return 0;
  689 + }
  690 + /* Is there enough space for summary? */
  691 + if (padsize < 0) {
  692 + /* don't try to write out summary for this jeb */
  693 + jffs2_sum_disable_collecting(c->summary);
  694 +
  695 + JFFS2_WARNING("Not enough space for summary, padsize = %d\n",
  696 + padsize);
  697 + /* Non-fatal */
  698 + return 0;
  699 + }
  700 +
679 701 memset(c->summary->sum_buf, 0xff, datasize);
680 702 memset(&isum, 0, sizeof(isum));
681 703  
... ... @@ -821,7 +843,7 @@
821 843 {
822 844 int datasize, infosize, padsize;
823 845 struct jffs2_eraseblock *jeb;
824   - int ret;
  846 + int ret = 0;
825 847  
826 848 dbg_summary("called\n");
827 849  
... ... @@ -840,16 +862,6 @@
840 862 padsize = jeb->free_size - infosize;
841 863 infosize += padsize;
842 864 datasize += padsize;
843   -
844   - /* Is there enough space for summary? */
845   - if (padsize < 0) {
846   - /* don't try to write out summary for this jeb */
847   - jffs2_sum_disable_collecting(c->summary);
848   -
849   - JFFS2_WARNING("Not enough space for summary, padsize = %d\n", padsize);
850   - spin_lock(&c->erase_completion_lock);
851   - return 0;
852   - }
853 865  
854 866 ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize);
855 867 spin_lock(&c->erase_completion_lock);
... ... @@ -13,6 +13,12 @@
13 13 #ifndef JFFS2_SUMMARY_H
14 14 #define JFFS2_SUMMARY_H
15 15  
  16 +/* Limit summary size to 64KiB so that we can kmalloc it. If the summary
  17 + is larger than that, we have to just ditch it and avoid using summary
  18 + for the eraseblock in question... and it probably doesn't hurt us much
  19 + anyway. */
  20 +#define MAX_SUMMARY_SIZE 65536
  21 +
16 22 #include <linux/uio.h>
17 23 #include <linux/jffs2.h>
18 24