aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/feature-removal-schedule.txt10
-rw-r--r--Documentation/filesystems/Locking24
-rw-r--r--Documentation/filesystems/nfs/nfs41-server.txt33
-rw-r--r--arch/tile/configs/tilegx_defconfig1
-rw-r--r--fs/Makefile1
-rw-r--r--fs/compat.c246
-rw-r--r--fs/dlm/plock.c10
-rw-r--r--fs/fuse/file.c2
-rw-r--r--fs/lockd/svclock.c8
-rw-r--r--fs/locks.c75
-rw-r--r--fs/nfsctl.c100
-rw-r--r--fs/nfsd/Kconfig12
-rw-r--r--fs/nfsd/cache.h2
-rw-r--r--fs/nfsd/export.c418
-rw-r--r--fs/nfsd/lockd.c2
-rw-r--r--fs/nfsd/nfs4proc.c58
-rw-r--r--fs/nfsd/nfs4state.c265
-rw-r--r--fs/nfsd/nfs4xdr.c144
-rw-r--r--fs/nfsd/nfscache.c3
-rw-r--r--fs/nfsd/nfsctl.c343
-rw-r--r--fs/nfsd/nfssvc.c33
-rw-r--r--fs/nfsd/state.h1
-rw-r--r--fs/nfsd/xdr4.h30
-rw-r--r--include/linux/compat.h9
-rw-r--r--include/linux/fs.h12
-rw-r--r--include/linux/nfsd/export.h2
-rw-r--r--include/linux/sunrpc/cache.h9
-rw-r--r--include/linux/sunrpc/svc.h1
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_mech.c7
-rw-r--r--net/sunrpc/auth_gss/gss_mech_switch.c32
-rw-r--r--net/sunrpc/svc_xprt.c11
-rw-r--r--net/sunrpc/svcauth_unix.c79
-rw-r--r--net/sunrpc/svcsock.c2
33 files changed, 559 insertions, 1426 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 89e46d3dc64..aca4f823596 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -491,16 +491,6 @@ Who: Wey-Yi Guy <wey-yi.w.guy@intel.com>
491 491
492---------------------------- 492----------------------------
493 493
494What: access to nfsd auth cache through sys_nfsservctl or '.' files
495 in the 'nfsd' filesystem.
496When: 3.0
497Why: This is a legacy interface which have been replaced by a more
498 dynamic cache. Continuing to maintain this interface is an
499 unnecessary burden.
500Who: NeilBrown <neilb@suse.de>
501
502----------------------------
503
504What: Legacy, non-standard chassis intrusion detection interface. 494What: Legacy, non-standard chassis intrusion detection interface.
505When: June 2011 495When: June 2011
506Why: The adm9240, w83792d and w83793 hardware monitoring drivers have 496Why: The adm9240, w83792d and w83793 hardware monitoring drivers have
diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking
index 7e4699146fe..653380793a6 100644
--- a/Documentation/filesystems/Locking
+++ b/Documentation/filesystems/Locking
@@ -338,21 +338,21 @@ fl_release_private: maybe no
338 338
339----------------------- lock_manager_operations --------------------------- 339----------------------- lock_manager_operations ---------------------------
340prototypes: 340prototypes:
341 int (*fl_compare_owner)(struct file_lock *, struct file_lock *); 341 int (*lm_compare_owner)(struct file_lock *, struct file_lock *);
342 void (*fl_notify)(struct file_lock *); /* unblock callback */ 342 void (*lm_notify)(struct file_lock *); /* unblock callback */
343 int (*fl_grant)(struct file_lock *, struct file_lock *, int); 343 int (*lm_grant)(struct file_lock *, struct file_lock *, int);
344 void (*fl_release_private)(struct file_lock *); 344 void (*lm_release_private)(struct file_lock *);
345 void (*fl_break)(struct file_lock *); /* break_lease callback */ 345 void (*lm_break)(struct file_lock *); /* break_lease callback */
346 int (*fl_change)(struct file_lock **, int); 346 int (*lm_change)(struct file_lock **, int);
347 347
348locking rules: 348locking rules:
349 file_lock_lock may block 349 file_lock_lock may block
350fl_compare_owner: yes no 350lm_compare_owner: yes no
351fl_notify: yes no 351lm_notify: yes no
352fl_grant: no no 352lm_grant: no no
353fl_release_private: maybe no 353lm_release_private: maybe no
354fl_break: yes no 354lm_break: yes no
355fl_change yes no 355lm_change yes no
356 356
357--------------------------- buffer_head ----------------------------------- 357--------------------------- buffer_head -----------------------------------
358prototypes: 358prototypes:
diff --git a/Documentation/filesystems/nfs/nfs41-server.txt b/Documentation/filesystems/nfs/nfs41-server.txt
index 04884914a1c..092fad92a3f 100644
--- a/Documentation/filesystems/nfs/nfs41-server.txt
+++ b/Documentation/filesystems/nfs/nfs41-server.txt
@@ -39,27 +39,17 @@ interoperability problems with future clients. Known issues:
39 from a linux client are possible, but we aren't really 39 from a linux client are possible, but we aren't really
40 conformant with the spec (for example, we don't use kerberos 40 conformant with the spec (for example, we don't use kerberos
41 on the backchannel correctly). 41 on the backchannel correctly).
42 - no trunking support: no clients currently take advantage of
43 trunking, but this is a mandatory feature, and its use is
44 recommended to clients in a number of places. (E.g. to ensure
45 timely renewal in case an existing connection's retry timeouts
46 have gotten too long; see section 8.3 of the RFC.)
47 Therefore, lack of this feature may cause future clients to
48 fail.
49 - Incomplete backchannel support: incomplete backchannel gss 42 - Incomplete backchannel support: incomplete backchannel gss
50 support and no support for BACKCHANNEL_CTL mean that 43 support and no support for BACKCHANNEL_CTL mean that
51 callbacks (hence delegations and layouts) may not be 44 callbacks (hence delegations and layouts) may not be
52 available and clients confused by the incomplete 45 available and clients confused by the incomplete
53 implementation may fail. 46 implementation may fail.
54 - Server reboot recovery is unsupported; if the server reboots,
55 clients may fail.
56 - We do not support SSV, which provides security for shared 47 - We do not support SSV, which provides security for shared
57 client-server state (thus preventing unauthorized tampering 48 client-server state (thus preventing unauthorized tampering
58 with locks and opens, for example). It is mandatory for 49 with locks and opens, for example). It is mandatory for
59 servers to support this, though no clients use it yet. 50 servers to support this, though no clients use it yet.
60 - Mandatory operations which we do not support, such as 51 - Mandatory operations which we do not support, such as
61 DESTROY_CLIENTID, FREE_STATEID, SECINFO_NO_NAME, and 52 DESTROY_CLIENTID, are not currently used by clients, but will be
62 TEST_STATEID, are not currently used by clients, but will be
63 (and the spec recommends their uses in common cases), and 53 (and the spec recommends their uses in common cases), and
64 clients should not be expected to know how to recover from the 54 clients should not be expected to know how to recover from the
65 case where they are not supported. This will eventually cause 55 case where they are not supported. This will eventually cause
@@ -69,8 +59,9 @@ In addition, some limitations are inherited from the current NFSv4
69implementation: 59implementation:
70 60
71 - Incomplete delegation enforcement: if a file is renamed or 61 - Incomplete delegation enforcement: if a file is renamed or
72 unlinked, a client holding a delegation may continue to 62 unlinked by a local process, a client holding a delegation may
73 indefinitely allow opens of the file under the old name. 63 continue to indefinitely allow opens of the file under the old
64 name.
74 65
75The table below, taken from the NFSv4.1 document, lists 66The table below, taken from the NFSv4.1 document, lists
76the operations that are mandatory to implement (REQ), optional 67the operations that are mandatory to implement (REQ), optional
@@ -99,7 +90,7 @@ Operations
99 +----------------------+------------+--------------+----------------+ 90 +----------------------+------------+--------------+----------------+
100 | ACCESS | REQ | | Section 18.1 | 91 | ACCESS | REQ | | Section 18.1 |
101NS | BACKCHANNEL_CTL | REQ | | Section 18.33 | 92NS | BACKCHANNEL_CTL | REQ | | Section 18.33 |
102NS | BIND_CONN_TO_SESSION | REQ | | Section 18.34 | 93I | BIND_CONN_TO_SESSION | REQ | | Section 18.34 |
103 | CLOSE | REQ | | Section 18.2 | 94 | CLOSE | REQ | | Section 18.2 |
104 | COMMIT | REQ | | Section 18.3 | 95 | COMMIT | REQ | | Section 18.3 |
105 | CREATE | REQ | | Section 18.4 | 96 | CREATE | REQ | | Section 18.4 |
@@ -111,7 +102,7 @@ NS*| DELEGPURGE | OPT | FDELG (REQ) | Section 18.5 |
111NS | DESTROY_CLIENTID | REQ | | Section 18.50 | 102NS | DESTROY_CLIENTID | REQ | | Section 18.50 |
112I | DESTROY_SESSION | REQ | | Section 18.37 | 103I | DESTROY_SESSION | REQ | | Section 18.37 |
113I | EXCHANGE_ID | REQ | | Section 18.35 | 104I | EXCHANGE_ID | REQ | | Section 18.35 |
114NS | FREE_STATEID | REQ | | Section 18.38 | 105I | FREE_STATEID | REQ | | Section 18.38 |
115 | GETATTR | REQ | | Section 18.7 | 106 | GETATTR | REQ | | Section 18.7 |
116P | GETDEVICEINFO | OPT | pNFS (REQ) | Section 18.40 | 107P | GETDEVICEINFO | OPT | pNFS (REQ) | Section 18.40 |
117P | GETDEVICELIST | OPT | pNFS (OPT) | Section 18.41 | 108P | GETDEVICELIST | OPT | pNFS (OPT) | Section 18.41 |
@@ -145,14 +136,14 @@ NS*| OPENATTR | OPT | | Section 18.17 |
145 | RESTOREFH | REQ | | Section 18.27 | 136 | RESTOREFH | REQ | | Section 18.27 |
146 | SAVEFH | REQ | | Section 18.28 | 137 | SAVEFH | REQ | | Section 18.28 |
147 | SECINFO | REQ | | Section 18.29 | 138 | SECINFO | REQ | | Section 18.29 |
148NS | SECINFO_NO_NAME | REC | pNFS files | Section 18.45, | 139I | SECINFO_NO_NAME | REC | pNFS files | Section 18.45, |
149 | | | layout (REQ) | Section 13.12 | 140 | | | layout (REQ) | Section 13.12 |
150I | SEQUENCE | REQ | | Section 18.46 | 141I | SEQUENCE | REQ | | Section 18.46 |
151 | SETATTR | REQ | | Section 18.30 | 142 | SETATTR | REQ | | Section 18.30 |
152 | SETCLIENTID | MNI | | N/A | 143 | SETCLIENTID | MNI | | N/A |
153 | SETCLIENTID_CONFIRM | MNI | | N/A | 144 | SETCLIENTID_CONFIRM | MNI | | N/A |
154NS | SET_SSV | REQ | | Section 18.47 | 145NS | SET_SSV | REQ | | Section 18.47 |
155NS | TEST_STATEID | REQ | | Section 18.48 | 146I | TEST_STATEID | REQ | | Section 18.48 |
156 | VERIFY | REQ | | Section 18.31 | 147 | VERIFY | REQ | | Section 18.31 |
157NS*| WANT_DELEGATION | OPT | FDELG (OPT) | Section 18.49 | 148NS*| WANT_DELEGATION | OPT | FDELG (OPT) | Section 18.49 |
158 | WRITE | REQ | | Section 18.32 | 149 | WRITE | REQ | | Section 18.32 |
@@ -206,12 +197,6 @@ CREATE_SESSION:
206SEQUENCE: 197SEQUENCE:
207* no support for dynamic slot table renegotiation (optional) 198* no support for dynamic slot table renegotiation (optional)
208 199
209nfsv4.1 COMPOUND rules:
210The following cases aren't supported yet:
211* Enforcing of NFS4ERR_NOT_ONLY_OP for: BIND_CONN_TO_SESSION, CREATE_SESSION,
212 DESTROY_CLIENTID, DESTROY_SESSION, EXCHANGE_ID.
213* DESTROY_SESSION MUST be the final operation in the COMPOUND request.
214
215Nonstandard compound limitations: 200Nonstandard compound limitations:
216* No support for a sessions fore channel RPC compound that requires both a 201* No support for a sessions fore channel RPC compound that requires both a
217 ca_maxrequestsize request and a ca_maxresponsesize reply, so we may 202 ca_maxrequestsize request and a ca_maxresponsesize reply, so we may
@@ -219,3 +204,5 @@ Nonstandard compound limitations:
219 negotiation. 204 negotiation.
220* No more than one IO operation (read, write, readdir) allowed per 205* No more than one IO operation (read, write, readdir) allowed per
221 compound. 206 compound.
207
208See also http://wiki.linux-nfs.org/wiki/index.php/Server_4.0_and_4.1_issues.
diff --git a/arch/tile/configs/tilegx_defconfig b/arch/tile/configs/tilegx_defconfig
index 09f1c7fad8b..2ad73fb707b 100644
--- a/arch/tile/configs/tilegx_defconfig
+++ b/arch/tile/configs/tilegx_defconfig
@@ -1479,7 +1479,6 @@ CONFIG_NFS_FSCACHE=y
1479CONFIG_NFS_USE_KERNEL_DNS=y 1479CONFIG_NFS_USE_KERNEL_DNS=y
1480# CONFIG_NFS_USE_NEW_IDMAPPER is not set 1480# CONFIG_NFS_USE_NEW_IDMAPPER is not set
1481CONFIG_NFSD=m 1481CONFIG_NFSD=m
1482CONFIG_NFSD_DEPRECATED=y
1483CONFIG_NFSD_V2_ACL=y 1482CONFIG_NFSD_V2_ACL=y
1484CONFIG_NFSD_V3=y 1483CONFIG_NFSD_V3=y
1485CONFIG_NFSD_V3_ACL=y 1484CONFIG_NFSD_V3_ACL=y
diff --git a/fs/Makefile b/fs/Makefile
index fb68c2b8cf8..afc109691a9 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -29,7 +29,6 @@ obj-$(CONFIG_EVENTFD) += eventfd.o
29obj-$(CONFIG_AIO) += aio.o 29obj-$(CONFIG_AIO) += aio.o
30obj-$(CONFIG_FILE_LOCKING) += locks.o 30obj-$(CONFIG_FILE_LOCKING) += locks.o
31obj-$(CONFIG_COMPAT) += compat.o compat_ioctl.o 31obj-$(CONFIG_COMPAT) += compat.o compat_ioctl.o
32obj-$(CONFIG_NFSD_DEPRECATED) += nfsctl.o
33obj-$(CONFIG_BINFMT_AOUT) += binfmt_aout.o 32obj-$(CONFIG_BINFMT_AOUT) += binfmt_aout.o
34obj-$(CONFIG_BINFMT_EM86) += binfmt_em86.o 33obj-$(CONFIG_BINFMT_EM86) += binfmt_em86.o
35obj-$(CONFIG_BINFMT_MISC) += binfmt_misc.o 34obj-$(CONFIG_BINFMT_MISC) += binfmt_misc.o
diff --git a/fs/compat.c b/fs/compat.c
index 0ea00832de2..0b48d018e38 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1675,256 +1675,10 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
1675} 1675}
1676#endif /* HAVE_SET_RESTORE_SIGMASK */ 1676#endif /* HAVE_SET_RESTORE_SIGMASK */
1677 1677
1678#if (defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)) && !defined(CONFIG_NFSD_DEPRECATED)
1679/* Stuff for NFS server syscalls... */
1680struct compat_nfsctl_svc {
1681 u16 svc32_port;
1682 s32 svc32_nthreads;
1683};
1684
1685struct compat_nfsctl_client {
1686 s8 cl32_ident[NFSCLNT_IDMAX+1];
1687 s32 cl32_naddr;
1688 struct in_addr cl32_addrlist[NFSCLNT_ADDRMAX];
1689 s32 cl32_fhkeytype;
1690 s32 cl32_fhkeylen;
1691 u8 cl32_fhkey[NFSCLNT_KEYMAX];
1692};
1693
1694struct compat_nfsctl_export {
1695 char ex32_client[NFSCLNT_IDMAX+1];
1696 char ex32_path[NFS_MAXPATHLEN+1];
1697 compat_dev_t ex32_dev;
1698 compat_ino_t ex32_ino;
1699 compat_int_t ex32_flags;
1700 __compat_uid_t ex32_anon_uid;
1701 __compat_gid_t ex32_anon_gid;
1702};
1703
1704struct compat_nfsctl_fdparm {
1705 struct sockaddr gd32_addr;
1706 s8 gd32_path[NFS_MAXPATHLEN+1];
1707 compat_int_t gd32_version;
1708};
1709
1710struct compat_nfsctl_fsparm {
1711 struct sockaddr gd32_addr;
1712 s8 gd32_path[NFS_MAXPATHLEN+1];
1713 compat_int_t gd32_maxlen;
1714};
1715
1716struct compat_nfsctl_arg {
1717 compat_int_t ca32_version; /* safeguard */
1718 union {
1719 struct compat_nfsctl_svc u32_svc;
1720 struct compat_nfsctl_client u32_client;
1721 struct compat_nfsctl_export u32_export;
1722 struct compat_nfsctl_fdparm u32_getfd;
1723 struct compat_nfsctl_fsparm u32_getfs;
1724 } u;
1725#define ca32_svc u.u32_svc
1726#define ca32_client u.u32_client
1727#define ca32_export u.u32_export
1728#define ca32_getfd u.u32_getfd
1729#define ca32_getfs u.u32_getfs
1730};
1731
1732union compat_nfsctl_res {
1733 __u8 cr32_getfh[NFS_FHSIZE];
1734 struct knfsd_fh cr32_getfs;
1735};
1736
1737static int compat_nfs_svc_trans(struct nfsctl_arg *karg,
1738 struct compat_nfsctl_arg __user *arg)
1739{
1740 if (!access_ok(VERIFY_READ, &arg->ca32_svc, sizeof(arg->ca32_svc)) ||
1741 get_user(karg->ca_version, &arg->ca32_version) ||
1742 __get_user(karg->ca_svc.svc_port, &arg->ca32_svc.svc32_port) ||
1743 __get_user(karg->ca_svc.svc_nthreads,
1744 &arg->ca32_svc.svc32_nthreads))
1745 return -EFAULT;
1746 return 0;
1747}
1748
1749static int compat_nfs_clnt_trans(struct nfsctl_arg *karg,
1750 struct compat_nfsctl_arg __user *arg)
1751{
1752 if (!access_ok(VERIFY_READ, &arg->ca32_client,
1753 sizeof(arg->ca32_client)) ||
1754 get_user(karg->ca_version, &arg->ca32_version) ||
1755 __copy_from_user(&karg->ca_client.cl_ident[0],
1756 &arg->ca32_client.cl32_ident[0],
1757 NFSCLNT_IDMAX) ||
1758 __get_user(karg->ca_client.cl_naddr,
1759 &arg->ca32_client.cl32_naddr) ||
1760 __copy_from_user(&karg->ca_client.cl_addrlist[0],
1761 &arg->ca32_client.cl32_addrlist[0],
1762 (sizeof(struct in_addr) * NFSCLNT_ADDRMAX)) ||
1763 __get_user(karg->ca_client.cl_fhkeytype,
1764 &arg->ca32_client.cl32_fhkeytype) ||
1765 __get_user(karg->ca_client.cl_fhkeylen,
1766 &arg->ca32_client.cl32_fhkeylen) ||
1767 __copy_from_user(&karg->ca_client.cl_fhkey[0],
1768 &arg->ca32_client.cl32_fhkey[0],
1769 NFSCLNT_KEYMAX))
1770 return -EFAULT;
1771
1772 return 0;
1773}
1774
1775static int compat_nfs_exp_trans(struct nfsctl_arg *karg,
1776 struct compat_nfsctl_arg __user *arg)
1777{
1778 if (!access_ok(VERIFY_READ, &arg->ca32_export,
1779 sizeof(arg->ca32_export)) ||
1780 get_user(karg->ca_version, &arg->ca32_version) ||
1781 __copy_from_user(&karg->ca_export.ex_client[0],
1782 &arg->ca32_export.ex32_client[0],
1783 NFSCLNT_IDMAX) ||
1784 __copy_from_user(&karg->ca_export.ex_path[0],
1785 &arg->ca32_export.ex32_path[0],
1786 NFS_MAXPATHLEN) ||
1787 __get_user(karg->ca_export.ex_dev,
1788 &arg->ca32_export.ex32_dev) ||
1789 __get_user(karg->ca_export.ex_ino,
1790 &arg->ca32_export.ex32_ino) ||
1791 __get_user(karg->ca_export.ex_flags,
1792 &arg->ca32_export.ex32_flags) ||
1793 __get_user(karg->ca_export.ex_anon_uid,
1794 &arg->ca32_export.ex32_anon_uid) ||
1795 __get_user(karg->ca_export.ex_anon_gid,
1796 &arg->ca32_export.ex32_anon_gid))
1797 return -EFAULT;
1798 SET_UID(karg->ca_export.ex_anon_uid, karg->ca_export.ex_anon_uid);
1799 SET_GID(karg->ca_export.ex_anon_gid, karg->ca_export.ex_anon_gid);
1800
1801 return 0;
1802}
1803
1804static int compat_nfs_getfd_trans(struct nfsctl_arg *karg,
1805 struct compat_nfsctl_arg __user *arg)
1806{
1807 if (!access_ok(VERIFY_READ, &arg->ca32_getfd,
1808 sizeof(arg->ca32_getfd)) ||
1809 get_user(karg->ca_version, &arg->ca32_version) ||
1810 __copy_from_user(&karg->ca_getfd.gd_addr,
1811 &arg->ca32_getfd.gd32_addr,
1812 (sizeof(struct sockaddr))) ||
1813 __copy_from_user(&karg->ca_getfd.gd_path,
1814 &arg->ca32_getfd.gd32_path,
1815 (NFS_MAXPATHLEN+1)) ||
1816 __get_user(karg->ca_getfd.gd_version,
1817 &arg->ca32_getfd.gd32_version))
1818 return -EFAULT;
1819
1820 return 0;
1821}
1822
1823static int compat_nfs_getfs_trans(struct nfsctl_arg *karg,
1824 struct compat_nfsctl_arg __user *arg)
1825{
1826 if (!access_ok(VERIFY_READ,&arg->ca32_getfs,sizeof(arg->ca32_getfs)) ||
1827 get_user(karg->ca_version, &arg->ca32_version) ||
1828 __copy_from_user(&karg->ca_getfs.gd_addr,
1829 &arg->ca32_getfs.gd32_addr,
1830 (sizeof(struct sockaddr))) ||
1831 __copy_from_user(&karg->ca_getfs.gd_path,
1832 &arg->ca32_getfs.gd32_path,
1833 (NFS_MAXPATHLEN+1)) ||
1834 __get_user(karg->ca_getfs.gd_maxlen,
1835 &arg->ca32_getfs.gd32_maxlen))
1836 return -EFAULT;
1837
1838 return 0;
1839}
1840
1841/* This really doesn't need translations, we are only passing
1842 * back a union which contains opaque nfs file handle data.
1843 */
1844static int compat_nfs_getfh_res_trans(union nfsctl_res *kres,
1845 union compat_nfsctl_res __user *res)
1846{
1847 int err;
1848
1849 err = copy_to_user(res, kres, sizeof(*res));
1850
1851 return (err) ? -EFAULT : 0;
1852}
1853
1854asmlinkage long compat_sys_nfsservctl(int cmd,
1855 struct compat_nfsctl_arg __user *arg,
1856 union compat_nfsctl_res __user *res)
1857{
1858 struct nfsctl_arg *karg;
1859 union nfsctl_res *kres;
1860 mm_segment_t oldfs;
1861 int err;
1862
1863 karg = kmalloc(sizeof(*karg), GFP_USER);
1864 kres = kmalloc(sizeof(*kres), GFP_USER);
1865 if(!karg || !kres) {
1866 err = -ENOMEM;
1867 goto done;
1868 }
1869
1870 switch(cmd) {
1871 case NFSCTL_SVC:
1872 err = compat_nfs_svc_trans(karg, arg);
1873 break;
1874
1875 case NFSCTL_ADDCLIENT:
1876 err = compat_nfs_clnt_trans(karg, arg);
1877 break;
1878
1879 case NFSCTL_DELCLIENT:
1880 err = compat_nfs_clnt_trans(karg, arg);
1881 break;
1882
1883 case NFSCTL_EXPORT:
1884 case NFSCTL_UNEXPORT:
1885 err = compat_nfs_exp_trans(karg, arg);
1886 break;
1887
1888 case NFSCTL_GETFD:
1889 err = compat_nfs_getfd_trans(karg, arg);
1890 break;
1891
1892 case NFSCTL_GETFS:
1893 err = compat_nfs_getfs_trans(karg, arg);
1894 break;
1895
1896 default:
1897 err = -EINVAL;
1898 break;
1899 }
1900
1901 if (err)
1902 goto done;
1903
1904 oldfs = get_fs();
1905 set_fs(KERNEL_DS);
1906 /* The __user pointer casts are valid because of the set_fs() */
1907 err = sys_nfsservctl(cmd, (void __user *) karg, (void __user *) kres);
1908 set_fs(oldfs);
1909
1910 if (err)
1911 goto done;
1912
1913 if((cmd == NFSCTL_GETFD) ||
1914 (cmd == NFSCTL_GETFS))
1915 err = compat_nfs_getfh_res_trans(kres, res);
1916
1917done:
1918 kfree(karg);
1919 kfree(kres);
1920 return err;
1921}
1922#else /* !NFSD */
1923long asmlinkage compat_sys_nfsservctl(int cmd, void *notused, void *notused2) 1678long asmlinkage compat_sys_nfsservctl(int cmd, void *notused, void *notused2)
1924{ 1679{
1925 return sys_ni_syscall(); 1680 return sys_ni_syscall();
1926} 1681}
1927#endif
1928 1682
1929#ifdef CONFIG_EPOLL 1683#ifdef CONFIG_EPOLL
1930 1684
diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c
index e2b87800436..01fd5c11a7f 100644
--- a/fs/dlm/plock.c
+++ b/fs/dlm/plock.c
@@ -92,7 +92,7 @@ static void do_unlock_close(struct dlm_ls *ls, u64 number,
92 op->info.number = number; 92 op->info.number = number;
93 op->info.start = 0; 93 op->info.start = 0;
94 op->info.end = OFFSET_MAX; 94 op->info.end = OFFSET_MAX;
95 if (fl->fl_lmops && fl->fl_lmops->fl_grant) 95 if (fl->fl_lmops && fl->fl_lmops->lm_grant)
96 op->info.owner = (__u64) fl->fl_pid; 96 op->info.owner = (__u64) fl->fl_pid;
97 else 97 else
98 op->info.owner = (__u64)(long) fl->fl_owner; 98 op->info.owner = (__u64)(long) fl->fl_owner;
@@ -128,11 +128,11 @@ int dlm_posix_lock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
128 op->info.number = number; 128 op->info.number = number;
129 op->info.start = fl->fl_start; 129 op->info.start = fl->fl_start;
130 op->info.end = fl->fl_end; 130 op->info.end = fl->fl_end;
131 if (fl->fl_lmops && fl->fl_lmops->fl_grant) { 131 if (fl->fl_lmops && fl->fl_lmops->lm_grant) {
132 /* fl_owner is lockd which doesn't distinguish 132 /* fl_owner is lockd which doesn't distinguish
133 processes on the nfs client */ 133 processes on the nfs client */
134 op->info.owner = (__u64) fl->fl_pid; 134 op->info.owner = (__u64) fl->fl_pid;
135 xop->callback = fl->fl_lmops->fl_grant; 135 xop->callback = fl->fl_lmops->lm_grant;
136 locks_init_lock(&xop->flc); 136 locks_init_lock(&xop->flc);
137 locks_copy_lock(&xop->flc, fl); 137 locks_copy_lock(&xop->flc, fl);
138 xop->fl = fl; 138 xop->fl = fl;
@@ -268,7 +268,7 @@ int dlm_posix_unlock(dlm_lockspace_t *lockspace, u64 number, struct file *file,
268 op->info.number = number; 268 op->info.number = number;
269 op->info.start = fl->fl_start; 269 op->info.start = fl->fl_start;
270 op->info.end = fl->fl_end; 270 op->info.end = fl->fl_end;
271 if (fl->fl_lmops && fl->fl_lmops->fl_grant) 271 if (fl->fl_lmops && fl->fl_lmops->lm_grant)
272 op->info.owner = (__u64) fl->fl_pid; 272 op->info.owner = (__u64) fl->fl_pid;
273 else 273 else
274 op->info.owner = (__u64)(long) fl->fl_owner; 274 op->info.owner = (__u64)(long) fl->fl_owner;
@@ -327,7 +327,7 @@ int dlm_posix_get(dlm_lockspace_t *lockspace, u64 number, struct file *file,
327 op->info.number = number; 327 op->info.number = number;
328 op->info.start = fl->fl_start; 328 op->info.start = fl->fl_start;
329 op->info.end = fl->fl_end; 329 op->info.end = fl->fl_end;
330 if (fl->fl_lmops && fl->fl_lmops->fl_grant) 330 if (fl->fl_lmops && fl->fl_lmops->lm_grant)
331 op->info.owner = (__u64) fl->fl_pid; 331 op->info.owner = (__u64) fl->fl_pid;
332 else 332 else
333 op->info.owner = (__u64)(long) fl->fl_owner; 333 op->info.owner = (__u64)(long) fl->fl_owner;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 7bb685cdd00..d480d9af46c 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1507,7 +1507,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
1507 pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0; 1507 pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0;
1508 int err; 1508 int err;
1509 1509
1510 if (fl->fl_lmops && fl->fl_lmops->fl_grant) { 1510 if (fl->fl_lmops && fl->fl_lmops->lm_grant) {
1511 /* NLM needs asynchronous locks, which we don't support yet */ 1511 /* NLM needs asynchronous locks, which we don't support yet */
1512 return -ENOLCK; 1512 return -ENOLCK;
1513 } 1513 }
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index 6e31695d046..f0179c3745d 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -632,7 +632,7 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
632 632
633/* 633/*
634 * This is a callback from the filesystem for VFS file lock requests. 634 * This is a callback from the filesystem for VFS file lock requests.
635 * It will be used if fl_grant is defined and the filesystem can not 635 * It will be used if lm_grant is defined and the filesystem can not
636 * respond to the request immediately. 636 * respond to the request immediately.
637 * For GETLK request it will copy the reply to the nlm_block. 637 * For GETLK request it will copy the reply to the nlm_block.
638 * For SETLK or SETLKW request it will get the local posix lock. 638 * For SETLK or SETLKW request it will get the local posix lock.
@@ -719,9 +719,9 @@ static int nlmsvc_same_owner(struct file_lock *fl1, struct file_lock *fl2)
719} 719}
720 720
721const struct lock_manager_operations nlmsvc_lock_operations = { 721const struct lock_manager_operations nlmsvc_lock_operations = {
722 .fl_compare_owner = nlmsvc_same_owner, 722 .lm_compare_owner = nlmsvc_same_owner,
723 .fl_notify = nlmsvc_notify_blocked, 723 .lm_notify = nlmsvc_notify_blocked,
724 .fl_grant = nlmsvc_grant_deferred, 724 .lm_grant = nlmsvc_grant_deferred,
725}; 725};
726 726
727/* 727/*
diff --git a/fs/locks.c b/fs/locks.c
index b286539d547..703f545097d 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -160,26 +160,20 @@ EXPORT_SYMBOL_GPL(unlock_flocks);
160 160
161static struct kmem_cache *filelock_cache __read_mostly; 161static struct kmem_cache *filelock_cache __read_mostly;
162 162
163static void locks_init_lock_always(struct file_lock *fl) 163static void locks_init_lock_heads(struct file_lock *fl)
164{ 164{
165 fl->fl_next = NULL; 165 INIT_LIST_HEAD(&fl->fl_link);
166 fl->fl_fasync = NULL; 166 INIT_LIST_HEAD(&fl->fl_block);
167 fl->fl_owner = NULL; 167 init_waitqueue_head(&fl->fl_wait);
168 fl->fl_pid = 0;
169 fl->fl_nspid = NULL;
170 fl->fl_file = NULL;
171 fl->fl_flags = 0;
172 fl->fl_type = 0;
173 fl->fl_start = fl->fl_end = 0;
174} 168}
175 169
176/* Allocate an empty lock structure. */ 170/* Allocate an empty lock structure. */
177struct file_lock *locks_alloc_lock(void) 171struct file_lock *locks_alloc_lock(void)
178{ 172{
179 struct file_lock *fl = kmem_cache_alloc(filelock_cache, GFP_KERNEL); 173 struct file_lock *fl = kmem_cache_zalloc(filelock_cache, GFP_KERNEL);
180 174
181 if (fl) 175 if (fl)
182 locks_init_lock_always(fl); 176 locks_init_lock_heads(fl);
183 177
184 return fl; 178 return fl;
185} 179}
@@ -193,8 +187,8 @@ void locks_release_private(struct file_lock *fl)
193 fl->fl_ops = NULL; 187 fl->fl_ops = NULL;
194 } 188 }
195 if (fl->fl_lmops) { 189 if (fl->fl_lmops) {
196 if (fl->fl_lmops->fl_release_private) 190 if (fl->fl_lmops->lm_release_private)
197 fl->fl_lmops->fl_release_private(fl); 191 fl->fl_lmops->lm_release_private(fl);
198 fl->fl_lmops = NULL; 192 fl->fl_lmops = NULL;
199 } 193 }
200 194
@@ -215,27 +209,12 @@ EXPORT_SYMBOL(locks_free_lock);
215 209
216void locks_init_lock(struct file_lock *fl) 210void locks_init_lock(struct file_lock *fl)
217{ 211{
218 INIT_LIST_HEAD(&fl->fl_link); 212 memset(fl, 0, sizeof(struct file_lock));
219 INIT_LIST_HEAD(&fl->fl_block); 213 locks_init_lock_heads(fl);
220 init_waitqueue_head(&fl->fl_wait);
221 fl->fl_ops = NULL;
222 fl->fl_lmops = NULL;
223 locks_init_lock_always(fl);
224} 214}
225 215
226EXPORT_SYMBOL(locks_init_lock); 216EXPORT_SYMBOL(locks_init_lock);
227 217
228/*
229 * Initialises the fields of the file lock which are invariant for
230 * free file_locks.
231 */
232static void init_once(void *foo)
233{
234 struct file_lock *lock = (struct file_lock *) foo;
235
236 locks_init_lock(lock);
237}
238
239static void locks_copy_private(struct file_lock *new, struct file_lock *fl) 218static void locks_copy_private(struct file_lock *new, struct file_lock *fl)
240{ 219{
241 if (fl->fl_ops) { 220 if (fl->fl_ops) {
@@ -444,9 +423,9 @@ static void lease_release_private_callback(struct file_lock *fl)
444} 423}
445 424
446static const struct lock_manager_operations lease_manager_ops = { 425static const struct lock_manager_operations lease_manager_ops = {
447 .fl_break = lease_break_callback, 426 .lm_break = lease_break_callback,
448 .fl_release_private = lease_release_private_callback, 427 .lm_release_private = lease_release_private_callback,
449 .fl_change = lease_modify, 428 .lm_change = lease_modify,
450}; 429};
451 430
452/* 431/*
@@ -499,9 +478,9 @@ static inline int locks_overlap(struct file_lock *fl1, struct file_lock *fl2)
499 */ 478 */
500static int posix_same_owner(struct file_lock *fl1, struct file_lock *fl2) 479static int posix_same_owner(struct file_lock *fl1, struct file_lock *fl2)
501{ 480{
502 if (fl1->fl_lmops && fl1->fl_lmops->fl_compare_owner) 481 if (fl1->fl_lmops && fl1->fl_lmops->lm_compare_owner)
503 return fl2->fl_lmops == fl1->fl_lmops && 482 return fl2->fl_lmops == fl1->fl_lmops &&
504 fl1->fl_lmops->fl_compare_owner(fl1, fl2); 483 fl1->fl_lmops->lm_compare_owner(fl1, fl2);
505 return fl1->fl_owner == fl2->fl_owner; 484 return fl1->fl_owner == fl2->fl_owner;
506} 485}
507 486
@@ -551,8 +530,8 @@ static void locks_wake_up_blocks(struct file_lock *blocker)
551 waiter = list_first_entry(&blocker->fl_block, 530 waiter = list_first_entry(&blocker->fl_block,
552 struct file_lock, fl_block); 531 struct file_lock, fl_block);
553 __locks_delete_block(waiter); 532 __locks_delete_block(waiter);
554 if (waiter->fl_lmops && waiter->fl_lmops->fl_notify) 533 if (waiter->fl_lmops && waiter->fl_lmops->lm_notify)
555 waiter->fl_lmops->fl_notify(waiter); 534 waiter->fl_lmops->lm_notify(waiter);
556 else 535 else
557 wake_up(&waiter->fl_wait); 536 wake_up(&waiter->fl_wait);
558 } 537 }
@@ -1239,7 +1218,7 @@ int __break_lease(struct inode *inode, unsigned int mode)
1239 fl->fl_type = future; 1218 fl->fl_type = future;
1240 fl->fl_break_time = break_time; 1219 fl->fl_break_time = break_time;
1241 /* lease must have lmops break callback */ 1220 /* lease must have lmops break callback */
1242 fl->fl_lmops->fl_break(fl); 1221 fl->fl_lmops->lm_break(fl);
1243 } 1222 }
1244 } 1223 }
1245 1224
@@ -1349,7 +1328,7 @@ int fcntl_getlease(struct file *filp)
1349 * @arg: type of lease to obtain 1328 * @arg: type of lease to obtain
1350 * @flp: input - file_lock to use, output - file_lock inserted 1329 * @flp: input - file_lock to use, output - file_lock inserted
1351 * 1330 *
1352 * The (input) flp->fl_lmops->fl_break function is required 1331 * The (input) flp->fl_lmops->lm_break function is required
1353 * by break_lease(). 1332 * by break_lease().
1354 * 1333 *
1355 * Called with file_lock_lock held. 1334 * Called with file_lock_lock held.
@@ -1375,7 +1354,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1375 1354
1376 time_out_leases(inode); 1355 time_out_leases(inode);
1377 1356
1378 BUG_ON(!(*flp)->fl_lmops->fl_break); 1357 BUG_ON(!(*flp)->fl_lmops->lm_break);
1379 1358
1380 if (arg != F_UNLCK) { 1359 if (arg != F_UNLCK) {
1381 error = -EAGAIN; 1360 error = -EAGAIN;
@@ -1417,7 +1396,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1417 goto out; 1396 goto out;
1418 1397
1419 if (my_before != NULL) { 1398 if (my_before != NULL) {
1420 error = lease->fl_lmops->fl_change(my_before, arg); 1399 error = lease->fl_lmops->lm_change(my_before, arg);
1421 if (!error) 1400 if (!error)
1422 *flp = *my_before; 1401 *flp = *my_before;
1423 goto out; 1402 goto out;
@@ -1453,7 +1432,7 @@ static int __vfs_setlease(struct file *filp, long arg, struct file_lock **lease)
1453 * @lease: file_lock to use 1432 * @lease: file_lock to use
1454 * 1433 *
1455 * Call this to establish a lease on the file. 1434 * Call this to establish a lease on the file.
1456 * The (*lease)->fl_lmops->fl_break operation must be set; if not, 1435 * The (*lease)->fl_lmops->lm_break operation must be set; if not,
1457 * break_lease will oops! 1436 * break_lease will oops!
1458 * 1437 *
1459 * This will call the filesystem's setlease file method, if 1438 * This will call the filesystem's setlease file method, if
@@ -1751,10 +1730,10 @@ out:
1751 * To avoid blocking kernel daemons, such as lockd, that need to acquire POSIX 1730 * To avoid blocking kernel daemons, such as lockd, that need to acquire POSIX
1752 * locks, the ->lock() interface may return asynchronously, before the lock has 1731 * locks, the ->lock() interface may return asynchronously, before the lock has
1753 * been granted or denied by the underlying filesystem, if (and only if) 1732 * been granted or denied by the underlying filesystem, if (and only if)
1754 * fl_grant is set. Callers expecting ->lock() to return asynchronously 1733 * lm_grant is set. Callers expecting ->lock() to return asynchronously
1755 * will only use F_SETLK, not F_SETLKW; they will set FL_SLEEP if (and only if) 1734 * will only use F_SETLK, not F_SETLKW; they will set FL_SLEEP if (and only if)
1756 * the request is for a blocking lock. When ->lock() does return asynchronously, 1735 * the request is for a blocking lock. When ->lock() does return asynchronously,
1757 * it must return FILE_LOCK_DEFERRED, and call ->fl_grant() when the lock 1736 * it must return FILE_LOCK_DEFERRED, and call ->lm_grant() when the lock
1758 * request completes. 1737 * request completes.
1759 * If the request is for non-blocking lock the file system should return 1738 * If the request is for non-blocking lock the file system should return
1760 * FILE_LOCK_DEFERRED then try to get the lock and call the callback routine 1739 * FILE_LOCK_DEFERRED then try to get the lock and call the callback routine
@@ -1764,7 +1743,7 @@ out:
1764 * grants a lock so the VFS can find out which locks are locally held and do 1743 * grants a lock so the VFS can find out which locks are locally held and do
1765 * the correct lock cleanup when required. 1744 * the correct lock cleanup when required.
1766 * The underlying filesystem must not drop the kernel lock or call 1745 * The underlying filesystem must not drop the kernel lock or call
1767 * ->fl_grant() before returning to the caller with a FILE_LOCK_DEFERRED 1746 * ->lm_grant() before returning to the caller with a FILE_LOCK_DEFERRED
1768 * return code. 1747 * return code.
1769 */ 1748 */
1770int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf) 1749int vfs_lock_file(struct file *filp, unsigned int cmd, struct file_lock *fl, struct file_lock *conf)
@@ -2333,8 +2312,8 @@ EXPORT_SYMBOL(lock_may_write);
2333static int __init filelock_init(void) 2312static int __init filelock_init(void)
2334{ 2313{
2335 filelock_cache = kmem_cache_create("file_lock_cache", 2314 filelock_cache = kmem_cache_create("file_lock_cache",
2336 sizeof(struct file_lock), 0, SLAB_PANIC, 2315 sizeof(struct file_lock), 0, SLAB_PANIC, NULL);
2337 init_once); 2316
2338 return 0; 2317 return 0;
2339} 2318}
2340 2319
diff --git a/fs/nfsctl.c b/fs/nfsctl.c
deleted file mode 100644
index 124e8fcb0dd..00000000000
--- a/fs/nfsctl.c
+++ /dev/null
@@ -1,100 +0,0 @@
1/*
2 * fs/nfsctl.c
3 *
4 * This should eventually move to userland.
5 *
6 */
7#include <linux/types.h>
8#include <linux/file.h>
9#include <linux/fs.h>
10#include <linux/nfsd/syscall.h>
11#include <linux/cred.h>
12#include <linux/sched.h>
13#include <linux/linkage.h>
14#include <linux/namei.h>
15#include <linux/mount.h>
16#include <linux/syscalls.h>
17#include <asm/uaccess.h>
18
19/*
20 * open a file on nfsd fs
21 */
22
23static struct file *do_open(char *name, int flags)
24{
25 struct vfsmount *mnt;
26 struct file *file;
27
28 mnt = do_kern_mount("nfsd", 0, "nfsd", NULL);
29 if (IS_ERR(mnt))
30 return (struct file *)mnt;
31
32 file = file_open_root(mnt->mnt_root, mnt, name, flags);
33
34 mntput(mnt); /* drop do_kern_mount reference */
35 return file;
36}
37
38static struct {
39 char *name; int wsize; int rsize;
40} map[] = {
41 [NFSCTL_SVC] = {
42 .name = ".svc",
43 .wsize = sizeof(struct nfsctl_svc)
44 },
45 [NFSCTL_ADDCLIENT] = {
46 .name = ".add",
47 .wsize = sizeof(struct nfsctl_client)
48 },
49 [NFSCTL_DELCLIENT] = {
50 .name = ".del",
51 .wsize = sizeof(struct nfsctl_client)
52 },
53 [NFSCTL_EXPORT] = {
54 .name = ".export",
55 .wsize = sizeof(struct nfsctl_export)
56 },
57 [NFSCTL_UNEXPORT] = {
58 .name = ".unexport",
59 .wsize = sizeof(struct nfsctl_export)
60 },
61 [NFSCTL_GETFD] = {
62 .name = ".getfd",
63 .wsize = sizeof(struct nfsctl_fdparm),
64 .rsize = NFS_FHSIZE
65 },
66 [NFSCTL_GETFS] = {
67 .name = ".getfs",
68 .wsize = sizeof(struct nfsctl_fsparm),
69 .rsize = sizeof(struct knfsd_fh)
70 },
71};
72
73SYSCALL_DEFINE3(nfsservctl, int, cmd, struct nfsctl_arg __user *, arg,
74 void __user *, res)
75{
76 struct file *file;
77 void __user *p = &arg->u;
78 int version;
79 int err;
80
81 if (copy_from_user(&version, &arg->ca_version, sizeof(int)))
82 return -EFAULT;
83
84 if (version != NFSCTL_VERSION)
85 return -EINVAL;
86
87 if (cmd < 0 || cmd >= ARRAY_SIZE(map) || !map[cmd].name)
88 return -EINVAL;
89
90 file = do_open(map[cmd].name, map[cmd].rsize ? O_RDWR : O_WRONLY);
91 if (IS_ERR(file))
92 return PTR_ERR(file);
93 err = file->f_op->write(file, p, map[cmd].wsize, &file->f_pos);
94 if (err >= 0 && map[cmd].rsize)
95 err = file->f_op->read(file, res, map[cmd].rsize, &file->f_pos);
96 if (err >= 0)
97 err = 0;
98 fput(file);
99 return err;
100}
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
index fbb2a5ef581..10e6366608f 100644
--- a/fs/nfsd/Kconfig
+++ b/fs/nfsd/Kconfig
@@ -28,18 +28,6 @@ config NFSD
28 28
29 If unsure, say N. 29 If unsure, say N.
30 30
31config NFSD_DEPRECATED
32 bool "Include support for deprecated syscall interface to NFSD"
33 depends on NFSD
34 default y
35 help
36 The syscall interface to nfsd was obsoleted in 2.6.0 by a new
37 filesystem based interface. The old interface is due for removal
38 in 2.6.40. If you wish to remove the interface before then
39 say N.
40
41 In unsure, say Y.
42
43config NFSD_V2_ACL 31config NFSD_V2_ACL
44 bool 32 bool
45 depends on NFSD 33 depends on NFSD
diff --git a/fs/nfsd/cache.h b/fs/nfsd/cache.h
index d892be61016..93cc9d34c45 100644
--- a/fs/nfsd/cache.h
+++ b/fs/nfsd/cache.h
@@ -69,7 +69,7 @@ enum {
69 69
70int nfsd_reply_cache_init(void); 70int nfsd_reply_cache_init(void);
71void nfsd_reply_cache_shutdown(void); 71void nfsd_reply_cache_shutdown(void);
72int nfsd_cache_lookup(struct svc_rqst *, int); 72int nfsd_cache_lookup(struct svc_rqst *);
73void nfsd_cache_update(struct svc_rqst *, int, __be32 *); 73void nfsd_cache_update(struct svc_rqst *, int, __be32 *);
74 74
75#ifdef CONFIG_NFSD_V4 75#ifdef CONFIG_NFSD_V4
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index b9566e46219..f4cc1e2bfc5 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -797,58 +797,6 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
797 return ek; 797 return ek;
798} 798}
799 799
800#ifdef CONFIG_NFSD_DEPRECATED
801static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
802 struct svc_export *exp)
803{
804 struct svc_expkey key, *ek;
805
806 key.ek_client = clp;
807 key.ek_fsidtype = fsid_type;
808 memcpy(key.ek_fsid, fsidv, key_len(fsid_type));
809 key.ek_path = exp->ex_path;
810 key.h.expiry_time = NEVER;
811 key.h.flags = 0;
812
813 ek = svc_expkey_lookup(&key);
814 if (ek)
815 ek = svc_expkey_update(&key,ek);
816 if (ek) {
817 cache_put(&ek->h, &svc_expkey_cache);
818 return 0;
819 }
820 return -ENOMEM;
821}
822
823/*
824 * Find the client's export entry matching xdev/xino.
825 */
826static inline struct svc_expkey *
827exp_get_key(svc_client *clp, dev_t dev, ino_t ino)
828{
829 u32 fsidv[3];
830
831 if (old_valid_dev(dev)) {
832 mk_fsid(FSID_DEV, fsidv, dev, ino, 0, NULL);
833 return exp_find_key(clp, FSID_DEV, fsidv, NULL);
834 }
835 mk_fsid(FSID_ENCODE_DEV, fsidv, dev, ino, 0, NULL);
836 return exp_find_key(clp, FSID_ENCODE_DEV, fsidv, NULL);
837}
838
839/*
840 * Find the client's export entry matching fsid
841 */
842static inline struct svc_expkey *
843exp_get_fsid_key(svc_client *clp, int fsid)
844{
845 u32 fsidv[2];
846
847 mk_fsid(FSID_NUM, fsidv, 0, 0, fsid, NULL);
848
849 return exp_find_key(clp, FSID_NUM, fsidv, NULL);
850}
851#endif
852 800
853static svc_export *exp_get_by_name(svc_client *clp, const struct path *path, 801static svc_export *exp_get_by_name(svc_client *clp, const struct path *path,
854 struct cache_req *reqp) 802 struct cache_req *reqp)
@@ -890,275 +838,7 @@ static struct svc_export *exp_parent(svc_client *clp, struct path *path)
890 return exp; 838 return exp;
891} 839}
892 840
893#ifdef CONFIG_NFSD_DEPRECATED
894/*
895 * Hashtable locking. Write locks are placed only by user processes
896 * wanting to modify export information.
897 * Write locking only done in this file. Read locking
898 * needed externally.
899 */
900
901static DECLARE_RWSEM(hash_sem);
902
903void
904exp_readlock(void)
905{
906 down_read(&hash_sem);
907}
908
909static inline void
910exp_writelock(void)
911{
912 down_write(&hash_sem);
913}
914
915void
916exp_readunlock(void)
917{
918 up_read(&hash_sem);
919}
920
921static inline void
922exp_writeunlock(void)
923{
924 up_write(&hash_sem);
925}
926#else
927
928/* hash_sem not needed once deprecated interface is removed */
929void exp_readlock(void) {}
930static inline void exp_writelock(void){}
931void exp_readunlock(void) {}
932static inline void exp_writeunlock(void){}
933
934#endif
935
936#ifdef CONFIG_NFSD_DEPRECATED
937static void exp_do_unexport(svc_export *unexp);
938static int exp_verify_string(char *cp, int max);
939
940static void exp_fsid_unhash(struct svc_export *exp)
941{
942 struct svc_expkey *ek;
943
944 if ((exp->ex_flags & NFSEXP_FSID) == 0)
945 return;
946
947 ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
948 if (!IS_ERR(ek)) {
949 sunrpc_invalidate(&ek->h, &svc_expkey_cache);
950 cache_put(&ek->h, &svc_expkey_cache);
951 }
952}
953
954static int exp_fsid_hash(svc_client *clp, struct svc_export *exp)
955{
956 u32 fsid[2];
957
958 if ((exp->ex_flags & NFSEXP_FSID) == 0)
959 return 0;
960
961 mk_fsid(FSID_NUM, fsid, 0, 0, exp->ex_fsid, NULL);
962 return exp_set_key(clp, FSID_NUM, fsid, exp);
963}
964
965static int exp_hash(struct auth_domain *clp, struct svc_export *exp)
966{
967 u32 fsid[2];
968 struct inode *inode = exp->ex_path.dentry->d_inode;
969 dev_t dev = inode->i_sb->s_dev;
970
971 if (old_valid_dev(dev)) {
972 mk_fsid(FSID_DEV, fsid, dev, inode->i_ino, 0, NULL);
973 return exp_set_key(clp, FSID_DEV, fsid, exp);
974 }
975 mk_fsid(FSID_ENCODE_DEV, fsid, dev, inode->i_ino, 0, NULL);
976 return exp_set_key(clp, FSID_ENCODE_DEV, fsid, exp);
977}
978 841
979static void exp_unhash(struct svc_export *exp)
980{
981 struct svc_expkey *ek;
982 struct inode *inode = exp->ex_path.dentry->d_inode;
983
984 ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
985 if (!IS_ERR(ek)) {
986 sunrpc_invalidate(&ek->h, &svc_expkey_cache);
987 cache_put(&ek->h, &svc_expkey_cache);
988 }
989}
990
991/*
992 * Export a file system.
993 */
994int
995exp_export(struct nfsctl_export *nxp)
996{
997 svc_client *clp;
998 struct svc_export *exp = NULL;
999 struct svc_export new;
1000 struct svc_expkey *fsid_key = NULL;
1001 struct path path;
1002 int err;
1003
1004 /* Consistency check */
1005 err = -EINVAL;
1006 if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
1007 !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
1008 goto out;
1009
1010 dprintk("exp_export called for %s:%s (%x/%ld fl %x).\n",
1011 nxp->ex_client, nxp->ex_path,
1012 (unsigned)nxp->ex_dev, (long)nxp->ex_ino,
1013 nxp->ex_flags);
1014
1015 /* Try to lock the export table for update */
1016 exp_writelock();
1017
1018 /* Look up client info */
1019 if (!(clp = auth_domain_find(nxp->ex_client)))
1020 goto out_unlock;
1021
1022
1023 /* Look up the dentry */
1024 err = kern_path(nxp->ex_path, 0, &path);
1025 if (err)
1026 goto out_put_clp;
1027 err = -EINVAL;
1028
1029 exp = exp_get_by_name(clp, &path, NULL);
1030
1031 memset(&new, 0, sizeof(new));
1032
1033 /* must make sure there won't be an ex_fsid clash */
1034 if ((nxp->ex_flags & NFSEXP_FSID) &&
1035 (!IS_ERR(fsid_key = exp_get_fsid_key(clp, nxp->ex_dev))) &&
1036 fsid_key->ek_path.mnt &&
1037 (fsid_key->ek_path.mnt != path.mnt ||
1038 fsid_key->ek_path.dentry != path.dentry))
1039 goto finish;
1040
1041 if (!IS_ERR(exp)) {
1042 /* just a flags/id/fsid update */
1043
1044 exp_fsid_unhash(exp);
1045 exp->ex_flags = nxp->ex_flags;
1046 exp->ex_anon_uid = nxp->ex_anon_uid;
1047 exp->ex_anon_gid = nxp->ex_anon_gid;
1048 exp->ex_fsid = nxp->ex_dev;
1049
1050 err = exp_fsid_hash(clp, exp);
1051 goto finish;
1052 }
1053
1054 err = check_export(path.dentry->d_inode, &nxp->ex_flags, NULL);
1055 if (err) goto finish;
1056
1057 err = -ENOMEM;
1058
1059 dprintk("nfsd: creating export entry %p for client %p\n", exp, clp);
1060
1061 new.h.expiry_time = NEVER;
1062 new.h.flags = 0;
1063 new.ex_pathname = kstrdup(nxp->ex_path, GFP_KERNEL);
1064 if (!new.ex_pathname)
1065 goto finish;
1066 new.ex_client = clp;
1067 new.ex_path = path;
1068 new.ex_flags = nxp->ex_flags;
1069 new.ex_anon_uid = nxp->ex_anon_uid;
1070 new.ex_anon_gid = nxp->ex_anon_gid;
1071 new.ex_fsid = nxp->ex_dev;
1072
1073 exp = svc_export_lookup(&new);
1074 if (exp)
1075 exp = svc_export_update(&new, exp);
1076
1077 if (!exp)
1078 goto finish;
1079
1080 if (exp_hash(clp, exp) ||
1081 exp_fsid_hash(clp, exp)) {
1082 /* failed to create at least one index */
1083 exp_do_unexport(exp);
1084 cache_flush();
1085 } else
1086 err = 0;
1087finish:
1088 kfree(new.ex_pathname);
1089 if (!IS_ERR_OR_NULL(exp))
1090 exp_put(exp);
1091 if (!IS_ERR_OR_NULL(fsid_key))
1092 cache_put(&fsid_key->h, &svc_expkey_cache);
1093 path_put(&path);
1094out_put_clp:
1095 auth_domain_put(clp);
1096out_unlock:
1097 exp_writeunlock();
1098out:
1099 return err;
1100}
1101
1102/*
1103 * Unexport a file system. The export entry has already
1104 * been removed from the client's list of exported fs's.
1105 */
1106static void
1107exp_do_unexport(svc_export *unexp)
1108{
1109 sunrpc_invalidate(&unexp->h, &svc_export_cache);
1110 exp_unhash(unexp);
1111 exp_fsid_unhash(unexp);
1112}
1113
1114
1115/*
1116 * unexport syscall.
1117 */
1118int
1119exp_unexport(struct nfsctl_export *nxp)
1120{
1121 struct auth_domain *dom;
1122 svc_export *exp;
1123 struct path path;
1124 int err;
1125
1126 /* Consistency check */
1127 if (!exp_verify_string(nxp->ex_path, NFS_MAXPATHLEN) ||
1128 !exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX))
1129 return -EINVAL;
1130
1131 exp_writelock();
1132
1133 err = -EINVAL;
1134 dom = auth_domain_find(nxp->ex_client);
1135 if (!dom) {
1136 dprintk("nfsd: unexport couldn't find %s\n", nxp->ex_client);
1137 goto out_unlock;
1138 }
1139
1140 err = kern_path(nxp->ex_path, 0, &path);
1141 if (err)
1142 goto out_domain;
1143
1144 err = -EINVAL;
1145 exp = exp_get_by_name(dom, &path, NULL);
1146 path_put(&path);
1147 if (IS_ERR(exp))
1148 goto out_domain;
1149
1150 exp_do_unexport(exp);
1151 exp_put(exp);
1152 err = 0;
1153
1154out_domain:
1155 auth_domain_put(dom);
1156 cache_flush();
1157out_unlock:
1158 exp_writeunlock();
1159 return err;
1160}
1161#endif /* CONFIG_NFSD_DEPRECATED */
1162 842
1163/* 843/*
1164 * Obtain the root fh on behalf of a client. 844 * Obtain the root fh on behalf of a client.
@@ -1367,7 +1047,6 @@ static void *e_start(struct seq_file *m, loff_t *pos)
1367 unsigned hash, export; 1047 unsigned hash, export;
1368 struct cache_head *ch; 1048 struct cache_head *ch;
1369 1049
1370 exp_readlock();
1371 read_lock(&svc_export_cache.hash_lock); 1050 read_lock(&svc_export_cache.hash_lock);
1372 if (!n--) 1051 if (!n--)
1373 return SEQ_START_TOKEN; 1052 return SEQ_START_TOKEN;
@@ -1418,7 +1097,6 @@ static void e_stop(struct seq_file *m, void *p)
1418 __releases(svc_export_cache.hash_lock) 1097 __releases(svc_export_cache.hash_lock)
1419{ 1098{
1420 read_unlock(&svc_export_cache.hash_lock); 1099 read_unlock(&svc_export_cache.hash_lock);
1421 exp_readunlock();
1422} 1100}
1423 1101
1424static struct flags { 1102static struct flags {
@@ -1550,97 +1228,6 @@ const struct seq_operations nfs_exports_op = {
1550 .show = e_show, 1228 .show = e_show,
1551}; 1229};
1552 1230
1553#ifdef CONFIG_NFSD_DEPRECATED
1554/*
1555 * Add or modify a client.
1556 * Change requests may involve the list of host addresses. The list of
1557 * exports and possibly existing uid maps are left untouched.
1558 */
1559int
1560exp_addclient(struct nfsctl_client *ncp)
1561{
1562 struct auth_domain *dom;
1563 int i, err;
1564 struct in6_addr addr6;
1565
1566 /* First, consistency check. */
1567 err = -EINVAL;
1568 if (! exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX))
1569 goto out;
1570 if (ncp->cl_naddr > NFSCLNT_ADDRMAX)
1571 goto out;
1572
1573 /* Lock the hashtable */
1574 exp_writelock();
1575
1576 dom = unix_domain_find(ncp->cl_ident);
1577
1578 err = -ENOMEM;
1579 if (!dom)
1580 goto out_unlock;
1581
1582 /* Insert client into hashtable. */
1583 for (i = 0; i < ncp->cl_naddr; i++) {
1584 ipv6_addr_set_v4mapped(ncp->cl_addrlist[i].s_addr, &addr6);
1585 auth_unix_add_addr(&init_net, &addr6, dom);
1586 }
1587 auth_unix_forget_old(dom);
1588 auth_domain_put(dom);
1589
1590 err = 0;
1591
1592out_unlock:
1593 exp_writeunlock();
1594out:
1595 return err;
1596}
1597
1598/*
1599 * Delete a client given an identifier.
1600 */
1601int
1602exp_delclient(struct nfsctl_client *ncp)
1603{
1604 int err;
1605 struct auth_domain *dom;
1606
1607 err = -EINVAL;
1608 if (!exp_verify_string(ncp->cl_ident, NFSCLNT_IDMAX))
1609 goto out;
1610
1611 /* Lock the hashtable */
1612 exp_writelock();
1613
1614 dom = auth_domain_find(ncp->cl_ident);
1615 /* just make sure that no addresses work
1616 * and that it will expire soon
1617 */
1618 if (dom) {
1619 err = auth_unix_forget_old(dom);
1620 auth_domain_put(dom);
1621 }
1622
1623 exp_writeunlock();
1624out:
1625 return err;
1626}
1627
1628/*
1629 * Verify that string is non-empty and does not exceed max length.
1630 */
1631static int
1632exp_verify_string(char *cp, int max)
1633{
1634 int i;
1635
1636 for (i = 0; i < max; i++)
1637 if (!cp[i])
1638 return i;
1639 cp[i] = 0;
1640 printk(KERN_NOTICE "nfsd: couldn't validate string %s\n", cp);
1641 return 0;
1642}
1643#endif /* CONFIG_NFSD_DEPRECATED */
1644 1231
1645/* 1232/*
1646 * Initialize the exports module. 1233 * Initialize the exports module.
@@ -1667,10 +1254,8 @@ nfsd_export_init(void)
1667void 1254void
1668nfsd_export_flush(void) 1255nfsd_export_flush(void)
1669{ 1256{
1670 exp_writelock();
1671 cache_purge(&svc_expkey_cache); 1257 cache_purge(&svc_expkey_cache);
1672 cache_purge(&svc_export_cache); 1258 cache_purge(&svc_export_cache);
1673 exp_writeunlock();
1674} 1259}
1675 1260
1676/* 1261/*
@@ -1682,12 +1267,9 @@ nfsd_export_shutdown(void)
1682 1267
1683 dprintk("nfsd: shutting down export module.\n"); 1268 dprintk("nfsd: shutting down export module.\n");
1684 1269
1685 exp_writelock();
1686
1687 cache_unregister(&svc_expkey_cache); 1270 cache_unregister(&svc_expkey_cache);
1688 cache_unregister(&svc_export_cache); 1271 cache_unregister(&svc_export_cache);
1689 svcauth_unix_purge(); 1272 svcauth_unix_purge();
1690 1273
1691 exp_writeunlock();
1692 dprintk("nfsd: export shutdown complete.\n"); 1274 dprintk("nfsd: export shutdown complete.\n");
1693} 1275}
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 7c831a2731f..77e7a5cca88 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -35,10 +35,8 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
35 memcpy((char*)&fh.fh_handle.fh_base, f->data, f->size); 35 memcpy((char*)&fh.fh_handle.fh_base, f->data, f->size);
36 fh.fh_export = NULL; 36 fh.fh_export = NULL;
37 37
38 exp_readlock();
39 nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp); 38 nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp);
40 fh_put(&fh); 39 fh_put(&fh);
41 exp_readunlock();
42 /* We return nlm error codes as nlm doesn't know 40 /* We return nlm error codes as nlm doesn't know
43 * about nfsd, but nfsd does know about nlm.. 41 * about nfsd, but nfsd does know about nlm..
44 */ 42 */
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 3a6dbd70b34..e8077766661 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -291,6 +291,15 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
291 if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL) 291 if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
292 return nfserr_inval; 292 return nfserr_inval;
293 293
294 /*
295 * RFC5661 18.51.3
296 * Before RECLAIM_COMPLETE done, server should deny new lock
297 */
298 if (nfsd4_has_session(cstate) &&
299 !cstate->session->se_client->cl_firststate &&
300 open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
301 return nfserr_grace;
302
294 if (nfsd4_has_session(cstate)) 303 if (nfsd4_has_session(cstate))
295 copy_clientid(&open->op_clientid, cstate->session); 304 copy_clientid(&open->op_clientid, cstate->session);
296 305
@@ -998,6 +1007,15 @@ struct nfsd4_operation {
998 nfsd4op_func op_func; 1007 nfsd4op_func op_func;
999 u32 op_flags; 1008 u32 op_flags;
1000 char *op_name; 1009 char *op_name;
1010 /*
1011 * We use the DRC for compounds containing non-idempotent
1012 * operations, *except* those that are 4.1-specific (since
1013 * sessions provide their own EOS), and except for stateful
1014 * operations other than setclientid and setclientid_confirm
1015 * (since sequence numbers provide EOS for open, lock, etc in
1016 * the v4.0 case).
1017 */
1018 bool op_cacheresult;
1001}; 1019};
1002 1020
1003static struct nfsd4_operation nfsd4_ops[]; 1021static struct nfsd4_operation nfsd4_ops[];
@@ -1042,6 +1060,11 @@ static inline struct nfsd4_operation *OPDESC(struct nfsd4_op *op)
1042 return &nfsd4_ops[op->opnum]; 1060 return &nfsd4_ops[op->opnum];
1043} 1061}
1044 1062
1063bool nfsd4_cache_this_op(struct nfsd4_op *op)
1064{
1065 return OPDESC(op)->op_cacheresult;
1066}
1067
1045static bool need_wrongsec_check(struct svc_rqst *rqstp) 1068static bool need_wrongsec_check(struct svc_rqst *rqstp)
1046{ 1069{
1047 struct nfsd4_compoundres *resp = rqstp->rq_resp; 1070 struct nfsd4_compoundres *resp = rqstp->rq_resp;
@@ -1209,7 +1232,6 @@ encode_op:
1209 fh_put(&resp->cstate.save_fh); 1232 fh_put(&resp->cstate.save_fh);
1210 BUG_ON(resp->cstate.replay_owner); 1233 BUG_ON(resp->cstate.replay_owner);
1211out: 1234out:
1212 nfsd4_release_compoundargs(args);
1213 /* Reset deferral mechanism for RPC deferrals */ 1235 /* Reset deferral mechanism for RPC deferrals */
1214 rqstp->rq_usedeferral = 1; 1236 rqstp->rq_usedeferral = 1;
1215 dprintk("nfsv4 compound returned %d\n", ntohl(status)); 1237 dprintk("nfsv4 compound returned %d\n", ntohl(status));
@@ -1232,6 +1254,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
1232 [OP_CREATE] = { 1254 [OP_CREATE] = {
1233 .op_func = (nfsd4op_func)nfsd4_create, 1255 .op_func = (nfsd4op_func)nfsd4_create,
1234 .op_name = "OP_CREATE", 1256 .op_name = "OP_CREATE",
1257 .op_cacheresult = true,
1235 }, 1258 },
1236 [OP_DELEGRETURN] = { 1259 [OP_DELEGRETURN] = {
1237 .op_func = (nfsd4op_func)nfsd4_delegreturn, 1260 .op_func = (nfsd4op_func)nfsd4_delegreturn,
@@ -1249,6 +1272,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
1249 [OP_LINK] = { 1272 [OP_LINK] = {
1250 .op_func = (nfsd4op_func)nfsd4_link, 1273 .op_func = (nfsd4op_func)nfsd4_link,
1251 .op_name = "OP_LINK", 1274 .op_name = "OP_LINK",
1275 .op_cacheresult = true,
1252 }, 1276 },
1253 [OP_LOCK] = { 1277 [OP_LOCK] = {
1254 .op_func = (nfsd4op_func)nfsd4_lock, 1278 .op_func = (nfsd4op_func)nfsd4_lock,
@@ -1322,10 +1346,12 @@ static struct nfsd4_operation nfsd4_ops[] = {
1322 [OP_REMOVE] = { 1346 [OP_REMOVE] = {
1323 .op_func = (nfsd4op_func)nfsd4_remove, 1347 .op_func = (nfsd4op_func)nfsd4_remove,
1324 .op_name = "OP_REMOVE", 1348 .op_name = "OP_REMOVE",
1349 .op_cacheresult = true,
1325 }, 1350 },
1326 [OP_RENAME] = { 1351 [OP_RENAME] = {
1327 .op_name = "OP_RENAME", 1352 .op_name = "OP_RENAME",
1328 .op_func = (nfsd4op_func)nfsd4_rename, 1353 .op_func = (nfsd4op_func)nfsd4_rename,
1354 .op_cacheresult = true,
1329 }, 1355 },
1330 [OP_RENEW] = { 1356 [OP_RENEW] = {
1331 .op_func = (nfsd4op_func)nfsd4_renew, 1357 .op_func = (nfsd4op_func)nfsd4_renew,
@@ -1351,16 +1377,19 @@ static struct nfsd4_operation nfsd4_ops[] = {
1351 [OP_SETATTR] = { 1377 [OP_SETATTR] = {
1352 .op_func = (nfsd4op_func)nfsd4_setattr, 1378 .op_func = (nfsd4op_func)nfsd4_setattr,
1353 .op_name = "OP_SETATTR", 1379 .op_name = "OP_SETATTR",
1380 .op_cacheresult = true,
1354 }, 1381 },
1355 [OP_SETCLIENTID] = { 1382 [OP_SETCLIENTID] = {
1356 .op_func = (nfsd4op_func)nfsd4_setclientid, 1383 .op_func = (nfsd4op_func)nfsd4_setclientid,
1357 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, 1384 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
1358 .op_name = "OP_SETCLIENTID", 1385 .op_name = "OP_SETCLIENTID",
1386 .op_cacheresult = true,
1359 }, 1387 },
1360 [OP_SETCLIENTID_CONFIRM] = { 1388 [OP_SETCLIENTID_CONFIRM] = {
1361 .op_func = (nfsd4op_func)nfsd4_setclientid_confirm, 1389 .op_func = (nfsd4op_func)nfsd4_setclientid_confirm,
1362 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, 1390 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
1363 .op_name = "OP_SETCLIENTID_CONFIRM", 1391 .op_name = "OP_SETCLIENTID_CONFIRM",
1392 .op_cacheresult = true,
1364 }, 1393 },
1365 [OP_VERIFY] = { 1394 [OP_VERIFY] = {
1366 .op_func = (nfsd4op_func)nfsd4_verify, 1395 .op_func = (nfsd4op_func)nfsd4_verify,
@@ -1369,6 +1398,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
1369 [OP_WRITE] = { 1398 [OP_WRITE] = {
1370 .op_func = (nfsd4op_func)nfsd4_write, 1399 .op_func = (nfsd4op_func)nfsd4_write,
1371 .op_name = "OP_WRITE", 1400 .op_name = "OP_WRITE",
1401 .op_cacheresult = true,
1372 }, 1402 },
1373 [OP_RELEASE_LOCKOWNER] = { 1403 [OP_RELEASE_LOCKOWNER] = {
1374 .op_func = (nfsd4op_func)nfsd4_release_lockowner, 1404 .op_func = (nfsd4op_func)nfsd4_release_lockowner,
@@ -1402,6 +1432,11 @@ static struct nfsd4_operation nfsd4_ops[] = {
1402 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP, 1432 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
1403 .op_name = "OP_SEQUENCE", 1433 .op_name = "OP_SEQUENCE",
1404 }, 1434 },
1435 [OP_DESTROY_CLIENTID] = {
1436 .op_func = NULL,
1437 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
1438 .op_name = "OP_DESTROY_CLIENTID",
1439 },
1405 [OP_RECLAIM_COMPLETE] = { 1440 [OP_RECLAIM_COMPLETE] = {
1406 .op_func = (nfsd4op_func)nfsd4_reclaim_complete, 1441 .op_func = (nfsd4op_func)nfsd4_reclaim_complete,
1407 .op_flags = ALLOWED_WITHOUT_FH, 1442 .op_flags = ALLOWED_WITHOUT_FH,
@@ -1412,6 +1447,16 @@ static struct nfsd4_operation nfsd4_ops[] = {
1412 .op_flags = OP_HANDLES_WRONGSEC, 1447 .op_flags = OP_HANDLES_WRONGSEC,
1413 .op_name = "OP_SECINFO_NO_NAME", 1448 .op_name = "OP_SECINFO_NO_NAME",
1414 }, 1449 },
1450 [OP_TEST_STATEID] = {
1451 .op_func = (nfsd4op_func)nfsd4_test_stateid,
1452 .op_flags = ALLOWED_WITHOUT_FH,
1453 .op_name = "OP_TEST_STATEID",
1454 },
1455 [OP_FREE_STATEID] = {
1456 .op_func = (nfsd4op_func)nfsd4_free_stateid,
1457 .op_flags = ALLOWED_WITHOUT_FH,
1458 .op_name = "OP_FREE_STATEID",
1459 },
1415}; 1460};
1416 1461
1417static const char *nfsd4_op_name(unsigned opnum) 1462static const char *nfsd4_op_name(unsigned opnum)
@@ -1424,16 +1469,6 @@ static const char *nfsd4_op_name(unsigned opnum)
1424#define nfsd4_voidres nfsd4_voidargs 1469#define nfsd4_voidres nfsd4_voidargs
1425struct nfsd4_voidargs { int dummy; }; 1470struct nfsd4_voidargs { int dummy; };
1426 1471
1427/*
1428 * TODO: At the present time, the NFSv4 server does not do XID caching
1429 * of requests. Implementing XID caching would not be a serious problem,
1430 * although it would require a mild change in interfaces since one
1431 * doesn't know whether an NFSv4 request is idempotent until after the
1432 * XDR decode. However, XID caching totally confuses pynfs (Peter
1433 * Astrand's regression testsuite for NFSv4 servers), which reuses
1434 * XID's liberally, so I've left it unimplemented until pynfs generates
1435 * better XID's.
1436 */
1437static struct svc_procedure nfsd_procedures4[2] = { 1472static struct svc_procedure nfsd_procedures4[2] = {
1438 [NFSPROC4_NULL] = { 1473 [NFSPROC4_NULL] = {
1439 .pc_func = (svc_procfunc) nfsd4_proc_null, 1474 .pc_func = (svc_procfunc) nfsd4_proc_null,
@@ -1449,6 +1484,7 @@ static struct svc_procedure nfsd_procedures4[2] = {
1449 .pc_encode = (kxdrproc_t) nfs4svc_encode_compoundres, 1484 .pc_encode = (kxdrproc_t) nfs4svc_encode_compoundres,
1450 .pc_argsize = sizeof(struct nfsd4_compoundargs), 1485 .pc_argsize = sizeof(struct nfsd4_compoundargs),
1451 .pc_ressize = sizeof(struct nfsd4_compoundres), 1486 .pc_ressize = sizeof(struct nfsd4_compoundres),
1487 .pc_release = nfsd4_release_compoundargs,
1452 .pc_cachetype = RC_NOCACHE, 1488 .pc_cachetype = RC_NOCACHE,
1453 .pc_xdrressize = NFSD_BUFSIZE/4, 1489 .pc_xdrressize = NFSD_BUFSIZE/4,
1454 }, 1490 },
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index e98f3c2e949..3787ec11740 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -37,6 +37,7 @@
37#include <linux/slab.h> 37#include <linux/slab.h>
38#include <linux/namei.h> 38#include <linux/namei.h>
39#include <linux/swap.h> 39#include <linux/swap.h>
40#include <linux/pagemap.h>
40#include <linux/sunrpc/svcauth_gss.h> 41#include <linux/sunrpc/svcauth_gss.h>
41#include <linux/sunrpc/clnt.h> 42#include <linux/sunrpc/clnt.h>
42#include "xdr4.h" 43#include "xdr4.h"
@@ -60,9 +61,12 @@ static u64 current_sessionid = 1;
60 61
61/* forward declarations */ 62/* forward declarations */
62static struct nfs4_stateid * find_stateid(stateid_t *stid, int flags); 63static struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
64static struct nfs4_stateid * search_for_stateid(stateid_t *stid);
65static struct nfs4_delegation * search_for_delegation(stateid_t *stid);
63static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid); 66static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
64static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; 67static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
65static void nfs4_set_recdir(char *recdir); 68static void nfs4_set_recdir(char *recdir);
69static int check_for_locks(struct nfs4_file *filp, struct nfs4_stateowner *lowner);
66 70
67/* Locking: */ 71/* Locking: */
68 72
@@ -381,14 +385,6 @@ static int nfs4_access_to_omode(u32 access)
381 BUG(); 385 BUG();
382} 386}
383 387
384static int nfs4_access_bmap_to_omode(struct nfs4_stateid *stp)
385{
386 unsigned int access;
387
388 set_access(&access, stp->st_access_bmap);
389 return nfs4_access_to_omode(access);
390}
391
392static void unhash_generic_stateid(struct nfs4_stateid *stp) 388static void unhash_generic_stateid(struct nfs4_stateid *stp)
393{ 389{
394 list_del(&stp->st_hash); 390 list_del(&stp->st_hash);
@@ -398,11 +394,14 @@ static void unhash_generic_stateid(struct nfs4_stateid *stp)
398 394
399static void free_generic_stateid(struct nfs4_stateid *stp) 395static void free_generic_stateid(struct nfs4_stateid *stp)
400{ 396{
401 int oflag; 397 int i;
402 398
403 if (stp->st_access_bmap) { 399 if (stp->st_access_bmap) {
404 oflag = nfs4_access_bmap_to_omode(stp); 400 for (i = 1; i < 4; i++) {
405 nfs4_file_put_access(stp->st_file, oflag); 401 if (test_bit(i, &stp->st_access_bmap))
402 nfs4_file_put_access(stp->st_file,
403 nfs4_access_to_omode(i));
404 }
406 } 405 }
407 put_nfs4_file(stp->st_file); 406 put_nfs4_file(stp->st_file);
408 kmem_cache_free(stateid_slab, stp); 407 kmem_cache_free(stateid_slab, stp);
@@ -1507,6 +1506,29 @@ nfsd4_replay_create_session(struct nfsd4_create_session *cr_ses,
1507 return slot->sl_status; 1506 return slot->sl_status;
1508} 1507}
1509 1508
1509#define NFSD_MIN_REQ_HDR_SEQ_SZ ((\
1510 2 * 2 + /* credential,verifier: AUTH_NULL, length 0 */ \
1511 1 + /* MIN tag is length with zero, only length */ \
1512 3 + /* version, opcount, opcode */ \
1513 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
1514 /* seqid, slotID, slotID, cache */ \
1515 4 ) * sizeof(__be32))
1516
1517#define NFSD_MIN_RESP_HDR_SEQ_SZ ((\
1518 2 + /* verifier: AUTH_NULL, length 0 */\
1519 1 + /* status */ \
1520 1 + /* MIN tag is length with zero, only length */ \
1521 3 + /* opcount, opcode, opstatus*/ \
1522 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
1523 /* seqid, slotID, slotID, slotID, status */ \
1524 5 ) * sizeof(__be32))
1525
1526static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs fchannel)
1527{
1528 return fchannel.maxreq_sz < NFSD_MIN_REQ_HDR_SEQ_SZ
1529 || fchannel.maxresp_sz < NFSD_MIN_RESP_HDR_SEQ_SZ;
1530}
1531
1510__be32 1532__be32
1511nfsd4_create_session(struct svc_rqst *rqstp, 1533nfsd4_create_session(struct svc_rqst *rqstp,
1512 struct nfsd4_compound_state *cstate, 1534 struct nfsd4_compound_state *cstate,
@@ -1575,6 +1597,10 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1575 cr_ses->flags &= ~SESSION4_PERSIST; 1597 cr_ses->flags &= ~SESSION4_PERSIST;
1576 cr_ses->flags &= ~SESSION4_RDMA; 1598 cr_ses->flags &= ~SESSION4_RDMA;
1577 1599
1600 status = nfserr_toosmall;
1601 if (check_forechannel_attrs(cr_ses->fore_channel))
1602 goto out;
1603
1578 status = nfserr_jukebox; 1604 status = nfserr_jukebox;
1579 new = alloc_init_session(rqstp, conf, cr_ses); 1605 new = alloc_init_session(rqstp, conf, cr_ses);
1580 if (!new) 1606 if (!new)
@@ -1736,6 +1762,14 @@ static bool nfsd4_session_too_many_ops(struct svc_rqst *rqstp, struct nfsd4_sess
1736 return args->opcnt > session->se_fchannel.maxops; 1762 return args->opcnt > session->se_fchannel.maxops;
1737} 1763}
1738 1764
1765static bool nfsd4_request_too_big(struct svc_rqst *rqstp,
1766 struct nfsd4_session *session)
1767{
1768 struct xdr_buf *xb = &rqstp->rq_arg;
1769
1770 return xb->len > session->se_fchannel.maxreq_sz;
1771}
1772
1739__be32 1773__be32
1740nfsd4_sequence(struct svc_rqst *rqstp, 1774nfsd4_sequence(struct svc_rqst *rqstp,
1741 struct nfsd4_compound_state *cstate, 1775 struct nfsd4_compound_state *cstate,
@@ -1768,6 +1802,10 @@ nfsd4_sequence(struct svc_rqst *rqstp,
1768 if (nfsd4_session_too_many_ops(rqstp, session)) 1802 if (nfsd4_session_too_many_ops(rqstp, session))
1769 goto out; 1803 goto out;
1770 1804
1805 status = nfserr_req_too_big;
1806 if (nfsd4_request_too_big(rqstp, session))
1807 goto out;
1808
1771 status = nfserr_badslot; 1809 status = nfserr_badslot;
1772 if (seq->slotid >= session->se_fchannel.maxreqs) 1810 if (seq->slotid >= session->se_fchannel.maxreqs)
1773 goto out; 1811 goto out;
@@ -2337,15 +2375,6 @@ out:
2337 return ret; 2375 return ret;
2338} 2376}
2339 2377
2340static inline void
2341nfs4_file_downgrade(struct nfs4_file *fp, unsigned int share_access)
2342{
2343 if (share_access & NFS4_SHARE_ACCESS_WRITE)
2344 nfs4_file_put_access(fp, O_WRONLY);
2345 if (share_access & NFS4_SHARE_ACCESS_READ)
2346 nfs4_file_put_access(fp, O_RDONLY);
2347}
2348
2349static void nfsd_break_one_deleg(struct nfs4_delegation *dp) 2378static void nfsd_break_one_deleg(struct nfs4_delegation *dp)
2350{ 2379{
2351 /* We're assuming the state code never drops its reference 2380 /* We're assuming the state code never drops its reference
@@ -2396,8 +2425,8 @@ int nfsd_change_deleg_cb(struct file_lock **onlist, int arg)
2396} 2425}
2397 2426
2398static const struct lock_manager_operations nfsd_lease_mng_ops = { 2427static const struct lock_manager_operations nfsd_lease_mng_ops = {
2399 .fl_break = nfsd_break_deleg_cb, 2428 .lm_break = nfsd_break_deleg_cb,
2400 .fl_change = nfsd_change_deleg_cb, 2429 .lm_change = nfsd_change_deleg_cb,
2401}; 2430};
2402 2431
2403 2432
@@ -2556,12 +2585,18 @@ static inline int nfs4_access_to_access(u32 nfs4_access)
2556 return flags; 2585 return flags;
2557} 2586}
2558 2587
2559static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file 2588static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp,
2560*fp, struct svc_fh *cur_fh, u32 nfs4_access) 2589 struct svc_fh *cur_fh, struct nfsd4_open *open)
2561{ 2590{
2562 __be32 status; 2591 __be32 status;
2563 int oflag = nfs4_access_to_omode(nfs4_access); 2592 int oflag = nfs4_access_to_omode(open->op_share_access);
2564 int access = nfs4_access_to_access(nfs4_access); 2593 int access = nfs4_access_to_access(open->op_share_access);
2594
2595 /* CLAIM_DELEGATE_CUR is used in response to a broken lease;
2596 * allowing it to break the lease and return EAGAIN leaves the
2597 * client unable to make progress in returning the delegation */
2598 if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR)
2599 access |= NFSD_MAY_NOT_BREAK_LEASE;
2565 2600
2566 if (!fp->fi_fds[oflag]) { 2601 if (!fp->fi_fds[oflag]) {
2567 status = nfsd_open(rqstp, cur_fh, S_IFREG, access, 2602 status = nfsd_open(rqstp, cur_fh, S_IFREG, access,
@@ -2586,7 +2621,7 @@ nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
2586 if (stp == NULL) 2621 if (stp == NULL)
2587 return nfserr_resource; 2622 return nfserr_resource;
2588 2623
2589 status = nfs4_get_vfs_file(rqstp, fp, cur_fh, open->op_share_access); 2624 status = nfs4_get_vfs_file(rqstp, fp, cur_fh, open);
2590 if (status) { 2625 if (status) {
2591 kmem_cache_free(stateid_slab, stp); 2626 kmem_cache_free(stateid_slab, stp);
2592 return status; 2627 return status;
@@ -2619,14 +2654,14 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct nfs4_file *fp, struct svc_fh *c
2619 2654
2620 new_access = !test_bit(op_share_access, &stp->st_access_bmap); 2655 new_access = !test_bit(op_share_access, &stp->st_access_bmap);
2621 if (new_access) { 2656 if (new_access) {
2622 status = nfs4_get_vfs_file(rqstp, fp, cur_fh, op_share_access); 2657 status = nfs4_get_vfs_file(rqstp, fp, cur_fh, open);
2623 if (status) 2658 if (status)
2624 return status; 2659 return status;
2625 } 2660 }
2626 status = nfsd4_truncate(rqstp, cur_fh, open); 2661 status = nfsd4_truncate(rqstp, cur_fh, open);
2627 if (status) { 2662 if (status) {
2628 if (new_access) { 2663 if (new_access) {
2629 int oflag = nfs4_access_to_omode(new_access); 2664 int oflag = nfs4_access_to_omode(op_share_access);
2630 nfs4_file_put_access(fp, oflag); 2665 nfs4_file_put_access(fp, oflag);
2631 } 2666 }
2632 return status; 2667 return status;
@@ -3137,6 +3172,37 @@ static int is_delegation_stateid(stateid_t *stateid)
3137 return stateid->si_fileid == 0; 3172 return stateid->si_fileid == 0;
3138} 3173}
3139 3174
3175static int is_open_stateid(struct nfs4_stateid *stateid)
3176{
3177 return stateid->st_openstp == NULL;
3178}
3179
3180__be32 nfs4_validate_stateid(stateid_t *stateid, int flags)
3181{
3182 struct nfs4_stateid *stp = NULL;
3183 __be32 status = nfserr_stale_stateid;
3184
3185 if (STALE_STATEID(stateid))
3186 goto out;
3187
3188 status = nfserr_expired;
3189 stp = search_for_stateid(stateid);
3190 if (!stp)
3191 goto out;
3192 status = nfserr_bad_stateid;
3193
3194 if (!stp->st_stateowner->so_confirmed)
3195 goto out;
3196
3197 status = check_stateid_generation(stateid, &stp->st_stateid, flags);
3198 if (status)
3199 goto out;
3200
3201 status = nfs_ok;
3202out:
3203 return status;
3204}
3205
3140/* 3206/*
3141* Checks for stateid operations 3207* Checks for stateid operations
3142*/ 3208*/
@@ -3216,6 +3282,81 @@ out:
3216 return status; 3282 return status;
3217} 3283}
3218 3284
3285static __be32
3286nfsd4_free_delegation_stateid(stateid_t *stateid)
3287{
3288 struct nfs4_delegation *dp = search_for_delegation(stateid);
3289 if (dp)
3290 return nfserr_locks_held;
3291 return nfserr_bad_stateid;
3292}
3293
3294static __be32
3295nfsd4_free_lock_stateid(struct nfs4_stateid *stp)
3296{
3297 if (check_for_locks(stp->st_file, stp->st_stateowner))
3298 return nfserr_locks_held;
3299 release_lock_stateid(stp);
3300 return nfs_ok;
3301}
3302
3303/*
3304 * Test if the stateid is valid
3305 */
3306__be32
3307nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3308 struct nfsd4_test_stateid *test_stateid)
3309{
3310 test_stateid->ts_has_session = nfsd4_has_session(cstate);
3311 return nfs_ok;
3312}
3313
3314/*
3315 * Free a state id
3316 */
3317__be32
3318nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3319 struct nfsd4_free_stateid *free_stateid)
3320{
3321 stateid_t *stateid = &free_stateid->fr_stateid;
3322 struct nfs4_stateid *stp;
3323 __be32 ret;
3324
3325 nfs4_lock_state();
3326 if (is_delegation_stateid(stateid)) {
3327 ret = nfsd4_free_delegation_stateid(stateid);
3328 goto out;
3329 }
3330
3331 stp = search_for_stateid(stateid);
3332 if (!stp) {
3333 ret = nfserr_bad_stateid;
3334 goto out;
3335 }
3336 if (stateid->si_generation != 0) {
3337 if (stateid->si_generation < stp->st_stateid.si_generation) {
3338 ret = nfserr_old_stateid;
3339 goto out;
3340 }
3341 if (stateid->si_generation > stp->st_stateid.si_generation) {
3342 ret = nfserr_bad_stateid;
3343 goto out;
3344 }
3345 }
3346
3347 if (is_open_stateid(stp)) {
3348 ret = nfserr_locks_held;
3349 goto out;
3350 } else {
3351 ret = nfsd4_free_lock_stateid(stp);
3352 goto out;
3353 }
3354
3355out:
3356 nfs4_unlock_state();
3357 return ret;
3358}
3359
3219static inline int 3360static inline int
3220setlkflg (int type) 3361setlkflg (int type)
3221{ 3362{
@@ -3384,18 +3525,15 @@ out:
3384 return status; 3525 return status;
3385} 3526}
3386 3527
3387 3528static inline void nfs4_file_downgrade(struct nfs4_stateid *stp, unsigned int to_access)
3388/*
3389 * unset all bits in union bitmap (bmap) that
3390 * do not exist in share (from successful OPEN_DOWNGRADE)
3391 */
3392static void
3393reset_union_bmap_access(unsigned long access, unsigned long *bmap)
3394{ 3529{
3395 int i; 3530 int i;
3531
3396 for (i = 1; i < 4; i++) { 3532 for (i = 1; i < 4; i++) {
3397 if ((i & access) != i) 3533 if (test_bit(i, &stp->st_access_bmap) && !(i & to_access)) {
3398 __clear_bit(i, bmap); 3534 nfs4_file_put_access(stp->st_file, i);
3535 __clear_bit(i, &stp->st_access_bmap);
3536 }
3399 } 3537 }
3400} 3538}
3401 3539
@@ -3416,7 +3554,6 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
3416{ 3554{
3417 __be32 status; 3555 __be32 status;
3418 struct nfs4_stateid *stp; 3556 struct nfs4_stateid *stp;
3419 unsigned int share_access;
3420 3557
3421 dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n", 3558 dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n",
3422 (int)cstate->current_fh.fh_dentry->d_name.len, 3559 (int)cstate->current_fh.fh_dentry->d_name.len,
@@ -3445,10 +3582,8 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
3445 stp->st_deny_bmap, od->od_share_deny); 3582 stp->st_deny_bmap, od->od_share_deny);
3446 goto out; 3583 goto out;
3447 } 3584 }
3448 set_access(&share_access, stp->st_access_bmap); 3585 nfs4_file_downgrade(stp, od->od_share_access);
3449 nfs4_file_downgrade(stp->st_file, share_access & ~od->od_share_access);
3450 3586
3451 reset_union_bmap_access(od->od_share_access, &stp->st_access_bmap);
3452 reset_union_bmap_deny(od->od_share_deny, &stp->st_deny_bmap); 3587 reset_union_bmap_deny(od->od_share_deny, &stp->st_deny_bmap);
3453 3588
3454 update_stateid(&stp->st_stateid); 3589 update_stateid(&stp->st_stateid);
@@ -3594,6 +3729,14 @@ static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE];
3594static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE]; 3729static struct list_head lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
3595static struct list_head lockstateid_hashtbl[STATEID_HASH_SIZE]; 3730static struct list_head lockstateid_hashtbl[STATEID_HASH_SIZE];
3596 3731
3732static int
3733same_stateid(stateid_t *id_one, stateid_t *id_two)
3734{
3735 if (id_one->si_stateownerid != id_two->si_stateownerid)
3736 return 0;
3737 return id_one->si_fileid == id_two->si_fileid;
3738}
3739
3597static struct nfs4_stateid * 3740static struct nfs4_stateid *
3598find_stateid(stateid_t *stid, int flags) 3741find_stateid(stateid_t *stid, int flags)
3599{ 3742{
@@ -3623,6 +3766,44 @@ find_stateid(stateid_t *stid, int flags)
3623 return NULL; 3766 return NULL;
3624} 3767}
3625 3768
3769static struct nfs4_stateid *
3770search_for_stateid(stateid_t *stid)
3771{
3772 struct nfs4_stateid *local;
3773 unsigned int hashval = stateid_hashval(stid->si_stateownerid, stid->si_fileid);
3774
3775 list_for_each_entry(local, &lockstateid_hashtbl[hashval], st_hash) {
3776 if (same_stateid(&local->st_stateid, stid))
3777 return local;
3778 }
3779
3780 list_for_each_entry(local, &stateid_hashtbl[hashval], st_hash) {
3781 if (same_stateid(&local->st_stateid, stid))
3782 return local;
3783 }
3784 return NULL;
3785}
3786
3787static struct nfs4_delegation *
3788search_for_delegation(stateid_t *stid)
3789{
3790 struct nfs4_file *fp;
3791 struct nfs4_delegation *dp;
3792 struct list_head *pos;
3793 int i;
3794
3795 for (i = 0; i < FILE_HASH_SIZE; i++) {
3796 list_for_each_entry(fp, &file_hashtbl[i], fi_hash) {
3797 list_for_each(pos, &fp->fi_delegations) {
3798 dp = list_entry(pos, struct nfs4_delegation, dl_perfile);
3799 if (same_stateid(&dp->dl_stateid, stid))
3800 return dp;
3801 }
3802 }
3803 }
3804 return NULL;
3805}
3806
3626static struct nfs4_delegation * 3807static struct nfs4_delegation *
3627find_delegation_stateid(struct inode *ino, stateid_t *stid) 3808find_delegation_stateid(struct inode *ino, stateid_t *stid)
3628{ 3809{
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 99018110321..c8bf405d19d 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -44,13 +44,15 @@
44#include <linux/namei.h> 44#include <linux/namei.h>
45#include <linux/statfs.h> 45#include <linux/statfs.h>
46#include <linux/utsname.h> 46#include <linux/utsname.h>
47#include <linux/pagemap.h>
47#include <linux/sunrpc/svcauth_gss.h> 48#include <linux/sunrpc/svcauth_gss.h>
48 49
49#include "idmap.h" 50#include "idmap.h"
50#include "acl.h" 51#include "acl.h"
51#include "xdr4.h" 52#include "xdr4.h"
52#include "vfs.h" 53#include "vfs.h"
53 54#include "state.h"
55#include "cache.h"
54 56
55#define NFSDDBG_FACILITY NFSDDBG_XDR 57#define NFSDDBG_FACILITY NFSDDBG_XDR
56 58
@@ -131,6 +133,22 @@ xdr_error: \
131 } \ 133 } \
132} while (0) 134} while (0)
133 135
136static void save_buf(struct nfsd4_compoundargs *argp, struct nfsd4_saved_compoundargs *savep)
137{
138 savep->p = argp->p;
139 savep->end = argp->end;
140 savep->pagelen = argp->pagelen;
141 savep->pagelist = argp->pagelist;
142}
143
144static void restore_buf(struct nfsd4_compoundargs *argp, struct nfsd4_saved_compoundargs *savep)
145{
146 argp->p = savep->p;
147 argp->end = savep->end;
148 argp->pagelen = savep->pagelen;
149 argp->pagelist = savep->pagelist;
150}
151
134static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) 152static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)
135{ 153{
136 /* We want more bytes than seem to be available. 154 /* We want more bytes than seem to be available.
@@ -1246,6 +1264,19 @@ nfsd4_decode_destroy_session(struct nfsd4_compoundargs *argp,
1246} 1264}
1247 1265
1248static __be32 1266static __be32
1267nfsd4_decode_free_stateid(struct nfsd4_compoundargs *argp,
1268 struct nfsd4_free_stateid *free_stateid)
1269{
1270 DECODE_HEAD;
1271
1272 READ_BUF(sizeof(stateid_t));
1273 READ32(free_stateid->fr_stateid.si_generation);
1274 COPYMEM(&free_stateid->fr_stateid.si_opaque, sizeof(stateid_opaque_t));
1275
1276 DECODE_TAIL;
1277}
1278
1279static __be32
1249nfsd4_decode_sequence(struct nfsd4_compoundargs *argp, 1280nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
1250 struct nfsd4_sequence *seq) 1281 struct nfsd4_sequence *seq)
1251{ 1282{
@@ -1261,6 +1292,40 @@ nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
1261 DECODE_TAIL; 1292 DECODE_TAIL;
1262} 1293}
1263 1294
1295static __be32
1296nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stateid *test_stateid)
1297{
1298 unsigned int nbytes;
1299 stateid_t si;
1300 int i;
1301 __be32 *p;
1302 __be32 status;
1303
1304 READ_BUF(4);
1305 test_stateid->ts_num_ids = ntohl(*p++);
1306
1307 nbytes = test_stateid->ts_num_ids * sizeof(stateid_t);
1308 if (nbytes > (u32)((char *)argp->end - (char *)argp->p))
1309 goto xdr_error;
1310
1311 test_stateid->ts_saved_args = argp;
1312 save_buf(argp, &test_stateid->ts_savedp);
1313
1314 for (i = 0; i < test_stateid->ts_num_ids; i++) {
1315 status = nfsd4_decode_stateid(argp, &si);
1316 if (status)
1317 return status;
1318 }
1319
1320 status = 0;
1321out:
1322 return status;
1323xdr_error:
1324 dprintk("NFSD: xdr error (%s:%d)\n", __FILE__, __LINE__);
1325 status = nfserr_bad_xdr;
1326 goto out;
1327}
1328
1264static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, struct nfsd4_reclaim_complete *rc) 1329static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, struct nfsd4_reclaim_complete *rc)
1265{ 1330{
1266 DECODE_HEAD; 1331 DECODE_HEAD;
@@ -1370,7 +1435,7 @@ static nfsd4_dec nfsd41_dec_ops[] = {
1370 [OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id, 1435 [OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id,
1371 [OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session, 1436 [OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session,
1372 [OP_DESTROY_SESSION] = (nfsd4_dec)nfsd4_decode_destroy_session, 1437 [OP_DESTROY_SESSION] = (nfsd4_dec)nfsd4_decode_destroy_session,
1373 [OP_FREE_STATEID] = (nfsd4_dec)nfsd4_decode_notsupp, 1438 [OP_FREE_STATEID] = (nfsd4_dec)nfsd4_decode_free_stateid,
1374 [OP_GET_DIR_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp, 1439 [OP_GET_DIR_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp,
1375 [OP_GETDEVICEINFO] = (nfsd4_dec)nfsd4_decode_notsupp, 1440 [OP_GETDEVICEINFO] = (nfsd4_dec)nfsd4_decode_notsupp,
1376 [OP_GETDEVICELIST] = (nfsd4_dec)nfsd4_decode_notsupp, 1441 [OP_GETDEVICELIST] = (nfsd4_dec)nfsd4_decode_notsupp,
@@ -1380,7 +1445,7 @@ static nfsd4_dec nfsd41_dec_ops[] = {
1380 [OP_SECINFO_NO_NAME] = (nfsd4_dec)nfsd4_decode_secinfo_no_name, 1445 [OP_SECINFO_NO_NAME] = (nfsd4_dec)nfsd4_decode_secinfo_no_name,
1381 [OP_SEQUENCE] = (nfsd4_dec)nfsd4_decode_sequence, 1446 [OP_SEQUENCE] = (nfsd4_dec)nfsd4_decode_sequence,
1382 [OP_SET_SSV] = (nfsd4_dec)nfsd4_decode_notsupp, 1447 [OP_SET_SSV] = (nfsd4_dec)nfsd4_decode_notsupp,
1383 [OP_TEST_STATEID] = (nfsd4_dec)nfsd4_decode_notsupp, 1448 [OP_TEST_STATEID] = (nfsd4_dec)nfsd4_decode_test_stateid,
1384 [OP_WANT_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp, 1449 [OP_WANT_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp,
1385 [OP_DESTROY_CLIENTID] = (nfsd4_dec)nfsd4_decode_notsupp, 1450 [OP_DESTROY_CLIENTID] = (nfsd4_dec)nfsd4_decode_notsupp,
1386 [OP_RECLAIM_COMPLETE] = (nfsd4_dec)nfsd4_decode_reclaim_complete, 1451 [OP_RECLAIM_COMPLETE] = (nfsd4_dec)nfsd4_decode_reclaim_complete,
@@ -1402,6 +1467,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1402 DECODE_HEAD; 1467 DECODE_HEAD;
1403 struct nfsd4_op *op; 1468 struct nfsd4_op *op;
1404 struct nfsd4_minorversion_ops *ops; 1469 struct nfsd4_minorversion_ops *ops;
1470 bool cachethis = false;
1405 int i; 1471 int i;
1406 1472
1407 /* 1473 /*
@@ -1483,7 +1549,16 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1483 argp->opcnt = i+1; 1549 argp->opcnt = i+1;
1484 break; 1550 break;
1485 } 1551 }
1552 /*
1553 * We'll try to cache the result in the DRC if any one
1554 * op in the compound wants to be cached:
1555 */
1556 cachethis |= nfsd4_cache_this_op(op);
1486 } 1557 }
1558 /* Sessions make the DRC unnecessary: */
1559 if (argp->minorversion)
1560 cachethis = false;
1561 argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE;
1487 1562
1488 DECODE_TAIL; 1563 DECODE_TAIL;
1489} 1564}
@@ -3116,6 +3191,21 @@ nfsd4_encode_destroy_session(struct nfsd4_compoundres *resp, int nfserr,
3116} 3191}
3117 3192
3118static __be32 3193static __be32
3194nfsd4_encode_free_stateid(struct nfsd4_compoundres *resp, int nfserr,
3195 struct nfsd4_free_stateid *free_stateid)
3196{
3197 __be32 *p;
3198
3199 if (nfserr)
3200 return nfserr;
3201
3202 RESERVE_SPACE(4);
3203 WRITE32(nfserr);
3204 ADJUST_ARGS();
3205 return nfserr;
3206}
3207
3208static __be32
3119nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr, 3209nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr,
3120 struct nfsd4_sequence *seq) 3210 struct nfsd4_sequence *seq)
3121{ 3211{
@@ -3138,6 +3228,36 @@ nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr,
3138 return 0; 3228 return 0;
3139} 3229}
3140 3230
3231__be32
3232nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, int nfserr,
3233 struct nfsd4_test_stateid *test_stateid)
3234{
3235 struct nfsd4_compoundargs *argp;
3236 stateid_t si;
3237 __be32 *p;
3238 int i;
3239 int valid;
3240
3241 restore_buf(test_stateid->ts_saved_args, &test_stateid->ts_savedp);
3242 argp = test_stateid->ts_saved_args;
3243
3244 RESERVE_SPACE(4);
3245 *p++ = htonl(test_stateid->ts_num_ids);
3246 resp->p = p;
3247
3248 nfs4_lock_state();
3249 for (i = 0; i < test_stateid->ts_num_ids; i++) {
3250 nfsd4_decode_stateid(argp, &si);
3251 valid = nfs4_validate_stateid(&si, test_stateid->ts_has_session);
3252 RESERVE_SPACE(4);
3253 *p++ = htonl(valid);
3254 resp->p = p;
3255 }
3256 nfs4_unlock_state();
3257
3258 return nfserr;
3259}
3260
3141static __be32 3261static __be32
3142nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p) 3262nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p)
3143{ 3263{
@@ -3196,7 +3316,7 @@ static nfsd4_enc nfsd4_enc_ops[] = {
3196 [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id, 3316 [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id,
3197 [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session, 3317 [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session,
3198 [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_destroy_session, 3318 [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_destroy_session,
3199 [OP_FREE_STATEID] = (nfsd4_enc)nfsd4_encode_noop, 3319 [OP_FREE_STATEID] = (nfsd4_enc)nfsd4_encode_free_stateid,
3200 [OP_GET_DIR_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop, 3320 [OP_GET_DIR_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop,
3201 [OP_GETDEVICEINFO] = (nfsd4_enc)nfsd4_encode_noop, 3321 [OP_GETDEVICEINFO] = (nfsd4_enc)nfsd4_encode_noop,
3202 [OP_GETDEVICELIST] = (nfsd4_enc)nfsd4_encode_noop, 3322 [OP_GETDEVICELIST] = (nfsd4_enc)nfsd4_encode_noop,
@@ -3206,7 +3326,7 @@ static nfsd4_enc nfsd4_enc_ops[] = {
3206 [OP_SECINFO_NO_NAME] = (nfsd4_enc)nfsd4_encode_secinfo_no_name, 3326 [OP_SECINFO_NO_NAME] = (nfsd4_enc)nfsd4_encode_secinfo_no_name,
3207 [OP_SEQUENCE] = (nfsd4_enc)nfsd4_encode_sequence, 3327 [OP_SEQUENCE] = (nfsd4_enc)nfsd4_encode_sequence,
3208 [OP_SET_SSV] = (nfsd4_enc)nfsd4_encode_noop, 3328 [OP_SET_SSV] = (nfsd4_enc)nfsd4_encode_noop,
3209 [OP_TEST_STATEID] = (nfsd4_enc)nfsd4_encode_noop, 3329 [OP_TEST_STATEID] = (nfsd4_enc)nfsd4_encode_test_stateid,
3210 [OP_WANT_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop, 3330 [OP_WANT_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop,
3211 [OP_DESTROY_CLIENTID] = (nfsd4_enc)nfsd4_encode_noop, 3331 [OP_DESTROY_CLIENTID] = (nfsd4_enc)nfsd4_encode_noop,
3212 [OP_RECLAIM_COMPLETE] = (nfsd4_enc)nfsd4_encode_noop, 3332 [OP_RECLAIM_COMPLETE] = (nfsd4_enc)nfsd4_encode_noop,
@@ -3319,8 +3439,11 @@ nfs4svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
3319 return xdr_ressize_check(rqstp, p); 3439 return xdr_ressize_check(rqstp, p);
3320} 3440}
3321 3441
3322void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args) 3442int nfsd4_release_compoundargs(void *rq, __be32 *p, void *resp)
3323{ 3443{
3444 struct svc_rqst *rqstp = rq;
3445 struct nfsd4_compoundargs *args = rqstp->rq_argp;
3446
3324 if (args->ops != args->iops) { 3447 if (args->ops != args->iops) {
3325 kfree(args->ops); 3448 kfree(args->ops);
3326 args->ops = args->iops; 3449 args->ops = args->iops;
@@ -3333,13 +3456,12 @@ void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args)
3333 tb->release(tb->buf); 3456 tb->release(tb->buf);
3334 kfree(tb); 3457 kfree(tb);
3335 } 3458 }
3459 return 1;
3336} 3460}
3337 3461
3338int 3462int
3339nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args) 3463nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args)
3340{ 3464{
3341 __be32 status;
3342
3343 args->p = p; 3465 args->p = p;
3344 args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len; 3466 args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len;
3345 args->pagelist = rqstp->rq_arg.pages; 3467 args->pagelist = rqstp->rq_arg.pages;
@@ -3349,11 +3471,7 @@ nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_comp
3349 args->ops = args->iops; 3471 args->ops = args->iops;
3350 args->rqstp = rqstp; 3472 args->rqstp = rqstp;
3351 3473
3352 status = nfsd4_decode_compound(args); 3474 return !nfsd4_decode_compound(args);
3353 if (status) {
3354 nfsd4_release_compoundargs(args);
3355 }
3356 return !status;
3357} 3475}
3358 3476
3359int 3477int
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index 4666a209678..2cbac34a55d 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -118,7 +118,7 @@ hash_refile(struct svc_cacherep *rp)
118 * Note that no operation within the loop may sleep. 118 * Note that no operation within the loop may sleep.
119 */ 119 */
120int 120int
121nfsd_cache_lookup(struct svc_rqst *rqstp, int type) 121nfsd_cache_lookup(struct svc_rqst *rqstp)
122{ 122{
123 struct hlist_node *hn; 123 struct hlist_node *hn;
124 struct hlist_head *rh; 124 struct hlist_head *rh;
@@ -128,6 +128,7 @@ nfsd_cache_lookup(struct svc_rqst *rqstp, int type)
128 vers = rqstp->rq_vers, 128 vers = rqstp->rq_vers,
129 proc = rqstp->rq_proc; 129 proc = rqstp->rq_proc;
130 unsigned long age; 130 unsigned long age;
131 int type = rqstp->rq_cachetype;
131 int rtn; 132 int rtn;
132 133
133 rqstp->rq_cacherep = NULL; 134 rqstp->rq_cacherep = NULL;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 2b1449dd2f4..c7716143cbd 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -24,15 +24,6 @@
24 */ 24 */
25enum { 25enum {
26 NFSD_Root = 1, 26 NFSD_Root = 1,
27#ifdef CONFIG_NFSD_DEPRECATED
28 NFSD_Svc,
29 NFSD_Add,
30 NFSD_Del,
31 NFSD_Export,
32 NFSD_Unexport,
33 NFSD_Getfd,
34 NFSD_Getfs,
35#endif
36 NFSD_List, 27 NFSD_List,
37 NFSD_Export_features, 28 NFSD_Export_features,
38 NFSD_Fh, 29 NFSD_Fh,
@@ -59,15 +50,6 @@ enum {
59/* 50/*
60 * write() for these nodes. 51 * write() for these nodes.
61 */ 52 */
62#ifdef CONFIG_NFSD_DEPRECATED
63static ssize_t write_svc(struct file *file, char *buf, size_t size);
64static ssize_t write_add(struct file *file, char *buf, size_t size);
65static ssize_t write_del(struct file *file, char *buf, size_t size);
66static ssize_t write_export(struct file *file, char *buf, size_t size);
67static ssize_t write_unexport(struct file *file, char *buf, size_t size);
68static ssize_t write_getfd(struct file *file, char *buf, size_t size);
69static ssize_t write_getfs(struct file *file, char *buf, size_t size);
70#endif
71static ssize_t write_filehandle(struct file *file, char *buf, size_t size); 53static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
72static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size); 54static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size);
73static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size); 55static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size);
@@ -83,15 +65,6 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
83#endif 65#endif
84 66
85static ssize_t (*write_op[])(struct file *, char *, size_t) = { 67static ssize_t (*write_op[])(struct file *, char *, size_t) = {
86#ifdef CONFIG_NFSD_DEPRECATED
87 [NFSD_Svc] = write_svc,
88 [NFSD_Add] = write_add,
89 [NFSD_Del] = write_del,
90 [NFSD_Export] = write_export,
91 [NFSD_Unexport] = write_unexport,
92 [NFSD_Getfd] = write_getfd,
93 [NFSD_Getfs] = write_getfs,
94#endif
95 [NFSD_Fh] = write_filehandle, 68 [NFSD_Fh] = write_filehandle,
96 [NFSD_FO_UnlockIP] = write_unlock_ip, 69 [NFSD_FO_UnlockIP] = write_unlock_ip,
97 [NFSD_FO_UnlockFS] = write_unlock_fs, 70 [NFSD_FO_UnlockFS] = write_unlock_fs,
@@ -130,16 +103,6 @@ static ssize_t nfsctl_transaction_write(struct file *file, const char __user *bu
130 103
131static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos) 104static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
132{ 105{
133#ifdef CONFIG_NFSD_DEPRECATED
134 static int warned;
135 if (file->f_dentry->d_name.name[0] == '.' && !warned) {
136 printk(KERN_INFO
137 "Warning: \"%s\" uses deprecated NFSD interface: %s."
138 " This will be removed in 2.6.40\n",
139 current->comm, file->f_dentry->d_name.name);
140 warned = 1;
141 }
142#endif
143 if (! file->private_data) { 106 if (! file->private_data) {
144 /* An attempt to read a transaction file without writing 107 /* An attempt to read a transaction file without writing
145 * causes a 0-byte write so that the file can return 108 * causes a 0-byte write so that the file can return
@@ -226,303 +189,6 @@ static const struct file_operations pool_stats_operations = {
226 * payload - write methods 189 * payload - write methods
227 */ 190 */
228 191
229#ifdef CONFIG_NFSD_DEPRECATED
230/**
231 * write_svc - Start kernel's NFSD server
232 *
233 * Deprecated. /proc/fs/nfsd/threads is preferred.
234 * Function remains to support old versions of nfs-utils.
235 *
236 * Input:
237 * buf: struct nfsctl_svc
238 * svc_port: port number of this
239 * server's listener
240 * svc_nthreads: number of threads to start
241 * size: size in bytes of passed in nfsctl_svc
242 * Output:
243 * On success: returns zero
244 * On error: return code is negative errno value
245 */
246static ssize_t write_svc(struct file *file, char *buf, size_t size)
247{
248 struct nfsctl_svc *data;
249 int err;
250 if (size < sizeof(*data))
251 return -EINVAL;
252 data = (struct nfsctl_svc*) buf;
253 err = nfsd_svc(data->svc_port, data->svc_nthreads);
254 if (err < 0)
255 return err;
256 return 0;
257}
258
259/**
260 * write_add - Add or modify client entry in auth unix cache
261 *
262 * Deprecated. /proc/net/rpc/auth.unix.ip is preferred.
263 * Function remains to support old versions of nfs-utils.
264 *
265 * Input:
266 * buf: struct nfsctl_client
267 * cl_ident: '\0'-terminated C string
268 * containing domain name
269 * of client
270 * cl_naddr: no. of items in cl_addrlist
271 * cl_addrlist: array of client addresses
272 * cl_fhkeytype: ignored
273 * cl_fhkeylen: ignored
274 * cl_fhkey: ignored
275 * size: size in bytes of passed in nfsctl_client
276 * Output:
277 * On success: returns zero
278 * On error: return code is negative errno value
279 *
280 * Note: Only AF_INET client addresses are passed in, since
281 * nfsctl_client.cl_addrlist contains only in_addr fields for addresses.
282 */
283static ssize_t write_add(struct file *file, char *buf, size_t size)
284{
285 struct nfsctl_client *data;
286 if (size < sizeof(*data))
287 return -EINVAL;
288 data = (struct nfsctl_client *)buf;
289 return exp_addclient(data);
290}
291
292/**
293 * write_del - Remove client from auth unix cache
294 *
295 * Deprecated. /proc/net/rpc/auth.unix.ip is preferred.
296 * Function remains to support old versions of nfs-utils.
297 *
298 * Input:
299 * buf: struct nfsctl_client
300 * cl_ident: '\0'-terminated C string
301 * containing domain name
302 * of client
303 * cl_naddr: ignored
304 * cl_addrlist: ignored
305 * cl_fhkeytype: ignored
306 * cl_fhkeylen: ignored
307 * cl_fhkey: ignored
308 * size: size in bytes of passed in nfsctl_client
309 * Output:
310 * On success: returns zero
311 * On error: return code is negative errno value
312 *
313 * Note: Only AF_INET client addresses are passed in, since
314 * nfsctl_client.cl_addrlist contains only in_addr fields for addresses.
315 */
316static ssize_t write_del(struct file *file, char *buf, size_t size)
317{
318 struct nfsctl_client *data;
319 if (size < sizeof(*data))
320 return -EINVAL;
321 data = (struct nfsctl_client *)buf;
322 return exp_delclient(data);
323}
324
325/**
326 * write_export - Export part or all of a local file system
327 *
328 * Deprecated. /proc/net/rpc/{nfsd.export,nfsd.fh} are preferred.
329 * Function remains to support old versions of nfs-utils.
330 *
331 * Input:
332 * buf: struct nfsctl_export
333 * ex_client: '\0'-terminated C string
334 * containing domain name
335 * of client allowed to access
336 * this export
337 * ex_path: '\0'-terminated C string
338 * containing pathname of
339 * directory in local file system
340 * ex_dev: fsid to use for this export
341 * ex_ino: ignored
342 * ex_flags: export flags for this export
343 * ex_anon_uid: UID to use for anonymous
344 * requests
345 * ex_anon_gid: GID to use for anonymous
346 * requests
347 * size: size in bytes of passed in nfsctl_export
348 * Output:
349 * On success: returns zero
350 * On error: return code is negative errno value
351 */
352static ssize_t write_export(struct file *file, char *buf, size_t size)
353{
354 struct nfsctl_export *data;
355 if (size < sizeof(*data))
356 return -EINVAL;
357 data = (struct nfsctl_export*)buf;
358 return exp_export(data);
359}
360
361/**
362 * write_unexport - Unexport a previously exported file system
363 *
364 * Deprecated. /proc/net/rpc/{nfsd.export,nfsd.fh} are preferred.
365 * Function remains to support old versions of nfs-utils.
366 *
367 * Input:
368 * buf: struct nfsctl_export
369 * ex_client: '\0'-terminated C string
370 * containing domain name
371 * of client no longer allowed
372 * to access this export
373 * ex_path: '\0'-terminated C string
374 * containing pathname of
375 * directory in local file system
376 * ex_dev: ignored
377 * ex_ino: ignored
378 * ex_flags: ignored
379 * ex_anon_uid: ignored
380 * ex_anon_gid: ignored
381 * size: size in bytes of passed in nfsctl_export
382 * Output:
383 * On success: returns zero
384 * On error: return code is negative errno value
385 */
386static ssize_t write_unexport(struct file *file, char *buf, size_t size)
387{
388 struct nfsctl_export *data;
389
390 if (size < sizeof(*data))
391 return -EINVAL;
392 data = (struct nfsctl_export*)buf;
393 return exp_unexport(data);
394}
395
396/**
397 * write_getfs - Get a variable-length NFS file handle by path
398 *
399 * Deprecated. /proc/fs/nfsd/filehandle is preferred.
400 * Function remains to support old versions of nfs-utils.
401 *
402 * Input:
403 * buf: struct nfsctl_fsparm
404 * gd_addr: socket address of client
405 * gd_path: '\0'-terminated C string
406 * containing pathname of
407 * directory in local file system
408 * gd_maxlen: maximum size of returned file
409 * handle
410 * size: size in bytes of passed in nfsctl_fsparm
411 * Output:
412 * On success: passed-in buffer filled with a knfsd_fh structure
413 * (a variable-length raw NFS file handle);
414 * return code is the size in bytes of the file handle
415 * On error: return code is negative errno value
416 *
417 * Note: Only AF_INET client addresses are passed in, since gd_addr
418 * is the same size as a struct sockaddr_in.
419 */
420static ssize_t write_getfs(struct file *file, char *buf, size_t size)
421{
422 struct nfsctl_fsparm *data;
423 struct sockaddr_in *sin;
424 struct auth_domain *clp;
425 int err = 0;
426 struct knfsd_fh *res;
427 struct in6_addr in6;
428
429 if (size < sizeof(*data))
430 return -EINVAL;
431 data = (struct nfsctl_fsparm*)buf;
432 err = -EPROTONOSUPPORT;
433 if (data->gd_addr.sa_family != AF_INET)
434 goto out;
435 sin = (struct sockaddr_in *)&data->gd_addr;
436 if (data->gd_maxlen > NFS3_FHSIZE)
437 data->gd_maxlen = NFS3_FHSIZE;
438
439 res = (struct knfsd_fh*)buf;
440
441 exp_readlock();
442
443 ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
444
445 clp = auth_unix_lookup(&init_net, &in6);
446 if (!clp)
447 err = -EPERM;
448 else {
449 err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
450 auth_domain_put(clp);
451 }
452 exp_readunlock();
453 if (err == 0)
454 err = res->fh_size + offsetof(struct knfsd_fh, fh_base);
455 out:
456 return err;
457}
458
459/**
460 * write_getfd - Get a fixed-length NFS file handle by path (used by mountd)
461 *
462 * Deprecated. /proc/fs/nfsd/filehandle is preferred.
463 * Function remains to support old versions of nfs-utils.
464 *
465 * Input:
466 * buf: struct nfsctl_fdparm
467 * gd_addr: socket address of client
468 * gd_path: '\0'-terminated C string
469 * containing pathname of
470 * directory in local file system
471 * gd_version: fdparm structure version
472 * size: size in bytes of passed in nfsctl_fdparm
473 * Output:
474 * On success: passed-in buffer filled with nfsctl_res
475 * (a fixed-length raw NFS file handle);
476 * return code is the size in bytes of the file handle
477 * On error: return code is negative errno value
478 *
479 * Note: Only AF_INET client addresses are passed in, since gd_addr
480 * is the same size as a struct sockaddr_in.
481 */
482static ssize_t write_getfd(struct file *file, char *buf, size_t size)
483{
484 struct nfsctl_fdparm *data;
485 struct sockaddr_in *sin;
486 struct auth_domain *clp;
487 int err = 0;
488 struct knfsd_fh fh;
489 char *res;
490 struct in6_addr in6;
491
492 if (size < sizeof(*data))
493 return -EINVAL;
494 data = (struct nfsctl_fdparm*)buf;
495 err = -EPROTONOSUPPORT;
496 if (data->gd_addr.sa_family != AF_INET)
497 goto out;
498 err = -EINVAL;
499 if (data->gd_version < 2 || data->gd_version > NFSSVC_MAXVERS)
500 goto out;
501
502 res = buf;
503 sin = (struct sockaddr_in *)&data->gd_addr;
504 exp_readlock();
505
506 ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
507
508 clp = auth_unix_lookup(&init_net, &in6);
509 if (!clp)
510 err = -EPERM;
511 else {
512 err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
513 auth_domain_put(clp);
514 }
515 exp_readunlock();
516
517 if (err == 0) {
518 memset(res,0, NFS_FHSIZE);
519 memcpy(res, &fh.fh_base, fh.fh_size);
520 err = NFS_FHSIZE;
521 }
522 out:
523 return err;
524}
525#endif /* CONFIG_NFSD_DEPRECATED */
526 192
527/** 193/**
528 * write_unlock_ip - Release all locks used by a client 194 * write_unlock_ip - Release all locks used by a client
@@ -1397,15 +1063,6 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
1397static int nfsd_fill_super(struct super_block * sb, void * data, int silent) 1063static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
1398{ 1064{
1399 static struct tree_descr nfsd_files[] = { 1065 static struct tree_descr nfsd_files[] = {
1400#ifdef CONFIG_NFSD_DEPRECATED
1401 [NFSD_Svc] = {".svc", &transaction_ops, S_IWUSR},
1402 [NFSD_Add] = {".add", &transaction_ops, S_IWUSR},
1403 [NFSD_Del] = {".del", &transaction_ops, S_IWUSR},
1404 [NFSD_Export] = {".export", &transaction_ops, S_IWUSR},
1405 [NFSD_Unexport] = {".unexport", &transaction_ops, S_IWUSR},
1406 [NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
1407 [NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
1408#endif
1409 [NFSD_List] = {"exports", &exports_operations, S_IRUGO}, 1066 [NFSD_List] = {"exports", &exports_operations, S_IRUGO},
1410 [NFSD_Export_features] = {"export_features", 1067 [NFSD_Export_features] = {"export_features",
1411 &export_features_operations, S_IRUGO}, 1068 &export_features_operations, S_IRUGO},
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 18743c4d8bc..dc5a1bf476b 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -528,16 +528,9 @@ nfsd(void *vrqstp)
528 continue; 528 continue;
529 } 529 }
530 530
531
532 /* Lock the export hash tables for reading. */
533 exp_readlock();
534
535 validate_process_creds(); 531 validate_process_creds();
536 svc_process(rqstp); 532 svc_process(rqstp);
537 validate_process_creds(); 533 validate_process_creds();
538
539 /* Unlock export hash tables */
540 exp_readunlock();
541 } 534 }
542 535
543 /* Clear signals before calling svc_exit_thread() */ 536 /* Clear signals before calling svc_exit_thread() */
@@ -577,8 +570,22 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
577 rqstp->rq_vers, rqstp->rq_proc); 570 rqstp->rq_vers, rqstp->rq_proc);
578 proc = rqstp->rq_procinfo; 571 proc = rqstp->rq_procinfo;
579 572
573 /*
574 * Give the xdr decoder a chance to change this if it wants
575 * (necessary in the NFSv4.0 compound case)
576 */
577 rqstp->rq_cachetype = proc->pc_cachetype;
578 /* Decode arguments */
579 xdr = proc->pc_decode;
580 if (xdr && !xdr(rqstp, (__be32*)rqstp->rq_arg.head[0].iov_base,
581 rqstp->rq_argp)) {
582 dprintk("nfsd: failed to decode arguments!\n");
583 *statp = rpc_garbage_args;
584 return 1;
585 }
586
580 /* Check whether we have this call in the cache. */ 587 /* Check whether we have this call in the cache. */
581 switch (nfsd_cache_lookup(rqstp, proc->pc_cachetype)) { 588 switch (nfsd_cache_lookup(rqstp)) {
582 case RC_INTR: 589 case RC_INTR:
583 case RC_DROPIT: 590 case RC_DROPIT:
584 return 0; 591 return 0;
@@ -588,16 +595,6 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
588 /* do it */ 595 /* do it */
589 } 596 }
590 597
591 /* Decode arguments */
592 xdr = proc->pc_decode;
593 if (xdr && !xdr(rqstp, (__be32*)rqstp->rq_arg.head[0].iov_base,
594 rqstp->rq_argp)) {
595 dprintk("nfsd: failed to decode arguments!\n");
596 nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
597 *statp = rpc_garbage_args;
598 return 1;
599 }
600
601 /* need to grab the location to store the status, as 598 /* need to grab the location to store the status, as
602 * nfsv4 does some encoding while processing 599 * nfsv4 does some encoding while processing
603 */ 600 */
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 6bd2f3c21f2..4eefaf1b42e 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -482,6 +482,7 @@ extern void nfsd4_recdir_purge_old(void);
482extern int nfsd4_create_clid_dir(struct nfs4_client *clp); 482extern int nfsd4_create_clid_dir(struct nfs4_client *clp);
483extern void nfsd4_remove_clid_dir(struct nfs4_client *clp); 483extern void nfsd4_remove_clid_dir(struct nfs4_client *clp);
484extern void release_session_client(struct nfsd4_session *); 484extern void release_session_client(struct nfsd4_session *);
485extern __be32 nfs4_validate_stateid(stateid_t *, int);
485 486
486static inline void 487static inline void
487nfs4_put_stateowner(struct nfs4_stateowner *so) 488nfs4_put_stateowner(struct nfs4_stateowner *so)
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 366401e1a53..d2a8d04428c 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -342,6 +342,25 @@ struct nfsd4_setclientid_confirm {
342 nfs4_verifier sc_confirm; 342 nfs4_verifier sc_confirm;
343}; 343};
344 344
345struct nfsd4_saved_compoundargs {
346 __be32 *p;
347 __be32 *end;
348 int pagelen;
349 struct page **pagelist;
350};
351
352struct nfsd4_test_stateid {
353 __be32 ts_num_ids;
354 __be32 ts_has_session;
355 struct nfsd4_compoundargs *ts_saved_args;
356 struct nfsd4_saved_compoundargs ts_savedp;
357};
358
359struct nfsd4_free_stateid {
360 stateid_t fr_stateid; /* request */
361 __be32 fr_status; /* response */
362};
363
345/* also used for NVERIFY */ 364/* also used for NVERIFY */
346struct nfsd4_verify { 365struct nfsd4_verify {
347 u32 ve_bmval[3]; /* request */ 366 u32 ve_bmval[3]; /* request */
@@ -432,10 +451,14 @@ struct nfsd4_op {
432 struct nfsd4_destroy_session destroy_session; 451 struct nfsd4_destroy_session destroy_session;
433 struct nfsd4_sequence sequence; 452 struct nfsd4_sequence sequence;
434 struct nfsd4_reclaim_complete reclaim_complete; 453 struct nfsd4_reclaim_complete reclaim_complete;
454 struct nfsd4_test_stateid test_stateid;
455 struct nfsd4_free_stateid free_stateid;
435 } u; 456 } u;
436 struct nfs4_replay * replay; 457 struct nfs4_replay * replay;
437}; 458};
438 459
460bool nfsd4_cache_this_op(struct nfsd4_op *);
461
439struct nfsd4_compoundargs { 462struct nfsd4_compoundargs {
440 /* scratch variables for XDR decode */ 463 /* scratch variables for XDR decode */
441 __be32 * p; 464 __be32 * p;
@@ -458,6 +481,7 @@ struct nfsd4_compoundargs {
458 u32 opcnt; 481 u32 opcnt;
459 struct nfsd4_op *ops; 482 struct nfsd4_op *ops;
460 struct nfsd4_op iops[8]; 483 struct nfsd4_op iops[8];
484 int cachetype;
461}; 485};
462 486
463struct nfsd4_compoundres { 487struct nfsd4_compoundres {
@@ -559,11 +583,15 @@ extern __be32
559nfsd4_release_lockowner(struct svc_rqst *rqstp, 583nfsd4_release_lockowner(struct svc_rqst *rqstp,
560 struct nfsd4_compound_state *, 584 struct nfsd4_compound_state *,
561 struct nfsd4_release_lockowner *rlockowner); 585 struct nfsd4_release_lockowner *rlockowner);
562extern void nfsd4_release_compoundargs(struct nfsd4_compoundargs *); 586extern int nfsd4_release_compoundargs(void *rq, __be32 *p, void *resp);
563extern __be32 nfsd4_delegreturn(struct svc_rqst *rqstp, 587extern __be32 nfsd4_delegreturn(struct svc_rqst *rqstp,
564 struct nfsd4_compound_state *, struct nfsd4_delegreturn *dr); 588 struct nfsd4_compound_state *, struct nfsd4_delegreturn *dr);
565extern __be32 nfsd4_renew(struct svc_rqst *rqstp, 589extern __be32 nfsd4_renew(struct svc_rqst *rqstp,
566 struct nfsd4_compound_state *, clientid_t *clid); 590 struct nfsd4_compound_state *, clientid_t *clid);
591extern __be32 nfsd4_test_stateid(struct svc_rqst *rqstp,
592 struct nfsd4_compound_state *, struct nfsd4_test_stateid *test_stateid);
593extern __be32 nfsd4_free_stateid(struct svc_rqst *rqstp,
594 struct nfsd4_compound_state *, struct nfsd4_free_stateid *free_stateid);
567#endif 595#endif
568 596
569/* 597/*
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 846bb179257..8779405e15a 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -438,16 +438,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
438 struct compat_timespec __user *tsp, 438 struct compat_timespec __user *tsp,
439 const compat_sigset_t __user *sigmask, 439 const compat_sigset_t __user *sigmask,
440 compat_size_t sigsetsize); 440 compat_size_t sigsetsize);
441#if (defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)) && \
442 !defined(CONFIG_NFSD_DEPRECATED)
443union compat_nfsctl_res;
444struct compat_nfsctl_arg;
445asmlinkage long compat_sys_nfsservctl(int cmd,
446 struct compat_nfsctl_arg __user *arg,
447 union compat_nfsctl_res __user *res);
448#else
449asmlinkage long compat_sys_nfsservctl(int cmd, void *notused, void *notused2); 441asmlinkage long compat_sys_nfsservctl(int cmd, void *notused, void *notused2);
450#endif
451asmlinkage long compat_sys_signalfd4(int ufd, 442asmlinkage long compat_sys_signalfd4(int ufd,
452 const compat_sigset_t __user *sigmask, 443 const compat_sigset_t __user *sigmask,
453 compat_size_t sigsetsize, int flags); 444 compat_size_t sigsetsize, int flags);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index a6658043258..5f523eb9bb8 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1072,12 +1072,12 @@ struct file_lock_operations {
1072}; 1072};
1073 1073
1074struct lock_manager_operations { 1074struct lock_manager_operations {
1075 int (*fl_compare_owner)(struct file_lock *, struct file_lock *); 1075 int (*lm_compare_owner)(struct file_lock *, struct file_lock *);
1076 void (*fl_notify)(struct file_lock *); /* unblock callback */ 1076 void (*lm_notify)(struct file_lock *); /* unblock callback */
1077 int (*fl_grant)(struct file_lock *, struct file_lock *, int); 1077 int (*lm_grant)(struct file_lock *, struct file_lock *, int);
1078 void (*fl_release_private)(struct file_lock *); 1078 void (*lm_release_private)(struct file_lock *);
1079 void (*fl_break)(struct file_lock *); 1079 void (*lm_break)(struct file_lock *);
1080 int (*fl_change)(struct file_lock **, int); 1080 int (*lm_change)(struct file_lock **, int);
1081}; 1081};
1082 1082
1083struct lock_manager { 1083struct lock_manager {
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index 84058ec6939..8a31a20efe7 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -133,8 +133,6 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp);
133int nfsd_export_init(void); 133int nfsd_export_init(void);
134void nfsd_export_shutdown(void); 134void nfsd_export_shutdown(void);
135void nfsd_export_flush(void); 135void nfsd_export_flush(void);
136void exp_readlock(void);
137void exp_readunlock(void);
138struct svc_export * rqst_exp_get_by_name(struct svc_rqst *, 136struct svc_export * rqst_exp_get_by_name(struct svc_rqst *,
139 struct path *); 137 struct path *);
140struct svc_export * rqst_exp_parent(struct svc_rqst *, 138struct svc_export * rqst_exp_parent(struct svc_rqst *,
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
index 8d2eef1a858..d1c79a90639 100644
--- a/include/linux/sunrpc/cache.h
+++ b/include/linux/sunrpc/cache.h
@@ -256,13 +256,4 @@ static inline time_t get_expiry(char **bpp)
256 return rv - boot.tv_sec; 256 return rv - boot.tv_sec;
257} 257}
258 258
259#ifdef CONFIG_NFSD_DEPRECATED
260static inline void sunrpc_invalidate(struct cache_head *h,
261 struct cache_detail *detail)
262{
263 h->expiry_time = seconds_since_boot() - 1;
264 detail->nextcheck = seconds_since_boot();
265}
266#endif /* CONFIG_NFSD_DEPRECATED */
267
268#endif /* _LINUX_SUNRPC_CACHE_H_ */ 259#endif /* _LINUX_SUNRPC_CACHE_H_ */
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index ea29330b78b..2f1e5186e04 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -273,6 +273,7 @@ struct svc_rqst {
273 /* Catering to nfsd */ 273 /* Catering to nfsd */
274 struct auth_domain * rq_client; /* RPC peer info */ 274 struct auth_domain * rq_client; /* RPC peer info */
275 struct auth_domain * rq_gssclient; /* "gss/"-style peer info */ 275 struct auth_domain * rq_gssclient; /* "gss/"-style peer info */
276 int rq_cachetype;
276 struct svc_cacherep * rq_cacherep; /* cache info */ 277 struct svc_cacherep * rq_cacherep; /* cache info */
277 int rq_splice_ok; /* turned off in gss privacy 278 int rq_splice_ok; /* turned off in gss privacy
278 * to prevent encrypting page 279 * to prevent encrypting page
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index c3b75333b82..8c67890de42 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -744,6 +744,13 @@ static struct pf_desc gss_kerberos_pfs[] = {
744 }, 744 },
745}; 745};
746 746
747MODULE_ALIAS("rpc-auth-gss-krb5");
748MODULE_ALIAS("rpc-auth-gss-krb5i");
749MODULE_ALIAS("rpc-auth-gss-krb5p");
750MODULE_ALIAS("rpc-auth-gss-390003");
751MODULE_ALIAS("rpc-auth-gss-390004");
752MODULE_ALIAS("rpc-auth-gss-390005");
753
747static struct gss_api_mech gss_kerberos_mech = { 754static struct gss_api_mech gss_kerberos_mech = {
748 .gm_name = "krb5", 755 .gm_name = "krb5",
749 .gm_owner = THIS_MODULE, 756 .gm_owner = THIS_MODULE,
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index e3c36a27441..ca8cad8251c 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -141,7 +141,7 @@ gss_mech_get(struct gss_api_mech *gm)
141EXPORT_SYMBOL_GPL(gss_mech_get); 141EXPORT_SYMBOL_GPL(gss_mech_get);
142 142
143struct gss_api_mech * 143struct gss_api_mech *
144gss_mech_get_by_name(const char *name) 144_gss_mech_get_by_name(const char *name)
145{ 145{
146 struct gss_api_mech *pos, *gm = NULL; 146 struct gss_api_mech *pos, *gm = NULL;
147 147
@@ -158,6 +158,17 @@ gss_mech_get_by_name(const char *name)
158 158
159} 159}
160 160
161struct gss_api_mech * gss_mech_get_by_name(const char *name)
162{
163 struct gss_api_mech *gm = NULL;
164
165 gm = _gss_mech_get_by_name(name);
166 if (!gm) {
167 request_module("rpc-auth-gss-%s", name);
168 gm = _gss_mech_get_by_name(name);
169 }
170 return gm;
171}
161EXPORT_SYMBOL_GPL(gss_mech_get_by_name); 172EXPORT_SYMBOL_GPL(gss_mech_get_by_name);
162 173
163struct gss_api_mech * 174struct gss_api_mech *
@@ -194,10 +205,9 @@ mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor)
194 return 0; 205 return 0;
195} 206}
196 207
197struct gss_api_mech * 208struct gss_api_mech *_gss_mech_get_by_pseudoflavor(u32 pseudoflavor)
198gss_mech_get_by_pseudoflavor(u32 pseudoflavor)
199{ 209{
200 struct gss_api_mech *pos, *gm = NULL; 210 struct gss_api_mech *gm = NULL, *pos;
201 211
202 spin_lock(&registered_mechs_lock); 212 spin_lock(&registered_mechs_lock);
203 list_for_each_entry(pos, &registered_mechs, gm_list) { 213 list_for_each_entry(pos, &registered_mechs, gm_list) {
@@ -213,6 +223,20 @@ gss_mech_get_by_pseudoflavor(u32 pseudoflavor)
213 return gm; 223 return gm;
214} 224}
215 225
226struct gss_api_mech *
227gss_mech_get_by_pseudoflavor(u32 pseudoflavor)
228{
229 struct gss_api_mech *gm;
230
231 gm = _gss_mech_get_by_pseudoflavor(pseudoflavor);
232
233 if (!gm) {
234 request_module("rpc-auth-gss-%u", pseudoflavor);
235 gm = _gss_mech_get_by_pseudoflavor(pseudoflavor);
236 }
237 return gm;
238}
239
216EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor); 240EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor);
217 241
218int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr) 242int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr)
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index ab86b7927f8..bd31208bbb6 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -902,12 +902,13 @@ void svc_delete_xprt(struct svc_xprt *xprt)
902 if (!test_and_set_bit(XPT_DETACHED, &xprt->xpt_flags)) 902 if (!test_and_set_bit(XPT_DETACHED, &xprt->xpt_flags))
903 list_del_init(&xprt->xpt_list); 903 list_del_init(&xprt->xpt_list);
904 /* 904 /*
905 * We used to delete the transport from whichever list 905 * The only time we're called while xpt_ready is still on a list
906 * it's sk_xprt.xpt_ready node was on, but we don't actually 906 * is while the list itself is about to be destroyed (in
907 * need to. This is because the only time we're called 907 * svc_destroy). BUT svc_xprt_enqueue could still be attempting
908 * while still attached to a queue, the queue itself 908 * to add new entries to the sp_sockets list, so we can't leave
909 * is about to be destroyed (in svc_destroy). 909 * a freed xprt on it.
910 */ 910 */
911 list_del_init(&xprt->xpt_ready);
911 if (test_bit(XPT_TEMP, &xprt->xpt_flags)) 912 if (test_bit(XPT_TEMP, &xprt->xpt_flags))
912 serv->sv_tmpcnt--; 913 serv->sv_tmpcnt--;
913 spin_unlock_bh(&serv->sv_lock); 914 spin_unlock_bh(&serv->sv_lock);
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index c8e10216c11..ce136323da8 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -30,12 +30,10 @@
30 30
31struct unix_domain { 31struct unix_domain {
32 struct auth_domain h; 32 struct auth_domain h;
33#ifdef CONFIG_NFSD_DEPRECATED
34 int addr_changes;
35#endif /* CONFIG_NFSD_DEPRECATED */
36 /* other stuff later */ 33 /* other stuff later */
37}; 34};
38 35
36extern struct auth_ops svcauth_null;
39extern struct auth_ops svcauth_unix; 37extern struct auth_ops svcauth_unix;
40 38
41static void svcauth_unix_domain_release(struct auth_domain *dom) 39static void svcauth_unix_domain_release(struct auth_domain *dom)
@@ -74,9 +72,6 @@ struct auth_domain *unix_domain_find(char *name)
74 return NULL; 72 return NULL;
75 } 73 }
76 new->h.flavour = &svcauth_unix; 74 new->h.flavour = &svcauth_unix;
77#ifdef CONFIG_NFSD_DEPRECATED
78 new->addr_changes = 0;
79#endif /* CONFIG_NFSD_DEPRECATED */
80 rv = auth_domain_lookup(name, &new->h); 75 rv = auth_domain_lookup(name, &new->h);
81 } 76 }
82} 77}
@@ -95,9 +90,6 @@ struct ip_map {
95 char m_class[8]; /* e.g. "nfsd" */ 90 char m_class[8]; /* e.g. "nfsd" */
96 struct in6_addr m_addr; 91 struct in6_addr m_addr;
97 struct unix_domain *m_client; 92 struct unix_domain *m_client;
98#ifdef CONFIG_NFSD_DEPRECATED
99 int m_add_change;
100#endif /* CONFIG_NFSD_DEPRECATED */
101}; 93};
102 94
103static void ip_map_put(struct kref *kref) 95static void ip_map_put(struct kref *kref)
@@ -151,9 +143,6 @@ static void update(struct cache_head *cnew, struct cache_head *citem)
151 143
152 kref_get(&item->m_client->h.ref); 144 kref_get(&item->m_client->h.ref);
153 new->m_client = item->m_client; 145 new->m_client = item->m_client;
154#ifdef CONFIG_NFSD_DEPRECATED
155 new->m_add_change = item->m_add_change;
156#endif /* CONFIG_NFSD_DEPRECATED */
157} 146}
158static struct cache_head *ip_map_alloc(void) 147static struct cache_head *ip_map_alloc(void)
159{ 148{
@@ -338,16 +327,6 @@ static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm,
338 ip.h.flags = 0; 327 ip.h.flags = 0;
339 if (!udom) 328 if (!udom)
340 set_bit(CACHE_NEGATIVE, &ip.h.flags); 329 set_bit(CACHE_NEGATIVE, &ip.h.flags);
341#ifdef CONFIG_NFSD_DEPRECATED
342 else {
343 ip.m_add_change = udom->addr_changes;
344 /* if this is from the legacy set_client system call,
345 * we need m_add_change to be one higher
346 */
347 if (expiry == NEVER)
348 ip.m_add_change++;
349 }
350#endif /* CONFIG_NFSD_DEPRECATED */
351 ip.h.expiry_time = expiry; 330 ip.h.expiry_time = expiry;
352 ch = sunrpc_cache_update(cd, &ip.h, &ipm->h, 331 ch = sunrpc_cache_update(cd, &ip.h, &ipm->h,
353 hash_str(ipm->m_class, IP_HASHBITS) ^ 332 hash_str(ipm->m_class, IP_HASHBITS) ^
@@ -367,62 +346,6 @@ static inline int ip_map_update(struct net *net, struct ip_map *ipm,
367 return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry); 346 return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry);
368} 347}
369 348
370#ifdef CONFIG_NFSD_DEPRECATED
371int auth_unix_add_addr(struct net *net, struct in6_addr *addr, struct auth_domain *dom)
372{
373 struct unix_domain *udom;
374 struct ip_map *ipmp;
375
376 if (dom->flavour != &svcauth_unix)
377 return -EINVAL;
378 udom = container_of(dom, struct unix_domain, h);
379 ipmp = ip_map_lookup(net, "nfsd", addr);
380
381 if (ipmp)
382 return ip_map_update(net, ipmp, udom, NEVER);
383 else
384 return -ENOMEM;
385}
386EXPORT_SYMBOL_GPL(auth_unix_add_addr);
387
388int auth_unix_forget_old(struct auth_domain *dom)
389{
390 struct unix_domain *udom;
391
392 if (dom->flavour != &svcauth_unix)
393 return -EINVAL;
394 udom = container_of(dom, struct unix_domain, h);
395 udom->addr_changes++;
396 return 0;
397}
398EXPORT_SYMBOL_GPL(auth_unix_forget_old);
399
400struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr)
401{
402 struct ip_map *ipm;
403 struct auth_domain *rv;
404 struct sunrpc_net *sn;
405
406 sn = net_generic(net, sunrpc_net_id);
407 ipm = ip_map_lookup(net, "nfsd", addr);
408
409 if (!ipm)
410 return NULL;
411 if (cache_check(sn->ip_map_cache, &ipm->h, NULL))
412 return NULL;
413
414 if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) {
415 sunrpc_invalidate(&ipm->h, sn->ip_map_cache);
416 rv = NULL;
417 } else {
418 rv = &ipm->m_client->h;
419 kref_get(&rv->ref);
420 }
421 cache_put(&ipm->h, sn->ip_map_cache);
422 return rv;
423}
424EXPORT_SYMBOL_GPL(auth_unix_lookup);
425#endif /* CONFIG_NFSD_DEPRECATED */
426 349
427void svcauth_unix_purge(void) 350void svcauth_unix_purge(void)
428{ 351{
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index af04f779ce9..f2cb5b881de 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -51,6 +51,8 @@
51#include <linux/sunrpc/stats.h> 51#include <linux/sunrpc/stats.h>
52#include <linux/sunrpc/xprt.h> 52#include <linux/sunrpc/xprt.h>
53 53
54#include "sunrpc.h"
55
54#define RPCDBG_FACILITY RPCDBG_SVCXPRT 56#define RPCDBG_FACILITY RPCDBG_SVCXPRT
55 57
56 58