Commit 12a54b15 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'nfsd-5.1-1' of git://linux-nfs.org/~bfields/linux

Pull nfsd bugfixes from Bruce Fields:
 "Fix miscellaneous nfsd bugs, in NFSv4.1 callbacks, NFSv4.1
  lock-notification callbacks, NFSv3 readdir encoding, and the
  cache/upcall code"

* tag 'nfsd-5.1-1' of git://linux-nfs.org/~bfields/linux:
  nfsd: wake blocked file lock waiters before sending callback
  nfsd: wake waiters blocked on file_lock before deleting it
  nfsd: Don't release the callback slot unless it was actually held
  nfsd/nfsd3_proc_readdir: fix buffer count and page pointers
  sunrpc: don't mark uninitialised items as VALID.
parents d286e13d f456458e
Loading
Loading
Loading
Loading
+15 −2
Original line number Diff line number Diff line
@@ -442,7 +442,9 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp)
	struct nfsd3_readdirargs *argp = rqstp->rq_argp;
	struct nfsd3_readdirres  *resp = rqstp->rq_resp;
	__be32		nfserr;
	int		count;
	int		count = 0;
	struct page	**p;
	caddr_t		page_addr = NULL;

	dprintk("nfsd: READDIR(3)  %s %d bytes at %d\n",
				SVCFH_fmt(&argp->fh),
@@ -462,7 +464,18 @@ nfsd3_proc_readdir(struct svc_rqst *rqstp)
	nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t*) &argp->cookie, 
					&resp->common, nfs3svc_encode_entry);
	memcpy(resp->verf, argp->verf, 8);
	resp->count = resp->buffer - argp->buffer;
	count = 0;
	for (p = rqstp->rq_respages + 1; p < rqstp->rq_next_page; p++) {
		page_addr = page_address(*p);

		if (((caddr_t)resp->buffer >= page_addr) &&
		    ((caddr_t)resp->buffer < page_addr + PAGE_SIZE)) {
			count += (caddr_t)resp->buffer - page_addr;
			break;
		}
		count += PAGE_SIZE;
	}
	resp->count = count >> 2;
	if (resp->offset) {
		loff_t offset = argp->cookie;

+9 −2
Original line number Diff line number Diff line
@@ -573,6 +573,7 @@ int
nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p)
{
	struct nfsd3_readdirargs *args = rqstp->rq_argp;
	int len;
	u32 max_blocksize = svc_max_payload(rqstp);

	p = decode_fh(p, &args->fh);
@@ -582,8 +583,14 @@ nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p)
	args->verf   = p; p += 2;
	args->dircount = ~0;
	args->count  = ntohl(*p++);
	args->count  = min_t(u32, args->count, max_blocksize);
	args->buffer = page_address(*(rqstp->rq_next_page++));
	len = args->count  = min_t(u32, args->count, max_blocksize);

	while (len > 0) {
		struct page *p = *(rqstp->rq_next_page++);
		if (!args->buffer)
			args->buffer = page_address(p);
		len -= PAGE_SIZE;
	}

	return xdr_argsize_check(rqstp, p);
}
+7 −1
Original line number Diff line number Diff line
@@ -1010,8 +1010,9 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
	cb->cb_seq_status = 1;
	cb->cb_status = 0;
	if (minorversion) {
		if (!nfsd41_cb_get_slot(clp, task))
		if (!cb->cb_holds_slot && !nfsd41_cb_get_slot(clp, task))
			return;
		cb->cb_holds_slot = true;
	}
	rpc_call_start(task);
}
@@ -1038,6 +1039,9 @@ static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback
		return true;
	}

	if (!cb->cb_holds_slot)
		goto need_restart;

	switch (cb->cb_seq_status) {
	case 0:
		/*
@@ -1076,6 +1080,7 @@ static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback
			cb->cb_seq_status);
	}

	cb->cb_holds_slot = false;
	clear_bit(0, &clp->cl_cb_slot_busy);
	rpc_wake_up_next(&clp->cl_cb_waitq);
	dprintk("%s: freed slot, new seqid=%d\n", __func__,
@@ -1283,6 +1288,7 @@ void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp,
	cb->cb_seq_status = 1;
	cb->cb_status = 0;
	cb->cb_need_restart = false;
	cb->cb_holds_slot = false;
}

void nfsd4_run_cb(struct nfsd4_callback *cb)
+10 −2
Original line number Diff line number Diff line
@@ -265,6 +265,7 @@ find_or_allocate_block(struct nfs4_lockowner *lo, struct knfsd_fh *fh,
static void
free_blocked_lock(struct nfsd4_blocked_lock *nbl)
{
	locks_delete_block(&nbl->nbl_lock);
	locks_release_private(&nbl->nbl_lock);
	kfree(nbl);
}
@@ -293,11 +294,18 @@ remove_blocked_locks(struct nfs4_lockowner *lo)
		nbl = list_first_entry(&reaplist, struct nfsd4_blocked_lock,
					nbl_lru);
		list_del_init(&nbl->nbl_lru);
		locks_delete_block(&nbl->nbl_lock);
		free_blocked_lock(nbl);
	}
}

static void
nfsd4_cb_notify_lock_prepare(struct nfsd4_callback *cb)
{
	struct nfsd4_blocked_lock	*nbl = container_of(cb,
						struct nfsd4_blocked_lock, nbl_cb);
	locks_delete_block(&nbl->nbl_lock);
}

static int
nfsd4_cb_notify_lock_done(struct nfsd4_callback *cb, struct rpc_task *task)
{
@@ -325,6 +333,7 @@ nfsd4_cb_notify_lock_release(struct nfsd4_callback *cb)
}

static const struct nfsd4_callback_ops nfsd4_cb_notify_lock_ops = {
	.prepare	= nfsd4_cb_notify_lock_prepare,
	.done		= nfsd4_cb_notify_lock_done,
	.release	= nfsd4_cb_notify_lock_release,
};
@@ -4863,7 +4872,6 @@ nfs4_laundromat(struct nfsd_net *nn)
		nbl = list_first_entry(&reaplist,
					struct nfsd4_blocked_lock, nbl_lru);
		list_del_init(&nbl->nbl_lru);
		locks_delete_block(&nbl->nbl_lock);
		free_blocked_lock(nbl);
	}
out:
+1 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ struct nfsd4_callback {
	int cb_seq_status;
	int cb_status;
	bool cb_need_restart;
	bool cb_holds_slot;
};

struct nfsd4_callback_ops {
Loading