summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4filelayout.c46
-rw-r--r--fs/nfs/nfs4filelayout.h8
-rw-r--r--fs/nfs/nfs4filelayoutdev.c106
-rw-r--r--fs/nfs/pnfs.c147
-rw-r--r--fs/nfs/pnfs.h48
-rw-r--r--include/linux/nfs_fs_sb.h1
6 files changed, 92 insertions, 264 deletions
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index 6a424c19abea..a922e75af42e 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -42,32 +42,6 @@ MODULE_DESCRIPTION("The NFSv4 file layout driver");
42 42
43#define FILELAYOUT_POLL_RETRY_MAX (15*HZ) 43#define FILELAYOUT_POLL_RETRY_MAX (15*HZ)
44 44
45static int
46filelayout_set_layoutdriver(struct nfs_server *nfss)
47{
48 int status = pnfs_alloc_init_deviceid_cache(nfss->nfs_client,
49 nfs4_fl_free_deviceid_callback);
50 if (status) {
51 printk(KERN_WARNING "%s: deviceid cache could not be "
52 "initialized\n", __func__);
53 return status;
54 }
55 dprintk("%s: deviceid cache has been initialized successfully\n",
56 __func__);
57 return 0;
58}
59
60/* Clear out the layout by destroying its device list */
61static int
62filelayout_clear_layoutdriver(struct nfs_server *nfss)
63{
64 dprintk("--> %s\n", __func__);
65
66 if (nfss->nfs_client->cl_devid_cache)
67 pnfs_put_deviceid_cache(nfss->nfs_client);
68 return 0;
69}
70
71static loff_t 45static loff_t
72filelayout_get_dense_offset(struct nfs4_filelayout_segment *flseg, 46filelayout_get_dense_offset(struct nfs4_filelayout_segment *flseg,
73 loff_t offset) 47 loff_t offset)
@@ -295,7 +269,7 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
295 } 269 }
296 270
297 /* find and reference the deviceid */ 271 /* find and reference the deviceid */
298 dsaddr = nfs4_fl_find_get_deviceid(nfss->nfs_client, id); 272 dsaddr = nfs4_fl_find_get_deviceid(id);
299 if (dsaddr == NULL) { 273 if (dsaddr == NULL) {
300 dsaddr = get_device_info(lo->plh_inode, id); 274 dsaddr = get_device_info(lo->plh_inode, id);
301 if (dsaddr == NULL) 275 if (dsaddr == NULL)
@@ -330,7 +304,7 @@ out:
330 dprintk("--> %s returns %d\n", __func__, status); 304 dprintk("--> %s returns %d\n", __func__, status);
331 return status; 305 return status;
332out_put: 306out_put:
333 pnfs_put_deviceid(nfss->nfs_client->cl_devid_cache, &dsaddr->deviceid); 307 nfs4_fl_put_deviceid(dsaddr);
334 goto out; 308 goto out;
335} 309}
336 310
@@ -439,12 +413,10 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
439static void 413static void
440filelayout_free_lseg(struct pnfs_layout_segment *lseg) 414filelayout_free_lseg(struct pnfs_layout_segment *lseg)
441{ 415{
442 struct nfs_server *nfss = NFS_SERVER(lseg->pls_layout->plh_inode);
443 struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); 416 struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg);
444 417
445 dprintk("--> %s\n", __func__); 418 dprintk("--> %s\n", __func__);
446 pnfs_put_deviceid(nfss->nfs_client->cl_devid_cache, 419 nfs4_fl_put_deviceid(fl->dsaddr);
447 &fl->dsaddr->deviceid);
448 _filelayout_free_lseg(fl); 420 _filelayout_free_lseg(fl);
449} 421}
450 422
@@ -474,13 +446,11 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
474} 446}
475 447
476static struct pnfs_layoutdriver_type filelayout_type = { 448static struct pnfs_layoutdriver_type filelayout_type = {
477 .id = LAYOUT_NFSV4_1_FILES, 449 .id = LAYOUT_NFSV4_1_FILES,
478 .name = "LAYOUT_NFSV4_1_FILES", 450 .name = "LAYOUT_NFSV4_1_FILES",
479 .owner = THIS_MODULE, 451 .owner = THIS_MODULE,
480 .set_layoutdriver = filelayout_set_layoutdriver, 452 .alloc_lseg = filelayout_alloc_lseg,
481 .clear_layoutdriver = filelayout_clear_layoutdriver, 453 .free_lseg = filelayout_free_lseg,
482 .alloc_lseg = filelayout_alloc_lseg,
483 .free_lseg = filelayout_free_lseg,
484 .pg_test = filelayout_pg_test, 454 .pg_test = filelayout_pg_test,
485 .read_pagelist = filelayout_read_pagelist, 455 .read_pagelist = filelayout_read_pagelist,
486}; 456};
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h
index 9fef76e04936..23f1e1e2a0f5 100644
--- a/fs/nfs/nfs4filelayout.h
+++ b/fs/nfs/nfs4filelayout.h
@@ -56,7 +56,9 @@ struct nfs4_pnfs_ds {
56}; 56};
57 57
58struct nfs4_file_layout_dsaddr { 58struct nfs4_file_layout_dsaddr {
59 struct pnfs_deviceid_node deviceid; 59 struct hlist_node node;
60 struct nfs4_deviceid deviceid;
61 atomic_t ref;
60 u32 stripe_count; 62 u32 stripe_count;
61 u8 *stripe_indices; 63 u8 *stripe_indices;
62 u32 ds_num; 64 u32 ds_num;
@@ -86,7 +88,6 @@ FILELAYOUT_LSEG(struct pnfs_layout_segment *lseg)
86extern struct nfs_fh * 88extern struct nfs_fh *
87nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j); 89nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j);
88 90
89extern void nfs4_fl_free_deviceid_callback(struct pnfs_deviceid_node *);
90extern void print_ds(struct nfs4_pnfs_ds *ds); 91extern void print_ds(struct nfs4_pnfs_ds *ds);
91extern void print_deviceid(struct nfs4_deviceid *dev_id); 92extern void print_deviceid(struct nfs4_deviceid *dev_id);
92u32 nfs4_fl_calc_j_index(struct pnfs_layout_segment *lseg, loff_t offset); 93u32 nfs4_fl_calc_j_index(struct pnfs_layout_segment *lseg, loff_t offset);
@@ -94,7 +95,8 @@ u32 nfs4_fl_calc_ds_index(struct pnfs_layout_segment *lseg, u32 j);
94struct nfs4_pnfs_ds *nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, 95struct nfs4_pnfs_ds *nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg,
95 u32 ds_idx); 96 u32 ds_idx);
96extern struct nfs4_file_layout_dsaddr * 97extern struct nfs4_file_layout_dsaddr *
97nfs4_fl_find_get_deviceid(struct nfs_client *, struct nfs4_deviceid *dev_id); 98nfs4_fl_find_get_deviceid(struct nfs4_deviceid *dev_id);
99extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr);
98struct nfs4_file_layout_dsaddr * 100struct nfs4_file_layout_dsaddr *
99get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id); 101get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id);
100 102
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
index f466fed2f466..f594ca35a996 100644
--- a/fs/nfs/nfs4filelayoutdev.c
+++ b/fs/nfs/nfs4filelayoutdev.c
@@ -37,6 +37,30 @@
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/*
40 * Data server cache 64 * Data server cache
41 * 65 *
42 * Data servers can be mapped to different device ids. 66 * Data servers can be mapped to different device ids.
@@ -183,7 +207,7 @@ nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
183 struct nfs4_pnfs_ds *ds; 207 struct nfs4_pnfs_ds *ds;
184 int i; 208 int i;
185 209
186 print_deviceid(&dsaddr->deviceid.de_id); 210 print_deviceid(&dsaddr->deviceid);
187 211
188 for (i = 0; i < dsaddr->ds_num; i++) { 212 for (i = 0; i < dsaddr->ds_num; i++) {
189 ds = dsaddr->ds_list[i]; 213 ds = dsaddr->ds_list[i];
@@ -200,15 +224,6 @@ nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
200 kfree(dsaddr); 224 kfree(dsaddr);
201} 225}
202 226
203void
204nfs4_fl_free_deviceid_callback(struct pnfs_deviceid_node *device)
205{
206 struct nfs4_file_layout_dsaddr *dsaddr =
207 container_of(device, struct nfs4_file_layout_dsaddr, deviceid);
208
209 nfs4_fl_free_deviceid(dsaddr);
210}
211
212static struct nfs4_pnfs_ds * 227static struct nfs4_pnfs_ds *
213nfs4_pnfs_ds_add(struct inode *inode, u32 ip_addr, u32 port) 228nfs4_pnfs_ds_add(struct inode *inode, u32 ip_addr, u32 port)
214{ 229{
@@ -361,7 +376,7 @@ decode_device(struct inode *ino, struct pnfs_device *pdev)
361 dsaddr->stripe_count = cnt; 376 dsaddr->stripe_count = cnt;
362 dsaddr->ds_num = num; 377 dsaddr->ds_num = num;
363 378
364 memcpy(&dsaddr->deviceid.de_id, &pdev->dev_id, sizeof(pdev->dev_id)); 379 memcpy(&dsaddr->deviceid, &pdev->dev_id, sizeof(pdev->dev_id));
365 380
366 /* Go back an read stripe indices */ 381 /* Go back an read stripe indices */
367 p = indicesp; 382 p = indicesp;
@@ -411,28 +426,37 @@ out_err:
411} 426}
412 427
413/* 428/*
414 * Decode the opaque device specified in 'dev' 429 * Decode the opaque device specified in 'dev' and add it to the cache of
415 * and add it to the list of available devices. 430 * available devices.
416 * If the deviceid is already cached, nfs4_add_deviceid will return
417 * a pointer to the cached struct and throw away the new.
418 */ 431 */
419static struct nfs4_file_layout_dsaddr* 432static struct nfs4_file_layout_dsaddr *
420decode_and_add_device(struct inode *inode, struct pnfs_device *dev) 433decode_and_add_device(struct inode *inode, struct pnfs_device *dev)
421{ 434{
422 struct nfs4_file_layout_dsaddr *dsaddr; 435 struct nfs4_file_layout_dsaddr *d, *new;
423 struct pnfs_deviceid_node *d; 436 long hash;
424 437
425 dsaddr = decode_device(inode, dev); 438 new = decode_device(inode, dev);
426 if (!dsaddr) { 439 if (!new) {
427 printk(KERN_WARNING "%s: Could not decode or add device\n", 440 printk(KERN_WARNING "%s: Could not decode or add device\n",
428 __func__); 441 __func__);
429 return NULL; 442 return NULL;
430 } 443 }
431 444
432 d = pnfs_add_deviceid(NFS_SERVER(inode)->nfs_client->cl_devid_cache, 445 spin_lock(&filelayout_deviceid_lock);
433 &dsaddr->deviceid); 446 d = nfs4_fl_find_get_deviceid(&new->deviceid);
447 if (d) {
448 spin_unlock(&filelayout_deviceid_lock);
449 nfs4_fl_free_deviceid(new);
450 return d;
451 }
452
453 INIT_HLIST_NODE(&new->node);
454 atomic_set(&new->ref, 1);
455 hash = nfs4_fl_deviceid_hash(&new->deviceid);
456 hlist_add_head_rcu(&new->node, &filelayout_deviceid_cache[hash]);
457 spin_unlock(&filelayout_deviceid_lock);
434 458
435 return container_of(d, struct nfs4_file_layout_dsaddr, deviceid); 459 return new;
436} 460}
437 461
438/* 462/*
@@ -507,14 +531,38 @@ out_free:
507 return dsaddr; 531 return dsaddr;
508} 532}
509 533
510struct nfs4_file_layout_dsaddr * 534void
511nfs4_fl_find_get_deviceid(struct nfs_client *clp, struct nfs4_deviceid *id) 535nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
512{ 536{
513 struct pnfs_deviceid_node *d; 537 if (atomic_dec_and_lock(&dsaddr->ref, &filelayout_deviceid_lock)) {
538 hlist_del_rcu(&dsaddr->node);
539 spin_unlock(&filelayout_deviceid_lock);
540
541 synchronize_rcu();
542 nfs4_fl_free_deviceid(dsaddr);
543 }
544}
514 545
515 d = pnfs_find_get_deviceid(clp->cl_devid_cache, id); 546struct nfs4_file_layout_dsaddr *
516 return (d == NULL) ? NULL : 547nfs4_fl_find_get_deviceid(struct nfs4_deviceid *id)
517 container_of(d, struct nfs4_file_layout_dsaddr, deviceid); 548{
549 struct nfs4_file_layout_dsaddr *d;
550 struct hlist_node *n;
551 long hash = nfs4_fl_deviceid_hash(id);
552
553
554 rcu_read_lock();
555 hlist_for_each_entry_rcu(d, n, &filelayout_deviceid_cache[hash], node) {
556 if (!memcmp(&d->deviceid, id, sizeof(*id))) {
557 if (!atomic_inc_not_zero(&d->ref))
558 goto fail;
559 rcu_read_unlock();
560 return d;
561 }
562 }
563fail:
564 rcu_read_unlock();
565 return NULL;
518} 566}
519 567
520/* 568/*
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 86c154bad5db..1f4c153441a1 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -75,10 +75,8 @@ find_pnfs_driver(u32 id)
75void 75void
76unset_pnfs_layoutdriver(struct nfs_server *nfss) 76unset_pnfs_layoutdriver(struct nfs_server *nfss)
77{ 77{
78 if (nfss->pnfs_curr_ld) { 78 if (nfss->pnfs_curr_ld)
79 nfss->pnfs_curr_ld->clear_layoutdriver(nfss);
80 module_put(nfss->pnfs_curr_ld->owner); 79 module_put(nfss->pnfs_curr_ld->owner);
81 }
82 nfss->pnfs_curr_ld = NULL; 80 nfss->pnfs_curr_ld = NULL;
83} 81}
84 82
@@ -116,13 +114,7 @@ set_pnfs_layoutdriver(struct nfs_server *server, u32 id)
116 goto out_no_driver; 114 goto out_no_driver;
117 } 115 }
118 server->pnfs_curr_ld = ld_type; 116 server->pnfs_curr_ld = ld_type;
119 if (ld_type->set_layoutdriver(server)) { 117
120 printk(KERN_ERR
121 "%s: Error initializing mount point for layout driver %u.\n",
122 __func__, id);
123 module_put(ld_type->owner);
124 goto out_no_driver;
125 }
126 dprintk("%s: pNFS module for %u set\n", __func__, id); 118 dprintk("%s: pNFS module for %u set\n", __func__, id);
127 return; 119 return;
128 120
@@ -906,138 +898,3 @@ pnfs_try_to_read_data(struct nfs_read_data *rdata,
906 dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs); 898 dprintk("%s End (trypnfs:%d)\n", __func__, trypnfs);
907 return trypnfs; 899 return trypnfs;
908} 900}
909
910/*
911 * Device ID cache. Currently supports one layout type per struct nfs_client.
912 * Add layout type to the lookup key to expand to support multiple types.
913 */
914int
915pnfs_alloc_init_deviceid_cache(struct nfs_client *clp,
916 void (*free_callback)(struct pnfs_deviceid_node *))
917{
918 struct pnfs_deviceid_cache *c;
919
920 c = kzalloc(sizeof(struct pnfs_deviceid_cache), GFP_KERNEL);
921 if (!c)
922 return -ENOMEM;
923 spin_lock(&clp->cl_lock);
924 if (clp->cl_devid_cache != NULL) {
925 atomic_inc(&clp->cl_devid_cache->dc_ref);
926 dprintk("%s [kref [%d]]\n", __func__,
927 atomic_read(&clp->cl_devid_cache->dc_ref));
928 kfree(c);
929 } else {
930 /* kzalloc initializes hlists */
931 spin_lock_init(&c->dc_lock);
932 atomic_set(&c->dc_ref, 1);
933 c->dc_free_callback = free_callback;
934 clp->cl_devid_cache = c;
935 dprintk("%s [new]\n", __func__);
936 }
937 spin_unlock(&clp->cl_lock);
938 return 0;
939}
940EXPORT_SYMBOL_GPL(pnfs_alloc_init_deviceid_cache);
941
942/*
943 * Called from pnfs_layoutdriver_type->free_lseg
944 * last layout segment reference frees deviceid
945 */
946void
947pnfs_put_deviceid(struct pnfs_deviceid_cache *c,
948 struct pnfs_deviceid_node *devid)
949{
950 struct nfs4_deviceid *id = &devid->de_id;
951 struct pnfs_deviceid_node *d;
952 struct hlist_node *n;
953 long h = nfs4_deviceid_hash(id);
954
955 dprintk("%s [%d]\n", __func__, atomic_read(&devid->de_ref));
956 if (!atomic_dec_and_lock(&devid->de_ref, &c->dc_lock))
957 return;
958
959 hlist_for_each_entry_rcu(d, n, &c->dc_deviceids[h], de_node)
960 if (!memcmp(&d->de_id, id, sizeof(*id))) {
961 hlist_del_rcu(&d->de_node);
962 spin_unlock(&c->dc_lock);
963 synchronize_rcu();
964 c->dc_free_callback(devid);
965 return;
966 }
967 spin_unlock(&c->dc_lock);
968 /* Why wasn't it found in the list? */
969 BUG();
970}
971EXPORT_SYMBOL_GPL(pnfs_put_deviceid);
972
973/* Find and reference a deviceid */
974struct pnfs_deviceid_node *
975pnfs_find_get_deviceid(struct pnfs_deviceid_cache *c, struct nfs4_deviceid *id)
976{
977 struct pnfs_deviceid_node *d;
978 struct hlist_node *n;
979 long hash = nfs4_deviceid_hash(id);
980
981 dprintk("--> %s hash %ld\n", __func__, hash);
982 rcu_read_lock();
983 hlist_for_each_entry_rcu(d, n, &c->dc_deviceids[hash], de_node) {
984 if (!memcmp(&d->de_id, id, sizeof(*id))) {
985 if (!atomic_inc_not_zero(&d->de_ref)) {
986 goto fail;
987 } else {
988 rcu_read_unlock();
989 return d;
990 }
991 }
992 }
993fail:
994 rcu_read_unlock();
995 return NULL;
996}
997EXPORT_SYMBOL_GPL(pnfs_find_get_deviceid);
998
999/*
1000 * Add a deviceid to the cache.
1001 * GETDEVICEINFOs for same deviceid can race. If deviceid is found, discard new
1002 */
1003struct pnfs_deviceid_node *
1004pnfs_add_deviceid(struct pnfs_deviceid_cache *c, struct pnfs_deviceid_node *new)
1005{
1006 struct pnfs_deviceid_node *d;
1007 long hash = nfs4_deviceid_hash(&new->de_id);
1008
1009 dprintk("--> %s hash %ld\n", __func__, hash);
1010 spin_lock(&c->dc_lock);
1011 d = pnfs_find_get_deviceid(c, &new->de_id);
1012 if (d) {
1013 spin_unlock(&c->dc_lock);
1014 dprintk("%s [discard]\n", __func__);
1015 c->dc_free_callback(new);
1016 return d;
1017 }
1018 INIT_HLIST_NODE(&new->de_node);
1019 atomic_set(&new->de_ref, 1);
1020 hlist_add_head_rcu(&new->de_node, &c->dc_deviceids[hash]);
1021 spin_unlock(&c->dc_lock);
1022 dprintk("%s [new]\n", __func__);
1023 return new;
1024}
1025EXPORT_SYMBOL_GPL(pnfs_add_deviceid);
1026
1027void
1028pnfs_put_deviceid_cache(struct nfs_client *clp)
1029{
1030 struct pnfs_deviceid_cache *local = clp->cl_devid_cache;
1031
1032 dprintk("--> %s ({%d})\n", __func__, atomic_read(&local->dc_ref));
1033 if (atomic_dec_and_lock(&local->dc_ref, &clp->cl_lock)) {
1034 int i;
1035 /* Verify cache is empty */
1036 for (i = 0; i < NFS4_DEVICE_ID_HASH_SIZE; i++)
1037 BUG_ON(!hlist_empty(&local->dc_deviceids[i]));
1038 clp->cl_devid_cache = NULL;
1039 spin_unlock(&clp->cl_lock);
1040 kfree(local);
1041 }
1042}
1043EXPORT_SYMBOL_GPL(pnfs_put_deviceid_cache);
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 585023fabb55..acbb77802075 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -68,8 +68,6 @@ struct pnfs_layoutdriver_type {
68 const u32 id; 68 const u32 id;
69 const char *name; 69 const char *name;
70 struct module *owner; 70 struct module *owner;
71 int (*set_layoutdriver) (struct nfs_server *);
72 int (*clear_layoutdriver) (struct nfs_server *);
73 struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr); 71 struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr);
74 void (*free_lseg) (struct pnfs_layout_segment *lseg); 72 void (*free_lseg) (struct pnfs_layout_segment *lseg);
75 73
@@ -106,52 +104,6 @@ struct pnfs_device {
106 unsigned int pglen; 104 unsigned int pglen;
107}; 105};
108 106
109/*
110 * Device ID RCU cache. A device ID is unique per client ID and layout type.
111 */
112#define NFS4_DEVICE_ID_HASH_BITS 5
113#define NFS4_DEVICE_ID_HASH_SIZE (1 << NFS4_DEVICE_ID_HASH_BITS)
114#define NFS4_DEVICE_ID_HASH_MASK (NFS4_DEVICE_ID_HASH_SIZE - 1)
115
116static inline u32
117nfs4_deviceid_hash(struct nfs4_deviceid *id)
118{
119 unsigned char *cptr = (unsigned char *)id->data;
120 unsigned int nbytes = NFS4_DEVICEID4_SIZE;
121 u32 x = 0;
122
123 while (nbytes--) {
124 x *= 37;
125 x += *cptr++;
126 }
127 return x & NFS4_DEVICE_ID_HASH_MASK;
128}
129
130struct pnfs_deviceid_node {
131 struct hlist_node de_node;
132 struct nfs4_deviceid de_id;
133 atomic_t de_ref;
134};
135
136struct pnfs_deviceid_cache {
137 spinlock_t dc_lock;
138 atomic_t dc_ref;
139 void (*dc_free_callback)(struct pnfs_deviceid_node *);
140 struct hlist_head dc_deviceids[NFS4_DEVICE_ID_HASH_SIZE];
141};
142
143extern int pnfs_alloc_init_deviceid_cache(struct nfs_client *,
144 void (*free_callback)(struct pnfs_deviceid_node *));
145extern void pnfs_put_deviceid_cache(struct nfs_client *);
146extern struct pnfs_deviceid_node *pnfs_find_get_deviceid(
147 struct pnfs_deviceid_cache *,
148 struct nfs4_deviceid *);
149extern struct pnfs_deviceid_node *pnfs_add_deviceid(
150 struct pnfs_deviceid_cache *,
151 struct pnfs_deviceid_node *);
152extern void pnfs_put_deviceid(struct pnfs_deviceid_cache *c,
153 struct pnfs_deviceid_node *devid);
154
155extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *); 107extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *);
156extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *); 108extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *);
157 109
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index c00d4ec47ec3..0cbf109a4056 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -77,7 +77,6 @@ struct nfs_client {
77 u32 cl_exchange_flags; 77 u32 cl_exchange_flags;
78 struct nfs4_session *cl_session; /* sharred session */ 78 struct nfs4_session *cl_session; /* sharred session */
79 struct list_head cl_layouts; 79 struct list_head cl_layouts;
80 struct pnfs_deviceid_cache *cl_devid_cache; /* pNFS deviceid cache */
81#endif /* CONFIG_NFS_V4 */ 80#endif /* CONFIG_NFS_V4 */
82 81
83#ifdef CONFIG_NFS_FSCACHE 82#ifdef CONFIG_NFS_FSCACHE