aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorFred Isaman <iisaman@netapp.com>2011-01-06 06:36:22 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-01-06 14:46:31 -0500
commitfd6002e9b8a93220d5f53b93d9624caf73cdc8a2 (patch)
treef45c22c9ec855949b1ec0488162229df4eb3f5ed /fs
parentb7edfaa1983362842351e425adeb8e297b4c11fb (diff)
pnfs: change layout state seqlock to a spinlock
This prepares for future changes, where the layout state needs to change atomically with several other variables. In particular, it will need to know if lo->segs is empty, as we test that instead of manipulating the NFS_LAYOUT_STATEID_SET bit. Moreover, the layoutstateid is not really a read-mostly structure, as it is written almost as often as it is read. The behavior of pnfs_get_layout_stateid is also slightly changed, so that it no longer changes the stateid. Its name is changed to +pnfs_choose_layoutget_stateid. Signed-off-by: Fred Isaman <iisaman@netapp.com> Signed-off-by: Benny Halevy <bhalevy@panasas.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/nfs4xdr.c2
-rw-r--r--fs/nfs/pnfs.c79
-rw-r--r--fs/nfs/pnfs.h7
3 files changed, 27 insertions, 61 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index f3f99156bfcb..4e28242360d6 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1798,7 +1798,7 @@ encode_layoutget(struct xdr_stream *xdr,
1798 p = xdr_encode_hyper(p, args->range.offset); 1798 p = xdr_encode_hyper(p, args->range.offset);
1799 p = xdr_encode_hyper(p, args->range.length); 1799 p = xdr_encode_hyper(p, args->range.length);
1800 p = xdr_encode_hyper(p, args->minlength); 1800 p = xdr_encode_hyper(p, args->minlength);
1801 pnfs_get_layout_stateid(&stateid, NFS_I(args->inode)->layout, 1801 pnfs_choose_layoutget_stateid(&stateid, NFS_I(args->inode)->layout,
1802 args->ctx->state); 1802 args->ctx->state);
1803 p = xdr_encode_opaque_fixed(p, &stateid.data, NFS4_STATEID_SIZE); 1803 p = xdr_encode_opaque_fixed(p, &stateid.data, NFS4_STATEID_SIZE);
1804 *p = cpu_to_be32(args->maxcount); 1804 *p = cpu_to_be32(args->maxcount);
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 6736f9e4f2e1..08313f536b45 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -258,9 +258,6 @@ pnfs_clear_lseg_list(struct pnfs_layout_hdr *lo, struct list_head *tmp_list)
258 /* List does not take a reference, so no need for put here */ 258 /* List does not take a reference, so no need for put here */
259 list_del_init(&lo->plh_layouts); 259 list_del_init(&lo->plh_layouts);
260 spin_unlock(&clp->cl_lock); 260 spin_unlock(&clp->cl_lock);
261 write_seqlock(&lo->plh_seqlock);
262 clear_bit(NFS_LAYOUT_STATEID_SET, &lo->plh_flags);
263 write_sequnlock(&lo->plh_seqlock);
264 261
265 dprintk("%s:Return\n", __func__); 262 dprintk("%s:Return\n", __func__);
266} 263}
@@ -319,69 +316,40 @@ pnfs_destroy_all_layouts(struct nfs_client *clp)
319 } 316 }
320} 317}
321 318
322/* update lo->plh_stateid with new if is more recent 319/* update lo->plh_stateid with new if is more recent */
323 *
324 * lo->plh_stateid could be the open stateid, in which case we just use what given.
325 */
326static void 320static void
327pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, 321pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo,
328 const nfs4_stateid *new) 322 const nfs4_stateid *new)
329{ 323{
330 nfs4_stateid *old = &lo->plh_stateid; 324 u32 oldseq, newseq;
331 bool overwrite = false;
332
333 write_seqlock(&lo->plh_seqlock);
334 if (!test_bit(NFS_LAYOUT_STATEID_SET, &lo->plh_flags) ||
335 memcmp(old->stateid.other, new->stateid.other, sizeof(new->stateid.other)))
336 overwrite = true;
337 else {
338 u32 oldseq, newseq;
339
340 oldseq = be32_to_cpu(old->stateid.seqid);
341 newseq = be32_to_cpu(new->stateid.seqid);
342 if ((int)(newseq - oldseq) > 0)
343 overwrite = true;
344 }
345 if (overwrite)
346 memcpy(&old->stateid, &new->stateid, sizeof(new->stateid));
347 write_sequnlock(&lo->plh_seqlock);
348}
349
350static void
351pnfs_layout_from_open_stateid(struct pnfs_layout_hdr *lo,
352 struct nfs4_state *state)
353{
354 int seq;
355 325
356 dprintk("--> %s\n", __func__); 326 oldseq = be32_to_cpu(lo->plh_stateid.stateid.seqid);
357 write_seqlock(&lo->plh_seqlock); 327 newseq = be32_to_cpu(new->stateid.seqid);
358 do { 328 if ((int)(newseq - oldseq) > 0)
359 seq = read_seqbegin(&state->seqlock); 329 memcpy(&lo->plh_stateid, &new->stateid, sizeof(new->stateid));
360 memcpy(lo->plh_stateid.data, state->stateid.data,
361 sizeof(state->stateid.data));
362 } while (read_seqretry(&state->seqlock, seq));
363 set_bit(NFS_LAYOUT_STATEID_SET, &lo->plh_flags);
364 write_sequnlock(&lo->plh_seqlock);
365 dprintk("<-- %s\n", __func__);
366} 330}
367 331
368void 332int
369pnfs_get_layout_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo, 333pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
370 struct nfs4_state *open_state) 334 struct nfs4_state *open_state)
371{ 335{
372 int seq; 336 int status = 0;
373 337
374 dprintk("--> %s\n", __func__); 338 dprintk("--> %s\n", __func__);
375 do { 339 spin_lock(&lo->plh_inode->i_lock);
376 seq = read_seqbegin(&lo->plh_seqlock); 340 if (list_empty(&lo->plh_segs)) {
377 if (!test_bit(NFS_LAYOUT_STATEID_SET, &lo->plh_flags)) { 341 int seq;
378 /* This will trigger retry of the read */ 342
379 pnfs_layout_from_open_stateid(lo, open_state); 343 do {
380 } else 344 seq = read_seqbegin(&open_state->seqlock);
381 memcpy(dst->data, lo->plh_stateid.data, 345 memcpy(dst->data, open_state->stateid.data,
382 sizeof(lo->plh_stateid.data)); 346 sizeof(open_state->stateid.data));
383 } while (read_seqretry(&lo->plh_seqlock, seq)); 347 } while (read_seqretry(&open_state->seqlock, seq));
348 } else
349 memcpy(dst->data, lo->plh_stateid.data, sizeof(lo->plh_stateid.data));
350 spin_unlock(&lo->plh_inode->i_lock);
384 dprintk("<-- %s\n", __func__); 351 dprintk("<-- %s\n", __func__);
352 return status;
385} 353}
386 354
387/* 355/*
@@ -496,7 +464,6 @@ alloc_init_layout_hdr(struct inode *ino)
496 lo->plh_refcount = 1; 464 lo->plh_refcount = 1;
497 INIT_LIST_HEAD(&lo->plh_layouts); 465 INIT_LIST_HEAD(&lo->plh_layouts);
498 INIT_LIST_HEAD(&lo->plh_segs); 466 INIT_LIST_HEAD(&lo->plh_segs);
499 seqlock_init(&lo->plh_seqlock);
500 lo->plh_inode = ino; 467 lo->plh_inode = ino;
501 return lo; 468 return lo;
502} 469}
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index c2f108640fc4..10937203d236 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -44,7 +44,6 @@ struct pnfs_layout_segment {
44enum { 44enum {
45 NFS_LAYOUT_RO_FAILED = 0, /* get ro layout failed stop trying */ 45 NFS_LAYOUT_RO_FAILED = 0, /* get ro layout failed stop trying */
46 NFS_LAYOUT_RW_FAILED, /* get rw layout failed stop trying */ 46 NFS_LAYOUT_RW_FAILED, /* get rw layout failed stop trying */
47 NFS_LAYOUT_STATEID_SET, /* have a valid layout stateid */
48}; 47};
49 48
50/* Per-layout driver specific registration structure */ 49/* Per-layout driver specific registration structure */
@@ -63,7 +62,6 @@ struct pnfs_layout_hdr {
63 unsigned long plh_refcount; 62 unsigned long plh_refcount;
64 struct list_head plh_layouts; /* other client layouts */ 63 struct list_head plh_layouts; /* other client layouts */
65 struct list_head plh_segs; /* layout segments list */ 64 struct list_head plh_segs; /* layout segments list */
66 seqlock_t plh_seqlock; /* Protects the stateid */
67 nfs4_stateid plh_stateid; 65 nfs4_stateid plh_stateid;
68 unsigned long plh_flags; 66 unsigned long plh_flags;
69 struct inode *plh_inode; 67 struct inode *plh_inode;
@@ -143,8 +141,9 @@ int pnfs_layout_process(struct nfs4_layoutget *lgp);
143void pnfs_destroy_layout(struct nfs_inode *); 141void pnfs_destroy_layout(struct nfs_inode *);
144void pnfs_destroy_all_layouts(struct nfs_client *); 142void pnfs_destroy_all_layouts(struct nfs_client *);
145void put_layout_hdr(struct inode *inode); 143void put_layout_hdr(struct inode *inode);
146void pnfs_get_layout_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo, 144int pnfs_choose_layoutget_stateid(nfs4_stateid *dst,
147 struct nfs4_state *open_state); 145 struct pnfs_layout_hdr *lo,
146 struct nfs4_state *open_state);
148 147
149 148
150static inline int lo_fail_bit(u32 iomode) 149static inline int lo_fail_bit(u32 iomode)