diff options
author | Benny Halevy <bhalevy@panasas.com> | 2011-05-19 22:14:47 -0400 |
---|---|---|
committer | Boaz Harrosh <bharrosh@panasas.com> | 2011-05-29 05:09:48 -0400 |
commit | a1eaecbc4c8307e27772d6584ef85a2e93250661 (patch) | |
tree | 940549d45db98a5bcfe22501de0bbe9c96de4c8e /fs/nfs/nfs4filelayoutdev.c | |
parent | 45df3c8b0f3a58facb125d7631890426706c0bfa (diff) |
NFSv4.1: make deviceid cache global
Move deviceid cache from the pnfs files layout driver to the
generic layer in preparation for the objects layout driver.
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
Diffstat (limited to 'fs/nfs/nfs4filelayoutdev.c')
-rw-r--r-- | fs/nfs/nfs4filelayoutdev.c | 104 |
1 files changed, 13 insertions, 91 deletions
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index 42e326637271..eda4527a57eb 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 | |||
46 | static inline u32 | ||
47 | nfs4_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 | |||
60 | static struct hlist_head filelayout_deviceid_cache[NFS4_FL_DEVICE_ID_HASH_SIZE]; | ||
61 | static 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 | ||
92 | void | ||
93 | print_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 | |||
105 | void 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 */ |
114 | static struct nfs4_pnfs_ds * | 69 | static struct nfs4_pnfs_ds * |
115 | _data_server_lookup_locked(u32 ip_addr, u32 port) | 70 | _data_server_lookup_locked(u32 ip_addr, u32 port) |
@@ -207,7 +162,7 @@ nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) | |||
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]; |
@@ -431,8 +386,8 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags) | |||
431 | dsaddr->stripe_indices = stripe_indices; | 386 | dsaddr->stripe_indices = stripe_indices; |
432 | stripe_indices = NULL; | 387 | stripe_indices = NULL; |
433 | dsaddr->ds_num = num; | 388 | dsaddr->ds_num = num; |
434 | dsaddr->nfs_client = NFS_SERVER(ino)->nfs_client; | 389 | nfs4_init_deviceid_node(&dsaddr->id_node, NFS_SERVER(ino)->nfs_client, |
435 | memcpy(&dsaddr->deviceid, &pdev->dev_id, sizeof(pdev->dev_id)); | 390 | &pdev->dev_id); |
436 | 391 | ||
437 | for (i = 0; i < dsaddr->ds_num; i++) { | 392 | for (i = 0; i < dsaddr->ds_num; i++) { |
438 | int j; | 393 | int j; |
@@ -505,8 +460,8 @@ out_err: | |||
505 | static struct nfs4_file_layout_dsaddr * | 460 | static struct nfs4_file_layout_dsaddr * |
506 | decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_flags) | 461 | decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_flags) |
507 | { | 462 | { |
508 | struct nfs4_file_layout_dsaddr *d, *new; | 463 | struct nfs4_deviceid_node *d; |
509 | long hash; | 464 | struct nfs4_file_layout_dsaddr *n, *new; |
510 | 465 | ||
511 | new = decode_device(inode, dev, gfp_flags); | 466 | new = decode_device(inode, dev, gfp_flags); |
512 | if (!new) { | 467 | if (!new) { |
@@ -515,20 +470,13 @@ decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_fl | |||
515 | return NULL; | 470 | return NULL; |
516 | } | 471 | } |
517 | 472 | ||
518 | spin_lock(&filelayout_deviceid_lock); | 473 | d = nfs4_insert_deviceid_node(&new->id_node); |
519 | d = nfs4_fl_find_get_deviceid(new->nfs_client, &new->deviceid); | 474 | n = container_of(d, struct nfs4_file_layout_dsaddr, id_node); |
520 | if (d) { | 475 | if (n != new) { |
521 | spin_unlock(&filelayout_deviceid_lock); | ||
522 | nfs4_fl_free_deviceid(new); | 476 | nfs4_fl_free_deviceid(new); |
523 | return d; | 477 | return n; |
524 | } | 478 | } |
525 | 479 | ||
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; | 480 | return new; |
533 | } | 481 | } |
534 | 482 | ||
@@ -600,34 +548,8 @@ out_free: | |||
600 | void | 548 | void |
601 | nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) | 549 | nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) |
602 | { | 550 | { |
603 | if (atomic_dec_and_lock(&dsaddr->ref, &filelayout_deviceid_lock)) { | 551 | if (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); | 552 | nfs4_fl_free_deviceid(dsaddr); |
609 | } | ||
610 | } | ||
611 | |||
612 | struct nfs4_file_layout_dsaddr * | ||
613 | nfs4_fl_find_get_deviceid(struct nfs_client *clp, 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 | rcu_read_lock(); | ||
620 | hlist_for_each_entry_rcu(d, n, &filelayout_deviceid_cache[hash], node) { | ||
621 | if (d->nfs_client == clp && !memcmp(&d->deviceid, id, sizeof(*id))) { | ||
622 | if (!atomic_inc_not_zero(&d->ref)) | ||
623 | goto fail; | ||
624 | rcu_read_unlock(); | ||
625 | return d; | ||
626 | } | ||
627 | } | ||
628 | fail: | ||
629 | rcu_read_unlock(); | ||
630 | return NULL; | ||
631 | } | 553 | } |
632 | 554 | ||
633 | /* | 555 | /* |
@@ -675,15 +597,15 @@ static void | |||
675 | filelayout_mark_devid_negative(struct nfs4_file_layout_dsaddr *dsaddr, | 597 | filelayout_mark_devid_negative(struct nfs4_file_layout_dsaddr *dsaddr, |
676 | int err, u32 ds_addr) | 598 | int err, u32 ds_addr) |
677 | { | 599 | { |
678 | u32 *p = (u32 *)&dsaddr->deviceid; | 600 | u32 *p = (u32 *)&dsaddr->id_node.deviceid; |
679 | 601 | ||
680 | printk(KERN_ERR "NFS: data server %x connection error %d." | 602 | printk(KERN_ERR "NFS: data server %x connection error %d." |
681 | " Deviceid [%x%x%x%x] marked out of use.\n", | 603 | " Deviceid [%x%x%x%x] marked out of use.\n", |
682 | ds_addr, err, p[0], p[1], p[2], p[3]); | 604 | ds_addr, err, p[0], p[1], p[2], p[3]); |
683 | 605 | ||
684 | spin_lock(&filelayout_deviceid_lock); | 606 | spin_lock(&nfs4_ds_cache_lock); |
685 | dsaddr->flags |= NFS4_DEVICE_ID_NEG_ENTRY; | 607 | dsaddr->flags |= NFS4_DEVICE_ID_NEG_ENTRY; |
686 | spin_unlock(&filelayout_deviceid_lock); | 608 | spin_unlock(&nfs4_ds_cache_lock); |
687 | } | 609 | } |
688 | 610 | ||
689 | struct nfs4_pnfs_ds * | 611 | struct nfs4_pnfs_ds * |