diff options
-rw-r--r-- | fs/nfsd/nfs4state.c | 18 |
1 files changed, 11 insertions, 7 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 9c912c004247..b421b51c3a9e 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -342,7 +342,7 @@ find_any_file(struct nfs4_file *f) | |||
342 | return ret; | 342 | return ret; |
343 | } | 343 | } |
344 | 344 | ||
345 | static int num_delegations; | 345 | static atomic_long_t num_delegations; |
346 | unsigned long max_delegations; | 346 | unsigned long max_delegations; |
347 | 347 | ||
348 | /* | 348 | /* |
@@ -582,22 +582,23 @@ static struct nfs4_delegation * | |||
582 | alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh) | 582 | alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh) |
583 | { | 583 | { |
584 | struct nfs4_delegation *dp; | 584 | struct nfs4_delegation *dp; |
585 | long n; | ||
585 | 586 | ||
586 | dprintk("NFSD alloc_init_deleg\n"); | 587 | dprintk("NFSD alloc_init_deleg\n"); |
587 | if (num_delegations > max_delegations) | 588 | n = atomic_long_inc_return(&num_delegations); |
588 | return NULL; | 589 | if (n < 0 || n > max_delegations) |
590 | goto out_dec; | ||
589 | if (delegation_blocked(¤t_fh->fh_handle)) | 591 | if (delegation_blocked(¤t_fh->fh_handle)) |
590 | return NULL; | 592 | goto out_dec; |
591 | dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab)); | 593 | dp = delegstateid(nfs4_alloc_stid(clp, deleg_slab)); |
592 | if (dp == NULL) | 594 | if (dp == NULL) |
593 | return dp; | 595 | goto out_dec; |
594 | /* | 596 | /* |
595 | * delegation seqid's are never incremented. The 4.1 special | 597 | * delegation seqid's are never incremented. The 4.1 special |
596 | * meaning of seqid 0 isn't meaningful, really, but let's avoid | 598 | * meaning of seqid 0 isn't meaningful, really, but let's avoid |
597 | * 0 anyway just for consistency and use 1: | 599 | * 0 anyway just for consistency and use 1: |
598 | */ | 600 | */ |
599 | dp->dl_stid.sc_stateid.si_generation = 1; | 601 | dp->dl_stid.sc_stateid.si_generation = 1; |
600 | num_delegations++; | ||
601 | INIT_LIST_HEAD(&dp->dl_perfile); | 602 | INIT_LIST_HEAD(&dp->dl_perfile); |
602 | INIT_LIST_HEAD(&dp->dl_perclnt); | 603 | INIT_LIST_HEAD(&dp->dl_perclnt); |
603 | INIT_LIST_HEAD(&dp->dl_recall_lru); | 604 | INIT_LIST_HEAD(&dp->dl_recall_lru); |
@@ -605,6 +606,9 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct sv | |||
605 | fh_copy_shallow(&dp->dl_fh, ¤t_fh->fh_handle); | 606 | fh_copy_shallow(&dp->dl_fh, ¤t_fh->fh_handle); |
606 | INIT_WORK(&dp->dl_recall.cb_work, nfsd4_run_cb_recall); | 607 | INIT_WORK(&dp->dl_recall.cb_work, nfsd4_run_cb_recall); |
607 | return dp; | 608 | return dp; |
609 | out_dec: | ||
610 | atomic_long_dec(&num_delegations); | ||
611 | return NULL; | ||
608 | } | 612 | } |
609 | 613 | ||
610 | static void remove_stid(struct nfs4_stid *s) | 614 | static void remove_stid(struct nfs4_stid *s) |
@@ -627,7 +631,7 @@ nfs4_put_delegation(struct nfs4_delegation *dp) | |||
627 | put_nfs4_file(dp->dl_file); | 631 | put_nfs4_file(dp->dl_file); |
628 | remove_stid(&dp->dl_stid); | 632 | remove_stid(&dp->dl_stid); |
629 | nfs4_free_stid(deleg_slab, &dp->dl_stid); | 633 | nfs4_free_stid(deleg_slab, &dp->dl_stid); |
630 | num_delegations--; | 634 | atomic_long_dec(&num_delegations); |
631 | } | 635 | } |
632 | } | 636 | } |
633 | 637 | ||