Re: [PATCH 3.17-stable] GFS2: Make rename not save dirent location

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]