Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'nfsd-5.1-1' of git://linux-nfs.org/~bfields/linux

Pull nfsd bugfixes from Bruce Fields:
"Fix miscellaneous nfsd bugs, in NFSv4.1 callbacks, NFSv4.1
lock-notification callbacks, NFSv3 readdir encoding, and the
cache/upcall code"

* tag 'nfsd-5.1-1' of git://linux-nfs.org/~bfields/linux:
nfsd: wake blocked file lock waiters before sending callback
nfsd: wake waiters blocked on file_lock before deleting it
nfsd: Don't release the callback slot unless it was actually held
nfsd/nfsd3_proc_readdir: fix buffer count and page pointers
sunrpc: don't mark uninitialised items as VALID.

+45 -7
+15 -2
fs/nfsd/nfs3proc.c
··· 442 442 struct nfsd3_readdirargs *argp = rqstp->rq_argp; 443 443 struct nfsd3_readdirres *resp = rqstp->rq_resp; 444 444 __be32 nfserr; 445 - int count; 445 + int count = 0; 446 + struct page **p; 447 + caddr_t page_addr = NULL; 446 448 447 449 dprintk("nfsd: READDIR(3) %s %d bytes at %d\n", 448 450 SVCFH_fmt(&argp->fh), ··· 464 462 nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t*) &argp->cookie, 465 463 &resp->common, nfs3svc_encode_entry); 466 464 memcpy(resp->verf, argp->verf, 8); 467 - resp->count = resp->buffer - argp->buffer; 465 + count = 0; 466 + for (p = rqstp->rq_respages + 1; p < rqstp->rq_next_page; p++) { 467 + page_addr = page_address(*p); 468 + 469 + if (((caddr_t)resp->buffer >= page_addr) && 470 + ((caddr_t)resp->buffer < page_addr + PAGE_SIZE)) { 471 + count += (caddr_t)resp->buffer - page_addr; 472 + break; 473 + } 474 + count += PAGE_SIZE; 475 + } 476 + resp->count = count >> 2; 468 477 if (resp->offset) { 469 478 loff_t offset = argp->cookie; 470 479
+9 -2
fs/nfsd/nfs3xdr.c
··· 573 573 nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p) 574 574 { 575 575 struct nfsd3_readdirargs *args = rqstp->rq_argp; 576 + int len; 576 577 u32 max_blocksize = svc_max_payload(rqstp); 577 578 578 579 p = decode_fh(p, &args->fh); ··· 583 582 args->verf = p; p += 2; 584 583 args->dircount = ~0; 585 584 args->count = ntohl(*p++); 586 - args->count = min_t(u32, args->count, max_blocksize); 587 - args->buffer = page_address(*(rqstp->rq_next_page++)); 585 + len = args->count = min_t(u32, args->count, max_blocksize); 586 + 587 + while (len > 0) { 588 + struct page *p = *(rqstp->rq_next_page++); 589 + if (!args->buffer) 590 + args->buffer = page_address(p); 591 + len -= PAGE_SIZE; 592 + } 588 593 589 594 return xdr_argsize_check(rqstp, p); 590 595 }
+7 -1
fs/nfsd/nfs4callback.c
··· 1010 1010 cb->cb_seq_status = 1; 1011 1011 cb->cb_status = 0; 1012 1012 if (minorversion) { 1013 - if (!nfsd41_cb_get_slot(clp, task)) 1013 + if (!cb->cb_holds_slot && !nfsd41_cb_get_slot(clp, task)) 1014 1014 return; 1015 + cb->cb_holds_slot = true; 1015 1016 } 1016 1017 rpc_call_start(task); 1017 1018 } ··· 1038 1037 1039 1038 return true; 1040 1039 } 1040 + 1041 + if (!cb->cb_holds_slot) 1042 + goto need_restart; 1041 1043 1042 1044 switch (cb->cb_seq_status) { 1043 1045 case 0: ··· 1080 1076 cb->cb_seq_status); 1081 1077 } 1082 1078 1079 + cb->cb_holds_slot = false; 1083 1080 clear_bit(0, &clp->cl_cb_slot_busy); 1084 1081 rpc_wake_up_next(&clp->cl_cb_waitq); 1085 1082 dprintk("%s: freed slot, new seqid=%d\n", __func__, ··· 1288 1283 cb->cb_seq_status = 1; 1289 1284 cb->cb_status = 0; 1290 1285 cb->cb_need_restart = false; 1286 + cb->cb_holds_slot = false; 1291 1287 } 1292 1288 1293 1289 void nfsd4_run_cb(struct nfsd4_callback *cb)
+10 -2
fs/nfsd/nfs4state.c
··· 265 265 static void 266 266 free_blocked_lock(struct nfsd4_blocked_lock *nbl) 267 267 { 268 + locks_delete_block(&nbl->nbl_lock); 268 269 locks_release_private(&nbl->nbl_lock); 269 270 kfree(nbl); 270 271 } ··· 294 293 nbl = list_first_entry(&reaplist, struct nfsd4_blocked_lock, 295 294 nbl_lru); 296 295 list_del_init(&nbl->nbl_lru); 297 - locks_delete_block(&nbl->nbl_lock); 298 296 free_blocked_lock(nbl); 299 297 } 298 + } 299 + 300 + static void 301 + nfsd4_cb_notify_lock_prepare(struct nfsd4_callback *cb) 302 + { 303 + struct nfsd4_blocked_lock *nbl = container_of(cb, 304 + struct nfsd4_blocked_lock, nbl_cb); 305 + locks_delete_block(&nbl->nbl_lock); 300 306 } 301 307 302 308 static int ··· 333 325 } 334 326 335 327 static const struct nfsd4_callback_ops nfsd4_cb_notify_lock_ops = { 328 + .prepare = nfsd4_cb_notify_lock_prepare, 336 329 .done = nfsd4_cb_notify_lock_done, 337 330 .release = nfsd4_cb_notify_lock_release, 338 331 }; ··· 4872 4863 nbl = list_first_entry(&reaplist, 4873 4864 struct nfsd4_blocked_lock, nbl_lru); 4874 4865 list_del_init(&nbl->nbl_lru); 4875 - locks_delete_block(&nbl->nbl_lock); 4876 4866 free_blocked_lock(nbl); 4877 4867 } 4878 4868 out:
+1
fs/nfsd/state.h
··· 70 70 int cb_seq_status; 71 71 int cb_status; 72 72 bool cb_need_restart; 73 + bool cb_holds_slot; 73 74 }; 74 75 75 76 struct nfsd4_callback_ops {
+3
net/sunrpc/cache.c
··· 54 54 h->last_refresh = now; 55 55 } 56 56 57 + static inline int cache_is_valid(struct cache_head *h); 57 58 static void cache_fresh_locked(struct cache_head *head, time_t expiry, 58 59 struct cache_detail *detail); 59 60 static void cache_fresh_unlocked(struct cache_head *head, ··· 106 105 if (cache_is_expired(detail, tmp)) { 107 106 hlist_del_init_rcu(&tmp->cache_list); 108 107 detail->entries --; 108 + if (cache_is_valid(tmp) == -EAGAIN) 109 + set_bit(CACHE_NEGATIVE, &tmp->flags); 109 110 cache_fresh_locked(tmp, 0, detail); 110 111 freeme = tmp; 111 112 break;