aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-04-20 19:24:51 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-04-20 23:14:28 -0400
commit95b72eb0bdef6476b7e73061f0382adf46c5495a (patch)
treedb1cbb01793ac5f744defb73e869373fefb7d0ce
parent98a2139f4f4d7b5fcc3a54c7fddbe88612abed20 (diff)
NFSv4: Ensure we do not reuse open owner names
The NFSv4 spec is ambiguous about whether or not it is permissible to reuse open owner names, so play it safe. This patch adds a timestamp to the state_owner structure, and combines that with the IDA based uniquifier. Fixes a regression whereby the Linux server returns NFS4ERR_BAD_SEQID. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/nfs4_fs.h1
-rw-r--r--fs/nfs/nfs4proc.c6
-rw-r--r--fs/nfs/nfs4state.c1
-rw-r--r--fs/nfs/nfs4xdr.c9
-rw-r--r--include/linux/nfs_xdr.h7
5 files changed, 16 insertions, 8 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 97ecc863dd76..b6db9e33fb7b 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -59,6 +59,7 @@ struct nfs_unique_id {
59 59
60#define NFS_SEQID_CONFIRMED 1 60#define NFS_SEQID_CONFIRMED 1
61struct nfs_seqid_counter { 61struct nfs_seqid_counter {
62 ktime_t create_time;
62 int owner_id; 63 int owner_id;
63 int flags; 64 int flags;
64 u32 counter; 65 u32 counter;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f875cf305237..60d5f4c26dda 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -838,7 +838,8 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry,
838 p->o_arg.open_flags = flags; 838 p->o_arg.open_flags = flags;
839 p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE); 839 p->o_arg.fmode = fmode & (FMODE_READ|FMODE_WRITE);
840 p->o_arg.clientid = server->nfs_client->cl_clientid; 840 p->o_arg.clientid = server->nfs_client->cl_clientid;
841 p->o_arg.id = sp->so_seqid.owner_id; 841 p->o_arg.id.create_time = ktime_to_ns(sp->so_seqid.create_time);
842 p->o_arg.id.uniquifier = sp->so_seqid.owner_id;
842 p->o_arg.name = &dentry->d_name; 843 p->o_arg.name = &dentry->d_name;
843 p->o_arg.server = server; 844 p->o_arg.server = server;
844 p->o_arg.bitmask = server->attr_bitmask; 845 p->o_arg.bitmask = server->attr_bitmask;
@@ -1466,8 +1467,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
1466 goto unlock_no_action; 1467 goto unlock_no_action;
1467 rcu_read_unlock(); 1468 rcu_read_unlock();
1468 } 1469 }
1469 /* Update sequence id. */ 1470 /* Update client id. */
1470 data->o_arg.id = sp->so_seqid.owner_id;
1471 data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid; 1471 data->o_arg.clientid = sp->so_server->nfs_client->cl_clientid;
1472 if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) { 1472 if (data->o_arg.claim == NFS4_OPEN_CLAIM_PREVIOUS) {
1473 task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; 1473 task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR];
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 0f43414eb25a..3b07f094f3a9 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -393,6 +393,7 @@ nfs4_remove_state_owner_locked(struct nfs4_state_owner *sp)
393static void 393static void
394nfs4_init_seqid_counter(struct nfs_seqid_counter *sc) 394nfs4_init_seqid_counter(struct nfs_seqid_counter *sc)
395{ 395{
396 sc->create_time = ktime_get();
396 sc->flags = 0; 397 sc->flags = 0;
397 sc->counter = 0; 398 sc->counter = 0;
398 spin_lock_init(&sc->lock); 399 spin_lock_init(&sc->lock);
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index c74fdb114b48..77fc5f959c4e 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -74,7 +74,7 @@ static int nfs4_stat_to_errno(int);
74/* lock,open owner id: 74/* lock,open owner id:
75 * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2) 75 * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2)
76 */ 76 */
77#define open_owner_id_maxsz (1 + 1 + 4) 77#define open_owner_id_maxsz (1 + 2 + 1 + 1 + 2)
78#define lock_owner_id_maxsz (1 + 1 + 4) 78#define lock_owner_id_maxsz (1 + 1 + 4)
79#define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) 79#define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
80#define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2)) 80#define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2))
@@ -1340,12 +1340,13 @@ static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_opena
1340 */ 1340 */
1341 encode_nfs4_seqid(xdr, arg->seqid); 1341 encode_nfs4_seqid(xdr, arg->seqid);
1342 encode_share_access(xdr, arg->fmode); 1342 encode_share_access(xdr, arg->fmode);
1343 p = reserve_space(xdr, 32); 1343 p = reserve_space(xdr, 36);
1344 p = xdr_encode_hyper(p, arg->clientid); 1344 p = xdr_encode_hyper(p, arg->clientid);
1345 *p++ = cpu_to_be32(20); 1345 *p++ = cpu_to_be32(24);
1346 p = xdr_encode_opaque_fixed(p, "open id:", 8); 1346 p = xdr_encode_opaque_fixed(p, "open id:", 8);
1347 *p++ = cpu_to_be32(arg->server->s_dev); 1347 *p++ = cpu_to_be32(arg->server->s_dev);
1348 xdr_encode_hyper(p, arg->id); 1348 *p++ = cpu_to_be32(arg->id.uniquifier);
1349 xdr_encode_hyper(p, arg->id.create_time);
1349} 1350}
1350 1351
1351static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg) 1352static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index bfd0d1bf6707..7ba3551a0414 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -312,6 +312,11 @@ struct nfs4_layoutreturn {
312 int rpc_status; 312 int rpc_status;
313}; 313};
314 314
315struct stateowner_id {
316 __u64 create_time;
317 __u32 uniquifier;
318};
319
315/* 320/*
316 * Arguments to the open call. 321 * Arguments to the open call.
317 */ 322 */
@@ -321,7 +326,7 @@ struct nfs_openargs {
321 int open_flags; 326 int open_flags;
322 fmode_t fmode; 327 fmode_t fmode;
323 __u64 clientid; 328 __u64 clientid;
324 __u64 id; 329 struct stateowner_id id;
325 union { 330 union {
326 struct { 331 struct {
327 struct iattr * attrs; /* UNCHECKED, GUARDED */ 332 struct iattr * attrs; /* UNCHECKED, GUARDED */