aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/acl.h59
-rw-r--r--fs/nfsd/export.c4
-rw-r--r--fs/nfsd/idmap.h62
-rw-r--r--fs/nfsd/nfs3proc.c8
-rw-r--r--fs/nfsd/nfs4acl.c2
-rw-r--r--fs/nfsd/nfs4callback.c151
-rw-r--r--fs/nfsd/nfs4idmap.c15
-rw-r--r--fs/nfsd/nfs4proc.c59
-rw-r--r--fs/nfsd/nfs4recover.c1
-rw-r--r--fs/nfsd/nfs4state.c243
-rw-r--r--fs/nfsd/nfs4xdr.c115
-rw-r--r--fs/nfsd/nfsctl.c4
-rw-r--r--fs/nfsd/nfsd.h1
-rw-r--r--fs/nfsd/nfsproc.c6
-rw-r--r--fs/nfsd/nfssvc.c2
-rw-r--r--fs/nfsd/state.h16
-rw-r--r--fs/nfsd/vfs.c85
-rw-r--r--fs/nfsd/xdr4.h9
18 files changed, 572 insertions, 270 deletions
diff --git a/fs/nfsd/acl.h b/fs/nfsd/acl.h
new file mode 100644
index 000000000000..34e5c40af5ef
--- /dev/null
+++ b/fs/nfsd/acl.h
@@ -0,0 +1,59 @@
1/*
2 * Common NFSv4 ACL handling definitions.
3 *
4 * Copyright (c) 2002 The Regents of the University of Michigan.
5 * All rights reserved.
6 *
7 * Marius Aamodt Eriksen <marius@umich.edu>
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#ifndef LINUX_NFS4_ACL_H
36#define LINUX_NFS4_ACL_H
37
38#include <linux/posix_acl.h>
39
40/* Maximum ACL we'll accept from client; chosen (somewhat arbitrarily) to
41 * fit in a page: */
42#define NFS4_ACL_MAX 170
43
44struct nfs4_acl *nfs4_acl_new(int);
45int nfs4_acl_get_whotype(char *, u32);
46int nfs4_acl_write_who(int who, char *p);
47int nfs4_acl_permission(struct nfs4_acl *acl, uid_t owner, gid_t group,
48 uid_t who, u32 mask);
49
50#define NFS4_ACL_TYPE_DEFAULT 0x01
51#define NFS4_ACL_DIR 0x02
52#define NFS4_ACL_OWNER 0x04
53
54struct nfs4_acl *nfs4_acl_posix_to_nfsv4(struct posix_acl *,
55 struct posix_acl *, unsigned int flags);
56int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *, struct posix_acl **,
57 struct posix_acl **, unsigned int flags);
58
59#endif /* LINUX_NFS4_ACL_H */
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 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
45int nfsd_idmap_init(void);
46void nfsd_idmap_shutdown(void);
47#else
48static inline int nfsd_idmap_init(void)
49{
50 return 0;
51}
52static inline void nfsd_idmap_shutdown(void)
53{
54}
55#endif
56
57__be32 nfsd_map_name_to_uid(struct svc_rqst *, const char *, size_t, __u32 *);
58__be32 nfsd_map_name_to_gid(struct svc_rqst *, const char *, size_t, __u32 *);
59int nfsd_map_uid_to_name(struct svc_rqst *, __u32, char *);
60int nfsd_map_gid_to_name(struct svc_rqst *, __u32, char *);
61
62#endif /* LINUX_NFSD_IDMAP_H */
diff --git a/fs/nfsd/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
634int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn) 632static 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
685static 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
682static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata) 691static 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
692static const struct rpc_call_ops nfsd4_cb_probe_ops = { 701static const struct rpc_call_ops nfsd4_cb_probe_ops = {
@@ -709,6 +718,11 @@ int set_callback_cred(void)
709 718
710static struct workqueue_struct *callback_wq; 719static struct workqueue_struct *callback_wq;
711 720
721static void run_nfsd4_cb(struct nfsd4_callback *cb)
722{
723 queue_work(callback_wq, &cb->cb_work);
724}
725
712static void do_probe_callback(struct nfs4_client *clp) 726static 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 */
733void nfsd4_probe_callback(struct nfs4_client *clp) 747void 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
739void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn) 755void 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
761void 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 */
753static int nfsd41_cb_setup_sequence(struct nfs4_client *clp, 774static 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 }
768out: 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
869static void nfsd4_cb_recall_release(void *calldata) 874static 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
877static const struct rpc_call_ops nfsd4_cb_recall_ops = { 888static 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
909void nfsd4_release_cb(struct nfsd4_callback *cb) 920static 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
915void nfsd4_process_cb_update(struct nfsd4_callback *cb) 926/* requires cl_lock: */
927static 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
941static 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
946void nfsd4_do_callback_rpc(struct work_struct *w) 989void nfsd4_do_callback_rpc(struct work_struct *w)
@@ -965,10 +1008,11 @@ void nfsd4_do_callback_rpc(struct work_struct *w)
965void nfsd4_cb_recall(struct nfs4_delegation *dp) 1008void 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
517static int 518static __be32
518idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen, 519idmap_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
563int 564__be32
564nfsd_map_name_to_uid(struct svc_rqst *rqstp, const char *name, size_t namelen, 565nfsd_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
570int 571__be32
571nfsd_map_name_to_gid(struct svc_rqst *rqstp, const char *name, size_t namelen, 572nfsd_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
607static __be32 607static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
608nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
609 void *arg)
610{ 608{
611 struct svc_fh tmp_fh; 609 struct svc_fh tmp_fh;
612 __be32 ret; 610 __be32 ret;
@@ -615,13 +613,19 @@ nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
615 ret = exp_pseudoroot(rqstp, &tmp_fh); 613 ret = exp_pseudoroot(rqstp, &tmp_fh);
616 if (ret) 614 if (ret)
617 return ret; 615 return ret;
618 if (tmp_fh.fh_dentry == cstate->current_fh.fh_dentry) { 616 if (tmp_fh.fh_dentry == fh->fh_dentry) {
619 fh_put(&tmp_fh); 617 fh_put(&tmp_fh);
620 return nfserr_noent; 618 return nfserr_noent;
621 } 619 }
622 fh_put(&tmp_fh); 620 fh_put(&tmp_fh);
623 return nfsd_lookup(rqstp, &cstate->current_fh, 621 return nfsd_lookup(rqstp, fh, "..", 2, fh);
624 "..", 2, &cstate->current_fh); 622}
623
624static __be32
625nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
626 void *arg)
627{
628 return nfsd4_do_lookupp(rqstp, &cstate->current_fh);
625} 629}
626 630
627static __be32 631static __be32
@@ -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
775static __be32 782static __be32
783nfsd4_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
805static __be32
776nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 806nfsd4_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
1325static const char *nfsd4_op_name(unsigned opnum) 1360static 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)
265static void 267static void
266nfs4_close_delegation(struct nfs4_delegation *dp) 268nfs4_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
647static struct nfsd4_conn *alloc_conn(struct svc_rqst *rqstp, u32 flags) 648static 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
682static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses) 683static __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
699static __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 */
701static void nfsd4_del_conns(struct nfsd4_session *s) 710static 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
817unhash_session(struct nfsd4_session *ses) 833unhash_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
930static void 950static 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/* 1156static 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 */
1144static inline int
1145match_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
1151static struct nfs4_client * 1161static struct nfs4_client *
1152find_confirmed_client_by_str(const char *dname, unsigned int hashval, 1162find_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
1165static struct nfs4_client * 1173static struct nfs4_client *
1166find_unconfirmed_client_by_str(const char *dname, unsigned int hashval, 1174find_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
1185static 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
1179static void 1199static void
1180gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, u32 scopeid) 1200gen_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;
1209out_err: 1232out_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
1613static __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
1584static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid) 1652static 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,
1733out: 1800out:
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
1775nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 1846nfsd4_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 */
2308static
2309void 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 */
2323static
2324int 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
2338static 2374static
2339int nfsd_change_deleg_cb(struct file_lock **onlist, int arg) 2375int 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
2347static const struct lock_manager_operations nfsd_lease_mng_ops = { 2383static 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?: */
2632static 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;
2800out: 2846out:
@@ -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
424static __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
423static __be32 439static __be32
424nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close) 440nfsd4_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
849static __be32 865static __be32
866nfsd4_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
876static __be32
850nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr) 877nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
851{ 878{
852 __be32 status; 879 __be32 status;
@@ -1005,7 +1032,7 @@ static __be32
1005nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp, 1032nfsd4_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
2401static __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
2368static __be32 2416static __be32
2369nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close) 2417nfsd4_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
2828static __be32 2876static __be32
2829nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr, 2877nfsd4_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
2942static __be32
2943nfsd4_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
2949static __be32
2950nfsd4_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
128static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos) 128static 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 {
68struct nfsd4_callback { 68struct 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
77struct nfs4_delegation { 79struct 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 {
95struct nfs4_cb_conn { 98struct 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
153struct 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 */
150struct nfsd4_clid_slot { 159struct 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);
454extern void nfs4_free_stateowner(struct kref *kref); 467extern void nfs4_free_stateowner(struct kref *kref);
455extern int set_callback_cred(void); 468extern int set_callback_cred(void);
456extern void nfsd4_probe_callback(struct nfs4_client *clp); 469extern void nfsd4_probe_callback(struct nfs4_client *clp);
470extern void nfsd4_probe_callback_sync(struct nfs4_client *clp);
457extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *); 471extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *);
458extern void nfsd4_do_callback_rpc(struct work_struct *); 472extern void nfsd4_do_callback_rpc(struct work_struct *);
459extern void nfsd4_cb_recall(struct nfs4_delegation *dp); 473extern 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
275static 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
877static 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
886static __be32 875static __be32
887nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, 876nfsd_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);
925out:
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);
1048out:
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 }
1661out_drop_write:
1679 mnt_drop_write(tfhp->fh_export->ex_path.mnt); 1662 mnt_drop_write(tfhp->fh_export->ex_path.mnt);
1680out_dput: 1663out_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 1752out_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 } 1823out_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
314struct nfsd4_secinfo_no_name {
315 u32 sin_style; /* request */
316 struct svc_export *sin_exp; /* response */
317};
318
314struct nfsd4_setattr { 319struct nfsd4_setattr {
315 stateid_t sa_stateid; /* request */ 320 stateid_t sa_stateid; /* request */
316 u32 sa_bmval[3]; /* request */ 321 u32 sa_bmval[3]; /* request */
@@ -373,8 +378,8 @@ struct nfsd4_sequence {
373 u32 cachethis; /* request */ 378 u32 cachethis; /* request */
374#if 0 379#if 0
375 u32 target_maxslots; /* response */ 380 u32 target_maxslots; /* response */
376 u32 status_flags; /* response */
377#endif /* not yet */ 381#endif /* not yet */
382 u32 status_flags; /* response */
378}; 383};
379 384
380struct nfsd4_destroy_session { 385struct nfsd4_destroy_session {
@@ -422,6 +427,7 @@ struct nfsd4_op {
422 427
423 /* NFSv4.1 */ 428 /* NFSv4.1 */
424 struct nfsd4_exchange_id exchange_id; 429 struct nfsd4_exchange_id exchange_id;
430 struct nfsd4_bind_conn_to_session bind_conn_to_session;
425 struct nfsd4_create_session create_session; 431 struct nfsd4_create_session create_session;
426 struct nfsd4_destroy_session destroy_session; 432 struct nfsd4_destroy_session destroy_session;
427 struct nfsd4_sequence sequence; 433 struct nfsd4_sequence sequence;
@@ -518,6 +524,7 @@ extern __be32 nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp,
518 struct nfsd4_sequence *seq); 524 struct nfsd4_sequence *seq);
519extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp, 525extern __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 *);
527extern __be32 nfsd4_bind_conn_to_session(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_bind_conn_to_session *);
521extern __be32 nfsd4_create_session(struct svc_rqst *, 528extern __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 *);