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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'for-3.16' of git://linux-nfs.org/~bfields/linux

Pull nfsd bugfixes from Bruce Fields:
"Fixes for a new regression from the xdr encoding rewrite, and a
delegation problem we've had for a while (made somewhat more annoying
by the vfs delegation support added in 3.13)"

* 'for-3.16' of git://linux-nfs.org/~bfields/linux:
NFSD: fix bug for readdir of pseudofs
NFSD: Don't hand out delegations for 30 seconds after recalling them.

+79
+78
fs/nfsd/nfs4state.c
··· 41 41 #include <linux/ratelimit.h> 42 42 #include <linux/sunrpc/svcauth_gss.h> 43 43 #include <linux/sunrpc/addr.h> 44 + #include <linux/hash.h> 44 45 #include "xdr4.h" 45 46 #include "xdr4cb.h" 46 47 #include "vfs.h" ··· 365 364 return openlockstateid(nfs4_alloc_stid(clp, stateid_slab)); 366 365 } 367 366 367 + /* 368 + * When we recall a delegation, we should be careful not to hand it 369 + * out again straight away. 370 + * To ensure this we keep a pair of bloom filters ('new' and 'old') 371 + * in which the filehandles of recalled delegations are "stored". 372 + * If a filehandle appear in either filter, a delegation is blocked. 373 + * When a delegation is recalled, the filehandle is stored in the "new" 374 + * filter. 375 + * Every 30 seconds we swap the filters and clear the "new" one, 376 + * unless both are empty of course. 377 + * 378 + * Each filter is 256 bits. We hash the filehandle to 32bit and use the 379 + * low 3 bytes as hash-table indices. 380 + * 381 + * 'state_lock', which is always held when block_delegations() is called, 382 + * is used to manage concurrent access. Testing does not need the lock 383 + * except when swapping the two filters. 384 + */ 385 + static struct bloom_pair { 386 + int entries, old_entries; 387 + time_t swap_time; 388 + int new; /* index into 'set' */ 389 + DECLARE_BITMAP(set[2], 256); 390 + } blocked_delegations; 391 + 392 + static int delegation_blocked(struct knfsd_fh *fh) 393 + { 394 + u32 hash; 395 + struct bloom_pair *bd = &blocked_delegations; 396 + 397 + if (bd->entries == 0) 398 + return 0; 399 + if (seconds_since_boot() - bd->swap_time > 30) { 400 + spin_lock(&state_lock); 401 + if (seconds_since_boot() - bd->swap_time > 30) { 402 + bd->entries -= bd->old_entries; 403 + bd->old_entries = bd->entries; 404 + memset(bd->set[bd->new], 0, 405 + sizeof(bd->set[0])); 406 + bd->new = 1-bd->new; 407 + bd->swap_time = seconds_since_boot(); 408 + } 409 + spin_unlock(&state_lock); 410 + } 411 + hash = arch_fast_hash(&fh->fh_base, fh->fh_size, 0); 412 + if (test_bit(hash&255, bd->set[0]) && 413 + test_bit((hash>>8)&255, bd->set[0]) && 414 + test_bit((hash>>16)&255, bd->set[0])) 415 + return 1; 416 + 417 + if (test_bit(hash&255, bd->set[1]) && 418 + test_bit((hash>>8)&255, bd->set[1]) && 419 + test_bit((hash>>16)&255, bd->set[1])) 420 + return 1; 421 + 422 + return 0; 423 + } 424 + 425 + static void block_delegations(struct knfsd_fh *fh) 426 + { 427 + u32 hash; 428 + struct bloom_pair *bd = &blocked_delegations; 429 + 430 + hash = arch_fast_hash(&fh->fh_base, fh->fh_size, 0); 431 + 432 + __set_bit(hash&255, bd->set[bd->new]); 433 + __set_bit((hash>>8)&255, bd->set[bd->new]); 434 + __set_bit((hash>>16)&255, bd->set[bd->new]); 435 + if (bd->entries == 0) 436 + bd->swap_time = seconds_since_boot(); 437 + bd->entries += 1; 438 + } 439 + 368 440 static struct nfs4_delegation * 369 441 alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh) 370 442 { ··· 445 371 446 372 dprintk("NFSD alloc_init_deleg\n"); 447 373 if (num_delegations > max_delegations) 374 + return NULL; 375 + if (delegation_blocked(&current_fh->fh_handle)) 448 376 return NULL; 449 377 dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab)); 450 378 if (dp == NULL) ··· 2845 2769 2846 2770 /* Only place dl_time is set; protected by i_lock: */ 2847 2771 dp->dl_time = get_seconds(); 2772 + 2773 + block_delegations(&dp->dl_fh); 2848 2774 2849 2775 nfsd4_cb_recall(dp); 2850 2776 }
+1
fs/nfsd/nfs4xdr.c
··· 2687 2687 nfserr = nfserr_toosmall; 2688 2688 goto fail; 2689 2689 case nfserr_noent: 2690 + xdr_truncate_encode(xdr, start_offset); 2690 2691 goto skip_entry; 2691 2692 default: 2692 2693 /*