2010-06-24 16:29:10

by J.Bruce Fields

[permalink] [raw]
Subject: bugfixes for 2.6.36


I'm queuing up the following small bugfixes and cleanup for 2.6.36.

--b.


2010-06-24 16:29:10

by J.Bruce Fields

[permalink] [raw]
Subject: [PATCH 4/6] nfsd4: remove some debugging code

This is overkill.

Signed-off-by: J. Bruce Fields <[email protected]>
---
fs/nfsd/nfs4state.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 603076f..182448f 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -591,10 +591,8 @@ find_in_sessionid_hashtbl(struct nfs4_sessionid *sessionid)

dump_sessionid(__func__, sessionid);
idx = hash_sessionid(sessionid);
- dprintk("%s: idx is %d\n", __func__, idx);
/* Search in the appropriate list */
list_for_each_entry(elem, &sessionid_hashtbl[idx], se_hash) {
- dump_sessionid("list traversal", &elem->se_sessionid);
if (!memcmp(elem->se_sessionid.data, sessionid->data,
NFS4_MAX_SESSIONID_LEN)) {
return elem;
--
1.7.0.4


2010-06-24 16:29:11

by J.Bruce Fields

[permalink] [raw]
Subject: [PATCH 5/6] nfsd4: fix deleg leak on callback error

Signed-off-by: J. Bruce Fields <[email protected]>
---
fs/nfsd/nfs4callback.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 874a56a..a468632 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -761,8 +761,10 @@ static void _nfsd4_cb_recall(struct nfs4_delegation *dp)
.rpc_cred = callback_cred
};

- if (clnt == NULL)
+ if (clnt == NULL) {
+ nfs4_put_delegation(dp);
return; /* Client is shutting down; give up. */
+ }

args->args_op = dp;
msg.rpc_argp = args;
--
1.7.0.4


2010-06-24 16:29:11

by J.Bruce Fields

[permalink] [raw]
Subject: [PATCH 6/6] nfsd4: fix delegation recall race use-after-free

When the rarely-used callback-connection-changing setclientid occurs
simultaneously with a delegation recall, we rerun the recall by
requeueing it on a workqueue. But we also need to take a reference on
the delegation in that case, since the delegation held by the rpc itself
will be released by the rpc_release callback.

Signed-off-by: J. Bruce Fields <[email protected]>
---
fs/nfsd/nfs4callback.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index a468632..1e6497e 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -689,6 +689,7 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
warn_no_callback_path(clp, task->tk_status);
if (current_rpc_client != task->tk_client) {
/* queue a callback on the new connection: */
+ atomic_inc(&dp->dl_count);
nfsd4_cb_recall(dp);
return;
}
--
1.7.0.4


2010-06-24 16:29:11

by J.Bruce Fields

[permalink] [raw]
Subject: [PATCH 3/6] nfsd: nfs4callback encode_stateid helper function

From: Benny Halevy <[email protected]>

To be used also for the pnfs cb_layoutrecall callback

Signed-off-by: Benny Halevy <[email protected]>
[nfsd4: fix cb_recall encoding]
"nfsd: nfs4callback encode_stateid helper function" forgot to reserve
more space after return from the new helper.
Reported-by: Michael Groshans <[email protected]>
Signed-off-by: Benny Halevy <[email protected]>
Signed-off-by: J. Bruce Fields <[email protected]>
---
fs/nfsd/nfs4callback.c | 16 +++++++++++++---
1 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index c8dd03c..874a56a 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -203,6 +203,16 @@ nfs_cb_stat_to_errno(int stat)
*/

static void
+encode_stateid(struct xdr_stream *xdr, stateid_t *sid)
+{
+ __be32 *p;
+
+ RESERVE_SPACE(sizeof(stateid_t));
+ WRITE32(sid->si_generation);
+ WRITEMEM(&sid->si_opaque, sizeof(stateid_opaque_t));
+}
+
+static void
encode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr)
{
__be32 * p;
@@ -227,10 +237,10 @@ encode_cb_recall(struct xdr_stream *xdr, struct nfs4_delegation *dp,
__be32 *p;
int len = dp->dl_fh.fh_size;

- RESERVE_SPACE(12+sizeof(dp->dl_stateid) + len);
+ RESERVE_SPACE(4);
WRITE32(OP_CB_RECALL);
- WRITE32(dp->dl_stateid.si_generation);
- WRITEMEM(&dp->dl_stateid.si_opaque, sizeof(stateid_opaque_t));
+ encode_stateid(xdr, &dp->dl_stateid);
+ RESERVE_SPACE(8 + (XDR_QUADLEN(len) << 2));
WRITE32(0); /* truncate optimization not implemented */
WRITE32(len);
WRITEMEM(&dp->dl_fh.fh_base, len);
--
1.7.0.4


2010-06-24 16:29:10

by J.Bruce Fields

[permalink] [raw]
Subject: [PATCH 1/6] nfsd4; fix session reference count leak

Note the session has to be put() here regardless of what happens to the
client.

Signed-off-by: J. Bruce Fields <[email protected]>
---
fs/nfsd/nfs4state.c | 1 -
fs/nfsd/nfs4xdr.c | 1 +
2 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 1176708..5a69ee6 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -714,7 +714,6 @@ release_session_client(struct nfsd4_session *session)
} else
renew_client_locked(clp);
spin_unlock(&client_lock);
- nfsd4_put_session(session);
}

/* must be called under the client_lock */
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index ac17a70..835924f 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -3325,6 +3325,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo
}
/* Renew the clientid on success and on replay */
release_session_client(cs->session);
+ nfsd4_put_session(cs->session);
}
return 1;
}
--
1.7.0.4


2010-06-24 16:29:10

by J.Bruce Fields

[permalink] [raw]
Subject: [PATCH 2/6] nfsd4: translate memory errors to delay, not serverfault

If the server is out of memory is better for clients to back off and
retry than to just error out.

Signed-off-by: J. Bruce Fields <[email protected]>
---
fs/nfsd/nfs4state.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 5a69ee6..603076f 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -457,7 +457,7 @@ static int set_forechannel_drc_size(struct nfsd4_channel_attrs *fchan)
spin_unlock(&nfsd_drc_lock);

if (fchan->maxreqs == 0)
- return nfserr_serverfault;
+ return nfserr_jukebox;

fchan->maxresp_cached = size + NFSD_MIN_HDR_SEQ_SZ;
return 0;
@@ -542,7 +542,7 @@ alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp,
BUILD_BUG_ON(NFSD_MAX_SLOTS_PER_SESSION * sizeof(struct nfsd4_slot)
+ sizeof(struct nfsd4_session) > PAGE_SIZE);

- status = nfserr_serverfault;
+ status = nfserr_jukebox;
/* allocate struct nfsd4_session and slot table pointers in one piece */
slotsize = tmp.se_fchannel.maxreqs * sizeof(struct nfsd4_slot *);
new = kzalloc(sizeof(*new) + slotsize, GFP_KERNEL);
@@ -1219,7 +1219,7 @@ out_new:
/* Normal case */
new = create_client(exid->clname, dname, rqstp, &verf);
if (new == NULL) {
- status = nfserr_serverfault;
+ status = nfserr_jukebox;
goto out;
}

--
1.7.0.4