aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4filelayoutdev.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-05-29 17:10:13 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-05-29 17:10:13 -0400
commitcd1acdf1723d71b28175f95b04305f1cc74ce363 (patch)
tree7ab58883eccd314be3d8efafd59a124d4ffbb861 /fs/nfs/nfs4filelayoutdev.c
parentfac04863cef53a69830590b2e1c54345068a9747 (diff)
parent9342077011d54f42fa1b88b7bc1f7008dcf5fff9 (diff)
Merge branch 'pnfs-submit' of git://git.open-osd.org/linux-open-osd
* 'pnfs-submit' of git://git.open-osd.org/linux-open-osd: (32 commits) pnfs-obj: pg_test check for max_io_size NFSv4.1: define nfs_generic_pg_test NFSv4.1: use pnfs_generic_pg_test directly by layout driver NFSv4.1: change pg_test return type to bool NFSv4.1: unify pnfs_pageio_init functions pnfs-obj: objlayout_encode_layoutcommit implementation pnfs: encode_layoutcommit pnfs-obj: report errors and .encode_layoutreturn Implementation. pnfs: encode_layoutreturn pnfs: layoutret_on_setattr pnfs: layoutreturn pnfs-obj: osd raid engine read/write implementation pnfs: support for non-rpc layout drivers pnfs-obj: define per-inode private structure pnfs: alloc and free layout_hdr layoutdriver methods pnfs-obj: objio_osd device information retrieval and caching pnfs-obj: decode layout, alloc/free lseg pnfs-obj: pnfs_osd XDR client implementation pnfs-obj: pnfs_osd XDR definitions pnfs-obj: objlayoutdriver module skeleton ...
Diffstat (limited to 'fs/nfs/nfs4filelayoutdev.c')
-rw-r--r--fs/nfs/nfs4filelayoutdev.c119
1 files changed, 18 insertions, 101 deletions
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
index db07c7af1395..3b7bf1377264 100644
--- a/fs/nfs/nfs4filelayoutdev.c
+++ b/fs/nfs/nfs4filelayoutdev.c
@@ -37,30 +37,6 @@
37#define NFSDBG_FACILITY NFSDBG_PNFS_LD 37#define NFSDBG_FACILITY NFSDBG_PNFS_LD
38 38
39/* 39/*
40 * Device ID RCU cache. A device ID is unique per client ID and layout type.
41 */
42#define NFS4_FL_DEVICE_ID_HASH_BITS 5
43#define NFS4_FL_DEVICE_ID_HASH_SIZE (1 << NFS4_FL_DEVICE_ID_HASH_BITS)
44#define NFS4_FL_DEVICE_ID_HASH_MASK (NFS4_FL_DEVICE_ID_HASH_SIZE - 1)
45
46static inline u32
47nfs4_fl_deviceid_hash(struct nfs4_deviceid *id)
48{
49 unsigned char *cptr = (unsigned char *)id->data;
50 unsigned int nbytes = NFS4_DEVICEID4_SIZE;
51 u32 x = 0;
52
53 while (nbytes--) {
54 x *= 37;
55 x += *cptr++;
56 }
57 return x & NFS4_FL_DEVICE_ID_HASH_MASK;
58}
59
60static struct hlist_head filelayout_deviceid_cache[NFS4_FL_DEVICE_ID_HASH_SIZE];
61static DEFINE_SPINLOCK(filelayout_deviceid_lock);
62
63/*
64 * Data server cache 40 * Data server cache
65 * 41 *
66 * Data servers can be mapped to different device ids. 42 * Data servers can be mapped to different device ids.
@@ -89,27 +65,6 @@ print_ds(struct nfs4_pnfs_ds *ds)
89 ds->ds_clp ? ds->ds_clp->cl_exchange_flags : 0); 65 ds->ds_clp ? ds->ds_clp->cl_exchange_flags : 0);
90} 66}
91 67
92void
93print_ds_list(struct nfs4_file_layout_dsaddr *dsaddr)
94{
95 int i;
96
97 ifdebug(FACILITY) {
98 printk("%s dsaddr->ds_num %d\n", __func__,
99 dsaddr->ds_num);
100 for (i = 0; i < dsaddr->ds_num; i++)
101 print_ds(dsaddr->ds_list[i]);
102 }
103}
104
105void print_deviceid(struct nfs4_deviceid *id)
106{
107 u32 *p = (u32 *)id;
108
109 dprintk("%s: device id= [%x%x%x%x]\n", __func__,
110 p[0], p[1], p[2], p[3]);
111}
112
113/* nfs4_ds_cache_lock is held */ 68/* nfs4_ds_cache_lock is held */
114static struct nfs4_pnfs_ds * 69static struct nfs4_pnfs_ds *
115_data_server_lookup_locked(u32 ip_addr, u32 port) 70_data_server_lookup_locked(u32 ip_addr, u32 port)
@@ -201,13 +156,13 @@ destroy_ds(struct nfs4_pnfs_ds *ds)
201 kfree(ds); 156 kfree(ds);
202} 157}
203 158
204static void 159void
205nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) 160nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
206{ 161{
207 struct nfs4_pnfs_ds *ds; 162 struct nfs4_pnfs_ds *ds;
208 int i; 163 int i;
209 164
210 print_deviceid(&dsaddr->deviceid); 165 nfs4_print_deviceid(&dsaddr->id_node.deviceid);
211 166
212 for (i = 0; i < dsaddr->ds_num; i++) { 167 for (i = 0; i < dsaddr->ds_num; i++) {
213 ds = dsaddr->ds_list[i]; 168 ds = dsaddr->ds_list[i];
@@ -353,12 +308,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags)
353 u8 max_stripe_index; 308 u8 max_stripe_index;
354 struct nfs4_file_layout_dsaddr *dsaddr = NULL; 309 struct nfs4_file_layout_dsaddr *dsaddr = NULL;
355 struct xdr_stream stream; 310 struct xdr_stream stream;
356 struct xdr_buf buf = { 311 struct xdr_buf buf;
357 .pages = pdev->pages,
358 .page_len = pdev->pglen,
359 .buflen = pdev->pglen,
360 .len = pdev->pglen,
361 };
362 struct page *scratch; 312 struct page *scratch;
363 313
364 /* set up xdr stream */ 314 /* set up xdr stream */
@@ -366,7 +316,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags)
366 if (!scratch) 316 if (!scratch)
367 goto out_err; 317 goto out_err;
368 318
369 xdr_init_decode(&stream, &buf, NULL); 319 xdr_init_decode_pages(&stream, &buf, pdev->pages, pdev->pglen);
370 xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE); 320 xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
371 321
372 /* Get the stripe count (number of stripe index) */ 322 /* Get the stripe count (number of stripe index) */
@@ -431,8 +381,10 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags)
431 dsaddr->stripe_indices = stripe_indices; 381 dsaddr->stripe_indices = stripe_indices;
432 stripe_indices = NULL; 382 stripe_indices = NULL;
433 dsaddr->ds_num = num; 383 dsaddr->ds_num = num;
434 384 nfs4_init_deviceid_node(&dsaddr->id_node,
435 memcpy(&dsaddr->deviceid, &pdev->dev_id, sizeof(pdev->dev_id)); 385 NFS_SERVER(ino)->pnfs_curr_ld,
386 NFS_SERVER(ino)->nfs_client,
387 &pdev->dev_id);
436 388
437 for (i = 0; i < dsaddr->ds_num; i++) { 389 for (i = 0; i < dsaddr->ds_num; i++) {
438 int j; 390 int j;
@@ -505,8 +457,8 @@ out_err:
505static struct nfs4_file_layout_dsaddr * 457static struct nfs4_file_layout_dsaddr *
506decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_flags) 458decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_flags)
507{ 459{
508 struct nfs4_file_layout_dsaddr *d, *new; 460 struct nfs4_deviceid_node *d;
509 long hash; 461 struct nfs4_file_layout_dsaddr *n, *new;
510 462
511 new = decode_device(inode, dev, gfp_flags); 463 new = decode_device(inode, dev, gfp_flags);
512 if (!new) { 464 if (!new) {
@@ -515,20 +467,13 @@ decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_fl
515 return NULL; 467 return NULL;
516 } 468 }
517 469
518 spin_lock(&filelayout_deviceid_lock); 470 d = nfs4_insert_deviceid_node(&new->id_node);
519 d = nfs4_fl_find_get_deviceid(&new->deviceid); 471 n = container_of(d, struct nfs4_file_layout_dsaddr, id_node);
520 if (d) { 472 if (n != new) {
521 spin_unlock(&filelayout_deviceid_lock);
522 nfs4_fl_free_deviceid(new); 473 nfs4_fl_free_deviceid(new);
523 return d; 474 return n;
524 } 475 }
525 476
526 INIT_HLIST_NODE(&new->node);
527 atomic_set(&new->ref, 1);
528 hash = nfs4_fl_deviceid_hash(&new->deviceid);
529 hlist_add_head_rcu(&new->node, &filelayout_deviceid_cache[hash]);
530 spin_unlock(&filelayout_deviceid_lock);
531
532 return new; 477 return new;
533} 478}
534 479
@@ -600,35 +545,7 @@ out_free:
600void 545void
601nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) 546nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
602{ 547{
603 if (atomic_dec_and_lock(&dsaddr->ref, &filelayout_deviceid_lock)) { 548 nfs4_put_deviceid_node(&dsaddr->id_node);
604 hlist_del_rcu(&dsaddr->node);
605 spin_unlock(&filelayout_deviceid_lock);
606
607 synchronize_rcu();
608 nfs4_fl_free_deviceid(dsaddr);
609 }
610}
611
612struct nfs4_file_layout_dsaddr *
613nfs4_fl_find_get_deviceid(struct nfs4_deviceid *id)
614{
615 struct nfs4_file_layout_dsaddr *d;
616 struct hlist_node *n;
617 long hash = nfs4_fl_deviceid_hash(id);
618
619
620 rcu_read_lock();
621 hlist_for_each_entry_rcu(d, n, &filelayout_deviceid_cache[hash], node) {
622 if (!memcmp(&d->deviceid, id, sizeof(*id))) {
623 if (!atomic_inc_not_zero(&d->ref))
624 goto fail;
625 rcu_read_unlock();
626 return d;
627 }
628 }
629fail:
630 rcu_read_unlock();
631 return NULL;
632} 549}
633 550
634/* 551/*
@@ -676,15 +593,15 @@ static void
676filelayout_mark_devid_negative(struct nfs4_file_layout_dsaddr *dsaddr, 593filelayout_mark_devid_negative(struct nfs4_file_layout_dsaddr *dsaddr,
677 int err, u32 ds_addr) 594 int err, u32 ds_addr)
678{ 595{
679 u32 *p = (u32 *)&dsaddr->deviceid; 596 u32 *p = (u32 *)&dsaddr->id_node.deviceid;
680 597
681 printk(KERN_ERR "NFS: data server %x connection error %d." 598 printk(KERN_ERR "NFS: data server %x connection error %d."
682 " Deviceid [%x%x%x%x] marked out of use.\n", 599 " Deviceid [%x%x%x%x] marked out of use.\n",
683 ds_addr, err, p[0], p[1], p[2], p[3]); 600 ds_addr, err, p[0], p[1], p[2], p[3]);
684 601
685 spin_lock(&filelayout_deviceid_lock); 602 spin_lock(&nfs4_ds_cache_lock);
686 dsaddr->flags |= NFS4_DEVICE_ID_NEG_ENTRY; 603 dsaddr->flags |= NFS4_DEVICE_ID_NEG_ENTRY;
687 spin_unlock(&filelayout_deviceid_lock); 604 spin_unlock(&nfs4_ds_cache_lock);
688} 605}
689 606
690struct nfs4_pnfs_ds * 607struct nfs4_pnfs_ds *