aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/vfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r--fs/nfsd/vfs.c95
1 files changed, 33 insertions, 62 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 3a359023c9f7..641117f2188d 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1,4 +1,3 @@
1#define MSNFS /* HACK HACK */
2/* 1/*
3 * File operations used by nfsd. Some of these have been ripped from 2 * File operations used by nfsd. Some of these have been ripped from
4 * other parts of the kernel because they weren't exported, others 3 * other parts of the kernel because they weren't exported, others
@@ -35,8 +34,8 @@
35#endif /* CONFIG_NFSD_V3 */ 34#endif /* CONFIG_NFSD_V3 */
36 35
37#ifdef CONFIG_NFSD_V4 36#ifdef CONFIG_NFSD_V4
38#include <linux/nfs4_acl.h> 37#include "acl.h"
39#include <linux/nfsd_idmap.h> 38#include "idmap.h"
40#endif /* CONFIG_NFSD_V4 */ 39#endif /* CONFIG_NFSD_V4 */
41 40
42#include "nfsd.h" 41#include "nfsd.h"
@@ -88,8 +87,9 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
88 .dentry = dget(dentry)}; 87 .dentry = dget(dentry)};
89 int err = 0; 88 int err = 0;
90 89
91 while (d_mountpoint(path.dentry) && follow_down(&path)) 90 err = follow_down(&path, false);
92 ; 91 if (err < 0)
92 goto out;
93 93
94 exp2 = rqst_exp_get_by_name(rqstp, &path); 94 exp2 = rqst_exp_get_by_name(rqstp, &path);
95 if (IS_ERR(exp2)) { 95 if (IS_ERR(exp2)) {
@@ -273,6 +273,13 @@ out:
273 return err; 273 return err;
274} 274}
275 275
276static int nfsd_break_lease(struct inode *inode)
277{
278 if (!S_ISREG(inode->i_mode))
279 return 0;
280 return break_lease(inode, O_WRONLY | O_NONBLOCK);
281}
282
276/* 283/*
277 * Commit metadata changes to stable storage. 284 * Commit metadata changes to stable storage.
278 */ 285 */
@@ -375,16 +382,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
375 goto out; 382 goto out;
376 } 383 }
377 384
378 /*
379 * If we are changing the size of the file, then
380 * we need to break all leases.
381 */
382 host_err = break_lease(inode, O_WRONLY | O_NONBLOCK);
383 if (host_err == -EWOULDBLOCK)
384 host_err = -ETIMEDOUT;
385 if (host_err) /* ENOMEM or EWOULDBLOCK */
386 goto out_nfserr;
387
388 host_err = get_write_access(inode); 385 host_err = get_write_access(inode);
389 if (host_err) 386 if (host_err)
390 goto out_nfserr; 387 goto out_nfserr;
@@ -425,7 +422,11 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
425 422
426 err = nfserr_notsync; 423 err = nfserr_notsync;
427 if (!check_guard || guardtime == inode->i_ctime.tv_sec) { 424 if (!check_guard || guardtime == inode->i_ctime.tv_sec) {
425 host_err = nfsd_break_lease(inode);
426 if (host_err)
427 goto out_nfserr;
428 fh_lock(fhp); 428 fh_lock(fhp);
429
429 host_err = notify_change(dentry, iap); 430 host_err = notify_change(dentry, iap);
430 err = nfserrno(host_err); 431 err = nfserrno(host_err);
431 fh_unlock(fhp); 432 fh_unlock(fhp);
@@ -752,8 +753,6 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
752 */ 753 */
753 if (!(access & NFSD_MAY_NOT_BREAK_LEASE)) 754 if (!(access & NFSD_MAY_NOT_BREAK_LEASE))
754 host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? O_WRONLY : 0)); 755 host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? O_WRONLY : 0));
755 if (host_err == -EWOULDBLOCK)
756 host_err = -ETIMEDOUT;
757 if (host_err) /* NOMEM or WOULDBLOCK */ 756 if (host_err) /* NOMEM or WOULDBLOCK */
758 goto out_nfserr; 757 goto out_nfserr;
759 758
@@ -845,11 +844,6 @@ nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
845 struct page **pp = rqstp->rq_respages + rqstp->rq_resused; 844 struct page **pp = rqstp->rq_respages + rqstp->rq_resused;
846 struct page *page = buf->page; 845 struct page *page = buf->page;
847 size_t size; 846 size_t size;
848 int ret;
849
850 ret = buf->ops->confirm(pipe, buf);
851 if (unlikely(ret))
852 return ret;
853 847
854 size = sd->len; 848 size = sd->len;
855 849
@@ -879,15 +873,6 @@ static int nfsd_direct_splice_actor(struct pipe_inode_info *pipe,
879 return __splice_from_pipe(pipe, sd, nfsd_splice_actor); 873 return __splice_from_pipe(pipe, sd, nfsd_splice_actor);
880} 874}
881 875
882static inline int svc_msnfs(struct svc_fh *ffhp)
883{
884#ifdef MSNFS
885 return (ffhp->fh_export->ex_flags & NFSEXP_MSNFS);
886#else
887 return 0;
888#endif
889}
890
891static __be32 876static __be32
892nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, 877nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
893 loff_t offset, struct kvec *vec, int vlen, unsigned long *count) 878 loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
@@ -900,9 +885,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
900 err = nfserr_perm; 885 err = nfserr_perm;
901 inode = file->f_path.dentry->d_inode; 886 inode = file->f_path.dentry->d_inode;
902 887
903 if (svc_msnfs(fhp) && !lock_may_read(inode, offset, *count))
904 goto out;
905
906 if (file->f_op->splice_read && rqstp->rq_splice_ok) { 888 if (file->f_op->splice_read && rqstp->rq_splice_ok) {
907 struct splice_desc sd = { 889 struct splice_desc sd = {
908 .len = 0, 890 .len = 0,
@@ -927,7 +909,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
927 fsnotify_access(file); 909 fsnotify_access(file);
928 } else 910 } else
929 err = nfserrno(host_err); 911 err = nfserrno(host_err);
930out:
931 return err; 912 return err;
932} 913}
933 914
@@ -992,14 +973,6 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
992 int stable = *stablep; 973 int stable = *stablep;
993 int use_wgather; 974 int use_wgather;
994 975
995#ifdef MSNFS
996 err = nfserr_perm;
997
998 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
999 (!lock_may_write(file->f_path.dentry->d_inode, offset, *cnt)))
1000 goto out;
1001#endif
1002
1003 dentry = file->f_path.dentry; 976 dentry = file->f_path.dentry;
1004 inode = dentry->d_inode; 977 inode = dentry->d_inode;
1005 exp = fhp->fh_export; 978 exp = fhp->fh_export;
@@ -1050,7 +1023,6 @@ out_nfserr:
1050 err = 0; 1023 err = 0;
1051 else 1024 else
1052 err = nfserrno(host_err); 1025 err = nfserrno(host_err);
1053out:
1054 return err; 1026 return err;
1055} 1027}
1056 1028
@@ -1670,6 +1642,12 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1670 err = nfserrno(host_err); 1642 err = nfserrno(host_err);
1671 goto out_dput; 1643 goto out_dput;
1672 } 1644 }
1645 err = nfserr_noent;
1646 if (!dold->d_inode)
1647 goto out_drop_write;
1648 host_err = nfsd_break_lease(dold->d_inode);
1649 if (host_err)
1650 goto out_drop_write;
1673 host_err = vfs_link(dold, dirp, dnew); 1651 host_err = vfs_link(dold, dirp, dnew);
1674 if (!host_err) { 1652 if (!host_err) {
1675 err = nfserrno(commit_metadata(ffhp)); 1653 err = nfserrno(commit_metadata(ffhp));
@@ -1681,6 +1659,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1681 else 1659 else
1682 err = nfserrno(host_err); 1660 err = nfserrno(host_err);
1683 } 1661 }
1662out_drop_write:
1684 mnt_drop_write(tfhp->fh_export->ex_path.mnt); 1663 mnt_drop_write(tfhp->fh_export->ex_path.mnt);
1685out_dput: 1664out_dput:
1686 dput(dnew); 1665 dput(dnew);
@@ -1755,12 +1734,6 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1755 if (ndentry == trap) 1734 if (ndentry == trap)
1756 goto out_dput_new; 1735 goto out_dput_new;
1757 1736
1758 if (svc_msnfs(ffhp) &&
1759 ((odentry->d_count > 1) || (ndentry->d_count > 1))) {
1760 host_err = -EPERM;
1761 goto out_dput_new;
1762 }
1763
1764 host_err = -EXDEV; 1737 host_err = -EXDEV;
1765 if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt) 1738 if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt)
1766 goto out_dput_new; 1739 goto out_dput_new;
@@ -1768,15 +1741,17 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1768 if (host_err) 1741 if (host_err)
1769 goto out_dput_new; 1742 goto out_dput_new;
1770 1743
1744 host_err = nfsd_break_lease(odentry->d_inode);
1745 if (host_err)
1746 goto out_drop_write;
1771 host_err = vfs_rename(fdir, odentry, tdir, ndentry); 1747 host_err = vfs_rename(fdir, odentry, tdir, ndentry);
1772 if (!host_err) { 1748 if (!host_err) {
1773 host_err = commit_metadata(tfhp); 1749 host_err = commit_metadata(tfhp);
1774 if (!host_err) 1750 if (!host_err)
1775 host_err = commit_metadata(ffhp); 1751 host_err = commit_metadata(ffhp);
1776 } 1752 }
1777 1753out_drop_write:
1778 mnt_drop_write(ffhp->fh_export->ex_path.mnt); 1754 mnt_drop_write(ffhp->fh_export->ex_path.mnt);
1779
1780 out_dput_new: 1755 out_dput_new:
1781 dput(ndentry); 1756 dput(ndentry);
1782 out_dput_old: 1757 out_dput_old:
@@ -1839,18 +1814,14 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
1839 if (host_err) 1814 if (host_err)
1840 goto out_nfserr; 1815 goto out_nfserr;
1841 1816
1842 if (type != S_IFDIR) { /* It's UNLINK */ 1817 host_err = nfsd_break_lease(rdentry->d_inode);
1843#ifdef MSNFS 1818 if (host_err)
1844 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && 1819 goto out_put;
1845 (rdentry->d_count > 1)) { 1820 if (type != S_IFDIR)
1846 host_err = -EPERM;
1847 } else
1848#endif
1849 host_err = vfs_unlink(dirp, rdentry); 1821 host_err = vfs_unlink(dirp, rdentry);
1850 } else { /* It's RMDIR */ 1822 else
1851 host_err = vfs_rmdir(dirp, rdentry); 1823 host_err = vfs_rmdir(dirp, rdentry);
1852 } 1824out_put:
1853
1854 dput(rdentry); 1825 dput(rdentry);
1855 1826
1856 if (!host_err) 1827 if (!host_err)