aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtem B. Bityuckiy <dedekind@infradead.org>2005-04-09 06:47:03 -0400
committerThomas Gleixner <tglx@mtd.linutronix.de>2005-05-23 07:16:47 -0400
commit8557fd51c22e4c2109f062decd19de439061ceae (patch)
tree66884a832e912decd06a8441db05fd78ec8e3e6e
parentabc37e6771ec92bb4c531d218ad572afbef6aa21 (diff)
[JFFS2] Fix race in garbage collector
Fix the race problem described here: http://lists.infradead.org/pipermail/linux-mtd/2005-April/012361.html Signed-off-by: Artem B. Bityuckiy <dedekind@infradead.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--fs/jffs2/gc.c30
-rw-r--r--fs/jffs2/nodelist.h14
2 files changed, 37 insertions, 7 deletions
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 694bc90ad779..7086cd634503 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -7,7 +7,7 @@
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: gc.c,v 1.147 2005/03/20 21:43:22 dedekind Exp $ 10 * $Id: gc.c,v 1.148 2005/04/09 10:47:00 dedekind Exp $
11 * 11 *
12 */ 12 */
13 13
@@ -669,9 +669,10 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
669{ 669{
670 struct jffs2_full_dnode *new_fn; 670 struct jffs2_full_dnode *new_fn;
671 struct jffs2_raw_inode ri; 671 struct jffs2_raw_inode ri;
672 struct jffs2_node_frag *last_frag;
672 jint16_t dev; 673 jint16_t dev;
673 char *mdata = NULL, mdatalen = 0; 674 char *mdata = NULL, mdatalen = 0;
674 uint32_t alloclen, phys_ofs; 675 uint32_t alloclen, phys_ofs, ilen;
675 int ret; 676 int ret;
676 677
677 if (S_ISBLK(JFFS2_F_I_MODE(f)) || 678 if (S_ISBLK(JFFS2_F_I_MODE(f)) ||
@@ -707,6 +708,14 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
707 goto out; 708 goto out;
708 } 709 }
709 710
711 last_frag = frag_last(&f->fragtree);
712 if (last_frag)
713 /* Fetch the inode length from the fragtree rather then
714 * from i_size since i_size may have not been updated yet */
715 ilen = last_frag->ofs + last_frag->size;
716 else
717 ilen = JFFS2_F_I_SIZE(f);
718
710 memset(&ri, 0, sizeof(ri)); 719 memset(&ri, 0, sizeof(ri));
711 ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 720 ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
712 ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); 721 ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
@@ -718,7 +727,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
718 ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f)); 727 ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f));
719 ri.uid = cpu_to_je16(JFFS2_F_I_UID(f)); 728 ri.uid = cpu_to_je16(JFFS2_F_I_UID(f));
720 ri.gid = cpu_to_je16(JFFS2_F_I_GID(f)); 729 ri.gid = cpu_to_je16(JFFS2_F_I_GID(f));
721 ri.isize = cpu_to_je32(JFFS2_F_I_SIZE(f)); 730 ri.isize = cpu_to_je32(ilen);
722 ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f)); 731 ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f));
723 ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f)); 732 ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f));
724 ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f)); 733 ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f));
@@ -898,7 +907,7 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras
898 struct jffs2_raw_inode ri; 907 struct jffs2_raw_inode ri;
899 struct jffs2_node_frag *frag; 908 struct jffs2_node_frag *frag;
900 struct jffs2_full_dnode *new_fn; 909 struct jffs2_full_dnode *new_fn;
901 uint32_t alloclen, phys_ofs; 910 uint32_t alloclen, phys_ofs, ilen;
902 int ret; 911 int ret;
903 912
904 D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%u from offset 0x%x to 0x%x\n", 913 D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%u from offset 0x%x to 0x%x\n",
@@ -958,10 +967,19 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras
958 ri.csize = cpu_to_je32(0); 967 ri.csize = cpu_to_je32(0);
959 ri.compr = JFFS2_COMPR_ZERO; 968 ri.compr = JFFS2_COMPR_ZERO;
960 } 969 }
970
971 frag = frag_last(&f->fragtree);
972 if (frag)
973 /* Fetch the inode length from the fragtree rather then
974 * from i_size since i_size may have not been updated yet */
975 ilen = frag->ofs + frag->size;
976 else
977 ilen = JFFS2_F_I_SIZE(f);
978
961 ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f)); 979 ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f));
962 ri.uid = cpu_to_je16(JFFS2_F_I_UID(f)); 980 ri.uid = cpu_to_je16(JFFS2_F_I_UID(f));
963 ri.gid = cpu_to_je16(JFFS2_F_I_GID(f)); 981 ri.gid = cpu_to_je16(JFFS2_F_I_GID(f));
964 ri.isize = cpu_to_je32(JFFS2_F_I_SIZE(f)); 982 ri.isize = cpu_to_je32(ilen);
965 ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f)); 983 ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f));
966 ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f)); 984 ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f));
967 ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f)); 985 ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f));
@@ -1168,7 +1186,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era
1168 D1(printk(KERN_DEBUG "Expanded dnode to write from (0x%x-0x%x) to (0x%x-0x%x)\n", 1186 D1(printk(KERN_DEBUG "Expanded dnode to write from (0x%x-0x%x) to (0x%x-0x%x)\n",
1169 orig_start, orig_end, start, end)); 1187 orig_start, orig_end, start, end));
1170 1188
1171 BUG_ON(end > JFFS2_F_I_SIZE(f)); 1189 D1(BUG_ON(end > frag_last(&f->fragtree)->ofs + frag_last(&f->fragtree)->size));
1172 BUG_ON(end < orig_end); 1190 BUG_ON(end < orig_end);
1173 BUG_ON(start > orig_start); 1191 BUG_ON(start > orig_start);
1174 } 1192 }
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
index 57f675c2c97f..a65539f28b06 100644
--- a/fs/jffs2/nodelist.h
+++ b/fs/jffs2/nodelist.h
@@ -7,7 +7,7 @@
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 * $Id: nodelist.h,v 1.128 2005/02/27 23:01:32 dwmw2 Exp $ 10 * $Id: nodelist.h,v 1.130 2005/04/09 10:46:59 dedekind Exp $
11 * 11 *
12 */ 12 */
13 13
@@ -363,6 +363,18 @@ static inline struct jffs2_node_frag *frag_first(struct rb_root *root)
363 node = node->rb_left; 363 node = node->rb_left;
364 return rb_entry(node, struct jffs2_node_frag, rb); 364 return rb_entry(node, struct jffs2_node_frag, rb);
365} 365}
366
367static inline struct jffs2_node_frag *frag_last(struct rb_root *root)
368{
369 struct rb_node *node = root->rb_node;
370
371 if (!node)
372 return NULL;
373 while(node->rb_right)
374 node = node->rb_right;
375 return rb_entry(node, struct jffs2_node_frag, rb);
376}
377
366#define rb_parent(rb) ((rb)->rb_parent) 378#define rb_parent(rb) ((rb)->rb_parent)
367#define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb) 379#define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb)
368#define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb) 380#define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb)