Re: [PATCH 10/12] locks: break delegations on rename

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

 



On Wed,  3 Jul 2013 16:12:34 -0400
"J. Bruce Fields" <bfields@xxxxxxxxxx> wrote:

> From: "J. Bruce Fields" <bfields@xxxxxxxxxx>
> 
> Cc: David Howells <dhowells@xxxxxxxxxx>
> Signed-off-by: J. Bruce Fields <bfields@xxxxxxxxxx>
> ---
>  fs/cachefiles/namei.c |    2 +-
>  fs/namei.c            |   26 ++++++++++++++++++++++----
>  fs/nfsd/vfs.c         |    2 +-
>  include/linux/fs.h    |    2 +-
>  4 files changed, 25 insertions(+), 7 deletions(-)
> 
> diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c
> index d61d884..678a8af 100644
> --- a/fs/cachefiles/namei.c
> +++ b/fs/cachefiles/namei.c
> @@ -396,7 +396,7 @@ try_again:
>  		cachefiles_io_error(cache, "Rename security error %d", ret);
>  	} else {
>  		ret = vfs_rename(dir->d_inode, rep,
> -				 cache->graveyard->d_inode, grave);
> +				 cache->graveyard->d_inode, grave, NULL);
>  		if (ret != 0 && ret != -ENOMEM)
>  			cachefiles_io_error(cache,
>  					    "Rename failed with error %d", ret);
> diff --git a/fs/namei.c b/fs/namei.c
> index a9d4031..be00d37 100644
> --- a/fs/namei.c
> +++ b/fs/namei.c
> @@ -3763,7 +3763,8 @@ out:
>  }
>  
>  static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
> -			    struct inode *new_dir, struct dentry *new_dentry)
> +			    struct inode *new_dir, struct dentry *new_dentry,
> +			    struct inode **delegated_inode)
>  {
>  	struct inode *target = new_dentry->d_inode;
>  	struct inode *source = old_dentry->d_inode;
> @@ -3783,6 +3784,14 @@ static int vfs_rename_other(struct inode *old_dir, struct dentry *old_dentry,
>  	if (d_mountpoint(old_dentry)||d_mountpoint(new_dentry))
>  		goto out;
>  
> +	error = try_break_deleg(source, delegated_inode);
> +	if (error)
> +		goto out;
> +	if (target) {
> +		error = try_break_deleg(target, delegated_inode);
> +		if (error)
> +			goto out;
> +	}
>  	error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
>  	if (error)
>  		goto out;
> @@ -3801,7 +3810,8 @@ out:
>  }
>  
>  int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
> -	       struct inode *new_dir, struct dentry *new_dentry)
> +	       struct inode *new_dir, struct dentry *new_dentry,
> +	       struct inode **delegated_inode)
>  {
>  	int error;
>  	int is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
> @@ -3829,7 +3839,7 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
>  	if (is_dir)
>  		error = vfs_rename_dir(old_dir,old_dentry,new_dir,new_dentry);
>  	else
> -		error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry);
> +		error = vfs_rename_other(old_dir,old_dentry,new_dir,new_dentry,delegated_inode);
>  	if (!error)
>  		fsnotify_move(old_dir, new_dir, old_name, is_dir,
>  			      new_dentry->d_inode, old_dentry);
> @@ -3845,6 +3855,7 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
>  	struct dentry *old_dentry, *new_dentry;
>  	struct dentry *trap;
>  	struct nameidata oldnd, newnd;
> +	struct inode *delegated_inode = NULL;
>  	struct filename *from;
>  	struct filename *to;
>  	unsigned int lookup_flags = 0;
> @@ -3884,6 +3895,7 @@ retry:
>  	newnd.flags &= ~LOOKUP_PARENT;
>  	newnd.flags |= LOOKUP_RENAME_TARGET;
>  
> +retry_deleg:
>  	trap = lock_rename(new_dir, old_dir);
>  
>  	old_dentry = lookup_hash(&oldnd);
> @@ -3920,13 +3932,19 @@ retry:
>  	if (error)
>  		goto exit5;
>  	error = vfs_rename(old_dir->d_inode, old_dentry,
> -				   new_dir->d_inode, new_dentry);
> +				   new_dir->d_inode, new_dentry,
> +				   &delegated_inode);
>  exit5:
>  	dput(new_dentry);
>  exit4:
>  	dput(old_dentry);
>  exit3:
>  	unlock_rename(new_dir, old_dir);
> +	if (delegated_inode) {
> +		error = break_deleg_wait(&delegated_inode);
> +		if (!error)
> +			goto retry_deleg;
> +	}
>  	mnt_drop_write(oldnd.path.mnt);
>  exit2:
>  	if (retry_estale(error, lookup_flags))
> diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> index 6ccaca2..54ac814 100644
> --- a/fs/nfsd/vfs.c
> +++ b/fs/nfsd/vfs.c
> @@ -1809,7 +1809,7 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
>  		if (host_err)
>  			goto out_dput_new;
>  	}
> -	host_err = vfs_rename(fdir, odentry, tdir, ndentry);
> +	host_err = vfs_rename(fdir, odentry, tdir, ndentry, NULL);
>  	if (!host_err) {
>  		host_err = commit_metadata(tfhp);
>  		if (!host_err)
> diff --git a/include/linux/fs.h b/include/linux/fs.h
> index c37e463..a35dadb 100644
> --- a/include/linux/fs.h
> +++ b/include/linux/fs.h
> @@ -1464,7 +1464,7 @@ extern int vfs_symlink(struct inode *, struct dentry *, const char *);
>  extern int vfs_link(struct dentry *, struct inode *, struct dentry *);
>  extern int vfs_rmdir(struct inode *, struct dentry *);
>  extern int vfs_unlink(struct inode *, struct dentry *, struct inode **);
> -extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
> +extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *, struct inode **);
>  
>  /*
>   * VFS dentry helper functions.

Acked-by: Jeff Layton <jlayton@xxxxxxxxxx>
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux