aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4state.c18
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
345static int num_delegations; 345static atomic_long_t num_delegations;
346unsigned long max_delegations; 346unsigned long max_delegations;
347 347
348/* 348/*
@@ -582,22 +582,23 @@ static struct nfs4_delegation *
582alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh) 582alloc_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(&current_fh->fh_handle)) 591 if (delegation_blocked(&current_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, &current_fh->fh_handle); 606 fh_copy_shallow(&dp->dl_fh, &current_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;
609out_dec:
610 atomic_long_dec(&num_delegations);
611 return NULL;
608} 612}
609 613
610static void remove_stid(struct nfs4_stid *s) 614static 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