aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/pnfs.c
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/nfs/pnfs.c
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/nfs/pnfs.c')
-rw-r--r--fs/nfs/pnfs.c79
1 files changed, 23 insertions, 56 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 6736f9e4f2e..08313f536b4 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}