diff options
-rw-r--r-- | fs/nfsd/vfs.c | 59 |
1 files changed, 35 insertions, 24 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 1319e8027d55..aa1d0d6489a1 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -83,7 +83,6 @@ struct raparm_hbucket { | |||
83 | spinlock_t pb_lock; | 83 | spinlock_t pb_lock; |
84 | } ____cacheline_aligned_in_smp; | 84 | } ____cacheline_aligned_in_smp; |
85 | 85 | ||
86 | static struct raparms * raparml; | ||
87 | #define RAPARM_HASH_BITS 4 | 86 | #define RAPARM_HASH_BITS 4 |
88 | #define RAPARM_HASH_SIZE (1<<RAPARM_HASH_BITS) | 87 | #define RAPARM_HASH_SIZE (1<<RAPARM_HASH_BITS) |
89 | #define RAPARM_HASH_MASK (RAPARM_HASH_SIZE-1) | 88 | #define RAPARM_HASH_MASK (RAPARM_HASH_SIZE-1) |
@@ -1966,11 +1965,20 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp, | |||
1966 | void | 1965 | void |
1967 | nfsd_racache_shutdown(void) | 1966 | nfsd_racache_shutdown(void) |
1968 | { | 1967 | { |
1969 | if (!raparml) | 1968 | struct raparms *raparm, *last_raparm; |
1970 | return; | 1969 | unsigned int i; |
1970 | |||
1971 | dprintk("nfsd: freeing readahead buffers.\n"); | 1971 | dprintk("nfsd: freeing readahead buffers.\n"); |
1972 | kfree(raparml); | 1972 | |
1973 | raparml = NULL; | 1973 | for (i = 0; i < RAPARM_HASH_SIZE; i++) { |
1974 | raparm = raparm_hash[i].pb_head; | ||
1975 | while(raparm) { | ||
1976 | last_raparm = raparm; | ||
1977 | raparm = raparm->p_next; | ||
1978 | kfree(last_raparm); | ||
1979 | } | ||
1980 | raparm_hash[i].pb_head = NULL; | ||
1981 | } | ||
1974 | } | 1982 | } |
1975 | /* | 1983 | /* |
1976 | * Initialize readahead param cache | 1984 | * Initialize readahead param cache |
@@ -1981,35 +1989,38 @@ nfsd_racache_init(int cache_size) | |||
1981 | int i; | 1989 | int i; |
1982 | int j = 0; | 1990 | int j = 0; |
1983 | int nperbucket; | 1991 | int nperbucket; |
1992 | struct raparms **raparm = NULL; | ||
1984 | 1993 | ||
1985 | 1994 | ||
1986 | if (raparml) | 1995 | if (raparm_hash[0].pb_head) |
1987 | return 0; | 1996 | return 0; |
1988 | if (cache_size < 2*RAPARM_HASH_SIZE) | 1997 | nperbucket = DIV_ROUND_UP(cache_size, RAPARM_HASH_SIZE); |
1989 | cache_size = 2*RAPARM_HASH_SIZE; | 1998 | if (nperbucket < 2) |
1990 | raparml = kcalloc(cache_size, sizeof(struct raparms), GFP_KERNEL); | 1999 | nperbucket = 2; |
1991 | 2000 | cache_size = nperbucket * RAPARM_HASH_SIZE; | |
1992 | if (!raparml) { | ||
1993 | printk(KERN_WARNING | ||
1994 | "nfsd: Could not allocate memory read-ahead cache.\n"); | ||
1995 | return -ENOMEM; | ||
1996 | } | ||
1997 | 2001 | ||
1998 | dprintk("nfsd: allocating %d readahead buffers.\n", cache_size); | 2002 | dprintk("nfsd: allocating %d readahead buffers.\n", cache_size); |
1999 | for (i = 0 ; i < RAPARM_HASH_SIZE ; i++) { | 2003 | |
2000 | raparm_hash[i].pb_head = NULL; | 2004 | for (i = 0; i < RAPARM_HASH_SIZE; i++) { |
2001 | spin_lock_init(&raparm_hash[i].pb_lock); | 2005 | spin_lock_init(&raparm_hash[i].pb_lock); |
2002 | } | 2006 | |
2003 | nperbucket = DIV_ROUND_UP(cache_size, RAPARM_HASH_SIZE); | 2007 | raparm = &raparm_hash[i].pb_head; |
2004 | for (i = 0; i < cache_size - 1; i++) { | 2008 | for (j = 0; j < nperbucket; j++) { |
2005 | if (i % nperbucket == 0) | 2009 | *raparm = kzalloc(sizeof(struct raparms), GFP_KERNEL); |
2006 | raparm_hash[j++].pb_head = raparml + i; | 2010 | if (!*raparm) |
2007 | if (i % nperbucket < nperbucket-1) | 2011 | goto out_nomem; |
2008 | raparml[i].p_next = raparml + i + 1; | 2012 | raparm = &(*raparm)->p_next; |
2013 | } | ||
2014 | *raparm = NULL; | ||
2009 | } | 2015 | } |
2010 | 2016 | ||
2011 | nfsdstats.ra_size = cache_size; | 2017 | nfsdstats.ra_size = cache_size; |
2012 | return 0; | 2018 | return 0; |
2019 | |||
2020 | out_nomem: | ||
2021 | dprintk("nfsd: kmalloc failed, freeing readahead buffers\n"); | ||
2022 | nfsd_racache_shutdown(); | ||
2023 | return -ENOMEM; | ||
2013 | } | 2024 | } |
2014 | 2025 | ||
2015 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) | 2026 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) |