diff options
| author | Neil Brown <neilb@cse.unsw.edu.au> | 2002-02-25 22:22:50 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@penguin.transmeta.com> | 2002-02-25 22:22:50 -0800 |
| commit | 8244559fdb8a3a6aa407b2509a259b6f3e30d74b (patch) | |
| tree | 0a2e9edeaecb40b7af8cf9ff828f7e67e51c4486 | |
| parent | dd63f4c1098fc3d69ab16cc5c3efe9b56c36bd9d (diff) | |
[PATCH] PATCH 2/16: NFSD: BKL Removal: Lock export table
Change export table lock to (SMP safe) rwsemaphore
As a first step to removing the BKL from nfsd, this patch
changes the lock used for the export table to be a rwsem semaphore.
Previously it had the same functionality but depended on the BKL
for correctness.
As there is no "down_write_interruptible" this patch removes the
posibility of interrupting the write_lock request, but this should
never be needed anyway.
| -rw-r--r-- | fs/nfsd/export.c | 123 | ||||
| -rw-r--r-- | fs/nfsd/lockd.c | 2 | ||||
| -rw-r--r-- | fs/nfsd/nfsctl.c | 4 | ||||
| -rw-r--r-- | fs/nfsd/nfssvc.c | 2 | ||||
| -rw-r--r-- | include/linux/nfsd/export.h | 3 |
5 files changed, 51 insertions, 83 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 6961ba4011fa..6f7339fb8b26 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -20,6 +20,7 @@ #include <linux/stat.h> #include <linux/in.h> #include <linux/seq_file.h> +#include <linux/rwsem.h> #include <linux/sunrpc/svc.h> #include <linux/nfsd/nfsd.h> @@ -60,10 +61,6 @@ struct svc_clnthash { static struct svc_clnthash * clnt_hash[CLIENT_HASHMAX]; static svc_client * clients; -static int hash_lock; -static int want_lock; -static int hash_count; -static DECLARE_WAIT_QUEUE_HEAD( hash_wait ); /* * Find the client's export entry matching xdev/xino. @@ -163,6 +160,39 @@ static void exp_change_parents(svc_client *clp, svc_export *old, svc_export *new } /* + * Hashtable locking. Write locks are placed only by user processes + * wanting to modify export information. + * Write locking only done in this file. Read locking + * needed externally. + */ + +static DECLARE_RWSEM(hash_sem); + +void +exp_readlock(void) +{ + down_read(&hash_sem); +} + +static inline void +exp_writelock(void) +{ + down_write(&hash_sem); +} + +void +exp_readunlock(void) +{ + up_read(&hash_sem); +} + +static inline void +exp_writeunlock(void) +{ + up_write(&hash_sem); +} + +/* * Export a file system. */ int @@ -189,11 +219,9 @@ exp_export(struct nfsctl_export *nxp) ino = nxp->ex_ino; /* Try to lock the export table for update */ - if ((err = exp_writelock()) < 0) - goto out; + exp_writelock(); /* Look up client info */ - err = -EINVAL; if (!(clp = exp_getclientbyname(nxp->ex_client))) goto out_unlock; @@ -278,7 +306,7 @@ exp_export(struct nfsctl_export *nxp) /* Unlock hashtable */ out_unlock: - exp_unlock(); + exp_writeunlock(); out: return err; @@ -345,8 +373,7 @@ exp_unexport(struct nfsctl_export *nxp) if (!exp_verify_string(nxp->ex_client, NFSCLNT_IDMAX)) return -EINVAL; - if ((err = exp_writelock()) < 0) - goto out; + exp_writelock(); err = -EINVAL; clp = exp_getclientbyname(nxp->ex_client); @@ -361,8 +388,7 @@ exp_unexport(struct nfsctl_export *nxp) } } - exp_unlock(); -out: + exp_writeunlock(); return err; } @@ -415,58 +441,6 @@ out: return err; } -/* - * Hashtable locking. Write locks are placed only by user processes - * wanting to modify export information. - */ -void -exp_readlock(void) -{ - while (hash_lock || want_lock) - sleep_on(&hash_wait); - hash_count++; -} - -int -exp_writelock(void) -{ - /* fast track */ - if (!hash_count && !hash_lock) { - lock_it: - hash_lock = 1; - return 0; - } - - clear_thread_flag(TIF_SIGPENDING); - want_lock++; - while (hash_count || hash_lock) { - interruptible_sleep_on(&hash_wait); - if (signal_pending(current)) - break; - } - want_lock--; - - /* restore the task's signals */ - spin_lock_irq(¤t->sigmask_lock); - recalc_sigpending(); - spin_unlock_irq(¤t->sigmask_lock); - - if (!hash_count && !hash_lock) - goto lock_it; - return -EINTR; -} - -void -exp_unlock(void) -{ - if (!hash_count && !hash_lock) - printk(KERN_WARNING "exp_unlock: not locked!\n"); - if (hash_count) - hash_count--; - else - hash_lock = 0; - wake_up(&hash_wait); -} /* * Find a valid client given an inet address. We always move the most @@ -572,7 +546,7 @@ static void *e_next(struct seq_file *m, void *p, loff_t *pos) static void e_stop(struct seq_file *m, void *p) { - exp_unlock(); + exp_readunlock(); } struct flags { @@ -688,8 +662,7 @@ exp_addclient(struct nfsctl_client *ncp) goto out; /* Lock the hashtable */ - if ((err = exp_writelock()) < 0) - goto out; + exp_writelock(); /* First check if this is a change request for a client. */ for (clp = clients; clp; clp = clp->cl_next) @@ -754,7 +727,7 @@ exp_addclient(struct nfsctl_client *ncp) err = 0; out_unlock: - exp_unlock(); + exp_writeunlock(); out: return err; } @@ -773,10 +746,8 @@ exp_delclient(struct nfsctl_client *ncp) goto out; /* Lock the hashtable */ - if ((err = exp_writelock()) < 0) - goto out; + exp_writelock(); - err = -EINVAL; for (clpp = &clients; (clp = *clpp); clpp = &(clp->cl_next)) if (!strcmp(ncp->cl_ident, clp->cl_ident)) break; @@ -787,7 +758,7 @@ exp_delclient(struct nfsctl_client *ncp) err = 0; } - exp_unlock(); + exp_writeunlock(); out: return err; } @@ -893,16 +864,14 @@ nfsd_export_shutdown(void) dprintk("nfsd: shutting down export module.\n"); - if (exp_writelock() < 0) { - printk(KERN_WARNING "Weird: hashtable locked in exp_shutdown"); - return; - } + exp_writelock(); + for (i = 0; i < CLIENT_HASHMAX; i++) { while (clnt_hash[i]) exp_freeclient(clnt_hash[i]->h_client); } clients = NULL; /* we may be restarted before the module unloads */ - exp_unlock(); + exp_writeunlock(); dprintk("nfsd: export shutdown complete.\n"); } diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c index 5bed6b8ae320..a09b4e891f0b 100644 --- a/fs/nfsd/lockd.c +++ b/fs/nfsd/lockd.c @@ -62,7 +62,7 @@ nlm_fclose(struct file *filp) struct nlmsvc_binding nfsd_nlm_ops = { exp_readlock, /* lock export table for reading */ - exp_unlock, /* unlock export table */ + exp_readunlock, /* unlock export table */ exp_getclient, /* look up NFS client */ nlm_fopen, /* open file for locking */ nlm_fclose, /* close file */ diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 3a6f89c3bf55..77b1cbcc9255 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -121,7 +121,7 @@ nfsctl_getfs(struct nfsctl_fsparm *data, struct knfsd_fh *res) err = -EPERM; else err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen); - exp_unlock(); + exp_readunlock(); return err; } @@ -144,7 +144,7 @@ nfsctl_getfd(struct nfsctl_fdparm *data, __u8 *res) err = -EPERM; else err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE); - exp_unlock(); + exp_readunlock(); if (err == 0) { if (fh.fh_size > NFS_FHSIZE) diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 3c4d5630f760..782ad1434074 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -211,7 +211,7 @@ nfsd(struct svc_rqst *rqstp) svc_process(serv, rqstp); /* Unlock export hash tables */ - exp_unlock(); + exp_readunlock(); update_thread_usage(nfsd_busy); nfsd_busy--; } diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index 6f3e970f40d4..1125d2fa1cbf 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h @@ -87,8 +87,7 @@ struct svc_export { void nfsd_export_init(void); void nfsd_export_shutdown(void); void exp_readlock(void); -int exp_writelock(void); -void exp_unlock(void); +void exp_readunlock(void); struct svc_client * exp_getclient(struct sockaddr_in *sin); void exp_putclient(struct svc_client *clp); struct svc_export * exp_get(struct svc_client *clp, kdev_t dev, ino_t ino); |
