Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9092131f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
parents f1b04770 eadf4598
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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

+1 −0
Original line number Diff line number Diff line
@@ -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
+62 −51
Original line number Diff line number Diff line
@@ -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 */
@@ -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
@@ -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;
}

/*
@@ -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;
}

/*
@@ -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);
+32 −8
Original line number Diff line number Diff line
@@ -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 *);
@@ -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) {
@@ -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;
@@ -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;
+3 −5
Original line number Diff line number Diff line
@@ -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