aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/nfsd
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/Kconfig13
-rw-r--r--fs/nfsd/acl.h59
-rw-r--r--fs/nfsd/export.c84
-rw-r--r--fs/nfsd/idmap.h62
-rw-r--r--fs/nfsd/lockd.c1
-rw-r--r--fs/nfsd/nfs3proc.c10
-rw-r--r--fs/nfsd/nfs3xdr.c10
-rw-r--r--fs/nfsd/nfs4acl.c2
-rw-r--r--fs/nfsd/nfs4callback.c1034
-rw-r--r--fs/nfsd/nfs4idmap.c121
-rw-r--r--fs/nfsd/nfs4proc.c143
-rw-r--r--fs/nfsd/nfs4recover.c1
-rw-r--r--fs/nfsd/nfs4state.c1117
-rw-r--r--fs/nfsd/nfs4xdr.c145
-rw-r--r--fs/nfsd/nfsctl.c67
-rw-r--r--fs/nfsd/nfsd.h3
-rw-r--r--fs/nfsd/nfsfh.c2
-rw-r--r--fs/nfsd/nfsproc.c6
-rw-r--r--fs/nfsd/nfssvc.c7
-rw-r--r--fs/nfsd/nfsxdr.c2
-rw-r--r--fs/nfsd/state.h83
-rw-r--r--fs/nfsd/stats.c2
-rw-r--r--fs/nfsd/vfs.c186
-rw-r--r--fs/nfsd/vfs.h6
-rw-r--r--fs/nfsd/xdr4.h30
25 files changed, 1979 insertions, 1217 deletions
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
index 4264377552e2..fbb2a5ef5817 100644
--- a/fs/nfsd/Kconfig
+++ b/fs/nfsd/Kconfig
@@ -28,6 +28,18 @@ 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
31config NFSD_V2_ACL 43config NFSD_V2_ACL
32 bool 44 bool
33 depends on NFSD 45 depends on NFSD
@@ -70,6 +82,7 @@ config NFSD_V4
70 select NFSD_V3 82 select NFSD_V3
71 select FS_POSIX_ACL 83 select FS_POSIX_ACL
72 select SUNRPC_GSS 84 select SUNRPC_GSS
85 select CRYPTO
73 help 86 help
74 This option enables support in your system's NFS server for 87 This option enables support in your system's NFS server for
75 version 4 of the NFS protocol (RFC 3530). 88 version 4 of the NFS protocol (RFC 3530).
diff --git a/fs/nfsd/acl.h b/fs/nfsd/acl.h
new file mode 100644
index 000000000000..34e5c40af5ef
--- /dev/null
+++ b/fs/nfsd/acl.h
@@ -0,0 +1,59 @@
1/*
2 * Common NFSv4 ACL handling definitions.
3 *
4 * Copyright (c) 2002 The Regents of the University of Michigan.
5 * All rights reserved.
6 *
7 * Marius Aamodt Eriksen <marius@umich.edu>
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#ifndef LINUX_NFS4_ACL_H
36#define LINUX_NFS4_ACL_H
37
38#include <linux/posix_acl.h>
39
40/* Maximum ACL we'll accept from client; chosen (somewhat arbitrarily) to
41 * fit in a page: */
42#define NFS4_ACL_MAX 170
43
44struct nfs4_acl *nfs4_acl_new(int);
45int nfs4_acl_get_whotype(char *, u32);
46int nfs4_acl_write_who(int who, char *p);
47int nfs4_acl_permission(struct nfs4_acl *acl, uid_t owner, gid_t group,
48 uid_t who, u32 mask);
49
50#define NFS4_ACL_TYPE_DEFAULT 0x01
51#define NFS4_ACL_DIR 0x02
52#define NFS4_ACL_OWNER 0x04
53
54struct nfs4_acl *nfs4_acl_posix_to_nfsv4(struct posix_acl *,
55 struct posix_acl *, unsigned int flags);
56int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *, struct posix_acl **,
57 struct posix_acl **, unsigned int flags);
58
59#endif /* LINUX_NFS4_ACL_H */
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index c2a4f71d87dd..b9566e46219f 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -1,4 +1,3 @@
1#define MSNFS /* HACK HACK */
2/* 1/*
3 * NFS exporting and validation. 2 * NFS exporting and validation.
4 * 3 *
@@ -28,9 +27,6 @@
28typedef struct auth_domain svc_client; 27typedef struct auth_domain svc_client;
29typedef struct svc_export svc_export; 28typedef struct svc_export svc_export;
30 29
31static void exp_do_unexport(svc_export *unexp);
32static int exp_verify_string(char *cp, int max);
33
34/* 30/*
35 * We have two caches. 31 * We have two caches.
36 * One maps client+vfsmnt+dentry to export options - the export map 32 * One maps client+vfsmnt+dentry to export options - the export map
@@ -303,7 +299,6 @@ svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old)
303 299
304#define EXPORT_HASHBITS 8 300#define EXPORT_HASHBITS 8
305#define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) 301#define EXPORT_HASHMAX (1<< EXPORT_HASHBITS)
306#define EXPORT_HASHMASK (EXPORT_HASHMAX -1)
307 302
308static struct cache_head *export_table[EXPORT_HASHMAX]; 303static struct cache_head *export_table[EXPORT_HASHMAX];
309 304
@@ -802,6 +797,7 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
802 return ek; 797 return ek;
803} 798}
804 799
800#ifdef CONFIG_NFSD_DEPRECATED
805static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv, 801static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
806 struct svc_export *exp) 802 struct svc_export *exp)
807{ 803{
@@ -852,6 +848,7 @@ exp_get_fsid_key(svc_client *clp, int fsid)
852 848
853 return exp_find_key(clp, FSID_NUM, fsidv, NULL); 849 return exp_find_key(clp, FSID_NUM, fsidv, NULL);
854} 850}
851#endif
855 852
856static svc_export *exp_get_by_name(svc_client *clp, const struct path *path, 853static svc_export *exp_get_by_name(svc_client *clp, const struct path *path,
857 struct cache_req *reqp) 854 struct cache_req *reqp)
@@ -893,6 +890,7 @@ static struct svc_export *exp_parent(svc_client *clp, struct path *path)
893 return exp; 890 return exp;
894} 891}
895 892
893#ifdef CONFIG_NFSD_DEPRECATED
896/* 894/*
897 * Hashtable locking. Write locks are placed only by user processes 895 * Hashtable locking. Write locks are placed only by user processes
898 * wanting to modify export information. 896 * wanting to modify export information.
@@ -925,6 +923,19 @@ exp_writeunlock(void)
925{ 923{
926 up_write(&hash_sem); 924 up_write(&hash_sem);
927} 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);
928 939
929static void exp_fsid_unhash(struct svc_export *exp) 940static void exp_fsid_unhash(struct svc_export *exp)
930{ 941{
@@ -935,10 +946,9 @@ static void exp_fsid_unhash(struct svc_export *exp)
935 946
936 ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid); 947 ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
937 if (!IS_ERR(ek)) { 948 if (!IS_ERR(ek)) {
938 ek->h.expiry_time = get_seconds()-1; 949 sunrpc_invalidate(&ek->h, &svc_expkey_cache);
939 cache_put(&ek->h, &svc_expkey_cache); 950 cache_put(&ek->h, &svc_expkey_cache);
940 } 951 }
941 svc_expkey_cache.nextcheck = get_seconds();
942} 952}
943 953
944static int exp_fsid_hash(svc_client *clp, struct svc_export *exp) 954static int exp_fsid_hash(svc_client *clp, struct svc_export *exp)
@@ -973,10 +983,9 @@ static void exp_unhash(struct svc_export *exp)
973 983
974 ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino); 984 ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
975 if (!IS_ERR(ek)) { 985 if (!IS_ERR(ek)) {
976 ek->h.expiry_time = get_seconds()-1; 986 sunrpc_invalidate(&ek->h, &svc_expkey_cache);
977 cache_put(&ek->h, &svc_expkey_cache); 987 cache_put(&ek->h, &svc_expkey_cache);
978 } 988 }
979 svc_expkey_cache.nextcheck = get_seconds();
980} 989}
981 990
982/* 991/*
@@ -1097,8 +1106,7 @@ out:
1097static void 1106static void
1098exp_do_unexport(svc_export *unexp) 1107exp_do_unexport(svc_export *unexp)
1099{ 1108{
1100 unexp->h.expiry_time = get_seconds()-1; 1109 sunrpc_invalidate(&unexp->h, &svc_export_cache);
1101 svc_export_cache.nextcheck = get_seconds();
1102 exp_unhash(unexp); 1110 exp_unhash(unexp);
1103 exp_fsid_unhash(unexp); 1111 exp_fsid_unhash(unexp);
1104} 1112}
@@ -1150,6 +1158,7 @@ out_unlock:
1150 exp_writeunlock(); 1158 exp_writeunlock();
1151 return err; 1159 return err;
1152} 1160}
1161#endif /* CONFIG_NFSD_DEPRECATED */
1153 1162
1154/* 1163/*
1155 * Obtain the root fh on behalf of a client. 1164 * Obtain the root fh on behalf of a client.
@@ -1345,12 +1354,6 @@ exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp)
1345 if (IS_ERR(exp)) 1354 if (IS_ERR(exp))
1346 return nfserrno(PTR_ERR(exp)); 1355 return nfserrno(PTR_ERR(exp));
1347 rv = fh_compose(fhp, exp, exp->ex_path.dentry, NULL); 1356 rv = fh_compose(fhp, exp, exp->ex_path.dentry, NULL);
1348 if (rv)
1349 goto out;
1350 rv = check_nfsd_access(exp, rqstp);
1351 if (rv)
1352 fh_put(fhp);
1353out:
1354 exp_put(exp); 1357 exp_put(exp);
1355 return rv; 1358 return rv;
1356} 1359}
@@ -1433,9 +1436,6 @@ static struct flags {
1433 { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}}, 1436 { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
1434 { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}}, 1437 { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
1435 { NFSEXP_V4ROOT, {"v4root", ""}}, 1438 { NFSEXP_V4ROOT, {"v4root", ""}},
1436#ifdef MSNFS
1437 { NFSEXP_MSNFS, {"msnfs", ""}},
1438#endif
1439 { 0, {"", ""}} 1439 { 0, {"", ""}}
1440}; 1440};
1441 1441
@@ -1459,25 +1459,43 @@ static void show_secinfo_flags(struct seq_file *m, int flags)
1459 show_expflags(m, flags, NFSEXP_SECINFO_FLAGS); 1459 show_expflags(m, flags, NFSEXP_SECINFO_FLAGS);
1460} 1460}
1461 1461
1462static bool secinfo_flags_equal(int f, int g)
1463{
1464 f &= NFSEXP_SECINFO_FLAGS;
1465 g &= NFSEXP_SECINFO_FLAGS;
1466 return f == g;
1467}
1468
1469static int show_secinfo_run(struct seq_file *m, struct exp_flavor_info **fp, struct exp_flavor_info *end)
1470{
1471 int flags;
1472
1473 flags = (*fp)->flags;
1474 seq_printf(m, ",sec=%d", (*fp)->pseudoflavor);
1475 (*fp)++;
1476 while (*fp != end && secinfo_flags_equal(flags, (*fp)->flags)) {
1477 seq_printf(m, ":%d", (*fp)->pseudoflavor);
1478 (*fp)++;
1479 }
1480 return flags;
1481}
1482
1462static void show_secinfo(struct seq_file *m, struct svc_export *exp) 1483static void show_secinfo(struct seq_file *m, struct svc_export *exp)
1463{ 1484{
1464 struct exp_flavor_info *f; 1485 struct exp_flavor_info *f;
1465 struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors; 1486 struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
1466 int lastflags = 0, first = 0; 1487 int flags;
1467 1488
1468 if (exp->ex_nflavors == 0) 1489 if (exp->ex_nflavors == 0)
1469 return; 1490 return;
1470 for (f = exp->ex_flavors; f < end; f++) { 1491 f = exp->ex_flavors;
1471 if (first || f->flags != lastflags) { 1492 flags = show_secinfo_run(m, &f, end);
1472 if (!first) 1493 if (!secinfo_flags_equal(flags, exp->ex_flags))
1473 show_secinfo_flags(m, lastflags); 1494 show_secinfo_flags(m, flags);
1474 seq_printf(m, ",sec=%d", f->pseudoflavor); 1495 while (f != end) {
1475 lastflags = f->flags; 1496 flags = show_secinfo_run(m, &f, end);
1476 } else { 1497 show_secinfo_flags(m, flags);
1477 seq_printf(m, ":%d", f->pseudoflavor);
1478 }
1479 } 1498 }
1480 show_secinfo_flags(m, lastflags);
1481} 1499}
1482 1500
1483static void exp_flags(struct seq_file *m, int flag, int fsid, 1501static void exp_flags(struct seq_file *m, int flag, int fsid,
@@ -1532,6 +1550,7 @@ const struct seq_operations nfs_exports_op = {
1532 .show = e_show, 1550 .show = e_show,
1533}; 1551};
1534 1552
1553#ifdef CONFIG_NFSD_DEPRECATED
1535/* 1554/*
1536 * Add or modify a client. 1555 * Add or modify a client.
1537 * Change requests may involve the list of host addresses. The list of 1556 * Change requests may involve the list of host addresses. The list of
@@ -1563,7 +1582,7 @@ exp_addclient(struct nfsctl_client *ncp)
1563 /* Insert client into hashtable. */ 1582 /* Insert client into hashtable. */
1564 for (i = 0; i < ncp->cl_naddr; i++) { 1583 for (i = 0; i < ncp->cl_naddr; i++) {
1565 ipv6_addr_set_v4mapped(ncp->cl_addrlist[i].s_addr, &addr6); 1584 ipv6_addr_set_v4mapped(ncp->cl_addrlist[i].s_addr, &addr6);
1566 auth_unix_add_addr(&addr6, dom); 1585 auth_unix_add_addr(&init_net, &addr6, dom);
1567 } 1586 }
1568 auth_unix_forget_old(dom); 1587 auth_unix_forget_old(dom);
1569 auth_domain_put(dom); 1588 auth_domain_put(dom);
@@ -1621,6 +1640,7 @@ exp_verify_string(char *cp, int max)
1621 printk(KERN_NOTICE "nfsd: couldn't validate string %s\n", cp); 1640 printk(KERN_NOTICE "nfsd: couldn't validate string %s\n", cp);
1622 return 0; 1641 return 0;
1623} 1642}
1643#endif /* CONFIG_NFSD_DEPRECATED */
1624 1644
1625/* 1645/*
1626 * Initialize the exports module. 1646 * Initialize the exports module.
diff --git a/fs/nfsd/idmap.h b/fs/nfsd/idmap.h
new file mode 100644
index 000000000000..2f3be1321534
--- /dev/null
+++ b/fs/nfsd/idmap.h
@@ -0,0 +1,62 @@
1/*
2 * Mapping of UID to name and vice versa.
3 *
4 * Copyright (c) 2002, 2003 The Regents of the University of
5 * Michigan. All rights reserved.
6> *
7 * Marius Aamodt Eriksen <marius@umich.edu>
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#ifndef LINUX_NFSD_IDMAP_H
36#define LINUX_NFSD_IDMAP_H
37
38#include <linux/in.h>
39#include <linux/sunrpc/svc.h>
40
41/* XXX from linux/nfs_idmap.h */
42#define IDMAP_NAMESZ 128
43
44#ifdef CONFIG_NFSD_V4
45int nfsd_idmap_init(void);
46void nfsd_idmap_shutdown(void);
47#else
48static inline int nfsd_idmap_init(void)
49{
50 return 0;
51}
52static inline void nfsd_idmap_shutdown(void)
53{
54}
55#endif
56
57__be32 nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, __u32 *);
58__be32 nfsd_map_name_to_gid(struct svc_rqst *, const char *, size_t, __u32 *);
59int nfsd_map_uid_to_name(struct svc_rqst *, __u32, char *);
60int nfsd_map_gid_to_name(struct svc_rqst *, __u32, char *);
61
62#endif /* LINUX_NFSD_IDMAP_H */
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index 0c6d81670137..7c831a2731fa 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -38,7 +38,6 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
38 exp_readlock(); 38 exp_readlock();
39 nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp); 39 nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp);
40 fh_put(&fh); 40 fh_put(&fh);
41 rqstp->rq_client = NULL;
42 exp_readunlock(); 41 exp_readunlock();
43 /* We return nlm error codes as nlm doesn't know 42 /* We return nlm error codes as nlm doesn't know
44 * about nfsd, but nfsd does know about nlm.. 43 * about nfsd, but nfsd does know about nlm..
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 5b7e3021e06b..9095f3c21df9 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -151,10 +151,10 @@ nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp,
151 __be32 nfserr; 151 __be32 nfserr;
152 u32 max_blocksize = svc_max_payload(rqstp); 152 u32 max_blocksize = svc_max_payload(rqstp);
153 153
154 dprintk("nfsd: READ(3) %s %lu bytes at %lu\n", 154 dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n",
155 SVCFH_fmt(&argp->fh), 155 SVCFH_fmt(&argp->fh),
156 (unsigned long) argp->count, 156 (unsigned long) argp->count,
157 (unsigned long) argp->offset); 157 (unsigned long long) argp->offset);
158 158
159 /* Obtain buffer pointer for payload. 159 /* Obtain buffer pointer for payload.
160 * 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof) 160 * 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof)
@@ -191,10 +191,10 @@ nfsd3_proc_write(struct svc_rqst *rqstp, struct nfsd3_writeargs *argp,
191 __be32 nfserr; 191 __be32 nfserr;
192 unsigned long cnt = argp->len; 192 unsigned long cnt = argp->len;
193 193
194 dprintk("nfsd: WRITE(3) %s %d bytes at %ld%s\n", 194 dprintk("nfsd: WRITE(3) %s %d bytes at %Lu%s\n",
195 SVCFH_fmt(&argp->fh), 195 SVCFH_fmt(&argp->fh),
196 argp->len, 196 argp->len,
197 (unsigned long) argp->offset, 197 (unsigned long long) argp->offset,
198 argp->stable? " stable" : ""); 198 argp->stable? " stable" : "");
199 199
200 fh_copy(&resp->fh, &argp->fh); 200 fh_copy(&resp->fh, &argp->fh);
@@ -245,7 +245,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
245 } 245 }
246 246
247 /* Now create the file and set attributes */ 247 /* Now create the file and set attributes */
248 nfserr = nfsd_create_v3(rqstp, dirfhp, argp->name, argp->len, 248 nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len,
249 attr, newfhp, 249 attr, newfhp,
250 argp->createmode, argp->verf, NULL, NULL); 250 argp->createmode, argp->verf, NULL, NULL);
251 251
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 2a533a0af2a9..08c6e36ab2eb 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -260,9 +260,11 @@ void fill_post_wcc(struct svc_fh *fhp)
260 err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry, 260 err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry,
261 &fhp->fh_post_attr); 261 &fhp->fh_post_attr);
262 fhp->fh_post_change = fhp->fh_dentry->d_inode->i_version; 262 fhp->fh_post_change = fhp->fh_dentry->d_inode->i_version;
263 if (err) 263 if (err) {
264 fhp->fh_post_saved = 0; 264 fhp->fh_post_saved = 0;
265 else 265 /* Grab the ctime anyway - set_change_info might use it */
266 fhp->fh_post_attr.ctime = fhp->fh_dentry->d_inode->i_ctime;
267 } else
266 fhp->fh_post_saved = 1; 268 fhp->fh_post_saved = 1;
267} 269}
268 270
@@ -700,7 +702,7 @@ nfs3svc_encode_readres(struct svc_rqst *rqstp, __be32 *p,
700 *p++ = htonl(resp->eof); 702 *p++ = htonl(resp->eof);
701 *p++ = htonl(resp->count); /* xdr opaque count */ 703 *p++ = htonl(resp->count); /* xdr opaque count */
702 xdr_ressize_check(rqstp, p); 704 xdr_ressize_check(rqstp, p);
703 /* now update rqstp->rq_res to reflect data aswell */ 705 /* now update rqstp->rq_res to reflect data as well */
704 rqstp->rq_res.page_len = resp->count; 706 rqstp->rq_res.page_len = resp->count;
705 if (resp->count & 3) { 707 if (resp->count & 3) {
706 /* need to pad the tail */ 708 /* need to pad the tail */
@@ -840,7 +842,7 @@ out:
840 return rv; 842 return rv;
841} 843}
842 844
843__be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen) 845static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen)
844{ 846{
845 struct svc_fh fh; 847 struct svc_fh fh;
846 int err; 848 int err;
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index e48052615159..ad88f1c0a4c3 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -36,7 +36,7 @@
36 36
37#include <linux/slab.h> 37#include <linux/slab.h>
38#include <linux/nfs_fs.h> 38#include <linux/nfs_fs.h>
39#include <linux/nfs4_acl.h> 39#include "acl.h"
40 40
41 41
42/* mode bit translations: */ 42/* mode bit translations: */
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 988cbb3a19b6..02eb4edf0ece 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -41,7 +41,6 @@
41 41
42#define NFSPROC4_CB_NULL 0 42#define NFSPROC4_CB_NULL 0
43#define NFSPROC4_CB_COMPOUND 1 43#define NFSPROC4_CB_COMPOUND 1
44#define NFS4_STATEID_SIZE 16
45 44
46/* Index of predefined Linux callback client operations */ 45/* Index of predefined Linux callback client operations */
47 46
@@ -51,11 +50,6 @@ enum {
51 NFSPROC4_CLNT_CB_SEQUENCE, 50 NFSPROC4_CLNT_CB_SEQUENCE,
52}; 51};
53 52
54enum nfs_cb_opnum4 {
55 OP_CB_RECALL = 4,
56 OP_CB_SEQUENCE = 11,
57};
58
59#define NFS4_MAXTAGLEN 20 53#define NFS4_MAXTAGLEN 20
60 54
61#define NFS4_enc_cb_null_sz 0 55#define NFS4_enc_cb_null_sz 0
@@ -80,61 +74,6 @@ enum nfs_cb_opnum4 {
80 cb_sequence_dec_sz + \ 74 cb_sequence_dec_sz + \
81 op_dec_sz) 75 op_dec_sz)
82 76
83/*
84* Generic encode routines from fs/nfs/nfs4xdr.c
85*/
86static inline __be32 *
87xdr_writemem(__be32 *p, const void *ptr, int nbytes)
88{
89 int tmp = XDR_QUADLEN(nbytes);
90 if (!tmp)
91 return p;
92 p[tmp-1] = 0;
93 memcpy(p, ptr, nbytes);
94 return p + tmp;
95}
96
97#define WRITE32(n) *p++ = htonl(n)
98#define WRITEMEM(ptr,nbytes) do { \
99 p = xdr_writemem(p, ptr, nbytes); \
100} while (0)
101#define RESERVE_SPACE(nbytes) do { \
102 p = xdr_reserve_space(xdr, nbytes); \
103 if (!p) dprintk("NFSD: RESERVE_SPACE(%d) failed in function %s\n", (int) (nbytes), __func__); \
104 BUG_ON(!p); \
105} while (0)
106
107/*
108 * Generic decode routines from fs/nfs/nfs4xdr.c
109 */
110#define DECODE_TAIL \
111 status = 0; \
112out: \
113 return status; \
114xdr_error: \
115 dprintk("NFSD: xdr error! (%s:%d)\n", __FILE__, __LINE__); \
116 status = -EIO; \
117 goto out
118
119#define READ32(x) (x) = ntohl(*p++)
120#define READ64(x) do { \
121 (x) = (u64)ntohl(*p++) << 32; \
122 (x) |= ntohl(*p++); \
123} while (0)
124#define READTIME(x) do { \
125 p++; \
126 (x.tv_sec) = ntohl(*p++); \
127 (x.tv_nsec) = ntohl(*p++); \
128} while (0)
129#define READ_BUF(nbytes) do { \
130 p = xdr_inline_decode(xdr, nbytes); \
131 if (!p) { \
132 dprintk("NFSD: %s: reply buffer overflowed in line %d.\n", \
133 __func__, __LINE__); \
134 return -EIO; \
135 } \
136} while (0)
137
138struct nfs4_cb_compound_hdr { 77struct nfs4_cb_compound_hdr {
139 /* args */ 78 /* args */
140 u32 ident; /* minorversion 0 only */ 79 u32 ident; /* minorversion 0 only */
@@ -145,270 +84,487 @@ struct nfs4_cb_compound_hdr {
145 int status; 84 int status;
146}; 85};
147 86
148static struct { 87/*
149int stat; 88 * Handle decode buffer overflows out-of-line.
150int errno; 89 */
151} nfs_cb_errtbl[] = { 90static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
152 { NFS4_OK, 0 }, 91{
153 { NFS4ERR_PERM, EPERM }, 92 dprintk("NFS: %s prematurely hit the end of our receive buffer. "
154 { NFS4ERR_NOENT, ENOENT }, 93 "Remaining buffer length is %tu words.\n",
155 { NFS4ERR_IO, EIO }, 94 func, xdr->end - xdr->p);
156 { NFS4ERR_NXIO, ENXIO }, 95}
157 { NFS4ERR_ACCESS, EACCES },
158 { NFS4ERR_EXIST, EEXIST },
159 { NFS4ERR_XDEV, EXDEV },
160 { NFS4ERR_NOTDIR, ENOTDIR },
161 { NFS4ERR_ISDIR, EISDIR },
162 { NFS4ERR_INVAL, EINVAL },
163 { NFS4ERR_FBIG, EFBIG },
164 { NFS4ERR_NOSPC, ENOSPC },
165 { NFS4ERR_ROFS, EROFS },
166 { NFS4ERR_MLINK, EMLINK },
167 { NFS4ERR_NAMETOOLONG, ENAMETOOLONG },
168 { NFS4ERR_NOTEMPTY, ENOTEMPTY },
169 { NFS4ERR_DQUOT, EDQUOT },
170 { NFS4ERR_STALE, ESTALE },
171 { NFS4ERR_BADHANDLE, EBADHANDLE },
172 { NFS4ERR_BAD_COOKIE, EBADCOOKIE },
173 { NFS4ERR_NOTSUPP, ENOTSUPP },
174 { NFS4ERR_TOOSMALL, ETOOSMALL },
175 { NFS4ERR_SERVERFAULT, ESERVERFAULT },
176 { NFS4ERR_BADTYPE, EBADTYPE },
177 { NFS4ERR_LOCKED, EAGAIN },
178 { NFS4ERR_RESOURCE, EREMOTEIO },
179 { NFS4ERR_SYMLINK, ELOOP },
180 { NFS4ERR_OP_ILLEGAL, EOPNOTSUPP },
181 { NFS4ERR_DEADLOCK, EDEADLK },
182 { -1, EIO }
183};
184 96
185static int 97static __be32 *xdr_encode_empty_array(__be32 *p)
186nfs_cb_stat_to_errno(int stat)
187{ 98{
188 int i; 99 *p++ = xdr_zero;
189 for (i = 0; nfs_cb_errtbl[i].stat != -1; i++) { 100 return p;
190 if (nfs_cb_errtbl[i].stat == stat)
191 return nfs_cb_errtbl[i].errno;
192 }
193 /* If we cannot translate the error, the recovery routines should
194 * handle it.
195 * Note: remaining NFSv4 error codes have values > 10000, so should
196 * not conflict with native Linux error codes.
197 */
198 return stat;
199} 101}
200 102
201/* 103/*
202 * XDR encode 104 * Encode/decode NFSv4 CB basic data types
105 *
106 * Basic NFSv4 callback data types are defined in section 15 of RFC
107 * 3530: "Network File System (NFS) version 4 Protocol" and section
108 * 20 of RFC 5661: "Network File System (NFS) Version 4 Minor Version
109 * 1 Protocol"
203 */ 110 */
204 111
205static void 112/*
206encode_stateid(struct xdr_stream *xdr, stateid_t *sid) 113 * nfs_cb_opnum4
114 *
115 * enum nfs_cb_opnum4 {
116 * OP_CB_GETATTR = 3,
117 * ...
118 * };
119 */
120enum nfs_cb_opnum4 {
121 OP_CB_GETATTR = 3,
122 OP_CB_RECALL = 4,
123 OP_CB_LAYOUTRECALL = 5,
124 OP_CB_NOTIFY = 6,
125 OP_CB_PUSH_DELEG = 7,
126 OP_CB_RECALL_ANY = 8,
127 OP_CB_RECALLABLE_OBJ_AVAIL = 9,
128 OP_CB_RECALL_SLOT = 10,
129 OP_CB_SEQUENCE = 11,
130 OP_CB_WANTS_CANCELLED = 12,
131 OP_CB_NOTIFY_LOCK = 13,
132 OP_CB_NOTIFY_DEVICEID = 14,
133 OP_CB_ILLEGAL = 10044
134};
135
136static void encode_nfs_cb_opnum4(struct xdr_stream *xdr, enum nfs_cb_opnum4 op)
207{ 137{
208 __be32 *p; 138 __be32 *p;
209 139
210 RESERVE_SPACE(sizeof(stateid_t)); 140 p = xdr_reserve_space(xdr, 4);
211 WRITE32(sid->si_generation); 141 *p = cpu_to_be32(op);
212 WRITEMEM(&sid->si_opaque, sizeof(stateid_opaque_t));
213} 142}
214 143
215static void 144/*
216encode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr) 145 * nfs_fh4
146 *
147 * typedef opaque nfs_fh4<NFS4_FHSIZE>;
148 */
149static void encode_nfs_fh4(struct xdr_stream *xdr, const struct knfsd_fh *fh)
217{ 150{
218 __be32 * p; 151 u32 length = fh->fh_size;
152 __be32 *p;
219 153
220 RESERVE_SPACE(16); 154 BUG_ON(length > NFS4_FHSIZE);
221 WRITE32(0); /* tag length is always 0 */ 155 p = xdr_reserve_space(xdr, 4 + length);
222 WRITE32(hdr->minorversion); 156 xdr_encode_opaque(p, &fh->fh_base, length);
223 WRITE32(hdr->ident);
224 hdr->nops_p = p;
225 WRITE32(hdr->nops);
226} 157}
227 158
228static void encode_cb_nops(struct nfs4_cb_compound_hdr *hdr) 159/*
160 * stateid4
161 *
162 * struct stateid4 {
163 * uint32_t seqid;
164 * opaque other[12];
165 * };
166 */
167static void encode_stateid4(struct xdr_stream *xdr, const stateid_t *sid)
229{ 168{
230 *hdr->nops_p = htonl(hdr->nops); 169 __be32 *p;
170
171 p = xdr_reserve_space(xdr, NFS4_STATEID_SIZE);
172 *p++ = cpu_to_be32(sid->si_generation);
173 xdr_encode_opaque_fixed(p, &sid->si_opaque, NFS4_STATEID_OTHER_SIZE);
231} 174}
232 175
233static void 176/*
234encode_cb_recall(struct xdr_stream *xdr, struct nfs4_delegation *dp, 177 * sessionid4
235 struct nfs4_cb_compound_hdr *hdr) 178 *
179 * typedef opaque sessionid4[NFS4_SESSIONID_SIZE];
180 */
181static void encode_sessionid4(struct xdr_stream *xdr,
182 const struct nfsd4_session *session)
236{ 183{
237 __be32 *p; 184 __be32 *p;
238 int len = dp->dl_fh.fh_size; 185
239 186 p = xdr_reserve_space(xdr, NFS4_MAX_SESSIONID_LEN);
240 RESERVE_SPACE(4); 187 xdr_encode_opaque_fixed(p, session->se_sessionid.data,
241 WRITE32(OP_CB_RECALL); 188 NFS4_MAX_SESSIONID_LEN);
242 encode_stateid(xdr, &dp->dl_stateid);
243 RESERVE_SPACE(8 + (XDR_QUADLEN(len) << 2));
244 WRITE32(0); /* truncate optimization not implemented */
245 WRITE32(len);
246 WRITEMEM(&dp->dl_fh.fh_base, len);
247 hdr->nops++;
248} 189}
249 190
250static void 191/*
251encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_sequence *args, 192 * nfsstat4
252 struct nfs4_cb_compound_hdr *hdr) 193 */
253{ 194static const struct {
254 __be32 *p; 195 int stat;
196 int errno;
197} nfs_cb_errtbl[] = {
198 { NFS4_OK, 0 },
199 { NFS4ERR_PERM, -EPERM },
200 { NFS4ERR_NOENT, -ENOENT },
201 { NFS4ERR_IO, -EIO },
202 { NFS4ERR_NXIO, -ENXIO },
203 { NFS4ERR_ACCESS, -EACCES },
204 { NFS4ERR_EXIST, -EEXIST },
205 { NFS4ERR_XDEV, -EXDEV },
206 { NFS4ERR_NOTDIR, -ENOTDIR },
207 { NFS4ERR_ISDIR, -EISDIR },
208 { NFS4ERR_INVAL, -EINVAL },
209 { NFS4ERR_FBIG, -EFBIG },
210 { NFS4ERR_NOSPC, -ENOSPC },
211 { NFS4ERR_ROFS, -EROFS },
212 { NFS4ERR_MLINK, -EMLINK },
213 { NFS4ERR_NAMETOOLONG, -ENAMETOOLONG },
214 { NFS4ERR_NOTEMPTY, -ENOTEMPTY },
215 { NFS4ERR_DQUOT, -EDQUOT },
216 { NFS4ERR_STALE, -ESTALE },
217 { NFS4ERR_BADHANDLE, -EBADHANDLE },
218 { NFS4ERR_BAD_COOKIE, -EBADCOOKIE },
219 { NFS4ERR_NOTSUPP, -ENOTSUPP },
220 { NFS4ERR_TOOSMALL, -ETOOSMALL },
221 { NFS4ERR_SERVERFAULT, -ESERVERFAULT },
222 { NFS4ERR_BADTYPE, -EBADTYPE },
223 { NFS4ERR_LOCKED, -EAGAIN },
224 { NFS4ERR_RESOURCE, -EREMOTEIO },
225 { NFS4ERR_SYMLINK, -ELOOP },
226 { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP },
227 { NFS4ERR_DEADLOCK, -EDEADLK },
228 { -1, -EIO }
229};
255 230
256 if (hdr->minorversion == 0) 231/*
257 return; 232 * If we cannot translate the error, the recovery routines should
233 * handle it.
234 *
235 * Note: remaining NFSv4 error codes have values > 10000, so should
236 * not conflict with native Linux error codes.
237 */
238static int nfs_cb_stat_to_errno(int status)
239{
240 int i;
258 241
259 RESERVE_SPACE(1 + NFS4_MAX_SESSIONID_LEN + 20); 242 for (i = 0; nfs_cb_errtbl[i].stat != -1; i++) {
243 if (nfs_cb_errtbl[i].stat == status)
244 return nfs_cb_errtbl[i].errno;
245 }
260 246
261 WRITE32(OP_CB_SEQUENCE); 247 dprintk("NFSD: Unrecognized NFS CB status value: %u\n", status);
262 WRITEMEM(args->cbs_clp->cl_sessionid.data, NFS4_MAX_SESSIONID_LEN); 248 return -status;
263 WRITE32(args->cbs_clp->cl_cb_seq_nr);
264 WRITE32(0); /* slotid, always 0 */
265 WRITE32(0); /* highest slotid always 0 */
266 WRITE32(0); /* cachethis always 0 */
267 WRITE32(0); /* FIXME: support referring_call_lists */
268 hdr->nops++;
269} 249}
270 250
271static int 251static int decode_cb_op_status(struct xdr_stream *xdr, enum nfs_opnum4 expected,
272nfs4_xdr_enc_cb_null(struct rpc_rqst *req, __be32 *p) 252 enum nfsstat4 *status)
273{ 253{
274 struct xdr_stream xdrs, *xdr = &xdrs; 254 __be32 *p;
255 u32 op;
275 256
276 xdr_init_encode(&xdrs, &req->rq_snd_buf, p); 257 p = xdr_inline_decode(xdr, 4 + 4);
277 RESERVE_SPACE(0); 258 if (unlikely(p == NULL))
259 goto out_overflow;
260 op = be32_to_cpup(p++);
261 if (unlikely(op != expected))
262 goto out_unexpected;
263 *status = be32_to_cpup(p);
278 return 0; 264 return 0;
265out_overflow:
266 print_overflow_msg(__func__, xdr);
267 return -EIO;
268out_unexpected:
269 dprintk("NFSD: Callback server returned operation %d but "
270 "we issued a request for %d\n", op, expected);
271 return -EIO;
279} 272}
280 273
281static int 274/*
282nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p, 275 * CB_COMPOUND4args
283 struct nfs4_rpc_args *rpc_args) 276 *
277 * struct CB_COMPOUND4args {
278 * utf8str_cs tag;
279 * uint32_t minorversion;
280 * uint32_t callback_ident;
281 * nfs_cb_argop4 argarray<>;
282 * };
283*/
284static void encode_cb_compound4args(struct xdr_stream *xdr,
285 struct nfs4_cb_compound_hdr *hdr)
284{ 286{
285 struct xdr_stream xdr; 287 __be32 * p;
286 struct nfs4_delegation *args = rpc_args->args_op;
287 struct nfs4_cb_compound_hdr hdr = {
288 .ident = args->dl_ident,
289 .minorversion = rpc_args->args_seq.cbs_minorversion,
290 };
291 288
292 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 289 p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4);
293 encode_cb_compound_hdr(&xdr, &hdr); 290 p = xdr_encode_empty_array(p); /* empty tag */
294 encode_cb_sequence(&xdr, &rpc_args->args_seq, &hdr); 291 *p++ = cpu_to_be32(hdr->minorversion);
295 encode_cb_recall(&xdr, args, &hdr); 292 *p++ = cpu_to_be32(hdr->ident);
296 encode_cb_nops(&hdr); 293
294 hdr->nops_p = p;
295 *p = cpu_to_be32(hdr->nops); /* argarray element count */
296}
297
298/*
299 * Update argarray element count
300 */
301static void encode_cb_nops(struct nfs4_cb_compound_hdr *hdr)
302{
303 BUG_ON(hdr->nops > NFS4_MAX_BACK_CHANNEL_OPS);
304 *hdr->nops_p = cpu_to_be32(hdr->nops);
305}
306
307/*
308 * CB_COMPOUND4res
309 *
310 * struct CB_COMPOUND4res {
311 * nfsstat4 status;
312 * utf8str_cs tag;
313 * nfs_cb_resop4 resarray<>;
314 * };
315 */
316static int decode_cb_compound4res(struct xdr_stream *xdr,
317 struct nfs4_cb_compound_hdr *hdr)
318{
319 u32 length;
320 __be32 *p;
321
322 p = xdr_inline_decode(xdr, 4 + 4);
323 if (unlikely(p == NULL))
324 goto out_overflow;
325 hdr->status = be32_to_cpup(p++);
326 /* Ignore the tag */
327 length = be32_to_cpup(p++);
328 p = xdr_inline_decode(xdr, length + 4);
329 if (unlikely(p == NULL))
330 goto out_overflow;
331 hdr->nops = be32_to_cpup(p);
297 return 0; 332 return 0;
333out_overflow:
334 print_overflow_msg(__func__, xdr);
335 return -EIO;
298} 336}
299 337
338/*
339 * CB_RECALL4args
340 *
341 * struct CB_RECALL4args {
342 * stateid4 stateid;
343 * bool truncate;
344 * nfs_fh4 fh;
345 * };
346 */
347static void encode_cb_recall4args(struct xdr_stream *xdr,
348 const struct nfs4_delegation *dp,
349 struct nfs4_cb_compound_hdr *hdr)
350{
351 __be32 *p;
352
353 encode_nfs_cb_opnum4(xdr, OP_CB_RECALL);
354 encode_stateid4(xdr, &dp->dl_stateid);
300 355
301static int 356 p = xdr_reserve_space(xdr, 4);
302decode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr){ 357 *p++ = xdr_zero; /* truncate */
303 __be32 *p;
304 u32 taglen;
305 358
306 READ_BUF(8); 359 encode_nfs_fh4(xdr, &dp->dl_fh);
307 READ32(hdr->status); 360
308 /* We've got no use for the tag; ignore it: */ 361 hdr->nops++;
309 READ32(taglen);
310 READ_BUF(taglen + 4);
311 p += XDR_QUADLEN(taglen);
312 READ32(hdr->nops);
313 return 0;
314} 362}
315 363
316static int 364/*
317decode_cb_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) 365 * CB_SEQUENCE4args
366 *
367 * struct CB_SEQUENCE4args {
368 * sessionid4 csa_sessionid;
369 * sequenceid4 csa_sequenceid;
370 * slotid4 csa_slotid;
371 * slotid4 csa_highest_slotid;
372 * bool csa_cachethis;
373 * referring_call_list4 csa_referring_call_lists<>;
374 * };
375 */
376static void encode_cb_sequence4args(struct xdr_stream *xdr,
377 const struct nfsd4_callback *cb,
378 struct nfs4_cb_compound_hdr *hdr)
318{ 379{
380 struct nfsd4_session *session = cb->cb_clp->cl_cb_session;
319 __be32 *p; 381 __be32 *p;
320 u32 op; 382
321 int32_t nfserr; 383 if (hdr->minorversion == 0)
322 384 return;
323 READ_BUF(8); 385
324 READ32(op); 386 encode_nfs_cb_opnum4(xdr, OP_CB_SEQUENCE);
325 if (op != expected) { 387 encode_sessionid4(xdr, session);
326 dprintk("NFSD: decode_cb_op_hdr: Callback server returned " 388
327 " operation %d but we issued a request for %d\n", 389 p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4 + 4);
328 op, expected); 390 *p++ = cpu_to_be32(session->se_cb_seq_nr); /* csa_sequenceid */
329 return -EIO; 391 *p++ = xdr_zero; /* csa_slotid */
330 } 392 *p++ = xdr_zero; /* csa_highest_slotid */
331 READ32(nfserr); 393 *p++ = xdr_zero; /* csa_cachethis */
332 if (nfserr != NFS_OK) 394 xdr_encode_empty_array(p); /* csa_referring_call_lists */
333 return -nfs_cb_stat_to_errno(nfserr); 395
334 return 0; 396 hdr->nops++;
335} 397}
336 398
337/* 399/*
400 * CB_SEQUENCE4resok
401 *
402 * struct CB_SEQUENCE4resok {
403 * sessionid4 csr_sessionid;
404 * sequenceid4 csr_sequenceid;
405 * slotid4 csr_slotid;
406 * slotid4 csr_highest_slotid;
407 * slotid4 csr_target_highest_slotid;
408 * };
409 *
410 * union CB_SEQUENCE4res switch (nfsstat4 csr_status) {
411 * case NFS4_OK:
412 * CB_SEQUENCE4resok csr_resok4;
413 * default:
414 * void;
415 * };
416 *
338 * Our current back channel implmentation supports a single backchannel 417 * Our current back channel implmentation supports a single backchannel
339 * with a single slot. 418 * with a single slot.
340 */ 419 */
341static int 420static int decode_cb_sequence4resok(struct xdr_stream *xdr,
342decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_sequence *res, 421 struct nfsd4_callback *cb)
343 struct rpc_rqst *rqstp)
344{ 422{
423 struct nfsd4_session *session = cb->cb_clp->cl_cb_session;
345 struct nfs4_sessionid id; 424 struct nfs4_sessionid id;
346 int status; 425 int status;
347 u32 dummy;
348 __be32 *p; 426 __be32 *p;
427 u32 dummy;
349 428
350 if (res->cbs_minorversion == 0) 429 status = -ESERVERFAULT;
351 return 0;
352
353 status = decode_cb_op_hdr(xdr, OP_CB_SEQUENCE);
354 if (status)
355 return status;
356 430
357 /* 431 /*
358 * If the server returns different values for sessionID, slotID or 432 * If the server returns different values for sessionID, slotID or
359 * sequence number, the server is looney tunes. 433 * sequence number, the server is looney tunes.
360 */ 434 */
361 status = -ESERVERFAULT; 435 p = xdr_inline_decode(xdr, NFS4_MAX_SESSIONID_LEN + 4 + 4 + 4 + 4);
362 436 if (unlikely(p == NULL))
363 READ_BUF(NFS4_MAX_SESSIONID_LEN + 16); 437 goto out_overflow;
364 memcpy(id.data, p, NFS4_MAX_SESSIONID_LEN); 438 memcpy(id.data, p, NFS4_MAX_SESSIONID_LEN);
365 p += XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN); 439 if (memcmp(id.data, session->se_sessionid.data,
366 if (memcmp(id.data, res->cbs_clp->cl_sessionid.data, 440 NFS4_MAX_SESSIONID_LEN) != 0) {
367 NFS4_MAX_SESSIONID_LEN)) { 441 dprintk("NFS: %s Invalid session id\n", __func__);
368 dprintk("%s Invalid session id\n", __func__);
369 goto out; 442 goto out;
370 } 443 }
371 READ32(dummy); 444 p += XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN);
372 if (dummy != res->cbs_clp->cl_cb_seq_nr) { 445
373 dprintk("%s Invalid sequence number\n", __func__); 446 dummy = be32_to_cpup(p++);
447 if (dummy != session->se_cb_seq_nr) {
448 dprintk("NFS: %s Invalid sequence number\n", __func__);
374 goto out; 449 goto out;
375 } 450 }
376 READ32(dummy); /* slotid must be 0 */ 451
452 dummy = be32_to_cpup(p++);
377 if (dummy != 0) { 453 if (dummy != 0) {
378 dprintk("%s Invalid slotid\n", __func__); 454 dprintk("NFS: %s Invalid slotid\n", __func__);
379 goto out; 455 goto out;
380 } 456 }
381 /* FIXME: process highest slotid and target highest slotid */ 457
458 /*
459 * FIXME: process highest slotid and target highest slotid
460 */
382 status = 0; 461 status = 0;
383out: 462out:
384 return status; 463 return status;
464out_overflow:
465 print_overflow_msg(__func__, xdr);
466 return -EIO;
467}
468
469static int decode_cb_sequence4res(struct xdr_stream *xdr,
470 struct nfsd4_callback *cb)
471{
472 enum nfsstat4 nfserr;
473 int status;
474
475 if (cb->cb_minorversion == 0)
476 return 0;
477
478 status = decode_cb_op_status(xdr, OP_CB_SEQUENCE, &nfserr);
479 if (unlikely(status))
480 goto out;
481 if (unlikely(nfserr != NFS4_OK))
482 goto out_default;
483 status = decode_cb_sequence4resok(xdr, cb);
484out:
485 return status;
486out_default:
487 return nfs_cb_stat_to_errno(nfserr);
488}
489
490/*
491 * NFSv4.0 and NFSv4.1 XDR encode functions
492 *
493 * NFSv4.0 callback argument types are defined in section 15 of RFC
494 * 3530: "Network File System (NFS) version 4 Protocol" and section 20
495 * of RFC 5661: "Network File System (NFS) Version 4 Minor Version 1
496 * Protocol".
497 */
498
499/*
500 * NB: Without this zero space reservation, callbacks over krb5p fail
501 */
502static void nfs4_xdr_enc_cb_null(struct rpc_rqst *req, struct xdr_stream *xdr,
503 void *__unused)
504{
505 xdr_reserve_space(xdr, 0);
506}
507
508/*
509 * 20.2. Operation 4: CB_RECALL - Recall a Delegation
510 */
511static void nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, struct xdr_stream *xdr,
512 const struct nfsd4_callback *cb)
513{
514 const struct nfs4_delegation *args = cb->cb_op;
515 struct nfs4_cb_compound_hdr hdr = {
516 .ident = cb->cb_clp->cl_cb_ident,
517 .minorversion = cb->cb_minorversion,
518 };
519
520 encode_cb_compound4args(xdr, &hdr);
521 encode_cb_sequence4args(xdr, cb, &hdr);
522 encode_cb_recall4args(xdr, args, &hdr);
523 encode_cb_nops(&hdr);
385} 524}
386 525
387 526
388static int 527/*
389nfs4_xdr_dec_cb_null(struct rpc_rqst *req, __be32 *p) 528 * NFSv4.0 and NFSv4.1 XDR decode functions
529 *
530 * NFSv4.0 callback result types are defined in section 15 of RFC
531 * 3530: "Network File System (NFS) version 4 Protocol" and section 20
532 * of RFC 5661: "Network File System (NFS) Version 4 Minor Version 1
533 * Protocol".
534 */
535
536static int nfs4_xdr_dec_cb_null(struct rpc_rqst *req, struct xdr_stream *xdr,
537 void *__unused)
390{ 538{
391 return 0; 539 return 0;
392} 540}
393 541
394static int 542/*
395nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, __be32 *p, 543 * 20.2. Operation 4: CB_RECALL - Recall a Delegation
396 struct nfsd4_cb_sequence *seq) 544 */
545static int nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp,
546 struct xdr_stream *xdr,
547 struct nfsd4_callback *cb)
397{ 548{
398 struct xdr_stream xdr;
399 struct nfs4_cb_compound_hdr hdr; 549 struct nfs4_cb_compound_hdr hdr;
550 enum nfsstat4 nfserr;
400 int status; 551 int status;
401 552
402 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); 553 status = decode_cb_compound4res(xdr, &hdr);
403 status = decode_cb_compound_hdr(&xdr, &hdr); 554 if (unlikely(status))
404 if (status)
405 goto out; 555 goto out;
406 if (seq) { 556
407 status = decode_cb_sequence(&xdr, seq, rqstp); 557 if (cb != NULL) {
408 if (status) 558 status = decode_cb_sequence4res(xdr, cb);
559 if (unlikely(status))
409 goto out; 560 goto out;
410 } 561 }
411 status = decode_cb_op_hdr(&xdr, OP_CB_RECALL); 562
563 status = decode_cb_op_status(xdr, OP_CB_RECALL, &nfserr);
564 if (unlikely(status))
565 goto out;
566 if (unlikely(nfserr != NFS4_OK))
567 status = nfs_cb_stat_to_errno(nfserr);
412out: 568out:
413 return status; 569 return status;
414} 570}
@@ -416,23 +572,23 @@ out:
416/* 572/*
417 * RPC procedure tables 573 * RPC procedure tables
418 */ 574 */
419#define PROC(proc, call, argtype, restype) \ 575#define PROC(proc, call, argtype, restype) \
420[NFSPROC4_CLNT_##proc] = { \ 576[NFSPROC4_CLNT_##proc] = { \
421 .p_proc = NFSPROC4_CB_##call, \ 577 .p_proc = NFSPROC4_CB_##call, \
422 .p_encode = (kxdrproc_t) nfs4_xdr_##argtype, \ 578 .p_encode = (kxdreproc_t)nfs4_xdr_enc_##argtype, \
423 .p_decode = (kxdrproc_t) nfs4_xdr_##restype, \ 579 .p_decode = (kxdrdproc_t)nfs4_xdr_dec_##restype, \
424 .p_arglen = NFS4_##argtype##_sz, \ 580 .p_arglen = NFS4_enc_##argtype##_sz, \
425 .p_replen = NFS4_##restype##_sz, \ 581 .p_replen = NFS4_dec_##restype##_sz, \
426 .p_statidx = NFSPROC4_CB_##call, \ 582 .p_statidx = NFSPROC4_CB_##call, \
427 .p_name = #proc, \ 583 .p_name = #proc, \
428} 584}
429 585
430static struct rpc_procinfo nfs4_cb_procedures[] = { 586static struct rpc_procinfo nfs4_cb_procedures[] = {
431 PROC(CB_NULL, NULL, enc_cb_null, dec_cb_null), 587 PROC(CB_NULL, NULL, cb_null, cb_null),
432 PROC(CB_RECALL, COMPOUND, enc_cb_recall, dec_cb_recall), 588 PROC(CB_RECALL, COMPOUND, cb_recall, cb_recall),
433}; 589};
434 590
435static struct rpc_version nfs_cb_version4 = { 591static struct rpc_version nfs_cb_version4 = {
436/* 592/*
437 * Note on the callback rpc program version number: despite language in rfc 593 * Note on the callback rpc program version number: despite language in rfc
438 * 5661 section 18.36.3 requiring servers to use 4 in this field, the 594 * 5661 section 18.36.3 requiring servers to use 4 in this field, the
@@ -440,29 +596,29 @@ static struct rpc_version nfs_cb_version4 = {
440 * in practice that appears to be what implementations use. The section 596 * in practice that appears to be what implementations use. The section
441 * 18.36.3 language is expected to be fixed in an erratum. 597 * 18.36.3 language is expected to be fixed in an erratum.
442 */ 598 */
443 .number = 1, 599 .number = 1,
444 .nrprocs = ARRAY_SIZE(nfs4_cb_procedures), 600 .nrprocs = ARRAY_SIZE(nfs4_cb_procedures),
445 .procs = nfs4_cb_procedures 601 .procs = nfs4_cb_procedures
446}; 602};
447 603
448static struct rpc_version * nfs_cb_version[] = { 604static struct rpc_version *nfs_cb_version[] = {
449 &nfs_cb_version4, 605 &nfs_cb_version4,
450}; 606};
451 607
452static struct rpc_program cb_program; 608static struct rpc_program cb_program;
453 609
454static struct rpc_stat cb_stats = { 610static struct rpc_stat cb_stats = {
455 .program = &cb_program 611 .program = &cb_program
456}; 612};
457 613
458#define NFS4_CALLBACK 0x40000000 614#define NFS4_CALLBACK 0x40000000
459static struct rpc_program cb_program = { 615static struct rpc_program cb_program = {
460 .name = "nfs4_cb", 616 .name = "nfs4_cb",
461 .number = NFS4_CALLBACK, 617 .number = NFS4_CALLBACK,
462 .nrvers = ARRAY_SIZE(nfs_cb_version), 618 .nrvers = ARRAY_SIZE(nfs_cb_version),
463 .version = nfs_cb_version, 619 .version = nfs_cb_version,
464 .stats = &cb_stats, 620 .stats = &cb_stats,
465 .pipe_dir_name = "/nfsd4_cb", 621 .pipe_dir_name = "/nfsd4_cb",
466}; 622};
467 623
468static int max_cb_time(void) 624static int max_cb_time(void)
@@ -470,33 +626,40 @@ static int max_cb_time(void)
470 return max(nfsd4_lease/10, (time_t)1) * HZ; 626 return max(nfsd4_lease/10, (time_t)1) * HZ;
471} 627}
472 628
473/* Reference counting, callback cleanup, etc., all look racy as heck.
474 * And why is cl_cb_set an atomic? */
475 629
476int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *cb) 630static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses)
477{ 631{
478 struct rpc_timeout timeparms = { 632 struct rpc_timeout timeparms = {
479 .to_initval = max_cb_time(), 633 .to_initval = max_cb_time(),
480 .to_retries = 0, 634 .to_retries = 0,
481 }; 635 };
482 struct rpc_create_args args = { 636 struct rpc_create_args args = {
483 .protocol = XPRT_TRANSPORT_TCP, 637 .net = &init_net,
484 .address = (struct sockaddr *) &cb->cb_addr, 638 .address = (struct sockaddr *) &conn->cb_addr,
485 .addrsize = cb->cb_addrlen, 639 .addrsize = conn->cb_addrlen,
640 .saddress = (struct sockaddr *) &conn->cb_saddr,
486 .timeout = &timeparms, 641 .timeout = &timeparms,
487 .program = &cb_program, 642 .program = &cb_program,
488 .prognumber = cb->cb_prog,
489 .version = 0, 643 .version = 0,
490 .authflavor = clp->cl_flavor, 644 .authflavor = clp->cl_flavor,
491 .flags = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET), 645 .flags = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
492 .client_name = clp->cl_principal,
493 }; 646 };
494 struct rpc_clnt *client; 647 struct rpc_clnt *client;
495 648
496 if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5)) 649 if (clp->cl_minorversion == 0) {
497 return -EINVAL; 650 if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5))
498 if (cb->cb_minorversion) { 651 return -EINVAL;
499 args.bc_xprt = cb->cb_xprt; 652 args.client_name = clp->cl_principal;
653 args.prognumber = conn->cb_prog,
654 args.protocol = XPRT_TRANSPORT_TCP;
655 clp->cl_cb_ident = conn->cb_ident;
656 } else {
657 if (!conn->cb_xprt)
658 return -EINVAL;
659 clp->cl_cb_conn.cb_xprt = conn->cb_xprt;
660 clp->cl_cb_session = ses;
661 args.bc_xprt = conn->cb_xprt;
662 args.prognumber = clp->cl_cb_session->se_cb_prog;
500 args.protocol = XPRT_TRANSPORT_BC_TCP; 663 args.protocol = XPRT_TRANSPORT_BC_TCP;
501 } 664 }
502 /* Create RPC client */ 665 /* Create RPC client */
@@ -506,7 +669,7 @@ int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *cb)
506 PTR_ERR(client)); 669 PTR_ERR(client));
507 return PTR_ERR(client); 670 return PTR_ERR(client);
508 } 671 }
509 nfsd4_set_callback_client(clp, client); 672 clp->cl_cb_client = client;
510 return 0; 673 return 0;
511 674
512} 675}
@@ -517,17 +680,25 @@ static void warn_no_callback_path(struct nfs4_client *clp, int reason)
517 (int)clp->cl_name.len, clp->cl_name.data, reason); 680 (int)clp->cl_name.len, clp->cl_name.data, reason);
518} 681}
519 682
683static void nfsd4_mark_cb_down(struct nfs4_client *clp, int reason)
684{
685 clp->cl_cb_state = NFSD4_CB_DOWN;
686 warn_no_callback_path(clp, reason);
687}
688
520static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata) 689static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata)
521{ 690{
522 struct nfs4_client *clp = calldata; 691 struct nfs4_client *clp = container_of(calldata, struct nfs4_client, cl_cb_null);
523 692
524 if (task->tk_status) 693 if (task->tk_status)
525 warn_no_callback_path(clp, task->tk_status); 694 nfsd4_mark_cb_down(clp, task->tk_status);
526 else 695 else
527 atomic_set(&clp->cl_cb_set, 1); 696 clp->cl_cb_state = NFSD4_CB_UP;
528} 697}
529 698
530static const struct rpc_call_ops nfsd4_cb_probe_ops = { 699static const struct rpc_call_ops nfsd4_cb_probe_ops = {
700 /* XXX: release method to ensure we set the cb channel down if
701 * necessary on early failure? */
531 .rpc_call_done = nfsd4_cb_probe_done, 702 .rpc_call_done = nfsd4_cb_probe_done,
532}; 703};
533 704
@@ -543,38 +714,54 @@ int set_callback_cred(void)
543 return 0; 714 return 0;
544} 715}
545 716
717static struct workqueue_struct *callback_wq;
546 718
547void do_probe_callback(struct nfs4_client *clp) 719static void run_nfsd4_cb(struct nfsd4_callback *cb)
548{ 720{
549 struct rpc_message msg = { 721 queue_work(callback_wq, &cb->cb_work);
550 .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], 722}
551 .rpc_argp = clp, 723
552 .rpc_cred = callback_cred 724static void do_probe_callback(struct nfs4_client *clp)
553 }; 725{
554 int status; 726 struct nfsd4_callback *cb = &clp->cl_cb_null;
727
728 cb->cb_op = NULL;
729 cb->cb_clp = clp;
730
731 cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL];
732 cb->cb_msg.rpc_argp = NULL;
733 cb->cb_msg.rpc_resp = NULL;
734 cb->cb_msg.rpc_cred = callback_cred;
555 735
556 status = rpc_call_async(clp->cl_cb_client, &msg, 736 cb->cb_ops = &nfsd4_cb_probe_ops;
557 RPC_TASK_SOFT | RPC_TASK_SOFTCONN, 737
558 &nfsd4_cb_probe_ops, (void *)clp); 738 run_nfsd4_cb(cb);
559 if (status)
560 warn_no_callback_path(clp, status);
561} 739}
562 740
563/* 741/*
564 * Set up the callback client and put a NFSPROC4_CB_NULL on the wire... 742 * Poke the callback thread to process any updates to the callback
743 * parameters, and send a null probe.
565 */ 744 */
566void nfsd4_probe_callback(struct nfs4_client *clp, struct nfs4_cb_conn *cb) 745void nfsd4_probe_callback(struct nfs4_client *clp)
567{ 746{
568 int status; 747 /* XXX: atomicity? Also, should we be using cl_cb_flags? */
748 clp->cl_cb_state = NFSD4_CB_UNKNOWN;
749 set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags);
750 do_probe_callback(clp);
751}
569 752
570 BUG_ON(atomic_read(&clp->cl_cb_set)); 753void nfsd4_probe_callback_sync(struct nfs4_client *clp)
754{
755 nfsd4_probe_callback(clp);
756 flush_workqueue(callback_wq);
757}
571 758
572 status = setup_callback_client(clp, cb); 759void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
573 if (status) { 760{
574 warn_no_callback_path(clp, status); 761 clp->cl_cb_state = NFSD4_CB_UNKNOWN;
575 return; 762 spin_lock(&clp->cl_lock);
576 } 763 memcpy(&clp->cl_cb_conn, conn, sizeof(struct nfs4_cb_conn));
577 do_probe_callback(clp); 764 spin_unlock(&clp->cl_lock);
578} 765}
579 766
580/* 767/*
@@ -582,33 +769,14 @@ void nfsd4_probe_callback(struct nfs4_client *clp, struct nfs4_cb_conn *cb)
582 * If the slot is available, then mark it busy. Otherwise, set the 769 * If the slot is available, then mark it busy. Otherwise, set the
583 * thread for sleeping on the callback RPC wait queue. 770 * thread for sleeping on the callback RPC wait queue.
584 */ 771 */
585static int nfsd41_cb_setup_sequence(struct nfs4_client *clp, 772static bool nfsd41_cb_get_slot(struct nfs4_client *clp, struct rpc_task *task)
586 struct rpc_task *task)
587{ 773{
588 struct nfs4_rpc_args *args = task->tk_msg.rpc_argp;
589 u32 *ptr = (u32 *)clp->cl_sessionid.data;
590 int status = 0;
591
592 dprintk("%s: %u:%u:%u:%u\n", __func__,
593 ptr[0], ptr[1], ptr[2], ptr[3]);
594
595 if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) { 774 if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) {
596 rpc_sleep_on(&clp->cl_cb_waitq, task, NULL); 775 rpc_sleep_on(&clp->cl_cb_waitq, task, NULL);
597 dprintk("%s slot is busy\n", __func__); 776 dprintk("%s slot is busy\n", __func__);
598 status = -EAGAIN; 777 return false;
599 goto out;
600 } 778 }
601 779 return true;
602 /*
603 * We'll need the clp during XDR encoding and decoding,
604 * and the sequence during decoding to verify the reply
605 */
606 args->args_seq.cbs_clp = clp;
607 task->tk_msg.rpc_resp = &args->args_seq;
608
609out:
610 dprintk("%s status=%d\n", __func__, status);
611 return status;
612} 780}
613 781
614/* 782/*
@@ -617,42 +785,42 @@ out:
617 */ 785 */
618static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata) 786static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
619{ 787{
620 struct nfs4_delegation *dp = calldata; 788 struct nfsd4_callback *cb = calldata;
789 struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
621 struct nfs4_client *clp = dp->dl_client; 790 struct nfs4_client *clp = dp->dl_client;
622 struct nfs4_rpc_args *args = task->tk_msg.rpc_argp; 791 u32 minorversion = clp->cl_minorversion;
623 u32 minorversion = clp->cl_cb_conn.cb_minorversion;
624 int status = 0;
625 792
626 args->args_seq.cbs_minorversion = minorversion; 793 cb->cb_minorversion = minorversion;
627 if (minorversion) { 794 if (minorversion) {
628 status = nfsd41_cb_setup_sequence(clp, task); 795 if (!nfsd41_cb_get_slot(clp, task))
629 if (status) {
630 if (status != -EAGAIN) {
631 /* terminate rpc task */
632 task->tk_status = status;
633 task->tk_action = NULL;
634 }
635 return; 796 return;
636 }
637 } 797 }
798 spin_lock(&clp->cl_lock);
799 if (list_empty(&cb->cb_per_client)) {
800 /* This is the first call, not a restart */
801 cb->cb_done = false;
802 list_add(&cb->cb_per_client, &clp->cl_callbacks);
803 }
804 spin_unlock(&clp->cl_lock);
638 rpc_call_start(task); 805 rpc_call_start(task);
639} 806}
640 807
641static void nfsd4_cb_done(struct rpc_task *task, void *calldata) 808static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
642{ 809{
643 struct nfs4_delegation *dp = calldata; 810 struct nfsd4_callback *cb = calldata;
811 struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
644 struct nfs4_client *clp = dp->dl_client; 812 struct nfs4_client *clp = dp->dl_client;
645 813
646 dprintk("%s: minorversion=%d\n", __func__, 814 dprintk("%s: minorversion=%d\n", __func__,
647 clp->cl_cb_conn.cb_minorversion); 815 clp->cl_minorversion);
648 816
649 if (clp->cl_cb_conn.cb_minorversion) { 817 if (clp->cl_minorversion) {
650 /* No need for lock, access serialized in nfsd4_cb_prepare */ 818 /* No need for lock, access serialized in nfsd4_cb_prepare */
651 ++clp->cl_cb_seq_nr; 819 ++clp->cl_cb_session->se_cb_seq_nr;
652 clear_bit(0, &clp->cl_cb_slot_busy); 820 clear_bit(0, &clp->cl_cb_slot_busy);
653 rpc_wake_up_next(&clp->cl_cb_waitq); 821 rpc_wake_up_next(&clp->cl_cb_waitq);
654 dprintk("%s: freed slot, new seqid=%d\n", __func__, 822 dprintk("%s: freed slot, new seqid=%d\n", __func__,
655 clp->cl_cb_seq_nr); 823 clp->cl_cb_session->se_cb_seq_nr);
656 824
657 /* We're done looking into the sequence information */ 825 /* We're done looking into the sequence information */
658 task->tk_msg.rpc_resp = NULL; 826 task->tk_msg.rpc_resp = NULL;
@@ -662,21 +830,25 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
662 830
663static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata) 831static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
664{ 832{
665 struct nfs4_delegation *dp = calldata; 833 struct nfsd4_callback *cb = calldata;
834 struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
666 struct nfs4_client *clp = dp->dl_client; 835 struct nfs4_client *clp = dp->dl_client;
667 struct rpc_clnt *current_rpc_client = clp->cl_cb_client; 836 struct rpc_clnt *current_rpc_client = clp->cl_cb_client;
668 837
669 nfsd4_cb_done(task, calldata); 838 nfsd4_cb_done(task, calldata);
670 839
671 if (current_rpc_client == NULL) { 840 if (current_rpc_client != task->tk_client) {
672 /* We're shutting down; give up. */ 841 /* We're shutting down or changing cl_cb_client; leave
673 /* XXX: err, or is it ok just to fall through 842 * it to nfsd4_process_cb_update to restart the call if
674 * and rpc_restart_call? */ 843 * necessary. */
675 return; 844 return;
676 } 845 }
677 846
847 if (cb->cb_done)
848 return;
678 switch (task->tk_status) { 849 switch (task->tk_status) {
679 case 0: 850 case 0:
851 cb->cb_done = true;
680 return; 852 return;
681 case -EBADHANDLE: 853 case -EBADHANDLE:
682 case -NFS4ERR_BAD_STATEID: 854 case -NFS4ERR_BAD_STATEID:
@@ -685,31 +857,30 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
685 break; 857 break;
686 default: 858 default:
687 /* Network partition? */ 859 /* Network partition? */
688 atomic_set(&clp->cl_cb_set, 0); 860 nfsd4_mark_cb_down(clp, task->tk_status);
689 warn_no_callback_path(clp, task->tk_status);
690 if (current_rpc_client != task->tk_client) {
691 /* queue a callback on the new connection: */
692 atomic_inc(&dp->dl_count);
693 nfsd4_cb_recall(dp);
694 return;
695 }
696 } 861 }
697 if (dp->dl_retries--) { 862 if (dp->dl_retries--) {
698 rpc_delay(task, 2*HZ); 863 rpc_delay(task, 2*HZ);
699 task->tk_status = 0; 864 task->tk_status = 0;
700 rpc_restart_call_prepare(task); 865 rpc_restart_call_prepare(task);
701 return; 866 return;
702 } else {
703 atomic_set(&clp->cl_cb_set, 0);
704 warn_no_callback_path(clp, task->tk_status);
705 } 867 }
868 nfsd4_mark_cb_down(clp, task->tk_status);
869 cb->cb_done = true;
706} 870}
707 871
708static void nfsd4_cb_recall_release(void *calldata) 872static void nfsd4_cb_recall_release(void *calldata)
709{ 873{
710 struct nfs4_delegation *dp = calldata; 874 struct nfsd4_callback *cb = calldata;
711 875 struct nfs4_client *clp = cb->cb_clp;
712 nfs4_put_delegation(dp); 876 struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
877
878 if (cb->cb_done) {
879 spin_lock(&clp->cl_lock);
880 list_del(&cb->cb_per_client);
881 spin_unlock(&clp->cl_lock);
882 nfs4_put_delegation(dp);
883 }
713} 884}
714 885
715static const struct rpc_call_ops nfsd4_cb_recall_ops = { 886static const struct rpc_call_ops nfsd4_cb_recall_ops = {
@@ -718,8 +889,6 @@ static const struct rpc_call_ops nfsd4_cb_recall_ops = {
718 .rpc_release = nfsd4_cb_recall_release, 889 .rpc_release = nfsd4_cb_recall_release,
719}; 890};
720 891
721static struct workqueue_struct *callback_wq;
722
723int nfsd4_create_callback_queue(void) 892int nfsd4_create_callback_queue(void)
724{ 893{
725 callback_wq = create_singlethread_workqueue("nfsd4_callbacks"); 894 callback_wq = create_singlethread_workqueue("nfsd4_callbacks");
@@ -734,57 +903,124 @@ void nfsd4_destroy_callback_queue(void)
734} 903}
735 904
736/* must be called under the state lock */ 905/* must be called under the state lock */
737void nfsd4_set_callback_client(struct nfs4_client *clp, struct rpc_clnt *new) 906void nfsd4_shutdown_callback(struct nfs4_client *clp)
738{ 907{
739 struct rpc_clnt *old = clp->cl_cb_client; 908 set_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags);
740
741 clp->cl_cb_client = new;
742 /* 909 /*
743 * After this, any work that saw the old value of cl_cb_client will 910 * Note this won't actually result in a null callback;
744 * be gone: 911 * instead, nfsd4_do_callback_rpc() will detect the killed
912 * client, destroy the rpc client, and stop:
745 */ 913 */
914 do_probe_callback(clp);
746 flush_workqueue(callback_wq); 915 flush_workqueue(callback_wq);
747 /* So we can safely shut it down: */
748 if (old)
749 rpc_shutdown_client(old);
750} 916}
751 917
752/* 918static void nfsd4_release_cb(struct nfsd4_callback *cb)
753 * called with dp->dl_count inc'ed.
754 */
755static void _nfsd4_cb_recall(struct nfs4_delegation *dp)
756{ 919{
757 struct nfs4_client *clp = dp->dl_client; 920 if (cb->cb_ops->rpc_release)
758 struct rpc_clnt *clnt = clp->cl_cb_client; 921 cb->cb_ops->rpc_release(cb);
759 struct nfs4_rpc_args *args = &dp->dl_recall.cb_args; 922}
760 struct rpc_message msg = {
761 .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
762 .rpc_cred = callback_cred
763 };
764 923
765 if (clnt == NULL) { 924/* requires cl_lock: */
766 nfs4_put_delegation(dp); 925static struct nfsd4_conn * __nfsd4_find_backchannel(struct nfs4_client *clp)
767 return; /* Client is shutting down; give up. */ 926{
927 struct nfsd4_session *s;
928 struct nfsd4_conn *c;
929
930 list_for_each_entry(s, &clp->cl_sessions, se_perclnt) {
931 list_for_each_entry(c, &s->se_conns, cn_persession) {
932 if (c->cn_flags & NFS4_CDFC4_BACK)
933 return c;
934 }
768 } 935 }
936 return NULL;
937}
769 938
770 args->args_op = dp; 939static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
771 msg.rpc_argp = args; 940{
772 dp->dl_retries = 1; 941 struct nfs4_cb_conn conn;
773 rpc_call_async(clnt, &msg, RPC_TASK_SOFT, &nfsd4_cb_recall_ops, dp); 942 struct nfs4_client *clp = cb->cb_clp;
943 struct nfsd4_session *ses = NULL;
944 struct nfsd4_conn *c;
945 int err;
946
947 /*
948 * This is either an update, or the client dying; in either case,
949 * kill the old client:
950 */
951 if (clp->cl_cb_client) {
952 rpc_shutdown_client(clp->cl_cb_client);
953 clp->cl_cb_client = NULL;
954 }
955 if (clp->cl_cb_conn.cb_xprt) {
956 svc_xprt_put(clp->cl_cb_conn.cb_xprt);
957 clp->cl_cb_conn.cb_xprt = NULL;
958 }
959 if (test_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags))
960 return;
961 spin_lock(&clp->cl_lock);
962 /*
963 * Only serialized callback code is allowed to clear these
964 * flags; main nfsd code can only set them:
965 */
966 BUG_ON(!clp->cl_cb_flags);
967 clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags);
968 memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn));
969 c = __nfsd4_find_backchannel(clp);
970 if (c) {
971 svc_xprt_get(c->cn_xprt);
972 conn.cb_xprt = c->cn_xprt;
973 ses = c->cn_session;
974 }
975 spin_unlock(&clp->cl_lock);
976
977 err = setup_callback_client(clp, &conn, ses);
978 if (err) {
979 warn_no_callback_path(clp, err);
980 return;
981 }
982 /* Yay, the callback channel's back! Restart any callbacks: */
983 list_for_each_entry(cb, &clp->cl_callbacks, cb_per_client)
984 run_nfsd4_cb(cb);
774} 985}
775 986
776void nfsd4_do_callback_rpc(struct work_struct *w) 987void nfsd4_do_callback_rpc(struct work_struct *w)
777{ 988{
778 /* XXX: for now, just send off delegation recall. */ 989 struct nfsd4_callback *cb = container_of(w, struct nfsd4_callback, cb_work);
779 /* In future, generalize to handle any sort of callback. */ 990 struct nfs4_client *clp = cb->cb_clp;
780 struct nfsd4_callback *c = container_of(w, struct nfsd4_callback, cb_work); 991 struct rpc_clnt *clnt;
781 struct nfs4_delegation *dp = container_of(c, struct nfs4_delegation, dl_recall);
782 992
783 _nfsd4_cb_recall(dp); 993 if (clp->cl_cb_flags)
784} 994 nfsd4_process_cb_update(cb);
785 995
996 clnt = clp->cl_cb_client;
997 if (!clnt) {
998 /* Callback channel broken, or client killed; give up: */
999 nfsd4_release_cb(cb);
1000 return;
1001 }
1002 rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
1003 cb->cb_ops, cb);
1004}
786 1005
787void nfsd4_cb_recall(struct nfs4_delegation *dp) 1006void nfsd4_cb_recall(struct nfs4_delegation *dp)
788{ 1007{
789 queue_work(callback_wq, &dp->dl_recall.cb_work); 1008 struct nfsd4_callback *cb = &dp->dl_recall;
1009 struct nfs4_client *clp = dp->dl_client;
1010
1011 dp->dl_retries = 1;
1012 cb->cb_op = dp;
1013 cb->cb_clp = clp;
1014 cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL];
1015 cb->cb_msg.rpc_argp = cb;
1016 cb->cb_msg.rpc_resp = cb;
1017 cb->cb_msg.rpc_cred = callback_cred;
1018
1019 cb->cb_ops = &nfsd4_cb_recall_ops;
1020 dp->dl_retries = 1;
1021
1022 INIT_LIST_HEAD(&cb->cb_per_client);
1023 cb->cb_done = true;
1024
1025 run_nfsd4_cb(&dp->dl_recall);
790} 1026}
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index c78dbf493424..55780a22fdbd 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -33,10 +33,11 @@
33 */ 33 */
34 34
35#include <linux/module.h> 35#include <linux/module.h>
36#include <linux/nfsd_idmap.h>
37#include <linux/seq_file.h> 36#include <linux/seq_file.h>
38#include <linux/sched.h> 37#include <linux/sched.h>
39#include <linux/slab.h> 38#include <linux/slab.h>
39#include "idmap.h"
40#include "nfsd.h"
40 41
41/* 42/*
42 * Cache entry 43 * Cache entry
@@ -62,7 +63,6 @@ struct ent {
62 63
63#define ENT_HASHBITS 8 64#define ENT_HASHBITS 8
64#define ENT_HASHMAX (1 << ENT_HASHBITS) 65#define ENT_HASHMAX (1 << ENT_HASHBITS)
65#define ENT_HASHMASK (ENT_HASHMAX - 1)
66 66
67static void 67static void
68ent_init(struct cache_head *cnew, struct cache_head *citm) 68ent_init(struct cache_head *cnew, struct cache_head *citm)
@@ -482,109 +482,26 @@ nfsd_idmap_shutdown(void)
482 cache_unregister(&nametoid_cache); 482 cache_unregister(&nametoid_cache);
483} 483}
484 484
485/*
486 * Deferred request handling
487 */
488
489struct idmap_defer_req {
490 struct cache_req req;
491 struct cache_deferred_req deferred_req;
492 wait_queue_head_t waitq;
493 atomic_t count;
494};
495
496static inline void
497put_mdr(struct idmap_defer_req *mdr)
498{
499 if (atomic_dec_and_test(&mdr->count))
500 kfree(mdr);
501}
502
503static inline void
504get_mdr(struct idmap_defer_req *mdr)
505{
506 atomic_inc(&mdr->count);
507}
508
509static void
510idmap_revisit(struct cache_deferred_req *dreq, int toomany)
511{
512 struct idmap_defer_req *mdr =
513 container_of(dreq, struct idmap_defer_req, deferred_req);
514
515 wake_up(&mdr->waitq);
516 put_mdr(mdr);
517}
518
519static struct cache_deferred_req *
520idmap_defer(struct cache_req *req)
521{
522 struct idmap_defer_req *mdr =
523 container_of(req, struct idmap_defer_req, req);
524
525 mdr->deferred_req.revisit = idmap_revisit;
526 get_mdr(mdr);
527 return (&mdr->deferred_req);
528}
529
530static inline int
531do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *), struct ent *key,
532 struct cache_detail *detail, struct ent **item,
533 struct idmap_defer_req *mdr)
534{
535 *item = lookup_fn(key);
536 if (!*item)
537 return -ENOMEM;
538 return cache_check(detail, &(*item)->h, &mdr->req);
539}
540
541static inline int
542do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *),
543 struct ent *key, struct cache_detail *detail,
544 struct ent **item)
545{
546 int ret = -ENOMEM;
547
548 *item = lookup_fn(key);
549 if (!*item)
550 goto out_err;
551 ret = -ETIMEDOUT;
552 if (!test_bit(CACHE_VALID, &(*item)->h.flags)
553 || (*item)->h.expiry_time < get_seconds()
554 || detail->flush_time > (*item)->h.last_refresh)
555 goto out_put;
556 ret = -ENOENT;
557 if (test_bit(CACHE_NEGATIVE, &(*item)->h.flags))
558 goto out_put;
559 return 0;
560out_put:
561 cache_put(&(*item)->h, detail);
562out_err:
563 *item = NULL;
564 return ret;
565}
566
567static int 485static int
568idmap_lookup(struct svc_rqst *rqstp, 486idmap_lookup(struct svc_rqst *rqstp,
569 struct ent *(*lookup_fn)(struct ent *), struct ent *key, 487 struct ent *(*lookup_fn)(struct ent *), struct ent *key,
570 struct cache_detail *detail, struct ent **item) 488 struct cache_detail *detail, struct ent **item)
571{ 489{
572 struct idmap_defer_req *mdr;
573 int ret; 490 int ret;
574 491
575 mdr = kzalloc(sizeof(*mdr), GFP_KERNEL); 492 *item = lookup_fn(key);
576 if (!mdr) 493 if (!*item)
577 return -ENOMEM; 494 return -ENOMEM;
578 atomic_set(&mdr->count, 1); 495 retry:
579 init_waitqueue_head(&mdr->waitq); 496 ret = cache_check(detail, &(*item)->h, &rqstp->rq_chandle);
580 mdr->req.defer = idmap_defer; 497
581 ret = do_idmap_lookup(lookup_fn, key, detail, item, mdr); 498 if (ret == -ETIMEDOUT) {
582 if (ret == -EAGAIN) { 499 struct ent *prev_item = *item;
583 wait_event_interruptible_timeout(mdr->waitq, 500 *item = lookup_fn(key);
584 test_bit(CACHE_VALID, &(*item)->h.flags), 1 * HZ); 501 if (*item != prev_item)
585 ret = do_idmap_lookup_nowait(lookup_fn, key, detail, item); 502 goto retry;
503 cache_put(&(*item)->h, detail);
586 } 504 }
587 put_mdr(mdr);
588 return ret; 505 return ret;
589} 506}
590 507
@@ -597,7 +514,7 @@ rqst_authname(struct svc_rqst *rqstp)
597 return clp->name; 514 return clp->name;
598} 515}
599 516
600static int 517static __be32
601idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, 518idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen,
602 uid_t *id) 519 uid_t *id)
603{ 520{
@@ -607,15 +524,15 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen
607 int ret; 524 int ret;
608 525
609 if (namelen + 1 > sizeof(key.name)) 526 if (namelen + 1 > sizeof(key.name))
610 return -EINVAL; 527 return nfserr_badowner;
611 memcpy(key.name, name, namelen); 528 memcpy(key.name, name, namelen);
612 key.name[namelen] = '\0'; 529 key.name[namelen] = '\0';
613 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); 530 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
614 ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item); 531 ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item);
615 if (ret == -ENOENT) 532 if (ret == -ENOENT)
616 ret = -ESRCH; /* nfserr_badname */ 533 return nfserr_badowner;
617 if (ret) 534 if (ret)
618 return ret; 535 return nfserrno(ret);
619 *id = item->id; 536 *id = item->id;
620 cache_put(&item->h, &nametoid_cache); 537 cache_put(&item->h, &nametoid_cache);
621 return 0; 538 return 0;
@@ -643,14 +560,14 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
643 return ret; 560 return ret;
644} 561}
645 562
646int 563__be32
647nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen, 564nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen,
648 __u32 *id) 565 __u32 *id)
649{ 566{
650 return idmap_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, id); 567 return idmap_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, id);
651} 568}
652 569
653int 570__be32
654nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen, 571nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen,
655 __u32 *id) 572 __u32 *id)
656{ 573{
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 59ec449b0c7f..3a6dbd70b34b 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -196,9 +196,9 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o
196 196
197 /* 197 /*
198 * Note: create modes (UNCHECKED,GUARDED...) are the same 198 * Note: create modes (UNCHECKED,GUARDED...) are the same
199 * in NFSv4 as in v3. 199 * in NFSv4 as in v3 except EXCLUSIVE4_1.
200 */ 200 */
201 status = nfsd_create_v3(rqstp, current_fh, open->op_fname.data, 201 status = do_nfsd_create(rqstp, current_fh, open->op_fname.data,
202 open->op_fname.len, &open->op_iattr, 202 open->op_fname.len, &open->op_iattr,
203 &resfh, open->op_createmode, 203 &resfh, open->op_createmode,
204 (u32 *)open->op_verf.data, 204 (u32 *)open->op_verf.data,
@@ -403,7 +403,7 @@ nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
403 cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen; 403 cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
404 memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval, 404 memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
405 putfh->pf_fhlen); 405 putfh->pf_fhlen);
406 return fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP); 406 return fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_BYPASS_GSS);
407} 407}
408 408
409static __be32 409static __be32
@@ -604,9 +604,7 @@ nfsd4_link(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
604 return status; 604 return status;
605} 605}
606 606
607static __be32 607static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
608nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
609 void *arg)
610{ 608{
611 struct svc_fh tmp_fh; 609 struct svc_fh tmp_fh;
612 __be32 ret; 610 __be32 ret;
@@ -615,13 +613,19 @@ nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
615 ret = exp_pseudoroot(rqstp, &tmp_fh); 613 ret = exp_pseudoroot(rqstp, &tmp_fh);
616 if (ret) 614 if (ret)
617 return ret; 615 return ret;
618 if (tmp_fh.fh_dentry == cstate->current_fh.fh_dentry) { 616 if (tmp_fh.fh_dentry == fh->fh_dentry) {
619 fh_put(&tmp_fh); 617 fh_put(&tmp_fh);
620 return nfserr_noent; 618 return nfserr_noent;
621 } 619 }
622 fh_put(&tmp_fh); 620 fh_put(&tmp_fh);
623 return nfsd_lookup(rqstp, &cstate->current_fh, 621 return nfsd_lookup(rqstp, fh, "..", 2, fh);
624 "..", 2, &cstate->current_fh); 622}
623
624static __be32
625nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
626 void *arg)
627{
628 return nfsd4_do_lookupp(rqstp, &cstate->current_fh);
625} 629}
626 630
627static __be32 631static __be32
@@ -758,6 +762,9 @@ nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
758 __be32 err; 762 __be32 err;
759 763
760 fh_init(&resfh, NFS4_FHSIZE); 764 fh_init(&resfh, NFS4_FHSIZE);
765 err = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, NFSD_MAY_EXEC);
766 if (err)
767 return err;
761 err = nfsd_lookup_dentry(rqstp, &cstate->current_fh, 768 err = nfsd_lookup_dentry(rqstp, &cstate->current_fh,
762 secinfo->si_name, secinfo->si_namelen, 769 secinfo->si_name, secinfo->si_namelen,
763 &exp, &dentry); 770 &exp, &dentry);
@@ -769,10 +776,36 @@ nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
769 } else 776 } else
770 secinfo->si_exp = exp; 777 secinfo->si_exp = exp;
771 dput(dentry); 778 dput(dentry);
779 if (cstate->minorversion)
780 /* See rfc 5661 section 2.6.3.1.1.8 */
781 fh_put(&cstate->current_fh);
772 return err; 782 return err;
773} 783}
774 784
775static __be32 785static __be32
786nfsd4_secinfo_no_name(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
787 struct nfsd4_secinfo_no_name *sin)
788{
789 __be32 err;
790
791 switch (sin->sin_style) {
792 case NFS4_SECINFO_STYLE4_CURRENT_FH:
793 break;
794 case NFS4_SECINFO_STYLE4_PARENT:
795 err = nfsd4_do_lookupp(rqstp, &cstate->current_fh);
796 if (err)
797 return err;
798 break;
799 default:
800 return nfserr_inval;
801 }
802 exp_get(cstate->current_fh.fh_export);
803 sin->sin_exp = cstate->current_fh.fh_export;
804 fh_put(&cstate->current_fh);
805 return nfs_ok;
806}
807
808static __be32
776nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 809nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
777 struct nfsd4_setattr *setattr) 810 struct nfsd4_setattr *setattr)
778{ 811{
@@ -954,8 +987,11 @@ typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *,
954 void *); 987 void *);
955enum nfsd4_op_flags { 988enum nfsd4_op_flags {
956 ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */ 989 ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */
957 ALLOWED_ON_ABSENT_FS = 2 << 0, /* ops processed on absent fs */ 990 ALLOWED_ON_ABSENT_FS = 1 << 1, /* ops processed on absent fs */
958 ALLOWED_AS_FIRST_OP = 3 << 0, /* ops reqired first in compound */ 991 ALLOWED_AS_FIRST_OP = 1 << 2, /* ops reqired first in compound */
992 /* For rfc 5661 section 2.6.3.1.1: */
993 OP_HANDLES_WRONGSEC = 1 << 3,
994 OP_IS_PUTFH_LIKE = 1 << 4,
959}; 995};
960 996
961struct nfsd4_operation { 997struct nfsd4_operation {
@@ -974,8 +1010,8 @@ static const char *nfsd4_op_name(unsigned opnum);
974 * Also note, enforced elsewhere: 1010 * Also note, enforced elsewhere:
975 * - SEQUENCE other than as first op results in 1011 * - SEQUENCE other than as first op results in
976 * NFS4ERR_SEQUENCE_POS. (Enforced in nfsd4_sequence().) 1012 * NFS4ERR_SEQUENCE_POS. (Enforced in nfsd4_sequence().)
977 * - BIND_CONN_TO_SESSION must be the only op in its compound 1013 * - BIND_CONN_TO_SESSION must be the only op in its compound.
978 * (Will be enforced in nfsd4_bind_conn_to_session().) 1014 * (Enforced in nfsd4_bind_conn_to_session().)
979 * - DESTROY_SESSION must be the final operation in a compound, if 1015 * - DESTROY_SESSION must be the final operation in a compound, if
980 * sessionid's in SEQUENCE and DESTROY_SESSION are the same. 1016 * sessionid's in SEQUENCE and DESTROY_SESSION are the same.
981 * (Enforced in nfsd4_destroy_session().) 1017 * (Enforced in nfsd4_destroy_session().)
@@ -1001,6 +1037,44 @@ static __be32 nfs41_check_op_ordering(struct nfsd4_compoundargs *args)
1001 return nfs_ok; 1037 return nfs_ok;
1002} 1038}
1003 1039
1040static inline struct nfsd4_operation *OPDESC(struct nfsd4_op *op)
1041{
1042 return &nfsd4_ops[op->opnum];
1043}
1044
1045static bool need_wrongsec_check(struct svc_rqst *rqstp)
1046{
1047 struct nfsd4_compoundres *resp = rqstp->rq_resp;
1048 struct nfsd4_compoundargs *argp = rqstp->rq_argp;
1049 struct nfsd4_op *this = &argp->ops[resp->opcnt - 1];
1050 struct nfsd4_op *next = &argp->ops[resp->opcnt];
1051 struct nfsd4_operation *thisd;
1052 struct nfsd4_operation *nextd;
1053
1054 thisd = OPDESC(this);
1055 /*
1056 * Most ops check wronsec on our own; only the putfh-like ops
1057 * have special rules.
1058 */
1059 if (!(thisd->op_flags & OP_IS_PUTFH_LIKE))
1060 return false;
1061 /*
1062 * rfc 5661 2.6.3.1.1.6: don't bother erroring out a
1063 * put-filehandle operation if we're not going to use the
1064 * result:
1065 */
1066 if (argp->opcnt == resp->opcnt)
1067 return false;
1068
1069 nextd = OPDESC(next);
1070 /*
1071 * Rest of 2.6.3.1.1: certain operations will return WRONGSEC
1072 * errors themselves as necessary; others should check for them
1073 * now:
1074 */
1075 return !(nextd->op_flags & OP_HANDLES_WRONGSEC);
1076}
1077
1004/* 1078/*
1005 * COMPOUND call. 1079 * COMPOUND call.
1006 */ 1080 */
@@ -1031,8 +1105,11 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
1031 resp->cstate.session = NULL; 1105 resp->cstate.session = NULL;
1032 fh_init(&resp->cstate.current_fh, NFS4_FHSIZE); 1106 fh_init(&resp->cstate.current_fh, NFS4_FHSIZE);
1033 fh_init(&resp->cstate.save_fh, NFS4_FHSIZE); 1107 fh_init(&resp->cstate.save_fh, NFS4_FHSIZE);
1034 /* Use the deferral mechanism only for NFSv4.0 compounds */ 1108 /*
1035 rqstp->rq_usedeferral = (args->minorversion == 0); 1109 * Don't use the deferral mechanism for NFSv4; compounds make it
1110 * too hard to avoid non-idempotency problems.
1111 */
1112 rqstp->rq_usedeferral = 0;
1036 1113
1037 /* 1114 /*
1038 * According to RFC3010, this takes precedence over all other errors. 1115 * According to RFC3010, this takes precedence over all other errors.
@@ -1075,7 +1152,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
1075 goto encode_op; 1152 goto encode_op;
1076 } 1153 }
1077 1154
1078 opdesc = &nfsd4_ops[op->opnum]; 1155 opdesc = OPDESC(op);
1079 1156
1080 if (!cstate->current_fh.fh_dentry) { 1157 if (!cstate->current_fh.fh_dentry) {
1081 if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) { 1158 if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
@@ -1093,6 +1170,9 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
1093 else 1170 else
1094 BUG_ON(op->status == nfs_ok); 1171 BUG_ON(op->status == nfs_ok);
1095 1172
1173 if (!op->status && need_wrongsec_check(rqstp))
1174 op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp);
1175
1096encode_op: 1176encode_op:
1097 /* Only from SEQUENCE */ 1177 /* Only from SEQUENCE */
1098 if (resp->cstate.status == nfserr_replay_cache) { 1178 if (resp->cstate.status == nfserr_replay_cache) {
@@ -1123,10 +1203,6 @@ encode_op:
1123 1203
1124 nfsd4_increment_op_stats(op->opnum); 1204 nfsd4_increment_op_stats(op->opnum);
1125 } 1205 }
1126 if (!rqstp->rq_usedeferral && status == nfserr_dropit) {
1127 dprintk("%s Dropit - send NFS4ERR_DELAY\n", __func__);
1128 status = nfserr_jukebox;
1129 }
1130 1206
1131 resp->cstate.status = status; 1207 resp->cstate.status = status;
1132 fh_put(&resp->cstate.current_fh); 1208 fh_put(&resp->cstate.current_fh);
@@ -1188,10 +1264,12 @@ static struct nfsd4_operation nfsd4_ops[] = {
1188 }, 1264 },
1189 [OP_LOOKUP] = { 1265 [OP_LOOKUP] = {
1190 .op_func = (nfsd4op_func)nfsd4_lookup, 1266 .op_func = (nfsd4op_func)nfsd4_lookup,
1267 .op_flags = OP_HANDLES_WRONGSEC,
1191 .op_name = "OP_LOOKUP", 1268 .op_name = "OP_LOOKUP",
1192 }, 1269 },
1193 [OP_LOOKUPP] = { 1270 [OP_LOOKUPP] = {
1194 .op_func = (nfsd4op_func)nfsd4_lookupp, 1271 .op_func = (nfsd4op_func)nfsd4_lookupp,
1272 .op_flags = OP_HANDLES_WRONGSEC,
1195 .op_name = "OP_LOOKUPP", 1273 .op_name = "OP_LOOKUPP",
1196 }, 1274 },
1197 [OP_NVERIFY] = { 1275 [OP_NVERIFY] = {
@@ -1200,6 +1278,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
1200 }, 1278 },
1201 [OP_OPEN] = { 1279 [OP_OPEN] = {
1202 .op_func = (nfsd4op_func)nfsd4_open, 1280 .op_func = (nfsd4op_func)nfsd4_open,
1281 .op_flags = OP_HANDLES_WRONGSEC,
1203 .op_name = "OP_OPEN", 1282 .op_name = "OP_OPEN",
1204 }, 1283 },
1205 [OP_OPEN_CONFIRM] = { 1284 [OP_OPEN_CONFIRM] = {
@@ -1212,17 +1291,20 @@ static struct nfsd4_operation nfsd4_ops[] = {
1212 }, 1291 },
1213 [OP_PUTFH] = { 1292 [OP_PUTFH] = {
1214 .op_func = (nfsd4op_func)nfsd4_putfh, 1293 .op_func = (nfsd4op_func)nfsd4_putfh,
1215 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, 1294 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
1295 | OP_IS_PUTFH_LIKE,
1216 .op_name = "OP_PUTFH", 1296 .op_name = "OP_PUTFH",
1217 }, 1297 },
1218 [OP_PUTPUBFH] = { 1298 [OP_PUTPUBFH] = {
1219 .op_func = (nfsd4op_func)nfsd4_putrootfh, 1299 .op_func = (nfsd4op_func)nfsd4_putrootfh,
1220 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, 1300 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
1301 | OP_IS_PUTFH_LIKE,
1221 .op_name = "OP_PUTPUBFH", 1302 .op_name = "OP_PUTPUBFH",
1222 }, 1303 },
1223 [OP_PUTROOTFH] = { 1304 [OP_PUTROOTFH] = {
1224 .op_func = (nfsd4op_func)nfsd4_putrootfh, 1305 .op_func = (nfsd4op_func)nfsd4_putrootfh,
1225 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, 1306 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
1307 | OP_IS_PUTFH_LIKE,
1226 .op_name = "OP_PUTROOTFH", 1308 .op_name = "OP_PUTROOTFH",
1227 }, 1309 },
1228 [OP_READ] = { 1310 [OP_READ] = {
@@ -1252,15 +1334,18 @@ static struct nfsd4_operation nfsd4_ops[] = {
1252 }, 1334 },
1253 [OP_RESTOREFH] = { 1335 [OP_RESTOREFH] = {
1254 .op_func = (nfsd4op_func)nfsd4_restorefh, 1336 .op_func = (nfsd4op_func)nfsd4_restorefh,
1255 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS, 1337 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
1338 | OP_IS_PUTFH_LIKE,
1256 .op_name = "OP_RESTOREFH", 1339 .op_name = "OP_RESTOREFH",
1257 }, 1340 },
1258 [OP_SAVEFH] = { 1341 [OP_SAVEFH] = {
1259 .op_func = (nfsd4op_func)nfsd4_savefh, 1342 .op_func = (nfsd4op_func)nfsd4_savefh,
1343 .op_flags = OP_HANDLES_WRONGSEC,
1260 .op_name = "OP_SAVEFH", 1344 .op_name = "OP_SAVEFH",
1261 }, 1345 },
1262 [OP_SECINFO] = { 1346 [OP_SECINFO] = {
1263 .op_func = (nfsd4op_func)nfsd4_secinfo, 1347 .op_func = (nfsd4op_func)nfsd4_secinfo,
1348 .op_flags = OP_HANDLES_WRONGSEC,
1264 .op_name = "OP_SECINFO", 1349 .op_name = "OP_SECINFO",
1265 }, 1350 },
1266 [OP_SETATTR] = { 1351 [OP_SETATTR] = {
@@ -1297,6 +1382,11 @@ static struct nfsd4_operation nfsd4_ops[] = {
1297 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP, 1382 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
1298 .op_name = "OP_EXCHANGE_ID", 1383 .op_name = "OP_EXCHANGE_ID",
1299 }, 1384 },
1385 [OP_BIND_CONN_TO_SESSION] = {
1386 .op_func = (nfsd4op_func)nfsd4_bind_conn_to_session,
1387 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
1388 .op_name = "OP_BIND_CONN_TO_SESSION",
1389 },
1300 [OP_CREATE_SESSION] = { 1390 [OP_CREATE_SESSION] = {
1301 .op_func = (nfsd4op_func)nfsd4_create_session, 1391 .op_func = (nfsd4op_func)nfsd4_create_session,
1302 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP, 1392 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
@@ -1317,6 +1407,11 @@ static struct nfsd4_operation nfsd4_ops[] = {
1317 .op_flags = ALLOWED_WITHOUT_FH, 1407 .op_flags = ALLOWED_WITHOUT_FH,
1318 .op_name = "OP_RECLAIM_COMPLETE", 1408 .op_name = "OP_RECLAIM_COMPLETE",
1319 }, 1409 },
1410 [OP_SECINFO_NO_NAME] = {
1411 .op_func = (nfsd4op_func)nfsd4_secinfo_no_name,
1412 .op_flags = OP_HANDLES_WRONGSEC,
1413 .op_name = "OP_SECINFO_NO_NAME",
1414 },
1320}; 1415};
1321 1416
1322static const char *nfsd4_op_name(unsigned opnum) 1417static const char *nfsd4_op_name(unsigned opnum)
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 7e26caab2a26..ffb59ef6f82f 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -302,7 +302,6 @@ purge_old(struct dentry *parent, struct dentry *child)
302{ 302{
303 int status; 303 int status;
304 304
305 /* note: we currently use this path only for minorversion 0 */
306 if (nfs4_has_reclaimed_state(child->d_name.name, false)) 305 if (nfs4_has_reclaimed_state(child->d_name.name, false))
307 return 0; 306 return 0;
308 307
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index cf0d2ffb3c84..e98f3c2e9492 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -33,7 +33,7 @@
33*/ 33*/
34 34
35#include <linux/file.h> 35#include <linux/file.h>
36#include <linux/smp_lock.h> 36#include <linux/fs.h>
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>
@@ -148,7 +148,7 @@ static struct list_head ownerstr_hashtbl[OWNER_HASH_SIZE];
148/* hash table for nfs4_file */ 148/* hash table for nfs4_file */
149#define FILE_HASH_BITS 8 149#define FILE_HASH_BITS 8
150#define FILE_HASH_SIZE (1 << FILE_HASH_BITS) 150#define FILE_HASH_SIZE (1 << FILE_HASH_BITS)
151#define FILE_HASH_MASK (FILE_HASH_SIZE - 1) 151
152/* hash table for (open)nfs4_stateid */ 152/* hash table for (open)nfs4_stateid */
153#define STATEID_HASH_BITS 10 153#define STATEID_HASH_BITS 10
154#define STATEID_HASH_SIZE (1 << STATEID_HASH_BITS) 154#define STATEID_HASH_SIZE (1 << STATEID_HASH_BITS)
@@ -207,7 +207,6 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
207{ 207{
208 struct nfs4_delegation *dp; 208 struct nfs4_delegation *dp;
209 struct nfs4_file *fp = stp->st_file; 209 struct nfs4_file *fp = stp->st_file;
210 struct nfs4_cb_conn *cb = &stp->st_stateowner->so_client->cl_cb_conn;
211 210
212 dprintk("NFSD alloc_init_deleg\n"); 211 dprintk("NFSD alloc_init_deleg\n");
213 /* 212 /*
@@ -231,10 +230,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
231 dp->dl_client = clp; 230 dp->dl_client = clp;
232 get_nfs4_file(fp); 231 get_nfs4_file(fp);
233 dp->dl_file = fp; 232 dp->dl_file = fp;
234 nfs4_file_get_access(fp, O_RDONLY);
235 dp->dl_flock = NULL;
236 dp->dl_type = type; 233 dp->dl_type = type;
237 dp->dl_ident = cb->cb_ident;
238 dp->dl_stateid.si_boot = boot_time; 234 dp->dl_stateid.si_boot = boot_time;
239 dp->dl_stateid.si_stateownerid = current_delegid++; 235 dp->dl_stateid.si_stateownerid = current_delegid++;
240 dp->dl_stateid.si_fileid = 0; 236 dp->dl_stateid.si_fileid = 0;
@@ -242,8 +238,6 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
242 fh_copy_shallow(&dp->dl_fh, &current_fh->fh_handle); 238 fh_copy_shallow(&dp->dl_fh, &current_fh->fh_handle);
243 dp->dl_time = 0; 239 dp->dl_time = 0;
244 atomic_set(&dp->dl_count, 1); 240 atomic_set(&dp->dl_count, 1);
245 list_add(&dp->dl_perfile, &fp->fi_delegations);
246 list_add(&dp->dl_perclnt, &clp->cl_delegations);
247 INIT_WORK(&dp->dl_recall.cb_work, nfsd4_do_callback_rpc); 241 INIT_WORK(&dp->dl_recall.cb_work, nfsd4_do_callback_rpc);
248 return dp; 242 return dp;
249} 243}
@@ -259,32 +253,26 @@ nfs4_put_delegation(struct nfs4_delegation *dp)
259 } 253 }
260} 254}
261 255
262/* Remove the associated file_lock first, then remove the delegation. 256static void nfs4_put_deleg_lease(struct nfs4_file *fp)
263 * lease_modify() is called to remove the FS_LEASE file_lock from
264 * the i_flock list, eventually calling nfsd's lock_manager
265 * fl_release_callback.
266 */
267static void
268nfs4_close_delegation(struct nfs4_delegation *dp)
269{ 257{
270 struct file *filp = find_readable_file(dp->dl_file); 258 if (atomic_dec_and_test(&fp->fi_delegees)) {
271 259 vfs_setlease(fp->fi_deleg_file, F_UNLCK, &fp->fi_lease);
272 dprintk("NFSD: close_delegation dp %p\n",dp); 260 fp->fi_lease = NULL;
273 if (dp->dl_flock) 261 fput(fp->fi_deleg_file);
274 vfs_setlease(filp, F_UNLCK, &dp->dl_flock); 262 fp->fi_deleg_file = NULL;
275 nfs4_file_put_access(dp->dl_file, O_RDONLY); 263 }
276} 264}
277 265
278/* Called under the state lock. */ 266/* Called under the state lock. */
279static void 267static void
280unhash_delegation(struct nfs4_delegation *dp) 268unhash_delegation(struct nfs4_delegation *dp)
281{ 269{
282 list_del_init(&dp->dl_perfile);
283 list_del_init(&dp->dl_perclnt); 270 list_del_init(&dp->dl_perclnt);
284 spin_lock(&recall_lock); 271 spin_lock(&recall_lock);
272 list_del_init(&dp->dl_perfile);
285 list_del_init(&dp->dl_recall_lru); 273 list_del_init(&dp->dl_recall_lru);
286 spin_unlock(&recall_lock); 274 spin_unlock(&recall_lock);
287 nfs4_close_delegation(dp); 275 nfs4_put_deleg_lease(dp->dl_file);
288 nfs4_put_delegation(dp); 276 nfs4_put_delegation(dp);
289} 277}
290 278
@@ -329,64 +317,6 @@ static struct list_head unconf_id_hashtbl[CLIENT_HASH_SIZE];
329static struct list_head client_lru; 317static struct list_head client_lru;
330static struct list_head close_lru; 318static struct list_head close_lru;
331 319
332static void unhash_generic_stateid(struct nfs4_stateid *stp)
333{
334 list_del(&stp->st_hash);
335 list_del(&stp->st_perfile);
336 list_del(&stp->st_perstateowner);
337}
338
339static void free_generic_stateid(struct nfs4_stateid *stp)
340{
341 put_nfs4_file(stp->st_file);
342 kmem_cache_free(stateid_slab, stp);
343}
344
345static void release_lock_stateid(struct nfs4_stateid *stp)
346{
347 struct file *file;
348
349 unhash_generic_stateid(stp);
350 file = find_any_file(stp->st_file);
351 if (file)
352 locks_remove_posix(file, (fl_owner_t)stp->st_stateowner);
353 free_generic_stateid(stp);
354}
355
356static void unhash_lockowner(struct nfs4_stateowner *sop)
357{
358 struct nfs4_stateid *stp;
359
360 list_del(&sop->so_idhash);
361 list_del(&sop->so_strhash);
362 list_del(&sop->so_perstateid);
363 while (!list_empty(&sop->so_stateids)) {
364 stp = list_first_entry(&sop->so_stateids,
365 struct nfs4_stateid, st_perstateowner);
366 release_lock_stateid(stp);
367 }
368}
369
370static void release_lockowner(struct nfs4_stateowner *sop)
371{
372 unhash_lockowner(sop);
373 nfs4_put_stateowner(sop);
374}
375
376static void
377release_stateid_lockowners(struct nfs4_stateid *open_stp)
378{
379 struct nfs4_stateowner *lock_sop;
380
381 while (!list_empty(&open_stp->st_lockowners)) {
382 lock_sop = list_entry(open_stp->st_lockowners.next,
383 struct nfs4_stateowner, so_perstateid);
384 /* list_del(&open_stp->st_lockowners); */
385 BUG_ON(lock_sop->so_is_open_owner);
386 release_lockowner(lock_sop);
387 }
388}
389
390/* 320/*
391 * We store the NONE, READ, WRITE, and BOTH bits separately in the 321 * We store the NONE, READ, WRITE, and BOTH bits separately in the
392 * st_{access,deny}_bmap field of the stateid, in order to track not 322 * st_{access,deny}_bmap field of the stateid, in order to track not
@@ -459,13 +389,74 @@ static int nfs4_access_bmap_to_omode(struct nfs4_stateid *stp)
459 return nfs4_access_to_omode(access); 389 return nfs4_access_to_omode(access);
460} 390}
461 391
462static void release_open_stateid(struct nfs4_stateid *stp) 392static void unhash_generic_stateid(struct nfs4_stateid *stp)
393{
394 list_del(&stp->st_hash);
395 list_del(&stp->st_perfile);
396 list_del(&stp->st_perstateowner);
397}
398
399static void free_generic_stateid(struct nfs4_stateid *stp)
463{ 400{
464 int oflag = nfs4_access_bmap_to_omode(stp); 401 int oflag;
402
403 if (stp->st_access_bmap) {
404 oflag = nfs4_access_bmap_to_omode(stp);
405 nfs4_file_put_access(stp->st_file, oflag);
406 }
407 put_nfs4_file(stp->st_file);
408 kmem_cache_free(stateid_slab, stp);
409}
410
411static void release_lock_stateid(struct nfs4_stateid *stp)
412{
413 struct file *file;
465 414
466 unhash_generic_stateid(stp); 415 unhash_generic_stateid(stp);
416 file = find_any_file(stp->st_file);
417 if (file)
418 locks_remove_posix(file, (fl_owner_t)stp->st_stateowner);
419 free_generic_stateid(stp);
420}
421
422static void unhash_lockowner(struct nfs4_stateowner *sop)
423{
424 struct nfs4_stateid *stp;
425
426 list_del(&sop->so_idhash);
427 list_del(&sop->so_strhash);
428 list_del(&sop->so_perstateid);
429 while (!list_empty(&sop->so_stateids)) {
430 stp = list_first_entry(&sop->so_stateids,
431 struct nfs4_stateid, st_perstateowner);
432 release_lock_stateid(stp);
433 }
434}
435
436static void release_lockowner(struct nfs4_stateowner *sop)
437{
438 unhash_lockowner(sop);
439 nfs4_put_stateowner(sop);
440}
441
442static void
443release_stateid_lockowners(struct nfs4_stateid *open_stp)
444{
445 struct nfs4_stateowner *lock_sop;
446
447 while (!list_empty(&open_stp->st_lockowners)) {
448 lock_sop = list_entry(open_stp->st_lockowners.next,
449 struct nfs4_stateowner, so_perstateid);
450 /* list_del(&open_stp->st_lockowners); */
451 BUG_ON(lock_sop->so_is_open_owner);
452 release_lockowner(lock_sop);
453 }
454}
455
456static void release_open_stateid(struct nfs4_stateid *stp)
457{
458 unhash_generic_stateid(stp);
467 release_stateid_lockowners(stp); 459 release_stateid_lockowners(stp);
468 nfs4_file_put_access(stp->st_file, oflag);
469 free_generic_stateid(stp); 460 free_generic_stateid(stp);
470} 461}
471 462
@@ -535,171 +526,279 @@ gen_sessionid(struct nfsd4_session *ses)
535 */ 526 */
536#define NFSD_MIN_HDR_SEQ_SZ (24 + 12 + 44) 527#define NFSD_MIN_HDR_SEQ_SZ (24 + 12 + 44)
537 528
529static void
530free_session_slots(struct nfsd4_session *ses)
531{
532 int i;
533
534 for (i = 0; i < ses->se_fchannel.maxreqs; i++)
535 kfree(ses->se_slots[i]);
536}
537
538/* 538/*
539 * Give the client the number of ca_maxresponsesize_cached slots it 539 * We don't actually need to cache the rpc and session headers, so we
540 * requests, of size bounded by NFSD_SLOT_CACHE_SIZE, 540 * can allocate a little less for each slot:
541 * NFSD_MAX_MEM_PER_SESSION, and nfsd_drc_max_mem. Do not allow more 541 */
542 * than NFSD_MAX_SLOTS_PER_SESSION. 542static inline int slot_bytes(struct nfsd4_channel_attrs *ca)
543 * 543{
544 * If we run out of reserved DRC memory we should (up to a point) 544 return ca->maxresp_cached - NFSD_MIN_HDR_SEQ_SZ;
545}
546
547static int nfsd4_sanitize_slot_size(u32 size)
548{
549 size -= NFSD_MIN_HDR_SEQ_SZ; /* We don't cache the rpc header */
550 size = min_t(u32, size, NFSD_SLOT_CACHE_SIZE);
551
552 return size;
553}
554
555/*
556 * XXX: If we run out of reserved DRC memory we could (up to a point)
545 * re-negotiate active sessions and reduce their slot usage to make 557 * re-negotiate active sessions and reduce their slot usage to make
546 * rooom for new connections. For now we just fail the create session. 558 * rooom for new connections. For now we just fail the create session.
547 */ 559 */
548static int set_forechannel_drc_size(struct nfsd4_channel_attrs *fchan) 560static int nfsd4_get_drc_mem(int slotsize, u32 num)
549{ 561{
550 int mem, size = fchan->maxresp_cached; 562 int avail;
551 563
552 if (fchan->maxreqs < 1) 564 num = min_t(u32, num, NFSD_MAX_SLOTS_PER_SESSION);
553 return nfserr_inval;
554 565
555 if (size < NFSD_MIN_HDR_SEQ_SZ) 566 spin_lock(&nfsd_drc_lock);
556 size = NFSD_MIN_HDR_SEQ_SZ; 567 avail = min_t(int, NFSD_MAX_MEM_PER_SESSION,
557 size -= NFSD_MIN_HDR_SEQ_SZ; 568 nfsd_drc_max_mem - nfsd_drc_mem_used);
558 if (size > NFSD_SLOT_CACHE_SIZE) 569 num = min_t(int, num, avail / slotsize);
559 size = NFSD_SLOT_CACHE_SIZE; 570 nfsd_drc_mem_used += num * slotsize;
560 571 spin_unlock(&nfsd_drc_lock);
561 /* bound the maxreqs by NFSD_MAX_MEM_PER_SESSION */ 572
562 mem = fchan->maxreqs * size; 573 return num;
563 if (mem > NFSD_MAX_MEM_PER_SESSION) { 574}
564 fchan->maxreqs = NFSD_MAX_MEM_PER_SESSION / size;
565 if (fchan->maxreqs > NFSD_MAX_SLOTS_PER_SESSION)
566 fchan->maxreqs = NFSD_MAX_SLOTS_PER_SESSION;
567 mem = fchan->maxreqs * size;
568 }
569 575
576static void nfsd4_put_drc_mem(int slotsize, int num)
577{
570 spin_lock(&nfsd_drc_lock); 578 spin_lock(&nfsd_drc_lock);
571 /* bound the total session drc memory ussage */ 579 nfsd_drc_mem_used -= slotsize * num;
572 if (mem + nfsd_drc_mem_used > nfsd_drc_max_mem) {
573 fchan->maxreqs = (nfsd_drc_max_mem - nfsd_drc_mem_used) / size;
574 mem = fchan->maxreqs * size;
575 }
576 nfsd_drc_mem_used += mem;
577 spin_unlock(&nfsd_drc_lock); 580 spin_unlock(&nfsd_drc_lock);
581}
578 582
579 if (fchan->maxreqs == 0) 583static struct nfsd4_session *alloc_session(int slotsize, int numslots)
580 return nfserr_jukebox; 584{
585 struct nfsd4_session *new;
586 int mem, i;
581 587
582 fchan->maxresp_cached = size + NFSD_MIN_HDR_SEQ_SZ; 588 BUILD_BUG_ON(NFSD_MAX_SLOTS_PER_SESSION * sizeof(struct nfsd4_slot *)
583 return 0; 589 + sizeof(struct nfsd4_session) > PAGE_SIZE);
590 mem = numslots * sizeof(struct nfsd4_slot *);
591
592 new = kzalloc(sizeof(*new) + mem, GFP_KERNEL);
593 if (!new)
594 return NULL;
595 /* allocate each struct nfsd4_slot and data cache in one piece */
596 for (i = 0; i < numslots; i++) {
597 mem = sizeof(struct nfsd4_slot) + slotsize;
598 new->se_slots[i] = kzalloc(mem, GFP_KERNEL);
599 if (!new->se_slots[i])
600 goto out_free;
601 }
602 return new;
603out_free:
604 while (i--)
605 kfree(new->se_slots[i]);
606 kfree(new);
607 return NULL;
584} 608}
585 609
586/* 610static void init_forechannel_attrs(struct nfsd4_channel_attrs *new, struct nfsd4_channel_attrs *req, int numslots, int slotsize)
587 * fchan holds the client values on input, and the server values on output
588 * sv_max_mesg is the maximum payload plus one page for overhead.
589 */
590static int init_forechannel_attrs(struct svc_rqst *rqstp,
591 struct nfsd4_channel_attrs *session_fchan,
592 struct nfsd4_channel_attrs *fchan)
593{ 611{
594 int status = 0; 612 u32 maxrpc = nfsd_serv->sv_max_mesg;
595 __u32 maxcount = nfsd_serv->sv_max_mesg;
596 613
597 /* headerpadsz set to zero in encode routine */ 614 new->maxreqs = numslots;
615 new->maxresp_cached = min_t(u32, req->maxresp_cached,
616 slotsize + NFSD_MIN_HDR_SEQ_SZ);
617 new->maxreq_sz = min_t(u32, req->maxreq_sz, maxrpc);
618 new->maxresp_sz = min_t(u32, req->maxresp_sz, maxrpc);
619 new->maxops = min_t(u32, req->maxops, NFSD_MAX_OPS_PER_COMPOUND);
620}
598 621
599 /* Use the client's max request and max response size if possible */ 622static void free_conn(struct nfsd4_conn *c)
600 if (fchan->maxreq_sz > maxcount) 623{
601 fchan->maxreq_sz = maxcount; 624 svc_xprt_put(c->cn_xprt);
602 session_fchan->maxreq_sz = fchan->maxreq_sz; 625 kfree(c);
626}
603 627
604 if (fchan->maxresp_sz > maxcount) 628static void nfsd4_conn_lost(struct svc_xpt_user *u)
605 fchan->maxresp_sz = maxcount; 629{
606 session_fchan->maxresp_sz = fchan->maxresp_sz; 630 struct nfsd4_conn *c = container_of(u, struct nfsd4_conn, cn_xpt_user);
631 struct nfs4_client *clp = c->cn_session->se_client;
607 632
608 /* Use the client's maxops if possible */ 633 spin_lock(&clp->cl_lock);
609 if (fchan->maxops > NFSD_MAX_OPS_PER_COMPOUND) 634 if (!list_empty(&c->cn_persession)) {
610 fchan->maxops = NFSD_MAX_OPS_PER_COMPOUND; 635 list_del(&c->cn_persession);
611 session_fchan->maxops = fchan->maxops; 636 free_conn(c);
637 }
638 spin_unlock(&clp->cl_lock);
639 nfsd4_probe_callback(clp);
640}
612 641
613 /* FIXME: Error means no more DRC pages so the server should 642static struct nfsd4_conn *alloc_conn(struct svc_rqst *rqstp, u32 flags)
614 * recover pages from existing sessions. For now fail session 643{
615 * creation. 644 struct nfsd4_conn *conn;
616 */
617 status = set_forechannel_drc_size(fchan);
618 645
619 session_fchan->maxresp_cached = fchan->maxresp_cached; 646 conn = kmalloc(sizeof(struct nfsd4_conn), GFP_KERNEL);
620 session_fchan->maxreqs = fchan->maxreqs; 647 if (!conn)
648 return NULL;
649 svc_xprt_get(rqstp->rq_xprt);
650 conn->cn_xprt = rqstp->rq_xprt;
651 conn->cn_flags = flags;
652 INIT_LIST_HEAD(&conn->cn_xpt_user.list);
653 return conn;
654}
621 655
622 dprintk("%s status %d\n", __func__, status); 656static void __nfsd4_hash_conn(struct nfsd4_conn *conn, struct nfsd4_session *ses)
623 return status; 657{
658 conn->cn_session = ses;
659 list_add(&conn->cn_persession, &ses->se_conns);
624} 660}
625 661
626static void 662static void nfsd4_hash_conn(struct nfsd4_conn *conn, struct nfsd4_session *ses)
627free_session_slots(struct nfsd4_session *ses)
628{ 663{
629 int i; 664 struct nfs4_client *clp = ses->se_client;
630 665
631 for (i = 0; i < ses->se_fchannel.maxreqs; i++) 666 spin_lock(&clp->cl_lock);
632 kfree(ses->se_slots[i]); 667 __nfsd4_hash_conn(conn, ses);
668 spin_unlock(&clp->cl_lock);
633} 669}
634 670
635/* 671static int nfsd4_register_conn(struct nfsd4_conn *conn)
636 * We don't actually need to cache the rpc and session headers, so we
637 * can allocate a little less for each slot:
638 */
639static inline int slot_bytes(struct nfsd4_channel_attrs *ca)
640{ 672{
641 return ca->maxresp_cached - NFSD_MIN_HDR_SEQ_SZ; 673 conn->cn_xpt_user.callback = nfsd4_conn_lost;
674 return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user);
642} 675}
643 676
644static int 677static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses, u32 dir)
645alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp,
646 struct nfsd4_create_session *cses)
647{ 678{
648 struct nfsd4_session *new, tmp; 679 struct nfsd4_conn *conn;
649 struct nfsd4_slot *sp; 680 int ret;
650 int idx, slotsize, cachesize, i;
651 int status;
652 681
653 memset(&tmp, 0, sizeof(tmp)); 682 conn = alloc_conn(rqstp, dir);
683 if (!conn)
684 return nfserr_jukebox;
685 nfsd4_hash_conn(conn, ses);
686 ret = nfsd4_register_conn(conn);
687 if (ret)
688 /* oops; xprt is already down: */
689 nfsd4_conn_lost(&conn->cn_xpt_user);
690 return nfs_ok;
691}
654 692
655 /* FIXME: For now, we just accept the client back channel attributes. */ 693static __be32 nfsd4_new_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_session *ses)
656 tmp.se_bchannel = cses->back_channel; 694{
657 status = init_forechannel_attrs(rqstp, &tmp.se_fchannel, 695 u32 dir = NFS4_CDFC4_FORE;
658 &cses->fore_channel);
659 if (status)
660 goto out;
661 696
662 BUILD_BUG_ON(NFSD_MAX_SLOTS_PER_SESSION * sizeof(struct nfsd4_slot) 697 if (ses->se_flags & SESSION4_BACK_CHAN)
663 + sizeof(struct nfsd4_session) > PAGE_SIZE); 698 dir |= NFS4_CDFC4_BACK;
664 699
665 status = nfserr_jukebox; 700 return nfsd4_new_conn(rqstp, ses, dir);
666 /* allocate struct nfsd4_session and slot table pointers in one piece */ 701}
667 slotsize = tmp.se_fchannel.maxreqs * sizeof(struct nfsd4_slot *);
668 new = kzalloc(sizeof(*new) + slotsize, GFP_KERNEL);
669 if (!new)
670 goto out;
671 702
672 memcpy(new, &tmp, sizeof(*new)); 703/* must be called under client_lock */
704static void nfsd4_del_conns(struct nfsd4_session *s)
705{
706 struct nfs4_client *clp = s->se_client;
707 struct nfsd4_conn *c;
673 708
674 /* allocate each struct nfsd4_slot and data cache in one piece */ 709 spin_lock(&clp->cl_lock);
675 cachesize = slot_bytes(&new->se_fchannel); 710 while (!list_empty(&s->se_conns)) {
676 for (i = 0; i < new->se_fchannel.maxreqs; i++) { 711 c = list_first_entry(&s->se_conns, struct nfsd4_conn, cn_persession);
677 sp = kzalloc(sizeof(*sp) + cachesize, GFP_KERNEL); 712 list_del_init(&c->cn_persession);
678 if (!sp) 713 spin_unlock(&clp->cl_lock);
679 goto out_free; 714
680 new->se_slots[i] = sp; 715 unregister_xpt_user(c->cn_xprt, &c->cn_xpt_user);
716 free_conn(c);
717
718 spin_lock(&clp->cl_lock);
719 }
720 spin_unlock(&clp->cl_lock);
721}
722
723void free_session(struct kref *kref)
724{
725 struct nfsd4_session *ses;
726 int mem;
727
728 ses = container_of(kref, struct nfsd4_session, se_ref);
729 nfsd4_del_conns(ses);
730 spin_lock(&nfsd_drc_lock);
731 mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel);
732 nfsd_drc_mem_used -= mem;
733 spin_unlock(&nfsd_drc_lock);
734 free_session_slots(ses);
735 kfree(ses);
736}
737
738static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses)
739{
740 struct nfsd4_session *new;
741 struct nfsd4_channel_attrs *fchan = &cses->fore_channel;
742 int numslots, slotsize;
743 int status;
744 int idx;
745
746 /*
747 * Note decreasing slot size below client's request may
748 * make it difficult for client to function correctly, whereas
749 * decreasing the number of slots will (just?) affect
750 * performance. When short on memory we therefore prefer to
751 * decrease number of slots instead of their size.
752 */
753 slotsize = nfsd4_sanitize_slot_size(fchan->maxresp_cached);
754 numslots = nfsd4_get_drc_mem(slotsize, fchan->maxreqs);
755 if (numslots < 1)
756 return NULL;
757
758 new = alloc_session(slotsize, numslots);
759 if (!new) {
760 nfsd4_put_drc_mem(slotsize, fchan->maxreqs);
761 return NULL;
681 } 762 }
763 init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize);
682 764
683 new->se_client = clp; 765 new->se_client = clp;
684 gen_sessionid(new); 766 gen_sessionid(new);
685 idx = hash_sessionid(&new->se_sessionid);
686 memcpy(clp->cl_sessionid.data, new->se_sessionid.data,
687 NFS4_MAX_SESSIONID_LEN);
688 767
768 INIT_LIST_HEAD(&new->se_conns);
769
770 new->se_cb_seq_nr = 1;
689 new->se_flags = cses->flags; 771 new->se_flags = cses->flags;
772 new->se_cb_prog = cses->callback_prog;
690 kref_init(&new->se_ref); 773 kref_init(&new->se_ref);
774 idx = hash_sessionid(&new->se_sessionid);
691 spin_lock(&client_lock); 775 spin_lock(&client_lock);
692 list_add(&new->se_hash, &sessionid_hashtbl[idx]); 776 list_add(&new->se_hash, &sessionid_hashtbl[idx]);
777 spin_lock(&clp->cl_lock);
693 list_add(&new->se_perclnt, &clp->cl_sessions); 778 list_add(&new->se_perclnt, &clp->cl_sessions);
779 spin_unlock(&clp->cl_lock);
694 spin_unlock(&client_lock); 780 spin_unlock(&client_lock);
695 781
696 status = nfs_ok; 782 status = nfsd4_new_conn_from_crses(rqstp, new);
697out: 783 /* whoops: benny points out, status is ignored! (err, or bogus) */
698 return status; 784 if (status) {
699out_free: 785 free_session(&new->se_ref);
700 free_session_slots(new); 786 return NULL;
701 kfree(new); 787 }
702 goto out; 788 if (cses->flags & SESSION4_BACK_CHAN) {
789 struct sockaddr *sa = svc_addr(rqstp);
790 /*
791 * This is a little silly; with sessions there's no real
792 * use for the callback address. Use the peer address
793 * as a reasonable default for now, but consider fixing
794 * the rpc client not to require an address in the
795 * future:
796 */
797 rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa);
798 clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
799 }
800 nfsd4_probe_callback(clp);
801 return new;
703} 802}
704 803
705/* caller must hold client_lock */ 804/* caller must hold client_lock */
@@ -728,22 +827,9 @@ static void
728unhash_session(struct nfsd4_session *ses) 827unhash_session(struct nfsd4_session *ses)
729{ 828{
730 list_del(&ses->se_hash); 829 list_del(&ses->se_hash);
830 spin_lock(&ses->se_client->cl_lock);
731 list_del(&ses->se_perclnt); 831 list_del(&ses->se_perclnt);
732} 832 spin_unlock(&ses->se_client->cl_lock);
733
734void
735free_session(struct kref *kref)
736{
737 struct nfsd4_session *ses;
738 int mem;
739
740 ses = container_of(kref, struct nfsd4_session, se_ref);
741 spin_lock(&nfsd_drc_lock);
742 mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel);
743 nfsd_drc_mem_used -= mem;
744 spin_unlock(&nfsd_drc_lock);
745 free_session_slots(ses);
746 kfree(ses);
747} 833}
748 834
749/* must be called under the client_lock */ 835/* must be called under the client_lock */
@@ -812,6 +898,13 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
812static inline void 898static inline void
813free_client(struct nfs4_client *clp) 899free_client(struct nfs4_client *clp)
814{ 900{
901 while (!list_empty(&clp->cl_sessions)) {
902 struct nfsd4_session *ses;
903 ses = list_entry(clp->cl_sessions.next, struct nfsd4_session,
904 se_perclnt);
905 list_del(&ses->se_perclnt);
906 nfsd4_put_session(ses);
907 }
815 if (clp->cl_cred.cr_group_info) 908 if (clp->cl_cred.cr_group_info)
816 put_group_info(clp->cl_cred.cr_group_info); 909 put_group_info(clp->cl_cred.cr_group_info);
817 kfree(clp->cl_principal); 910 kfree(clp->cl_principal);
@@ -838,15 +931,14 @@ release_session_client(struct nfsd4_session *session)
838static inline void 931static inline void
839unhash_client_locked(struct nfs4_client *clp) 932unhash_client_locked(struct nfs4_client *clp)
840{ 933{
934 struct nfsd4_session *ses;
935
841 mark_client_expired(clp); 936 mark_client_expired(clp);
842 list_del(&clp->cl_lru); 937 list_del(&clp->cl_lru);
843 while (!list_empty(&clp->cl_sessions)) { 938 spin_lock(&clp->cl_lock);
844 struct nfsd4_session *ses; 939 list_for_each_entry(ses, &clp->cl_sessions, se_perclnt)
845 ses = list_entry(clp->cl_sessions.next, struct nfsd4_session, 940 list_del_init(&ses->se_hash);
846 se_perclnt); 941 spin_unlock(&clp->cl_lock);
847 unhash_session(ses);
848 nfsd4_put_session(ses);
849 }
850} 942}
851 943
852static void 944static void
@@ -860,8 +952,6 @@ expire_client(struct nfs4_client *clp)
860 spin_lock(&recall_lock); 952 spin_lock(&recall_lock);
861 while (!list_empty(&clp->cl_delegations)) { 953 while (!list_empty(&clp->cl_delegations)) {
862 dp = list_entry(clp->cl_delegations.next, struct nfs4_delegation, dl_perclnt); 954 dp = list_entry(clp->cl_delegations.next, struct nfs4_delegation, dl_perclnt);
863 dprintk("NFSD: expire client. dp %p, fp %p\n", dp,
864 dp->dl_flock);
865 list_del_init(&dp->dl_perclnt); 955 list_del_init(&dp->dl_perclnt);
866 list_move(&dp->dl_recall_lru, &reaplist); 956 list_move(&dp->dl_recall_lru, &reaplist);
867 } 957 }
@@ -875,7 +965,7 @@ expire_client(struct nfs4_client *clp)
875 sop = list_entry(clp->cl_openowners.next, struct nfs4_stateowner, so_perclient); 965 sop = list_entry(clp->cl_openowners.next, struct nfs4_stateowner, so_perclient);
876 release_openowner(sop); 966 release_openowner(sop);
877 } 967 }
878 nfsd4_set_callback_client(clp, NULL); 968 nfsd4_shutdown_callback(clp);
879 if (clp->cl_cb_conn.cb_xprt) 969 if (clp->cl_cb_conn.cb_xprt)
880 svc_xprt_put(clp->cl_cb_conn.cb_xprt); 970 svc_xprt_put(clp->cl_cb_conn.cb_xprt);
881 list_del(&clp->cl_idhash); 971 list_del(&clp->cl_idhash);
@@ -960,6 +1050,8 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
960 if (clp == NULL) 1050 if (clp == NULL)
961 return NULL; 1051 return NULL;
962 1052
1053 INIT_LIST_HEAD(&clp->cl_sessions);
1054
963 princ = svc_gss_principal(rqstp); 1055 princ = svc_gss_principal(rqstp);
964 if (princ) { 1056 if (princ) {
965 clp->cl_principal = kstrdup(princ, GFP_KERNEL); 1057 clp->cl_principal = kstrdup(princ, GFP_KERNEL);
@@ -971,13 +1063,15 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
971 1063
972 memcpy(clp->cl_recdir, recdir, HEXDIR_LEN); 1064 memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
973 atomic_set(&clp->cl_refcount, 0); 1065 atomic_set(&clp->cl_refcount, 0);
974 atomic_set(&clp->cl_cb_set, 0); 1066 clp->cl_cb_state = NFSD4_CB_UNKNOWN;
975 INIT_LIST_HEAD(&clp->cl_idhash); 1067 INIT_LIST_HEAD(&clp->cl_idhash);
976 INIT_LIST_HEAD(&clp->cl_strhash); 1068 INIT_LIST_HEAD(&clp->cl_strhash);
977 INIT_LIST_HEAD(&clp->cl_openowners); 1069 INIT_LIST_HEAD(&clp->cl_openowners);
978 INIT_LIST_HEAD(&clp->cl_delegations); 1070 INIT_LIST_HEAD(&clp->cl_delegations);
979 INIT_LIST_HEAD(&clp->cl_sessions);
980 INIT_LIST_HEAD(&clp->cl_lru); 1071 INIT_LIST_HEAD(&clp->cl_lru);
1072 INIT_LIST_HEAD(&clp->cl_callbacks);
1073 spin_lock_init(&clp->cl_lock);
1074 INIT_WORK(&clp->cl_cb_null.cb_work, nfsd4_do_callback_rpc);
981 clp->cl_time = get_seconds(); 1075 clp->cl_time = get_seconds();
982 clear_bit(0, &clp->cl_cb_slot_busy); 1076 clear_bit(0, &clp->cl_cb_slot_busy);
983 rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table"); 1077 rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table");
@@ -986,7 +1080,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
986 clp->cl_flavor = rqstp->rq_flavor; 1080 clp->cl_flavor = rqstp->rq_flavor;
987 copy_cred(&clp->cl_cred, &rqstp->rq_cred); 1081 copy_cred(&clp->cl_cred, &rqstp->rq_cred);
988 gen_confirm(clp); 1082 gen_confirm(clp);
989 1083 clp->cl_cb_session = NULL;
990 return clp; 1084 return clp;
991} 1085}
992 1086
@@ -1051,54 +1145,55 @@ find_unconfirmed_client(clientid_t *clid)
1051 return NULL; 1145 return NULL;
1052} 1146}
1053 1147
1054/* 1148static bool clp_used_exchangeid(struct nfs4_client *clp)
1055 * Return 1 iff clp's clientid establishment method matches the use_exchange_id
1056 * parameter. Matching is based on the fact the at least one of the
1057 * EXCHGID4_FLAG_USE_{NON_PNFS,PNFS_MDS,PNFS_DS} flags must be set for v4.1
1058 *
1059 * FIXME: we need to unify the clientid namespaces for nfsv4.x
1060 * and correctly deal with client upgrade/downgrade in EXCHANGE_ID
1061 * and SET_CLIENTID{,_CONFIRM}
1062 */
1063static inline int
1064match_clientid_establishment(struct nfs4_client *clp, bool use_exchange_id)
1065{ 1149{
1066 bool has_exchange_flags = (clp->cl_exchange_flags != 0); 1150 return clp->cl_exchange_flags != 0;
1067 return use_exchange_id == has_exchange_flags; 1151}
1068}
1069 1152
1070static struct nfs4_client * 1153static struct nfs4_client *
1071find_confirmed_client_by_str(const char *dname, unsigned int hashval, 1154find_confirmed_client_by_str(const char *dname, unsigned int hashval)
1072 bool use_exchange_id)
1073{ 1155{
1074 struct nfs4_client *clp; 1156 struct nfs4_client *clp;
1075 1157
1076 list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) { 1158 list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) {
1077 if (same_name(clp->cl_recdir, dname) && 1159 if (same_name(clp->cl_recdir, dname))
1078 match_clientid_establishment(clp, use_exchange_id))
1079 return clp; 1160 return clp;
1080 } 1161 }
1081 return NULL; 1162 return NULL;
1082} 1163}
1083 1164
1084static struct nfs4_client * 1165static struct nfs4_client *
1085find_unconfirmed_client_by_str(const char *dname, unsigned int hashval, 1166find_unconfirmed_client_by_str(const char *dname, unsigned int hashval)
1086 bool use_exchange_id)
1087{ 1167{
1088 struct nfs4_client *clp; 1168 struct nfs4_client *clp;
1089 1169
1090 list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) { 1170 list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) {
1091 if (same_name(clp->cl_recdir, dname) && 1171 if (same_name(clp->cl_recdir, dname))
1092 match_clientid_establishment(clp, use_exchange_id))
1093 return clp; 1172 return clp;
1094 } 1173 }
1095 return NULL; 1174 return NULL;
1096} 1175}
1097 1176
1177static void rpc_svcaddr2sockaddr(struct sockaddr *sa, unsigned short family, union svc_addr_u *svcaddr)
1178{
1179 switch (family) {
1180 case AF_INET:
1181 ((struct sockaddr_in *)sa)->sin_family = AF_INET;
1182 ((struct sockaddr_in *)sa)->sin_addr = svcaddr->addr;
1183 return;
1184 case AF_INET6:
1185 ((struct sockaddr_in6 *)sa)->sin6_family = AF_INET6;
1186 ((struct sockaddr_in6 *)sa)->sin6_addr = svcaddr->addr6;
1187 return;
1188 }
1189}
1190
1098static void 1191static void
1099gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, u32 scopeid) 1192gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, struct svc_rqst *rqstp)
1100{ 1193{
1101 struct nfs4_cb_conn *cb = &clp->cl_cb_conn; 1194 struct nfs4_cb_conn *conn = &clp->cl_cb_conn;
1195 struct sockaddr *sa = svc_addr(rqstp);
1196 u32 scopeid = rpc_get_scope_id(sa);
1102 unsigned short expected_family; 1197 unsigned short expected_family;
1103 1198
1104 /* Currently, we only support tcp and tcp6 for the callback channel */ 1199 /* Currently, we only support tcp and tcp6 for the callback channel */
@@ -1111,24 +1206,24 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, u32 scopeid)
1111 else 1206 else
1112 goto out_err; 1207 goto out_err;
1113 1208
1114 cb->cb_addrlen = rpc_uaddr2sockaddr(se->se_callback_addr_val, 1209 conn->cb_addrlen = rpc_uaddr2sockaddr(se->se_callback_addr_val,
1115 se->se_callback_addr_len, 1210 se->se_callback_addr_len,
1116 (struct sockaddr *) &cb->cb_addr, 1211 (struct sockaddr *)&conn->cb_addr,
1117 sizeof(cb->cb_addr)); 1212 sizeof(conn->cb_addr));
1118 1213
1119 if (!cb->cb_addrlen || cb->cb_addr.ss_family != expected_family) 1214 if (!conn->cb_addrlen || conn->cb_addr.ss_family != expected_family)
1120 goto out_err; 1215 goto out_err;
1121 1216
1122 if (cb->cb_addr.ss_family == AF_INET6) 1217 if (conn->cb_addr.ss_family == AF_INET6)
1123 ((struct sockaddr_in6 *) &cb->cb_addr)->sin6_scope_id = scopeid; 1218 ((struct sockaddr_in6 *)&conn->cb_addr)->sin6_scope_id = scopeid;
1124 1219
1125 cb->cb_minorversion = 0; 1220 conn->cb_prog = se->se_callback_prog;
1126 cb->cb_prog = se->se_callback_prog; 1221 conn->cb_ident = se->se_callback_ident;
1127 cb->cb_ident = se->se_callback_ident; 1222 rpc_svcaddr2sockaddr((struct sockaddr *)&conn->cb_saddr, expected_family, &rqstp->rq_daddr);
1128 return; 1223 return;
1129out_err: 1224out_err:
1130 cb->cb_addr.ss_family = AF_UNSPEC; 1225 conn->cb_addr.ss_family = AF_UNSPEC;
1131 cb->cb_addrlen = 0; 1226 conn->cb_addrlen = 0;
1132 dprintk(KERN_INFO "NFSD: this client (clientid %08x/%08x) " 1227 dprintk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
1133 "will not receive delegations\n", 1228 "will not receive delegations\n",
1134 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); 1229 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
@@ -1264,7 +1359,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
1264 case SP4_NONE: 1359 case SP4_NONE:
1265 break; 1360 break;
1266 case SP4_SSV: 1361 case SP4_SSV:
1267 return nfserr_encr_alg_unsupp; 1362 return nfserr_serverfault;
1268 default: 1363 default:
1269 BUG(); /* checked by xdr code */ 1364 BUG(); /* checked by xdr code */
1270 case SP4_MACH_CRED: 1365 case SP4_MACH_CRED:
@@ -1281,8 +1376,12 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
1281 nfs4_lock_state(); 1376 nfs4_lock_state();
1282 status = nfs_ok; 1377 status = nfs_ok;
1283 1378
1284 conf = find_confirmed_client_by_str(dname, strhashval, true); 1379 conf = find_confirmed_client_by_str(dname, strhashval);
1285 if (conf) { 1380 if (conf) {
1381 if (!clp_used_exchangeid(conf)) {
1382 status = nfserr_clid_inuse; /* XXX: ? */
1383 goto out;
1384 }
1286 if (!same_verf(&verf, &conf->cl_verifier)) { 1385 if (!same_verf(&verf, &conf->cl_verifier)) {
1287 /* 18.35.4 case 8 */ 1386 /* 18.35.4 case 8 */
1288 if (exid->flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A) { 1387 if (exid->flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A) {
@@ -1323,7 +1422,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp,
1323 goto out; 1422 goto out;
1324 } 1423 }
1325 1424
1326 unconf = find_unconfirmed_client_by_str(dname, strhashval, true); 1425 unconf = find_unconfirmed_client_by_str(dname, strhashval);
1327 if (unconf) { 1426 if (unconf) {
1328 /* 1427 /*
1329 * Possible retry or client restart. Per 18.35.4 case 4, 1428 * Possible retry or client restart. Per 18.35.4 case 4,
@@ -1415,9 +1514,14 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1415{ 1514{
1416 struct sockaddr *sa = svc_addr(rqstp); 1515 struct sockaddr *sa = svc_addr(rqstp);
1417 struct nfs4_client *conf, *unconf; 1516 struct nfs4_client *conf, *unconf;
1517 struct nfsd4_session *new;
1418 struct nfsd4_clid_slot *cs_slot = NULL; 1518 struct nfsd4_clid_slot *cs_slot = NULL;
1519 bool confirm_me = false;
1419 int status = 0; 1520 int status = 0;
1420 1521
1522 if (cr_ses->flags & ~SESSION4_FLAG_MASK_A)
1523 return nfserr_inval;
1524
1421 nfs4_lock_state(); 1525 nfs4_lock_state();
1422 unconf = find_unconfirmed_client(&cr_ses->clientid); 1526 unconf = find_unconfirmed_client(&cr_ses->clientid);
1423 conf = find_confirmed_client(&cr_ses->clientid); 1527 conf = find_confirmed_client(&cr_ses->clientid);
@@ -1438,7 +1542,6 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1438 cs_slot->sl_seqid, cr_ses->seqid); 1542 cs_slot->sl_seqid, cr_ses->seqid);
1439 goto out; 1543 goto out;
1440 } 1544 }
1441 cs_slot->sl_seqid++;
1442 } else if (unconf) { 1545 } else if (unconf) {
1443 if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) || 1546 if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) ||
1444 !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) { 1547 !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) {
@@ -1451,25 +1554,10 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1451 if (status) { 1554 if (status) {
1452 /* an unconfirmed replay returns misordered */ 1555 /* an unconfirmed replay returns misordered */
1453 status = nfserr_seq_misordered; 1556 status = nfserr_seq_misordered;
1454 goto out_cache; 1557 goto out;
1455 } 1558 }
1456 1559
1457 cs_slot->sl_seqid++; /* from 0 to 1 */ 1560 confirm_me = true;
1458 move_to_confirmed(unconf);
1459
1460 if (cr_ses->flags & SESSION4_BACK_CHAN) {
1461 unconf->cl_cb_conn.cb_xprt = rqstp->rq_xprt;
1462 svc_xprt_get(rqstp->rq_xprt);
1463 rpc_copy_addr(
1464 (struct sockaddr *)&unconf->cl_cb_conn.cb_addr,
1465 sa);
1466 unconf->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
1467 unconf->cl_cb_conn.cb_minorversion =
1468 cstate->minorversion;
1469 unconf->cl_cb_conn.cb_prog = cr_ses->callback_prog;
1470 unconf->cl_cb_seq_nr = 1;
1471 nfsd4_probe_callback(unconf, &unconf->cl_cb_conn);
1472 }
1473 conf = unconf; 1561 conf = unconf;
1474 } else { 1562 } else {
1475 status = nfserr_stale_clientid; 1563 status = nfserr_stale_clientid;
@@ -1477,22 +1565,32 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1477 } 1565 }
1478 1566
1479 /* 1567 /*
1568 * XXX: we should probably set this at creation time, and check
1569 * for consistent minorversion use throughout:
1570 */
1571 conf->cl_minorversion = 1;
1572 /*
1480 * We do not support RDMA or persistent sessions 1573 * We do not support RDMA or persistent sessions
1481 */ 1574 */
1482 cr_ses->flags &= ~SESSION4_PERSIST; 1575 cr_ses->flags &= ~SESSION4_PERSIST;
1483 cr_ses->flags &= ~SESSION4_RDMA; 1576 cr_ses->flags &= ~SESSION4_RDMA;
1484 1577
1485 status = alloc_init_session(rqstp, conf, cr_ses); 1578 status = nfserr_jukebox;
1486 if (status) 1579 new = alloc_init_session(rqstp, conf, cr_ses);
1580 if (!new)
1487 goto out; 1581 goto out;
1488 1582 status = nfs_ok;
1489 memcpy(cr_ses->sessionid.data, conf->cl_sessionid.data, 1583 memcpy(cr_ses->sessionid.data, new->se_sessionid.data,
1490 NFS4_MAX_SESSIONID_LEN); 1584 NFS4_MAX_SESSIONID_LEN);
1585 memcpy(&cr_ses->fore_channel, &new->se_fchannel,
1586 sizeof(struct nfsd4_channel_attrs));
1587 cs_slot->sl_seqid++;
1491 cr_ses->seqid = cs_slot->sl_seqid; 1588 cr_ses->seqid = cs_slot->sl_seqid;
1492 1589
1493out_cache:
1494 /* cache solo and embedded create sessions under the state lock */ 1590 /* cache solo and embedded create sessions under the state lock */
1495 nfsd4_cache_create_session(cr_ses, cs_slot, status); 1591 nfsd4_cache_create_session(cr_ses, cs_slot, status);
1592 if (confirm_me)
1593 move_to_confirmed(conf);
1496out: 1594out:
1497 nfs4_unlock_state(); 1595 nfs4_unlock_state();
1498 dprintk("%s returns %d\n", __func__, ntohl(status)); 1596 dprintk("%s returns %d\n", __func__, ntohl(status));
@@ -1507,6 +1605,46 @@ static bool nfsd4_last_compound_op(struct svc_rqst *rqstp)
1507 return argp->opcnt == resp->opcnt; 1605 return argp->opcnt == resp->opcnt;
1508} 1606}
1509 1607
1608static __be32 nfsd4_map_bcts_dir(u32 *dir)
1609{
1610 switch (*dir) {
1611 case NFS4_CDFC4_FORE:
1612 case NFS4_CDFC4_BACK:
1613 return nfs_ok;
1614 case NFS4_CDFC4_FORE_OR_BOTH:
1615 case NFS4_CDFC4_BACK_OR_BOTH:
1616 *dir = NFS4_CDFC4_BOTH;
1617 return nfs_ok;
1618 };
1619 return nfserr_inval;
1620}
1621
1622__be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
1623 struct nfsd4_compound_state *cstate,
1624 struct nfsd4_bind_conn_to_session *bcts)
1625{
1626 __be32 status;
1627
1628 if (!nfsd4_last_compound_op(rqstp))
1629 return nfserr_not_only_op;
1630 spin_lock(&client_lock);
1631 cstate->session = find_in_sessionid_hashtbl(&bcts->sessionid);
1632 /* Sorta weird: we only need the refcnt'ing because new_conn acquires
1633 * client_lock iself: */
1634 if (cstate->session) {
1635 nfsd4_get_session(cstate->session);
1636 atomic_inc(&cstate->session->se_client->cl_refcount);
1637 }
1638 spin_unlock(&client_lock);
1639 if (!cstate->session)
1640 return nfserr_badsession;
1641
1642 status = nfsd4_map_bcts_dir(&bcts->dir);
1643 if (!status)
1644 nfsd4_new_conn(rqstp, cstate->session, bcts->dir);
1645 return status;
1646}
1647
1510static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid) 1648static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid)
1511{ 1649{
1512 if (!session) 1650 if (!session)
@@ -1545,9 +1683,11 @@ nfsd4_destroy_session(struct svc_rqst *r,
1545 spin_unlock(&client_lock); 1683 spin_unlock(&client_lock);
1546 1684
1547 nfs4_lock_state(); 1685 nfs4_lock_state();
1548 /* wait for callbacks */ 1686 nfsd4_probe_callback_sync(ses->se_client);
1549 nfsd4_set_callback_client(ses->se_client, NULL);
1550 nfs4_unlock_state(); 1687 nfs4_unlock_state();
1688
1689 nfsd4_del_conns(ses);
1690
1551 nfsd4_put_session(ses); 1691 nfsd4_put_session(ses);
1552 status = nfs_ok; 1692 status = nfs_ok;
1553out: 1693out:
@@ -1555,6 +1695,47 @@ out:
1555 return status; 1695 return status;
1556} 1696}
1557 1697
1698static struct nfsd4_conn *__nfsd4_find_conn(struct svc_xprt *xpt, struct nfsd4_session *s)
1699{
1700 struct nfsd4_conn *c;
1701
1702 list_for_each_entry(c, &s->se_conns, cn_persession) {
1703 if (c->cn_xprt == xpt) {
1704 return c;
1705 }
1706 }
1707 return NULL;
1708}
1709
1710static void nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_session *ses)
1711{
1712 struct nfs4_client *clp = ses->se_client;
1713 struct nfsd4_conn *c;
1714 int ret;
1715
1716 spin_lock(&clp->cl_lock);
1717 c = __nfsd4_find_conn(new->cn_xprt, ses);
1718 if (c) {
1719 spin_unlock(&clp->cl_lock);
1720 free_conn(new);
1721 return;
1722 }
1723 __nfsd4_hash_conn(new, ses);
1724 spin_unlock(&clp->cl_lock);
1725 ret = nfsd4_register_conn(new);
1726 if (ret)
1727 /* oops; xprt is already down: */
1728 nfsd4_conn_lost(&new->cn_xpt_user);
1729 return;
1730}
1731
1732static bool nfsd4_session_too_many_ops(struct svc_rqst *rqstp, struct nfsd4_session *session)
1733{
1734 struct nfsd4_compoundargs *args = rqstp->rq_argp;
1735
1736 return args->opcnt > session->se_fchannel.maxops;
1737}
1738
1558__be32 1739__be32
1559nfsd4_sequence(struct svc_rqst *rqstp, 1740nfsd4_sequence(struct svc_rqst *rqstp,
1560 struct nfsd4_compound_state *cstate, 1741 struct nfsd4_compound_state *cstate,
@@ -1563,17 +1744,30 @@ nfsd4_sequence(struct svc_rqst *rqstp,
1563 struct nfsd4_compoundres *resp = rqstp->rq_resp; 1744 struct nfsd4_compoundres *resp = rqstp->rq_resp;
1564 struct nfsd4_session *session; 1745 struct nfsd4_session *session;
1565 struct nfsd4_slot *slot; 1746 struct nfsd4_slot *slot;
1747 struct nfsd4_conn *conn;
1566 int status; 1748 int status;
1567 1749
1568 if (resp->opcnt != 1) 1750 if (resp->opcnt != 1)
1569 return nfserr_sequence_pos; 1751 return nfserr_sequence_pos;
1570 1752
1753 /*
1754 * Will be either used or freed by nfsd4_sequence_check_conn
1755 * below.
1756 */
1757 conn = alloc_conn(rqstp, NFS4_CDFC4_FORE);
1758 if (!conn)
1759 return nfserr_jukebox;
1760
1571 spin_lock(&client_lock); 1761 spin_lock(&client_lock);
1572 status = nfserr_badsession; 1762 status = nfserr_badsession;
1573 session = find_in_sessionid_hashtbl(&seq->sessionid); 1763 session = find_in_sessionid_hashtbl(&seq->sessionid);
1574 if (!session) 1764 if (!session)
1575 goto out; 1765 goto out;
1576 1766
1767 status = nfserr_too_many_ops;
1768 if (nfsd4_session_too_many_ops(rqstp, session))
1769 goto out;
1770
1577 status = nfserr_badslot; 1771 status = nfserr_badslot;
1578 if (seq->slotid >= session->se_fchannel.maxreqs) 1772 if (seq->slotid >= session->se_fchannel.maxreqs)
1579 goto out; 1773 goto out;
@@ -1599,6 +1793,9 @@ nfsd4_sequence(struct svc_rqst *rqstp,
1599 if (status) 1793 if (status)
1600 goto out; 1794 goto out;
1601 1795
1796 nfsd4_sequence_check_conn(conn, session);
1797 conn = NULL;
1798
1602 /* Success! bump slot seqid */ 1799 /* Success! bump slot seqid */
1603 slot->sl_inuse = true; 1800 slot->sl_inuse = true;
1604 slot->sl_seqid = seq->seqid; 1801 slot->sl_seqid = seq->seqid;
@@ -1610,9 +1807,14 @@ nfsd4_sequence(struct svc_rqst *rqstp,
1610out: 1807out:
1611 /* Hold a session reference until done processing the compound. */ 1808 /* Hold a session reference until done processing the compound. */
1612 if (cstate->session) { 1809 if (cstate->session) {
1810 struct nfs4_client *clp = session->se_client;
1811
1613 nfsd4_get_session(cstate->session); 1812 nfsd4_get_session(cstate->session);
1614 atomic_inc(&session->se_client->cl_refcount); 1813 atomic_inc(&clp->cl_refcount);
1814 if (clp->cl_cb_state == NFSD4_CB_DOWN)
1815 seq->status_flags |= SEQ4_STATUS_CB_PATH_DOWN;
1615 } 1816 }
1817 kfree(conn);
1616 spin_unlock(&client_lock); 1818 spin_unlock(&client_lock);
1617 dprintk("%s: return %d\n", __func__, ntohl(status)); 1819 dprintk("%s: return %d\n", __func__, ntohl(status));
1618 return status; 1820 return status;
@@ -1621,6 +1823,8 @@ out:
1621__be32 1823__be32
1622nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_reclaim_complete *rc) 1824nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_reclaim_complete *rc)
1623{ 1825{
1826 int status = 0;
1827
1624 if (rc->rca_one_fs) { 1828 if (rc->rca_one_fs) {
1625 if (!cstate->current_fh.fh_dentry) 1829 if (!cstate->current_fh.fh_dentry)
1626 return nfserr_nofilehandle; 1830 return nfserr_nofilehandle;
@@ -1630,9 +1834,14 @@ nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
1630 */ 1834 */
1631 return nfs_ok; 1835 return nfs_ok;
1632 } 1836 }
1837
1633 nfs4_lock_state(); 1838 nfs4_lock_state();
1634 if (is_client_expired(cstate->session->se_client)) { 1839 status = nfserr_complete_already;
1635 nfs4_unlock_state(); 1840 if (cstate->session->se_client->cl_firststate)
1841 goto out;
1842
1843 status = nfserr_stale_clientid;
1844 if (is_client_expired(cstate->session->se_client))
1636 /* 1845 /*
1637 * The following error isn't really legal. 1846 * The following error isn't really legal.
1638 * But we only get here if the client just explicitly 1847 * But we only get here if the client just explicitly
@@ -1640,18 +1849,19 @@ nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
1640 * error it gets back on an operation for the dead 1849 * error it gets back on an operation for the dead
1641 * client. 1850 * client.
1642 */ 1851 */
1643 return nfserr_stale_clientid; 1852 goto out;
1644 } 1853
1854 status = nfs_ok;
1645 nfsd4_create_clid_dir(cstate->session->se_client); 1855 nfsd4_create_clid_dir(cstate->session->se_client);
1856out:
1646 nfs4_unlock_state(); 1857 nfs4_unlock_state();
1647 return nfs_ok; 1858 return status;
1648} 1859}
1649 1860
1650__be32 1861__be32
1651nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 1862nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
1652 struct nfsd4_setclientid *setclid) 1863 struct nfsd4_setclientid *setclid)
1653{ 1864{
1654 struct sockaddr *sa = svc_addr(rqstp);
1655 struct xdr_netobj clname = { 1865 struct xdr_netobj clname = {
1656 .len = setclid->se_namelen, 1866 .len = setclid->se_namelen,
1657 .data = setclid->se_name, 1867 .data = setclid->se_name,
@@ -1677,10 +1887,12 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
1677 strhashval = clientstr_hashval(dname); 1887 strhashval = clientstr_hashval(dname);
1678 1888
1679 nfs4_lock_state(); 1889 nfs4_lock_state();
1680 conf = find_confirmed_client_by_str(dname, strhashval, false); 1890 conf = find_confirmed_client_by_str(dname, strhashval);
1681 if (conf) { 1891 if (conf) {
1682 /* RFC 3530 14.2.33 CASE 0: */ 1892 /* RFC 3530 14.2.33 CASE 0: */
1683 status = nfserr_clid_inuse; 1893 status = nfserr_clid_inuse;
1894 if (clp_used_exchangeid(conf))
1895 goto out;
1684 if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) { 1896 if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) {
1685 char addr_str[INET6_ADDRSTRLEN]; 1897 char addr_str[INET6_ADDRSTRLEN];
1686 rpc_ntop((struct sockaddr *) &conf->cl_addr, addr_str, 1898 rpc_ntop((struct sockaddr *) &conf->cl_addr, addr_str,
@@ -1695,7 +1907,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
1695 * has a description of SETCLIENTID request processing consisting 1907 * has a description of SETCLIENTID request processing consisting
1696 * of 5 bullet points, labeled as CASE0 - CASE4 below. 1908 * of 5 bullet points, labeled as CASE0 - CASE4 below.
1697 */ 1909 */
1698 unconf = find_unconfirmed_client_by_str(dname, strhashval, false); 1910 unconf = find_unconfirmed_client_by_str(dname, strhashval);
1699 status = nfserr_resource; 1911 status = nfserr_resource;
1700 if (!conf) { 1912 if (!conf) {
1701 /* 1913 /*
@@ -1747,7 +1959,12 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
1747 goto out; 1959 goto out;
1748 gen_clid(new); 1960 gen_clid(new);
1749 } 1961 }
1750 gen_callback(new, setclid, rpc_get_scope_id(sa)); 1962 /*
1963 * XXX: we should probably set this at creation time, and check
1964 * for consistent minorversion use throughout:
1965 */
1966 new->cl_minorversion = 0;
1967 gen_callback(new, setclid, rqstp);
1751 add_to_unconfirmed(new, strhashval); 1968 add_to_unconfirmed(new, strhashval);
1752 setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot; 1969 setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot;
1753 setclid->se_clientid.cl_id = new->cl_clientid.cl_id; 1970 setclid->se_clientid.cl_id = new->cl_clientid.cl_id;
@@ -1806,8 +2023,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
1806 if (!same_creds(&conf->cl_cred, &unconf->cl_cred)) 2023 if (!same_creds(&conf->cl_cred, &unconf->cl_cred))
1807 status = nfserr_clid_inuse; 2024 status = nfserr_clid_inuse;
1808 else { 2025 else {
1809 atomic_set(&conf->cl_cb_set, 0); 2026 nfsd4_change_callback(conf, &unconf->cl_cb_conn);
1810 nfsd4_probe_callback(conf, &unconf->cl_cb_conn); 2027 nfsd4_probe_callback(conf);
1811 expire_client(unconf); 2028 expire_client(unconf);
1812 status = nfs_ok; 2029 status = nfs_ok;
1813 2030
@@ -1834,14 +2051,14 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
1834 unsigned int hash = 2051 unsigned int hash =
1835 clientstr_hashval(unconf->cl_recdir); 2052 clientstr_hashval(unconf->cl_recdir);
1836 conf = find_confirmed_client_by_str(unconf->cl_recdir, 2053 conf = find_confirmed_client_by_str(unconf->cl_recdir,
1837 hash, false); 2054 hash);
1838 if (conf) { 2055 if (conf) {
1839 nfsd4_remove_clid_dir(conf); 2056 nfsd4_remove_clid_dir(conf);
1840 expire_client(conf); 2057 expire_client(conf);
1841 } 2058 }
1842 move_to_confirmed(unconf); 2059 move_to_confirmed(unconf);
1843 conf = unconf; 2060 conf = unconf;
1844 nfsd4_probe_callback(conf, &conf->cl_cb_conn); 2061 nfsd4_probe_callback(conf);
1845 status = nfs_ok; 2062 status = nfs_ok;
1846 } 2063 }
1847 } else if ((!conf || (conf && !same_verf(&conf->cl_confirm, &confirm))) 2064 } else if ((!conf || (conf && !same_verf(&conf->cl_confirm, &confirm)))
@@ -1877,6 +2094,7 @@ alloc_init_file(struct inode *ino)
1877 fp->fi_inode = igrab(ino); 2094 fp->fi_inode = igrab(ino);
1878 fp->fi_id = current_fileid++; 2095 fp->fi_id = current_fileid++;
1879 fp->fi_had_conflict = false; 2096 fp->fi_had_conflict = false;
2097 fp->fi_lease = NULL;
1880 memset(fp->fi_fds, 0, sizeof(fp->fi_fds)); 2098 memset(fp->fi_fds, 0, sizeof(fp->fi_fds));
1881 memset(fp->fi_access, 0, sizeof(fp->fi_access)); 2099 memset(fp->fi_access, 0, sizeof(fp->fi_access));
1882 spin_lock(&recall_lock); 2100 spin_lock(&recall_lock);
@@ -2128,23 +2346,8 @@ nfs4_file_downgrade(struct nfs4_file *fp, unsigned int share_access)
2128 nfs4_file_put_access(fp, O_RDONLY); 2346 nfs4_file_put_access(fp, O_RDONLY);
2129} 2347}
2130 2348
2131/* 2349static void nfsd_break_one_deleg(struct nfs4_delegation *dp)
2132 * Spawn a thread to perform a recall on the delegation represented
2133 * by the lease (file_lock)
2134 *
2135 * Called from break_lease() with lock_kernel() held.
2136 * Note: we assume break_lease will only call this *once* for any given
2137 * lease.
2138 */
2139static
2140void nfsd_break_deleg_cb(struct file_lock *fl)
2141{ 2350{
2142 struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner;
2143
2144 dprintk("NFSD nfsd_break_deleg_cb: dp %p fl %p\n",dp,fl);
2145 if (!dp)
2146 return;
2147
2148 /* We're assuming the state code never drops its reference 2351 /* We're assuming the state code never drops its reference
2149 * without first removing the lease. Since we're in this lease 2352 * without first removing the lease. Since we're in this lease
2150 * callback (and since the lease code is serialized by the kernel 2353 * callback (and since the lease code is serialized by the kernel
@@ -2152,75 +2355,37 @@ void nfsd_break_deleg_cb(struct file_lock *fl)
2152 * it's safe to take a reference: */ 2355 * it's safe to take a reference: */
2153 atomic_inc(&dp->dl_count); 2356 atomic_inc(&dp->dl_count);
2154 2357
2155 spin_lock(&recall_lock);
2156 list_add_tail(&dp->dl_recall_lru, &del_recall_lru); 2358 list_add_tail(&dp->dl_recall_lru, &del_recall_lru);
2157 spin_unlock(&recall_lock);
2158 2359
2159 /* only place dl_time is set. protected by lock_kernel*/ 2360 /* only place dl_time is set. protected by lock_flocks*/
2160 dp->dl_time = get_seconds(); 2361 dp->dl_time = get_seconds();
2161 2362
2162 /*
2163 * We don't want the locks code to timeout the lease for us;
2164 * we'll remove it ourself if the delegation isn't returned
2165 * in time.
2166 */
2167 fl->fl_break_time = 0;
2168
2169 dp->dl_file->fi_had_conflict = true;
2170 nfsd4_cb_recall(dp); 2363 nfsd4_cb_recall(dp);
2171} 2364}
2172 2365
2173/* 2366/* Called from break_lease() with lock_flocks() held. */
2174 * The file_lock is being reapd. 2367static void nfsd_break_deleg_cb(struct file_lock *fl)
2175 *
2176 * Called by locks_free_lock() with lock_kernel() held.
2177 */
2178static
2179void nfsd_release_deleg_cb(struct file_lock *fl)
2180{
2181 struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner;
2182
2183 dprintk("NFSD nfsd_release_deleg_cb: fl %p dp %p dl_count %d\n", fl,dp, atomic_read(&dp->dl_count));
2184
2185 if (!(fl->fl_flags & FL_LEASE) || !dp)
2186 return;
2187 dp->dl_flock = NULL;
2188}
2189
2190/*
2191 * Set the delegation file_lock back pointer.
2192 *
2193 * Called from setlease() with lock_kernel() held.
2194 */
2195static
2196void nfsd_copy_lock_deleg_cb(struct file_lock *new, struct file_lock *fl)
2197{
2198 struct nfs4_delegation *dp = (struct nfs4_delegation *)new->fl_owner;
2199
2200 dprintk("NFSD: nfsd_copy_lock_deleg_cb: new fl %p dp %p\n", new, dp);
2201 if (!dp)
2202 return;
2203 dp->dl_flock = new;
2204}
2205
2206/*
2207 * Called from setlease() with lock_kernel() held
2208 */
2209static
2210int nfsd_same_client_deleg_cb(struct file_lock *onlist, struct file_lock *try)
2211{ 2368{
2212 struct nfs4_delegation *onlistd = 2369 struct nfs4_file *fp = (struct nfs4_file *)fl->fl_owner;
2213 (struct nfs4_delegation *)onlist->fl_owner; 2370 struct nfs4_delegation *dp;
2214 struct nfs4_delegation *tryd =
2215 (struct nfs4_delegation *)try->fl_owner;
2216 2371
2217 if (onlist->fl_lmops != try->fl_lmops) 2372 BUG_ON(!fp);
2218 return 0; 2373 /* We assume break_lease is only called once per lease: */
2374 BUG_ON(fp->fi_had_conflict);
2375 /*
2376 * We don't want the locks code to timeout the lease for us;
2377 * we'll remove it ourself if a delegation isn't returned
2378 * in time:
2379 */
2380 fl->fl_break_time = 0;
2219 2381
2220 return onlistd->dl_client == tryd->dl_client; 2382 spin_lock(&recall_lock);
2383 fp->fi_had_conflict = true;
2384 list_for_each_entry(dp, &fp->fi_delegations, dl_perfile)
2385 nfsd_break_one_deleg(dp);
2386 spin_unlock(&recall_lock);
2221} 2387}
2222 2388
2223
2224static 2389static
2225int nfsd_change_deleg_cb(struct file_lock **onlist, int arg) 2390int nfsd_change_deleg_cb(struct file_lock **onlist, int arg)
2226{ 2391{
@@ -2232,9 +2397,6 @@ int nfsd_change_deleg_cb(struct file_lock **onlist, int arg)
2232 2397
2233static const struct lock_manager_operations nfsd_lease_mng_ops = { 2398static const struct lock_manager_operations nfsd_lease_mng_ops = {
2234 .fl_break = nfsd_break_deleg_cb, 2399 .fl_break = nfsd_break_deleg_cb,
2235 .fl_release_private = nfsd_release_deleg_cb,
2236 .fl_copy_lock = nfsd_copy_lock_deleg_cb,
2237 .fl_mylease = nfsd_same_client_deleg_cb,
2238 .fl_change = nfsd_change_deleg_cb, 2400 .fl_change = nfsd_change_deleg_cb,
2239}; 2401};
2240 2402
@@ -2314,14 +2476,17 @@ find_delegation_file(struct nfs4_file *fp, stateid_t *stid)
2314{ 2476{
2315 struct nfs4_delegation *dp; 2477 struct nfs4_delegation *dp;
2316 2478
2317 list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) { 2479 spin_lock(&recall_lock);
2318 if (dp->dl_stateid.si_stateownerid == stid->si_stateownerid) 2480 list_for_each_entry(dp, &fp->fi_delegations, dl_perfile)
2481 if (dp->dl_stateid.si_stateownerid == stid->si_stateownerid) {
2482 spin_unlock(&recall_lock);
2319 return dp; 2483 return dp;
2320 } 2484 }
2485 spin_unlock(&recall_lock);
2321 return NULL; 2486 return NULL;
2322} 2487}
2323 2488
2324int share_access_to_flags(u32 share_access) 2489static int share_access_to_flags(u32 share_access)
2325{ 2490{
2326 share_access &= ~NFS4_SHARE_WANT_MASK; 2491 share_access &= ~NFS4_SHARE_WANT_MASK;
2327 2492
@@ -2401,8 +2566,6 @@ static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file
2401 if (!fp->fi_fds[oflag]) { 2566 if (!fp->fi_fds[oflag]) {
2402 status = nfsd_open(rqstp, cur_fh, S_IFREG, access, 2567 status = nfsd_open(rqstp, cur_fh, S_IFREG, access,
2403 &fp->fi_fds[oflag]); 2568 &fp->fi_fds[oflag]);
2404 if (status == nfserr_dropit)
2405 status = nfserr_jukebox;
2406 if (status) 2569 if (status)
2407 return status; 2570 return status;
2408 } 2571 }
@@ -2483,6 +2646,79 @@ nfs4_set_claim_prev(struct nfsd4_open *open)
2483 open->op_stateowner->so_client->cl_firststate = 1; 2646 open->op_stateowner->so_client->cl_firststate = 1;
2484} 2647}
2485 2648
2649/* Should we give out recallable state?: */
2650static bool nfsd4_cb_channel_good(struct nfs4_client *clp)
2651{
2652 if (clp->cl_cb_state == NFSD4_CB_UP)
2653 return true;
2654 /*
2655 * In the sessions case, since we don't have to establish a
2656 * separate connection for callbacks, we assume it's OK
2657 * until we hear otherwise:
2658 */
2659 return clp->cl_minorversion && clp->cl_cb_state == NFSD4_CB_UNKNOWN;
2660}
2661
2662static struct file_lock *nfs4_alloc_init_lease(struct nfs4_delegation *dp, int flag)
2663{
2664 struct file_lock *fl;
2665
2666 fl = locks_alloc_lock();
2667 if (!fl)
2668 return NULL;
2669 locks_init_lock(fl);
2670 fl->fl_lmops = &nfsd_lease_mng_ops;
2671 fl->fl_flags = FL_LEASE;
2672 fl->fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK;
2673 fl->fl_end = OFFSET_MAX;
2674 fl->fl_owner = (fl_owner_t)(dp->dl_file);
2675 fl->fl_pid = current->tgid;
2676 return fl;
2677}
2678
2679static int nfs4_setlease(struct nfs4_delegation *dp, int flag)
2680{
2681 struct nfs4_file *fp = dp->dl_file;
2682 struct file_lock *fl;
2683 int status;
2684
2685 fl = nfs4_alloc_init_lease(dp, flag);
2686 if (!fl)
2687 return -ENOMEM;
2688 fl->fl_file = find_readable_file(fp);
2689 list_add(&dp->dl_perclnt, &dp->dl_client->cl_delegations);
2690 status = vfs_setlease(fl->fl_file, fl->fl_type, &fl);
2691 if (status) {
2692 list_del_init(&dp->dl_perclnt);
2693 locks_free_lock(fl);
2694 return -ENOMEM;
2695 }
2696 fp->fi_lease = fl;
2697 fp->fi_deleg_file = fl->fl_file;
2698 get_file(fp->fi_deleg_file);
2699 atomic_set(&fp->fi_delegees, 1);
2700 list_add(&dp->dl_perfile, &fp->fi_delegations);
2701 return 0;
2702}
2703
2704static int nfs4_set_delegation(struct nfs4_delegation *dp, int flag)
2705{
2706 struct nfs4_file *fp = dp->dl_file;
2707
2708 if (!fp->fi_lease)
2709 return nfs4_setlease(dp, flag);
2710 spin_lock(&recall_lock);
2711 if (fp->fi_had_conflict) {
2712 spin_unlock(&recall_lock);
2713 return -EAGAIN;
2714 }
2715 atomic_inc(&fp->fi_delegees);
2716 list_add(&dp->dl_perfile, &fp->fi_delegations);
2717 spin_unlock(&recall_lock);
2718 list_add(&dp->dl_perclnt, &dp->dl_client->cl_delegations);
2719 return 0;
2720}
2721
2486/* 2722/*
2487 * Attempt to hand out a delegation. 2723 * Attempt to hand out a delegation.
2488 */ 2724 */
@@ -2491,10 +2727,10 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
2491{ 2727{
2492 struct nfs4_delegation *dp; 2728 struct nfs4_delegation *dp;
2493 struct nfs4_stateowner *sop = stp->st_stateowner; 2729 struct nfs4_stateowner *sop = stp->st_stateowner;
2494 int cb_up = atomic_read(&sop->so_client->cl_cb_set); 2730 int cb_up;
2495 struct file_lock fl, *flp = &fl;
2496 int status, flag = 0; 2731 int status, flag = 0;
2497 2732
2733 cb_up = nfsd4_cb_channel_good(sop->so_client);
2498 flag = NFS4_OPEN_DELEGATE_NONE; 2734 flag = NFS4_OPEN_DELEGATE_NONE;
2499 open->op_recall = 0; 2735 open->op_recall = 0;
2500 switch (open->op_claim_type) { 2736 switch (open->op_claim_type) {
@@ -2522,29 +2758,11 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
2522 } 2758 }
2523 2759
2524 dp = alloc_init_deleg(sop->so_client, stp, fh, flag); 2760 dp = alloc_init_deleg(sop->so_client, stp, fh, flag);
2525 if (dp == NULL) { 2761 if (dp == NULL)
2526 flag = NFS4_OPEN_DELEGATE_NONE; 2762 goto out_no_deleg;
2527 goto out; 2763 status = nfs4_set_delegation(dp, flag);
2528 } 2764 if (status)
2529 locks_init_lock(&fl); 2765 goto out_free;
2530 fl.fl_lmops = &nfsd_lease_mng_ops;
2531 fl.fl_flags = FL_LEASE;
2532 fl.fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK;
2533 fl.fl_end = OFFSET_MAX;
2534 fl.fl_owner = (fl_owner_t)dp;
2535 fl.fl_file = find_readable_file(stp->st_file);
2536 BUG_ON(!fl.fl_file);
2537 fl.fl_pid = current->tgid;
2538
2539 /* vfs_setlease checks to see if delegation should be handed out.
2540 * the lock_manager callbacks fl_mylease and fl_change are used
2541 */
2542 if ((status = vfs_setlease(fl.fl_file, fl.fl_type, &flp))) {
2543 dprintk("NFSD: setlease failed [%d], no delegation\n", status);
2544 unhash_delegation(dp);
2545 flag = NFS4_OPEN_DELEGATE_NONE;
2546 goto out;
2547 }
2548 2766
2549 memcpy(&open->op_delegate_stateid, &dp->dl_stateid, sizeof(dp->dl_stateid)); 2767 memcpy(&open->op_delegate_stateid, &dp->dl_stateid, sizeof(dp->dl_stateid));
2550 2768
@@ -2556,6 +2774,12 @@ out:
2556 && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) 2774 && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE)
2557 dprintk("NFSD: WARNING: refusing delegation reclaim\n"); 2775 dprintk("NFSD: WARNING: refusing delegation reclaim\n");
2558 open->op_delegate_type = flag; 2776 open->op_delegate_type = flag;
2777 return;
2778out_free:
2779 nfs4_put_delegation(dp);
2780out_no_deleg:
2781 flag = NFS4_OPEN_DELEGATE_NONE;
2782 goto out;
2559} 2783}
2560 2784
2561/* 2785/*
@@ -2674,7 +2898,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2674 renew_client(clp); 2898 renew_client(clp);
2675 status = nfserr_cb_path_down; 2899 status = nfserr_cb_path_down;
2676 if (!list_empty(&clp->cl_delegations) 2900 if (!list_empty(&clp->cl_delegations)
2677 && !atomic_read(&clp->cl_cb_set)) 2901 && clp->cl_cb_state != NFSD4_CB_UP)
2678 goto out; 2902 goto out;
2679 status = nfs_ok; 2903 status = nfs_ok;
2680out: 2904out:
@@ -2682,7 +2906,7 @@ out:
2682 return status; 2906 return status;
2683} 2907}
2684 2908
2685struct lock_manager nfsd4_manager = { 2909static struct lock_manager nfsd4_manager = {
2686}; 2910};
2687 2911
2688static void 2912static void
@@ -2750,8 +2974,6 @@ nfs4_laundromat(void)
2750 test_val = u; 2974 test_val = u;
2751 break; 2975 break;
2752 } 2976 }
2753 dprintk("NFSD: purging unused delegation dp %p, fp %p\n",
2754 dp, dp->dl_flock);
2755 list_move(&dp->dl_recall_lru, &reaplist); 2977 list_move(&dp->dl_recall_lru, &reaplist);
2756 } 2978 }
2757 spin_unlock(&recall_lock); 2979 spin_unlock(&recall_lock);
@@ -2861,7 +3083,7 @@ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
2861 if (ONE_STATEID(stateid) && (flags & RD_STATE)) 3083 if (ONE_STATEID(stateid) && (flags & RD_STATE))
2862 return nfs_ok; 3084 return nfs_ok;
2863 else if (locks_in_grace()) { 3085 else if (locks_in_grace()) {
2864 /* Answer in remaining cases depends on existance of 3086 /* Answer in remaining cases depends on existence of
2865 * conflicting state; so we must wait out the grace period. */ 3087 * conflicting state; so we must wait out the grace period. */
2866 return nfserr_grace; 3088 return nfserr_grace;
2867 } else if (flags & WR_STATE) 3089 } else if (flags & WR_STATE)
@@ -2944,7 +3166,11 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
2944 if (STALE_STATEID(stateid)) 3166 if (STALE_STATEID(stateid))
2945 goto out; 3167 goto out;
2946 3168
2947 status = nfserr_bad_stateid; 3169 /*
3170 * We assume that any stateid that has the current boot time,
3171 * but that we can't find, is expired:
3172 */
3173 status = nfserr_expired;
2948 if (is_delegation_stateid(stateid)) { 3174 if (is_delegation_stateid(stateid)) {
2949 dp = find_delegation_stateid(ino, stateid); 3175 dp = find_delegation_stateid(ino, stateid);
2950 if (!dp) 3176 if (!dp)
@@ -2957,13 +3183,15 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
2957 if (status) 3183 if (status)
2958 goto out; 3184 goto out;
2959 renew_client(dp->dl_client); 3185 renew_client(dp->dl_client);
2960 if (filpp) 3186 if (filpp) {
2961 *filpp = find_readable_file(dp->dl_file); 3187 *filpp = dp->dl_file->fi_deleg_file;
2962 BUG_ON(!*filpp); 3188 BUG_ON(!*filpp);
3189 }
2963 } else { /* open or lock stateid */ 3190 } else { /* open or lock stateid */
2964 stp = find_stateid(stateid, flags); 3191 stp = find_stateid(stateid, flags);
2965 if (!stp) 3192 if (!stp)
2966 goto out; 3193 goto out;
3194 status = nfserr_bad_stateid;
2967 if (nfs4_check_fh(current_fh, stp)) 3195 if (nfs4_check_fh(current_fh, stp))
2968 goto out; 3196 goto out;
2969 if (!stp->st_stateowner->so_confirmed) 3197 if (!stp->st_stateowner->so_confirmed)
@@ -3038,8 +3266,9 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
3038 * a replayed close: 3266 * a replayed close:
3039 */ 3267 */
3040 sop = search_close_lru(stateid->si_stateownerid, flags); 3268 sop = search_close_lru(stateid->si_stateownerid, flags);
3269 /* It's not stale; let's assume it's expired: */
3041 if (sop == NULL) 3270 if (sop == NULL)
3042 return nfserr_bad_stateid; 3271 return nfserr_expired;
3043 *sopp = sop; 3272 *sopp = sop;
3044 goto check_replay; 3273 goto check_replay;
3045 } 3274 }
@@ -3304,6 +3533,7 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3304 status = nfserr_bad_stateid; 3533 status = nfserr_bad_stateid;
3305 if (!is_delegation_stateid(stateid)) 3534 if (!is_delegation_stateid(stateid))
3306 goto out; 3535 goto out;
3536 status = nfserr_expired;
3307 dp = find_delegation_stateid(inode, stateid); 3537 dp = find_delegation_stateid(inode, stateid);
3308 if (!dp) 3538 if (!dp)
3309 goto out; 3539 goto out;
@@ -3473,7 +3703,7 @@ find_lockstateowner_str(struct inode *inode, clientid_t *clid,
3473/* 3703/*
3474 * Alloc a lock owner structure. 3704 * Alloc a lock owner structure.
3475 * Called in nfsd4_lock - therefore, OPEN and OPEN_CONFIRM (if needed) has 3705 * Called in nfsd4_lock - therefore, OPEN and OPEN_CONFIRM (if needed) has
3476 * occured. 3706 * occurred.
3477 * 3707 *
3478 * strhashval = lock_ownerstr_hashval 3708 * strhashval = lock_ownerstr_hashval
3479 */ 3709 */
@@ -3534,6 +3764,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
3534 stp->st_stateid.si_stateownerid = sop->so_id; 3764 stp->st_stateid.si_stateownerid = sop->so_id;
3535 stp->st_stateid.si_fileid = fp->fi_id; 3765 stp->st_stateid.si_fileid = fp->fi_id;
3536 stp->st_stateid.si_generation = 0; 3766 stp->st_stateid.si_generation = 0;
3767 stp->st_access_bmap = 0;
3537 stp->st_deny_bmap = open_stp->st_deny_bmap; 3768 stp->st_deny_bmap = open_stp->st_deny_bmap;
3538 stp->st_openstp = open_stp; 3769 stp->st_openstp = open_stp;
3539 3770
@@ -3548,6 +3779,17 @@ check_lock_length(u64 offset, u64 length)
3548 LOFF_OVERFLOW(offset, length))); 3779 LOFF_OVERFLOW(offset, length)));
3549} 3780}
3550 3781
3782static void get_lock_access(struct nfs4_stateid *lock_stp, u32 access)
3783{
3784 struct nfs4_file *fp = lock_stp->st_file;
3785 int oflag = nfs4_access_to_omode(access);
3786
3787 if (test_bit(access, &lock_stp->st_access_bmap))
3788 return;
3789 nfs4_file_get_access(fp, oflag);
3790 __set_bit(access, &lock_stp->st_access_bmap);
3791}
3792
3551/* 3793/*
3552 * LOCK operation 3794 * LOCK operation
3553 */ 3795 */
@@ -3564,7 +3806,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3564 struct file_lock conflock; 3806 struct file_lock conflock;
3565 __be32 status = 0; 3807 __be32 status = 0;
3566 unsigned int strhashval; 3808 unsigned int strhashval;
3567 unsigned int cmd;
3568 int err; 3809 int err;
3569 3810
3570 dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n", 3811 dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
@@ -3646,22 +3887,18 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3646 switch (lock->lk_type) { 3887 switch (lock->lk_type) {
3647 case NFS4_READ_LT: 3888 case NFS4_READ_LT:
3648 case NFS4_READW_LT: 3889 case NFS4_READW_LT:
3649 if (find_readable_file(lock_stp->st_file)) { 3890 filp = find_readable_file(lock_stp->st_file);
3650 nfs4_get_vfs_file(rqstp, fp, &cstate->current_fh, NFS4_SHARE_ACCESS_READ); 3891 if (filp)
3651 filp = find_readable_file(lock_stp->st_file); 3892 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ);
3652 }
3653 file_lock.fl_type = F_RDLCK; 3893 file_lock.fl_type = F_RDLCK;
3654 cmd = F_SETLK; 3894 break;
3655 break;
3656 case NFS4_WRITE_LT: 3895 case NFS4_WRITE_LT:
3657 case NFS4_WRITEW_LT: 3896 case NFS4_WRITEW_LT:
3658 if (find_writeable_file(lock_stp->st_file)) { 3897 filp = find_writeable_file(lock_stp->st_file);
3659 nfs4_get_vfs_file(rqstp, fp, &cstate->current_fh, NFS4_SHARE_ACCESS_WRITE); 3898 if (filp)
3660 filp = find_writeable_file(lock_stp->st_file); 3899 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE);
3661 }
3662 file_lock.fl_type = F_WRLCK; 3900 file_lock.fl_type = F_WRLCK;
3663 cmd = F_SETLK; 3901 break;
3664 break;
3665 default: 3902 default:
3666 status = nfserr_inval; 3903 status = nfserr_inval;
3667 goto out; 3904 goto out;
@@ -3685,7 +3922,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3685 * Note: locks.c uses the BKL to protect the inode's lock list. 3922 * Note: locks.c uses the BKL to protect the inode's lock list.
3686 */ 3923 */
3687 3924
3688 err = vfs_lock_file(filp, cmd, &file_lock, &conflock); 3925 err = vfs_lock_file(filp, F_SETLK, &file_lock, &conflock);
3689 switch (-err) { 3926 switch (-err) {
3690 case 0: /* success! */ 3927 case 0: /* success! */
3691 update_stateid(&lock_stp->st_stateid); 3928 update_stateid(&lock_stp->st_stateid);
@@ -3895,7 +4132,7 @@ check_for_locks(struct nfs4_file *filp, struct nfs4_stateowner *lowner)
3895 struct inode *inode = filp->fi_inode; 4132 struct inode *inode = filp->fi_inode;
3896 int status = 0; 4133 int status = 0;
3897 4134
3898 lock_kernel(); 4135 lock_flocks();
3899 for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) { 4136 for (flpp = &inode->i_flock; *flpp != NULL; flpp = &(*flpp)->fl_next) {
3900 if ((*flpp)->fl_owner == (fl_owner_t)lowner) { 4137 if ((*flpp)->fl_owner == (fl_owner_t)lowner) {
3901 status = 1; 4138 status = 1;
@@ -3903,7 +4140,7 @@ check_for_locks(struct nfs4_file *filp, struct nfs4_stateowner *lowner)
3903 } 4140 }
3904 } 4141 }
3905out: 4142out:
3906 unlock_kernel(); 4143 unlock_flocks();
3907 return status; 4144 return status;
3908} 4145}
3909 4146
@@ -3980,7 +4217,7 @@ nfs4_has_reclaimed_state(const char *name, bool use_exchange_id)
3980 unsigned int strhashval = clientstr_hashval(name); 4217 unsigned int strhashval = clientstr_hashval(name);
3981 struct nfs4_client *clp; 4218 struct nfs4_client *clp;
3982 4219
3983 clp = find_confirmed_client_by_str(name, strhashval, use_exchange_id); 4220 clp = find_confirmed_client_by_str(name, strhashval);
3984 return clp ? 1 : 0; 4221 return clp ? 1 : 0;
3985} 4222}
3986 4223
@@ -4209,7 +4446,7 @@ __nfs4_state_shutdown(void)
4209void 4446void
4210nfs4_state_shutdown(void) 4447nfs4_state_shutdown(void)
4211{ 4448{
4212 cancel_rearming_delayed_workqueue(laundry_wq, &laundromat_work); 4449 cancel_delayed_work_sync(&laundromat_work);
4213 destroy_workqueue(laundry_wq); 4450 destroy_workqueue(laundry_wq);
4214 locks_end_grace(&nfsd4_manager); 4451 locks_end_grace(&nfsd4_manager);
4215 nfs4_lock_state(); 4452 nfs4_lock_state();
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 1a468bbd330f..990181103214 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -44,13 +44,14 @@
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/nfsd_idmap.h>
48#include <linux/nfs4_acl.h>
49#include <linux/sunrpc/svcauth_gss.h> 47#include <linux/sunrpc/svcauth_gss.h>
50 48
49#include "idmap.h"
50#include "acl.h"
51#include "xdr4.h" 51#include "xdr4.h"
52#include "vfs.h" 52#include "vfs.h"
53 53
54
54#define NFSDDBG_FACILITY NFSDDBG_XDR 55#define NFSDDBG_FACILITY NFSDDBG_XDR
55 56
56/* 57/*
@@ -288,17 +289,17 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
288 len += XDR_QUADLEN(dummy32) << 2; 289 len += XDR_QUADLEN(dummy32) << 2;
289 READMEM(buf, dummy32); 290 READMEM(buf, dummy32);
290 ace->whotype = nfs4_acl_get_whotype(buf, dummy32); 291 ace->whotype = nfs4_acl_get_whotype(buf, dummy32);
291 host_err = 0; 292 status = nfs_ok;
292 if (ace->whotype != NFS4_ACL_WHO_NAMED) 293 if (ace->whotype != NFS4_ACL_WHO_NAMED)
293 ace->who = 0; 294 ace->who = 0;
294 else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP) 295 else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
295 host_err = nfsd_map_name_to_gid(argp->rqstp, 296 status = nfsd_map_name_to_gid(argp->rqstp,
296 buf, dummy32, &ace->who); 297 buf, dummy32, &ace->who);
297 else 298 else
298 host_err = nfsd_map_name_to_uid(argp->rqstp, 299 status = nfsd_map_name_to_uid(argp->rqstp,
299 buf, dummy32, &ace->who); 300 buf, dummy32, &ace->who);
300 if (host_err) 301 if (status)
301 goto out_nfserr; 302 return status;
302 } 303 }
303 } else 304 } else
304 *acl = NULL; 305 *acl = NULL;
@@ -316,8 +317,8 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
316 READ_BUF(dummy32); 317 READ_BUF(dummy32);
317 len += (XDR_QUADLEN(dummy32) << 2); 318 len += (XDR_QUADLEN(dummy32) << 2);
318 READMEM(buf, dummy32); 319 READMEM(buf, dummy32);
319 if ((host_err = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid))) 320 if ((status = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid)))
320 goto out_nfserr; 321 return status;
321 iattr->ia_valid |= ATTR_UID; 322 iattr->ia_valid |= ATTR_UID;
322 } 323 }
323 if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) { 324 if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) {
@@ -327,8 +328,8 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
327 READ_BUF(dummy32); 328 READ_BUF(dummy32);
328 len += (XDR_QUADLEN(dummy32) << 2); 329 len += (XDR_QUADLEN(dummy32) << 2);
329 READMEM(buf, dummy32); 330 READMEM(buf, dummy32);
330 if ((host_err = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid))) 331 if ((status = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid)))
331 goto out_nfserr; 332 return status;
332 iattr->ia_valid |= ATTR_GID; 333 iattr->ia_valid |= ATTR_GID;
333 } 334 }
334 if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) { 335 if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
@@ -420,6 +421,18 @@ nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access
420 DECODE_TAIL; 421 DECODE_TAIL;
421} 422}
422 423
424static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts)
425{
426 DECODE_HEAD;
427
428 READ_BUF(NFS4_MAX_SESSIONID_LEN + 8);
429 COPYMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN);
430 READ32(bcts->dir);
431 /* XXX: skipping ctsa_use_conn_in_rdma_mode. Perhaps Tom Tucker
432 * could help us figure out we should be using it. */
433 DECODE_TAIL;
434}
435
423static __be32 436static __be32
424nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close) 437nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
425{ 438{
@@ -572,8 +585,6 @@ nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt)
572 READ_BUF(lockt->lt_owner.len); 585 READ_BUF(lockt->lt_owner.len);
573 READMEM(lockt->lt_owner.data, lockt->lt_owner.len); 586 READMEM(lockt->lt_owner.data, lockt->lt_owner.len);
574 587
575 if (argp->minorversion && !zero_clientid(&lockt->lt_clientid))
576 return nfserr_inval;
577 DECODE_TAIL; 588 DECODE_TAIL;
578} 589}
579 590
@@ -847,6 +858,17 @@ nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
847} 858}
848 859
849static __be32 860static __be32
861nfsd4_decode_secinfo_no_name(struct nfsd4_compoundargs *argp,
862 struct nfsd4_secinfo_no_name *sin)
863{
864 DECODE_HEAD;
865
866 READ_BUF(4);
867 READ32(sin->sin_style);
868 DECODE_TAIL;
869}
870
871static __be32
850nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr) 872nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
851{ 873{
852 __be32 status; 874 __be32 status;
@@ -1005,7 +1027,7 @@ static __be32
1005nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp, 1027nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
1006 struct nfsd4_exchange_id *exid) 1028 struct nfsd4_exchange_id *exid)
1007{ 1029{
1008 int dummy; 1030 int dummy, tmp;
1009 DECODE_HEAD; 1031 DECODE_HEAD;
1010 1032
1011 READ_BUF(NFS4_VERIFIER_SIZE); 1033 READ_BUF(NFS4_VERIFIER_SIZE);
@@ -1053,15 +1075,23 @@ nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
1053 1075
1054 /* ssp_hash_algs<> */ 1076 /* ssp_hash_algs<> */
1055 READ_BUF(4); 1077 READ_BUF(4);
1056 READ32(dummy); 1078 READ32(tmp);
1057 READ_BUF(dummy); 1079 while (tmp--) {
1058 p += XDR_QUADLEN(dummy); 1080 READ_BUF(4);
1081 READ32(dummy);
1082 READ_BUF(dummy);
1083 p += XDR_QUADLEN(dummy);
1084 }
1059 1085
1060 /* ssp_encr_algs<> */ 1086 /* ssp_encr_algs<> */
1061 READ_BUF(4); 1087 READ_BUF(4);
1062 READ32(dummy); 1088 READ32(tmp);
1063 READ_BUF(dummy); 1089 while (tmp--) {
1064 p += XDR_QUADLEN(dummy); 1090 READ_BUF(4);
1091 READ32(dummy);
1092 READ_BUF(dummy);
1093 p += XDR_QUADLEN(dummy);
1094 }
1065 1095
1066 /* ssp_window and ssp_num_gss_handles */ 1096 /* ssp_window and ssp_num_gss_handles */
1067 READ_BUF(8); 1097 READ_BUF(8);
@@ -1180,8 +1210,6 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
1180 READ_BUF(4); 1210 READ_BUF(4);
1181 READ32(dummy); 1211 READ32(dummy);
1182 READ_BUF(dummy * 4); 1212 READ_BUF(dummy * 4);
1183 for (i = 0; i < dummy; ++i)
1184 READ32(dummy);
1185 break; 1213 break;
1186 case RPC_AUTH_GSS: 1214 case RPC_AUTH_GSS:
1187 dprintk("RPC_AUTH_GSS callback secflavor " 1215 dprintk("RPC_AUTH_GSS callback secflavor "
@@ -1197,7 +1225,6 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
1197 READ_BUF(4); 1225 READ_BUF(4);
1198 READ32(dummy); 1226 READ32(dummy);
1199 READ_BUF(dummy); 1227 READ_BUF(dummy);
1200 p += XDR_QUADLEN(dummy);
1201 break; 1228 break;
1202 default: 1229 default:
1203 dprintk("Illegal callback secflavor\n"); 1230 dprintk("Illegal callback secflavor\n");
@@ -1339,7 +1366,7 @@ static nfsd4_dec nfsd41_dec_ops[] = {
1339 1366
1340 /* new operations for NFSv4.1 */ 1367 /* new operations for NFSv4.1 */
1341 [OP_BACKCHANNEL_CTL] = (nfsd4_dec)nfsd4_decode_notsupp, 1368 [OP_BACKCHANNEL_CTL] = (nfsd4_dec)nfsd4_decode_notsupp,
1342 [OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_notsupp, 1369 [OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_bind_conn_to_session,
1343 [OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id, 1370 [OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id,
1344 [OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session, 1371 [OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session,
1345 [OP_DESTROY_SESSION] = (nfsd4_dec)nfsd4_decode_destroy_session, 1372 [OP_DESTROY_SESSION] = (nfsd4_dec)nfsd4_decode_destroy_session,
@@ -1350,7 +1377,7 @@ static nfsd4_dec nfsd41_dec_ops[] = {
1350 [OP_LAYOUTCOMMIT] = (nfsd4_dec)nfsd4_decode_notsupp, 1377 [OP_LAYOUTCOMMIT] = (nfsd4_dec)nfsd4_decode_notsupp,
1351 [OP_LAYOUTGET] = (nfsd4_dec)nfsd4_decode_notsupp, 1378 [OP_LAYOUTGET] = (nfsd4_dec)nfsd4_decode_notsupp,
1352 [OP_LAYOUTRETURN] = (nfsd4_dec)nfsd4_decode_notsupp, 1379 [OP_LAYOUTRETURN] = (nfsd4_dec)nfsd4_decode_notsupp,
1353 [OP_SECINFO_NO_NAME] = (nfsd4_dec)nfsd4_decode_notsupp, 1380 [OP_SECINFO_NO_NAME] = (nfsd4_dec)nfsd4_decode_secinfo_no_name,
1354 [OP_SEQUENCE] = (nfsd4_dec)nfsd4_decode_sequence, 1381 [OP_SEQUENCE] = (nfsd4_dec)nfsd4_decode_sequence,
1355 [OP_SET_SSV] = (nfsd4_dec)nfsd4_decode_notsupp, 1382 [OP_SET_SSV] = (nfsd4_dec)nfsd4_decode_notsupp,
1356 [OP_TEST_STATEID] = (nfsd4_dec)nfsd4_decode_notsupp, 1383 [OP_TEST_STATEID] = (nfsd4_dec)nfsd4_decode_notsupp,
@@ -1805,19 +1832,23 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1805 goto out_nfserr; 1832 goto out_nfserr;
1806 } 1833 }
1807 } 1834 }
1808 if ((buflen -= 16) < 0)
1809 goto out_resource;
1810 1835
1811 if (unlikely(bmval2)) { 1836 if (bmval2) {
1837 if ((buflen -= 16) < 0)
1838 goto out_resource;
1812 WRITE32(3); 1839 WRITE32(3);
1813 WRITE32(bmval0); 1840 WRITE32(bmval0);
1814 WRITE32(bmval1); 1841 WRITE32(bmval1);
1815 WRITE32(bmval2); 1842 WRITE32(bmval2);
1816 } else if (likely(bmval1)) { 1843 } else if (bmval1) {
1844 if ((buflen -= 12) < 0)
1845 goto out_resource;
1817 WRITE32(2); 1846 WRITE32(2);
1818 WRITE32(bmval0); 1847 WRITE32(bmval0);
1819 WRITE32(bmval1); 1848 WRITE32(bmval1);
1820 } else { 1849 } else {
1850 if ((buflen -= 8) < 0)
1851 goto out_resource;
1821 WRITE32(1); 1852 WRITE32(1);
1822 WRITE32(bmval0); 1853 WRITE32(bmval0);
1823 } 1854 }
@@ -1828,15 +1859,17 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1828 u32 word1 = nfsd_suppattrs1(minorversion); 1859 u32 word1 = nfsd_suppattrs1(minorversion);
1829 u32 word2 = nfsd_suppattrs2(minorversion); 1860 u32 word2 = nfsd_suppattrs2(minorversion);
1830 1861
1831 if ((buflen -= 12) < 0)
1832 goto out_resource;
1833 if (!aclsupport) 1862 if (!aclsupport)
1834 word0 &= ~FATTR4_WORD0_ACL; 1863 word0 &= ~FATTR4_WORD0_ACL;
1835 if (!word2) { 1864 if (!word2) {
1865 if ((buflen -= 12) < 0)
1866 goto out_resource;
1836 WRITE32(2); 1867 WRITE32(2);
1837 WRITE32(word0); 1868 WRITE32(word0);
1838 WRITE32(word1); 1869 WRITE32(word1);
1839 } else { 1870 } else {
1871 if ((buflen -= 16) < 0)
1872 goto out_resource;
1840 WRITE32(3); 1873 WRITE32(3);
1841 WRITE32(word0); 1874 WRITE32(word0);
1842 WRITE32(word1); 1875 WRITE32(word1);
@@ -2303,8 +2336,6 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
2303 case nfserr_resource: 2336 case nfserr_resource:
2304 nfserr = nfserr_toosmall; 2337 nfserr = nfserr_toosmall;
2305 goto fail; 2338 goto fail;
2306 case nfserr_dropit:
2307 goto fail;
2308 case nfserr_noent: 2339 case nfserr_noent:
2309 goto skip_entry; 2340 goto skip_entry;
2310 default: 2341 default:
@@ -2359,6 +2390,21 @@ nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
2359 return nfserr; 2390 return nfserr;
2360} 2391}
2361 2392
2393static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_bind_conn_to_session *bcts)
2394{
2395 __be32 *p;
2396
2397 if (!nfserr) {
2398 RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 8);
2399 WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN);
2400 WRITE32(bcts->dir);
2401 /* XXX: ? */
2402 WRITE32(0);
2403 ADJUST_ARGS();
2404 }
2405 return nfserr;
2406}
2407
2362static __be32 2408static __be32
2363nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close) 2409nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close)
2364{ 2410{
@@ -2820,11 +2866,10 @@ nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_
2820} 2866}
2821 2867
2822static __be32 2868static __be32
2823nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr, 2869nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp,
2824 struct nfsd4_secinfo *secinfo) 2870 __be32 nfserr,struct svc_export *exp)
2825{ 2871{
2826 int i = 0; 2872 int i = 0;
2827 struct svc_export *exp = secinfo->si_exp;
2828 u32 nflavs; 2873 u32 nflavs;
2829 struct exp_flavor_info *flavs; 2874 struct exp_flavor_info *flavs;
2830 struct exp_flavor_info def_flavs[2]; 2875 struct exp_flavor_info def_flavs[2];
@@ -2886,6 +2931,20 @@ out:
2886 return nfserr; 2931 return nfserr;
2887} 2932}
2888 2933
2934static __be32
2935nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
2936 struct nfsd4_secinfo *secinfo)
2937{
2938 return nfsd4_do_encode_secinfo(resp, nfserr, secinfo->si_exp);
2939}
2940
2941static __be32
2942nfsd4_encode_secinfo_no_name(struct nfsd4_compoundres *resp, __be32 nfserr,
2943 struct nfsd4_secinfo_no_name *secinfo)
2944{
2945 return nfsd4_do_encode_secinfo(resp, nfserr, secinfo->sin_exp);
2946}
2947
2889/* 2948/*
2890 * The SETATTR encode routine is special -- it always encodes a bitmap, 2949 * The SETATTR encode routine is special -- it always encodes a bitmap,
2891 * regardless of the error status. 2950 * regardless of the error status.
@@ -3056,7 +3115,7 @@ nfsd4_encode_destroy_session(struct nfsd4_compoundres *resp, int nfserr,
3056 return nfserr; 3115 return nfserr;
3057} 3116}
3058 3117
3059__be32 3118static __be32
3060nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr, 3119nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr,
3061 struct nfsd4_sequence *seq) 3120 struct nfsd4_sequence *seq)
3062{ 3121{
@@ -3070,13 +3129,9 @@ nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr,
3070 WRITE32(seq->seqid); 3129 WRITE32(seq->seqid);
3071 WRITE32(seq->slotid); 3130 WRITE32(seq->slotid);
3072 WRITE32(seq->maxslots); 3131 WRITE32(seq->maxslots);
3073 /* 3132 /* For now: target_maxslots = maxslots */
3074 * FIXME: for now:
3075 * target_maxslots = maxslots
3076 * status_flags = 0
3077 */
3078 WRITE32(seq->maxslots); 3133 WRITE32(seq->maxslots);
3079 WRITE32(0); 3134 WRITE32(seq->status_flags);
3080 3135
3081 ADJUST_ARGS(); 3136 ADJUST_ARGS();
3082 resp->cstate.datap = p; /* DRC cache data pointer */ 3137 resp->cstate.datap = p; /* DRC cache data pointer */
@@ -3137,7 +3192,7 @@ static nfsd4_enc nfsd4_enc_ops[] = {
3137 3192
3138 /* NFSv4.1 operations */ 3193 /* NFSv4.1 operations */
3139 [OP_BACKCHANNEL_CTL] = (nfsd4_enc)nfsd4_encode_noop, 3194 [OP_BACKCHANNEL_CTL] = (nfsd4_enc)nfsd4_encode_noop,
3140 [OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_noop, 3195 [OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_bind_conn_to_session,
3141 [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id, 3196 [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id,
3142 [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session, 3197 [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session,
3143 [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_destroy_session, 3198 [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_destroy_session,
@@ -3148,7 +3203,7 @@ static nfsd4_enc nfsd4_enc_ops[] = {
3148 [OP_LAYOUTCOMMIT] = (nfsd4_enc)nfsd4_encode_noop, 3203 [OP_LAYOUTCOMMIT] = (nfsd4_enc)nfsd4_encode_noop,
3149 [OP_LAYOUTGET] = (nfsd4_enc)nfsd4_encode_noop, 3204 [OP_LAYOUTGET] = (nfsd4_enc)nfsd4_encode_noop,
3150 [OP_LAYOUTRETURN] = (nfsd4_enc)nfsd4_encode_noop, 3205 [OP_LAYOUTRETURN] = (nfsd4_enc)nfsd4_encode_noop,
3151 [OP_SECINFO_NO_NAME] = (nfsd4_enc)nfsd4_encode_noop, 3206 [OP_SECINFO_NO_NAME] = (nfsd4_enc)nfsd4_encode_secinfo_no_name,
3152 [OP_SEQUENCE] = (nfsd4_enc)nfsd4_encode_sequence, 3207 [OP_SEQUENCE] = (nfsd4_enc)nfsd4_encode_sequence,
3153 [OP_SET_SSV] = (nfsd4_enc)nfsd4_encode_noop, 3208 [OP_SET_SSV] = (nfsd4_enc)nfsd4_encode_noop,
3154 [OP_TEST_STATEID] = (nfsd4_enc)nfsd4_encode_noop, 3209 [OP_TEST_STATEID] = (nfsd4_enc)nfsd4_encode_noop,
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index b53b1d042f1f..2b1449dd2f49 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -8,20 +8,23 @@
8#include <linux/namei.h> 8#include <linux/namei.h>
9#include <linux/ctype.h> 9#include <linux/ctype.h>
10 10
11#include <linux/nfsd_idmap.h>
12#include <linux/sunrpc/svcsock.h> 11#include <linux/sunrpc/svcsock.h>
13#include <linux/nfsd/syscall.h> 12#include <linux/nfsd/syscall.h>
14#include <linux/lockd/lockd.h> 13#include <linux/lockd/lockd.h>
15#include <linux/sunrpc/clnt.h> 14#include <linux/sunrpc/clnt.h>
15#include <linux/sunrpc/gss_api.h>
16#include <linux/sunrpc/gss_krb5_enctypes.h>
16 17
18#include "idmap.h"
17#include "nfsd.h" 19#include "nfsd.h"
18#include "cache.h" 20#include "cache.h"
19 21
20/* 22/*
21 * We have a single directory with 9 nodes in it. 23 * We have a single directory with several nodes in it.
22 */ 24 */
23enum { 25enum {
24 NFSD_Root = 1, 26 NFSD_Root = 1,
27#ifdef CONFIG_NFSD_DEPRECATED
25 NFSD_Svc, 28 NFSD_Svc,
26 NFSD_Add, 29 NFSD_Add,
27 NFSD_Del, 30 NFSD_Del,
@@ -29,6 +32,7 @@ enum {
29 NFSD_Unexport, 32 NFSD_Unexport,
30 NFSD_Getfd, 33 NFSD_Getfd,
31 NFSD_Getfs, 34 NFSD_Getfs,
35#endif
32 NFSD_List, 36 NFSD_List,
33 NFSD_Export_features, 37 NFSD_Export_features,
34 NFSD_Fh, 38 NFSD_Fh,
@@ -40,6 +44,7 @@ enum {
40 NFSD_Versions, 44 NFSD_Versions,
41 NFSD_Ports, 45 NFSD_Ports,
42 NFSD_MaxBlkSize, 46 NFSD_MaxBlkSize,
47 NFSD_SupportedEnctypes,
43 /* 48 /*
44 * The below MUST come last. Otherwise we leave a hole in nfsd_files[] 49 * The below MUST come last. Otherwise we leave a hole in nfsd_files[]
45 * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops 50 * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops
@@ -54,6 +59,7 @@ enum {
54/* 59/*
55 * write() for these nodes. 60 * write() for these nodes.
56 */ 61 */
62#ifdef CONFIG_NFSD_DEPRECATED
57static ssize_t write_svc(struct file *file, char *buf, size_t size); 63static ssize_t write_svc(struct file *file, char *buf, size_t size);
58static ssize_t write_add(struct file *file, char *buf, size_t size); 64static ssize_t write_add(struct file *file, char *buf, size_t size);
59static ssize_t write_del(struct file *file, char *buf, size_t size); 65static ssize_t write_del(struct file *file, char *buf, size_t size);
@@ -61,6 +67,7 @@ static ssize_t write_export(struct file *file, char *buf, size_t size);
61static ssize_t write_unexport(struct file *file, char *buf, size_t size); 67static ssize_t write_unexport(struct file *file, char *buf, size_t size);
62static ssize_t write_getfd(struct file *file, char *buf, size_t size); 68static ssize_t write_getfd(struct file *file, char *buf, size_t size);
63static ssize_t write_getfs(struct file *file, char *buf, size_t size); 69static ssize_t write_getfs(struct file *file, char *buf, size_t size);
70#endif
64static ssize_t write_filehandle(struct file *file, char *buf, size_t size); 71static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
65static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size); 72static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size);
66static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size); 73static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size);
@@ -76,6 +83,7 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
76#endif 83#endif
77 84
78static ssize_t (*write_op[])(struct file *, char *, size_t) = { 85static ssize_t (*write_op[])(struct file *, char *, size_t) = {
86#ifdef CONFIG_NFSD_DEPRECATED
79 [NFSD_Svc] = write_svc, 87 [NFSD_Svc] = write_svc,
80 [NFSD_Add] = write_add, 88 [NFSD_Add] = write_add,
81 [NFSD_Del] = write_del, 89 [NFSD_Del] = write_del,
@@ -83,6 +91,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
83 [NFSD_Unexport] = write_unexport, 91 [NFSD_Unexport] = write_unexport,
84 [NFSD_Getfd] = write_getfd, 92 [NFSD_Getfd] = write_getfd,
85 [NFSD_Getfs] = write_getfs, 93 [NFSD_Getfs] = write_getfs,
94#endif
86 [NFSD_Fh] = write_filehandle, 95 [NFSD_Fh] = write_filehandle,
87 [NFSD_FO_UnlockIP] = write_unlock_ip, 96 [NFSD_FO_UnlockIP] = write_unlock_ip,
88 [NFSD_FO_UnlockFS] = write_unlock_fs, 97 [NFSD_FO_UnlockFS] = write_unlock_fs,
@@ -121,6 +130,16 @@ static ssize_t nfsctl_transaction_write(struct file *file, const char __user *bu
121 130
122static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos) 131static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
123{ 132{
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
124 if (! file->private_data) { 143 if (! file->private_data) {
125 /* An attempt to read a transaction file without writing 144 /* An attempt to read a transaction file without writing
126 * causes a 0-byte write so that the file can return 145 * causes a 0-byte write so that the file can return
@@ -137,6 +156,7 @@ static const struct file_operations transaction_ops = {
137 .write = nfsctl_transaction_write, 156 .write = nfsctl_transaction_write,
138 .read = nfsctl_transaction_read, 157 .read = nfsctl_transaction_read,
139 .release = simple_transaction_release, 158 .release = simple_transaction_release,
159 .llseek = default_llseek,
140}; 160};
141 161
142static int exports_open(struct inode *inode, struct file *file) 162static int exports_open(struct inode *inode, struct file *file)
@@ -170,6 +190,26 @@ static struct file_operations export_features_operations = {
170 .release = single_release, 190 .release = single_release,
171}; 191};
172 192
193#if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE)
194static int supported_enctypes_show(struct seq_file *m, void *v)
195{
196 seq_printf(m, KRB5_SUPPORTED_ENCTYPES);
197 return 0;
198}
199
200static int supported_enctypes_open(struct inode *inode, struct file *file)
201{
202 return single_open(file, supported_enctypes_show, NULL);
203}
204
205static struct file_operations supported_enctypes_ops = {
206 .open = supported_enctypes_open,
207 .read = seq_read,
208 .llseek = seq_lseek,
209 .release = single_release,
210};
211#endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
212
173extern int nfsd_pool_stats_open(struct inode *inode, struct file *file); 213extern int nfsd_pool_stats_open(struct inode *inode, struct file *file);
174extern int nfsd_pool_stats_release(struct inode *inode, struct file *file); 214extern int nfsd_pool_stats_release(struct inode *inode, struct file *file);
175 215
@@ -186,6 +226,7 @@ static const struct file_operations pool_stats_operations = {
186 * payload - write methods 226 * payload - write methods
187 */ 227 */
188 228
229#ifdef CONFIG_NFSD_DEPRECATED
189/** 230/**
190 * write_svc - Start kernel's NFSD server 231 * write_svc - Start kernel's NFSD server
191 * 232 *
@@ -401,7 +442,7 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size)
401 442
402 ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6); 443 ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
403 444
404 clp = auth_unix_lookup(&in6); 445 clp = auth_unix_lookup(&init_net, &in6);
405 if (!clp) 446 if (!clp)
406 err = -EPERM; 447 err = -EPERM;
407 else { 448 else {
@@ -464,7 +505,7 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
464 505
465 ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6); 506 ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
466 507
467 clp = auth_unix_lookup(&in6); 508 clp = auth_unix_lookup(&init_net, &in6);
468 if (!clp) 509 if (!clp)
469 err = -EPERM; 510 err = -EPERM;
470 else { 511 else {
@@ -481,6 +522,7 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
481 out: 522 out:
482 return err; 523 return err;
483} 524}
525#endif /* CONFIG_NFSD_DEPRECATED */
484 526
485/** 527/**
486 * write_unlock_ip - Release all locks used by a client 528 * write_unlock_ip - Release all locks used by a client
@@ -999,12 +1041,12 @@ static ssize_t __write_ports_addxprt(char *buf)
999 if (err != 0) 1041 if (err != 0)
1000 return err; 1042 return err;
1001 1043
1002 err = svc_create_xprt(nfsd_serv, transport, 1044 err = svc_create_xprt(nfsd_serv, transport, &init_net,
1003 PF_INET, port, SVC_SOCK_ANONYMOUS); 1045 PF_INET, port, SVC_SOCK_ANONYMOUS);
1004 if (err < 0) 1046 if (err < 0)
1005 goto out_err; 1047 goto out_err;
1006 1048
1007 err = svc_create_xprt(nfsd_serv, transport, 1049 err = svc_create_xprt(nfsd_serv, transport, &init_net,
1008 PF_INET6, port, SVC_SOCK_ANONYMOUS); 1050 PF_INET6, port, SVC_SOCK_ANONYMOUS);
1009 if (err < 0 && err != -EAFNOSUPPORT) 1051 if (err < 0 && err != -EAFNOSUPPORT)
1010 goto out_close; 1052 goto out_close;
@@ -1355,6 +1397,7 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
1355static int nfsd_fill_super(struct super_block * sb, void * data, int silent) 1397static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
1356{ 1398{
1357 static struct tree_descr nfsd_files[] = { 1399 static struct tree_descr nfsd_files[] = {
1400#ifdef CONFIG_NFSD_DEPRECATED
1358 [NFSD_Svc] = {".svc", &transaction_ops, S_IWUSR}, 1401 [NFSD_Svc] = {".svc", &transaction_ops, S_IWUSR},
1359 [NFSD_Add] = {".add", &transaction_ops, S_IWUSR}, 1402 [NFSD_Add] = {".add", &transaction_ops, S_IWUSR},
1360 [NFSD_Del] = {".del", &transaction_ops, S_IWUSR}, 1403 [NFSD_Del] = {".del", &transaction_ops, S_IWUSR},
@@ -1362,6 +1405,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
1362 [NFSD_Unexport] = {".unexport", &transaction_ops, S_IWUSR}, 1405 [NFSD_Unexport] = {".unexport", &transaction_ops, S_IWUSR},
1363 [NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR}, 1406 [NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
1364 [NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR}, 1407 [NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
1408#endif
1365 [NFSD_List] = {"exports", &exports_operations, S_IRUGO}, 1409 [NFSD_List] = {"exports", &exports_operations, S_IRUGO},
1366 [NFSD_Export_features] = {"export_features", 1410 [NFSD_Export_features] = {"export_features",
1367 &export_features_operations, S_IRUGO}, 1411 &export_features_operations, S_IRUGO},
@@ -1376,6 +1420,9 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
1376 [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, 1420 [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
1377 [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, 1421 [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
1378 [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, 1422 [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO},
1423#if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE)
1424 [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO},
1425#endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
1379#ifdef CONFIG_NFSD_V4 1426#ifdef CONFIG_NFSD_V4
1380 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, 1427 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
1381 [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR}, 1428 [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR},
@@ -1386,16 +1433,16 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
1386 return simple_fill_super(sb, 0x6e667364, nfsd_files); 1433 return simple_fill_super(sb, 0x6e667364, nfsd_files);
1387} 1434}
1388 1435
1389static int nfsd_get_sb(struct file_system_type *fs_type, 1436static struct dentry *nfsd_mount(struct file_system_type *fs_type,
1390 int flags, const char *dev_name, void *data, struct vfsmount *mnt) 1437 int flags, const char *dev_name, void *data)
1391{ 1438{
1392 return get_sb_single(fs_type, flags, data, nfsd_fill_super, mnt); 1439 return mount_single(fs_type, flags, data, nfsd_fill_super);
1393} 1440}
1394 1441
1395static struct file_system_type nfsd_fs_type = { 1442static struct file_system_type nfsd_fs_type = {
1396 .owner = THIS_MODULE, 1443 .owner = THIS_MODULE,
1397 .name = "nfsd", 1444 .name = "nfsd",
1398 .get_sb = nfsd_get_sb, 1445 .mount = nfsd_mount,
1399 .kill_sb = kill_litter_super, 1446 .kill_sb = kill_litter_super,
1400}; 1447};
1401 1448
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index b76ac3a82e39..7ecfa2420307 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -158,6 +158,7 @@ void nfsd_lockd_shutdown(void);
158#define nfserr_attrnotsupp cpu_to_be32(NFSERR_ATTRNOTSUPP) 158#define nfserr_attrnotsupp cpu_to_be32(NFSERR_ATTRNOTSUPP)
159#define nfserr_bad_xdr cpu_to_be32(NFSERR_BAD_XDR) 159#define nfserr_bad_xdr cpu_to_be32(NFSERR_BAD_XDR)
160#define nfserr_openmode cpu_to_be32(NFSERR_OPENMODE) 160#define nfserr_openmode cpu_to_be32(NFSERR_OPENMODE)
161#define nfserr_badowner cpu_to_be32(NFSERR_BADOWNER)
161#define nfserr_locks_held cpu_to_be32(NFSERR_LOCKS_HELD) 162#define nfserr_locks_held cpu_to_be32(NFSERR_LOCKS_HELD)
162#define nfserr_op_illegal cpu_to_be32(NFSERR_OP_ILLEGAL) 163#define nfserr_op_illegal cpu_to_be32(NFSERR_OP_ILLEGAL)
163#define nfserr_grace cpu_to_be32(NFSERR_GRACE) 164#define nfserr_grace cpu_to_be32(NFSERR_GRACE)
@@ -249,7 +250,7 @@ extern time_t nfsd4_grace;
249#define COMPOUND_SLACK_SPACE 140 /* OP_GETFH */ 250#define COMPOUND_SLACK_SPACE 140 /* OP_GETFH */
250#define COMPOUND_ERR_SLACK_SPACE 12 /* OP_SETATTR */ 251#define COMPOUND_ERR_SLACK_SPACE 12 /* OP_SETATTR */
251 252
252#define NFSD_LAUNDROMAT_MINTIMEOUT 10 /* seconds */ 253#define NFSD_LAUNDROMAT_MINTIMEOUT 1 /* seconds */
253 254
254/* 255/*
255 * The following attributes are currently not supported by the NFSv4 server: 256 * The following attributes are currently not supported by the NFSv4 server:
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 55c8e63af0be..90c6aa6d5e0f 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -344,7 +344,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, int access)
344 * which clients virtually always use auth_sys for, 344 * which clients virtually always use auth_sys for,
345 * even while using RPCSEC_GSS for NFS. 345 * even while using RPCSEC_GSS for NFS.
346 */ 346 */
347 if (access & NFSD_MAY_LOCK) 347 if (access & NFSD_MAY_LOCK || access & NFSD_MAY_BYPASS_GSS)
348 goto skip_pseudoflavor_check; 348 goto skip_pseudoflavor_check;
349 /* 349 /*
350 * Clients may expect to be able to use auth_sys during mount, 350 * Clients may expect to be able to use auth_sys during mount,
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 08e17264784b..e15dc45fc5ec 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -735,9 +735,9 @@ nfserrno (int errno)
735 { nfserr_stale, -ESTALE }, 735 { nfserr_stale, -ESTALE },
736 { nfserr_jukebox, -ETIMEDOUT }, 736 { nfserr_jukebox, -ETIMEDOUT },
737 { nfserr_jukebox, -ERESTARTSYS }, 737 { nfserr_jukebox, -ERESTARTSYS },
738 { nfserr_dropit, -EAGAIN }, 738 { nfserr_jukebox, -EAGAIN },
739 { nfserr_dropit, -ENOMEM }, 739 { nfserr_jukebox, -EWOULDBLOCK },
740 { nfserr_badname, -ESRCH }, 740 { nfserr_jukebox, -ENOMEM },
741 { nfserr_io, -ETXTBSY }, 741 { nfserr_io, -ETXTBSY },
742 { nfserr_notsupp, -EOPNOTSUPP }, 742 { nfserr_notsupp, -EOPNOTSUPP },
743 { nfserr_toosmall, -ETOOSMALL }, 743 { nfserr_toosmall, -ETOOSMALL },
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index e2c43464f237..18743c4d8bca 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -16,6 +16,7 @@
16#include <linux/lockd/bind.h> 16#include <linux/lockd/bind.h>
17#include <linux/nfsacl.h> 17#include <linux/nfsacl.h>
18#include <linux/seq_file.h> 18#include <linux/seq_file.h>
19#include <net/net_namespace.h>
19#include "nfsd.h" 20#include "nfsd.h"
20#include "cache.h" 21#include "cache.h"
21#include "vfs.h" 22#include "vfs.h"
@@ -186,12 +187,12 @@ static int nfsd_init_socks(int port)
186 if (!list_empty(&nfsd_serv->sv_permsocks)) 187 if (!list_empty(&nfsd_serv->sv_permsocks))
187 return 0; 188 return 0;
188 189
189 error = svc_create_xprt(nfsd_serv, "udp", PF_INET, port, 190 error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, port,
190 SVC_SOCK_DEFAULTS); 191 SVC_SOCK_DEFAULTS);
191 if (error < 0) 192 if (error < 0)
192 return error; 193 return error;
193 194
194 error = svc_create_xprt(nfsd_serv, "tcp", PF_INET, port, 195 error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, port,
195 SVC_SOCK_DEFAULTS); 196 SVC_SOCK_DEFAULTS);
196 if (error < 0) 197 if (error < 0)
197 return error; 198 return error;
@@ -607,7 +608,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
607 /* Now call the procedure handler, and encode NFS status. */ 608 /* Now call the procedure handler, and encode NFS status. */
608 nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); 609 nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);
609 nfserr = map_new_errors(rqstp->rq_vers, nfserr); 610 nfserr = map_new_errors(rqstp->rq_vers, nfserr);
610 if (nfserr == nfserr_dropit) { 611 if (nfserr == nfserr_dropit || rqstp->rq_dropme) {
611 dprintk("nfsd: Dropping request; may be revisited later\n"); 612 dprintk("nfsd: Dropping request; may be revisited later\n");
612 nfsd_cache_update(rqstp, RC_NOCACHE, NULL); 613 nfsd_cache_update(rqstp, RC_NOCACHE, NULL);
613 return 0; 614 return 0;
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 4ce005dbf3e6..65ec595e2226 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -451,7 +451,7 @@ nfssvc_encode_readres(struct svc_rqst *rqstp, __be32 *p,
451 *p++ = htonl(resp->count); 451 *p++ = htonl(resp->count);
452 xdr_ressize_check(rqstp, p); 452 xdr_ressize_check(rqstp, p);
453 453
454 /* now update rqstp->rq_res to reflect data aswell */ 454 /* now update rqstp->rq_res to reflect data as well */
455 rqstp->rq_res.page_len = resp->count; 455 rqstp->rq_res.page_len = resp->count;
456 if (resp->count & 3) { 456 if (resp->count & 3) {
457 /* need to pad the tail */ 457 /* need to pad the tail */
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 322518c88e4b..6bd2f3c21f2b 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -35,6 +35,7 @@
35#ifndef _NFSD4_STATE_H 35#ifndef _NFSD4_STATE_H
36#define _NFSD4_STATE_H 36#define _NFSD4_STATE_H
37 37
38#include <linux/sunrpc/svc_xprt.h>
38#include <linux/nfsd/nfsfh.h> 39#include <linux/nfsd/nfsfh.h>
39#include "nfsfh.h" 40#include "nfsfh.h"
40 41
@@ -64,20 +65,15 @@ typedef struct {
64 (s)->si_fileid, \ 65 (s)->si_fileid, \
65 (s)->si_generation 66 (s)->si_generation
66 67
67struct nfsd4_cb_sequence {
68 /* args/res */
69 u32 cbs_minorversion;
70 struct nfs4_client *cbs_clp;
71};
72
73struct nfs4_rpc_args {
74 void *args_op;
75 struct nfsd4_cb_sequence args_seq;
76};
77
78struct nfsd4_callback { 68struct nfsd4_callback {
79 struct nfs4_rpc_args cb_args; 69 void *cb_op;
70 struct nfs4_client *cb_clp;
71 struct list_head cb_per_client;
72 u32 cb_minorversion;
73 struct rpc_message cb_msg;
74 const struct rpc_call_ops *cb_ops;
80 struct work_struct cb_work; 75 struct work_struct cb_work;
76 bool cb_done;
81}; 77};
82 78
83struct nfs4_delegation { 79struct nfs4_delegation {
@@ -87,11 +83,9 @@ struct nfs4_delegation {
87 atomic_t dl_count; /* ref count */ 83 atomic_t dl_count; /* ref count */
88 struct nfs4_client *dl_client; 84 struct nfs4_client *dl_client;
89 struct nfs4_file *dl_file; 85 struct nfs4_file *dl_file;
90 struct file_lock *dl_flock;
91 u32 dl_type; 86 u32 dl_type;
92 time_t dl_time; 87 time_t dl_time;
93/* For recall: */ 88/* For recall: */
94 u32 dl_ident;
95 stateid_t dl_stateid; 89 stateid_t dl_stateid;
96 struct knfsd_fh dl_fh; 90 struct knfsd_fh dl_fh;
97 int dl_retries; 91 int dl_retries;
@@ -102,9 +96,10 @@ struct nfs4_delegation {
102struct nfs4_cb_conn { 96struct nfs4_cb_conn {
103 /* SETCLIENTID info */ 97 /* SETCLIENTID info */
104 struct sockaddr_storage cb_addr; 98 struct sockaddr_storage cb_addr;
99 struct sockaddr_storage cb_saddr;
105 size_t cb_addrlen; 100 size_t cb_addrlen;
106 u32 cb_prog; 101 u32 cb_prog; /* used only in 4.0 case;
107 u32 cb_minorversion; 102 per-session otherwise */
108 u32 cb_ident; /* minorversion 0 only */ 103 u32 cb_ident; /* minorversion 0 only */
109 struct svc_xprt *cb_xprt; /* minorversion 1 only */ 104 struct svc_xprt *cb_xprt; /* minorversion 1 only */
110}; 105};
@@ -153,6 +148,11 @@ struct nfsd4_create_session {
153 u32 gid; 148 u32 gid;
154}; 149};
155 150
151struct nfsd4_bind_conn_to_session {
152 struct nfs4_sessionid sessionid;
153 u32 dir;
154};
155
156/* The single slot clientid cache structure */ 156/* The single slot clientid cache structure */
157struct nfsd4_clid_slot { 157struct nfsd4_clid_slot {
158 u32 sl_seqid; 158 u32 sl_seqid;
@@ -160,6 +160,15 @@ struct nfsd4_clid_slot {
160 struct nfsd4_create_session sl_cr_ses; 160 struct nfsd4_create_session sl_cr_ses;
161}; 161};
162 162
163struct nfsd4_conn {
164 struct list_head cn_persession;
165 struct svc_xprt *cn_xprt;
166 struct svc_xpt_user cn_xpt_user;
167 struct nfsd4_session *cn_session;
168/* CDFC4_FORE, CDFC4_BACK: */
169 unsigned char cn_flags;
170};
171
163struct nfsd4_session { 172struct nfsd4_session {
164 struct kref se_ref; 173 struct kref se_ref;
165 struct list_head se_hash; /* hash by sessionid */ 174 struct list_head se_hash; /* hash by sessionid */
@@ -169,6 +178,9 @@ struct nfsd4_session {
169 struct nfs4_sessionid se_sessionid; 178 struct nfs4_sessionid se_sessionid;
170 struct nfsd4_channel_attrs se_fchannel; 179 struct nfsd4_channel_attrs se_fchannel;
171 struct nfsd4_channel_attrs se_bchannel; 180 struct nfsd4_channel_attrs se_bchannel;
181 struct list_head se_conns;
182 u32 se_cb_prog;
183 u32 se_cb_seq_nr;
172 struct nfsd4_slot *se_slots[]; /* forward channel slots */ 184 struct nfsd4_slot *se_slots[]; /* forward channel slots */
173}; 185};
174 186
@@ -221,24 +233,36 @@ struct nfs4_client {
221 clientid_t cl_clientid; /* generated by server */ 233 clientid_t cl_clientid; /* generated by server */
222 nfs4_verifier cl_confirm; /* generated by server */ 234 nfs4_verifier cl_confirm; /* generated by server */
223 u32 cl_firststate; /* recovery dir creation */ 235 u32 cl_firststate; /* recovery dir creation */
236 u32 cl_minorversion;
224 237
225 /* for v4.0 and v4.1 callbacks: */ 238 /* for v4.0 and v4.1 callbacks: */
226 struct nfs4_cb_conn cl_cb_conn; 239 struct nfs4_cb_conn cl_cb_conn;
240#define NFSD4_CLIENT_CB_UPDATE 1
241#define NFSD4_CLIENT_KILL 2
242 unsigned long cl_cb_flags;
227 struct rpc_clnt *cl_cb_client; 243 struct rpc_clnt *cl_cb_client;
228 atomic_t cl_cb_set; 244 u32 cl_cb_ident;
245#define NFSD4_CB_UP 0
246#define NFSD4_CB_UNKNOWN 1
247#define NFSD4_CB_DOWN 2
248 int cl_cb_state;
249 struct nfsd4_callback cl_cb_null;
250 struct nfsd4_session *cl_cb_session;
251 struct list_head cl_callbacks; /* list of in-progress callbacks */
252
253 /* for all client information that callback code might need: */
254 spinlock_t cl_lock;
229 255
230 /* for nfs41 */ 256 /* for nfs41 */
231 struct list_head cl_sessions; 257 struct list_head cl_sessions;
232 struct nfsd4_clid_slot cl_cs_slot; /* create_session slot */ 258 struct nfsd4_clid_slot cl_cs_slot; /* create_session slot */
233 u32 cl_exchange_flags; 259 u32 cl_exchange_flags;
234 struct nfs4_sessionid cl_sessionid;
235 /* number of rpc's in progress over an associated session: */ 260 /* number of rpc's in progress over an associated session: */
236 atomic_t cl_refcount; 261 atomic_t cl_refcount;
237 262
238 /* for nfs41 callbacks */ 263 /* for nfs41 callbacks */
239 /* We currently support a single back channel with a single slot */ 264 /* We currently support a single back channel with a single slot */
240 unsigned long cl_cb_slot_busy; 265 unsigned long cl_cb_slot_busy;
241 u32 cl_cb_seq_nr;
242 struct rpc_wait_queue cl_cb_waitq; /* backchannel callers may */ 266 struct rpc_wait_queue cl_cb_waitq; /* backchannel callers may */
243 /* wait here for slots */ 267 /* wait here for slots */
244}; 268};
@@ -343,16 +367,15 @@ struct nfs4_file {
343 struct list_head fi_delegations; 367 struct list_head fi_delegations;
344 /* One each for O_RDONLY, O_WRONLY, O_RDWR: */ 368 /* One each for O_RDONLY, O_WRONLY, O_RDWR: */
345 struct file * fi_fds[3]; 369 struct file * fi_fds[3];
346 /* One each for O_RDONLY, O_WRONLY: */
347 atomic_t fi_access[2];
348 /* 370 /*
349 * Each open stateid contributes 1 to either fi_readers or 371 * Each open or lock stateid contributes 1 to either
350 * fi_writers, or both, depending on the open mode. A 372 * fi_access[O_RDONLY], fi_access[O_WRONLY], or both, depending
351 * delegation also takes an fi_readers reference. Lock 373 * on open or lock mode:
352 * stateid's take none.
353 */ 374 */
354 atomic_t fi_readers; 375 atomic_t fi_access[2];
355 atomic_t fi_writers; 376 struct file *fi_deleg_file;
377 struct file_lock *fi_lease;
378 atomic_t fi_delegees;
356 struct inode *fi_inode; 379 struct inode *fi_inode;
357 u32 fi_id; /* used with stateowner->so_id 380 u32 fi_id; /* used with stateowner->so_id
358 * for stateid_hashtbl hash */ 381 * for stateid_hashtbl hash */
@@ -440,12 +463,14 @@ extern int nfs4_in_grace(void);
440extern __be32 nfs4_check_open_reclaim(clientid_t *clid); 463extern __be32 nfs4_check_open_reclaim(clientid_t *clid);
441extern void nfs4_free_stateowner(struct kref *kref); 464extern void nfs4_free_stateowner(struct kref *kref);
442extern int set_callback_cred(void); 465extern int set_callback_cred(void);
443extern void nfsd4_probe_callback(struct nfs4_client *clp, struct nfs4_cb_conn *); 466extern void nfsd4_probe_callback(struct nfs4_client *clp);
467extern void nfsd4_probe_callback_sync(struct nfs4_client *clp);
468extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *);
444extern void nfsd4_do_callback_rpc(struct work_struct *); 469extern void nfsd4_do_callback_rpc(struct work_struct *);
445extern void nfsd4_cb_recall(struct nfs4_delegation *dp); 470extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
446extern int nfsd4_create_callback_queue(void); 471extern int nfsd4_create_callback_queue(void);
447extern void nfsd4_destroy_callback_queue(void); 472extern void nfsd4_destroy_callback_queue(void);
448extern void nfsd4_set_callback_client(struct nfs4_client *, struct rpc_clnt *); 473extern void nfsd4_shutdown_callback(struct nfs4_client *);
449extern void nfs4_put_delegation(struct nfs4_delegation *dp); 474extern void nfs4_put_delegation(struct nfs4_delegation *dp);
450extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname); 475extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
451extern void nfsd4_init_recdir(char *recdir_name); 476extern void nfsd4_init_recdir(char *recdir_name);
diff --git a/fs/nfsd/stats.c b/fs/nfsd/stats.c
index 5232d3e8fb2f..a2e2402b2afb 100644
--- a/fs/nfsd/stats.c
+++ b/fs/nfsd/stats.c
@@ -8,7 +8,7 @@
8 * Statistsics for the reply cache 8 * Statistsics for the reply cache
9 * fh <stale> <total-lookups> <anonlookups> <dir-not-in-dcache> <nondir-not-in-dcache> 9 * fh <stale> <total-lookups> <anonlookups> <dir-not-in-dcache> <nondir-not-in-dcache>
10 * statistics for filehandle lookup 10 * statistics for filehandle lookup
11 * io <bytes-read> <bytes-writtten> 11 * io <bytes-read> <bytes-written>
12 * statistics for IO throughput 12 * statistics for IO throughput
13 * th <threads> <fullcnt> <10%-20%> <20%-30%> ... <90%-100%> <100%> 13 * th <threads> <fullcnt> <10%-20%> <20%-30%> ... <90%-100%> <100%>
14 * time (seconds) when nfsd thread usage above thresholds 14 * time (seconds) when nfsd thread usage above thresholds
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 661a6cf8e826..fd0acca5370a 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1,4 +1,3 @@
1#define MSNFS /* HACK HACK */
2/* 1/*
3 * File operations used by nfsd. Some of these have been ripped from 2 * File operations used by nfsd. Some of these have been ripped from
4 * other parts of the kernel because they weren't exported, others 3 * other parts of the kernel because they weren't exported, others
@@ -35,8 +34,8 @@
35#endif /* CONFIG_NFSD_V3 */ 34#endif /* CONFIG_NFSD_V3 */
36 35
37#ifdef CONFIG_NFSD_V4 36#ifdef CONFIG_NFSD_V4
38#include <linux/nfs4_acl.h> 37#include "acl.h"
39#include <linux/nfsd_idmap.h> 38#include "idmap.h"
40#endif /* CONFIG_NFSD_V4 */ 39#endif /* CONFIG_NFSD_V4 */
41 40
42#include "nfsd.h" 41#include "nfsd.h"
@@ -88,8 +87,9 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
88 .dentry = dget(dentry)}; 87 .dentry = dget(dentry)};
89 int err = 0; 88 int err = 0;
90 89
91 while (d_mountpoint(path.dentry) && follow_down(&path)) 90 err = follow_down(&path);
92 ; 91 if (err < 0)
92 goto out;
93 93
94 exp2 = rqst_exp_get_by_name(rqstp, &path); 94 exp2 = rqst_exp_get_by_name(rqstp, &path);
95 if (IS_ERR(exp2)) { 95 if (IS_ERR(exp2)) {
@@ -181,16 +181,10 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp,
181 struct svc_export *exp; 181 struct svc_export *exp;
182 struct dentry *dparent; 182 struct dentry *dparent;
183 struct dentry *dentry; 183 struct dentry *dentry;
184 __be32 err;
185 int host_err; 184 int host_err;
186 185
187 dprintk("nfsd: nfsd_lookup(fh %s, %.*s)\n", SVCFH_fmt(fhp), len,name); 186 dprintk("nfsd: nfsd_lookup(fh %s, %.*s)\n", SVCFH_fmt(fhp), len,name);
188 187
189 /* Obtain dentry and export. */
190 err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
191 if (err)
192 return err;
193
194 dparent = fhp->fh_dentry; 188 dparent = fhp->fh_dentry;
195 exp = fhp->fh_export; 189 exp = fhp->fh_export;
196 exp_get(exp); 190 exp_get(exp);
@@ -254,6 +248,9 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
254 struct dentry *dentry; 248 struct dentry *dentry;
255 __be32 err; 249 __be32 err;
256 250
251 err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
252 if (err)
253 return err;
257 err = nfsd_lookup_dentry(rqstp, fhp, name, len, &exp, &dentry); 254 err = nfsd_lookup_dentry(rqstp, fhp, name, len, &exp, &dentry);
258 if (err) 255 if (err)
259 return err; 256 return err;
@@ -273,6 +270,13 @@ out:
273 return err; 270 return err;
274} 271}
275 272
273static int nfsd_break_lease(struct inode *inode)
274{
275 if (!S_ISREG(inode->i_mode))
276 return 0;
277 return break_lease(inode, O_WRONLY | O_NONBLOCK);
278}
279
276/* 280/*
277 * Commit metadata changes to stable storage. 281 * Commit metadata changes to stable storage.
278 */ 282 */
@@ -281,23 +285,13 @@ commit_metadata(struct svc_fh *fhp)
281{ 285{
282 struct inode *inode = fhp->fh_dentry->d_inode; 286 struct inode *inode = fhp->fh_dentry->d_inode;
283 const struct export_operations *export_ops = inode->i_sb->s_export_op; 287 const struct export_operations *export_ops = inode->i_sb->s_export_op;
284 int error = 0;
285 288
286 if (!EX_ISSYNC(fhp->fh_export)) 289 if (!EX_ISSYNC(fhp->fh_export))
287 return 0; 290 return 0;
288 291
289 if (export_ops->commit_metadata) { 292 if (export_ops->commit_metadata)
290 error = export_ops->commit_metadata(inode); 293 return export_ops->commit_metadata(inode);
291 } else { 294 return sync_inode_metadata(inode, 1);
292 struct writeback_control wbc = {
293 .sync_mode = WB_SYNC_ALL,
294 .nr_to_write = 0, /* metadata only */
295 };
296
297 error = sync_inode(inode, &wbc);
298 }
299
300 return error;
301} 295}
302 296
303/* 297/*
@@ -385,16 +379,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
385 goto out; 379 goto out;
386 } 380 }
387 381
388 /*
389 * If we are changing the size of the file, then
390 * we need to break all leases.
391 */
392 host_err = break_lease(inode, O_WRONLY | O_NONBLOCK);
393 if (host_err == -EWOULDBLOCK)
394 host_err = -ETIMEDOUT;
395 if (host_err) /* ENOMEM or EWOULDBLOCK */
396 goto out_nfserr;
397
398 host_err = get_write_access(inode); 382 host_err = get_write_access(inode);
399 if (host_err) 383 if (host_err)
400 goto out_nfserr; 384 goto out_nfserr;
@@ -435,7 +419,11 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
435 419
436 err = nfserr_notsync; 420 err = nfserr_notsync;
437 if (!check_guard || guardtime == inode->i_ctime.tv_sec) { 421 if (!check_guard || guardtime == inode->i_ctime.tv_sec) {
422 host_err = nfsd_break_lease(inode);
423 if (host_err)
424 goto out_nfserr;
438 fh_lock(fhp); 425 fh_lock(fhp);
426
439 host_err = notify_change(dentry, iap); 427 host_err = notify_change(dentry, iap);
440 err = nfserrno(host_err); 428 err = nfserrno(host_err);
441 fh_unlock(fhp); 429 fh_unlock(fhp);
@@ -708,7 +696,15 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor
708} 696}
709#endif /* CONFIG_NFSD_V3 */ 697#endif /* CONFIG_NFSD_V3 */
710 698
699static int nfsd_open_break_lease(struct inode *inode, int access)
700{
701 unsigned int mode;
711 702
703 if (access & NFSD_MAY_NOT_BREAK_LEASE)
704 return 0;
705 mode = (access & NFSD_MAY_WRITE) ? O_WRONLY : O_RDONLY;
706 return break_lease(inode, mode | O_NONBLOCK);
707}
712 708
713/* 709/*
714 * Open an existing file or directory. 710 * Open an existing file or directory.
@@ -756,14 +752,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
756 if (!inode->i_fop) 752 if (!inode->i_fop)
757 goto out; 753 goto out;
758 754
759 /* 755 host_err = nfsd_open_break_lease(inode, access);
760 * Check to see if there are any leases on this file.
761 * This may block while leases are broken.
762 */
763 if (!(access & NFSD_MAY_NOT_BREAK_LEASE))
764 host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? O_WRONLY : 0));
765 if (host_err == -EWOULDBLOCK)
766 host_err = -ETIMEDOUT;
767 if (host_err) /* NOMEM or WOULDBLOCK */ 756 if (host_err) /* NOMEM or WOULDBLOCK */
768 goto out_nfserr; 757 goto out_nfserr;
769 758
@@ -819,7 +808,7 @@ nfsd_get_raparms(dev_t dev, ino_t ino)
819 if (ra->p_count == 0) 808 if (ra->p_count == 0)
820 frap = rap; 809 frap = rap;
821 } 810 }
822 depth = nfsdstats.ra_size*11/10; 811 depth = nfsdstats.ra_size;
823 if (!frap) { 812 if (!frap) {
824 spin_unlock(&rab->pb_lock); 813 spin_unlock(&rab->pb_lock);
825 return NULL; 814 return NULL;
@@ -855,11 +844,6 @@ nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
855 struct page **pp = rqstp->rq_respages + rqstp->rq_resused; 844 struct page **pp = rqstp->rq_respages + rqstp->rq_resused;
856 struct page *page = buf->page; 845 struct page *page = buf->page;
857 size_t size; 846 size_t size;
858 int ret;
859
860 ret = buf->ops->confirm(pipe, buf);
861 if (unlikely(ret))
862 return ret;
863 847
864 size = sd->len; 848 size = sd->len;
865 849
@@ -889,29 +873,15 @@ static int nfsd_direct_splice_actor(struct pipe_inode_info *pipe,
889 return __splice_from_pipe(pipe, sd, nfsd_splice_actor); 873 return __splice_from_pipe(pipe, sd, nfsd_splice_actor);
890} 874}
891 875
892static inline int svc_msnfs(struct svc_fh *ffhp)
893{
894#ifdef MSNFS
895 return (ffhp->fh_export->ex_flags & NFSEXP_MSNFS);
896#else
897 return 0;
898#endif
899}
900
901static __be32 876static __be32
902nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, 877nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
903 loff_t offset, struct kvec *vec, int vlen, unsigned long *count) 878 loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
904{ 879{
905 struct inode *inode;
906 mm_segment_t oldfs; 880 mm_segment_t oldfs;
907 __be32 err; 881 __be32 err;
908 int host_err; 882 int host_err;
909 883
910 err = nfserr_perm; 884 err = nfserr_perm;
911 inode = file->f_path.dentry->d_inode;
912
913 if (svc_msnfs(fhp) && !lock_may_read(inode, offset, *count))
914 goto out;
915 885
916 if (file->f_op->splice_read && rqstp->rq_splice_ok) { 886 if (file->f_op->splice_read && rqstp->rq_splice_ok) {
917 struct splice_desc sd = { 887 struct splice_desc sd = {
@@ -937,7 +907,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
937 fsnotify_access(file); 907 fsnotify_access(file);
938 } else 908 } else
939 err = nfserrno(host_err); 909 err = nfserrno(host_err);
940out:
941 return err; 910 return err;
942} 911}
943 912
@@ -1002,14 +971,6 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
1002 int stable = *stablep; 971 int stable = *stablep;
1003 int use_wgather; 972 int use_wgather;
1004 973
1005#ifdef MSNFS
1006 err = nfserr_perm;
1007
1008 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
1009 (!lock_may_write(file->f_path.dentry->d_inode, offset, *cnt)))
1010 goto out;
1011#endif
1012
1013 dentry = file->f_path.dentry; 974 dentry = file->f_path.dentry;
1014 inode = dentry->d_inode; 975 inode = dentry->d_inode;
1015 exp = fhp->fh_export; 976 exp = fhp->fh_export;
@@ -1060,7 +1021,6 @@ out_nfserr:
1060 err = 0; 1021 err = 0;
1061 else 1022 else
1062 err = nfserrno(host_err); 1023 err = nfserrno(host_err);
1063out:
1064 return err; 1024 return err;
1065} 1025}
1066 1026
@@ -1378,11 +1338,18 @@ out_nfserr:
1378} 1338}
1379 1339
1380#ifdef CONFIG_NFSD_V3 1340#ifdef CONFIG_NFSD_V3
1341
1342static inline int nfsd_create_is_exclusive(int createmode)
1343{
1344 return createmode == NFS3_CREATE_EXCLUSIVE
1345 || createmode == NFS4_CREATE_EXCLUSIVE4_1;
1346}
1347
1381/* 1348/*
1382 * NFSv3 version of nfsd_create 1349 * NFSv3 and NFSv4 version of nfsd_create
1383 */ 1350 */
1384__be32 1351__be32
1385nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, 1352do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
1386 char *fname, int flen, struct iattr *iap, 1353 char *fname, int flen, struct iattr *iap,
1387 struct svc_fh *resfhp, int createmode, u32 *verifier, 1354 struct svc_fh *resfhp, int createmode, u32 *verifier,
1388 int *truncp, int *created) 1355 int *truncp, int *created)
@@ -1401,7 +1368,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1401 goto out; 1368 goto out;
1402 if (!(iap->ia_valid & ATTR_MODE)) 1369 if (!(iap->ia_valid & ATTR_MODE))
1403 iap->ia_mode = 0; 1370 iap->ia_mode = 0;
1404 err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE); 1371 err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
1405 if (err) 1372 if (err)
1406 goto out; 1373 goto out;
1407 1374
@@ -1423,11 +1390,18 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1423 if (IS_ERR(dchild)) 1390 if (IS_ERR(dchild))
1424 goto out_nfserr; 1391 goto out_nfserr;
1425 1392
1393 /* If file doesn't exist, check for permissions to create one */
1394 if (!dchild->d_inode) {
1395 err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
1396 if (err)
1397 goto out;
1398 }
1399
1426 err = fh_compose(resfhp, fhp->fh_export, dchild, fhp); 1400 err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
1427 if (err) 1401 if (err)
1428 goto out; 1402 goto out;
1429 1403
1430 if (createmode == NFS3_CREATE_EXCLUSIVE) { 1404 if (nfsd_create_is_exclusive(createmode)) {
1431 /* solaris7 gets confused (bugid 4218508) if these have 1405 /* solaris7 gets confused (bugid 4218508) if these have
1432 * the high bit set, so just clear the high bits. If this is 1406 * the high bit set, so just clear the high bits. If this is
1433 * ever changed to use different attrs for storing the 1407 * ever changed to use different attrs for storing the
@@ -1468,6 +1442,11 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1468 && dchild->d_inode->i_atime.tv_sec == v_atime 1442 && dchild->d_inode->i_atime.tv_sec == v_atime
1469 && dchild->d_inode->i_size == 0 ) 1443 && dchild->d_inode->i_size == 0 )
1470 break; 1444 break;
1445 case NFS4_CREATE_EXCLUSIVE4_1:
1446 if ( dchild->d_inode->i_mtime.tv_sec == v_mtime
1447 && dchild->d_inode->i_atime.tv_sec == v_atime
1448 && dchild->d_inode->i_size == 0 )
1449 goto set_attr;
1471 /* fallthru */ 1450 /* fallthru */
1472 case NFS3_CREATE_GUARDED: 1451 case NFS3_CREATE_GUARDED:
1473 err = nfserr_exist; 1452 err = nfserr_exist;
@@ -1486,7 +1465,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
1486 1465
1487 nfsd_check_ignore_resizing(iap); 1466 nfsd_check_ignore_resizing(iap);
1488 1467
1489 if (createmode == NFS3_CREATE_EXCLUSIVE) { 1468 if (nfsd_create_is_exclusive(createmode)) {
1490 /* Cram the verifier into atime/mtime */ 1469 /* Cram the verifier into atime/mtime */
1491 iap->ia_valid = ATTR_MTIME|ATTR_ATIME 1470 iap->ia_valid = ATTR_MTIME|ATTR_ATIME
1492 | ATTR_MTIME_SET|ATTR_ATIME_SET; 1471 | ATTR_MTIME_SET|ATTR_ATIME_SET;
@@ -1680,6 +1659,14 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1680 err = nfserrno(host_err); 1659 err = nfserrno(host_err);
1681 goto out_dput; 1660 goto out_dput;
1682 } 1661 }
1662 err = nfserr_noent;
1663 if (!dold->d_inode)
1664 goto out_drop_write;
1665 host_err = nfsd_break_lease(dold->d_inode);
1666 if (host_err) {
1667 err = nfserrno(host_err);
1668 goto out_drop_write;
1669 }
1683 host_err = vfs_link(dold, dirp, dnew); 1670 host_err = vfs_link(dold, dirp, dnew);
1684 if (!host_err) { 1671 if (!host_err) {
1685 err = nfserrno(commit_metadata(ffhp)); 1672 err = nfserrno(commit_metadata(ffhp));
@@ -1691,6 +1678,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
1691 else 1678 else
1692 err = nfserrno(host_err); 1679 err = nfserrno(host_err);
1693 } 1680 }
1681out_drop_write:
1694 mnt_drop_write(tfhp->fh_export->ex_path.mnt); 1682 mnt_drop_write(tfhp->fh_export->ex_path.mnt);
1695out_dput: 1683out_dput:
1696 dput(dnew); 1684 dput(dnew);
@@ -1765,13 +1753,6 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1765 if (ndentry == trap) 1753 if (ndentry == trap)
1766 goto out_dput_new; 1754 goto out_dput_new;
1767 1755
1768 if (svc_msnfs(ffhp) &&
1769 ((atomic_read(&odentry->d_count) > 1)
1770 || (atomic_read(&ndentry->d_count) > 1))) {
1771 host_err = -EPERM;
1772 goto out_dput_new;
1773 }
1774
1775 host_err = -EXDEV; 1756 host_err = -EXDEV;
1776 if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt) 1757 if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt)
1777 goto out_dput_new; 1758 goto out_dput_new;
@@ -1779,15 +1760,22 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
1779 if (host_err) 1760 if (host_err)
1780 goto out_dput_new; 1761 goto out_dput_new;
1781 1762
1763 host_err = nfsd_break_lease(odentry->d_inode);
1764 if (host_err)
1765 goto out_drop_write;
1766 if (ndentry->d_inode) {
1767 host_err = nfsd_break_lease(ndentry->d_inode);
1768 if (host_err)
1769 goto out_drop_write;
1770 }
1782 host_err = vfs_rename(fdir, odentry, tdir, ndentry); 1771 host_err = vfs_rename(fdir, odentry, tdir, ndentry);
1783 if (!host_err) { 1772 if (!host_err) {
1784 host_err = commit_metadata(tfhp); 1773 host_err = commit_metadata(tfhp);
1785 if (!host_err) 1774 if (!host_err)
1786 host_err = commit_metadata(ffhp); 1775 host_err = commit_metadata(ffhp);
1787 } 1776 }
1788 1777out_drop_write:
1789 mnt_drop_write(ffhp->fh_export->ex_path.mnt); 1778 mnt_drop_write(ffhp->fh_export->ex_path.mnt);
1790
1791 out_dput_new: 1779 out_dput_new:
1792 dput(ndentry); 1780 dput(ndentry);
1793 out_dput_old: 1781 out_dput_old:
@@ -1848,26 +1836,22 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
1848 1836
1849 host_err = mnt_want_write(fhp->fh_export->ex_path.mnt); 1837 host_err = mnt_want_write(fhp->fh_export->ex_path.mnt);
1850 if (host_err) 1838 if (host_err)
1851 goto out_nfserr; 1839 goto out_put;
1852 1840
1853 if (type != S_IFDIR) { /* It's UNLINK */ 1841 host_err = nfsd_break_lease(rdentry->d_inode);
1854#ifdef MSNFS 1842 if (host_err)
1855 if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && 1843 goto out_drop_write;
1856 (atomic_read(&rdentry->d_count) > 1)) { 1844 if (type != S_IFDIR)
1857 host_err = -EPERM;
1858 } else
1859#endif
1860 host_err = vfs_unlink(dirp, rdentry); 1845 host_err = vfs_unlink(dirp, rdentry);
1861 } else { /* It's RMDIR */ 1846 else
1862 host_err = vfs_rmdir(dirp, rdentry); 1847 host_err = vfs_rmdir(dirp, rdentry);
1863 }
1864
1865 dput(rdentry);
1866
1867 if (!host_err) 1848 if (!host_err)
1868 host_err = commit_metadata(fhp); 1849 host_err = commit_metadata(fhp);
1869 1850out_drop_write:
1870 mnt_drop_write(fhp->fh_export->ex_path.mnt); 1851 mnt_drop_write(fhp->fh_export->ex_path.mnt);
1852out_put:
1853 dput(rdentry);
1854
1871out_nfserr: 1855out_nfserr:
1872 err = nfserrno(host_err); 1856 err = nfserrno(host_err);
1873out: 1857out:
@@ -2062,7 +2046,7 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
2062 struct inode *inode = dentry->d_inode; 2046 struct inode *inode = dentry->d_inode;
2063 int err; 2047 int err;
2064 2048
2065 if (acc == NFSD_MAY_NOP) 2049 if ((acc & NFSD_MAY_MASK) == NFSD_MAY_NOP)
2066 return 0; 2050 return 0;
2067#if 0 2051#if 0
2068 dprintk("nfsd: permission 0x%x%s%s%s%s%s%s%s mode 0%o%s%s%s\n", 2052 dprintk("nfsd: permission 0x%x%s%s%s%s%s%s%s mode 0%o%s%s%s\n",
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
index 9a370a5e36b7..e0bbac04d1dd 100644
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -17,10 +17,14 @@
17#define NFSD_MAY_SATTR 8 17#define NFSD_MAY_SATTR 8
18#define NFSD_MAY_TRUNC 16 18#define NFSD_MAY_TRUNC 16
19#define NFSD_MAY_LOCK 32 19#define NFSD_MAY_LOCK 32
20#define NFSD_MAY_MASK 63
21
22/* extra hints to permission and open routines: */
20#define NFSD_MAY_OWNER_OVERRIDE 64 23#define NFSD_MAY_OWNER_OVERRIDE 64
21#define NFSD_MAY_LOCAL_ACCESS 128 /* IRIX doing local access check on device special file*/ 24#define NFSD_MAY_LOCAL_ACCESS 128 /* IRIX doing local access check on device special file*/
22#define NFSD_MAY_BYPASS_GSS_ON_ROOT 256 25#define NFSD_MAY_BYPASS_GSS_ON_ROOT 256
23#define NFSD_MAY_NOT_BREAK_LEASE 512 26#define NFSD_MAY_NOT_BREAK_LEASE 512
27#define NFSD_MAY_BYPASS_GSS 1024
24 28
25#define NFSD_MAY_CREATE (NFSD_MAY_EXEC|NFSD_MAY_WRITE) 29#define NFSD_MAY_CREATE (NFSD_MAY_EXEC|NFSD_MAY_WRITE)
26#define NFSD_MAY_REMOVE (NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC) 30#define NFSD_MAY_REMOVE (NFSD_MAY_EXEC|NFSD_MAY_WRITE|NFSD_MAY_TRUNC)
@@ -54,7 +58,7 @@ __be32 nfsd_create(struct svc_rqst *, struct svc_fh *,
54 int type, dev_t rdev, struct svc_fh *res); 58 int type, dev_t rdev, struct svc_fh *res);
55#ifdef CONFIG_NFSD_V3 59#ifdef CONFIG_NFSD_V3
56__be32 nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *); 60__be32 nfsd_access(struct svc_rqst *, struct svc_fh *, u32 *, u32 *);
57__be32 nfsd_create_v3(struct svc_rqst *, struct svc_fh *, 61__be32 do_nfsd_create(struct svc_rqst *, struct svc_fh *,
58 char *name, int len, struct iattr *attrs, 62 char *name, int len, struct iattr *attrs,
59 struct svc_fh *res, int createmode, 63 struct svc_fh *res, int createmode,
60 u32 *verifier, int *truncp, int *created); 64 u32 *verifier, int *truncp, int *created);
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index 4d476ff08ae6..366401e1a536 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -311,6 +311,11 @@ struct nfsd4_secinfo {
311 struct svc_export *si_exp; /* response */ 311 struct svc_export *si_exp; /* response */
312}; 312};
313 313
314struct nfsd4_secinfo_no_name {
315 u32 sin_style; /* request */
316 struct svc_export *sin_exp; /* response */
317};
318
314struct nfsd4_setattr { 319struct nfsd4_setattr {
315 stateid_t sa_stateid; /* request */ 320 stateid_t sa_stateid; /* request */
316 u32 sa_bmval[3]; /* request */ 321 u32 sa_bmval[3]; /* request */
@@ -373,8 +378,8 @@ struct nfsd4_sequence {
373 u32 cachethis; /* request */ 378 u32 cachethis; /* request */
374#if 0 379#if 0
375 u32 target_maxslots; /* response */ 380 u32 target_maxslots; /* response */
376 u32 status_flags; /* response */
377#endif /* not yet */ 381#endif /* not yet */
382 u32 status_flags; /* response */
378}; 383};
379 384
380struct nfsd4_destroy_session { 385struct nfsd4_destroy_session {
@@ -422,6 +427,7 @@ struct nfsd4_op {
422 427
423 /* NFSv4.1 */ 428 /* NFSv4.1 */
424 struct nfsd4_exchange_id exchange_id; 429 struct nfsd4_exchange_id exchange_id;
430 struct nfsd4_bind_conn_to_session bind_conn_to_session;
425 struct nfsd4_create_session create_session; 431 struct nfsd4_create_session create_session;
426 struct nfsd4_destroy_session destroy_session; 432 struct nfsd4_destroy_session destroy_session;
427 struct nfsd4_sequence sequence; 433 struct nfsd4_sequence sequence;
@@ -484,18 +490,17 @@ static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp)
484static inline void 490static inline void
485set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp) 491set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
486{ 492{
487 BUG_ON(!fhp->fh_pre_saved || !fhp->fh_post_saved); 493 BUG_ON(!fhp->fh_pre_saved);
488 cinfo->atomic = 1; 494 cinfo->atomic = fhp->fh_post_saved;
489 cinfo->change_supported = IS_I_VERSION(fhp->fh_dentry->d_inode); 495 cinfo->change_supported = IS_I_VERSION(fhp->fh_dentry->d_inode);
490 if (cinfo->change_supported) { 496
491 cinfo->before_change = fhp->fh_pre_change; 497 cinfo->before_change = fhp->fh_pre_change;
492 cinfo->after_change = fhp->fh_post_change; 498 cinfo->after_change = fhp->fh_post_change;
493 } else { 499 cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
494 cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec; 500 cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
495 cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec; 501 cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
496 cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec; 502 cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
497 cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec; 503
498 }
499} 504}
500 505
501int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *); 506int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *);
@@ -519,6 +524,7 @@ extern __be32 nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp,
519 struct nfsd4_sequence *seq); 524 struct nfsd4_sequence *seq);
520extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp, 525extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp,
521 struct nfsd4_compound_state *, struct nfsd4_exchange_id *); 526 struct nfsd4_compound_state *, struct nfsd4_exchange_id *);
527extern __be32 nfsd4_bind_conn_to_session(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_bind_conn_to_session *);
522extern __be32 nfsd4_create_session(struct svc_rqst *, 528extern __be32 nfsd4_create_session(struct svc_rqst *,
523 struct nfsd4_compound_state *, 529 struct nfsd4_compound_state *,
524 struct nfsd4_create_session *); 530 struct nfsd4_create_session *);