Loading fs/Kconfig +35 −0 Original line number Diff line number Diff line Loading @@ -1268,6 +1268,7 @@ config NFS_FS depends on INET select LOCKD select SUNRPC select NFS_ACL_SUPPORT if NFS_V3_ACL help If you are connected to some other (usually local) Unix computer (using SLIP, PLIP, PPP or Ethernet) and want to mount files residing Loading Loading @@ -1310,6 +1311,16 @@ config NFS_V3 If unsure, say Y. config NFS_V3_ACL bool "Provide client support for the NFSv3 ACL protocol extension" depends on NFS_V3 help Implement the NFSv3 ACL protocol extension for manipulating POSIX Access Control Lists. The server should also be compiled with the NFSv3 ACL protocol extension; see the CONFIG_NFSD_V3_ACL option. If unsure, say N. config NFS_V4 bool "Provide NFSv4 client support (EXPERIMENTAL)" depends on NFS_FS && EXPERIMENTAL Loading Loading @@ -1353,6 +1364,7 @@ config NFSD select LOCKD select SUNRPC select EXPORTFS select NFS_ACL_SUPPORT if NFSD_V3_ACL || NFSD_V2_ACL help If you want your Linux box to act as an NFS *server*, so that other computers on your local network which support NFS can access certain Loading @@ -1376,6 +1388,10 @@ config NFSD To compile the NFS server support as a module, choose M here: the module will be called nfsd. If unsure, say N. config NFSD_V2_ACL bool depends on NFSD config NFSD_V3 bool "Provide NFSv3 server support" depends on NFSD Loading @@ -1383,6 +1399,16 @@ config NFSD_V3 If you would like to include the NFSv3 server as well as the NFSv2 server, say Y here. If unsure, say Y. config NFSD_V3_ACL bool "Provide server support for the NFSv3 ACL protocol extension" depends on NFSD_V3 select NFSD_V2_ACL help Implement the NFSv3 ACL protocol extension for manipulating POSIX Access Control Lists on exported file systems. NFS clients should be compiled with the NFSv3 ACL protocol extension; see the CONFIG_NFS_V3_ACL option. If unsure, say N. config NFSD_V4 bool "Provide NFSv4 server support (EXPERIMENTAL)" depends on NFSD_V3 && EXPERIMENTAL Loading Loading @@ -1427,6 +1453,15 @@ config LOCKD_V4 config EXPORTFS tristate config NFS_ACL_SUPPORT tristate select FS_POSIX_ACL config NFS_COMMON bool depends on NFSD || NFS_FS default y config SUNRPC tristate Loading fs/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ obj-$(CONFIG_BINFMT_FLAT) += binfmt_flat.o obj-$(CONFIG_FS_MBCACHE) += mbcache.o obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o xattr_acl.o obj-$(CONFIG_NFS_COMMON) += nfs_common/ obj-$(CONFIG_QUOTA) += dquot.o obj-$(CONFIG_QFMT_V1) += quota_v1.o Loading fs/lockd/clntlock.c +62 −51 Original line number Diff line number Diff line Loading @@ -31,7 +31,7 @@ static int reclaimer(void *ptr); * This is the representation of a blocked client lock. */ struct nlm_wait { struct nlm_wait * b_next; /* linked list */ struct list_head b_list; /* linked list */ wait_queue_head_t b_wait; /* where to wait on */ struct nlm_host * b_host; struct file_lock * b_lock; /* local file lock */ Loading @@ -39,27 +39,54 @@ struct nlm_wait { u32 b_status; /* grant callback status */ }; static struct nlm_wait * nlm_blocked; static LIST_HEAD(nlm_blocked); /* * Block on a lock * Queue up a lock for blocking so that the GRANTED request can see it */ int nlmclnt_block(struct nlm_host *host, struct file_lock *fl, u32 *statp) int nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl) { struct nlm_wait block, **head; int err; u32 pstate; struct nlm_wait *block; BUG_ON(req->a_block != NULL); block = kmalloc(sizeof(*block), GFP_KERNEL); if (block == NULL) return -ENOMEM; block->b_host = host; block->b_lock = fl; init_waitqueue_head(&block->b_wait); block->b_status = NLM_LCK_BLOCKED; list_add(&block->b_list, &nlm_blocked); req->a_block = block; block.b_host = host; block.b_lock = fl; init_waitqueue_head(&block.b_wait); block.b_status = NLM_LCK_BLOCKED; block.b_next = nlm_blocked; nlm_blocked = █ return 0; } void nlmclnt_finish_block(struct nlm_rqst *req) { struct nlm_wait *block = req->a_block; if (block == NULL) return; req->a_block = NULL; list_del(&block->b_list); kfree(block); } /* * Block on a lock */ long nlmclnt_block(struct nlm_rqst *req, long timeout) { struct nlm_wait *block = req->a_block; long ret; /* Remember pseudo nsm state */ pstate = host->h_state; /* A borken server might ask us to block even if we didn't * request it. Just say no! */ if (!req->a_args.block) return -EAGAIN; /* Go to sleep waiting for GRANT callback. Some servers seem * to lose callbacks, however, so we're going to poll from Loading @@ -69,28 +96,16 @@ nlmclnt_block(struct nlm_host *host, struct file_lock *fl, u32 *statp) * a 1 minute timeout would do. See the comment before * nlmclnt_lock for an explanation. */ sleep_on_timeout(&block.b_wait, 30*HZ); ret = wait_event_interruptible_timeout(block->b_wait, block->b_status != NLM_LCK_BLOCKED, timeout); for (head = &nlm_blocked; *head; head = &(*head)->b_next) { if (*head == &block) { *head = block.b_next; break; if (block->b_status != NLM_LCK_BLOCKED) { req->a_res.status = block->b_status; block->b_status = NLM_LCK_BLOCKED; } } if (!signalled()) { *statp = block.b_status; return 0; } /* Okay, we were interrupted. Cancel the pending request * unless the server has rebooted. */ if (pstate == host->h_state && (err = nlmclnt_cancel(host, fl)) < 0) printk(KERN_NOTICE "lockd: CANCEL call failed (errno %d)\n", -err); return -ERESTARTSYS; return ret; } /* Loading @@ -100,27 +115,23 @@ u32 nlmclnt_grant(struct nlm_lock *lock) { struct nlm_wait *block; u32 res = nlm_lck_denied; /* * Look up blocked request based on arguments. * Warning: must not use cookie to match it! */ for (block = nlm_blocked; block; block = block->b_next) { if (nlm_compare_locks(block->b_lock, &lock->fl)) break; } /* Ooops, no blocked request found. */ if (block == NULL) return nlm_lck_denied; /* Alright, we found the lock. Set the return status and * wake up the caller. list_for_each_entry(block, &nlm_blocked, b_list) { if (nlm_compare_locks(block->b_lock, &lock->fl)) { /* Alright, we found a lock. Set the return status * and wake up the caller */ block->b_status = NLM_LCK_GRANTED; wake_up(&block->b_wait); return nlm_granted; res = nlm_granted; } } return res; } /* Loading Loading @@ -230,7 +241,7 @@ restart: host->h_reclaiming = 0; /* Now, wake up all processes that sleep on a blocked lock */ for (block = nlm_blocked; block; block = block->b_next) { list_for_each_entry(block, &nlm_blocked, b_list) { if (block->b_host == host) { block->b_status = NLM_LCK_DENIED_GRACE_PERIOD; wake_up(&block->b_wait); Loading fs/lockd/clntproc.c +32 −8 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #define NLMDBG_FACILITY NLMDBG_CLIENT #define NLMCLNT_GRACE_WAIT (5*HZ) #define NLMCLNT_POLL_TIMEOUT (30*HZ) static int nlmclnt_test(struct nlm_rqst *, struct file_lock *); static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *); Loading Loading @@ -553,6 +554,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) { struct nlm_host *host = req->a_host; struct nlm_res *resp = &req->a_res; long timeout; int status; if (!host->h_monitored && nsm_monitor(host) < 0) { Loading @@ -562,15 +564,32 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) goto out; } do { if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0) { if (req->a_args.block) { status = nlmclnt_prepare_block(req, host, fl); if (status < 0) goto out; } for(;;) { status = nlmclnt_call(req, NLMPROC_LOCK); if (status < 0) goto out_unblock; if (resp->status != NLM_LCK_BLOCKED) break; /* Wait on an NLM blocking lock */ timeout = nlmclnt_block(req, NLMCLNT_POLL_TIMEOUT); /* Did a reclaimer thread notify us of a server reboot? */ if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD) continue; if (resp->status != NLM_LCK_BLOCKED) break; status = nlmclnt_block(host, fl, &resp->status); if (timeout >= 0) continue; /* We were interrupted. Send a CANCEL request to the server * and exit */ status = (int)timeout; goto out_unblock; } if (status < 0) goto out; } while (resp->status == NLM_LCK_BLOCKED && req->a_args.block); if (resp->status == NLM_LCK_GRANTED) { fl->fl_u.nfs_fl.state = host->h_state; Loading @@ -579,6 +598,11 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) do_vfs_lock(fl); } status = nlm_stat_to_errno(resp->status); out_unblock: nlmclnt_finish_block(req); /* Cancel the blocked request if it is still pending */ if (resp->status == NLM_LCK_BLOCKED) nlmclnt_cancel(host, fl); out: nlmclnt_release_lockargs(req); return status; Loading fs/lockd/host.c +3 −5 Original line number Diff line number Diff line Loading @@ -189,17 +189,15 @@ nlm_bind_host(struct nlm_host *host) goto forgetit; xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout); xprt->nocong = 1; /* No congestion control for NLM */ xprt->resvport = 1; /* NLM requires a reserved port */ /* Existing NLM servers accept AUTH_UNIX only */ clnt = rpc_create_client(xprt, host->h_name, &nlm_program, host->h_version, RPC_AUTH_UNIX); if (IS_ERR(clnt)) { xprt_destroy(xprt); if (IS_ERR(clnt)) goto forgetit; } clnt->cl_autobind = 1; /* turn on pmap queries */ xprt->nocong = 1; /* No congestion control for NLM */ xprt->resvport = 1; /* NLM requires a reserved port */ host->h_rpcclnt = clnt; } Loading Loading
fs/Kconfig +35 −0 Original line number Diff line number Diff line Loading @@ -1268,6 +1268,7 @@ config NFS_FS depends on INET select LOCKD select SUNRPC select NFS_ACL_SUPPORT if NFS_V3_ACL help If you are connected to some other (usually local) Unix computer (using SLIP, PLIP, PPP or Ethernet) and want to mount files residing Loading Loading @@ -1310,6 +1311,16 @@ config NFS_V3 If unsure, say Y. config NFS_V3_ACL bool "Provide client support for the NFSv3 ACL protocol extension" depends on NFS_V3 help Implement the NFSv3 ACL protocol extension for manipulating POSIX Access Control Lists. The server should also be compiled with the NFSv3 ACL protocol extension; see the CONFIG_NFSD_V3_ACL option. If unsure, say N. config NFS_V4 bool "Provide NFSv4 client support (EXPERIMENTAL)" depends on NFS_FS && EXPERIMENTAL Loading Loading @@ -1353,6 +1364,7 @@ config NFSD select LOCKD select SUNRPC select EXPORTFS select NFS_ACL_SUPPORT if NFSD_V3_ACL || NFSD_V2_ACL help If you want your Linux box to act as an NFS *server*, so that other computers on your local network which support NFS can access certain Loading @@ -1376,6 +1388,10 @@ config NFSD To compile the NFS server support as a module, choose M here: the module will be called nfsd. If unsure, say N. config NFSD_V2_ACL bool depends on NFSD config NFSD_V3 bool "Provide NFSv3 server support" depends on NFSD Loading @@ -1383,6 +1399,16 @@ config NFSD_V3 If you would like to include the NFSv3 server as well as the NFSv2 server, say Y here. If unsure, say Y. config NFSD_V3_ACL bool "Provide server support for the NFSv3 ACL protocol extension" depends on NFSD_V3 select NFSD_V2_ACL help Implement the NFSv3 ACL protocol extension for manipulating POSIX Access Control Lists on exported file systems. NFS clients should be compiled with the NFSv3 ACL protocol extension; see the CONFIG_NFS_V3_ACL option. If unsure, say N. config NFSD_V4 bool "Provide NFSv4 server support (EXPERIMENTAL)" depends on NFSD_V3 && EXPERIMENTAL Loading Loading @@ -1427,6 +1453,15 @@ config LOCKD_V4 config EXPORTFS tristate config NFS_ACL_SUPPORT tristate select FS_POSIX_ACL config NFS_COMMON bool depends on NFSD || NFS_FS default y config SUNRPC tristate Loading
fs/Makefile +1 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ obj-$(CONFIG_BINFMT_FLAT) += binfmt_flat.o obj-$(CONFIG_FS_MBCACHE) += mbcache.o obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o xattr_acl.o obj-$(CONFIG_NFS_COMMON) += nfs_common/ obj-$(CONFIG_QUOTA) += dquot.o obj-$(CONFIG_QFMT_V1) += quota_v1.o Loading
fs/lockd/clntlock.c +62 −51 Original line number Diff line number Diff line Loading @@ -31,7 +31,7 @@ static int reclaimer(void *ptr); * This is the representation of a blocked client lock. */ struct nlm_wait { struct nlm_wait * b_next; /* linked list */ struct list_head b_list; /* linked list */ wait_queue_head_t b_wait; /* where to wait on */ struct nlm_host * b_host; struct file_lock * b_lock; /* local file lock */ Loading @@ -39,27 +39,54 @@ struct nlm_wait { u32 b_status; /* grant callback status */ }; static struct nlm_wait * nlm_blocked; static LIST_HEAD(nlm_blocked); /* * Block on a lock * Queue up a lock for blocking so that the GRANTED request can see it */ int nlmclnt_block(struct nlm_host *host, struct file_lock *fl, u32 *statp) int nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl) { struct nlm_wait block, **head; int err; u32 pstate; struct nlm_wait *block; BUG_ON(req->a_block != NULL); block = kmalloc(sizeof(*block), GFP_KERNEL); if (block == NULL) return -ENOMEM; block->b_host = host; block->b_lock = fl; init_waitqueue_head(&block->b_wait); block->b_status = NLM_LCK_BLOCKED; list_add(&block->b_list, &nlm_blocked); req->a_block = block; block.b_host = host; block.b_lock = fl; init_waitqueue_head(&block.b_wait); block.b_status = NLM_LCK_BLOCKED; block.b_next = nlm_blocked; nlm_blocked = █ return 0; } void nlmclnt_finish_block(struct nlm_rqst *req) { struct nlm_wait *block = req->a_block; if (block == NULL) return; req->a_block = NULL; list_del(&block->b_list); kfree(block); } /* * Block on a lock */ long nlmclnt_block(struct nlm_rqst *req, long timeout) { struct nlm_wait *block = req->a_block; long ret; /* Remember pseudo nsm state */ pstate = host->h_state; /* A borken server might ask us to block even if we didn't * request it. Just say no! */ if (!req->a_args.block) return -EAGAIN; /* Go to sleep waiting for GRANT callback. Some servers seem * to lose callbacks, however, so we're going to poll from Loading @@ -69,28 +96,16 @@ nlmclnt_block(struct nlm_host *host, struct file_lock *fl, u32 *statp) * a 1 minute timeout would do. See the comment before * nlmclnt_lock for an explanation. */ sleep_on_timeout(&block.b_wait, 30*HZ); ret = wait_event_interruptible_timeout(block->b_wait, block->b_status != NLM_LCK_BLOCKED, timeout); for (head = &nlm_blocked; *head; head = &(*head)->b_next) { if (*head == &block) { *head = block.b_next; break; if (block->b_status != NLM_LCK_BLOCKED) { req->a_res.status = block->b_status; block->b_status = NLM_LCK_BLOCKED; } } if (!signalled()) { *statp = block.b_status; return 0; } /* Okay, we were interrupted. Cancel the pending request * unless the server has rebooted. */ if (pstate == host->h_state && (err = nlmclnt_cancel(host, fl)) < 0) printk(KERN_NOTICE "lockd: CANCEL call failed (errno %d)\n", -err); return -ERESTARTSYS; return ret; } /* Loading @@ -100,27 +115,23 @@ u32 nlmclnt_grant(struct nlm_lock *lock) { struct nlm_wait *block; u32 res = nlm_lck_denied; /* * Look up blocked request based on arguments. * Warning: must not use cookie to match it! */ for (block = nlm_blocked; block; block = block->b_next) { if (nlm_compare_locks(block->b_lock, &lock->fl)) break; } /* Ooops, no blocked request found. */ if (block == NULL) return nlm_lck_denied; /* Alright, we found the lock. Set the return status and * wake up the caller. list_for_each_entry(block, &nlm_blocked, b_list) { if (nlm_compare_locks(block->b_lock, &lock->fl)) { /* Alright, we found a lock. Set the return status * and wake up the caller */ block->b_status = NLM_LCK_GRANTED; wake_up(&block->b_wait); return nlm_granted; res = nlm_granted; } } return res; } /* Loading Loading @@ -230,7 +241,7 @@ restart: host->h_reclaiming = 0; /* Now, wake up all processes that sleep on a blocked lock */ for (block = nlm_blocked; block; block = block->b_next) { list_for_each_entry(block, &nlm_blocked, b_list) { if (block->b_host == host) { block->b_status = NLM_LCK_DENIED_GRACE_PERIOD; wake_up(&block->b_wait); Loading
fs/lockd/clntproc.c +32 −8 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #define NLMDBG_FACILITY NLMDBG_CLIENT #define NLMCLNT_GRACE_WAIT (5*HZ) #define NLMCLNT_POLL_TIMEOUT (30*HZ) static int nlmclnt_test(struct nlm_rqst *, struct file_lock *); static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *); Loading Loading @@ -553,6 +554,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) { struct nlm_host *host = req->a_host; struct nlm_res *resp = &req->a_res; long timeout; int status; if (!host->h_monitored && nsm_monitor(host) < 0) { Loading @@ -562,15 +564,32 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) goto out; } do { if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0) { if (req->a_args.block) { status = nlmclnt_prepare_block(req, host, fl); if (status < 0) goto out; } for(;;) { status = nlmclnt_call(req, NLMPROC_LOCK); if (status < 0) goto out_unblock; if (resp->status != NLM_LCK_BLOCKED) break; /* Wait on an NLM blocking lock */ timeout = nlmclnt_block(req, NLMCLNT_POLL_TIMEOUT); /* Did a reclaimer thread notify us of a server reboot? */ if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD) continue; if (resp->status != NLM_LCK_BLOCKED) break; status = nlmclnt_block(host, fl, &resp->status); if (timeout >= 0) continue; /* We were interrupted. Send a CANCEL request to the server * and exit */ status = (int)timeout; goto out_unblock; } if (status < 0) goto out; } while (resp->status == NLM_LCK_BLOCKED && req->a_args.block); if (resp->status == NLM_LCK_GRANTED) { fl->fl_u.nfs_fl.state = host->h_state; Loading @@ -579,6 +598,11 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) do_vfs_lock(fl); } status = nlm_stat_to_errno(resp->status); out_unblock: nlmclnt_finish_block(req); /* Cancel the blocked request if it is still pending */ if (resp->status == NLM_LCK_BLOCKED) nlmclnt_cancel(host, fl); out: nlmclnt_release_lockargs(req); return status; Loading
fs/lockd/host.c +3 −5 Original line number Diff line number Diff line Loading @@ -189,17 +189,15 @@ nlm_bind_host(struct nlm_host *host) goto forgetit; xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout); xprt->nocong = 1; /* No congestion control for NLM */ xprt->resvport = 1; /* NLM requires a reserved port */ /* Existing NLM servers accept AUTH_UNIX only */ clnt = rpc_create_client(xprt, host->h_name, &nlm_program, host->h_version, RPC_AUTH_UNIX); if (IS_ERR(clnt)) { xprt_destroy(xprt); if (IS_ERR(clnt)) goto forgetit; } clnt->cl_autobind = 1; /* turn on pmap queries */ xprt->nocong = 1; /* No congestion control for NLM */ xprt->resvport = 1; /* NLM requires a reserved port */ host->h_rpcclnt = clnt; } Loading