diff options
author | Benny Halevy <bhalevy@panasas.com> | 2011-05-20 07:47:33 -0400 |
---|---|---|
committer | Boaz Harrosh <bharrosh@panasas.com> | 2011-05-29 13:50:42 -0400 |
commit | 1775bc342c6eacd6304493cbb2e0cda1a0182246 (patch) | |
tree | b0a884a41f565a41957524146ff6ee51b2b7db7b | |
parent | a1eaecbc4c8307e27772d6584ef85a2e93250661 (diff) |
NFSv4.1: purge deviceid cache on nfs_free_client
Use the pnfs_layoutdriver_type both as a qualifier for the deviceid,
distinguishing deviceid from different layout types on the server,
and for freeing the layout-driver allocated structure containing the
nfs4_deviceid_node.
[BUG in _deviceid_purge_client]
[layout_driver MUST set free_deviceid_node if using dev-cache]
[let ver < 4.1 compile]
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
[removed EXPORT_SYMBOL_GPL(nfs4_deviceid_purge_client)]
Signed-off-by: Benny Halevy <bhalevy@panasas.com>
-rw-r--r-- | fs/nfs/client.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 7 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayout.h | 1 | ||||
-rw-r--r-- | fs/nfs/nfs4filelayoutdev.c | 9 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 11 | ||||
-rw-r--r-- | fs/nfs/pnfs_dev.c | 47 |
6 files changed, 70 insertions, 7 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 139be9647d80..b3dc2b88b65b 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -290,6 +290,8 @@ static void nfs_free_client(struct nfs_client *clp) | |||
290 | if (clp->cl_machine_cred != NULL) | 290 | if (clp->cl_machine_cred != NULL) |
291 | put_rpccred(clp->cl_machine_cred); | 291 | put_rpccred(clp->cl_machine_cred); |
292 | 292 | ||
293 | nfs4_deviceid_purge_client(clp); | ||
294 | |||
293 | kfree(clp->cl_hostname); | 295 | kfree(clp->cl_hostname); |
294 | kfree(clp); | 296 | kfree(clp); |
295 | 297 | ||
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 4c67a6f6519d..cd289d9b7de7 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -862,6 +862,12 @@ filelayout_commit_pagelist(struct inode *inode, struct list_head *mds_pages, | |||
862 | return -ENOMEM; | 862 | return -ENOMEM; |
863 | } | 863 | } |
864 | 864 | ||
865 | static void | ||
866 | filelayout_free_deveiceid_node(struct nfs4_deviceid_node *d) | ||
867 | { | ||
868 | nfs4_fl_free_deviceid(container_of(d, struct nfs4_file_layout_dsaddr, id_node)); | ||
869 | } | ||
870 | |||
865 | static struct pnfs_layoutdriver_type filelayout_type = { | 871 | static struct pnfs_layoutdriver_type filelayout_type = { |
866 | .id = LAYOUT_NFSV4_1_FILES, | 872 | .id = LAYOUT_NFSV4_1_FILES, |
867 | .name = "LAYOUT_NFSV4_1_FILES", | 873 | .name = "LAYOUT_NFSV4_1_FILES", |
@@ -874,6 +880,7 @@ static struct pnfs_layoutdriver_type filelayout_type = { | |||
874 | .commit_pagelist = filelayout_commit_pagelist, | 880 | .commit_pagelist = filelayout_commit_pagelist, |
875 | .read_pagelist = filelayout_read_pagelist, | 881 | .read_pagelist = filelayout_read_pagelist, |
876 | .write_pagelist = filelayout_write_pagelist, | 882 | .write_pagelist = filelayout_write_pagelist, |
883 | .free_deviceid_node = filelayout_free_deveiceid_node, | ||
877 | }; | 884 | }; |
878 | 885 | ||
879 | static int __init nfs4filelayout_init(void) | 886 | static int __init nfs4filelayout_init(void) |
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h index 0ace0a2d6d7d..cebe01e3795e 100644 --- a/fs/nfs/nfs4filelayout.h +++ b/fs/nfs/nfs4filelayout.h | |||
@@ -98,6 +98,7 @@ u32 nfs4_fl_calc_ds_index(struct pnfs_layout_segment *lseg, u32 j); | |||
98 | struct nfs4_pnfs_ds *nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, | 98 | struct nfs4_pnfs_ds *nfs4_fl_prepare_ds(struct pnfs_layout_segment *lseg, |
99 | u32 ds_idx); | 99 | u32 ds_idx); |
100 | extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); | 100 | extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); |
101 | extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); | ||
101 | struct nfs4_file_layout_dsaddr * | 102 | struct nfs4_file_layout_dsaddr * |
102 | get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags); | 103 | get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags); |
103 | 104 | ||
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index eda4527a57eb..5914659c8ec5 100644 --- a/fs/nfs/nfs4filelayoutdev.c +++ b/fs/nfs/nfs4filelayoutdev.c | |||
@@ -156,7 +156,7 @@ destroy_ds(struct nfs4_pnfs_ds *ds) | |||
156 | kfree(ds); | 156 | kfree(ds); |
157 | } | 157 | } |
158 | 158 | ||
159 | static void | 159 | void |
160 | nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) | 160 | nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) |
161 | { | 161 | { |
162 | struct nfs4_pnfs_ds *ds; | 162 | struct nfs4_pnfs_ds *ds; |
@@ -386,7 +386,9 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags) | |||
386 | dsaddr->stripe_indices = stripe_indices; | 386 | dsaddr->stripe_indices = stripe_indices; |
387 | stripe_indices = NULL; | 387 | stripe_indices = NULL; |
388 | dsaddr->ds_num = num; | 388 | dsaddr->ds_num = num; |
389 | nfs4_init_deviceid_node(&dsaddr->id_node, NFS_SERVER(ino)->nfs_client, | 389 | nfs4_init_deviceid_node(&dsaddr->id_node, |
390 | NFS_SERVER(ino)->pnfs_curr_ld, | ||
391 | NFS_SERVER(ino)->nfs_client, | ||
390 | &pdev->dev_id); | 392 | &pdev->dev_id); |
391 | 393 | ||
392 | for (i = 0; i < dsaddr->ds_num; i++) { | 394 | for (i = 0; i < dsaddr->ds_num; i++) { |
@@ -548,8 +550,7 @@ out_free: | |||
548 | void | 550 | void |
549 | nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) | 551 | nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr) |
550 | { | 552 | { |
551 | if (nfs4_put_deviceid_node(&dsaddr->id_node)) | 553 | nfs4_put_deviceid_node(&dsaddr->id_node); |
552 | nfs4_fl_free_deviceid(dsaddr); | ||
553 | } | 554 | } |
554 | 555 | ||
555 | /* | 556 | /* |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 3831ad04a231..80a5d0e2cc43 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -65,6 +65,8 @@ enum { | |||
65 | NFS_LAYOUT_DESTROYED, /* no new use of layout allowed */ | 65 | NFS_LAYOUT_DESTROYED, /* no new use of layout allowed */ |
66 | }; | 66 | }; |
67 | 67 | ||
68 | struct nfs4_deviceid_node; | ||
69 | |||
68 | /* Per-layout driver specific registration structure */ | 70 | /* Per-layout driver specific registration structure */ |
69 | struct pnfs_layoutdriver_type { | 71 | struct pnfs_layoutdriver_type { |
70 | struct list_head pnfs_tblid; | 72 | struct list_head pnfs_tblid; |
@@ -90,6 +92,8 @@ struct pnfs_layoutdriver_type { | |||
90 | */ | 92 | */ |
91 | enum pnfs_try_status (*read_pagelist) (struct nfs_read_data *nfs_data); | 93 | enum pnfs_try_status (*read_pagelist) (struct nfs_read_data *nfs_data); |
92 | enum pnfs_try_status (*write_pagelist) (struct nfs_write_data *nfs_data, int how); | 94 | enum pnfs_try_status (*write_pagelist) (struct nfs_write_data *nfs_data, int how); |
95 | |||
96 | void (*free_deviceid_node) (struct nfs4_deviceid_node *); | ||
93 | }; | 97 | }; |
94 | 98 | ||
95 | struct pnfs_layout_hdr { | 99 | struct pnfs_layout_hdr { |
@@ -160,6 +164,7 @@ int pnfs_layoutcommit_inode(struct inode *inode, bool sync); | |||
160 | /* pnfs_dev.c */ | 164 | /* pnfs_dev.c */ |
161 | struct nfs4_deviceid_node { | 165 | struct nfs4_deviceid_node { |
162 | struct hlist_node node; | 166 | struct hlist_node node; |
167 | const struct pnfs_layoutdriver_type *ld; | ||
163 | const struct nfs_client *nfs_client; | 168 | const struct nfs_client *nfs_client; |
164 | struct nfs4_deviceid deviceid; | 169 | struct nfs4_deviceid deviceid; |
165 | atomic_t ref; | 170 | atomic_t ref; |
@@ -169,10 +174,12 @@ void nfs4_print_deviceid(const struct nfs4_deviceid *dev_id); | |||
169 | struct nfs4_deviceid_node *nfs4_find_get_deviceid(const struct nfs_client *, const struct nfs4_deviceid *); | 174 | struct nfs4_deviceid_node *nfs4_find_get_deviceid(const struct nfs_client *, const struct nfs4_deviceid *); |
170 | struct nfs4_deviceid_node *nfs4_unhash_put_deviceid(const struct nfs_client *, const struct nfs4_deviceid *); | 175 | struct nfs4_deviceid_node *nfs4_unhash_put_deviceid(const struct nfs_client *, const struct nfs4_deviceid *); |
171 | void nfs4_init_deviceid_node(struct nfs4_deviceid_node *, | 176 | void nfs4_init_deviceid_node(struct nfs4_deviceid_node *, |
177 | const struct pnfs_layoutdriver_type *, | ||
172 | const struct nfs_client *, | 178 | const struct nfs_client *, |
173 | const struct nfs4_deviceid *); | 179 | const struct nfs4_deviceid *); |
174 | struct nfs4_deviceid_node *nfs4_insert_deviceid_node(struct nfs4_deviceid_node *); | 180 | struct nfs4_deviceid_node *nfs4_insert_deviceid_node(struct nfs4_deviceid_node *); |
175 | bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *); | 181 | bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *); |
182 | void nfs4_deviceid_purge_client(const struct nfs_client *); | ||
176 | 183 | ||
177 | static inline int lo_fail_bit(u32 iomode) | 184 | static inline int lo_fail_bit(u32 iomode) |
178 | { | 185 | { |
@@ -349,6 +356,10 @@ static inline int pnfs_layoutcommit_inode(struct inode *inode, bool sync) | |||
349 | { | 356 | { |
350 | return 0; | 357 | return 0; |
351 | } | 358 | } |
359 | |||
360 | static inline void nfs4_deviceid_purge_client(struct nfs_client *ncl) | ||
361 | { | ||
362 | } | ||
352 | #endif /* CONFIG_NFS_V4_1 */ | 363 | #endif /* CONFIG_NFS_V4_1 */ |
353 | 364 | ||
354 | #endif /* FS_NFS_PNFS_H */ | 365 | #endif /* FS_NFS_PNFS_H */ |
diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c index bf05189a7cbf..64a4b85c7dbc 100644 --- a/fs/nfs/pnfs_dev.c +++ b/fs/nfs/pnfs_dev.c | |||
@@ -96,11 +96,15 @@ EXPORT_SYMBOL_GPL(nfs4_find_get_deviceid); | |||
96 | 96 | ||
97 | void | 97 | void |
98 | nfs4_init_deviceid_node(struct nfs4_deviceid_node *d, | 98 | nfs4_init_deviceid_node(struct nfs4_deviceid_node *d, |
99 | const struct pnfs_layoutdriver_type *ld, | ||
99 | const struct nfs_client *nfs_client, | 100 | const struct nfs_client *nfs_client, |
100 | const struct nfs4_deviceid *id) | 101 | const struct nfs4_deviceid *id) |
101 | { | 102 | { |
103 | INIT_HLIST_NODE(&d->node); | ||
104 | d->ld = ld; | ||
102 | d->nfs_client = nfs_client; | 105 | d->nfs_client = nfs_client; |
103 | d->deviceid = *id; | 106 | d->deviceid = *id; |
107 | atomic_set(&d->ref, 1); | ||
104 | } | 108 | } |
105 | EXPORT_SYMBOL_GPL(nfs4_init_deviceid_node); | 109 | EXPORT_SYMBOL_GPL(nfs4_init_deviceid_node); |
106 | 110 | ||
@@ -108,7 +112,10 @@ EXPORT_SYMBOL_GPL(nfs4_init_deviceid_node); | |||
108 | * Uniquely initialize and insert a deviceid node into cache | 112 | * Uniquely initialize and insert a deviceid node into cache |
109 | * | 113 | * |
110 | * @new new deviceid node | 114 | * @new new deviceid node |
111 | * Note that the caller must set up new->nfs_client and new->deviceid | 115 | * Note that the caller must set up the following members: |
116 | * new->ld | ||
117 | * new->nfs_client | ||
118 | * new->deviceid | ||
112 | * | 119 | * |
113 | * @ret the inserted node, if none found, otherwise, the found entry. | 120 | * @ret the inserted node, if none found, otherwise, the found entry. |
114 | */ | 121 | */ |
@@ -125,8 +132,6 @@ nfs4_insert_deviceid_node(struct nfs4_deviceid_node *new) | |||
125 | return d; | 132 | return d; |
126 | } | 133 | } |
127 | 134 | ||
128 | INIT_HLIST_NODE(&new->node); | ||
129 | atomic_set(&new->ref, 1); | ||
130 | hash = nfs4_deviceid_hash(&new->deviceid); | 135 | hash = nfs4_deviceid_hash(&new->deviceid); |
131 | hlist_add_head_rcu(&new->node, &nfs4_deviceid_cache[hash]); | 136 | hlist_add_head_rcu(&new->node, &nfs4_deviceid_cache[hash]); |
132 | spin_unlock(&nfs4_deviceid_lock); | 137 | spin_unlock(&nfs4_deviceid_lock); |
@@ -151,6 +156,42 @@ nfs4_put_deviceid_node(struct nfs4_deviceid_node *d) | |||
151 | hlist_del_init_rcu(&d->node); | 156 | hlist_del_init_rcu(&d->node); |
152 | spin_unlock(&nfs4_deviceid_lock); | 157 | spin_unlock(&nfs4_deviceid_lock); |
153 | synchronize_rcu(); | 158 | synchronize_rcu(); |
159 | d->ld->free_deviceid_node(d); | ||
154 | return true; | 160 | return true; |
155 | } | 161 | } |
156 | EXPORT_SYMBOL_GPL(nfs4_put_deviceid_node); | 162 | EXPORT_SYMBOL_GPL(nfs4_put_deviceid_node); |
163 | |||
164 | static void | ||
165 | _deviceid_purge_client(const struct nfs_client *clp, long hash) | ||
166 | { | ||
167 | struct nfs4_deviceid_node *d; | ||
168 | struct hlist_node *n, *next; | ||
169 | HLIST_HEAD(tmp); | ||
170 | |||
171 | rcu_read_lock(); | ||
172 | hlist_for_each_entry_rcu(d, n, &nfs4_deviceid_cache[hash], node) | ||
173 | if (d->nfs_client == clp && atomic_read(&d->ref)) { | ||
174 | hlist_del_init_rcu(&d->node); | ||
175 | hlist_add_head(&d->node, &tmp); | ||
176 | } | ||
177 | rcu_read_unlock(); | ||
178 | |||
179 | if (hlist_empty(&tmp)) | ||
180 | return; | ||
181 | |||
182 | synchronize_rcu(); | ||
183 | hlist_for_each_entry_safe(d, n, next, &tmp, node) | ||
184 | if (atomic_dec_and_test(&d->ref)) | ||
185 | d->ld->free_deviceid_node(d); | ||
186 | } | ||
187 | |||
188 | void | ||
189 | nfs4_deviceid_purge_client(const struct nfs_client *clp) | ||
190 | { | ||
191 | long h; | ||
192 | |||
193 | spin_lock(&nfs4_deviceid_lock); | ||
194 | for (h = 0; h < NFS4_DEVICE_ID_HASH_SIZE; h++) | ||
195 | _deviceid_purge_client(clp, h); | ||
196 | spin_unlock(&nfs4_deviceid_lock); | ||
197 | } | ||