On Wed, 3 Jul 2013 16:12:35 -0400 "J. Bruce Fields" <bfields@xxxxxxxxxx> wrote: > From: "J. Bruce Fields" <bfields@xxxxxxxxxx> > > Cc: Tyler Hicks <tyhicks@xxxxxxxxxxxxx> > Cc: Dustin Kirkland <dustin.kirkland@xxxxxxxxxxx> > Signed-off-by: J. Bruce Fields <bfields@xxxxxxxxxx> > --- > fs/ecryptfs/inode.c | 2 +- > fs/namei.c | 17 +++++++++++++---- > fs/nfsd/vfs.c | 2 +- > include/linux/fs.h | 2 +- > 4 files changed, 16 insertions(+), 7 deletions(-) > > diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c > index af42d88..19e4435 100644 > --- a/fs/ecryptfs/inode.c > +++ b/fs/ecryptfs/inode.c > @@ -475,7 +475,7 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir, > dget(lower_new_dentry); > lower_dir_dentry = lock_parent(lower_new_dentry); > rc = vfs_link(lower_old_dentry, lower_dir_dentry->d_inode, > - lower_new_dentry); > + lower_new_dentry, NULL); > if (rc || !lower_new_dentry->d_inode) > goto out_lock; > rc = ecryptfs_interpose(lower_new_dentry, new_dentry, dir->i_sb); > diff --git a/fs/namei.c b/fs/namei.c > index be00d37..18267e0 100644 > --- a/fs/namei.c > +++ b/fs/namei.c > @@ -3566,7 +3566,7 @@ SYSCALL_DEFINE2(symlink, const char __user *, oldname, const char __user *, newn > return sys_symlinkat(oldname, AT_FDCWD, newname); > } > > -int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) > +int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry, struct inode **delegated_inode) A kerneldoc comment would be nice here. Ditto for vfs_rename* in the previous patch... > { > struct inode *inode = old_dentry->d_inode; > unsigned max_links = dir->i_sb->s_max_links; > @@ -3602,8 +3602,11 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de > error = -ENOENT; > else if (max_links && inode->i_nlink >= max_links) > error = -EMLINK; > - else > - error = dir->i_op->link(old_dentry, dir, new_dentry); > + else { > + error = try_break_deleg(inode, delegated_inode); > + if (!error) > + error = dir->i_op->link(old_dentry, dir, new_dentry); > + } > mutex_unlock(&inode->i_mutex); > if (!error) > fsnotify_link(dir, inode, new_dentry); > @@ -3624,6 +3627,7 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname, > { > struct dentry *new_dentry; > struct path old_path, new_path; > + struct inode *delegated_inode = NULL; > int how = 0; > int error; > > @@ -3662,9 +3666,14 @@ retry: > error = security_path_link(old_path.dentry, &new_path, new_dentry); > if (error) > goto out_dput; > - error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry); > + error = vfs_link(old_path.dentry, new_path.dentry->d_inode, new_dentry, &delegated_inode); > out_dput: > done_path_create(&new_path, new_dentry); > + if (delegated_inode) { > + error = break_deleg_wait(&delegated_inode); > + if (!error) > + goto retry; > + } > if (retry_estale(error, how)) { > how |= LOOKUP_REVAL; > goto retry; > diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c > index 54ac814..b9740cb 100644 > --- a/fs/nfsd/vfs.c > +++ b/fs/nfsd/vfs.c > @@ -1708,7 +1708,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, > err = nfserrno(host_err); > goto out_dput; > } > - host_err = vfs_link(dold, dirp, dnew); > + host_err = vfs_link(dold, dirp, dnew, NULL); > if (!host_err) { > err = nfserrno(commit_metadata(ffhp)); > if (!err) > diff --git a/include/linux/fs.h b/include/linux/fs.h > index a35dadb..936413c 100644 > --- a/include/linux/fs.h > +++ b/include/linux/fs.h > @@ -1461,7 +1461,7 @@ extern int vfs_create(struct inode *, struct dentry *, umode_t, bool); > extern int vfs_mkdir(struct inode *, struct dentry *, umode_t); > extern int vfs_mknod(struct inode *, struct dentry *, umode_t, dev_t); > extern int vfs_symlink(struct inode *, struct dentry *, const char *); > -extern int vfs_link(struct dentry *, struct inode *, struct dentry *); > +extern int vfs_link(struct dentry *, struct inode *, struct dentry *, struct inode **); > 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 *, struct inode **); 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