aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenny Halevy <bhalevy@panasas.com>2011-05-19 22:14:47 -0400
committerBoaz Harrosh <bharrosh@panasas.com>2011-05-29 05:09:48 -0400
commita1eaecbc4c8307e27772d6584ef85a2e93250661 (patch)
tree940549d45db98a5bcfe22501de0bbe9c96de4c8e
parent45df3c8b0f3a58facb125d7631890426706c0bfa (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>
-rw-r--r--fs/nfs/Makefile2
-rw-r--r--fs/nfs/nfs4filelayout.c10
-rw-r--r--fs/nfs/nfs4filelayout.h8
-rw-r--r--fs/nfs/nfs4filelayoutdev.c104
-rw-r--r--fs/nfs/pnfs.h17
-rw-r--r--fs/nfs/pnfs_dev.c156
6 files changed, 194 insertions, 103 deletions
diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile
index 4776ff9e3814..7516a8aaa42e 100644
--- a/fs/nfs/Makefile
+++ b/fs/nfs/Makefile
@@ -15,7 +15,7 @@ nfs-$(CONFIG_NFS_V4) += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
15 delegation.o idmap.o \ 15 delegation.o idmap.o \
16 callback.o callback_xdr.o callback_proc.o \ 16 callback.o callback_xdr.o callback_proc.o \
17 nfs4namespace.o 17 nfs4namespace.o
18nfs-$(CONFIG_NFS_V4_1) += pnfs.o 18nfs-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o
19nfs-$(CONFIG_SYSCTL) += sysctl.o 19nfs-$(CONFIG_SYSCTL) += sysctl.o
20nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o 20nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
21 21
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index 571c1b032e9d..4c67a6f6519d 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -421,6 +421,7 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
421 struct nfs4_deviceid *id, 421 struct nfs4_deviceid *id,
422 gfp_t gfp_flags) 422 gfp_t gfp_flags)
423{ 423{
424 struct nfs4_deviceid_node *d;
424 struct nfs4_file_layout_dsaddr *dsaddr; 425 struct nfs4_file_layout_dsaddr *dsaddr;
425 int status = -EINVAL; 426 int status = -EINVAL;
426 struct nfs_server *nfss = NFS_SERVER(lo->plh_inode); 427 struct nfs_server *nfss = NFS_SERVER(lo->plh_inode);
@@ -440,12 +441,13 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
440 } 441 }
441 442
442 /* find and reference the deviceid */ 443 /* find and reference the deviceid */
443 dsaddr = nfs4_fl_find_get_deviceid(NFS_SERVER(lo->plh_inode)->nfs_client, id); 444 d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode)->nfs_client, id);
444 if (dsaddr == NULL) { 445 if (d == NULL) {
445 dsaddr = get_device_info(lo->plh_inode, id, gfp_flags); 446 dsaddr = get_device_info(lo->plh_inode, id, gfp_flags);
446 if (dsaddr == NULL) 447 if (dsaddr == NULL)
447 goto out; 448 goto out;
448 } 449 } else
450 dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node);
449 fl->dsaddr = dsaddr; 451 fl->dsaddr = dsaddr;
450 452
451 if (fl->first_stripe_index < 0 || 453 if (fl->first_stripe_index < 0 ||
@@ -535,7 +537,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
535 537
536 memcpy(id, p, sizeof(*id)); 538 memcpy(id, p, sizeof(*id));
537 p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE); 539 p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE);
538 print_deviceid(id); 540 nfs4_print_deviceid(id);
539 541
540 nfl_util = be32_to_cpup(p++); 542 nfl_util = be32_to_cpup(p++);
541 if (nfl_util & NFL4_UFLG_COMMIT_THRU_MDS) 543 if (nfl_util & NFL4_UFLG_COMMIT_THRU_MDS)
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h
index 301b95568bd2..0ace0a2d6d7d 100644
--- a/fs/nfs/nfs4filelayout.h
+++ b/fs/nfs/nfs4filelayout.h
@@ -59,10 +59,7 @@ struct nfs4_pnfs_ds {
59#define NFS4_DEVICE_ID_NEG_ENTRY 0x00000001 59#define NFS4_DEVICE_ID_NEG_ENTRY 0x00000001
60 60
61struct nfs4_file_layout_dsaddr { 61struct nfs4_file_layout_dsaddr {
62 struct hlist_node node; 62 struct nfs4_deviceid_node id_node;
63 struct nfs_client *nfs_client;
64 struct nfs4_deviceid deviceid;
65 atomic_t ref;
66 unsigned long flags; 63 unsigned long flags;
67 u32 stripe_count; 64 u32 stripe_count;
68 u8 *stripe_indices; 65 u8 *stripe_indices;
@@ -96,13 +93,10 @@ extern struct nfs_fh *
96nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j); 93nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j);
97 94
98extern void print_ds(struct nfs4_pnfs_ds *ds); 95extern void print_ds(struct nfs4_pnfs_ds *ds);
99extern void print_deviceid(struct nfs4_deviceid *dev_id);
100u32 nfs4_fl_calc_j_index(struct pnfs_layout_segment *lseg, loff_t offset); 96u32 nfs4_fl_calc_j_index(struct pnfs_layout_segment *lseg, loff_t offset);
101u32 nfs4_fl_calc_ds_index(struct pnfs_layout_segment *lseg, u32 j); 97u32 nfs4_fl_calc_ds_index(struct pnfs_layout_segment *lseg, u32 j);
102struct nfs4_pnfs_ds *nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, 98struct nfs4_pnfs_ds *nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg,
103 u32 ds_idx); 99 u32 ds_idx);
104extern struct nfs4_file_layout_dsaddr *
105nfs4_fl_find_get_deviceid(struct nfs_client *, struct nfs4_deviceid *dev_id);
106extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); 100extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr);
107struct nfs4_file_layout_dsaddr * 101struct nfs4_file_layout_dsaddr *
108get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags); 102get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags);
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
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)
@@ -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:
505static struct nfs4_file_layout_dsaddr * 460static struct nfs4_file_layout_dsaddr *
506decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_flags) 461decode_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:
600void 548void
601nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) 549nfs4_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
612struct nfs4_file_layout_dsaddr *
613nfs4_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 }
628fail:
629 rcu_read_unlock();
630 return NULL;
631} 553}
632 554
633/* 555/*
@@ -675,15 +597,15 @@ static void
675filelayout_mark_devid_negative(struct nfs4_file_layout_dsaddr *dsaddr, 597filelayout_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
689struct nfs4_pnfs_ds * 611struct nfs4_pnfs_ds *
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 720bb9da3f9b..3831ad04a231 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -157,6 +157,23 @@ bool pnfs_roc_drain(struct inode *ino, u32 *barrier);
157void pnfs_set_layoutcommit(struct nfs_write_data *wdata); 157void pnfs_set_layoutcommit(struct nfs_write_data *wdata);
158int pnfs_layoutcommit_inode(struct inode *inode, bool sync); 158int pnfs_layoutcommit_inode(struct inode *inode, bool sync);
159 159
160/* pnfs_dev.c */
161struct nfs4_deviceid_node {
162 struct hlist_node node;
163 const struct nfs_client *nfs_client;
164 struct nfs4_deviceid deviceid;
165 atomic_t ref;
166};
167
168void nfs4_print_deviceid(const struct nfs4_deviceid *dev_id);
169struct nfs4_deviceid_node *nfs4_find_get_deviceid(const struct nfs_client *, const struct nfs4_deviceid *);
170struct nfs4_deviceid_node *nfs4_unhash_put_deviceid(const struct nfs_client *, const struct nfs4_deviceid *);
171void nfs4_init_deviceid_node(struct nfs4_deviceid_node *,
172 const struct nfs_client *,
173 const struct nfs4_deviceid *);
174struct nfs4_deviceid_node *nfs4_insert_deviceid_node(struct nfs4_deviceid_node *);
175bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *);
176
160static inline int lo_fail_bit(u32 iomode) 177static inline int lo_fail_bit(u32 iomode)
161{ 178{
162 return iomode == IOMODE_RW ? 179 return iomode == IOMODE_RW ?
diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c
new file mode 100644
index 000000000000..bf05189a7cbf
--- /dev/null
+++ b/fs/nfs/pnfs_dev.c
@@ -0,0 +1,156 @@
1/*
2 * Device operations for the pnfs client.
3 *
4 * Copyright (c) 2002
5 * The Regents of the University of Michigan
6 * All Rights Reserved
7 *
8 * Dean Hildebrand <dhildebz@umich.edu>
9 * Garth Goodson <Garth.Goodson@netapp.com>
10 *
11 * Permission is granted to use, copy, create derivative works, and
12 * redistribute this software and such derivative works for any purpose,
13 * so long as the name of the University of Michigan is not used in
14 * any advertising or publicity pertaining to the use or distribution
15 * of this software without specific, written prior authorization. If
16 * the above copyright notice or any other identification of the
17 * University of Michigan is included in any copy of any portion of
18 * this software, then the disclaimer below must also be included.
19 *
20 * This software is provided as is, without representation or warranty
21 * of any kind either express or implied, including without limitation
22 * the implied warranties of merchantability, fitness for a particular
23 * purpose, or noninfringement. The Regents of the University of
24 * Michigan shall not be liable for any damages, including special,
25 * indirect, incidental, or consequential damages, with respect to any
26 * claim arising out of or in connection with the use of the software,
27 * even if it has been or is hereafter advised of the possibility of
28 * such damages.
29 */
30
31#include "pnfs.h"
32
33#define NFSDBG_FACILITY NFSDBG_PNFS
34
35/*
36 * Device ID RCU cache. A device ID is unique per server and layout type.
37 */
38#define NFS4_DEVICE_ID_HASH_BITS 5
39#define NFS4_DEVICE_ID_HASH_SIZE (1 << NFS4_DEVICE_ID_HASH_BITS)
40#define NFS4_DEVICE_ID_HASH_MASK (NFS4_DEVICE_ID_HASH_SIZE - 1)
41
42static struct hlist_head nfs4_deviceid_cache[NFS4_DEVICE_ID_HASH_SIZE];
43static DEFINE_SPINLOCK(nfs4_deviceid_lock);
44
45void
46nfs4_print_deviceid(const struct nfs4_deviceid *id)
47{
48 u32 *p = (u32 *)id;
49
50 dprintk("%s: device id= [%x%x%x%x]\n", __func__,
51 p[0], p[1], p[2], p[3]);
52}
53EXPORT_SYMBOL_GPL(nfs4_print_deviceid);
54
55static inline u32
56nfs4_deviceid_hash(const struct nfs4_deviceid *id)
57{
58 unsigned char *cptr = (unsigned char *)id->data;
59 unsigned int nbytes = NFS4_DEVICEID4_SIZE;
60 u32 x = 0;
61
62 while (nbytes--) {
63 x *= 37;
64 x += *cptr++;
65 }
66 return x & NFS4_DEVICE_ID_HASH_MASK;
67}
68
69/*
70 * Lookup a deviceid in cache and get a reference count on it if found
71 *
72 * @clp nfs_client associated with deviceid
73 * @id deviceid to look up
74 */
75struct nfs4_deviceid_node *
76nfs4_find_get_deviceid(const struct nfs_client *clp, const struct nfs4_deviceid *id)
77{
78 struct nfs4_deviceid_node *d;
79 struct hlist_node *n;
80 long hash = nfs4_deviceid_hash(id);
81
82 rcu_read_lock();
83 hlist_for_each_entry_rcu(d, n, &nfs4_deviceid_cache[hash], node) {
84 if (d->nfs_client == clp && !memcmp(&d->deviceid, id, sizeof(*id))) {
85 if (!atomic_inc_not_zero(&d->ref))
86 goto fail;
87 rcu_read_unlock();
88 return d;
89 }
90 }
91fail:
92 rcu_read_unlock();
93 return NULL;
94}
95EXPORT_SYMBOL_GPL(nfs4_find_get_deviceid);
96
97void
98nfs4_init_deviceid_node(struct nfs4_deviceid_node *d,
99 const struct nfs_client *nfs_client,
100 const struct nfs4_deviceid *id)
101{
102 d->nfs_client = nfs_client;
103 d->deviceid = *id;
104}
105EXPORT_SYMBOL_GPL(nfs4_init_deviceid_node);
106
107/*
108 * Uniquely initialize and insert a deviceid node into cache
109 *
110 * @new new deviceid node
111 * Note that the caller must set up new->nfs_client and new->deviceid
112 *
113 * @ret the inserted node, if none found, otherwise, the found entry.
114 */
115struct nfs4_deviceid_node *
116nfs4_insert_deviceid_node(struct nfs4_deviceid_node *new)
117{
118 struct nfs4_deviceid_node *d;
119 long hash;
120
121 spin_lock(&nfs4_deviceid_lock);
122 d = nfs4_find_get_deviceid(new->nfs_client, &new->deviceid);
123 if (d) {
124 spin_unlock(&nfs4_deviceid_lock);
125 return d;
126 }
127
128 INIT_HLIST_NODE(&new->node);
129 atomic_set(&new->ref, 1);
130 hash = nfs4_deviceid_hash(&new->deviceid);
131 hlist_add_head_rcu(&new->node, &nfs4_deviceid_cache[hash]);
132 spin_unlock(&nfs4_deviceid_lock);
133
134 return new;
135}
136EXPORT_SYMBOL_GPL(nfs4_insert_deviceid_node);
137
138/*
139 * Dereference a deviceid node and delete it when its reference count drops
140 * to zero.
141 *
142 * @d deviceid node to put
143 *
144 * @ret true iff the node was deleted
145 */
146bool
147nfs4_put_deviceid_node(struct nfs4_deviceid_node *d)
148{
149 if (!atomic_dec_and_lock(&d->ref, &nfs4_deviceid_lock))
150 return false;
151 hlist_del_init_rcu(&d->node);
152 spin_unlock(&nfs4_deviceid_lock);
153 synchronize_rcu();
154 return true;
155}
156EXPORT_SYMBOL_GPL(nfs4_put_deviceid_node);