diff options
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r-- | fs/nfsd/vfs.c | 85 |
1 files changed, 30 insertions, 55 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 230b79fbf005..a3c7f701395a 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" |
@@ -273,6 +272,13 @@ out: | |||
273 | return err; | 272 | return err; |
274 | } | 273 | } |
275 | 274 | ||
275 | static int nfsd_break_lease(struct inode *inode) | ||
276 | { | ||
277 | if (!S_ISREG(inode->i_mode)) | ||
278 | return 0; | ||
279 | return break_lease(inode, O_WRONLY | O_NONBLOCK); | ||
280 | } | ||
281 | |||
276 | /* | 282 | /* |
277 | * Commit metadata changes to stable storage. | 283 | * Commit metadata changes to stable storage. |
278 | */ | 284 | */ |
@@ -375,16 +381,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, | |||
375 | goto out; | 381 | goto out; |
376 | } | 382 | } |
377 | 383 | ||
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); | 384 | host_err = get_write_access(inode); |
389 | if (host_err) | 385 | if (host_err) |
390 | goto out_nfserr; | 386 | goto out_nfserr; |
@@ -425,7 +421,11 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, | |||
425 | 421 | ||
426 | err = nfserr_notsync; | 422 | err = nfserr_notsync; |
427 | if (!check_guard || guardtime == inode->i_ctime.tv_sec) { | 423 | if (!check_guard || guardtime == inode->i_ctime.tv_sec) { |
424 | host_err = nfsd_break_lease(inode); | ||
425 | if (host_err) | ||
426 | goto out_nfserr; | ||
428 | fh_lock(fhp); | 427 | fh_lock(fhp); |
428 | |||
429 | host_err = notify_change(dentry, iap); | 429 | host_err = notify_change(dentry, iap); |
430 | err = nfserrno(host_err); | 430 | err = nfserrno(host_err); |
431 | fh_unlock(fhp); | 431 | fh_unlock(fhp); |
@@ -752,8 +752,6 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
752 | */ | 752 | */ |
753 | if (!(access & NFSD_MAY_NOT_BREAK_LEASE)) | 753 | if (!(access & NFSD_MAY_NOT_BREAK_LEASE)) |
754 | host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? O_WRONLY : 0)); | 754 | 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 */ | 755 | if (host_err) /* NOMEM or WOULDBLOCK */ |
758 | goto out_nfserr; | 756 | goto out_nfserr; |
759 | 757 | ||
@@ -874,15 +872,6 @@ static int nfsd_direct_splice_actor(struct pipe_inode_info *pipe, | |||
874 | return __splice_from_pipe(pipe, sd, nfsd_splice_actor); | 872 | return __splice_from_pipe(pipe, sd, nfsd_splice_actor); |
875 | } | 873 | } |
876 | 874 | ||
877 | static inline int svc_msnfs(struct svc_fh *ffhp) | ||
878 | { | ||
879 | #ifdef MSNFS | ||
880 | return (ffhp->fh_export->ex_flags & NFSEXP_MSNFS); | ||
881 | #else | ||
882 | return 0; | ||
883 | #endif | ||
884 | } | ||
885 | |||
886 | static __be32 | 875 | static __be32 |
887 | nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | 876 | nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, |
888 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) | 877 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) |
@@ -895,9 +884,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
895 | err = nfserr_perm; | 884 | err = nfserr_perm; |
896 | inode = file->f_path.dentry->d_inode; | 885 | inode = file->f_path.dentry->d_inode; |
897 | 886 | ||
898 | if (svc_msnfs(fhp) && !lock_may_read(inode, offset, *count)) | ||
899 | goto out; | ||
900 | |||
901 | if (file->f_op->splice_read && rqstp->rq_splice_ok) { | 887 | if (file->f_op->splice_read && rqstp->rq_splice_ok) { |
902 | struct splice_desc sd = { | 888 | struct splice_desc sd = { |
903 | .len = 0, | 889 | .len = 0, |
@@ -922,7 +908,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
922 | fsnotify_access(file); | 908 | fsnotify_access(file); |
923 | } else | 909 | } else |
924 | err = nfserrno(host_err); | 910 | err = nfserrno(host_err); |
925 | out: | ||
926 | return err; | 911 | return err; |
927 | } | 912 | } |
928 | 913 | ||
@@ -987,14 +972,6 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
987 | int stable = *stablep; | 972 | int stable = *stablep; |
988 | int use_wgather; | 973 | int use_wgather; |
989 | 974 | ||
990 | #ifdef MSNFS | ||
991 | err = nfserr_perm; | ||
992 | |||
993 | if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && | ||
994 | (!lock_may_write(file->f_path.dentry->d_inode, offset, *cnt))) | ||
995 | goto out; | ||
996 | #endif | ||
997 | |||
998 | dentry = file->f_path.dentry; | 975 | dentry = file->f_path.dentry; |
999 | inode = dentry->d_inode; | 976 | inode = dentry->d_inode; |
1000 | exp = fhp->fh_export; | 977 | exp = fhp->fh_export; |
@@ -1045,7 +1022,6 @@ out_nfserr: | |||
1045 | err = 0; | 1022 | err = 0; |
1046 | else | 1023 | else |
1047 | err = nfserrno(host_err); | 1024 | err = nfserrno(host_err); |
1048 | out: | ||
1049 | return err; | 1025 | return err; |
1050 | } | 1026 | } |
1051 | 1027 | ||
@@ -1665,6 +1641,12 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1665 | err = nfserrno(host_err); | 1641 | err = nfserrno(host_err); |
1666 | goto out_dput; | 1642 | goto out_dput; |
1667 | } | 1643 | } |
1644 | err = nfserr_noent; | ||
1645 | if (!dold->d_inode) | ||
1646 | goto out_drop_write; | ||
1647 | host_err = nfsd_break_lease(dold->d_inode); | ||
1648 | if (host_err) | ||
1649 | goto out_drop_write; | ||
1668 | host_err = vfs_link(dold, dirp, dnew); | 1650 | host_err = vfs_link(dold, dirp, dnew); |
1669 | if (!host_err) { | 1651 | if (!host_err) { |
1670 | err = nfserrno(commit_metadata(ffhp)); | 1652 | err = nfserrno(commit_metadata(ffhp)); |
@@ -1676,6 +1658,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
1676 | else | 1658 | else |
1677 | err = nfserrno(host_err); | 1659 | err = nfserrno(host_err); |
1678 | } | 1660 | } |
1661 | out_drop_write: | ||
1679 | mnt_drop_write(tfhp->fh_export->ex_path.mnt); | 1662 | mnt_drop_write(tfhp->fh_export->ex_path.mnt); |
1680 | out_dput: | 1663 | out_dput: |
1681 | dput(dnew); | 1664 | dput(dnew); |
@@ -1750,12 +1733,6 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1750 | if (ndentry == trap) | 1733 | if (ndentry == trap) |
1751 | goto out_dput_new; | 1734 | goto out_dput_new; |
1752 | 1735 | ||
1753 | if (svc_msnfs(ffhp) && | ||
1754 | ((odentry->d_count > 1) || (ndentry->d_count > 1))) { | ||
1755 | host_err = -EPERM; | ||
1756 | goto out_dput_new; | ||
1757 | } | ||
1758 | |||
1759 | host_err = -EXDEV; | 1736 | host_err = -EXDEV; |
1760 | if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt) | 1737 | if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt) |
1761 | goto out_dput_new; | 1738 | goto out_dput_new; |
@@ -1763,15 +1740,17 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
1763 | if (host_err) | 1740 | if (host_err) |
1764 | goto out_dput_new; | 1741 | goto out_dput_new; |
1765 | 1742 | ||
1743 | host_err = nfsd_break_lease(odentry->d_inode); | ||
1744 | if (host_err) | ||
1745 | goto out_drop_write; | ||
1766 | host_err = vfs_rename(fdir, odentry, tdir, ndentry); | 1746 | host_err = vfs_rename(fdir, odentry, tdir, ndentry); |
1767 | if (!host_err) { | 1747 | if (!host_err) { |
1768 | host_err = commit_metadata(tfhp); | 1748 | host_err = commit_metadata(tfhp); |
1769 | if (!host_err) | 1749 | if (!host_err) |
1770 | host_err = commit_metadata(ffhp); | 1750 | host_err = commit_metadata(ffhp); |
1771 | } | 1751 | } |
1772 | 1752 | out_drop_write: | |
1773 | mnt_drop_write(ffhp->fh_export->ex_path.mnt); | 1753 | mnt_drop_write(ffhp->fh_export->ex_path.mnt); |
1774 | |||
1775 | out_dput_new: | 1754 | out_dput_new: |
1776 | dput(ndentry); | 1755 | dput(ndentry); |
1777 | out_dput_old: | 1756 | out_dput_old: |
@@ -1834,18 +1813,14 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
1834 | if (host_err) | 1813 | if (host_err) |
1835 | goto out_nfserr; | 1814 | goto out_nfserr; |
1836 | 1815 | ||
1837 | if (type != S_IFDIR) { /* It's UNLINK */ | 1816 | host_err = nfsd_break_lease(rdentry->d_inode); |
1838 | #ifdef MSNFS | 1817 | if (host_err) |
1839 | if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && | 1818 | goto out_put; |
1840 | (rdentry->d_count > 1)) { | 1819 | if (type != S_IFDIR) |
1841 | host_err = -EPERM; | ||
1842 | } else | ||
1843 | #endif | ||
1844 | host_err = vfs_unlink(dirp, rdentry); | 1820 | host_err = vfs_unlink(dirp, rdentry); |
1845 | } else { /* It's RMDIR */ | 1821 | else |
1846 | host_err = vfs_rmdir(dirp, rdentry); | 1822 | host_err = vfs_rmdir(dirp, rdentry); |
1847 | } | 1823 | out_put: |
1848 | |||
1849 | dput(rdentry); | 1824 | dput(rdentry); |
1850 | 1825 | ||
1851 | if (!host_err) | 1826 | if (!host_err) |