Messages in this thread Patches in this message | | | From | Craig Christophel <> | Subject | Re: [PATCH] -- filesystems.c::sys_nfsservctl 2.5.5-pre1 | Date | Wed, 13 Feb 2002 17:46:26 -0500 |
| |
> What would remain to protect 'nfsd_linkage' if you removed the BKL?
ok here is a patch with that changed. inlined for commenting and attached for patching. (kmail screws up my inlines occasionally) All of this extra checking is only in place if nfsd is a module. rw_sems shouldn't impost that much overhead in the normal case.
The while is there to catch extremely unlikely cases of the module unloading during this loop, ie: the cleanup_module section of nfsd is waiting for the semaphore.
===== fs/filesystems.c 1.4 vs edited ===== --- 1.4/fs/filesystems.c Fri Feb 8 22:10:55 2002 +++ edited/fs/filesystems.c Wed Feb 13 17:43:41 2002 @@ -16,19 +16,28 @@ #if defined(CONFIG_NFSD_MODULE) struct nfsd_linkage *nfsd_linkage = NULL; +DECLARE_RWSEM(nfsd_linkage_lock); long asmlinkage sys_nfsservctl(int cmd, void *argp, void *resp) { int ret = -ENOSYS; - lock_kernel(); - - if (nfsd_linkage || - (request_module ("nfsd") == 0 && nfsd_linkage)) - ret = nfsd_linkage->do_nfsservctl(cmd, argp, resp); - - unlock_kernel(); + down_read(&nfsd_linkage_lock); + while(!nfsd_linkage) { + up_read(&nfsd_linkage_lock); + down_write(&nfsd_linkage_lock); + if (!nfsd_linkage) + if (request_module ("nfsd") != 0) { + up_write(&nfsd_linkage_lock); + goto out; + } + up_write(&nfsd_linkage_lock); + down_read(&nfsd_linkage_lock); + } + ret = nfsd_linkage->do_nfsservctl(cmd, argp, resp); + up_read(&nfsd_linkage_lock); +out: return ret; } EXPORT_SYMBOL(nfsd_linkage); ===== fs/nfsd/nfsctl.c 1.10 vs edited ===== --- 1.10/fs/nfsd/nfsctl.c Fri Feb 8 22:10:55 2002 +++ edited/fs/nfsd/nfsctl.c Wed Feb 13 17:33:17 2002 @@ -290,6 +290,7 @@ do_nfsservctl: handle_sys_nfsservctl, }; +extern struct nfsd_linkage_lock; /* * Initialize the module */ @@ -307,7 +308,9 @@ void cleanup_module(void) { + down_write(&nfsd_linkage_lock); nfsd_linkage = NULL; + up_write(&nfsd_linkage_lock); nfsd_export_shutdown(); nfsd_cache_shutdown(); remove_proc_entry("fs/nfs/exports", NULL);===== fs/filesystems.c 1.4 vs edited ===== --- 1.4/fs/filesystems.c Fri Feb 8 22:10:55 2002 +++ edited/fs/filesystems.c Wed Feb 13 17:43:41 2002 @@ -16,19 +16,28 @@ #if defined(CONFIG_NFSD_MODULE) struct nfsd_linkage *nfsd_linkage = NULL; +DECLARE_RWSEM(nfsd_linkage_lock); long asmlinkage sys_nfsservctl(int cmd, void *argp, void *resp) { int ret = -ENOSYS; - lock_kernel(); - - if (nfsd_linkage || - (request_module ("nfsd") == 0 && nfsd_linkage)) - ret = nfsd_linkage->do_nfsservctl(cmd, argp, resp); - - unlock_kernel(); + down_read(&nfsd_linkage_lock); + while(!nfsd_linkage) { + up_read(&nfsd_linkage_lock); + down_write(&nfsd_linkage_lock); + if (!nfsd_linkage) + if (request_module ("nfsd") != 0) { + up_write(&nfsd_linkage_lock); + goto out; + } + up_write(&nfsd_linkage_lock); + down_read(&nfsd_linkage_lock); + } + ret = nfsd_linkage->do_nfsservctl(cmd, argp, resp); + up_read(&nfsd_linkage_lock); +out: return ret; } EXPORT_SYMBOL(nfsd_linkage); ===== fs/nfsd/nfsctl.c 1.10 vs edited ===== --- 1.10/fs/nfsd/nfsctl.c Fri Feb 8 22:10:55 2002 +++ edited/fs/nfsd/nfsctl.c Wed Feb 13 17:33:17 2002 @@ -290,6 +290,7 @@ do_nfsservctl: handle_sys_nfsservctl, }; +extern struct nfsd_linkage_lock; /* * Initialize the module */ @@ -307,7 +308,9 @@ void cleanup_module(void) { + down_write(&nfsd_linkage_lock); nfsd_linkage = NULL; + up_write(&nfsd_linkage_lock); nfsd_export_shutdown(); nfsd_cache_shutdown(); remove_proc_entry("fs/nfs/exports", NULL); | |