aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-11 13:17:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-11 13:17:13 -0400
commit0ff08ba5d066619f9973bfcdb5a21320d54219d0 (patch)
tree526e4a5799eb3023e9d5d81e81c0964b1d928a3e /net/sunrpc
parentc72bb316916b1a6cf35e1d5238566ef27b0b7f80 (diff)
parentd109148111cdfcdae94f797dc142468bd0ff7557 (diff)
Merge branch 'for-3.11' of git://linux-nfs.org/~bfields/linux
Pull nfsd changes from Bruce Fields: "Changes this time include: - 4.1 enabled on the server by default: the last 4.1-specific issues I know of are fixed, so we're not going to find the rest of the bugs without more exposure. - Experimental support for NFSv4.2 MAC Labeling (to allow running selinux over NFS), from Dave Quigley. - Fixes for some delicate cache/upcall races that could cause rare server hangs; thanks to Neil Brown and Bodo Stroesser for extreme debugging persistence. - Fixes for some bugs found at the recent NFS bakeathon, mostly v4 and v4.1-specific, but also a generic bug handling fragmented rpc calls" * 'for-3.11' of git://linux-nfs.org/~bfields/linux: (31 commits) nfsd4: support minorversion 1 by default nfsd4: allow destroy_session over destroyed session svcrpc: fix failures to handle -1 uid's sunrpc: Don't schedule an upcall on a replaced cache entry. net/sunrpc: xpt_auth_cache should be ignored when expired. sunrpc/cache: ensure items removed from cache do not have pending upcalls. sunrpc/cache: use cache_fresh_unlocked consistently and correctly. sunrpc/cache: remove races with queuing an upcall. nfsd4: return delegation immediately if lease fails nfsd4: do not throw away 4.1 lock state on last unlock nfsd4: delegation-based open reclaims should bypass permissions svcrpc: don't error out on small tcp fragment svcrpc: fix handling of too-short rpc's nfsd4: minor read_buf cleanup nfsd4: fix decoding of compounds across page boundaries nfsd4: clean up nfs4_open_delegation NFSD: Don't give out read delegations on creates nfsd4: allow client to send no cb_sec flavors nfsd4: fail attempts to request gss on the backchannel nfsd4: implement minimal SP4_MACH_CRED ...
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/auth_gss/gss_mech_switch.c5
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c10
-rw-r--r--net/sunrpc/cache.c83
-rw-r--r--net/sunrpc/svcauth_unix.c6
-rw-r--r--net/sunrpc/svcsock.c9
-rw-r--r--net/sunrpc/xprtsock.c1
6 files changed, 63 insertions, 51 deletions
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
index defa9d33925c..27ce26240932 100644
--- a/net/sunrpc/auth_gss/gss_mech_switch.c
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c
@@ -139,11 +139,12 @@ void gss_mech_unregister(struct gss_api_mech *gm)
139} 139}
140EXPORT_SYMBOL_GPL(gss_mech_unregister); 140EXPORT_SYMBOL_GPL(gss_mech_unregister);
141 141
142static struct gss_api_mech *gss_mech_get(struct gss_api_mech *gm) 142struct gss_api_mech *gss_mech_get(struct gss_api_mech *gm)
143{ 143{
144 __module_get(gm->gm_owner); 144 __module_get(gm->gm_owner);
145 return gm; 145 return gm;
146} 146}
147EXPORT_SYMBOL(gss_mech_get);
147 148
148static struct gss_api_mech * 149static struct gss_api_mech *
149_gss_mech_get_by_name(const char *name) 150_gss_mech_get_by_name(const char *name)
@@ -360,6 +361,7 @@ gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor)
360 } 361 }
361 return 0; 362 return 0;
362} 363}
364EXPORT_SYMBOL(gss_pseudoflavor_to_service);
363 365
364char * 366char *
365gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service) 367gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service)
@@ -379,6 +381,7 @@ gss_mech_put(struct gss_api_mech * gm)
379 if (gm) 381 if (gm)
380 module_put(gm->gm_owner); 382 module_put(gm->gm_owner);
381} 383}
384EXPORT_SYMBOL(gss_mech_put);
382 385
383/* The mech could probably be determined from the token instead, but it's just 386/* The mech could probably be determined from the token instead, but it's just
384 * as easy for now to pass it in. */ 387 * as easy for now to pass it in. */
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index b05ace4c5f12..d0347d148b34 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -377,8 +377,7 @@ rsc_init(struct cache_head *cnew, struct cache_head *ctmp)
377 new->handle.data = tmp->handle.data; 377 new->handle.data = tmp->handle.data;
378 tmp->handle.data = NULL; 378 tmp->handle.data = NULL;
379 new->mechctx = NULL; 379 new->mechctx = NULL;
380 new->cred.cr_group_info = NULL; 380 init_svc_cred(&new->cred);
381 new->cred.cr_principal = NULL;
382} 381}
383 382
384static void 383static void
@@ -392,9 +391,7 @@ update_rsc(struct cache_head *cnew, struct cache_head *ctmp)
392 memset(&new->seqdata, 0, sizeof(new->seqdata)); 391 memset(&new->seqdata, 0, sizeof(new->seqdata));
393 spin_lock_init(&new->seqdata.sd_lock); 392 spin_lock_init(&new->seqdata.sd_lock);
394 new->cred = tmp->cred; 393 new->cred = tmp->cred;
395 tmp->cred.cr_group_info = NULL; 394 init_svc_cred(&tmp->cred);
396 new->cred.cr_principal = tmp->cred.cr_principal;
397 tmp->cred.cr_principal = NULL;
398} 395}
399 396
400static struct cache_head * 397static struct cache_head *
@@ -487,7 +484,7 @@ static int rsc_parse(struct cache_detail *cd,
487 len = qword_get(&mesg, buf, mlen); 484 len = qword_get(&mesg, buf, mlen);
488 if (len < 0) 485 if (len < 0)
489 goto out; 486 goto out;
490 gm = gss_mech_get_by_name(buf); 487 gm = rsci.cred.cr_gss_mech = gss_mech_get_by_name(buf);
491 status = -EOPNOTSUPP; 488 status = -EOPNOTSUPP;
492 if (!gm) 489 if (!gm)
493 goto out; 490 goto out;
@@ -517,7 +514,6 @@ static int rsc_parse(struct cache_detail *cd,
517 rscp = rsc_update(cd, &rsci, rscp); 514 rscp = rsc_update(cd, &rsci, rscp);
518 status = 0; 515 status = 0;
519out: 516out:
520 gss_mech_put(gm);
521 rsc_free(&rsci); 517 rsc_free(&rsci);
522 if (rscp) 518 if (rscp)
523 cache_put(&rscp->h, cd); 519 cache_put(&rscp->h, cd);
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 80fe5c86efd1..49eb37010aa3 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -50,12 +50,6 @@ static void cache_init(struct cache_head *h)
50 h->last_refresh = now; 50 h->last_refresh = now;
51} 51}
52 52
53static inline int cache_is_expired(struct cache_detail *detail, struct cache_head *h)
54{
55 return (h->expiry_time < seconds_since_boot()) ||
56 (detail->flush_time > h->last_refresh);
57}
58
59struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail, 53struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
60 struct cache_head *key, int hash) 54 struct cache_head *key, int hash)
61{ 55{
@@ -201,7 +195,7 @@ static int cache_make_upcall(struct cache_detail *cd, struct cache_head *h)
201 return sunrpc_cache_pipe_upcall(cd, h); 195 return sunrpc_cache_pipe_upcall(cd, h);
202} 196}
203 197
204static inline int cache_is_valid(struct cache_detail *detail, struct cache_head *h) 198static inline int cache_is_valid(struct cache_head *h)
205{ 199{
206 if (!test_bit(CACHE_VALID, &h->flags)) 200 if (!test_bit(CACHE_VALID, &h->flags))
207 return -EAGAIN; 201 return -EAGAIN;
@@ -227,16 +221,15 @@ static int try_to_negate_entry(struct cache_detail *detail, struct cache_head *h
227 int rv; 221 int rv;
228 222
229 write_lock(&detail->hash_lock); 223 write_lock(&detail->hash_lock);
230 rv = cache_is_valid(detail, h); 224 rv = cache_is_valid(h);
231 if (rv != -EAGAIN) { 225 if (rv == -EAGAIN) {
232 write_unlock(&detail->hash_lock); 226 set_bit(CACHE_NEGATIVE, &h->flags);
233 return rv; 227 cache_fresh_locked(h, seconds_since_boot()+CACHE_NEW_EXPIRY);
228 rv = -ENOENT;
234 } 229 }
235 set_bit(CACHE_NEGATIVE, &h->flags);
236 cache_fresh_locked(h, seconds_since_boot()+CACHE_NEW_EXPIRY);
237 write_unlock(&detail->hash_lock); 230 write_unlock(&detail->hash_lock);
238 cache_fresh_unlocked(h, detail); 231 cache_fresh_unlocked(h, detail);
239 return -ENOENT; 232 return rv;
240} 233}
241 234
242/* 235/*
@@ -260,7 +253,7 @@ int cache_check(struct cache_detail *detail,
260 long refresh_age, age; 253 long refresh_age, age;
261 254
262 /* First decide return status as best we can */ 255 /* First decide return status as best we can */
263 rv = cache_is_valid(detail, h); 256 rv = cache_is_valid(h);
264 257
265 /* now see if we want to start an upcall */ 258 /* now see if we want to start an upcall */
266 refresh_age = (h->expiry_time - h->last_refresh); 259 refresh_age = (h->expiry_time - h->last_refresh);
@@ -269,19 +262,17 @@ int cache_check(struct cache_detail *detail,
269 if (rqstp == NULL) { 262 if (rqstp == NULL) {
270 if (rv == -EAGAIN) 263 if (rv == -EAGAIN)
271 rv = -ENOENT; 264 rv = -ENOENT;
272 } else if (rv == -EAGAIN || age > refresh_age/2) { 265 } else if (rv == -EAGAIN ||
266 (h->expiry_time != 0 && age > refresh_age/2)) {
273 dprintk("RPC: Want update, refage=%ld, age=%ld\n", 267 dprintk("RPC: Want update, refage=%ld, age=%ld\n",
274 refresh_age, age); 268 refresh_age, age);
275 if (!test_and_set_bit(CACHE_PENDING, &h->flags)) { 269 if (!test_and_set_bit(CACHE_PENDING, &h->flags)) {
276 switch (cache_make_upcall(detail, h)) { 270 switch (cache_make_upcall(detail, h)) {
277 case -EINVAL: 271 case -EINVAL:
278 clear_bit(CACHE_PENDING, &h->flags);
279 cache_revisit_request(h);
280 rv = try_to_negate_entry(detail, h); 272 rv = try_to_negate_entry(detail, h);
281 break; 273 break;
282 case -EAGAIN: 274 case -EAGAIN:
283 clear_bit(CACHE_PENDING, &h->flags); 275 cache_fresh_unlocked(h, detail);
284 cache_revisit_request(h);
285 break; 276 break;
286 } 277 }
287 } 278 }
@@ -293,7 +284,7 @@ int cache_check(struct cache_detail *detail,
293 * Request was not deferred; handle it as best 284 * Request was not deferred; handle it as best
294 * we can ourselves: 285 * we can ourselves:
295 */ 286 */
296 rv = cache_is_valid(detail, h); 287 rv = cache_is_valid(h);
297 if (rv == -EAGAIN) 288 if (rv == -EAGAIN)
298 rv = -ETIMEDOUT; 289 rv = -ETIMEDOUT;
299 } 290 }
@@ -310,7 +301,7 @@ EXPORT_SYMBOL_GPL(cache_check);
310 * a current pointer into that list and into the table 301 * a current pointer into that list and into the table
311 * for that entry. 302 * for that entry.
312 * 303 *
313 * Each time clean_cache is called it finds the next non-empty entry 304 * Each time cache_clean is called it finds the next non-empty entry
314 * in the current table and walks the list in that entry 305 * in the current table and walks the list in that entry
315 * looking for entries that can be removed. 306 * looking for entries that can be removed.
316 * 307 *
@@ -457,9 +448,8 @@ static int cache_clean(void)
457 current_index ++; 448 current_index ++;
458 spin_unlock(&cache_list_lock); 449 spin_unlock(&cache_list_lock);
459 if (ch) { 450 if (ch) {
460 if (test_and_clear_bit(CACHE_PENDING, &ch->flags)) 451 set_bit(CACHE_CLEANED, &ch->flags);
461 cache_dequeue(current_detail, ch); 452 cache_fresh_unlocked(ch, d);
462 cache_revisit_request(ch);
463 cache_put(ch, d); 453 cache_put(ch, d);
464 } 454 }
465 } else 455 } else
@@ -1036,23 +1026,32 @@ static int cache_release(struct inode *inode, struct file *filp,
1036 1026
1037static void cache_dequeue(struct cache_detail *detail, struct cache_head *ch) 1027static void cache_dequeue(struct cache_detail *detail, struct cache_head *ch)
1038{ 1028{
1039 struct cache_queue *cq; 1029 struct cache_queue *cq, *tmp;
1030 struct cache_request *cr;
1031 struct list_head dequeued;
1032
1033 INIT_LIST_HEAD(&dequeued);
1040 spin_lock(&queue_lock); 1034 spin_lock(&queue_lock);
1041 list_for_each_entry(cq, &detail->queue, list) 1035 list_for_each_entry_safe(cq, tmp, &detail->queue, list)
1042 if (!cq->reader) { 1036 if (!cq->reader) {
1043 struct cache_request *cr = container_of(cq, struct cache_request, q); 1037 cr = container_of(cq, struct cache_request, q);
1044 if (cr->item != ch) 1038 if (cr->item != ch)
1045 continue; 1039 continue;
1040 if (test_bit(CACHE_PENDING, &ch->flags))
1041 /* Lost a race and it is pending again */
1042 break;
1046 if (cr->readers != 0) 1043 if (cr->readers != 0)
1047 continue; 1044 continue;
1048 list_del(&cr->q.list); 1045 list_move(&cr->q.list, &dequeued);
1049 spin_unlock(&queue_lock);
1050 cache_put(cr->item, detail);
1051 kfree(cr->buf);
1052 kfree(cr);
1053 return;
1054 } 1046 }
1055 spin_unlock(&queue_lock); 1047 spin_unlock(&queue_lock);
1048 while (!list_empty(&dequeued)) {
1049 cr = list_entry(dequeued.next, struct cache_request, q.list);
1050 list_del(&cr->q.list);
1051 cache_put(cr->item, detail);
1052 kfree(cr->buf);
1053 kfree(cr);
1054 }
1056} 1055}
1057 1056
1058/* 1057/*
@@ -1166,6 +1165,7 @@ int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h)
1166 1165
1167 char *buf; 1166 char *buf;
1168 struct cache_request *crq; 1167 struct cache_request *crq;
1168 int ret = 0;
1169 1169
1170 if (!detail->cache_request) 1170 if (!detail->cache_request)
1171 return -EINVAL; 1171 return -EINVAL;
@@ -1174,6 +1174,9 @@ int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h)
1174 warn_no_listener(detail); 1174 warn_no_listener(detail);
1175 return -EINVAL; 1175 return -EINVAL;
1176 } 1176 }
1177 if (test_bit(CACHE_CLEANED, &h->flags))
1178 /* Too late to make an upcall */
1179 return -EAGAIN;
1177 1180
1178 buf = kmalloc(PAGE_SIZE, GFP_KERNEL); 1181 buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
1179 if (!buf) 1182 if (!buf)
@@ -1191,10 +1194,18 @@ int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h)
1191 crq->len = 0; 1194 crq->len = 0;
1192 crq->readers = 0; 1195 crq->readers = 0;
1193 spin_lock(&queue_lock); 1196 spin_lock(&queue_lock);
1194 list_add_tail(&crq->q.list, &detail->queue); 1197 if (test_bit(CACHE_PENDING, &h->flags))
1198 list_add_tail(&crq->q.list, &detail->queue);
1199 else
1200 /* Lost a race, no longer PENDING, so don't enqueue */
1201 ret = -EAGAIN;
1195 spin_unlock(&queue_lock); 1202 spin_unlock(&queue_lock);
1196 wake_up(&queue_wait); 1203 wake_up(&queue_wait);
1197 return 0; 1204 if (ret == -EAGAIN) {
1205 kfree(buf);
1206 kfree(crq);
1207 }
1208 return ret;
1198} 1209}
1199EXPORT_SYMBOL_GPL(sunrpc_cache_pipe_upcall); 1210EXPORT_SYMBOL_GPL(sunrpc_cache_pipe_upcall);
1200 1211
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 06bdf5a1082c..621ca7b4a155 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -347,13 +347,13 @@ ip_map_cached_get(struct svc_xprt *xprt)
347 spin_lock(&xprt->xpt_lock); 347 spin_lock(&xprt->xpt_lock);
348 ipm = xprt->xpt_auth_cache; 348 ipm = xprt->xpt_auth_cache;
349 if (ipm != NULL) { 349 if (ipm != NULL) {
350 if (!cache_valid(&ipm->h)) { 350 sn = net_generic(xprt->xpt_net, sunrpc_net_id);
351 if (cache_is_expired(sn->ip_map_cache, &ipm->h)) {
351 /* 352 /*
352 * The entry has been invalidated since it was 353 * The entry has been invalidated since it was
353 * remembered, e.g. by a second mount from the 354 * remembered, e.g. by a second mount from the
354 * same IP address. 355 * same IP address.
355 */ 356 */
356 sn = net_generic(xprt->xpt_net, sunrpc_net_id);
357 xprt->xpt_auth_cache = NULL; 357 xprt->xpt_auth_cache = NULL;
358 spin_unlock(&xprt->xpt_lock); 358 spin_unlock(&xprt->xpt_lock);
359 cache_put(&ipm->h, sn->ip_map_cache); 359 cache_put(&ipm->h, sn->ip_map_cache);
@@ -493,8 +493,6 @@ static int unix_gid_parse(struct cache_detail *cd,
493 if (rv) 493 if (rv)
494 return -EINVAL; 494 return -EINVAL;
495 uid = make_kuid(&init_user_ns, id); 495 uid = make_kuid(&init_user_ns, id);
496 if (!uid_valid(uid))
497 return -EINVAL;
498 ug.uid = uid; 496 ug.uid = uid;
499 497
500 expiry = get_expiry(&mesg); 498 expiry = get_expiry(&mesg);
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 0f679df7d072..305374d4fb98 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -917,7 +917,10 @@ static void svc_tcp_clear_pages(struct svc_sock *svsk)
917 len = svsk->sk_datalen; 917 len = svsk->sk_datalen;
918 npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; 918 npages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
919 for (i = 0; i < npages; i++) { 919 for (i = 0; i < npages; i++) {
920 BUG_ON(svsk->sk_pages[i] == NULL); 920 if (svsk->sk_pages[i] == NULL) {
921 WARN_ON_ONCE(1);
922 continue;
923 }
921 put_page(svsk->sk_pages[i]); 924 put_page(svsk->sk_pages[i]);
922 svsk->sk_pages[i] = NULL; 925 svsk->sk_pages[i] = NULL;
923 } 926 }
@@ -1092,8 +1095,10 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
1092 goto err_noclose; 1095 goto err_noclose;
1093 } 1096 }
1094 1097
1095 if (svc_sock_reclen(svsk) < 8) 1098 if (svsk->sk_datalen < 8) {
1099 svsk->sk_datalen = 0;
1096 goto err_delete; /* client is nuts. */ 1100 goto err_delete; /* client is nuts. */
1101 }
1097 1102
1098 rqstp->rq_arg.len = svsk->sk_datalen; 1103 rqstp->rq_arg.len = svsk->sk_datalen;
1099 rqstp->rq_arg.page_base = 0; 1104 rqstp->rq_arg.page_base = 0;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 412de7cfcc80..ddf0602603bd 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -2534,7 +2534,6 @@ static struct rpc_xprt_ops bc_tcp_ops = {
2534 .reserve_xprt = xprt_reserve_xprt, 2534 .reserve_xprt = xprt_reserve_xprt,
2535 .release_xprt = xprt_release_xprt, 2535 .release_xprt = xprt_release_xprt,
2536 .alloc_slot = xprt_alloc_slot, 2536 .alloc_slot = xprt_alloc_slot,
2537 .rpcbind = xs_local_rpcbind,
2538 .buf_alloc = bc_malloc, 2537 .buf_alloc = bc_malloc,
2539 .buf_free = bc_free, 2538 .buf_free = bc_free,
2540 .send_request = bc_send_request, 2539 .send_request = bc_send_request,