On Fri, Nov 07, 2014 at 09:54:13AM +0000, Andrew Price wrote: > From: Bob Peterson <rpeterso@xxxxxxxxxx> > > [ Upstream commit 19aeb5a65f1a6504fc665466c188241e7393d66f ] > Thank you, I'll queue this for the 3.16 kernel as well. Cheers, -- Luís > This patch fixes a regression in the patch "GFS2: Remember directory > insert point", commit 2b47dad866d04f14c328f888ba5406057b8c7d33. > The problem had to do with the rename function: The function found > space for the new dirent, and remembered that location. But then the > old dirent was removed, which often moved the eligible location for > the renamed dirent. Putting the new dirent at the saved location > caused file system corruption. > > This patch adds a new "save_loc" variable to struct gfs2_diradd. > If 1, the dirent location is saved. If 0, the dirent location is not > saved and the buffer_head is released as per previous behavior. > > Signed-off-by: Bob Peterson <rpeterso@xxxxxxxxxx> > Signed-off-by: Steven Whitehouse <swhiteho@xxxxxxxxxx> > --- > fs/gfs2/dir.c | 9 +++++++-- > fs/gfs2/dir.h | 1 + > fs/gfs2/inode.c | 6 +++--- > 3 files changed, 11 insertions(+), 5 deletions(-) > > diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c > index 1a349f9..5d4261f 100644 > --- a/fs/gfs2/dir.c > +++ b/fs/gfs2/dir.c > @@ -2100,8 +2100,13 @@ int gfs2_diradd_alloc_required(struct inode *inode, const struct qstr *name, > } > if (IS_ERR(dent)) > return PTR_ERR(dent); > - da->bh = bh; > - da->dent = dent; > + > + if (da->save_loc) { > + da->bh = bh; > + da->dent = dent; > + } else { > + brelse(bh); > + } > return 0; > } > > diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h > index 126c65d..e1b309c 100644 > --- a/fs/gfs2/dir.h > +++ b/fs/gfs2/dir.h > @@ -23,6 +23,7 @@ struct gfs2_diradd { > unsigned nr_blocks; > struct gfs2_dirent *dent; > struct buffer_head *bh; > + int save_loc; > }; > > extern struct inode *gfs2_dir_search(struct inode *dir, > diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c > index 9516f5c..fcf42ea 100644 > --- a/fs/gfs2/inode.c > +++ b/fs/gfs2/inode.c > @@ -600,7 +600,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, > int error, free_vfs_inode = 0; > u32 aflags = 0; > unsigned blocks = 1; > - struct gfs2_diradd da = { .bh = NULL, }; > + struct gfs2_diradd da = { .bh = NULL, .save_loc = 1, }; > > if (!name->len || name->len > GFS2_FNAMESIZE) > return -ENAMETOOLONG; > @@ -900,7 +900,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, > struct gfs2_inode *ip = GFS2_I(inode); > struct gfs2_holder ghs[2]; > struct buffer_head *dibh; > - struct gfs2_diradd da = { .bh = NULL, }; > + struct gfs2_diradd da = { .bh = NULL, .save_loc = 1, }; > int error; > > if (S_ISDIR(inode->i_mode)) > @@ -1338,7 +1338,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, > struct gfs2_rgrpd *nrgd; > unsigned int num_gh; > int dir_rename = 0; > - struct gfs2_diradd da = { .nr_blocks = 0, }; > + struct gfs2_diradd da = { .nr_blocks = 0, .save_loc = 0, }; > unsigned int x; > int error; > > -- > 1.9.3 > > -- > To unsubscribe from this list: send the line "unsubscribe stable" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html