aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-12 21:53:54 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-12 21:53:54 -0400
commitbd81ccea8558daab570d70d2c23746413f26cecf (patch)
treea3a75dde2dc3cf26c74353b21792da30d65d7c13 /fs
parent98260daa184c4a171834463cf85ab3a2c509d983 (diff)
parenta9ca4043d074509b9d15003fbcb068d3cdae85a4 (diff)
Merge branch 'for-3.7' of git://linux-nfs.org/~bfields/linux
Pull nfsd update from J Bruce Fields: "Another relatively quiet cycle. There was some progress on my remaining 4.1 todo's, but a couple of them were just of the form "check that we do X correctly", so didn't have much affect on the code. Other than that, a bunch of cleanup and some bugfixes (including an annoying NFSv4.0 state leak and a busy-loop in the server that could cause it to peg the CPU without making progress)." * 'for-3.7' of git://linux-nfs.org/~bfields/linux: (46 commits) UAPI: (Scripted) Disintegrate include/linux/sunrpc UAPI: (Scripted) Disintegrate include/linux/nfsd nfsd4: don't allow reclaims of expired clients nfsd4: remove redundant callback probe nfsd4: expire old client earlier nfsd4: separate session allocation and initialization nfsd4: clean up session allocation nfsd4: minor free_session cleanup nfsd4: new_conn_from_crses should only allocate nfsd4: separate connection allocation and initialization nfsd4: reject bad forechannel attrs earlier nfsd4: enforce per-client sessions/no-sessions distinction nfsd4: set cl_minorversion at create time nfsd4: don't pin clientids to pseudoflavors nfsd4: fix bind_conn_to_session xdr comment nfsd4: cast readlink() bug argument NFSD: pass null terminated buf to kstrtouint() nfsd: remove duplicate init in nfsd4_cb_recall nfsd4: eliminate redundant nfs4_free_stateid fs/nfsd/nfs4idmap.c: adjust inconsistent IS_ERR and PTR_ERR ...
Diffstat (limited to 'fs')
-rw-r--r--fs/lockd/svc.c17
-rw-r--r--fs/locks.c6
-rw-r--r--fs/nfs/callback.c16
-rw-r--r--fs/nfsd/nfs2acl.c3
-rw-r--r--fs/nfsd/nfs3proc.c2
-rw-r--r--fs/nfsd/nfs4callback.c1
-rw-r--r--fs/nfsd/nfs4idmap.c4
-rw-r--r--fs/nfsd/nfs4proc.c6
-rw-r--r--fs/nfsd/nfs4state.c351
-rw-r--r--fs/nfsd/nfs4xdr.c2
-rw-r--r--fs/nfsd/nfsctl.c84
-rw-r--r--fs/nfsd/nfsd.h4
-rw-r--r--fs/nfsd/nfssvc.c26
-rw-r--r--fs/nfsd/state.h8
-rw-r--r--fs/nfsd/vfs.c2
15 files changed, 227 insertions, 305 deletions
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 7e355870d519..a2aa97d45670 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -126,7 +126,7 @@ static void restart_grace(void)
126static int 126static int
127lockd(void *vrqstp) 127lockd(void *vrqstp)
128{ 128{
129 int err = 0, preverr = 0; 129 int err = 0;
130 struct svc_rqst *rqstp = vrqstp; 130 struct svc_rqst *rqstp = vrqstp;
131 131
132 /* try_to_freeze() is called from svc_recv() */ 132 /* try_to_freeze() is called from svc_recv() */
@@ -165,21 +165,8 @@ lockd(void *vrqstp)
165 * recvfrom routine. 165 * recvfrom routine.
166 */ 166 */
167 err = svc_recv(rqstp, timeout); 167 err = svc_recv(rqstp, timeout);
168 if (err == -EAGAIN || err == -EINTR) { 168 if (err == -EAGAIN || err == -EINTR)
169 preverr = err;
170 continue; 169 continue;
171 }
172 if (err < 0) {
173 if (err != preverr) {
174 printk(KERN_WARNING "%s: unexpected error "
175 "from svc_recv (%d)\n", __func__, err);
176 preverr = err;
177 }
178 schedule_timeout_interruptible(HZ);
179 continue;
180 }
181 preverr = err;
182
183 dprintk("lockd: request from %s\n", 170 dprintk("lockd: request from %s\n",
184 svc_print_addr(rqstp, buf, sizeof(buf))); 171 svc_print_addr(rqstp, buf, sizeof(buf)));
185 172
diff --git a/fs/locks.c b/fs/locks.c
index abc7dc6c490b..a94e331a52a2 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1289,7 +1289,7 @@ EXPORT_SYMBOL(__break_lease);
1289void lease_get_mtime(struct inode *inode, struct timespec *time) 1289void lease_get_mtime(struct inode *inode, struct timespec *time)
1290{ 1290{
1291 struct file_lock *flock = inode->i_flock; 1291 struct file_lock *flock = inode->i_flock;
1292 if (flock && IS_LEASE(flock) && (flock->fl_type & F_WRLCK)) 1292 if (flock && IS_LEASE(flock) && (flock->fl_type == F_WRLCK))
1293 *time = current_fs_time(inode->i_sb); 1293 *time = current_fs_time(inode->i_sb);
1294 else 1294 else
1295 *time = inode->i_mtime; 1295 *time = inode->i_mtime;
@@ -2185,8 +2185,8 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
2185 } else { 2185 } else {
2186 seq_printf(f, "%s ", 2186 seq_printf(f, "%s ",
2187 (lease_breaking(fl)) 2187 (lease_breaking(fl))
2188 ? (fl->fl_type & F_UNLCK) ? "UNLCK" : "READ " 2188 ? (fl->fl_type == F_UNLCK) ? "UNLCK" : "READ "
2189 : (fl->fl_type & F_WRLCK) ? "WRITE" : "READ "); 2189 : (fl->fl_type == F_WRLCK) ? "WRITE" : "READ ");
2190 } 2190 }
2191 if (inode) { 2191 if (inode) {
2192#ifdef WE_CAN_BREAK_LSLK_NOW 2192#ifdef WE_CAN_BREAK_LSLK_NOW
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 2245bef50f37..9a521fb39869 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -72,7 +72,7 @@ out_err:
72static int 72static int
73nfs4_callback_svc(void *vrqstp) 73nfs4_callback_svc(void *vrqstp)
74{ 74{
75 int err, preverr = 0; 75 int err;
76 struct svc_rqst *rqstp = vrqstp; 76 struct svc_rqst *rqstp = vrqstp;
77 77
78 set_freezable(); 78 set_freezable();
@@ -82,20 +82,8 @@ nfs4_callback_svc(void *vrqstp)
82 * Listen for a request on the socket 82 * Listen for a request on the socket
83 */ 83 */
84 err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT); 84 err = svc_recv(rqstp, MAX_SCHEDULE_TIMEOUT);
85 if (err == -EAGAIN || err == -EINTR) { 85 if (err == -EAGAIN || err == -EINTR)
86 preverr = err;
87 continue; 86 continue;
88 }
89 if (err < 0) {
90 if (err != preverr) {
91 printk(KERN_WARNING "NFS: %s: unexpected error "
92 "from svc_recv (%d)\n", __func__, err);
93 preverr = err;
94 }
95 schedule_timeout_uninterruptible(HZ);
96 continue;
97 }
98 preverr = err;
99 svc_process(rqstp); 87 svc_process(rqstp);
100 } 88 }
101 return 0; 89 return 0;
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index 6aa5590c3679..b314888825d5 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -218,8 +218,7 @@ static int nfsaclsvc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p,
218 * There must be an encoding function for void results so svc_process 218 * There must be an encoding function for void results so svc_process
219 * will work properly. 219 * will work properly.
220 */ 220 */
221int 221static int nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
222nfsaclsvc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
223{ 222{
224 return xdr_ressize_check(rqstp, p); 223 return xdr_ressize_check(rqstp, p);
225} 224}
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 9095f3c21df9..97d90d1c8608 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -247,7 +247,7 @@ nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp,
247 /* Now create the file and set attributes */ 247 /* Now create the file and set attributes */
248 nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len, 248 nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len,
249 attr, newfhp, 249 attr, newfhp,
250 argp->createmode, argp->verf, NULL, NULL); 250 argp->createmode, (u32 *)argp->verf, NULL, NULL);
251 251
252 RETURN_STATUS(nfserr); 252 RETURN_STATUS(nfserr);
253} 253}
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 4c7bd35b1876..bdf29c96e4cd 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -1028,7 +1028,6 @@ void nfsd4_cb_recall(struct nfs4_delegation *dp)
1028 cb->cb_msg.rpc_cred = callback_cred; 1028 cb->cb_msg.rpc_cred = callback_cred;
1029 1029
1030 cb->cb_ops = &nfsd4_cb_recall_ops; 1030 cb->cb_ops = &nfsd4_cb_recall_ops;
1031 dp->dl_retries = 1;
1032 1031
1033 INIT_LIST_HEAD(&cb->cb_per_client); 1032 INIT_LIST_HEAD(&cb->cb_per_client);
1034 cb->cb_done = true; 1033 cb->cb_done = true;
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c
index fdc91a6fc9c4..a1f10c0a6255 100644
--- a/fs/nfsd/nfs4idmap.c
+++ b/fs/nfsd/nfs4idmap.c
@@ -478,7 +478,7 @@ nfsd_idmap_init(struct net *net)
478 goto destroy_idtoname_cache; 478 goto destroy_idtoname_cache;
479 nn->nametoid_cache = cache_create_net(&nametoid_cache_template, net); 479 nn->nametoid_cache = cache_create_net(&nametoid_cache_template, net);
480 if (IS_ERR(nn->nametoid_cache)) { 480 if (IS_ERR(nn->nametoid_cache)) {
481 rv = PTR_ERR(nn->idtoname_cache); 481 rv = PTR_ERR(nn->nametoid_cache);
482 goto unregister_idtoname_cache; 482 goto unregister_idtoname_cache;
483 } 483 }
484 rv = cache_register_net(nn->nametoid_cache, net); 484 rv = cache_register_net(nn->nametoid_cache, net);
@@ -598,7 +598,7 @@ numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namel
598 /* Just to make sure it's null-terminated: */ 598 /* Just to make sure it's null-terminated: */
599 memcpy(buf, name, namelen); 599 memcpy(buf, name, namelen);
600 buf[namelen] = '\0'; 600 buf[namelen] = '\0';
601 ret = kstrtouint(name, 10, id); 601 ret = kstrtouint(buf, 10, id);
602 return ret == 0; 602 return ret == 0;
603} 603}
604 604
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index c9c1c0a25417..6c9a4b291dba 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -370,7 +370,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
370 break; 370 break;
371 case NFS4_OPEN_CLAIM_PREVIOUS: 371 case NFS4_OPEN_CLAIM_PREVIOUS:
372 open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; 372 open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
373 status = nfs4_check_open_reclaim(&open->op_clientid); 373 status = nfs4_check_open_reclaim(&open->op_clientid, cstate->minorversion);
374 if (status) 374 if (status)
375 goto out; 375 goto out;
376 case NFS4_OPEN_CLAIM_FH: 376 case NFS4_OPEN_CLAIM_FH:
@@ -1054,8 +1054,8 @@ struct nfsd4_operation {
1054 char *op_name; 1054 char *op_name;
1055 /* Try to get response size before operation */ 1055 /* Try to get response size before operation */
1056 nfsd4op_rsize op_rsize_bop; 1056 nfsd4op_rsize op_rsize_bop;
1057 stateid_setter op_get_currentstateid; 1057 stateid_getter op_get_currentstateid;
1058 stateid_getter op_set_currentstateid; 1058 stateid_setter op_set_currentstateid;
1059}; 1059};
1060 1060
1061static struct nfsd4_operation nfsd4_ops[]; 1061static struct nfsd4_operation nfsd4_ops[];
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 48a1bad37334..d0237f872cc4 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -758,7 +758,7 @@ static void nfsd4_put_drc_mem(int slotsize, int num)
758 spin_unlock(&nfsd_drc_lock); 758 spin_unlock(&nfsd_drc_lock);
759} 759}
760 760
761static struct nfsd4_session *alloc_session(int slotsize, int numslots) 761static struct nfsd4_session *__alloc_session(int slotsize, int numslots)
762{ 762{
763 struct nfsd4_session *new; 763 struct nfsd4_session *new;
764 int mem, i; 764 int mem, i;
@@ -852,35 +852,28 @@ static int nfsd4_register_conn(struct nfsd4_conn *conn)
852 return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user); 852 return register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user);
853} 853}
854 854
855static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses, u32 dir) 855static void nfsd4_init_conn(struct svc_rqst *rqstp, struct nfsd4_conn *conn, struct nfsd4_session *ses)
856{ 856{
857 struct nfsd4_conn *conn;
858 int ret; 857 int ret;
859 858
860 conn = alloc_conn(rqstp, dir);
861 if (!conn)
862 return nfserr_jukebox;
863 nfsd4_hash_conn(conn, ses); 859 nfsd4_hash_conn(conn, ses);
864 ret = nfsd4_register_conn(conn); 860 ret = nfsd4_register_conn(conn);
865 if (ret) 861 if (ret)
866 /* oops; xprt is already down: */ 862 /* oops; xprt is already down: */
867 nfsd4_conn_lost(&conn->cn_xpt_user); 863 nfsd4_conn_lost(&conn->cn_xpt_user);
868 if (ses->se_client->cl_cb_state == NFSD4_CB_DOWN && 864 if (conn->cn_flags & NFS4_CDFC4_BACK) {
869 dir & NFS4_CDFC4_BACK) {
870 /* callback channel may be back up */ 865 /* callback channel may be back up */
871 nfsd4_probe_callback(ses->se_client); 866 nfsd4_probe_callback(ses->se_client);
872 } 867 }
873 return nfs_ok;
874} 868}
875 869
876static __be32 nfsd4_new_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_session *ses) 870static struct nfsd4_conn *alloc_conn_from_crses(struct svc_rqst *rqstp, struct nfsd4_create_session *cses)
877{ 871{
878 u32 dir = NFS4_CDFC4_FORE; 872 u32 dir = NFS4_CDFC4_FORE;
879 873
880 if (ses->se_flags & SESSION4_BACK_CHAN) 874 if (cses->flags & SESSION4_BACK_CHAN)
881 dir |= NFS4_CDFC4_BACK; 875 dir |= NFS4_CDFC4_BACK;
882 876 return alloc_conn(rqstp, dir);
883 return nfsd4_new_conn(rqstp, ses, dir);
884} 877}
885 878
886/* must be called under client_lock */ 879/* must be called under client_lock */
@@ -903,20 +896,21 @@ static void nfsd4_del_conns(struct nfsd4_session *s)
903 spin_unlock(&clp->cl_lock); 896 spin_unlock(&clp->cl_lock);
904} 897}
905 898
899static void __free_session(struct nfsd4_session *ses)
900{
901 nfsd4_put_drc_mem(slot_bytes(&ses->se_fchannel), ses->se_fchannel.maxreqs);
902 free_session_slots(ses);
903 kfree(ses);
904}
905
906static void free_session(struct kref *kref) 906static void free_session(struct kref *kref)
907{ 907{
908 struct nfsd4_session *ses; 908 struct nfsd4_session *ses;
909 int mem;
910 909
911 lockdep_assert_held(&client_lock); 910 lockdep_assert_held(&client_lock);
912 ses = container_of(kref, struct nfsd4_session, se_ref); 911 ses = container_of(kref, struct nfsd4_session, se_ref);
913 nfsd4_del_conns(ses); 912 nfsd4_del_conns(ses);
914 spin_lock(&nfsd_drc_lock); 913 __free_session(ses);
915 mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel);
916 nfsd_drc_mem_used -= mem;
917 spin_unlock(&nfsd_drc_lock);
918 free_session_slots(ses);
919 kfree(ses);
920} 914}
921 915
922void nfsd4_put_session(struct nfsd4_session *ses) 916void nfsd4_put_session(struct nfsd4_session *ses)
@@ -926,14 +920,10 @@ void nfsd4_put_session(struct nfsd4_session *ses)
926 spin_unlock(&client_lock); 920 spin_unlock(&client_lock);
927} 921}
928 922
929static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses) 923static struct nfsd4_session *alloc_session(struct nfsd4_channel_attrs *fchan)
930{ 924{
931 struct nfsd4_session *new; 925 struct nfsd4_session *new;
932 struct nfsd4_channel_attrs *fchan = &cses->fore_channel;
933 int numslots, slotsize; 926 int numslots, slotsize;
934 __be32 status;
935 int idx;
936
937 /* 927 /*
938 * Note decreasing slot size below client's request may 928 * Note decreasing slot size below client's request may
939 * make it difficult for client to function correctly, whereas 929 * make it difficult for client to function correctly, whereas
@@ -946,12 +936,18 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n
946 if (numslots < 1) 936 if (numslots < 1)
947 return NULL; 937 return NULL;
948 938
949 new = alloc_session(slotsize, numslots); 939 new = __alloc_session(slotsize, numslots);
950 if (!new) { 940 if (!new) {
951 nfsd4_put_drc_mem(slotsize, fchan->maxreqs); 941 nfsd4_put_drc_mem(slotsize, fchan->maxreqs);
952 return NULL; 942 return NULL;
953 } 943 }
954 init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize); 944 init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize);
945 return new;
946}
947
948static struct nfsd4_session *init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, struct nfs4_client *clp, struct nfsd4_create_session *cses)
949{
950 int idx;
955 951
956 new->se_client = clp; 952 new->se_client = clp;
957 gen_sessionid(new); 953 gen_sessionid(new);
@@ -970,14 +966,6 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n
970 spin_unlock(&clp->cl_lock); 966 spin_unlock(&clp->cl_lock);
971 spin_unlock(&client_lock); 967 spin_unlock(&client_lock);
972 968
973 status = nfsd4_new_conn_from_crses(rqstp, new);
974 /* whoops: benny points out, status is ignored! (err, or bogus) */
975 if (status) {
976 spin_lock(&client_lock);
977 free_session(&new->se_ref);
978 spin_unlock(&client_lock);
979 return NULL;
980 }
981 if (cses->flags & SESSION4_BACK_CHAN) { 969 if (cses->flags & SESSION4_BACK_CHAN) {
982 struct sockaddr *sa = svc_addr(rqstp); 970 struct sockaddr *sa = svc_addr(rqstp);
983 /* 971 /*
@@ -990,7 +978,6 @@ static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct n
990 rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa); 978 rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa);
991 clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa); 979 clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
992 } 980 }
993 nfsd4_probe_callback(clp);
994 return new; 981 return new;
995} 982}
996 983
@@ -1131,7 +1118,7 @@ unhash_client_locked(struct nfs4_client *clp)
1131} 1118}
1132 1119
1133static void 1120static void
1134expire_client(struct nfs4_client *clp) 1121destroy_client(struct nfs4_client *clp)
1135{ 1122{
1136 struct nfs4_openowner *oo; 1123 struct nfs4_openowner *oo;
1137 struct nfs4_delegation *dp; 1124 struct nfs4_delegation *dp;
@@ -1165,6 +1152,12 @@ expire_client(struct nfs4_client *clp)
1165 spin_unlock(&client_lock); 1152 spin_unlock(&client_lock);
1166} 1153}
1167 1154
1155static void expire_client(struct nfs4_client *clp)
1156{
1157 nfsd4_client_record_remove(clp);
1158 destroy_client(clp);
1159}
1160
1168static void copy_verf(struct nfs4_client *target, nfs4_verifier *source) 1161static void copy_verf(struct nfs4_client *target, nfs4_verifier *source)
1169{ 1162{
1170 memcpy(target->cl_verifier.data, source->data, 1163 memcpy(target->cl_verifier.data, source->data,
@@ -1223,10 +1216,26 @@ static bool groups_equal(struct group_info *g1, struct group_info *g2)
1223 return true; 1216 return true;
1224} 1217}
1225 1218
1219/*
1220 * RFC 3530 language requires clid_inuse be returned when the
1221 * "principal" associated with a requests differs from that previously
1222 * used. We use uid, gid's, and gss principal string as our best
1223 * approximation. We also don't want to allow non-gss use of a client
1224 * established using gss: in theory cr_principal should catch that
1225 * change, but in practice cr_principal can be null even in the gss case
1226 * since gssd doesn't always pass down a principal string.
1227 */
1228static bool is_gss_cred(struct svc_cred *cr)
1229{
1230 /* Is cr_flavor one of the gss "pseudoflavors"?: */
1231 return (cr->cr_flavor > RPC_AUTH_MAXFLAVOR);
1232}
1233
1234
1226static bool 1235static bool
1227same_creds(struct svc_cred *cr1, struct svc_cred *cr2) 1236same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
1228{ 1237{
1229 if ((cr1->cr_flavor != cr2->cr_flavor) 1238 if ((is_gss_cred(cr1) != is_gss_cred(cr2))
1230 || (cr1->cr_uid != cr2->cr_uid) 1239 || (cr1->cr_uid != cr2->cr_uid)
1231 || (cr1->cr_gid != cr2->cr_gid) 1240 || (cr1->cr_gid != cr2->cr_gid)
1232 || !groups_equal(cr1->cr_group_info, cr2->cr_group_info)) 1241 || !groups_equal(cr1->cr_group_info, cr2->cr_group_info))
@@ -1340,13 +1349,15 @@ move_to_confirmed(struct nfs4_client *clp)
1340} 1349}
1341 1350
1342static struct nfs4_client * 1351static struct nfs4_client *
1343find_confirmed_client(clientid_t *clid) 1352find_confirmed_client(clientid_t *clid, bool sessions)
1344{ 1353{
1345 struct nfs4_client *clp; 1354 struct nfs4_client *clp;
1346 unsigned int idhashval = clientid_hashval(clid->cl_id); 1355 unsigned int idhashval = clientid_hashval(clid->cl_id);
1347 1356
1348 list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) { 1357 list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
1349 if (same_clid(&clp->cl_clientid, clid)) { 1358 if (same_clid(&clp->cl_clientid, clid)) {
1359 if ((bool)clp->cl_minorversion != sessions)
1360 return NULL;
1350 renew_client(clp); 1361 renew_client(clp);
1351 return clp; 1362 return clp;
1352 } 1363 }
@@ -1355,14 +1366,17 @@ find_confirmed_client(clientid_t *clid)
1355} 1366}
1356 1367
1357static struct nfs4_client * 1368static struct nfs4_client *
1358find_unconfirmed_client(clientid_t *clid) 1369find_unconfirmed_client(clientid_t *clid, bool sessions)
1359{ 1370{
1360 struct nfs4_client *clp; 1371 struct nfs4_client *clp;
1361 unsigned int idhashval = clientid_hashval(clid->cl_id); 1372 unsigned int idhashval = clientid_hashval(clid->cl_id);
1362 1373
1363 list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) { 1374 list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) {
1364 if (same_clid(&clp->cl_clientid, clid)) 1375 if (same_clid(&clp->cl_clientid, clid)) {
1376 if ((bool)clp->cl_minorversion != sessions)
1377 return NULL;
1365 return clp; 1378 return clp;
1379 }
1366 } 1380 }
1367 return NULL; 1381 return NULL;
1368} 1382}
@@ -1651,6 +1665,7 @@ out_new:
1651 status = nfserr_jukebox; 1665 status = nfserr_jukebox;
1652 goto out; 1666 goto out;
1653 } 1667 }
1668 new->cl_minorversion = 1;
1654 1669
1655 gen_clid(new); 1670 gen_clid(new);
1656 add_to_unconfirmed(new, strhashval); 1671 add_to_unconfirmed(new, strhashval);
@@ -1743,67 +1758,71 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1743 struct sockaddr *sa = svc_addr(rqstp); 1758 struct sockaddr *sa = svc_addr(rqstp);
1744 struct nfs4_client *conf, *unconf; 1759 struct nfs4_client *conf, *unconf;
1745 struct nfsd4_session *new; 1760 struct nfsd4_session *new;
1761 struct nfsd4_conn *conn;
1746 struct nfsd4_clid_slot *cs_slot = NULL; 1762 struct nfsd4_clid_slot *cs_slot = NULL;
1747 bool confirm_me = false;
1748 __be32 status = 0; 1763 __be32 status = 0;
1749 1764
1750 if (cr_ses->flags & ~SESSION4_FLAG_MASK_A) 1765 if (cr_ses->flags & ~SESSION4_FLAG_MASK_A)
1751 return nfserr_inval; 1766 return nfserr_inval;
1767 if (check_forechannel_attrs(cr_ses->fore_channel))
1768 return nfserr_toosmall;
1769 new = alloc_session(&cr_ses->fore_channel);
1770 if (!new)
1771 return nfserr_jukebox;
1772 status = nfserr_jukebox;
1773 conn = alloc_conn_from_crses(rqstp, cr_ses);
1774 if (!conn)
1775 goto out_free_session;
1752 1776
1753 nfs4_lock_state(); 1777 nfs4_lock_state();
1754 unconf = find_unconfirmed_client(&cr_ses->clientid); 1778 unconf = find_unconfirmed_client(&cr_ses->clientid, true);
1755 conf = find_confirmed_client(&cr_ses->clientid); 1779 conf = find_confirmed_client(&cr_ses->clientid, true);
1756 1780
1757 if (conf) { 1781 if (conf) {
1758 cs_slot = &conf->cl_cs_slot; 1782 cs_slot = &conf->cl_cs_slot;
1759 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); 1783 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
1760 if (status == nfserr_replay_cache) { 1784 if (status == nfserr_replay_cache) {
1761 status = nfsd4_replay_create_session(cr_ses, cs_slot); 1785 status = nfsd4_replay_create_session(cr_ses, cs_slot);
1762 goto out; 1786 goto out_free_conn;
1763 } else if (cr_ses->seqid != cs_slot->sl_seqid + 1) { 1787 } else if (cr_ses->seqid != cs_slot->sl_seqid + 1) {
1764 status = nfserr_seq_misordered; 1788 status = nfserr_seq_misordered;
1765 goto out; 1789 goto out_free_conn;
1766 } 1790 }
1767 } else if (unconf) { 1791 } else if (unconf) {
1792 unsigned int hash;
1793 struct nfs4_client *old;
1768 if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) || 1794 if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) ||
1769 !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) { 1795 !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) {
1770 status = nfserr_clid_inuse; 1796 status = nfserr_clid_inuse;
1771 goto out; 1797 goto out_free_conn;
1772 } 1798 }
1773 cs_slot = &unconf->cl_cs_slot; 1799 cs_slot = &unconf->cl_cs_slot;
1774 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0); 1800 status = check_slot_seqid(cr_ses->seqid, cs_slot->sl_seqid, 0);
1775 if (status) { 1801 if (status) {
1776 /* an unconfirmed replay returns misordered */ 1802 /* an unconfirmed replay returns misordered */
1777 status = nfserr_seq_misordered; 1803 status = nfserr_seq_misordered;
1778 goto out; 1804 goto out_free_conn;
1779 } 1805 }
1780 confirm_me = true; 1806 hash = clientstr_hashval(unconf->cl_recdir);
1807 old = find_confirmed_client_by_str(unconf->cl_recdir, hash);
1808 if (old)
1809 expire_client(old);
1810 move_to_confirmed(unconf);
1781 conf = unconf; 1811 conf = unconf;
1782 } else { 1812 } else {
1783 status = nfserr_stale_clientid; 1813 status = nfserr_stale_clientid;
1784 goto out; 1814 goto out_free_conn;
1785 } 1815 }
1786 1816 status = nfs_ok;
1787 /*
1788 * XXX: we should probably set this at creation time, and check
1789 * for consistent minorversion use throughout:
1790 */
1791 conf->cl_minorversion = 1;
1792 /* 1817 /*
1793 * We do not support RDMA or persistent sessions 1818 * We do not support RDMA or persistent sessions
1794 */ 1819 */
1795 cr_ses->flags &= ~SESSION4_PERSIST; 1820 cr_ses->flags &= ~SESSION4_PERSIST;
1796 cr_ses->flags &= ~SESSION4_RDMA; 1821 cr_ses->flags &= ~SESSION4_RDMA;
1797 1822
1798 status = nfserr_toosmall; 1823 init_session(rqstp, new, conf, cr_ses);
1799 if (check_forechannel_attrs(cr_ses->fore_channel)) 1824 nfsd4_init_conn(rqstp, conn, new);
1800 goto out;
1801 1825
1802 status = nfserr_jukebox;
1803 new = alloc_init_session(rqstp, conf, cr_ses);
1804 if (!new)
1805 goto out;
1806 status = nfs_ok;
1807 memcpy(cr_ses->sessionid.data, new->se_sessionid.data, 1826 memcpy(cr_ses->sessionid.data, new->se_sessionid.data,
1808 NFS4_MAX_SESSIONID_LEN); 1827 NFS4_MAX_SESSIONID_LEN);
1809 memcpy(&cr_ses->fore_channel, &new->se_fchannel, 1828 memcpy(&cr_ses->fore_channel, &new->se_fchannel,
@@ -1813,18 +1832,15 @@ nfsd4_create_session(struct svc_rqst *rqstp,
1813 1832
1814 /* cache solo and embedded create sessions under the state lock */ 1833 /* cache solo and embedded create sessions under the state lock */
1815 nfsd4_cache_create_session(cr_ses, cs_slot, status); 1834 nfsd4_cache_create_session(cr_ses, cs_slot, status);
1816 if (confirm_me) {
1817 unsigned int hash = clientstr_hashval(unconf->cl_recdir);
1818 struct nfs4_client *old =
1819 find_confirmed_client_by_str(conf->cl_recdir, hash);
1820 if (old)
1821 expire_client(old);
1822 move_to_confirmed(conf);
1823 }
1824out: 1835out:
1825 nfs4_unlock_state(); 1836 nfs4_unlock_state();
1826 dprintk("%s returns %d\n", __func__, ntohl(status)); 1837 dprintk("%s returns %d\n", __func__, ntohl(status));
1827 return status; 1838 return status;
1839out_free_conn:
1840 free_conn(conn);
1841out_free_session:
1842 __free_session(new);
1843 goto out;
1828} 1844}
1829 1845
1830static bool nfsd4_last_compound_op(struct svc_rqst *rqstp) 1846static bool nfsd4_last_compound_op(struct svc_rqst *rqstp)
@@ -1854,6 +1870,7 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
1854 struct nfsd4_bind_conn_to_session *bcts) 1870 struct nfsd4_bind_conn_to_session *bcts)
1855{ 1871{
1856 __be32 status; 1872 __be32 status;
1873 struct nfsd4_conn *conn;
1857 1874
1858 if (!nfsd4_last_compound_op(rqstp)) 1875 if (!nfsd4_last_compound_op(rqstp))
1859 return nfserr_not_only_op; 1876 return nfserr_not_only_op;
@@ -1870,9 +1887,13 @@ __be32 nfsd4_bind_conn_to_session(struct svc_rqst *rqstp,
1870 return nfserr_badsession; 1887 return nfserr_badsession;
1871 1888
1872 status = nfsd4_map_bcts_dir(&bcts->dir); 1889 status = nfsd4_map_bcts_dir(&bcts->dir);
1873 if (!status) 1890 if (status)
1874 nfsd4_new_conn(rqstp, cstate->session, bcts->dir); 1891 return status;
1875 return status; 1892 conn = alloc_conn(rqstp, bcts->dir);
1893 if (!conn)
1894 return nfserr_jukebox;
1895 nfsd4_init_conn(rqstp, conn, cstate->session);
1896 return nfs_ok;
1876} 1897}
1877 1898
1878static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid) 1899static bool nfsd4_compound_in_session(struct nfsd4_session *session, struct nfs4_sessionid *sid)
@@ -2085,8 +2106,8 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
2085 __be32 status = 0; 2106 __be32 status = 0;
2086 2107
2087 nfs4_lock_state(); 2108 nfs4_lock_state();
2088 unconf = find_unconfirmed_client(&dc->clientid); 2109 unconf = find_unconfirmed_client(&dc->clientid, true);
2089 conf = find_confirmed_client(&dc->clientid); 2110 conf = find_confirmed_client(&dc->clientid, true);
2090 2111
2091 if (conf) { 2112 if (conf) {
2092 clp = conf; 2113 clp = conf;
@@ -2200,10 +2221,6 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2200 copy_clid(new, conf); 2221 copy_clid(new, conf);
2201 else /* case 4 (new client) or cases 2, 3 (client reboot): */ 2222 else /* case 4 (new client) or cases 2, 3 (client reboot): */
2202 gen_clid(new); 2223 gen_clid(new);
2203 /*
2204 * XXX: we should probably set this at creation time, and check
2205 * for consistent minorversion use throughout:
2206 */
2207 new->cl_minorversion = 0; 2224 new->cl_minorversion = 0;
2208 gen_callback(new, setclid, rqstp); 2225 gen_callback(new, setclid, rqstp);
2209 add_to_unconfirmed(new, strhashval); 2226 add_to_unconfirmed(new, strhashval);
@@ -2232,8 +2249,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
2232 return nfserr_stale_clientid; 2249 return nfserr_stale_clientid;
2233 nfs4_lock_state(); 2250 nfs4_lock_state();
2234 2251
2235 conf = find_confirmed_client(clid); 2252 conf = find_confirmed_client(clid, false);
2236 unconf = find_unconfirmed_client(clid); 2253 unconf = find_unconfirmed_client(clid, false);
2237 /* 2254 /*
2238 * We try hard to give out unique clientid's, so if we get an 2255 * We try hard to give out unique clientid's, so if we get an
2239 * attempt to confirm the same clientid with a different cred, 2256 * attempt to confirm the same clientid with a different cred,
@@ -2262,10 +2279,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
2262 unsigned int hash = clientstr_hashval(unconf->cl_recdir); 2279 unsigned int hash = clientstr_hashval(unconf->cl_recdir);
2263 2280
2264 conf = find_confirmed_client_by_str(unconf->cl_recdir, hash); 2281 conf = find_confirmed_client_by_str(unconf->cl_recdir, hash);
2265 if (conf) { 2282 if (conf)
2266 nfsd4_client_record_remove(conf);
2267 expire_client(conf); 2283 expire_client(conf);
2268 }
2269 move_to_confirmed(unconf); 2284 move_to_confirmed(unconf);
2270 nfsd4_probe_callback(unconf); 2285 nfsd4_probe_callback(unconf);
2271 } 2286 }
@@ -2447,16 +2462,20 @@ same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner,
2447} 2462}
2448 2463
2449static struct nfs4_openowner * 2464static struct nfs4_openowner *
2450find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open) 2465find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, bool sessions)
2451{ 2466{
2452 struct nfs4_stateowner *so; 2467 struct nfs4_stateowner *so;
2453 struct nfs4_openowner *oo; 2468 struct nfs4_openowner *oo;
2469 struct nfs4_client *clp;
2454 2470
2455 list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) { 2471 list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) {
2456 if (!so->so_is_open_owner) 2472 if (!so->so_is_open_owner)
2457 continue; 2473 continue;
2458 if (same_owner_str(so, &open->op_owner, &open->op_clientid)) { 2474 if (same_owner_str(so, &open->op_owner, &open->op_clientid)) {
2459 oo = openowner(so); 2475 oo = openowner(so);
2476 clp = oo->oo_owner.so_client;
2477 if ((bool)clp->cl_minorversion != sessions)
2478 return NULL;
2460 renew_client(oo->oo_owner.so_client); 2479 renew_client(oo->oo_owner.so_client);
2461 return oo; 2480 return oo;
2462 } 2481 }
@@ -2600,10 +2619,10 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate,
2600 return nfserr_jukebox; 2619 return nfserr_jukebox;
2601 2620
2602 strhashval = ownerstr_hashval(clientid->cl_id, &open->op_owner); 2621 strhashval = ownerstr_hashval(clientid->cl_id, &open->op_owner);
2603 oo = find_openstateowner_str(strhashval, open); 2622 oo = find_openstateowner_str(strhashval, open, cstate->minorversion);
2604 open->op_openowner = oo; 2623 open->op_openowner = oo;
2605 if (!oo) { 2624 if (!oo) {
2606 clp = find_confirmed_client(clientid); 2625 clp = find_confirmed_client(clientid, cstate->minorversion);
2607 if (clp == NULL) 2626 if (clp == NULL)
2608 return nfserr_expired; 2627 return nfserr_expired;
2609 goto new_owner; 2628 goto new_owner;
@@ -2705,11 +2724,6 @@ nfs4_check_open(struct nfs4_file *fp, struct nfsd4_open *open, struct nfs4_ol_st
2705 return nfs_ok; 2724 return nfs_ok;
2706} 2725}
2707 2726
2708static void nfs4_free_stateid(struct nfs4_ol_stateid *s)
2709{
2710 kmem_cache_free(stateid_slab, s);
2711}
2712
2713static inline int nfs4_access_to_access(u32 nfs4_access) 2727static inline int nfs4_access_to_access(u32 nfs4_access)
2714{ 2728{
2715 int flags = 0; 2729 int flags = 0;
@@ -3087,7 +3101,7 @@ void nfsd4_cleanup_open_state(struct nfsd4_open *open, __be32 status)
3087 if (open->op_file) 3101 if (open->op_file)
3088 nfsd4_free_file(open->op_file); 3102 nfsd4_free_file(open->op_file);
3089 if (open->op_stp) 3103 if (open->op_stp)
3090 nfs4_free_stateid(open->op_stp); 3104 free_generic_stateid(open->op_stp);
3091} 3105}
3092 3106
3093__be32 3107__be32
@@ -3104,7 +3118,7 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3104 status = nfserr_stale_clientid; 3118 status = nfserr_stale_clientid;
3105 if (STALE_CLIENTID(clid, nn)) 3119 if (STALE_CLIENTID(clid, nn))
3106 goto out; 3120 goto out;
3107 clp = find_confirmed_client(clid); 3121 clp = find_confirmed_client(clid, cstate->minorversion);
3108 status = nfserr_expired; 3122 status = nfserr_expired;
3109 if (clp == NULL) { 3123 if (clp == NULL) {
3110 /* We assume the client took too long to RENEW. */ 3124 /* We assume the client took too long to RENEW. */
@@ -3180,7 +3194,6 @@ nfs4_laundromat(void)
3180 clp = list_entry(pos, struct nfs4_client, cl_lru); 3194 clp = list_entry(pos, struct nfs4_client, cl_lru);
3181 dprintk("NFSD: purging unused client (clientid %08x)\n", 3195 dprintk("NFSD: purging unused client (clientid %08x)\n",
3182 clp->cl_clientid.cl_id); 3196 clp->cl_clientid.cl_id);
3183 nfsd4_client_record_remove(clp);
3184 expire_client(clp); 3197 expire_client(clp);
3185 } 3198 }
3186 spin_lock(&recall_lock); 3199 spin_lock(&recall_lock);
@@ -3372,7 +3385,7 @@ static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
3372 return nfs_ok; 3385 return nfs_ok;
3373} 3386}
3374 3387
3375static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s) 3388static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s, bool sessions)
3376{ 3389{
3377 struct nfs4_client *cl; 3390 struct nfs4_client *cl;
3378 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 3391 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
@@ -3381,7 +3394,7 @@ static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, s
3381 return nfserr_bad_stateid; 3394 return nfserr_bad_stateid;
3382 if (STALE_STATEID(stateid, nn)) 3395 if (STALE_STATEID(stateid, nn))
3383 return nfserr_stale_stateid; 3396 return nfserr_stale_stateid;
3384 cl = find_confirmed_client(&stateid->si_opaque.so_clid); 3397 cl = find_confirmed_client(&stateid->si_opaque.so_clid, sessions);
3385 if (!cl) 3398 if (!cl)
3386 return nfserr_expired; 3399 return nfserr_expired;
3387 *s = find_stateid_by_type(cl, stateid, typemask); 3400 *s = find_stateid_by_type(cl, stateid, typemask);
@@ -3414,7 +3427,7 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
3414 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) 3427 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
3415 return check_special_stateids(net, current_fh, stateid, flags); 3428 return check_special_stateids(net, current_fh, stateid, flags);
3416 3429
3417 status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s); 3430 status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s, cstate->minorversion);
3418 if (status) 3431 if (status)
3419 return status; 3432 return status;
3420 status = check_stateid_generation(stateid, &s->sc_stateid, nfsd4_has_session(cstate)); 3433 status = check_stateid_generation(stateid, &s->sc_stateid, nfsd4_has_session(cstate));
@@ -3564,7 +3577,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
3564 seqid, STATEID_VAL(stateid)); 3577 seqid, STATEID_VAL(stateid));
3565 3578
3566 *stpp = NULL; 3579 *stpp = NULL;
3567 status = nfsd4_lookup_stateid(stateid, typemask, &s); 3580 status = nfsd4_lookup_stateid(stateid, typemask, &s, cstate->minorversion);
3568 if (status) 3581 if (status)
3569 return status; 3582 return status;
3570 *stpp = openlockstateid(s); 3583 *stpp = openlockstateid(s);
@@ -3765,6 +3778,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3765 memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); 3778 memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
3766 3779
3767 nfsd4_close_open_stateid(stp); 3780 nfsd4_close_open_stateid(stp);
3781 release_last_closed_stateid(oo);
3768 oo->oo_last_closed_stid = stp; 3782 oo->oo_last_closed_stid = stp;
3769 3783
3770 if (list_empty(&oo->oo_owner.so_stateids)) { 3784 if (list_empty(&oo->oo_owner.so_stateids)) {
@@ -3801,7 +3815,7 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3801 inode = cstate->current_fh.fh_dentry->d_inode; 3815 inode = cstate->current_fh.fh_dentry->d_inode;
3802 3816
3803 nfs4_lock_state(); 3817 nfs4_lock_state();
3804 status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID, &s); 3818 status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID, &s, cstate->minorversion);
3805 if (status) 3819 if (status)
3806 goto out; 3820 goto out;
3807 dp = delegstateid(s); 3821 dp = delegstateid(s);
@@ -4045,8 +4059,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4045 struct nfs4_lockowner *lock_sop = NULL; 4059 struct nfs4_lockowner *lock_sop = NULL;
4046 struct nfs4_ol_stateid *lock_stp; 4060 struct nfs4_ol_stateid *lock_stp;
4047 struct file *filp = NULL; 4061 struct file *filp = NULL;
4048 struct file_lock file_lock; 4062 struct file_lock *file_lock = NULL;
4049 struct file_lock conflock; 4063 struct file_lock *conflock = NULL;
4050 __be32 status = 0; 4064 __be32 status = 0;
4051 bool new_state = false; 4065 bool new_state = false;
4052 int lkflg; 4066 int lkflg;
@@ -4116,21 +4130,28 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4116 if (!locks_in_grace(SVC_NET(rqstp)) && lock->lk_reclaim) 4130 if (!locks_in_grace(SVC_NET(rqstp)) && lock->lk_reclaim)
4117 goto out; 4131 goto out;
4118 4132
4119 locks_init_lock(&file_lock); 4133 file_lock = locks_alloc_lock();
4134 if (!file_lock) {
4135 dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
4136 status = nfserr_jukebox;
4137 goto out;
4138 }
4139
4140 locks_init_lock(file_lock);
4120 switch (lock->lk_type) { 4141 switch (lock->lk_type) {
4121 case NFS4_READ_LT: 4142 case NFS4_READ_LT:
4122 case NFS4_READW_LT: 4143 case NFS4_READW_LT:
4123 filp = find_readable_file(lock_stp->st_file); 4144 filp = find_readable_file(lock_stp->st_file);
4124 if (filp) 4145 if (filp)
4125 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ); 4146 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_READ);
4126 file_lock.fl_type = F_RDLCK; 4147 file_lock->fl_type = F_RDLCK;
4127 break; 4148 break;
4128 case NFS4_WRITE_LT: 4149 case NFS4_WRITE_LT:
4129 case NFS4_WRITEW_LT: 4150 case NFS4_WRITEW_LT:
4130 filp = find_writeable_file(lock_stp->st_file); 4151 filp = find_writeable_file(lock_stp->st_file);
4131 if (filp) 4152 if (filp)
4132 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE); 4153 get_lock_access(lock_stp, NFS4_SHARE_ACCESS_WRITE);
4133 file_lock.fl_type = F_WRLCK; 4154 file_lock->fl_type = F_WRLCK;
4134 break; 4155 break;
4135 default: 4156 default:
4136 status = nfserr_inval; 4157 status = nfserr_inval;
@@ -4140,22 +4161,23 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4140 status = nfserr_openmode; 4161 status = nfserr_openmode;
4141 goto out; 4162 goto out;
4142 } 4163 }
4143 file_lock.fl_owner = (fl_owner_t)lock_sop; 4164 file_lock->fl_owner = (fl_owner_t)lock_sop;
4144 file_lock.fl_pid = current->tgid; 4165 file_lock->fl_pid = current->tgid;
4145 file_lock.fl_file = filp; 4166 file_lock->fl_file = filp;
4146 file_lock.fl_flags = FL_POSIX; 4167 file_lock->fl_flags = FL_POSIX;
4147 file_lock.fl_lmops = &nfsd_posix_mng_ops; 4168 file_lock->fl_lmops = &nfsd_posix_mng_ops;
4148 4169 file_lock->fl_start = lock->lk_offset;
4149 file_lock.fl_start = lock->lk_offset; 4170 file_lock->fl_end = last_byte_offset(lock->lk_offset, lock->lk_length);
4150 file_lock.fl_end = last_byte_offset(lock->lk_offset, lock->lk_length); 4171 nfs4_transform_lock_offset(file_lock);
4151 nfs4_transform_lock_offset(&file_lock); 4172
4152 4173 conflock = locks_alloc_lock();
4153 /* 4174 if (!conflock) {
4154 * Try to lock the file in the VFS. 4175 dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
4155 * Note: locks.c uses the BKL to protect the inode's lock list. 4176 status = nfserr_jukebox;
4156 */ 4177 goto out;
4178 }
4157 4179
4158 err = vfs_lock_file(filp, F_SETLK, &file_lock, &conflock); 4180 err = vfs_lock_file(filp, F_SETLK, file_lock, conflock);
4159 switch (-err) { 4181 switch (-err) {
4160 case 0: /* success! */ 4182 case 0: /* success! */
4161 update_stateid(&lock_stp->st_stid.sc_stateid); 4183 update_stateid(&lock_stp->st_stid.sc_stateid);
@@ -4166,7 +4188,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4166 case (EAGAIN): /* conflock holds conflicting lock */ 4188 case (EAGAIN): /* conflock holds conflicting lock */
4167 status = nfserr_denied; 4189 status = nfserr_denied;
4168 dprintk("NFSD: nfsd4_lock: conflicting lock found!\n"); 4190 dprintk("NFSD: nfsd4_lock: conflicting lock found!\n");
4169 nfs4_set_lock_denied(&conflock, &lock->lk_denied); 4191 nfs4_set_lock_denied(conflock, &lock->lk_denied);
4170 break; 4192 break;
4171 case (EDEADLK): 4193 case (EDEADLK):
4172 status = nfserr_deadlock; 4194 status = nfserr_deadlock;
@@ -4181,6 +4203,10 @@ out:
4181 release_lockowner(lock_sop); 4203 release_lockowner(lock_sop);
4182 if (!cstate->replay_owner) 4204 if (!cstate->replay_owner)
4183 nfs4_unlock_state(); 4205 nfs4_unlock_state();
4206 if (file_lock)
4207 locks_free_lock(file_lock);
4208 if (conflock)
4209 locks_free_lock(conflock);
4184 return status; 4210 return status;
4185} 4211}
4186 4212
@@ -4209,7 +4235,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4209 struct nfsd4_lockt *lockt) 4235 struct nfsd4_lockt *lockt)
4210{ 4236{
4211 struct inode *inode; 4237 struct inode *inode;
4212 struct file_lock file_lock; 4238 struct file_lock *file_lock = NULL;
4213 struct nfs4_lockowner *lo; 4239 struct nfs4_lockowner *lo;
4214 __be32 status; 4240 __be32 status;
4215 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 4241 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
@@ -4230,15 +4256,21 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4230 goto out; 4256 goto out;
4231 4257
4232 inode = cstate->current_fh.fh_dentry->d_inode; 4258 inode = cstate->current_fh.fh_dentry->d_inode;
4233 locks_init_lock(&file_lock); 4259 file_lock = locks_alloc_lock();
4260 if (!file_lock) {
4261 dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
4262 status = nfserr_jukebox;
4263 goto out;
4264 }
4265 locks_init_lock(file_lock);
4234 switch (lockt->lt_type) { 4266 switch (lockt->lt_type) {
4235 case NFS4_READ_LT: 4267 case NFS4_READ_LT:
4236 case NFS4_READW_LT: 4268 case NFS4_READW_LT:
4237 file_lock.fl_type = F_RDLCK; 4269 file_lock->fl_type = F_RDLCK;
4238 break; 4270 break;
4239 case NFS4_WRITE_LT: 4271 case NFS4_WRITE_LT:
4240 case NFS4_WRITEW_LT: 4272 case NFS4_WRITEW_LT:
4241 file_lock.fl_type = F_WRLCK; 4273 file_lock->fl_type = F_WRLCK;
4242 break; 4274 break;
4243 default: 4275 default:
4244 dprintk("NFSD: nfs4_lockt: bad lock type!\n"); 4276 dprintk("NFSD: nfs4_lockt: bad lock type!\n");
@@ -4248,25 +4280,27 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4248 4280
4249 lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner); 4281 lo = find_lockowner_str(inode, &lockt->lt_clientid, &lockt->lt_owner);
4250 if (lo) 4282 if (lo)
4251 file_lock.fl_owner = (fl_owner_t)lo; 4283 file_lock->fl_owner = (fl_owner_t)lo;
4252 file_lock.fl_pid = current->tgid; 4284 file_lock->fl_pid = current->tgid;
4253 file_lock.fl_flags = FL_POSIX; 4285 file_lock->fl_flags = FL_POSIX;
4254 4286
4255 file_lock.fl_start = lockt->lt_offset; 4287 file_lock->fl_start = lockt->lt_offset;
4256 file_lock.fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length); 4288 file_lock->fl_end = last_byte_offset(lockt->lt_offset, lockt->lt_length);
4257 4289
4258 nfs4_transform_lock_offset(&file_lock); 4290 nfs4_transform_lock_offset(file_lock);
4259 4291
4260 status = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock); 4292 status = nfsd_test_lock(rqstp, &cstate->current_fh, file_lock);
4261 if (status) 4293 if (status)
4262 goto out; 4294 goto out;
4263 4295
4264 if (file_lock.fl_type != F_UNLCK) { 4296 if (file_lock->fl_type != F_UNLCK) {
4265 status = nfserr_denied; 4297 status = nfserr_denied;
4266 nfs4_set_lock_denied(&file_lock, &lockt->lt_denied); 4298 nfs4_set_lock_denied(file_lock, &lockt->lt_denied);
4267 } 4299 }
4268out: 4300out:
4269 nfs4_unlock_state(); 4301 nfs4_unlock_state();
4302 if (file_lock)
4303 locks_free_lock(file_lock);
4270 return status; 4304 return status;
4271} 4305}
4272 4306
@@ -4276,7 +4310,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4276{ 4310{
4277 struct nfs4_ol_stateid *stp; 4311 struct nfs4_ol_stateid *stp;
4278 struct file *filp = NULL; 4312 struct file *filp = NULL;
4279 struct file_lock file_lock; 4313 struct file_lock *file_lock = NULL;
4280 __be32 status; 4314 __be32 status;
4281 int err; 4315 int err;
4282 4316
@@ -4298,23 +4332,29 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4298 status = nfserr_lock_range; 4332 status = nfserr_lock_range;
4299 goto out; 4333 goto out;
4300 } 4334 }
4301 BUG_ON(!filp); 4335 file_lock = locks_alloc_lock();
4302 locks_init_lock(&file_lock); 4336 if (!file_lock) {
4303 file_lock.fl_type = F_UNLCK; 4337 dprintk("NFSD: %s: unable to allocate lock!\n", __func__);
4304 file_lock.fl_owner = (fl_owner_t)lockowner(stp->st_stateowner); 4338 status = nfserr_jukebox;
4305 file_lock.fl_pid = current->tgid; 4339 goto out;
4306 file_lock.fl_file = filp; 4340 }
4307 file_lock.fl_flags = FL_POSIX; 4341 locks_init_lock(file_lock);
4308 file_lock.fl_lmops = &nfsd_posix_mng_ops; 4342 file_lock->fl_type = F_UNLCK;
4309 file_lock.fl_start = locku->lu_offset; 4343 file_lock->fl_owner = (fl_owner_t)lockowner(stp->st_stateowner);
4310 4344 file_lock->fl_pid = current->tgid;
4311 file_lock.fl_end = last_byte_offset(locku->lu_offset, locku->lu_length); 4345 file_lock->fl_file = filp;
4312 nfs4_transform_lock_offset(&file_lock); 4346 file_lock->fl_flags = FL_POSIX;
4347 file_lock->fl_lmops = &nfsd_posix_mng_ops;
4348 file_lock->fl_start = locku->lu_offset;
4349
4350 file_lock->fl_end = last_byte_offset(locku->lu_offset,
4351 locku->lu_length);
4352 nfs4_transform_lock_offset(file_lock);
4313 4353
4314 /* 4354 /*
4315 * Try to unlock the file in the VFS. 4355 * Try to unlock the file in the VFS.
4316 */ 4356 */
4317 err = vfs_lock_file(filp, F_SETLK, &file_lock, NULL); 4357 err = vfs_lock_file(filp, F_SETLK, file_lock, NULL);
4318 if (err) { 4358 if (err) {
4319 dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n"); 4359 dprintk("NFSD: nfs4_locku: vfs_lock_file failed!\n");
4320 goto out_nfserr; 4360 goto out_nfserr;
@@ -4328,6 +4368,8 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4328out: 4368out:
4329 if (!cstate->replay_owner) 4369 if (!cstate->replay_owner)
4330 nfs4_unlock_state(); 4370 nfs4_unlock_state();
4371 if (file_lock)
4372 locks_free_lock(file_lock);
4331 return status; 4373 return status;
4332 4374
4333out_nfserr: 4375out_nfserr:
@@ -4501,12 +4543,12 @@ nfsd4_find_reclaim_client(struct nfs4_client *clp)
4501* Called from OPEN. Look for clientid in reclaim list. 4543* Called from OPEN. Look for clientid in reclaim list.
4502*/ 4544*/
4503__be32 4545__be32
4504nfs4_check_open_reclaim(clientid_t *clid) 4546nfs4_check_open_reclaim(clientid_t *clid, bool sessions)
4505{ 4547{
4506 struct nfs4_client *clp; 4548 struct nfs4_client *clp;
4507 4549
4508 /* find clientid in conf_id_hashtbl */ 4550 /* find clientid in conf_id_hashtbl */
4509 clp = find_confirmed_client(clid); 4551 clp = find_confirmed_client(clid, sessions);
4510 if (clp == NULL) 4552 if (clp == NULL)
4511 return nfserr_reclaim_bad; 4553 return nfserr_reclaim_bad;
4512 4554
@@ -4522,7 +4564,6 @@ void nfsd_forget_clients(u64 num)
4522 4564
4523 nfs4_lock_state(); 4565 nfs4_lock_state();
4524 list_for_each_entry_safe(clp, next, &client_lru, cl_lru) { 4566 list_for_each_entry_safe(clp, next, &client_lru, cl_lru) {
4525 nfsd4_client_record_remove(clp);
4526 expire_client(clp); 4567 expire_client(clp);
4527 if (++count == num) 4568 if (++count == num)
4528 break; 4569 break;
@@ -4582,7 +4623,7 @@ void nfsd_forget_openowners(u64 num)
4582 printk(KERN_INFO "NFSD: Forgot %d open owners", count); 4623 printk(KERN_INFO "NFSD: Forgot %d open owners", count);
4583} 4624}
4584 4625
4585int nfsd_process_n_delegations(u64 num, struct list_head *list) 4626static int nfsd_process_n_delegations(u64 num, struct list_head *list)
4586{ 4627{
4587 int i, count = 0; 4628 int i, count = 0;
4588 struct nfs4_file *fp, *fnext; 4629 struct nfs4_file *fp, *fnext;
@@ -4747,11 +4788,11 @@ __nfs4_state_shutdown(void)
4747 for (i = 0; i < CLIENT_HASH_SIZE; i++) { 4788 for (i = 0; i < CLIENT_HASH_SIZE; i++) {
4748 while (!list_empty(&conf_id_hashtbl[i])) { 4789 while (!list_empty(&conf_id_hashtbl[i])) {
4749 clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash); 4790 clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
4750 expire_client(clp); 4791 destroy_client(clp);
4751 } 4792 }
4752 while (!list_empty(&unconf_str_hashtbl[i])) { 4793 while (!list_empty(&unconf_str_hashtbl[i])) {
4753 clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash); 4794 clp = list_entry(unconf_str_hashtbl[i].next, struct nfs4_client, cl_strhash);
4754 expire_client(clp); 4795 destroy_client(clp);
4755 } 4796 }
4756 } 4797 }
4757 INIT_LIST_HEAD(&reaplist); 4798 INIT_LIST_HEAD(&reaplist);
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 6322df36031f..fd548d155088 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2659,7 +2659,7 @@ static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp,
2659 RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 8); 2659 RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 8);
2660 WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN); 2660 WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN);
2661 WRITE32(bcts->dir); 2661 WRITE32(bcts->dir);
2662 /* XXX: ? */ 2662 /* Sorry, we do not yet support RDMA over 4.1: */
2663 WRITE32(0); 2663 WRITE32(0);
2664 ADJUST_ARGS(); 2664 ADJUST_ARGS();
2665 } 2665 }
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index fa49cff5ee65..dab350dfc376 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -406,7 +406,7 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
406 return rv; 406 return rv;
407 if (newthreads < 0) 407 if (newthreads < 0)
408 return -EINVAL; 408 return -EINVAL;
409 rv = nfsd_svc(NFS_PORT, newthreads); 409 rv = nfsd_svc(newthreads);
410 if (rv < 0) 410 if (rv < 0)
411 return rv; 411 return rv;
412 } else 412 } else
@@ -683,25 +683,6 @@ static ssize_t __write_ports_addfd(char *buf)
683} 683}
684 684
685/* 685/*
686 * A '-' followed by the 'name' of a socket means we close the socket.
687 */
688static ssize_t __write_ports_delfd(char *buf)
689{
690 char *toclose;
691 int len = 0;
692
693 toclose = kstrdup(buf + 1, GFP_KERNEL);
694 if (toclose == NULL)
695 return -ENOMEM;
696
697 if (nfsd_serv != NULL)
698 len = svc_sock_names(nfsd_serv, buf,
699 SIMPLE_TRANSACTION_LIMIT, toclose);
700 kfree(toclose);
701 return len;
702}
703
704/*
705 * A transport listener is added by writing it's transport name and 686 * A transport listener is added by writing it's transport name and
706 * a port number. 687 * a port number.
707 */ 688 */
@@ -712,7 +693,7 @@ static ssize_t __write_ports_addxprt(char *buf)
712 int port, err; 693 int port, err;
713 struct net *net = &init_net; 694 struct net *net = &init_net;
714 695
715 if (sscanf(buf, "%15s %4u", transport, &port) != 2) 696 if (sscanf(buf, "%15s %5u", transport, &port) != 2)
716 return -EINVAL; 697 return -EINVAL;
717 698
718 if (port < 1 || port > USHRT_MAX) 699 if (port < 1 || port > USHRT_MAX)
@@ -746,31 +727,6 @@ out_err:
746 return err; 727 return err;
747} 728}
748 729
749/*
750 * A transport listener is removed by writing a "-", it's transport
751 * name, and it's port number.
752 */
753static ssize_t __write_ports_delxprt(char *buf)
754{
755 struct svc_xprt *xprt;
756 char transport[16];
757 int port;
758
759 if (sscanf(&buf[1], "%15s %4u", transport, &port) != 2)
760 return -EINVAL;
761
762 if (port < 1 || port > USHRT_MAX || nfsd_serv == NULL)
763 return -EINVAL;
764
765 xprt = svc_find_xprt(nfsd_serv, transport, &init_net, AF_UNSPEC, port);
766 if (xprt == NULL)
767 return -ENOTCONN;
768
769 svc_close_xprt(xprt);
770 svc_xprt_put(xprt);
771 return 0;
772}
773
774static ssize_t __write_ports(struct file *file, char *buf, size_t size) 730static ssize_t __write_ports(struct file *file, char *buf, size_t size)
775{ 731{
776 if (size == 0) 732 if (size == 0)
@@ -779,15 +735,9 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
779 if (isdigit(buf[0])) 735 if (isdigit(buf[0]))
780 return __write_ports_addfd(buf); 736 return __write_ports_addfd(buf);
781 737
782 if (buf[0] == '-' && isdigit(buf[1]))
783 return __write_ports_delfd(buf);
784
785 if (isalpha(buf[0])) 738 if (isalpha(buf[0]))
786 return __write_ports_addxprt(buf); 739 return __write_ports_addxprt(buf);
787 740
788 if (buf[0] == '-' && isalpha(buf[1]))
789 return __write_ports_delxprt(buf);
790
791 return -EINVAL; 741 return -EINVAL;
792} 742}
793 743
@@ -825,21 +775,6 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
825 * OR 775 * OR
826 * 776 *
827 * Input: 777 * Input:
828 * buf: C string containing a "-" followed
829 * by an integer value representing a
830 * previously passed in socket file
831 * descriptor
832 * size: non-zero length of C string in @buf
833 * Output:
834 * On success: NFS service no longer listens on that socket;
835 * passed-in buffer filled with a '\n'-terminated C
836 * string containing a unique name of the listener;
837 * return code is the size in bytes of the string
838 * On error: return code is a negative errno value
839 *
840 * OR
841 *
842 * Input:
843 * buf: C string containing a transport 778 * buf: C string containing a transport
844 * name and an unsigned integer value 779 * name and an unsigned integer value
845 * representing the port to listen on, 780 * representing the port to listen on,
@@ -848,19 +783,6 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
848 * Output: 783 * Output:
849 * On success: returns zero; NFS service is started 784 * On success: returns zero; NFS service is started
850 * On error: return code is a negative errno value 785 * On error: return code is a negative errno value
851 *
852 * OR
853 *
854 * Input:
855 * buf: C string containing a "-" followed
856 * by a transport name and an unsigned
857 * integer value representing the port
858 * to listen on, separated by whitespace
859 * size: non-zero length of C string in @buf
860 * Output:
861 * On success: returns zero; NFS service no longer listens
862 * on that transport
863 * On error: return code is a negative errno value
864 */ 786 */
865static ssize_t write_ports(struct file *file, char *buf, size_t size) 787static ssize_t write_ports(struct file *file, char *buf, size_t size)
866{ 788{
@@ -1008,8 +930,6 @@ static ssize_t write_gracetime(struct file *file, char *buf, size_t size)
1008 return nfsd4_write_time(file, buf, size, &nfsd4_grace); 930 return nfsd4_write_time(file, buf, size, &nfsd4_grace);
1009} 931}
1010 932
1011extern char *nfs4_recoverydir(void);
1012
1013static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size) 933static ssize_t __write_recoverydir(struct file *file, char *buf, size_t size)
1014{ 934{
1015 char *mesg = buf; 935 char *mesg = buf;
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
index 2244222368ab..80d5ce40aadb 100644
--- a/fs/nfsd/nfsd.h
+++ b/fs/nfsd/nfsd.h
@@ -65,7 +65,7 @@ extern const struct seq_operations nfs_exports_op;
65/* 65/*
66 * Function prototypes. 66 * Function prototypes.
67 */ 67 */
68int nfsd_svc(unsigned short port, int nrservs); 68int nfsd_svc(int nrservs);
69int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp); 69int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp);
70 70
71int nfsd_nrthreads(void); 71int nfsd_nrthreads(void);
@@ -124,6 +124,7 @@ int nfs4_state_start(void);
124void nfs4_state_shutdown(void); 124void nfs4_state_shutdown(void);
125void nfs4_reset_lease(time_t leasetime); 125void nfs4_reset_lease(time_t leasetime);
126int nfs4_reset_recoverydir(char *recdir); 126int nfs4_reset_recoverydir(char *recdir);
127char * nfs4_recoverydir(void);
127#else 128#else
128static inline void nfs4_state_init(void) { } 129static inline void nfs4_state_init(void) { }
129static inline int nfsd4_init_slabs(void) { return 0; } 130static inline int nfsd4_init_slabs(void) { return 0; }
@@ -132,6 +133,7 @@ static inline int nfs4_state_start(void) { return 0; }
132static inline void nfs4_state_shutdown(void) { } 133static inline void nfs4_state_shutdown(void) { }
133static inline void nfs4_reset_lease(time_t leasetime) { } 134static inline void nfs4_reset_lease(time_t leasetime) { }
134static inline int nfs4_reset_recoverydir(char *recdir) { return 0; } 135static inline int nfs4_reset_recoverydir(char *recdir) { return 0; }
136static inline char * nfs4_recoverydir(void) {return NULL; }
135#endif 137#endif
136 138
137/* 139/*
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index 240473cb708f..2013aa001dab 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -183,18 +183,18 @@ int nfsd_nrthreads(void)
183 return rv; 183 return rv;
184} 184}
185 185
186static int nfsd_init_socks(int port) 186static int nfsd_init_socks(void)
187{ 187{
188 int error; 188 int error;
189 if (!list_empty(&nfsd_serv->sv_permsocks)) 189 if (!list_empty(&nfsd_serv->sv_permsocks))
190 return 0; 190 return 0;
191 191
192 error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, port, 192 error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, NFS_PORT,
193 SVC_SOCK_DEFAULTS); 193 SVC_SOCK_DEFAULTS);
194 if (error < 0) 194 if (error < 0)
195 return error; 195 return error;
196 196
197 error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, port, 197 error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, NFS_PORT,
198 SVC_SOCK_DEFAULTS); 198 SVC_SOCK_DEFAULTS);
199 if (error < 0) 199 if (error < 0)
200 return error; 200 return error;
@@ -204,7 +204,7 @@ static int nfsd_init_socks(int port)
204 204
205static bool nfsd_up = false; 205static bool nfsd_up = false;
206 206
207static int nfsd_startup(unsigned short port, int nrservs) 207static int nfsd_startup(int nrservs)
208{ 208{
209 int ret; 209 int ret;
210 210
@@ -218,7 +218,7 @@ static int nfsd_startup(unsigned short port, int nrservs)
218 ret = nfsd_racache_init(2*nrservs); 218 ret = nfsd_racache_init(2*nrservs);
219 if (ret) 219 if (ret)
220 return ret; 220 return ret;
221 ret = nfsd_init_socks(port); 221 ret = nfsd_init_socks();
222 if (ret) 222 if (ret)
223 goto out_racache; 223 goto out_racache;
224 ret = lockd_up(&init_net); 224 ret = lockd_up(&init_net);
@@ -436,7 +436,7 @@ int nfsd_set_nrthreads(int n, int *nthreads)
436 * this is the first time nrservs is nonzero. 436 * this is the first time nrservs is nonzero.
437 */ 437 */
438int 438int
439nfsd_svc(unsigned short port, int nrservs) 439nfsd_svc(int nrservs)
440{ 440{
441 int error; 441 int error;
442 bool nfsd_up_before; 442 bool nfsd_up_before;
@@ -458,7 +458,7 @@ nfsd_svc(unsigned short port, int nrservs)
458 458
459 nfsd_up_before = nfsd_up; 459 nfsd_up_before = nfsd_up;
460 460
461 error = nfsd_startup(port, nrservs); 461 error = nfsd_startup(nrservs);
462 if (error) 462 if (error)
463 goto out_destroy; 463 goto out_destroy;
464 error = svc_set_num_threads(nfsd_serv, NULL, nrservs); 464 error = svc_set_num_threads(nfsd_serv, NULL, nrservs);
@@ -487,7 +487,7 @@ static int
487nfsd(void *vrqstp) 487nfsd(void *vrqstp)
488{ 488{
489 struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp; 489 struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp;
490 int err, preverr = 0; 490 int err;
491 491
492 /* Lock module and set up kernel thread */ 492 /* Lock module and set up kernel thread */
493 mutex_lock(&nfsd_mutex); 493 mutex_lock(&nfsd_mutex);
@@ -534,16 +534,6 @@ nfsd(void *vrqstp)
534 ; 534 ;
535 if (err == -EINTR) 535 if (err == -EINTR)
536 break; 536 break;
537 else if (err < 0) {
538 if (err != preverr) {
539 printk(KERN_WARNING "%s: unexpected error "
540 "from svc_recv (%d)\n", __func__, -err);
541 preverr = err;
542 }
543 schedule_timeout_uninterruptible(HZ);
544 continue;
545 }
546
547 validate_process_creds(); 537 validate_process_creds();
548 svc_process(rqstp); 538 svc_process(rqstp);
549 validate_process_creds(); 539 validate_process_creds();
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 22bd0a66c356..e036894bce57 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -373,11 +373,7 @@ static inline struct nfs4_lockowner * lockowner(struct nfs4_stateowner *so)
373 return container_of(so, struct nfs4_lockowner, lo_owner); 373 return container_of(so, struct nfs4_lockowner, lo_owner);
374} 374}
375 375
376/* 376/* nfs4_file: a file opened by some number of (open) nfs4_stateowners. */
377* nfs4_file: a file opened by some number of (open) nfs4_stateowners.
378* o fi_perfile list is used to search for conflicting
379* share_acces, share_deny on the file.
380*/
381struct nfs4_file { 377struct nfs4_file {
382 atomic_t fi_ref; 378 atomic_t fi_ref;
383 struct list_head fi_hash; /* hash by "struct inode *" */ 379 struct list_head fi_hash; /* hash by "struct inode *" */
@@ -459,7 +455,7 @@ extern void nfs4_unlock_state(void);
459extern int nfs4_in_grace(void); 455extern int nfs4_in_grace(void);
460extern void nfs4_release_reclaim(void); 456extern void nfs4_release_reclaim(void);
461extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp); 457extern struct nfs4_client_reclaim *nfsd4_find_reclaim_client(struct nfs4_client *crp);
462extern __be32 nfs4_check_open_reclaim(clientid_t *clid); 458extern __be32 nfs4_check_open_reclaim(clientid_t *clid, bool sessions);
463extern void nfs4_free_openowner(struct nfs4_openowner *); 459extern void nfs4_free_openowner(struct nfs4_openowner *);
464extern void nfs4_free_lockowner(struct nfs4_lockowner *); 460extern void nfs4_free_lockowner(struct nfs4_lockowner *);
465extern int set_callback_cred(void); 461extern int set_callback_cred(void);
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 3f67b8e12251..c120b48ec305 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1581,7 +1581,7 @@ nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp)
1581 */ 1581 */
1582 1582
1583 oldfs = get_fs(); set_fs(KERNEL_DS); 1583 oldfs = get_fs(); set_fs(KERNEL_DS);
1584 host_err = inode->i_op->readlink(path.dentry, buf, *lenp); 1584 host_err = inode->i_op->readlink(path.dentry, (char __user *)buf, *lenp);
1585 set_fs(oldfs); 1585 set_fs(oldfs);
1586 1586
1587 if (host_err < 0) 1587 if (host_err < 0)