aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4filelayoutdev.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2011-02-28 20:34:21 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-03-11 15:38:43 -0500
commitea8eecdd11ee6becd09c095c8efa88aa7df95961 (patch)
tree4db9c584989d006790637e255657a010c8243cb9 /fs/nfs/nfs4filelayoutdev.c
parentcbdabc7f8bf14ca1d40ab1cb86f64b3bc09716e8 (diff)
NFSv4.1 move deviceid cache to filelayout driver
No need for generic cache with only one user. Keep a simple hash of deviceids in the filelayout driver. Signed-off-by: Christoph Hellwig <hch@infradead.org> Acked-by: Andy Adamson <andros@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4filelayoutdev.c')
-rw-r--r--fs/nfs/nfs4filelayoutdev.c106
1 files changed, 77 insertions, 29 deletions
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
index f466fed2f46..f594ca35a99 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/*