diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-14 16:17:26 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-14 16:17:26 -0500 |
| commit | 18bce371ae09af6c20ee62c1092a4d1d0e84dd49 (patch) | |
| tree | f3467fafd8e49392e3f6efef7b88a7b4dd3b7b06 /fs | |
| parent | ec08bdb148767f1193f5f3028749ed865ac27181 (diff) | |
| parent | a8f2800b4f7b76cecb7209cb6a7d2b14904fc711 (diff) | |
Merge branch 'for-2.6.38' of git://linux-nfs.org/~bfields/linux
* 'for-2.6.38' of git://linux-nfs.org/~bfields/linux: (62 commits)
nfsd4: fix callback restarting
nfsd: break lease on unlink, link, and rename
nfsd4: break lease on nfsd setattr
nfsd: don't support msnfs export option
nfsd4: initialize cb_per_client
nfsd4: allow restarting callbacks
nfsd4: simplify nfsd4_cb_prepare
nfsd4: give out delegations more quickly in 4.1 case
nfsd4: add helper function to run callbacks
nfsd4: make sure sequence flags are set after destroy_session
nfsd4: re-probe callback on connection loss
nfsd4: set sequence flag when backchannel is down
nfsd4: keep finer-grained callback status
rpc: allow xprt_class->setup to return a preexisting xprt
rpc: keep backchannel xprt as long as server connection
rpc: move sk_bc_xprt to svc_xprt
nfsd4: allow backchannel recovery
nfsd4: support BIND_CONN_TO_SESSION
nfsd4: modify session list under cl_lock
Documentation: fl_mylease no longer exists
...
Fix up conflicts in fs/nfsd/vfs.c with the vfs-scale work. The
vfs-scale work touched some msnfs cases, and this merge removes support
for that entirely, so the conflict was trivial to resolve.
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/locks.c | 8 | ||||
| -rw-r--r-- | fs/nfsd/acl.h | 59 | ||||
| -rw-r--r-- | fs/nfsd/export.c | 4 | ||||
| -rw-r--r-- | fs/nfsd/idmap.h | 62 | ||||
| -rw-r--r-- | fs/nfsd/nfs3proc.c | 8 | ||||
| -rw-r--r-- | fs/nfsd/nfs4acl.c | 2 | ||||
| -rw-r--r-- | fs/nfsd/nfs4callback.c | 151 | ||||
| -rw-r--r-- | fs/nfsd/nfs4idmap.c | 15 | ||||
| -rw-r--r-- | fs/nfsd/nfs4proc.c | 59 | ||||
| -rw-r--r-- | fs/nfsd/nfs4recover.c | 1 | ||||
| -rw-r--r-- | fs/nfsd/nfs4state.c | 243 | ||||
| -rw-r--r-- | fs/nfsd/nfs4xdr.c | 115 | ||||
| -rw-r--r-- | fs/nfsd/nfsctl.c | 4 | ||||
| -rw-r--r-- | fs/nfsd/nfsd.h | 1 | ||||
| -rw-r--r-- | fs/nfsd/nfsproc.c | 6 | ||||
| -rw-r--r-- | fs/nfsd/nfssvc.c | 2 | ||||
| -rw-r--r-- | fs/nfsd/state.h | 16 | ||||
| -rw-r--r-- | fs/nfsd/vfs.c | 85 | ||||
| -rw-r--r-- | fs/nfsd/xdr4.h | 9 |
19 files changed, 573 insertions, 277 deletions
diff --git a/fs/locks.c b/fs/locks.c index 08415b2a6d36..0f3998291f78 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
| @@ -444,15 +444,9 @@ static void lease_release_private_callback(struct file_lock *fl) | |||
| 444 | fl->fl_file->f_owner.signum = 0; | 444 | fl->fl_file->f_owner.signum = 0; |
| 445 | } | 445 | } |
| 446 | 446 | ||
| 447 | static int lease_mylease_callback(struct file_lock *fl, struct file_lock *try) | ||
| 448 | { | ||
| 449 | return fl->fl_file == try->fl_file; | ||
| 450 | } | ||
| 451 | |||
| 452 | static const struct lock_manager_operations lease_manager_ops = { | 447 | static const struct lock_manager_operations lease_manager_ops = { |
| 453 | .fl_break = lease_break_callback, | 448 | .fl_break = lease_break_callback, |
| 454 | .fl_release_private = lease_release_private_callback, | 449 | .fl_release_private = lease_release_private_callback, |
| 455 | .fl_mylease = lease_mylease_callback, | ||
| 456 | .fl_change = lease_modify, | 450 | .fl_change = lease_modify, |
| 457 | }; | 451 | }; |
| 458 | 452 | ||
| @@ -1405,7 +1399,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp) | |||
| 1405 | for (before = &inode->i_flock; | 1399 | for (before = &inode->i_flock; |
| 1406 | ((fl = *before) != NULL) && IS_LEASE(fl); | 1400 | ((fl = *before) != NULL) && IS_LEASE(fl); |
| 1407 | before = &fl->fl_next) { | 1401 | before = &fl->fl_next) { |
| 1408 | if (lease->fl_lmops->fl_mylease(fl, lease)) | 1402 | if (fl->fl_file == filp) |
| 1409 | my_before = before; | 1403 | my_before = before; |
| 1410 | else if (fl->fl_type == (F_INPROGRESS | F_UNLCK)) | 1404 | else if (fl->fl_type == (F_INPROGRESS | F_UNLCK)) |
| 1411 | /* | 1405 | /* |
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 | |||
| 44 | struct nfs4_acl *nfs4_acl_new(int); | ||
| 45 | int nfs4_acl_get_whotype(char *, u32); | ||
| 46 | int nfs4_acl_write_who(int who, char *p); | ||
| 47 | int 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 | |||
| 54 | struct nfs4_acl *nfs4_acl_posix_to_nfsv4(struct posix_acl *, | ||
| 55 | struct posix_acl *, unsigned int flags); | ||
| 56 | int 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 c0fcb7ab7f6d..8b31e5f8795d 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 | * |
| @@ -1444,9 +1443,6 @@ static struct flags { | |||
| 1444 | { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}}, | 1443 | { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}}, |
| 1445 | { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}}, | 1444 | { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}}, |
| 1446 | { NFSEXP_V4ROOT, {"v4root", ""}}, | 1445 | { NFSEXP_V4ROOT, {"v4root", ""}}, |
| 1447 | #ifdef MSNFS | ||
| 1448 | { NFSEXP_MSNFS, {"msnfs", ""}}, | ||
| 1449 | #endif | ||
| 1450 | { 0, {"", ""}} | 1446 | { 0, {"", ""}} |
| 1451 | }; | 1447 | }; |
| 1452 | 1448 | ||
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 | ||
| 45 | int nfsd_idmap_init(void); | ||
| 46 | void nfsd_idmap_shutdown(void); | ||
| 47 | #else | ||
| 48 | static inline int nfsd_idmap_init(void) | ||
| 49 | { | ||
| 50 | return 0; | ||
| 51 | } | ||
| 52 | static 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 *); | ||
| 59 | int nfsd_map_uid_to_name(struct svc_rqst *, __u32, char *); | ||
| 60 | int nfsd_map_gid_to_name(struct svc_rqst *, __u32, char *); | ||
| 61 | |||
| 62 | #endif /* LINUX_NFSD_IDMAP_H */ | ||
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c index 5b7e3021e06b..2247fc91d5e9 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); |
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 21a63da305ff..3be975e18919 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
| @@ -628,10 +628,8 @@ static int max_cb_time(void) | |||
| 628 | return max(nfsd4_lease/10, (time_t)1) * HZ; | 628 | return max(nfsd4_lease/10, (time_t)1) * HZ; |
| 629 | } | 629 | } |
| 630 | 630 | ||
| 631 | /* Reference counting, callback cleanup, etc., all look racy as heck. | ||
| 632 | * And why is cl_cb_set an atomic? */ | ||
| 633 | 631 | ||
| 634 | int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn) | 632 | static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses) |
| 635 | { | 633 | { |
| 636 | struct rpc_timeout timeparms = { | 634 | struct rpc_timeout timeparms = { |
| 637 | .to_initval = max_cb_time(), | 635 | .to_initval = max_cb_time(), |
| @@ -641,6 +639,7 @@ int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn) | |||
| 641 | .net = &init_net, | 639 | .net = &init_net, |
| 642 | .address = (struct sockaddr *) &conn->cb_addr, | 640 | .address = (struct sockaddr *) &conn->cb_addr, |
| 643 | .addrsize = conn->cb_addrlen, | 641 | .addrsize = conn->cb_addrlen, |
| 642 | .saddress = (struct sockaddr *) &conn->cb_saddr, | ||
| 644 | .timeout = &timeparms, | 643 | .timeout = &timeparms, |
| 645 | .program = &cb_program, | 644 | .program = &cb_program, |
| 646 | .version = 0, | 645 | .version = 0, |
| @@ -657,6 +656,10 @@ int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn) | |||
| 657 | args.protocol = XPRT_TRANSPORT_TCP; | 656 | args.protocol = XPRT_TRANSPORT_TCP; |
| 658 | clp->cl_cb_ident = conn->cb_ident; | 657 | clp->cl_cb_ident = conn->cb_ident; |
| 659 | } else { | 658 | } else { |
| 659 | if (!conn->cb_xprt) | ||
| 660 | return -EINVAL; | ||
| 661 | clp->cl_cb_conn.cb_xprt = conn->cb_xprt; | ||
| 662 | clp->cl_cb_session = ses; | ||
| 660 | args.bc_xprt = conn->cb_xprt; | 663 | args.bc_xprt = conn->cb_xprt; |
| 661 | args.prognumber = clp->cl_cb_session->se_cb_prog; | 664 | args.prognumber = clp->cl_cb_session->se_cb_prog; |
| 662 | args.protocol = XPRT_TRANSPORT_BC_TCP; | 665 | args.protocol = XPRT_TRANSPORT_BC_TCP; |
| @@ -679,14 +682,20 @@ static void warn_no_callback_path(struct nfs4_client *clp, int reason) | |||
| 679 | (int)clp->cl_name.len, clp->cl_name.data, reason); | 682 | (int)clp->cl_name.len, clp->cl_name.data, reason); |
| 680 | } | 683 | } |
| 681 | 684 | ||
| 685 | static void nfsd4_mark_cb_down(struct nfs4_client *clp, int reason) | ||
| 686 | { | ||
| 687 | clp->cl_cb_state = NFSD4_CB_DOWN; | ||
| 688 | warn_no_callback_path(clp, reason); | ||
| 689 | } | ||
| 690 | |||
| 682 | static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata) | 691 | static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata) |
| 683 | { | 692 | { |
| 684 | struct nfs4_client *clp = container_of(calldata, struct nfs4_client, cl_cb_null); | 693 | struct nfs4_client *clp = container_of(calldata, struct nfs4_client, cl_cb_null); |
| 685 | 694 | ||
| 686 | if (task->tk_status) | 695 | if (task->tk_status) |
| 687 | warn_no_callback_path(clp, task->tk_status); | 696 | nfsd4_mark_cb_down(clp, task->tk_status); |
| 688 | else | 697 | else |
| 689 | atomic_set(&clp->cl_cb_set, 1); | 698 | clp->cl_cb_state = NFSD4_CB_UP; |
| 690 | } | 699 | } |
| 691 | 700 | ||
| 692 | static const struct rpc_call_ops nfsd4_cb_probe_ops = { | 701 | static const struct rpc_call_ops nfsd4_cb_probe_ops = { |
| @@ -709,6 +718,11 @@ int set_callback_cred(void) | |||
| 709 | 718 | ||
| 710 | static struct workqueue_struct *callback_wq; | 719 | static struct workqueue_struct *callback_wq; |
| 711 | 720 | ||
| 721 | static void run_nfsd4_cb(struct nfsd4_callback *cb) | ||
| 722 | { | ||
| 723 | queue_work(callback_wq, &cb->cb_work); | ||
| 724 | } | ||
| 725 | |||
| 712 | static void do_probe_callback(struct nfs4_client *clp) | 726 | static void do_probe_callback(struct nfs4_client *clp) |
| 713 | { | 727 | { |
| 714 | struct nfsd4_callback *cb = &clp->cl_cb_null; | 728 | struct nfsd4_callback *cb = &clp->cl_cb_null; |
| @@ -723,7 +737,7 @@ static void do_probe_callback(struct nfs4_client *clp) | |||
| 723 | 737 | ||
| 724 | cb->cb_ops = &nfsd4_cb_probe_ops; | 738 | cb->cb_ops = &nfsd4_cb_probe_ops; |
| 725 | 739 | ||
| 726 | queue_work(callback_wq, &cb->cb_work); | 740 | run_nfsd4_cb(cb); |
| 727 | } | 741 | } |
| 728 | 742 | ||
| 729 | /* | 743 | /* |
| @@ -732,14 +746,21 @@ static void do_probe_callback(struct nfs4_client *clp) | |||
| 732 | */ | 746 | */ |
| 733 | void nfsd4_probe_callback(struct nfs4_client *clp) | 747 | void nfsd4_probe_callback(struct nfs4_client *clp) |
| 734 | { | 748 | { |
| 749 | /* XXX: atomicity? Also, should we be using cl_cb_flags? */ | ||
| 750 | clp->cl_cb_state = NFSD4_CB_UNKNOWN; | ||
| 735 | set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags); | 751 | set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags); |
| 736 | do_probe_callback(clp); | 752 | do_probe_callback(clp); |
| 737 | } | 753 | } |
| 738 | 754 | ||
| 739 | void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn) | 755 | void nfsd4_probe_callback_sync(struct nfs4_client *clp) |
| 740 | { | 756 | { |
| 741 | BUG_ON(atomic_read(&clp->cl_cb_set)); | 757 | nfsd4_probe_callback(clp); |
| 758 | flush_workqueue(callback_wq); | ||
| 759 | } | ||
| 742 | 760 | ||
| 761 | void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn) | ||
| 762 | { | ||
| 763 | clp->cl_cb_state = NFSD4_CB_UNKNOWN; | ||
| 743 | spin_lock(&clp->cl_lock); | 764 | spin_lock(&clp->cl_lock); |
| 744 | memcpy(&clp->cl_cb_conn, conn, sizeof(struct nfs4_cb_conn)); | 765 | memcpy(&clp->cl_cb_conn, conn, sizeof(struct nfs4_cb_conn)); |
| 745 | spin_unlock(&clp->cl_lock); | 766 | spin_unlock(&clp->cl_lock); |
| @@ -750,24 +771,14 @@ void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn) | |||
| 750 | * If the slot is available, then mark it busy. Otherwise, set the | 771 | * If the slot is available, then mark it busy. Otherwise, set the |
| 751 | * thread for sleeping on the callback RPC wait queue. | 772 | * thread for sleeping on the callback RPC wait queue. |
| 752 | */ | 773 | */ |
| 753 | static int nfsd41_cb_setup_sequence(struct nfs4_client *clp, | 774 | static bool nfsd41_cb_get_slot(struct nfs4_client *clp, struct rpc_task *task) |
| 754 | struct rpc_task *task) | ||
| 755 | { | 775 | { |
| 756 | u32 *ptr = (u32 *)clp->cl_cb_session->se_sessionid.data; | ||
| 757 | int status = 0; | ||
| 758 | |||
| 759 | dprintk("%s: %u:%u:%u:%u\n", __func__, | ||
| 760 | ptr[0], ptr[1], ptr[2], ptr[3]); | ||
| 761 | |||
| 762 | if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) { | 776 | if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) { |
| 763 | rpc_sleep_on(&clp->cl_cb_waitq, task, NULL); | 777 | rpc_sleep_on(&clp->cl_cb_waitq, task, NULL); |
| 764 | dprintk("%s slot is busy\n", __func__); | 778 | dprintk("%s slot is busy\n", __func__); |
| 765 | status = -EAGAIN; | 779 | return false; |
| 766 | goto out; | ||
| 767 | } | 780 | } |
| 768 | out: | 781 | return true; |
| 769 | dprintk("%s status=%d\n", __func__, status); | ||
| 770 | return status; | ||
| 771 | } | 782 | } |
| 772 | 783 | ||
| 773 | /* | 784 | /* |
| @@ -780,20 +791,19 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata) | |||
| 780 | struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall); | 791 | struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall); |
| 781 | struct nfs4_client *clp = dp->dl_client; | 792 | struct nfs4_client *clp = dp->dl_client; |
| 782 | u32 minorversion = clp->cl_minorversion; | 793 | u32 minorversion = clp->cl_minorversion; |
| 783 | int status = 0; | ||
| 784 | 794 | ||
| 785 | cb->cb_minorversion = minorversion; | 795 | cb->cb_minorversion = minorversion; |
| 786 | if (minorversion) { | 796 | if (minorversion) { |
| 787 | status = nfsd41_cb_setup_sequence(clp, task); | 797 | if (!nfsd41_cb_get_slot(clp, task)) |
| 788 | if (status) { | ||
| 789 | if (status != -EAGAIN) { | ||
| 790 | /* terminate rpc task */ | ||
| 791 | task->tk_status = status; | ||
| 792 | task->tk_action = NULL; | ||
| 793 | } | ||
| 794 | return; | 798 | return; |
| 795 | } | ||
| 796 | } | 799 | } |
| 800 | spin_lock(&clp->cl_lock); | ||
| 801 | if (list_empty(&cb->cb_per_client)) { | ||
| 802 | /* This is the first call, not a restart */ | ||
| 803 | cb->cb_done = false; | ||
| 804 | list_add(&cb->cb_per_client, &clp->cl_callbacks); | ||
| 805 | } | ||
| 806 | spin_unlock(&clp->cl_lock); | ||
| 797 | rpc_call_start(task); | 807 | rpc_call_start(task); |
| 798 | } | 808 | } |
| 799 | 809 | ||
| @@ -829,15 +839,18 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata) | |||
| 829 | 839 | ||
| 830 | nfsd4_cb_done(task, calldata); | 840 | nfsd4_cb_done(task, calldata); |
| 831 | 841 | ||
| 832 | if (current_rpc_client == NULL) { | 842 | if (current_rpc_client != task->tk_client) { |
| 833 | /* We're shutting down; give up. */ | 843 | /* We're shutting down or changing cl_cb_client; leave |
| 834 | /* XXX: err, or is it ok just to fall through | 844 | * it to nfsd4_process_cb_update to restart the call if |
| 835 | * and rpc_restart_call? */ | 845 | * necessary. */ |
| 836 | return; | 846 | return; |
| 837 | } | 847 | } |
| 838 | 848 | ||
| 849 | if (cb->cb_done) | ||
| 850 | return; | ||
| 839 | switch (task->tk_status) { | 851 | switch (task->tk_status) { |
| 840 | case 0: | 852 | case 0: |
| 853 | cb->cb_done = true; | ||
| 841 | return; | 854 | return; |
| 842 | case -EBADHANDLE: | 855 | case -EBADHANDLE: |
| 843 | case -NFS4ERR_BAD_STATEID: | 856 | case -NFS4ERR_BAD_STATEID: |
| @@ -846,32 +859,30 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata) | |||
| 846 | break; | 859 | break; |
| 847 | default: | 860 | default: |
| 848 | /* Network partition? */ | 861 | /* Network partition? */ |
| 849 | atomic_set(&clp->cl_cb_set, 0); | 862 | nfsd4_mark_cb_down(clp, task->tk_status); |
| 850 | warn_no_callback_path(clp, task->tk_status); | ||
| 851 | if (current_rpc_client != task->tk_client) { | ||
| 852 | /* queue a callback on the new connection: */ | ||
| 853 | atomic_inc(&dp->dl_count); | ||
| 854 | nfsd4_cb_recall(dp); | ||
| 855 | return; | ||
| 856 | } | ||
| 857 | } | 863 | } |
| 858 | if (dp->dl_retries--) { | 864 | if (dp->dl_retries--) { |
| 859 | rpc_delay(task, 2*HZ); | 865 | rpc_delay(task, 2*HZ); |
| 860 | task->tk_status = 0; | 866 | task->tk_status = 0; |
| 861 | rpc_restart_call_prepare(task); | 867 | rpc_restart_call_prepare(task); |
| 862 | return; | 868 | return; |
| 863 | } else { | ||
| 864 | atomic_set(&clp->cl_cb_set, 0); | ||
| 865 | warn_no_callback_path(clp, task->tk_status); | ||
| 866 | } | 869 | } |
| 870 | nfsd4_mark_cb_down(clp, task->tk_status); | ||
| 871 | cb->cb_done = true; | ||
| 867 | } | 872 | } |
| 868 | 873 | ||
| 869 | static void nfsd4_cb_recall_release(void *calldata) | 874 | static void nfsd4_cb_recall_release(void *calldata) |
| 870 | { | 875 | { |
| 871 | struct nfsd4_callback *cb = calldata; | 876 | struct nfsd4_callback *cb = calldata; |
| 877 | struct nfs4_client *clp = cb->cb_clp; | ||
| 872 | struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall); | 878 | struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall); |
| 873 | 879 | ||
| 874 | nfs4_put_delegation(dp); | 880 | if (cb->cb_done) { |
| 881 | spin_lock(&clp->cl_lock); | ||
| 882 | list_del(&cb->cb_per_client); | ||
| 883 | spin_unlock(&clp->cl_lock); | ||
| 884 | nfs4_put_delegation(dp); | ||
| 885 | } | ||
| 875 | } | 886 | } |
| 876 | 887 | ||
| 877 | static const struct rpc_call_ops nfsd4_cb_recall_ops = { | 888 | static const struct rpc_call_ops nfsd4_cb_recall_ops = { |
| @@ -906,16 +917,33 @@ void nfsd4_shutdown_callback(struct nfs4_client *clp) | |||
| 906 | flush_workqueue(callback_wq); | 917 | flush_workqueue(callback_wq); |
| 907 | } | 918 | } |
| 908 | 919 | ||
| 909 | void nfsd4_release_cb(struct nfsd4_callback *cb) | 920 | static void nfsd4_release_cb(struct nfsd4_callback *cb) |
| 910 | { | 921 | { |
| 911 | if (cb->cb_ops->rpc_release) | 922 | if (cb->cb_ops->rpc_release) |
| 912 | cb->cb_ops->rpc_release(cb); | 923 | cb->cb_ops->rpc_release(cb); |
| 913 | } | 924 | } |
| 914 | 925 | ||
| 915 | void nfsd4_process_cb_update(struct nfsd4_callback *cb) | 926 | /* requires cl_lock: */ |
| 927 | static struct nfsd4_conn * __nfsd4_find_backchannel(struct nfs4_client *clp) | ||
| 928 | { | ||
| 929 | struct nfsd4_session *s; | ||
| 930 | struct nfsd4_conn *c; | ||
| 931 | |||
| 932 | list_for_each_entry(s, &clp->cl_sessions, se_perclnt) { | ||
| 933 | list_for_each_entry(c, &s->se_conns, cn_persession) { | ||
| 934 | if (c->cn_flags & NFS4_CDFC4_BACK) | ||
| 935 | return c; | ||
| 936 | } | ||
| 937 | } | ||
| 938 | return NULL; | ||
| 939 | } | ||
| 940 | |||
| 941 | static void nfsd4_process_cb_update(struct nfsd4_callback *cb) | ||
| 916 | { | 942 | { |
| 917 | struct nfs4_cb_conn conn; | 943 | struct nfs4_cb_conn conn; |
| 918 | struct nfs4_client *clp = cb->cb_clp; | 944 | struct nfs4_client *clp = cb->cb_clp; |
| 945 | struct nfsd4_session *ses = NULL; | ||
| 946 | struct nfsd4_conn *c; | ||
| 919 | int err; | 947 | int err; |
| 920 | 948 | ||
| 921 | /* | 949 | /* |
| @@ -926,6 +954,10 @@ void nfsd4_process_cb_update(struct nfsd4_callback *cb) | |||
| 926 | rpc_shutdown_client(clp->cl_cb_client); | 954 | rpc_shutdown_client(clp->cl_cb_client); |
| 927 | clp->cl_cb_client = NULL; | 955 | clp->cl_cb_client = NULL; |
| 928 | } | 956 | } |
| 957 | if (clp->cl_cb_conn.cb_xprt) { | ||
| 958 | svc_xprt_put(clp->cl_cb_conn.cb_xprt); | ||
| 959 | clp->cl_cb_conn.cb_xprt = NULL; | ||
| 960 | } | ||
| 929 | if (test_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags)) | 961 | if (test_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags)) |
| 930 | return; | 962 | return; |
| 931 | spin_lock(&clp->cl_lock); | 963 | spin_lock(&clp->cl_lock); |
| @@ -936,11 +968,22 @@ void nfsd4_process_cb_update(struct nfsd4_callback *cb) | |||
| 936 | BUG_ON(!clp->cl_cb_flags); | 968 | BUG_ON(!clp->cl_cb_flags); |
| 937 | clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags); | 969 | clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags); |
| 938 | memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn)); | 970 | memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn)); |
| 971 | c = __nfsd4_find_backchannel(clp); | ||
| 972 | if (c) { | ||
| 973 | svc_xprt_get(c->cn_xprt); | ||
| 974 | conn.cb_xprt = c->cn_xprt; | ||
| 975 | ses = c->cn_session; | ||
| 976 | } | ||
| 939 | spin_unlock(&clp->cl_lock); | 977 | spin_unlock(&clp->cl_lock); |
| 940 | 978 | ||
| 941 | err = setup_callback_client(clp, &conn); | 979 | err = setup_callback_client(clp, &conn, ses); |
| 942 | if (err) | 980 | if (err) { |
| 943 | warn_no_callback_path(clp, err); | 981 | warn_no_callback_path(clp, err); |
| 982 | return; | ||
| 983 | } | ||
| 984 | /* Yay, the callback channel's back! Restart any callbacks: */ | ||
| 985 | list_for_each_entry(cb, &clp->cl_callbacks, cb_per_client) | ||
| 986 | run_nfsd4_cb(cb); | ||
| 944 | } | 987 | } |
| 945 | 988 | ||
| 946 | void nfsd4_do_callback_rpc(struct work_struct *w) | 989 | void nfsd4_do_callback_rpc(struct work_struct *w) |
| @@ -965,10 +1008,11 @@ void nfsd4_do_callback_rpc(struct work_struct *w) | |||
| 965 | void nfsd4_cb_recall(struct nfs4_delegation *dp) | 1008 | void nfsd4_cb_recall(struct nfs4_delegation *dp) |
| 966 | { | 1009 | { |
| 967 | struct nfsd4_callback *cb = &dp->dl_recall; | 1010 | struct nfsd4_callback *cb = &dp->dl_recall; |
| 1011 | struct nfs4_client *clp = dp->dl_client; | ||
| 968 | 1012 | ||
| 969 | dp->dl_retries = 1; | 1013 | dp->dl_retries = 1; |
| 970 | cb->cb_op = dp; | 1014 | cb->cb_op = dp; |
| 971 | cb->cb_clp = dp->dl_client; | 1015 | cb->cb_clp = clp; |
| 972 | cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL]; | 1016 | cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL]; |
| 973 | cb->cb_msg.rpc_argp = cb; | 1017 | cb->cb_msg.rpc_argp = cb; |
| 974 | cb->cb_msg.rpc_resp = cb; | 1018 | cb->cb_msg.rpc_resp = cb; |
| @@ -977,5 +1021,8 @@ void nfsd4_cb_recall(struct nfs4_delegation *dp) | |||
| 977 | cb->cb_ops = &nfsd4_cb_recall_ops; | 1021 | cb->cb_ops = &nfsd4_cb_recall_ops; |
| 978 | dp->dl_retries = 1; | 1022 | dp->dl_retries = 1; |
| 979 | 1023 | ||
| 980 | queue_work(callback_wq, &dp->dl_recall.cb_work); | 1024 | INIT_LIST_HEAD(&cb->cb_per_client); |
| 1025 | cb->cb_done = true; | ||
| 1026 | |||
| 1027 | run_nfsd4_cb(&dp->dl_recall); | ||
| 981 | } | 1028 | } |
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index f0695e815f0e..6d2c397d458b 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 |
| @@ -514,7 +515,7 @@ rqst_authname(struct svc_rqst *rqstp) | |||
| 514 | return clp->name; | 515 | return clp->name; |
| 515 | } | 516 | } |
| 516 | 517 | ||
| 517 | static int | 518 | static __be32 |
| 518 | idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, | 519 | idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, |
| 519 | uid_t *id) | 520 | uid_t *id) |
| 520 | { | 521 | { |
| @@ -524,15 +525,15 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen | |||
| 524 | int ret; | 525 | int ret; |
| 525 | 526 | ||
| 526 | if (namelen + 1 > sizeof(key.name)) | 527 | if (namelen + 1 > sizeof(key.name)) |
| 527 | return -EINVAL; | 528 | return nfserr_badowner; |
| 528 | memcpy(key.name, name, namelen); | 529 | memcpy(key.name, name, namelen); |
| 529 | key.name[namelen] = '\0'; | 530 | key.name[namelen] = '\0'; |
| 530 | strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); | 531 | strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); |
| 531 | ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item); | 532 | ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item); |
| 532 | if (ret == -ENOENT) | 533 | if (ret == -ENOENT) |
| 533 | ret = -ESRCH; /* nfserr_badname */ | 534 | return nfserr_badowner; |
| 534 | if (ret) | 535 | if (ret) |
| 535 | return ret; | 536 | return nfserrno(ret); |
| 536 | *id = item->id; | 537 | *id = item->id; |
| 537 | cache_put(&item->h, &nametoid_cache); | 538 | cache_put(&item->h, &nametoid_cache); |
| 538 | return 0; | 539 | return 0; |
| @@ -560,14 +561,14 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name) | |||
| 560 | return ret; | 561 | return ret; |
| 561 | } | 562 | } |
| 562 | 563 | ||
| 563 | int | 564 | __be32 |
| 564 | nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen, | 565 | nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen, |
| 565 | __u32 *id) | 566 | __u32 *id) |
| 566 | { | 567 | { |
| 567 | return idmap_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, id); | 568 | return idmap_name_to_id(rqstp, IDMAP_TYPE_USER, name, namelen, id); |
| 568 | } | 569 | } |
| 569 | 570 | ||
| 570 | int | 571 | __be32 |
| 571 | nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen, | 572 | nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen, |
| 572 | __u32 *id) | 573 | __u32 *id) |
| 573 | { | 574 | { |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 0cdfd022bb7b..db52546143d1 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
| @@ -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 | ||
| 607 | static __be32 | 607 | static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh) |
| 608 | nfsd4_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 | |||
| 624 | static __be32 | ||
| 625 | nfsd4_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 | ||
| 627 | static __be32 | 631 | static __be32 |
| @@ -769,10 +773,36 @@ nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 769 | } else | 773 | } else |
| 770 | secinfo->si_exp = exp; | 774 | secinfo->si_exp = exp; |
| 771 | dput(dentry); | 775 | dput(dentry); |
| 776 | if (cstate->minorversion) | ||
| 777 | /* See rfc 5661 section 2.6.3.1.1.8 */ | ||
| 778 | fh_put(&cstate->current_fh); | ||
| 772 | return err; | 779 | return err; |
| 773 | } | 780 | } |
| 774 | 781 | ||
| 775 | static __be32 | 782 | static __be32 |
| 783 | nfsd4_secinfo_no_name(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | ||
| 784 | struct nfsd4_secinfo_no_name *sin) | ||
| 785 | { | ||
| 786 | __be32 err; | ||
| 787 | |||
| 788 | switch (sin->sin_style) { | ||
| 789 | case NFS4_SECINFO_STYLE4_CURRENT_FH: | ||
| 790 | break; | ||
| 791 | case NFS4_SECINFO_STYLE4_PARENT: | ||
| 792 | err = nfsd4_do_lookupp(rqstp, &cstate->current_fh); | ||
| 793 | if (err) | ||
| 794 | return err; | ||
| 795 | break; | ||
| 796 | default: | ||
| 797 | return nfserr_inval; | ||
| 798 | } | ||
| 799 | exp_get(cstate->current_fh.fh_export); | ||
| 800 | sin->sin_exp = cstate->current_fh.fh_export; | ||
| 801 | fh_put(&cstate->current_fh); | ||
| 802 | return nfs_ok; | ||
| 803 | } | ||
| 804 | |||
| 805 | static __be32 | ||
| 776 | nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | 806 | nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
| 777 | struct nfsd4_setattr *setattr) | 807 | struct nfsd4_setattr *setattr) |
| 778 | { | 808 | { |
| @@ -974,8 +1004,8 @@ static const char *nfsd4_op_name(unsigned opnum); | |||
| 974 | * Also note, enforced elsewhere: | 1004 | * Also note, enforced elsewhere: |
| 975 | * - SEQUENCE other than as first op results in | 1005 | * - SEQUENCE other than as first op results in |
| 976 | * NFS4ERR_SEQUENCE_POS. (Enforced in nfsd4_sequence().) | 1006 | * NFS4ERR_SEQUENCE_POS. (Enforced in nfsd4_sequence().) |
| 977 | * - BIND_CONN_TO_SESSION must be the only op in its compound | 1007 | * - BIND_CONN_TO_SESSION must be the only op in its compound. |
| 978 | * (Will be enforced in nfsd4_bind_conn_to_session().) | 1008 | * (Enforced in nfsd4_bind_conn_to_session().) |
| 979 | * - DESTROY_SESSION must be the final operation in a compound, if | 1009 | * - DESTROY_SESSION must be the final operation in a compound, if |
| 980 | * sessionid's in SEQUENCE and DESTROY_SESSION are the same. | 1010 | * sessionid's in SEQUENCE and DESTROY_SESSION are the same. |
| 981 | * (Enforced in nfsd4_destroy_session().) | 1011 | * (Enforced in nfsd4_destroy_session().) |
| @@ -1126,10 +1156,6 @@ encode_op: | |||
| 1126 | 1156 | ||
| 1127 | nfsd4_increment_op_stats(op->opnum); | 1157 | nfsd4_increment_op_stats(op->opnum); |
| 1128 | } | 1158 | } |
| 1129 | if (!rqstp->rq_usedeferral && status == nfserr_dropit) { | ||
| 1130 | dprintk("%s Dropit - send NFS4ERR_DELAY\n", __func__); | ||
| 1131 | status = nfserr_jukebox; | ||
| 1132 | } | ||
| 1133 | 1159 | ||
| 1134 | resp->cstate.status = status; | 1160 | resp->cstate.status = status; |
| 1135 | fh_put(&resp->cstate.current_fh); | 1161 | fh_put(&resp->cstate.current_fh); |
| @@ -1300,6 +1326,11 @@ static struct nfsd4_operation nfsd4_ops[] = { | |||
| 1300 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP, | 1326 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP, |
| 1301 | .op_name = "OP_EXCHANGE_ID", | 1327 | .op_name = "OP_EXCHANGE_ID", |
| 1302 | }, | 1328 | }, |
| 1329 | [OP_BIND_CONN_TO_SESSION] = { | ||
| 1330 | .op_func = (nfsd4op_func)nfsd4_bind_conn_to_session, | ||
| 1331 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP, | ||
| 1332 | .op_name = "OP_BIND_CONN_TO_SESSION", | ||
| 1333 | }, | ||
| 1303 | [OP_CREATE_SESSION] = { | 1334 | [OP_CREATE_SESSION] = { |
| 1304 | .op_func = (nfsd4op_func)nfsd4_create_session, | 1335 | .op_func = (nfsd4op_func)nfsd4_create_session, |
| 1305 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP, | 1336 | .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP, |
| @@ -1320,6 +1351,10 @@ static struct nfsd4_operation nfsd4_ops[] = { | |||
| 1320 | .op_flags = ALLOWED_WITHOUT_FH, | 1351 | .op_flags = ALLOWED_WITHOUT_FH, |
| 1321 | .op_name = "OP_RECLAIM_COMPLETE", | 1352 | .op_name = "OP_RECLAIM_COMPLETE", |
| 1322 | }, | 1353 | }, |
| 1354 | [OP_SECINFO_NO_NAME] = { | ||
| 1355 | .op_func = (nfsd4op_func)nfsd4_secinfo_no_name, | ||
| 1356 | .op_name = "OP_SECINFO_NO_NAME", | ||
| 1357 | }, | ||
| 1323 | }; | 1358 | }; |
| 1324 | 1359 | ||
| 1325 | static const char *nfsd4_op_name(unsigned opnum) | 1360 | static 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 fbd18c3074bb..d98d0213285d 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
| @@ -230,7 +230,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f | |||
| 230 | dp->dl_client = clp; | 230 | dp->dl_client = clp; |
| 231 | get_nfs4_file(fp); | 231 | get_nfs4_file(fp); |
| 232 | dp->dl_file = fp; | 232 | dp->dl_file = fp; |
| 233 | nfs4_file_get_access(fp, O_RDONLY); | 233 | dp->dl_vfs_file = find_readable_file(fp); |
| 234 | get_file(dp->dl_vfs_file); | ||
| 234 | dp->dl_flock = NULL; | 235 | dp->dl_flock = NULL; |
| 235 | dp->dl_type = type; | 236 | dp->dl_type = type; |
| 236 | dp->dl_stateid.si_boot = boot_time; | 237 | dp->dl_stateid.si_boot = boot_time; |
| @@ -252,6 +253,7 @@ nfs4_put_delegation(struct nfs4_delegation *dp) | |||
| 252 | if (atomic_dec_and_test(&dp->dl_count)) { | 253 | if (atomic_dec_and_test(&dp->dl_count)) { |
| 253 | dprintk("NFSD: freeing dp %p\n",dp); | 254 | dprintk("NFSD: freeing dp %p\n",dp); |
| 254 | put_nfs4_file(dp->dl_file); | 255 | put_nfs4_file(dp->dl_file); |
| 256 | fput(dp->dl_vfs_file); | ||
| 255 | kmem_cache_free(deleg_slab, dp); | 257 | kmem_cache_free(deleg_slab, dp); |
| 256 | num_delegations--; | 258 | num_delegations--; |
| 257 | } | 259 | } |
| @@ -265,12 +267,10 @@ nfs4_put_delegation(struct nfs4_delegation *dp) | |||
| 265 | static void | 267 | static void |
| 266 | nfs4_close_delegation(struct nfs4_delegation *dp) | 268 | nfs4_close_delegation(struct nfs4_delegation *dp) |
| 267 | { | 269 | { |
| 268 | struct file *filp = find_readable_file(dp->dl_file); | ||
| 269 | |||
| 270 | dprintk("NFSD: close_delegation dp %p\n",dp); | 270 | dprintk("NFSD: close_delegation dp %p\n",dp); |
| 271 | /* XXX: do we even need this check?: */ | ||
| 271 | if (dp->dl_flock) | 272 | if (dp->dl_flock) |
| 272 | vfs_setlease(filp, F_UNLCK, &dp->dl_flock); | 273 | vfs_setlease(dp->dl_vfs_file, F_UNLCK, &dp->dl_flock); |
| 273 | nfs4_file_put_access(dp->dl_file, O_RDONLY); | ||
| 274 | } | 274 | } |
| 275 | 275 | ||
| 276 | /* Called under the state lock. */ | 276 | /* Called under the state lock. */ |
| @@ -642,6 +642,7 @@ static void nfsd4_conn_lost(struct svc_xpt_user *u) | |||
| 642 | free_conn(c); | 642 | free_conn(c); |
| 643 | } | 643 | } |
| 644 | spin_unlock(&clp->cl_lock); | 644 | spin_unlock(&clp->cl_lock); |
| 645 | nfsd4_probe_callback(clp); | ||
| 645 | } | 646 | } |
| 646 | 647 | ||
| 647 | static struct nfsd4_conn *alloc_conn(struct svc_rqst *rqstp, u32 flags) | 648 | static struct nfsd4_conn *alloc_conn(struct svc_rqst *rqstp, u32 flags) |
| @@ -679,15 +680,12 @@ static int nfsd4_register_conn(struct nfsd4_conn *conn) | |||
| 679 | return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user); | 680 | return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user); |
| 680 | } | 681 | } |
| 681 | 682 | ||
| 682 | static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses) | 683 | static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses, u32 dir) |
| 683 | { | 684 | { |
| 684 | struct nfsd4_conn *conn; | 685 | struct nfsd4_conn *conn; |
| 685 | u32 flags = NFS4_CDFC4_FORE; | ||
| 686 | int ret; | 686 | int ret; |
| 687 | 687 | ||
| 688 | if (ses->se_flags & SESSION4_BACK_CHAN) | 688 | conn = alloc_conn(rqstp, dir); |
| 689 | flags |= NFS4_CDFC4_BACK; | ||
| 690 | conn = alloc_conn(rqstp, flags); | ||
| 691 | if (!conn) | 689 | if (!conn) |
| 692 | return nfserr_jukebox; | 690 | return nfserr_jukebox; |
| 693 | nfsd4_hash_conn(conn, ses); | 691 | nfsd4_hash_conn(conn, ses); |
| @@ -698,6 +696,17 @@ static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses) | |||
| 698 | return nfs_ok; | 696 | return nfs_ok; |
| 699 | } | 697 | } |
| 700 | 698 | ||
| 699 | static __be32 nfsd4_new_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_session *ses) | ||
| 700 | { | ||
| 701 | u32 dir = NFS4_CDFC4_FORE; | ||
| 702 | |||
| 703 | if (ses->se_flags & SESSION4_BACK_CHAN) | ||
| 704 | dir |= NFS4_CDFC4_BACK; | ||
| 705 | |||
| 706 | return nfsd4_new_conn(rqstp, ses, dir); | ||
| 707 | } | ||
| 708 | |||
| 709 | /* must be called under client_lock */ | ||
| 701 | static void nfsd4_del_conns(struct nfsd4_session *s) | 710 | static void nfsd4_del_conns(struct nfsd4_session *s) |
| 702 | { | 711 | { |
| 703 | struct nfs4_client *clp = s->se_client; | 712 | struct nfs4_client *clp = s->se_client; |
| @@ -749,6 +758,8 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n | |||
| 749 | */ | 758 | */ |
| 750 | slotsize = nfsd4_sanitize_slot_size(fchan->maxresp_cached); | 759 | slotsize = nfsd4_sanitize_slot_size(fchan->maxresp_cached); |
| 751 | numslots = nfsd4_get_drc_mem(slotsize, fchan->maxreqs); | 760 | numslots = nfsd4_get_drc_mem(slotsize, fchan->maxreqs); |
| 761 | if (numslots < 1) | ||
| 762 | return NULL; | ||
| 752 | 763 | ||
| 753 | new = alloc_session(slotsize, numslots); | 764 | new = alloc_session(slotsize, numslots); |
| 754 | if (!new) { | 765 | if (!new) { |
| @@ -769,25 +780,30 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n | |||
| 769 | idx = hash_sessionid(&new->se_sessionid); | 780 | idx = hash_sessionid(&new->se_sessionid); |
| 770 | spin_lock(&client_lock); | 781 | spin_lock(&client_lock); |
| 771 | list_add(&new->se_hash, &sessionid_hashtbl[idx]); | 782 | list_add(&new->se_hash, &sessionid_hashtbl[idx]); |
| 783 | spin_lock(&clp->cl_lock); | ||
| 772 | list_add(&new->se_perclnt, &clp->cl_sessions); | 784 | list_add(&new->se_perclnt, &clp->cl_sessions); |
| 785 | spin_unlock(&clp->cl_lock); | ||
| 773 | spin_unlock(&client_lock); | 786 | spin_unlock(&client_lock); |
| 774 | 787 | ||
| 775 | status = nfsd4_new_conn(rqstp, new); | 788 | status = nfsd4_new_conn_from_crses(rqstp, new); |
| 776 | /* whoops: benny points out, status is ignored! (err, or bogus) */ | 789 | /* whoops: benny points out, status is ignored! (err, or bogus) */ |
| 777 | if (status) { | 790 | if (status) { |
| 778 | free_session(&new->se_ref); | 791 | free_session(&new->se_ref); |
| 779 | return NULL; | 792 | return NULL; |
| 780 | } | 793 | } |
| 781 | if (!clp->cl_cb_session && (cses->flags & SESSION4_BACK_CHAN)) { | 794 | if (cses->flags & SESSION4_BACK_CHAN) { |
| 782 | struct sockaddr *sa = svc_addr(rqstp); | 795 | struct sockaddr *sa = svc_addr(rqstp); |
| 783 | 796 | /* | |
| 784 | clp->cl_cb_session = new; | 797 | * This is a little silly; with sessions there's no real |
| 785 | clp->cl_cb_conn.cb_xprt = rqstp->rq_xprt; | 798 | * use for the callback address. Use the peer address |
| 786 | svc_xprt_get(rqstp->rq_xprt); | 799 | * as a reasonable default for now, but consider fixing |
| 800 | * the rpc client not to require an address in the | ||
| 801 | * future: | ||
| 802 | */ | ||
| 787 | rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa); | 803 | rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa); |
| 788 | clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa); | 804 | clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa); |
| 789 | nfsd4_probe_callback(clp); | ||
| 790 | } | 805 | } |
| 806 | nfsd4_probe_callback(clp); | ||
| 791 | return new; | 807 | return new; |
| 792 | } | 808 | } |
| 793 | 809 | ||
| @@ -817,7 +833,9 @@ static void | |||
| 817 | unhash_session(struct nfsd4_session *ses) | 833 | unhash_session(struct nfsd4_session *ses) |
| 818 | { | 834 | { |
| 819 | list_del(&ses->se_hash); | 835 | list_del(&ses->se_hash); |
| 836 | spin_lock(&ses->se_client->cl_lock); | ||
| 820 | list_del(&ses->se_perclnt); | 837 | list_del(&ses->se_perclnt); |
| 838 | spin_unlock(&ses->se_client->cl_lock); | ||
| 821 | } | 839 | } |
| 822 | 840 | ||
| 823 | /* must be called under the client_lock */ | 841 | /* must be called under the client_lock */ |
| @@ -923,8 +941,10 @@ unhash_client_locked(struct nfs4_client *clp) | |||
| 923 | 941 | ||
| 924 | mark_client_expired(clp); | 942 | mark_client_expired(clp); |
| 925 | list_del(&clp->cl_lru); | 943 | list_del(&clp->cl_lru); |
| 944 | spin_lock(&clp->cl_lock); | ||
| 926 | list_for_each_entry(ses, &clp->cl_sessions, se_perclnt) | 945 | list_for_each_entry(ses, &clp->cl_sessions, se_perclnt) |
| 927 | list_del_init(&ses->se_hash); | 946 | list_del_init(&ses->se_hash); |
| 947 | spin_unlock(&clp->cl_lock); | ||
| 928 | } | 948 | } |
| 929 | 949 | ||
| 930 | static void | 950 | static void |
| @@ -1051,12 +1071,13 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir, | |||
| 1051 | 1071 | ||
| 1052 | memcpy(clp->cl_recdir, recdir, HEXDIR_LEN); | 1072 | memcpy(clp->cl_recdir, recdir, HEXDIR_LEN); |
| 1053 | atomic_set(&clp->cl_refcount, 0); | 1073 | atomic_set(&clp->cl_refcount, 0); |
| 1054 | atomic_set(&clp->cl_cb_set, 0); | 1074 | clp->cl_cb_state = NFSD4_CB_UNKNOWN; |
| 1055 | INIT_LIST_HEAD(&clp->cl_idhash); | 1075 | INIT_LIST_HEAD(&clp->cl_idhash); |
| 1056 | INIT_LIST_HEAD(&clp->cl_strhash); | 1076 | INIT_LIST_HEAD(&clp->cl_strhash); |
| 1057 | INIT_LIST_HEAD(&clp->cl_openowners); | 1077 | INIT_LIST_HEAD(&clp->cl_openowners); |
| 1058 | INIT_LIST_HEAD(&clp->cl_delegations); | 1078 | INIT_LIST_HEAD(&clp->cl_delegations); |
| 1059 | INIT_LIST_HEAD(&clp->cl_lru); | 1079 | INIT_LIST_HEAD(&clp->cl_lru); |
| 1080 | INIT_LIST_HEAD(&clp->cl_callbacks); | ||
| 1060 | spin_lock_init(&clp->cl_lock); | 1081 | spin_lock_init(&clp->cl_lock); |
| 1061 | INIT_WORK(&clp->cl_cb_null.cb_work, nfsd4_do_callback_rpc); | 1082 | INIT_WORK(&clp->cl_cb_null.cb_work, nfsd4_do_callback_rpc); |
| 1062 | clp->cl_time = get_seconds(); | 1083 | clp->cl_time = get_seconds(); |
| @@ -1132,54 +1153,55 @@ find_unconfirmed_client(clientid_t *clid) | |||
| 1132 | return NULL; | 1153 | return NULL; |
| 1133 | } | 1154 | } |
| 1134 | 1155 | ||
| 1135 | /* | 1156 | static bool clp_used_exchangeid(struct nfs4_client *clp) |
| 1136 | * Return 1 iff clp's clientid establishment method matches the use_exchange_id | ||
| 1137 | * parameter. Matching is based on the fact the at least one of the | ||
| 1138 | * EXCHGID4_FLAG_USE_{NON_PNFS,PNFS_MDS,PNFS_DS} flags must be set for v4.1 | ||
| 1139 | * | ||
| 1140 | * FIXME: we need to unify the clientid namespaces for nfsv4.x | ||
| 1141 | * and correctly deal with client upgrade/downgrade in EXCHANGE_ID | ||
| 1142 | * and SET_CLIENTID{,_CONFIRM} | ||
| 1143 | */ | ||
| 1144 | static inline int | ||
| 1145 | match_clientid_establishment(struct nfs4_client *clp, bool use_exchange_id) | ||
| 1146 | { | 1157 | { |
| 1147 | bool has_exchange_flags = (clp->cl_exchange_flags != 0); | 1158 | return clp->cl_exchange_flags != 0; |
| 1148 | return use_exchange_id == has_exchange_flags; | 1159 | } |
| 1149 | } | ||
| 1150 | 1160 | ||
| 1151 | static struct nfs4_client * | 1161 | static struct nfs4_client * |
| 1152 | find_confirmed_client_by_str(const char *dname, unsigned int hashval, | 1162 | find_confirmed_client_by_str(const char *dname, unsigned int hashval) |
| 1153 | bool use_exchange_id) | ||
| 1154 | { | 1163 | { |
| 1155 | struct nfs4_client *clp; | 1164 | struct nfs4_client *clp; |
| 1156 | 1165 | ||
| 1157 | list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) { | 1166 | list_for_each_entry(clp, &conf_str_hashtbl[hashval], cl_strhash) { |
| 1158 | if (same_name(clp->cl_recdir, dname) && | 1167 | if (same_name(clp->cl_recdir, dname)) |
| 1159 | match_clientid_establishment(clp, use_exchange_id)) | ||
| 1160 | return clp; | 1168 | return clp; |
| 1161 | } | 1169 | } |
| 1162 | return NULL; | 1170 | return NULL; |
| 1163 | } | 1171 | } |
| 1164 | 1172 | ||
| 1165 | static struct nfs4_client * | 1173 | static struct nfs4_client * |
| 1166 | find_unconfirmed_client_by_str(const char *dname, unsigned int hashval, | 1174 | find_unconfirmed_client_by_str(const char *dname, unsigned int hashval) |
| 1167 | bool use_exchange_id) | ||
| 1168 | { | 1175 | { |
| 1169 | struct nfs4_client *clp; | 1176 | struct nfs4_client *clp; |
| 1170 | 1177 | ||
| 1171 | list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) { | 1178 | list_for_each_entry(clp, &unconf_str_hashtbl[hashval], cl_strhash) { |
| 1172 | if (same_name(clp->cl_recdir, dname) && | 1179 | if (same_name(clp->cl_recdir, dname)) |
| 1173 | match_clientid_establishment(clp, use_exchange_id)) | ||
| 1174 | return clp; | 1180 | return clp; |
| 1175 | } | 1181 | } |
| 1176 | return NULL; | 1182 | return NULL; |
| 1177 | } | 1183 | } |
| 1178 | 1184 | ||
| 1185 | static void rpc_svcaddr2sockaddr(struct sockaddr *sa, unsigned short family, union svc_addr_u *svcaddr) | ||
| 1186 | { | ||
| 1187 | switch (family) { | ||
| 1188 | case AF_INET: | ||
| 1189 | ((struct sockaddr_in *)sa)->sin_family = AF_INET; | ||
| 1190 | ((struct sockaddr_in *)sa)->sin_addr = svcaddr->addr; | ||
| 1191 | return; | ||
| 1192 | case AF_INET6: | ||
| 1193 | ((struct sockaddr_in6 *)sa)->sin6_family = AF_INET6; | ||
| 1194 | ((struct sockaddr_in6 *)sa)->sin6_addr = svcaddr->addr6; | ||
| 1195 | return; | ||
| 1196 | } | ||
| 1197 | } | ||
| 1198 | |||
| 1179 | static void | 1199 | static void |
| 1180 | gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, u32 scopeid) | 1200 | gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, struct svc_rqst *rqstp) |
| 1181 | { | 1201 | { |
| 1182 | struct nfs4_cb_conn *conn = &clp->cl_cb_conn; | 1202 | struct nfs4_cb_conn *conn = &clp->cl_cb_conn; |
| 1203 | struct sockaddr *sa = svc_addr(rqstp); | ||
| 1204 | u32 scopeid = rpc_get_scope_id(sa); | ||
| 1183 | unsigned short expected_family; | 1205 | unsigned short expected_family; |
| 1184 | 1206 | ||
| 1185 | /* Currently, we only support tcp and tcp6 for the callback channel */ | 1207 | /* Currently, we only support tcp and tcp6 for the callback channel */ |
| @@ -1205,6 +1227,7 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, u32 scopeid) | |||
| 1205 | 1227 | ||
| 1206 | conn->cb_prog = se->se_callback_prog; | 1228 | conn->cb_prog = se->se_callback_prog; |
| 1207 | conn->cb_ident = se->se_callback_ident; | 1229 | conn->cb_ident = se->se_callback_ident; |
| 1230 | rpc_svcaddr2sockaddr((struct sockaddr *)&conn->cb_saddr, expected_family, &rqstp->rq_daddr); | ||
| 1208 | return; | 1231 | return; |
| 1209 | out_err: | 1232 | out_err: |
| 1210 | conn->cb_addr.ss_family = AF_UNSPEC; | 1233 | conn->cb_addr.ss_family = AF_UNSPEC; |
| @@ -1344,7 +1367,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, | |||
| 1344 | case SP4_NONE: | 1367 | case SP4_NONE: |
| 1345 | break; | 1368 | break; |
| 1346 | case SP4_SSV: | 1369 | case SP4_SSV: |
| 1347 | return nfserr_encr_alg_unsupp; | 1370 | return nfserr_serverfault; |
| 1348 | default: | 1371 | default: |
| 1349 | BUG(); /* checked by xdr code */ | 1372 | BUG(); /* checked by xdr code */ |
| 1350 | case SP4_MACH_CRED: | 1373 | case SP4_MACH_CRED: |
| @@ -1361,8 +1384,12 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, | |||
| 1361 | nfs4_lock_state(); | 1384 | nfs4_lock_state(); |
| 1362 | status = nfs_ok; | 1385 | status = nfs_ok; |
| 1363 | 1386 | ||
| 1364 | conf = find_confirmed_client_by_str(dname, strhashval, true); | 1387 | conf = find_confirmed_client_by_str(dname, strhashval); |
| 1365 | if (conf) { | 1388 | if (conf) { |
| 1389 | if (!clp_used_exchangeid(conf)) { | ||
| 1390 | status = nfserr_clid_inuse; /* XXX: ? */ | ||
| 1391 | goto out; | ||
| 1392 | } | ||
| 1366 | if (!same_verf(&verf, &conf->cl_verifier)) { | 1393 | if (!same_verf(&verf, &conf->cl_verifier)) { |
| 1367 | /* 18.35.4 case 8 */ | 1394 | /* 18.35.4 case 8 */ |
| 1368 | if (exid->flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A) { | 1395 | if (exid->flags & EXCHGID4_FLAG_UPD_CONFIRMED_REC_A) { |
| @@ -1403,7 +1430,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, | |||
| 1403 | goto out; | 1430 | goto out; |
| 1404 | } | 1431 | } |
| 1405 | 1432 | ||
| 1406 | unconf = find_unconfirmed_client_by_str(dname, strhashval, true); | 1433 | unconf = find_unconfirmed_client_by_str(dname, strhashval); |
| 1407 | if (unconf) { | 1434 | if (unconf) { |
| 1408 | /* | 1435 | /* |
| 1409 | * Possible retry or client restart. Per 18.35.4 case 4, | 1436 | * Possible retry or client restart. Per 18.35.4 case 4, |
| @@ -1560,6 +1587,8 @@ nfsd4_create_session(struct svc_rqst *rqstp, | |||
| 1560 | status = nfs_ok; | 1587 | status = nfs_ok; |
| 1561 | memcpy(cr_ses->sessionid.data, new->se_sessionid.data, | 1588 | memcpy(cr_ses->sessionid.data, new->se_sessionid.data, |
| 1562 | NFS4_MAX_SESSIONID_LEN); | 1589 | NFS4_MAX_SESSIONID_LEN); |
| 1590 | memcpy(&cr_ses->fore_channel, &new->se_fchannel, | ||
| 1591 | sizeof(struct nfsd4_channel_attrs)); | ||
| 1563 | cs_slot->sl_seqid++; | 1592 | cs_slot->sl_seqid++; |
| 1564 | cr_ses->seqid = cs_slot->sl_seqid; | 1593 | cr_ses->seqid = cs_slot->sl_seqid; |
| 1565 | 1594 | ||
| @@ -1581,6 +1610,45 @@ static bool nfsd4_last_compound_op(struct svc_rqst *rqstp) | |||
| 1581 | return argp->opcnt == resp->opcnt; | 1610 | return argp->opcnt == resp->opcnt; |
| 1582 | } | 1611 | } |
| 1583 | 1612 | ||
| 1613 | static __be32 nfsd4_map_bcts_dir(u32 *dir) | ||
| 1614 | { | ||
| 1615 | switch (*dir) { | ||
| 1616 | case NFS4_CDFC4_FORE: | ||
| 1617 | case NFS4_CDFC4_BACK: | ||
| 1618 | return nfs_ok; | ||
| 1619 | case NFS4_CDFC4_FORE_OR_BOTH: | ||
| 1620 | case NFS4_CDFC4_BACK_OR_BOTH: | ||
| 1621 | *dir = NFS4_CDFC4_BOTH; | ||
| 1622 | return nfs_ok; | ||
| 1623 | }; | ||
| 1624 | return nfserr_inval; | ||
| 1625 | } | ||
| 1626 | |||
| 1627 | __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp, | ||
| 1628 | struct nfsd4_compound_state *cstate, | ||
| 1629 | struct nfsd4_bind_conn_to_session *bcts) | ||
| 1630 | { | ||
| 1631 | __be32 status; | ||
| 1632 | |||
| 1633 | if (!nfsd4_last_compound_op(rqstp)) | ||
| 1634 | return nfserr_not_only_op; | ||
| 1635 | spin_lock(&client_lock); | ||
| 1636 | cstate->session = find_in_sessionid_hashtbl(&bcts->sessionid); | ||
| 1637 | /* Sorta weird: we only need the refcnt'ing because new_conn acquires | ||
| 1638 | * client_lock iself: */ | ||
| 1639 | if (cstate->session) { | ||
| 1640 | nfsd4_get_session(cstate->session); | ||
| 1641 | atomic_inc(&cstate->session->se_client->cl_refcount); | ||
| 1642 | } | ||
| 1643 | spin_unlock(&client_lock); | ||
| 1644 | if (!cstate->session) | ||
| 1645 | return nfserr_badsession; | ||
| 1646 | |||
| 1647 | status = nfsd4_map_bcts_dir(&bcts->dir); | ||
| 1648 | nfsd4_new_conn(rqstp, cstate->session, bcts->dir); | ||
| 1649 | return nfs_ok; | ||
| 1650 | } | ||
| 1651 | |||
| 1584 | static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid) | 1652 | static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid) |
| 1585 | { | 1653 | { |
| 1586 | if (!session) | 1654 | if (!session) |
| @@ -1619,8 +1687,7 @@ nfsd4_destroy_session(struct svc_rqst *r, | |||
| 1619 | spin_unlock(&client_lock); | 1687 | spin_unlock(&client_lock); |
| 1620 | 1688 | ||
| 1621 | nfs4_lock_state(); | 1689 | nfs4_lock_state(); |
| 1622 | /* wait for callbacks */ | 1690 | nfsd4_probe_callback_sync(ses->se_client); |
| 1623 | nfsd4_shutdown_callback(ses->se_client); | ||
| 1624 | nfs4_unlock_state(); | 1691 | nfs4_unlock_state(); |
| 1625 | 1692 | ||
| 1626 | nfsd4_del_conns(ses); | 1693 | nfsd4_del_conns(ses); |
| @@ -1733,8 +1800,12 @@ nfsd4_sequence(struct svc_rqst *rqstp, | |||
| 1733 | out: | 1800 | out: |
| 1734 | /* Hold a session reference until done processing the compound. */ | 1801 | /* Hold a session reference until done processing the compound. */ |
| 1735 | if (cstate->session) { | 1802 | if (cstate->session) { |
| 1803 | struct nfs4_client *clp = session->se_client; | ||
| 1804 | |||
| 1736 | nfsd4_get_session(cstate->session); | 1805 | nfsd4_get_session(cstate->session); |
| 1737 | atomic_inc(&session->se_client->cl_refcount); | 1806 | atomic_inc(&clp->cl_refcount); |
| 1807 | if (clp->cl_cb_state == NFSD4_CB_DOWN) | ||
| 1808 | seq->status_flags |= SEQ4_STATUS_CB_PATH_DOWN; | ||
| 1738 | } | 1809 | } |
| 1739 | kfree(conn); | 1810 | kfree(conn); |
| 1740 | spin_unlock(&client_lock); | 1811 | spin_unlock(&client_lock); |
| @@ -1775,7 +1846,6 @@ __be32 | |||
| 1775 | nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | 1846 | nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
| 1776 | struct nfsd4_setclientid *setclid) | 1847 | struct nfsd4_setclientid *setclid) |
| 1777 | { | 1848 | { |
| 1778 | struct sockaddr *sa = svc_addr(rqstp); | ||
| 1779 | struct xdr_netobj clname = { | 1849 | struct xdr_netobj clname = { |
| 1780 | .len = setclid->se_namelen, | 1850 | .len = setclid->se_namelen, |
| 1781 | .data = setclid->se_name, | 1851 | .data = setclid->se_name, |
| @@ -1801,10 +1871,12 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 1801 | strhashval = clientstr_hashval(dname); | 1871 | strhashval = clientstr_hashval(dname); |
| 1802 | 1872 | ||
| 1803 | nfs4_lock_state(); | 1873 | nfs4_lock_state(); |
| 1804 | conf = find_confirmed_client_by_str(dname, strhashval, false); | 1874 | conf = find_confirmed_client_by_str(dname, strhashval); |
| 1805 | if (conf) { | 1875 | if (conf) { |
| 1806 | /* RFC 3530 14.2.33 CASE 0: */ | 1876 | /* RFC 3530 14.2.33 CASE 0: */ |
| 1807 | status = nfserr_clid_inuse; | 1877 | status = nfserr_clid_inuse; |
| 1878 | if (clp_used_exchangeid(conf)) | ||
| 1879 | goto out; | ||
| 1808 | if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) { | 1880 | if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) { |
| 1809 | char addr_str[INET6_ADDRSTRLEN]; | 1881 | char addr_str[INET6_ADDRSTRLEN]; |
| 1810 | rpc_ntop((struct sockaddr *) &conf->cl_addr, addr_str, | 1882 | rpc_ntop((struct sockaddr *) &conf->cl_addr, addr_str, |
| @@ -1819,7 +1891,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 1819 | * has a description of SETCLIENTID request processing consisting | 1891 | * has a description of SETCLIENTID request processing consisting |
| 1820 | * of 5 bullet points, labeled as CASE0 - CASE4 below. | 1892 | * of 5 bullet points, labeled as CASE0 - CASE4 below. |
| 1821 | */ | 1893 | */ |
| 1822 | unconf = find_unconfirmed_client_by_str(dname, strhashval, false); | 1894 | unconf = find_unconfirmed_client_by_str(dname, strhashval); |
| 1823 | status = nfserr_resource; | 1895 | status = nfserr_resource; |
| 1824 | if (!conf) { | 1896 | if (!conf) { |
| 1825 | /* | 1897 | /* |
| @@ -1876,7 +1948,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 1876 | * for consistent minorversion use throughout: | 1948 | * for consistent minorversion use throughout: |
| 1877 | */ | 1949 | */ |
| 1878 | new->cl_minorversion = 0; | 1950 | new->cl_minorversion = 0; |
| 1879 | gen_callback(new, setclid, rpc_get_scope_id(sa)); | 1951 | gen_callback(new, setclid, rqstp); |
| 1880 | add_to_unconfirmed(new, strhashval); | 1952 | add_to_unconfirmed(new, strhashval); |
| 1881 | setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot; | 1953 | setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot; |
| 1882 | setclid->se_clientid.cl_id = new->cl_clientid.cl_id; | 1954 | setclid->se_clientid.cl_id = new->cl_clientid.cl_id; |
| @@ -1935,7 +2007,6 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
| 1935 | if (!same_creds(&conf->cl_cred, &unconf->cl_cred)) | 2007 | if (!same_creds(&conf->cl_cred, &unconf->cl_cred)) |
| 1936 | status = nfserr_clid_inuse; | 2008 | status = nfserr_clid_inuse; |
| 1937 | else { | 2009 | else { |
| 1938 | atomic_set(&conf->cl_cb_set, 0); | ||
| 1939 | nfsd4_change_callback(conf, &unconf->cl_cb_conn); | 2010 | nfsd4_change_callback(conf, &unconf->cl_cb_conn); |
| 1940 | nfsd4_probe_callback(conf); | 2011 | nfsd4_probe_callback(conf); |
| 1941 | expire_client(unconf); | 2012 | expire_client(unconf); |
| @@ -1964,7 +2035,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
| 1964 | unsigned int hash = | 2035 | unsigned int hash = |
| 1965 | clientstr_hashval(unconf->cl_recdir); | 2036 | clientstr_hashval(unconf->cl_recdir); |
| 1966 | conf = find_confirmed_client_by_str(unconf->cl_recdir, | 2037 | conf = find_confirmed_client_by_str(unconf->cl_recdir, |
| 1967 | hash, false); | 2038 | hash); |
| 1968 | if (conf) { | 2039 | if (conf) { |
| 1969 | nfsd4_remove_clid_dir(conf); | 2040 | nfsd4_remove_clid_dir(conf); |
| 1970 | expire_client(conf); | 2041 | expire_client(conf); |
| @@ -2300,41 +2371,6 @@ void nfsd_break_deleg_cb(struct file_lock *fl) | |||
| 2300 | nfsd4_cb_recall(dp); | 2371 | nfsd4_cb_recall(dp); |
| 2301 | } | 2372 | } |
| 2302 | 2373 | ||
| 2303 | /* | ||
| 2304 | * The file_lock is being reapd. | ||
| 2305 | * | ||
| 2306 | * Called by locks_free_lock() with lock_flocks() held. | ||
| 2307 | */ | ||
| 2308 | static | ||
| 2309 | void nfsd_release_deleg_cb(struct file_lock *fl) | ||
| 2310 | { | ||
| 2311 | struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner; | ||
| 2312 | |||
| 2313 | dprintk("NFSD nfsd_release_deleg_cb: fl %p dp %p dl_count %d\n", fl,dp, atomic_read(&dp->dl_count)); | ||
| 2314 | |||
| 2315 | if (!(fl->fl_flags & FL_LEASE) || !dp) | ||
| 2316 | return; | ||
| 2317 | dp->dl_flock = NULL; | ||
| 2318 | } | ||
| 2319 | |||
| 2320 | /* | ||
| 2321 | * Called from setlease() with lock_flocks() held | ||
| 2322 | */ | ||
| 2323 | static | ||
| 2324 | int nfsd_same_client_deleg_cb(struct file_lock *onlist, struct file_lock *try) | ||
| 2325 | { | ||
| 2326 | struct nfs4_delegation *onlistd = | ||
| 2327 | (struct nfs4_delegation *)onlist->fl_owner; | ||
| 2328 | struct nfs4_delegation *tryd = | ||
| 2329 | (struct nfs4_delegation *)try->fl_owner; | ||
| 2330 | |||
| 2331 | if (onlist->fl_lmops != try->fl_lmops) | ||
| 2332 | return 0; | ||
| 2333 | |||
| 2334 | return onlistd->dl_client == tryd->dl_client; | ||
| 2335 | } | ||
| 2336 | |||
| 2337 | |||
| 2338 | static | 2374 | static |
| 2339 | int nfsd_change_deleg_cb(struct file_lock **onlist, int arg) | 2375 | int nfsd_change_deleg_cb(struct file_lock **onlist, int arg) |
| 2340 | { | 2376 | { |
| @@ -2346,8 +2382,6 @@ int nfsd_change_deleg_cb(struct file_lock **onlist, int arg) | |||
| 2346 | 2382 | ||
| 2347 | static const struct lock_manager_operations nfsd_lease_mng_ops = { | 2383 | static const struct lock_manager_operations nfsd_lease_mng_ops = { |
| 2348 | .fl_break = nfsd_break_deleg_cb, | 2384 | .fl_break = nfsd_break_deleg_cb, |
| 2349 | .fl_release_private = nfsd_release_deleg_cb, | ||
| 2350 | .fl_mylease = nfsd_same_client_deleg_cb, | ||
| 2351 | .fl_change = nfsd_change_deleg_cb, | 2385 | .fl_change = nfsd_change_deleg_cb, |
| 2352 | }; | 2386 | }; |
| 2353 | 2387 | ||
| @@ -2514,8 +2548,6 @@ static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file | |||
| 2514 | if (!fp->fi_fds[oflag]) { | 2548 | if (!fp->fi_fds[oflag]) { |
| 2515 | status = nfsd_open(rqstp, cur_fh, S_IFREG, access, | 2549 | status = nfsd_open(rqstp, cur_fh, S_IFREG, access, |
| 2516 | &fp->fi_fds[oflag]); | 2550 | &fp->fi_fds[oflag]); |
| 2517 | if (status == nfserr_dropit) | ||
| 2518 | status = nfserr_jukebox; | ||
| 2519 | if (status) | 2551 | if (status) |
| 2520 | return status; | 2552 | return status; |
| 2521 | } | 2553 | } |
| @@ -2596,6 +2628,19 @@ nfs4_set_claim_prev(struct nfsd4_open *open) | |||
| 2596 | open->op_stateowner->so_client->cl_firststate = 1; | 2628 | open->op_stateowner->so_client->cl_firststate = 1; |
| 2597 | } | 2629 | } |
| 2598 | 2630 | ||
| 2631 | /* Should we give out recallable state?: */ | ||
| 2632 | static bool nfsd4_cb_channel_good(struct nfs4_client *clp) | ||
| 2633 | { | ||
| 2634 | if (clp->cl_cb_state == NFSD4_CB_UP) | ||
| 2635 | return true; | ||
| 2636 | /* | ||
| 2637 | * In the sessions case, since we don't have to establish a | ||
| 2638 | * separate connection for callbacks, we assume it's OK | ||
| 2639 | * until we hear otherwise: | ||
| 2640 | */ | ||
| 2641 | return clp->cl_minorversion && clp->cl_cb_state == NFSD4_CB_UNKNOWN; | ||
| 2642 | } | ||
| 2643 | |||
| 2599 | /* | 2644 | /* |
| 2600 | * Attempt to hand out a delegation. | 2645 | * Attempt to hand out a delegation. |
| 2601 | */ | 2646 | */ |
| @@ -2604,10 +2649,11 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta | |||
| 2604 | { | 2649 | { |
| 2605 | struct nfs4_delegation *dp; | 2650 | struct nfs4_delegation *dp; |
| 2606 | struct nfs4_stateowner *sop = stp->st_stateowner; | 2651 | struct nfs4_stateowner *sop = stp->st_stateowner; |
| 2607 | int cb_up = atomic_read(&sop->so_client->cl_cb_set); | 2652 | int cb_up; |
| 2608 | struct file_lock *fl; | 2653 | struct file_lock *fl; |
| 2609 | int status, flag = 0; | 2654 | int status, flag = 0; |
| 2610 | 2655 | ||
| 2656 | cb_up = nfsd4_cb_channel_good(sop->so_client); | ||
| 2611 | flag = NFS4_OPEN_DELEGATE_NONE; | 2657 | flag = NFS4_OPEN_DELEGATE_NONE; |
| 2612 | open->op_recall = 0; | 2658 | open->op_recall = 0; |
| 2613 | switch (open->op_claim_type) { | 2659 | switch (open->op_claim_type) { |
| @@ -2655,7 +2701,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta | |||
| 2655 | dp->dl_flock = fl; | 2701 | dp->dl_flock = fl; |
| 2656 | 2702 | ||
| 2657 | /* vfs_setlease checks to see if delegation should be handed out. | 2703 | /* vfs_setlease checks to see if delegation should be handed out. |
| 2658 | * the lock_manager callbacks fl_mylease and fl_change are used | 2704 | * the lock_manager callback fl_change is used |
| 2659 | */ | 2705 | */ |
| 2660 | if ((status = vfs_setlease(fl->fl_file, fl->fl_type, &fl))) { | 2706 | if ((status = vfs_setlease(fl->fl_file, fl->fl_type, &fl))) { |
| 2661 | dprintk("NFSD: setlease failed [%d], no delegation\n", status); | 2707 | dprintk("NFSD: setlease failed [%d], no delegation\n", status); |
| @@ -2794,7 +2840,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 2794 | renew_client(clp); | 2840 | renew_client(clp); |
| 2795 | status = nfserr_cb_path_down; | 2841 | status = nfserr_cb_path_down; |
| 2796 | if (!list_empty(&clp->cl_delegations) | 2842 | if (!list_empty(&clp->cl_delegations) |
| 2797 | && !atomic_read(&clp->cl_cb_set)) | 2843 | && clp->cl_cb_state != NFSD4_CB_UP) |
| 2798 | goto out; | 2844 | goto out; |
| 2799 | status = nfs_ok; | 2845 | status = nfs_ok; |
| 2800 | out: | 2846 | out: |
| @@ -3081,9 +3127,10 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, | |||
| 3081 | if (status) | 3127 | if (status) |
| 3082 | goto out; | 3128 | goto out; |
| 3083 | renew_client(dp->dl_client); | 3129 | renew_client(dp->dl_client); |
| 3084 | if (filpp) | 3130 | if (filpp) { |
| 3085 | *filpp = find_readable_file(dp->dl_file); | 3131 | *filpp = find_readable_file(dp->dl_file); |
| 3086 | BUG_ON(!*filpp); | 3132 | BUG_ON(!*filpp); |
| 3133 | } | ||
| 3087 | } else { /* open or lock stateid */ | 3134 | } else { /* open or lock stateid */ |
| 3088 | stp = find_stateid(stateid, flags); | 3135 | stp = find_stateid(stateid, flags); |
| 3089 | if (!stp) | 3136 | if (!stp) |
| @@ -4107,7 +4154,7 @@ nfs4_has_reclaimed_state(const char *name, bool use_exchange_id) | |||
| 4107 | unsigned int strhashval = clientstr_hashval(name); | 4154 | unsigned int strhashval = clientstr_hashval(name); |
| 4108 | struct nfs4_client *clp; | 4155 | struct nfs4_client *clp; |
| 4109 | 4156 | ||
| 4110 | clp = find_confirmed_client_by_str(name, strhashval, use_exchange_id); | 4157 | clp = find_confirmed_client_by_str(name, strhashval); |
| 4111 | return clp ? 1 : 0; | 4158 | return clp ? 1 : 0; |
| 4112 | } | 4159 | } |
| 4113 | 4160 | ||
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index f35a94a04026..956629b9cdc9 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; |
| @@ -420,6 +421,21 @@ nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access | |||
| 420 | DECODE_TAIL; | 421 | DECODE_TAIL; |
| 421 | } | 422 | } |
| 422 | 423 | ||
| 424 | static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts) | ||
| 425 | { | ||
| 426 | DECODE_HEAD; | ||
| 427 | u32 dummy; | ||
| 428 | |||
| 429 | READ_BUF(NFS4_MAX_SESSIONID_LEN + 8); | ||
| 430 | COPYMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN); | ||
| 431 | READ32(bcts->dir); | ||
| 432 | /* XXX: Perhaps Tom Tucker could help us figure out how we | ||
| 433 | * should be using ctsa_use_conn_in_rdma_mode: */ | ||
| 434 | READ32(dummy); | ||
| 435 | |||
| 436 | DECODE_TAIL; | ||
| 437 | } | ||
| 438 | |||
| 423 | static __be32 | 439 | static __be32 |
| 424 | nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close) | 440 | nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close) |
| 425 | { | 441 | { |
| @@ -847,6 +863,17 @@ nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp, | |||
| 847 | } | 863 | } |
| 848 | 864 | ||
| 849 | static __be32 | 865 | static __be32 |
| 866 | nfsd4_decode_secinfo_no_name(struct nfsd4_compoundargs *argp, | ||
| 867 | struct nfsd4_secinfo_no_name *sin) | ||
| 868 | { | ||
| 869 | DECODE_HEAD; | ||
| 870 | |||
| 871 | READ_BUF(4); | ||
| 872 | READ32(sin->sin_style); | ||
| 873 | DECODE_TAIL; | ||
| 874 | } | ||
| 875 | |||
| 876 | static __be32 | ||
| 850 | nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr) | 877 | nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr) |
| 851 | { | 878 | { |
| 852 | __be32 status; | 879 | __be32 status; |
| @@ -1005,7 +1032,7 @@ static __be32 | |||
| 1005 | nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp, | 1032 | nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp, |
| 1006 | struct nfsd4_exchange_id *exid) | 1033 | struct nfsd4_exchange_id *exid) |
| 1007 | { | 1034 | { |
| 1008 | int dummy; | 1035 | int dummy, tmp; |
| 1009 | DECODE_HEAD; | 1036 | DECODE_HEAD; |
| 1010 | 1037 | ||
| 1011 | READ_BUF(NFS4_VERIFIER_SIZE); | 1038 | READ_BUF(NFS4_VERIFIER_SIZE); |
| @@ -1053,15 +1080,23 @@ nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp, | |||
| 1053 | 1080 | ||
| 1054 | /* ssp_hash_algs<> */ | 1081 | /* ssp_hash_algs<> */ |
| 1055 | READ_BUF(4); | 1082 | READ_BUF(4); |
| 1056 | READ32(dummy); | 1083 | READ32(tmp); |
| 1057 | READ_BUF(dummy); | 1084 | while (tmp--) { |
| 1058 | p += XDR_QUADLEN(dummy); | 1085 | READ_BUF(4); |
| 1086 | READ32(dummy); | ||
| 1087 | READ_BUF(dummy); | ||
| 1088 | p += XDR_QUADLEN(dummy); | ||
| 1089 | } | ||
| 1059 | 1090 | ||
| 1060 | /* ssp_encr_algs<> */ | 1091 | /* ssp_encr_algs<> */ |
| 1061 | READ_BUF(4); | 1092 | READ_BUF(4); |
| 1062 | READ32(dummy); | 1093 | READ32(tmp); |
| 1063 | READ_BUF(dummy); | 1094 | while (tmp--) { |
| 1064 | p += XDR_QUADLEN(dummy); | 1095 | READ_BUF(4); |
| 1096 | READ32(dummy); | ||
| 1097 | READ_BUF(dummy); | ||
| 1098 | p += XDR_QUADLEN(dummy); | ||
| 1099 | } | ||
| 1065 | 1100 | ||
| 1066 | /* ssp_window and ssp_num_gss_handles */ | 1101 | /* ssp_window and ssp_num_gss_handles */ |
| 1067 | READ_BUF(8); | 1102 | READ_BUF(8); |
| @@ -1339,7 +1374,7 @@ static nfsd4_dec nfsd41_dec_ops[] = { | |||
| 1339 | 1374 | ||
| 1340 | /* new operations for NFSv4.1 */ | 1375 | /* new operations for NFSv4.1 */ |
| 1341 | [OP_BACKCHANNEL_CTL] = (nfsd4_dec)nfsd4_decode_notsupp, | 1376 | [OP_BACKCHANNEL_CTL] = (nfsd4_dec)nfsd4_decode_notsupp, |
| 1342 | [OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_notsupp, | 1377 | [OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_bind_conn_to_session, |
| 1343 | [OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id, | 1378 | [OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id, |
| 1344 | [OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session, | 1379 | [OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session, |
| 1345 | [OP_DESTROY_SESSION] = (nfsd4_dec)nfsd4_decode_destroy_session, | 1380 | [OP_DESTROY_SESSION] = (nfsd4_dec)nfsd4_decode_destroy_session, |
| @@ -1350,7 +1385,7 @@ static nfsd4_dec nfsd41_dec_ops[] = { | |||
| 1350 | [OP_LAYOUTCOMMIT] = (nfsd4_dec)nfsd4_decode_notsupp, | 1385 | [OP_LAYOUTCOMMIT] = (nfsd4_dec)nfsd4_decode_notsupp, |
| 1351 | [OP_LAYOUTGET] = (nfsd4_dec)nfsd4_decode_notsupp, | 1386 | [OP_LAYOUTGET] = (nfsd4_dec)nfsd4_decode_notsupp, |
| 1352 | [OP_LAYOUTRETURN] = (nfsd4_dec)nfsd4_decode_notsupp, | 1387 | [OP_LAYOUTRETURN] = (nfsd4_dec)nfsd4_decode_notsupp, |
| 1353 | [OP_SECINFO_NO_NAME] = (nfsd4_dec)nfsd4_decode_notsupp, | 1388 | [OP_SECINFO_NO_NAME] = (nfsd4_dec)nfsd4_decode_secinfo_no_name, |
| 1354 | [OP_SEQUENCE] = (nfsd4_dec)nfsd4_decode_sequence, | 1389 | [OP_SEQUENCE] = (nfsd4_dec)nfsd4_decode_sequence, |
| 1355 | [OP_SET_SSV] = (nfsd4_dec)nfsd4_decode_notsupp, | 1390 | [OP_SET_SSV] = (nfsd4_dec)nfsd4_decode_notsupp, |
| 1356 | [OP_TEST_STATEID] = (nfsd4_dec)nfsd4_decode_notsupp, | 1391 | [OP_TEST_STATEID] = (nfsd4_dec)nfsd4_decode_notsupp, |
| @@ -2309,8 +2344,6 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen, | |||
| 2309 | case nfserr_resource: | 2344 | case nfserr_resource: |
| 2310 | nfserr = nfserr_toosmall; | 2345 | nfserr = nfserr_toosmall; |
| 2311 | goto fail; | 2346 | goto fail; |
| 2312 | case nfserr_dropit: | ||
| 2313 | goto fail; | ||
| 2314 | case nfserr_noent: | 2347 | case nfserr_noent: |
| 2315 | goto skip_entry; | 2348 | goto skip_entry; |
| 2316 | default: | 2349 | default: |
| @@ -2365,6 +2398,21 @@ nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_ | |||
| 2365 | return nfserr; | 2398 | return nfserr; |
| 2366 | } | 2399 | } |
| 2367 | 2400 | ||
| 2401 | static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_bind_conn_to_session *bcts) | ||
| 2402 | { | ||
| 2403 | __be32 *p; | ||
| 2404 | |||
| 2405 | if (!nfserr) { | ||
| 2406 | RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 8); | ||
| 2407 | WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN); | ||
| 2408 | WRITE32(bcts->dir); | ||
| 2409 | /* XXX: ? */ | ||
| 2410 | WRITE32(0); | ||
| 2411 | ADJUST_ARGS(); | ||
| 2412 | } | ||
| 2413 | return nfserr; | ||
| 2414 | } | ||
| 2415 | |||
| 2368 | static __be32 | 2416 | static __be32 |
| 2369 | nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close) | 2417 | nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close) |
| 2370 | { | 2418 | { |
| @@ -2826,11 +2874,10 @@ nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_ | |||
| 2826 | } | 2874 | } |
| 2827 | 2875 | ||
| 2828 | static __be32 | 2876 | static __be32 |
| 2829 | nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr, | 2877 | nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp, |
| 2830 | struct nfsd4_secinfo *secinfo) | 2878 | __be32 nfserr,struct svc_export *exp) |
| 2831 | { | 2879 | { |
| 2832 | int i = 0; | 2880 | int i = 0; |
| 2833 | struct svc_export *exp = secinfo->si_exp; | ||
| 2834 | u32 nflavs; | 2881 | u32 nflavs; |
| 2835 | struct exp_flavor_info *flavs; | 2882 | struct exp_flavor_info *flavs; |
| 2836 | struct exp_flavor_info def_flavs[2]; | 2883 | struct exp_flavor_info def_flavs[2]; |
| @@ -2892,6 +2939,20 @@ out: | |||
| 2892 | return nfserr; | 2939 | return nfserr; |
| 2893 | } | 2940 | } |
| 2894 | 2941 | ||
| 2942 | static __be32 | ||
| 2943 | nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr, | ||
| 2944 | struct nfsd4_secinfo *secinfo) | ||
| 2945 | { | ||
| 2946 | return nfsd4_do_encode_secinfo(resp, nfserr, secinfo->si_exp); | ||
| 2947 | } | ||
| 2948 | |||
| 2949 | static __be32 | ||
| 2950 | nfsd4_encode_secinfo_no_name(struct nfsd4_compoundres *resp, __be32 nfserr, | ||
| 2951 | struct nfsd4_secinfo_no_name *secinfo) | ||
| 2952 | { | ||
| 2953 | return nfsd4_do_encode_secinfo(resp, nfserr, secinfo->sin_exp); | ||
| 2954 | } | ||
| 2955 | |||
| 2895 | /* | 2956 | /* |
| 2896 | * The SETATTR encode routine is special -- it always encodes a bitmap, | 2957 | * The SETATTR encode routine is special -- it always encodes a bitmap, |
| 2897 | * regardless of the error status. | 2958 | * regardless of the error status. |
| @@ -3076,13 +3137,9 @@ nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr, | |||
| 3076 | WRITE32(seq->seqid); | 3137 | WRITE32(seq->seqid); |
| 3077 | WRITE32(seq->slotid); | 3138 | WRITE32(seq->slotid); |
| 3078 | WRITE32(seq->maxslots); | 3139 | WRITE32(seq->maxslots); |
| 3079 | /* | 3140 | /* For now: target_maxslots = maxslots */ |
| 3080 | * FIXME: for now: | ||
| 3081 | * target_maxslots = maxslots | ||
| 3082 | * status_flags = 0 | ||
| 3083 | */ | ||
| 3084 | WRITE32(seq->maxslots); | 3141 | WRITE32(seq->maxslots); |
| 3085 | WRITE32(0); | 3142 | WRITE32(seq->status_flags); |
| 3086 | 3143 | ||
| 3087 | ADJUST_ARGS(); | 3144 | ADJUST_ARGS(); |
| 3088 | resp->cstate.datap = p; /* DRC cache data pointer */ | 3145 | resp->cstate.datap = p; /* DRC cache data pointer */ |
| @@ -3143,7 +3200,7 @@ static nfsd4_enc nfsd4_enc_ops[] = { | |||
| 3143 | 3200 | ||
| 3144 | /* NFSv4.1 operations */ | 3201 | /* NFSv4.1 operations */ |
| 3145 | [OP_BACKCHANNEL_CTL] = (nfsd4_enc)nfsd4_encode_noop, | 3202 | [OP_BACKCHANNEL_CTL] = (nfsd4_enc)nfsd4_encode_noop, |
| 3146 | [OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_noop, | 3203 | [OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_bind_conn_to_session, |
| 3147 | [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id, | 3204 | [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id, |
| 3148 | [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session, | 3205 | [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session, |
| 3149 | [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_destroy_session, | 3206 | [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_destroy_session, |
| @@ -3154,7 +3211,7 @@ static nfsd4_enc nfsd4_enc_ops[] = { | |||
| 3154 | [OP_LAYOUTCOMMIT] = (nfsd4_enc)nfsd4_encode_noop, | 3211 | [OP_LAYOUTCOMMIT] = (nfsd4_enc)nfsd4_encode_noop, |
| 3155 | [OP_LAYOUTGET] = (nfsd4_enc)nfsd4_encode_noop, | 3212 | [OP_LAYOUTGET] = (nfsd4_enc)nfsd4_encode_noop, |
| 3156 | [OP_LAYOUTRETURN] = (nfsd4_enc)nfsd4_encode_noop, | 3213 | [OP_LAYOUTRETURN] = (nfsd4_enc)nfsd4_encode_noop, |
| 3157 | [OP_SECINFO_NO_NAME] = (nfsd4_enc)nfsd4_encode_noop, | 3214 | [OP_SECINFO_NO_NAME] = (nfsd4_enc)nfsd4_encode_secinfo_no_name, |
| 3158 | [OP_SEQUENCE] = (nfsd4_enc)nfsd4_encode_sequence, | 3215 | [OP_SEQUENCE] = (nfsd4_enc)nfsd4_encode_sequence, |
| 3159 | [OP_SET_SSV] = (nfsd4_enc)nfsd4_encode_noop, | 3216 | [OP_SET_SSV] = (nfsd4_enc)nfsd4_encode_noop, |
| 3160 | [OP_TEST_STATEID] = (nfsd4_enc)nfsd4_encode_noop, | 3217 | [OP_TEST_STATEID] = (nfsd4_enc)nfsd4_encode_noop, |
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 4514ebbee4d6..33b3e2b06779 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
| @@ -8,12 +8,12 @@ | |||
| 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> |
| 16 | 15 | ||
| 16 | #include "idmap.h" | ||
| 17 | #include "nfsd.h" | 17 | #include "nfsd.h" |
| 18 | #include "cache.h" | 18 | #include "cache.h" |
| 19 | 19 | ||
| @@ -127,6 +127,7 @@ static ssize_t nfsctl_transaction_write(struct file *file, const char __user *bu | |||
| 127 | 127 | ||
| 128 | static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos) | 128 | static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos) |
| 129 | { | 129 | { |
| 130 | #ifdef CONFIG_NFSD_DEPRECATED | ||
| 130 | static int warned; | 131 | static int warned; |
| 131 | if (file->f_dentry->d_name.name[0] == '.' && !warned) { | 132 | if (file->f_dentry->d_name.name[0] == '.' && !warned) { |
| 132 | printk(KERN_INFO | 133 | printk(KERN_INFO |
| @@ -135,6 +136,7 @@ static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size | |||
| 135 | current->comm, file->f_dentry->d_name.name); | 136 | current->comm, file->f_dentry->d_name.name); |
| 136 | warned = 1; | 137 | warned = 1; |
| 137 | } | 138 | } |
| 139 | #endif | ||
| 138 | if (! file->private_data) { | 140 | if (! file->private_data) { |
| 139 | /* An attempt to read a transaction file without writing | 141 | /* An attempt to read a transaction file without writing |
| 140 | * causes a 0-byte write so that the file can return | 142 | * causes a 0-byte write so that the file can return |
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 6b641cf2c19a..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) |
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 2bae1d86f5f2..18743c4d8bca 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
| @@ -608,7 +608,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) | |||
| 608 | /* Now call the procedure handler, and encode NFS status. */ | 608 | /* Now call the procedure handler, and encode NFS status. */ |
| 609 | nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); | 609 | nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); |
| 610 | nfserr = map_new_errors(rqstp->rq_vers, nfserr); | 610 | nfserr = map_new_errors(rqstp->rq_vers, nfserr); |
| 611 | if (nfserr == nfserr_dropit) { | 611 | if (nfserr == nfserr_dropit || rqstp->rq_dropme) { |
| 612 | dprintk("nfsd: Dropping request; may be revisited later\n"); | 612 | dprintk("nfsd: Dropping request; may be revisited later\n"); |
| 613 | nfsd_cache_update(rqstp, RC_NOCACHE, NULL); | 613 | nfsd_cache_update(rqstp, RC_NOCACHE, NULL); |
| 614 | return 0; | 614 | return 0; |
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 39adc27b0685..3074656ba7bf 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
| @@ -68,10 +68,12 @@ typedef struct { | |||
| 68 | struct nfsd4_callback { | 68 | struct nfsd4_callback { |
| 69 | void *cb_op; | 69 | void *cb_op; |
| 70 | struct nfs4_client *cb_clp; | 70 | struct nfs4_client *cb_clp; |
| 71 | struct list_head cb_per_client; | ||
| 71 | u32 cb_minorversion; | 72 | u32 cb_minorversion; |
| 72 | struct rpc_message cb_msg; | 73 | struct rpc_message cb_msg; |
| 73 | const struct rpc_call_ops *cb_ops; | 74 | const struct rpc_call_ops *cb_ops; |
| 74 | struct work_struct cb_work; | 75 | struct work_struct cb_work; |
| 76 | bool cb_done; | ||
| 75 | }; | 77 | }; |
| 76 | 78 | ||
| 77 | struct nfs4_delegation { | 79 | struct nfs4_delegation { |
| @@ -81,6 +83,7 @@ struct nfs4_delegation { | |||
| 81 | atomic_t dl_count; /* ref count */ | 83 | atomic_t dl_count; /* ref count */ |
| 82 | struct nfs4_client *dl_client; | 84 | struct nfs4_client *dl_client; |
| 83 | struct nfs4_file *dl_file; | 85 | struct nfs4_file *dl_file; |
| 86 | struct file *dl_vfs_file; | ||
| 84 | struct file_lock *dl_flock; | 87 | struct file_lock *dl_flock; |
| 85 | u32 dl_type; | 88 | u32 dl_type; |
| 86 | time_t dl_time; | 89 | time_t dl_time; |
| @@ -95,6 +98,7 @@ struct nfs4_delegation { | |||
| 95 | struct nfs4_cb_conn { | 98 | struct nfs4_cb_conn { |
| 96 | /* SETCLIENTID info */ | 99 | /* SETCLIENTID info */ |
| 97 | struct sockaddr_storage cb_addr; | 100 | struct sockaddr_storage cb_addr; |
| 101 | struct sockaddr_storage cb_saddr; | ||
| 98 | size_t cb_addrlen; | 102 | size_t cb_addrlen; |
| 99 | u32 cb_prog; /* used only in 4.0 case; | 103 | u32 cb_prog; /* used only in 4.0 case; |
| 100 | per-session otherwise */ | 104 | per-session otherwise */ |
| @@ -146,6 +150,11 @@ struct nfsd4_create_session { | |||
| 146 | u32 gid; | 150 | u32 gid; |
| 147 | }; | 151 | }; |
| 148 | 152 | ||
| 153 | struct nfsd4_bind_conn_to_session { | ||
| 154 | struct nfs4_sessionid sessionid; | ||
| 155 | u32 dir; | ||
| 156 | }; | ||
| 157 | |||
| 149 | /* The single slot clientid cache structure */ | 158 | /* The single slot clientid cache structure */ |
| 150 | struct nfsd4_clid_slot { | 159 | struct nfsd4_clid_slot { |
| 151 | u32 sl_seqid; | 160 | u32 sl_seqid; |
| @@ -235,9 +244,13 @@ struct nfs4_client { | |||
| 235 | unsigned long cl_cb_flags; | 244 | unsigned long cl_cb_flags; |
| 236 | struct rpc_clnt *cl_cb_client; | 245 | struct rpc_clnt *cl_cb_client; |
| 237 | u32 cl_cb_ident; | 246 | u32 cl_cb_ident; |
| 238 | atomic_t cl_cb_set; | 247 | #define NFSD4_CB_UP 0 |
| 248 | #define NFSD4_CB_UNKNOWN 1 | ||
| 249 | #define NFSD4_CB_DOWN 2 | ||
| 250 | int cl_cb_state; | ||
| 239 | struct nfsd4_callback cl_cb_null; | 251 | struct nfsd4_callback cl_cb_null; |
| 240 | struct nfsd4_session *cl_cb_session; | 252 | struct nfsd4_session *cl_cb_session; |
| 253 | struct list_head cl_callbacks; /* list of in-progress callbacks */ | ||
| 241 | 254 | ||
| 242 | /* for all client information that callback code might need: */ | 255 | /* for all client information that callback code might need: */ |
| 243 | spinlock_t cl_lock; | 256 | spinlock_t cl_lock; |
| @@ -454,6 +467,7 @@ extern __be32 nfs4_check_open_reclaim(clientid_t *clid); | |||
| 454 | extern void nfs4_free_stateowner(struct kref *kref); | 467 | extern void nfs4_free_stateowner(struct kref *kref); |
| 455 | extern int set_callback_cred(void); | 468 | extern int set_callback_cred(void); |
| 456 | extern void nfsd4_probe_callback(struct nfs4_client *clp); | 469 | extern void nfsd4_probe_callback(struct nfs4_client *clp); |
| 470 | extern void nfsd4_probe_callback_sync(struct nfs4_client *clp); | ||
| 457 | extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *); | 471 | extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *); |
| 458 | extern void nfsd4_do_callback_rpc(struct work_struct *); | 472 | extern void nfsd4_do_callback_rpc(struct work_struct *); |
| 459 | extern void nfsd4_cb_recall(struct nfs4_delegation *dp); | 473 | extern void nfsd4_cb_recall(struct nfs4_delegation *dp); |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 230b79fbf005..a3c7f701395a 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -1,4 +1,3 @@ | |||
| 1 | #define MSNFS /* HACK HACK */ | ||
| 2 | /* | 1 | /* |
| 3 | * File operations used by nfsd. Some of these have been ripped from | 2 | * File operations used by nfsd. Some of these have been ripped from |
| 4 | * other parts of the kernel because they weren't exported, others | 3 | * other parts of the kernel because they weren't exported, others |
| @@ -35,8 +34,8 @@ | |||
| 35 | #endif /* CONFIG_NFSD_V3 */ | 34 | #endif /* CONFIG_NFSD_V3 */ |
| 36 | 35 | ||
| 37 | #ifdef CONFIG_NFSD_V4 | 36 | #ifdef CONFIG_NFSD_V4 |
| 38 | #include <linux/nfs4_acl.h> | 37 | #include "acl.h" |
| 39 | #include <linux/nfsd_idmap.h> | 38 | #include "idmap.h" |
| 40 | #endif /* CONFIG_NFSD_V4 */ | 39 | #endif /* CONFIG_NFSD_V4 */ |
| 41 | 40 | ||
| 42 | #include "nfsd.h" | 41 | #include "nfsd.h" |
| @@ -273,6 +272,13 @@ out: | |||
| 273 | return err; | 272 | return err; |
| 274 | } | 273 | } |
| 275 | 274 | ||
| 275 | static int nfsd_break_lease(struct inode *inode) | ||
| 276 | { | ||
| 277 | if (!S_ISREG(inode->i_mode)) | ||
| 278 | return 0; | ||
| 279 | return break_lease(inode, O_WRONLY | O_NONBLOCK); | ||
| 280 | } | ||
| 281 | |||
| 276 | /* | 282 | /* |
| 277 | * Commit metadata changes to stable storage. | 283 | * Commit metadata changes to stable storage. |
| 278 | */ | 284 | */ |
| @@ -375,16 +381,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, | |||
| 375 | goto out; | 381 | goto out; |
| 376 | } | 382 | } |
| 377 | 383 | ||
| 378 | /* | ||
| 379 | * If we are changing the size of the file, then | ||
| 380 | * we need to break all leases. | ||
| 381 | */ | ||
| 382 | host_err = break_lease(inode, O_WRONLY | O_NONBLOCK); | ||
| 383 | if (host_err == -EWOULDBLOCK) | ||
| 384 | host_err = -ETIMEDOUT; | ||
| 385 | if (host_err) /* ENOMEM or EWOULDBLOCK */ | ||
| 386 | goto out_nfserr; | ||
| 387 | |||
| 388 | host_err = get_write_access(inode); | 384 | host_err = get_write_access(inode); |
| 389 | if (host_err) | 385 | if (host_err) |
| 390 | goto out_nfserr; | 386 | goto out_nfserr; |
| @@ -425,7 +421,11 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, | |||
| 425 | 421 | ||
| 426 | err = nfserr_notsync; | 422 | err = nfserr_notsync; |
| 427 | if (!check_guard || guardtime == inode->i_ctime.tv_sec) { | 423 | if (!check_guard || guardtime == inode->i_ctime.tv_sec) { |
| 424 | host_err = nfsd_break_lease(inode); | ||
| 425 | if (host_err) | ||
| 426 | goto out_nfserr; | ||
| 428 | fh_lock(fhp); | 427 | fh_lock(fhp); |
| 428 | |||
| 429 | host_err = notify_change(dentry, iap); | 429 | host_err = notify_change(dentry, iap); |
| 430 | err = nfserrno(host_err); | 430 | err = nfserrno(host_err); |
| 431 | fh_unlock(fhp); | 431 | fh_unlock(fhp); |
| @@ -752,8 +752,6 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
| 752 | */ | 752 | */ |
| 753 | if (!(access & NFSD_MAY_NOT_BREAK_LEASE)) | 753 | if (!(access & NFSD_MAY_NOT_BREAK_LEASE)) |
| 754 | host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? O_WRONLY : 0)); | 754 | host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? O_WRONLY : 0)); |
| 755 | if (host_err == -EWOULDBLOCK) | ||
| 756 | host_err = -ETIMEDOUT; | ||
| 757 | if (host_err) /* NOMEM or WOULDBLOCK */ | 755 | if (host_err) /* NOMEM or WOULDBLOCK */ |
| 758 | goto out_nfserr; | 756 | goto out_nfserr; |
| 759 | 757 | ||
| @@ -874,15 +872,6 @@ static int nfsd_direct_splice_actor(struct pipe_inode_info *pipe, | |||
| 874 | return __splice_from_pipe(pipe, sd, nfsd_splice_actor); | 872 | return __splice_from_pipe(pipe, sd, nfsd_splice_actor); |
| 875 | } | 873 | } |
| 876 | 874 | ||
| 877 | static inline int svc_msnfs(struct svc_fh *ffhp) | ||
| 878 | { | ||
| 879 | #ifdef MSNFS | ||
| 880 | return (ffhp->fh_export->ex_flags & NFSEXP_MSNFS); | ||
| 881 | #else | ||
| 882 | return 0; | ||
| 883 | #endif | ||
| 884 | } | ||
| 885 | |||
| 886 | static __be32 | 875 | static __be32 |
| 887 | nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | 876 | nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, |
| 888 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) | 877 | loff_t offset, struct kvec *vec, int vlen, unsigned long *count) |
| @@ -895,9 +884,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
| 895 | err = nfserr_perm; | 884 | err = nfserr_perm; |
| 896 | inode = file->f_path.dentry->d_inode; | 885 | inode = file->f_path.dentry->d_inode; |
| 897 | 886 | ||
| 898 | if (svc_msnfs(fhp) && !lock_may_read(inode, offset, *count)) | ||
| 899 | goto out; | ||
| 900 | |||
| 901 | if (file->f_op->splice_read && rqstp->rq_splice_ok) { | 887 | if (file->f_op->splice_read && rqstp->rq_splice_ok) { |
| 902 | struct splice_desc sd = { | 888 | struct splice_desc sd = { |
| 903 | .len = 0, | 889 | .len = 0, |
| @@ -922,7 +908,6 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
| 922 | fsnotify_access(file); | 908 | fsnotify_access(file); |
| 923 | } else | 909 | } else |
| 924 | err = nfserrno(host_err); | 910 | err = nfserrno(host_err); |
| 925 | out: | ||
| 926 | return err; | 911 | return err; |
| 927 | } | 912 | } |
| 928 | 913 | ||
| @@ -987,14 +972,6 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
| 987 | int stable = *stablep; | 972 | int stable = *stablep; |
| 988 | int use_wgather; | 973 | int use_wgather; |
| 989 | 974 | ||
| 990 | #ifdef MSNFS | ||
| 991 | err = nfserr_perm; | ||
| 992 | |||
| 993 | if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && | ||
| 994 | (!lock_may_write(file->f_path.dentry->d_inode, offset, *cnt))) | ||
| 995 | goto out; | ||
| 996 | #endif | ||
| 997 | |||
| 998 | dentry = file->f_path.dentry; | 975 | dentry = file->f_path.dentry; |
| 999 | inode = dentry->d_inode; | 976 | inode = dentry->d_inode; |
| 1000 | exp = fhp->fh_export; | 977 | exp = fhp->fh_export; |
| @@ -1045,7 +1022,6 @@ out_nfserr: | |||
| 1045 | err = 0; | 1022 | err = 0; |
| 1046 | else | 1023 | else |
| 1047 | err = nfserrno(host_err); | 1024 | err = nfserrno(host_err); |
| 1048 | out: | ||
| 1049 | return err; | 1025 | return err; |
| 1050 | } | 1026 | } |
| 1051 | 1027 | ||
| @@ -1665,6 +1641,12 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
| 1665 | err = nfserrno(host_err); | 1641 | err = nfserrno(host_err); |
| 1666 | goto out_dput; | 1642 | goto out_dput; |
| 1667 | } | 1643 | } |
| 1644 | err = nfserr_noent; | ||
| 1645 | if (!dold->d_inode) | ||
| 1646 | goto out_drop_write; | ||
| 1647 | host_err = nfsd_break_lease(dold->d_inode); | ||
| 1648 | if (host_err) | ||
| 1649 | goto out_drop_write; | ||
| 1668 | host_err = vfs_link(dold, dirp, dnew); | 1650 | host_err = vfs_link(dold, dirp, dnew); |
| 1669 | if (!host_err) { | 1651 | if (!host_err) { |
| 1670 | err = nfserrno(commit_metadata(ffhp)); | 1652 | err = nfserrno(commit_metadata(ffhp)); |
| @@ -1676,6 +1658,7 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
| 1676 | else | 1658 | else |
| 1677 | err = nfserrno(host_err); | 1659 | err = nfserrno(host_err); |
| 1678 | } | 1660 | } |
| 1661 | out_drop_write: | ||
| 1679 | mnt_drop_write(tfhp->fh_export->ex_path.mnt); | 1662 | mnt_drop_write(tfhp->fh_export->ex_path.mnt); |
| 1680 | out_dput: | 1663 | out_dput: |
| 1681 | dput(dnew); | 1664 | dput(dnew); |
| @@ -1750,12 +1733,6 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
| 1750 | if (ndentry == trap) | 1733 | if (ndentry == trap) |
| 1751 | goto out_dput_new; | 1734 | goto out_dput_new; |
| 1752 | 1735 | ||
| 1753 | if (svc_msnfs(ffhp) && | ||
| 1754 | ((odentry->d_count > 1) || (ndentry->d_count > 1))) { | ||
| 1755 | host_err = -EPERM; | ||
| 1756 | goto out_dput_new; | ||
| 1757 | } | ||
| 1758 | |||
| 1759 | host_err = -EXDEV; | 1736 | host_err = -EXDEV; |
| 1760 | if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt) | 1737 | if (ffhp->fh_export->ex_path.mnt != tfhp->fh_export->ex_path.mnt) |
| 1761 | goto out_dput_new; | 1738 | goto out_dput_new; |
| @@ -1763,15 +1740,17 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |||
| 1763 | if (host_err) | 1740 | if (host_err) |
| 1764 | goto out_dput_new; | 1741 | goto out_dput_new; |
| 1765 | 1742 | ||
| 1743 | host_err = nfsd_break_lease(odentry->d_inode); | ||
| 1744 | if (host_err) | ||
| 1745 | goto out_drop_write; | ||
| 1766 | host_err = vfs_rename(fdir, odentry, tdir, ndentry); | 1746 | host_err = vfs_rename(fdir, odentry, tdir, ndentry); |
| 1767 | if (!host_err) { | 1747 | if (!host_err) { |
| 1768 | host_err = commit_metadata(tfhp); | 1748 | host_err = commit_metadata(tfhp); |
| 1769 | if (!host_err) | 1749 | if (!host_err) |
| 1770 | host_err = commit_metadata(ffhp); | 1750 | host_err = commit_metadata(ffhp); |
| 1771 | } | 1751 | } |
| 1772 | 1752 | out_drop_write: | |
| 1773 | mnt_drop_write(ffhp->fh_export->ex_path.mnt); | 1753 | mnt_drop_write(ffhp->fh_export->ex_path.mnt); |
| 1774 | |||
| 1775 | out_dput_new: | 1754 | out_dput_new: |
| 1776 | dput(ndentry); | 1755 | dput(ndentry); |
| 1777 | out_dput_old: | 1756 | out_dput_old: |
| @@ -1834,18 +1813,14 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
| 1834 | if (host_err) | 1813 | if (host_err) |
| 1835 | goto out_nfserr; | 1814 | goto out_nfserr; |
| 1836 | 1815 | ||
| 1837 | if (type != S_IFDIR) { /* It's UNLINK */ | 1816 | host_err = nfsd_break_lease(rdentry->d_inode); |
| 1838 | #ifdef MSNFS | 1817 | if (host_err) |
| 1839 | if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && | 1818 | goto out_put; |
| 1840 | (rdentry->d_count > 1)) { | 1819 | if (type != S_IFDIR) |
| 1841 | host_err = -EPERM; | ||
| 1842 | } else | ||
| 1843 | #endif | ||
| 1844 | host_err = vfs_unlink(dirp, rdentry); | 1820 | host_err = vfs_unlink(dirp, rdentry); |
| 1845 | } else { /* It's RMDIR */ | 1821 | else |
| 1846 | host_err = vfs_rmdir(dirp, rdentry); | 1822 | host_err = vfs_rmdir(dirp, rdentry); |
| 1847 | } | 1823 | out_put: |
| 1848 | |||
| 1849 | dput(rdentry); | 1824 | dput(rdentry); |
| 1850 | 1825 | ||
| 1851 | if (!host_err) | 1826 | if (!host_err) |
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index 60fce3dc5cb5..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 | ||
| 314 | struct nfsd4_secinfo_no_name { | ||
| 315 | u32 sin_style; /* request */ | ||
| 316 | struct svc_export *sin_exp; /* response */ | ||
| 317 | }; | ||
| 318 | |||
| 314 | struct nfsd4_setattr { | 319 | struct 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 | ||
| 380 | struct nfsd4_destroy_session { | 385 | struct 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; |
| @@ -518,6 +524,7 @@ extern __be32 nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp, | |||
| 518 | struct nfsd4_sequence *seq); | 524 | struct nfsd4_sequence *seq); |
| 519 | extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp, | 525 | extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp, |
| 520 | struct nfsd4_compound_state *, struct nfsd4_exchange_id *); | 526 | struct nfsd4_compound_state *, struct nfsd4_exchange_id *); |
| 527 | extern __be32 nfsd4_bind_conn_to_session(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_bind_conn_to_session *); | ||
| 521 | extern __be32 nfsd4_create_session(struct svc_rqst *, | 528 | extern __be32 nfsd4_create_session(struct svc_rqst *, |
| 522 | struct nfsd4_compound_state *, | 529 | struct nfsd4_compound_state *, |
| 523 | struct nfsd4_create_session *); | 530 | struct nfsd4_create_session *); |
