Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

+32 -14
+26 -14
fs/jffs2/summary.c
··· 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) { ··· 32 30 return -ENOMEM; 33 31 } 34 32 35 - c->summary->sum_buf = vmalloc(c->sector_size); 33 + c->summary->sum_buf = kmalloc(sum_size, GFP_KERNEL); 36 34 37 35 if (!c->summary->sum_buf) { 38 36 JFFS2_WARNING("Can't allocate buffer for writing out summary information!\n"); ··· 51 49 52 50 jffs2_sum_disable_collecting(c->summary); 53 51 54 - vfree(c->summary->sum_buf); 52 + kfree(c->summary->sum_buf); 55 53 c->summary->sum_buf = NULL; 56 54 57 55 kfree(c->summary); ··· 667 665 /* Write summary data to flash - helper function for jffs2_sum_write_sumnode() */ 668 666 669 667 static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, 670 - uint32_t infosize, uint32_t datasize, int padsize) 668 + uint32_t infosize, uint32_t datasize, int padsize) 671 669 { 672 670 struct jffs2_raw_summary isum; 673 671 union jffs2_sum_mem *temp; ··· 677 675 void *wpage; 678 676 int ret; 679 677 size_t retlen; 678 + 679 + if (padsize + datasize > MAX_SUMMARY_SIZE) { 680 + /* It won't fit in the buffer. Abort summary for this jeb */ 681 + jffs2_sum_disable_collecting(c->summary); 682 + 683 + JFFS2_WARNING("Summary too big (%d data, %d pad) in eraseblock at %08x\n", 684 + datasize, padsize, jeb->offset); 685 + /* Non-fatal */ 686 + return 0; 687 + } 688 + /* Is there enough space for summary? */ 689 + if (padsize < 0) { 690 + /* don't try to write out summary for this jeb */ 691 + jffs2_sum_disable_collecting(c->summary); 692 + 693 + JFFS2_WARNING("Not enough space for summary, padsize = %d\n", 694 + padsize); 695 + /* Non-fatal */ 696 + return 0; 697 + } 680 698 681 699 memset(c->summary->sum_buf, 0xff, datasize); 682 700 memset(&isum, 0, sizeof(isum)); ··· 843 821 { 844 822 int datasize, infosize, padsize; 845 823 struct jffs2_eraseblock *jeb; 846 - int ret; 824 + int ret = 0; 847 825 848 826 dbg_summary("called\n"); 849 827 ··· 862 840 padsize = jeb->free_size - infosize; 863 841 infosize += padsize; 864 842 datasize += padsize; 865 - 866 - /* Is there enough space for summary? */ 867 - if (padsize < 0) { 868 - /* don't try to write out summary for this jeb */ 869 - jffs2_sum_disable_collecting(c->summary); 870 - 871 - JFFS2_WARNING("Not enough space for summary, padsize = %d\n", padsize); 872 - spin_lock(&c->erase_completion_lock); 873 - return 0; 874 - } 875 843 876 844 ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize); 877 845 spin_lock(&c->erase_completion_lock);
+6
fs/jffs2/summary.h
··· 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