nfsd: break lease on unlink, link, and rename

Any change to any of the links pointing to an entry should also break
delegations.

Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
J. Bruce Fields 2011-01-11 13:55:46 -05:00
parent 6a76bebefe
commit 4795bb37ef

View file

@ -272,6 +272,13 @@ out:
return err; return err;
} }
static int nfsd_break_lease(struct inode *inode)
{
if (!S_ISREG(inode->i_mode))
return 0;
return break_lease(inode, O_WRONLY | O_NONBLOCK);
}
/* /*
* Commit metadata changes to stable storage. * Commit metadata changes to stable storage.
*/ */
@ -414,7 +421,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
err = nfserr_notsync; err = nfserr_notsync;
if (!check_guard || guardtime == inode->i_ctime.tv_sec) { if (!check_guard || guardtime == inode->i_ctime.tv_sec) {
host_err = break_lease(inode, O_WRONLY | O_NONBLOCK); host_err = nfsd_break_lease(inode);
if (host_err) if (host_err)
goto out_nfserr; goto out_nfserr;
fh_lock(fhp); fh_lock(fhp);
@ -1639,6 +1646,12 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
err = nfserrno(host_err); err = nfserrno(host_err);
goto out_dput; goto out_dput;
} }
err = nfserr_noent;
if (!dold->d_inode)
goto out_drop_write;
host_err = nfsd_break_lease(dold->d_inode);
if (host_err)
goto out_drop_write;
host_err = vfs_link(dold, dirp, dnew); host_err = vfs_link(dold, dirp, dnew);
if (!host_err) { if (!host_err) {
err = nfserrno(commit_metadata(ffhp)); err = nfserrno(commit_metadata(ffhp));
@ -1650,6 +1663,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
else else
err = nfserrno(host_err); err = nfserrno(host_err);
} }
out_drop_write:
mnt_drop_write(tfhp->fh_export->ex_path.mnt); mnt_drop_write(tfhp->fh_export->ex_path.mnt);
out_dput: out_dput:
dput(dnew); dput(dnew);
@ -1731,15 +1745,17 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
if (host_err) if (host_err)
goto out_dput_new; goto out_dput_new;
host_err = nfsd_break_lease(odentry->d_inode);
if (host_err)
goto out_drop_write;
host_err = vfs_rename(fdir, odentry, tdir, ndentry); host_err = vfs_rename(fdir, odentry, tdir, ndentry);
if (!host_err) { if (!host_err) {
host_err = commit_metadata(tfhp); host_err = commit_metadata(tfhp);
if (!host_err) if (!host_err)
host_err = commit_metadata(ffhp); host_err = commit_metadata(ffhp);
} }
out_drop_write:
mnt_drop_write(ffhp->fh_export->ex_path.mnt); mnt_drop_write(ffhp->fh_export->ex_path.mnt);
out_dput_new: out_dput_new:
dput(ndentry); dput(ndentry);
out_dput_old: out_dput_old:
@ -1802,11 +1818,14 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
if (host_err) if (host_err)
goto out_nfserr; goto out_nfserr;
host_err = nfsd_break_lease(rdentry->d_inode);
if (host_err)
goto out_put;
if (type != S_IFDIR) if (type != S_IFDIR)
host_err = vfs_unlink(dirp, rdentry); host_err = vfs_unlink(dirp, rdentry);
else else
host_err = vfs_rmdir(dirp, rdentry); host_err = vfs_rmdir(dirp, rdentry);
out_put:
dput(rdentry); dput(rdentry);
if (!host_err) if (!host_err)