Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8557fd51 authored by Artem B. Bityuckiy's avatar Artem B. Bityuckiy Committed by Thomas Gleixner
Browse files

[JFFS2] Fix race in garbage collector

parent abc37e67
Loading
Loading
Loading
Loading
+24 −6
Original line number Original line Diff line number Diff line
@@ -7,7 +7,7 @@
 *
 *
 * For licensing information, see the file 'LICENCE' in this directory.
 * For licensing information, see the file 'LICENCE' in this directory.
 *
 *
 * $Id: gc.c,v 1.147 2005/03/20 21:43:22 dedekind Exp $
 * $Id: gc.c,v 1.148 2005/04/09 10:47:00 dedekind Exp $
 *
 *
 */
 */


@@ -669,9 +669,10 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
{
{
	struct jffs2_full_dnode *new_fn;
	struct jffs2_full_dnode *new_fn;
	struct jffs2_raw_inode ri;
	struct jffs2_raw_inode ri;
	struct jffs2_node_frag *last_frag;
	jint16_t dev;
	jint16_t dev;
	char *mdata = NULL, mdatalen = 0;
	char *mdata = NULL, mdatalen = 0;
	uint32_t alloclen, phys_ofs;
	uint32_t alloclen, phys_ofs, ilen;
	int ret;
	int ret;


	if (S_ISBLK(JFFS2_F_I_MODE(f)) ||
	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_
		goto out;
		goto out;
	}
	}
	
	
	last_frag = frag_last(&f->fragtree);
	if (last_frag)
		/* Fetch the inode length from the fragtree rather then
		 * from i_size since i_size may have not been updated yet */
		ilen = last_frag->ofs + last_frag->size;
	else
		ilen = JFFS2_F_I_SIZE(f);
	
	memset(&ri, 0, sizeof(ri));
	memset(&ri, 0, sizeof(ri));
	ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
	ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
	ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
	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_
	ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f));
	ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f));
	ri.uid = cpu_to_je16(JFFS2_F_I_UID(f));
	ri.uid = cpu_to_je16(JFFS2_F_I_UID(f));
	ri.gid = cpu_to_je16(JFFS2_F_I_GID(f));
	ri.gid = cpu_to_je16(JFFS2_F_I_GID(f));
	ri.isize = cpu_to_je32(JFFS2_F_I_SIZE(f));
	ri.isize = cpu_to_je32(ilen);
	ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f));
	ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f));
	ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f));
	ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f));
	ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f));
	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
	struct jffs2_raw_inode ri;
	struct jffs2_raw_inode ri;
	struct jffs2_node_frag *frag;
	struct jffs2_node_frag *frag;
	struct jffs2_full_dnode *new_fn;
	struct jffs2_full_dnode *new_fn;
	uint32_t alloclen, phys_ofs;
	uint32_t alloclen, phys_ofs, ilen;
	int ret;
	int ret;


	D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%u from offset 0x%x to 0x%x\n",
	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
		ri.csize = cpu_to_je32(0);
		ri.csize = cpu_to_je32(0);
		ri.compr = JFFS2_COMPR_ZERO;
		ri.compr = JFFS2_COMPR_ZERO;
	}
	}
	
	frag = frag_last(&f->fragtree);
	if (frag)
		/* Fetch the inode length from the fragtree rather then
		 * from i_size since i_size may have not been updated yet */
		ilen = frag->ofs + frag->size;
	else
		ilen = JFFS2_F_I_SIZE(f);

	ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f));
	ri.mode = cpu_to_jemode(JFFS2_F_I_MODE(f));
	ri.uid = cpu_to_je16(JFFS2_F_I_UID(f));
	ri.uid = cpu_to_je16(JFFS2_F_I_UID(f));
	ri.gid = cpu_to_je16(JFFS2_F_I_GID(f));
	ri.gid = cpu_to_je16(JFFS2_F_I_GID(f));
	ri.isize = cpu_to_je32(JFFS2_F_I_SIZE(f));
	ri.isize = cpu_to_je32(ilen);
	ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f));
	ri.atime = cpu_to_je32(JFFS2_F_I_ATIME(f));
	ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f));
	ri.ctime = cpu_to_je32(JFFS2_F_I_CTIME(f));
	ri.mtime = cpu_to_je32(JFFS2_F_I_MTIME(f));
	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
		D1(printk(KERN_DEBUG "Expanded dnode to write from (0x%x-0x%x) to (0x%x-0x%x)\n", 
		D1(printk(KERN_DEBUG "Expanded dnode to write from (0x%x-0x%x) to (0x%x-0x%x)\n", 
			  orig_start, orig_end, start, end));
			  orig_start, orig_end, start, end));


		BUG_ON(end > JFFS2_F_I_SIZE(f));
		D1(BUG_ON(end > frag_last(&f->fragtree)->ofs + frag_last(&f->fragtree)->size));
		BUG_ON(end < orig_end);
		BUG_ON(end < orig_end);
		BUG_ON(start > orig_start);
		BUG_ON(start > orig_start);
	}
	}
+13 −1
Original line number Original line Diff line number Diff line
@@ -7,7 +7,7 @@
 *
 *
 * For licensing information, see the file 'LICENCE' in this directory.
 * For licensing information, see the file 'LICENCE' in this directory.
 *
 *
 * $Id: nodelist.h,v 1.128 2005/02/27 23:01:32 dwmw2 Exp $
 * $Id: nodelist.h,v 1.130 2005/04/09 10:46:59 dedekind Exp $
 *
 *
 */
 */


@@ -363,6 +363,18 @@ static inline struct jffs2_node_frag *frag_first(struct rb_root *root)
		node = node->rb_left;
		node = node->rb_left;
	return rb_entry(node, struct jffs2_node_frag, rb);
	return rb_entry(node, struct jffs2_node_frag, rb);
}
}

static inline struct jffs2_node_frag *frag_last(struct rb_root *root)
{
	struct rb_node *node = root->rb_node;

	if (!node)
		return NULL;
	while(node->rb_right)
		node = node->rb_right;
	return rb_entry(node, struct jffs2_node_frag, rb);
}

#define rb_parent(rb) ((rb)->rb_parent)
#define rb_parent(rb) ((rb)->rb_parent)
#define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb)
#define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb)
#define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb)
#define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb)