diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-03-09 14:48:32 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-03-27 12:32:24 -0400 |
commit | df52699e4fcefe30ebe4f1db48bd161254a0b102 (patch) | |
tree | 7b590d25515d0fa5bbbe5c48e76a0857a73e10b0 /fs | |
parent | 4e59080397faadee59d39ffa2116dc8607adc9c9 (diff) |
NFSv4.1: Don't cache deviceids that have no notifications
The spec says that once all layouts that reference a given deviceid
have been returned, then we are only allowed to continue to cache
the deviceid if the metadata server supports notifications.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/nfs4proc.c | 2 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 2 | ||||
-rw-r--r-- | fs/nfs/pnfs_dev.c | 9 |
3 files changed, 13 insertions, 0 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index ba8b2b5e98a1..9ff8c63c9cac 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -7962,6 +7962,8 @@ _nfs4_proc_getdeviceinfo(struct nfs_server *server, | |||
7962 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); | 7962 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
7963 | if (res.notification & ~args.notify_types) | 7963 | if (res.notification & ~args.notify_types) |
7964 | dprintk("%s: unsupported notification\n", __func__); | 7964 | dprintk("%s: unsupported notification\n", __func__); |
7965 | if (res.notification != args.notify_types) | ||
7966 | pdev->nocache = 1; | ||
7965 | 7967 | ||
7966 | dprintk("<-- %s status=%d\n", __func__, status); | 7968 | dprintk("<-- %s status=%d\n", __func__, status); |
7967 | 7969 | ||
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index a1fc16c971a7..b5654e8da936 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -203,6 +203,7 @@ struct pnfs_device { | |||
203 | struct page **pages; | 203 | struct page **pages; |
204 | unsigned int pgbase; | 204 | unsigned int pgbase; |
205 | unsigned int pglen; /* reply buffer length */ | 205 | unsigned int pglen; /* reply buffer length */ |
206 | unsigned char nocache : 1;/* May not be cached */ | ||
206 | }; | 207 | }; |
207 | 208 | ||
208 | #define NFS4_PNFS_GETDEVLIST_MAXNUM 16 | 209 | #define NFS4_PNFS_GETDEVLIST_MAXNUM 16 |
@@ -291,6 +292,7 @@ void pnfs_error_mark_layout_for_return(struct inode *inode, | |||
291 | enum { | 292 | enum { |
292 | NFS_DEVICEID_INVALID = 0, /* set when MDS clientid recalled */ | 293 | NFS_DEVICEID_INVALID = 0, /* set when MDS clientid recalled */ |
293 | NFS_DEVICEID_UNAVAILABLE, /* device temporarily unavailable */ | 294 | NFS_DEVICEID_UNAVAILABLE, /* device temporarily unavailable */ |
295 | NFS_DEVICEID_NOCACHE, /* device may not be cached */ | ||
294 | }; | 296 | }; |
295 | 297 | ||
296 | /* pnfs_dev.c */ | 298 | /* pnfs_dev.c */ |
diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c index 7e07f4ba4822..2961fcd7a2df 100644 --- a/fs/nfs/pnfs_dev.c +++ b/fs/nfs/pnfs_dev.c | |||
@@ -149,6 +149,8 @@ nfs4_get_device_info(struct nfs_server *server, | |||
149 | */ | 149 | */ |
150 | d = server->pnfs_curr_ld->alloc_deviceid_node(server, pdev, | 150 | d = server->pnfs_curr_ld->alloc_deviceid_node(server, pdev, |
151 | gfp_flags); | 151 | gfp_flags); |
152 | if (d && pdev->nocache) | ||
153 | set_bit(NFS_DEVICEID_NOCACHE, &d->flags); | ||
152 | 154 | ||
153 | out_free_pages: | 155 | out_free_pages: |
154 | for (i = 0; i < max_pages; i++) | 156 | for (i = 0; i < max_pages; i++) |
@@ -235,6 +237,7 @@ nfs4_delete_deviceid(const struct pnfs_layoutdriver_type *ld, | |||
235 | return; | 237 | return; |
236 | } | 238 | } |
237 | hlist_del_init_rcu(&d->node); | 239 | hlist_del_init_rcu(&d->node); |
240 | clear_bit(NFS_DEVICEID_NOCACHE, &d->flags); | ||
238 | spin_unlock(&nfs4_deviceid_lock); | 241 | spin_unlock(&nfs4_deviceid_lock); |
239 | 242 | ||
240 | /* balance the initial ref set in pnfs_insert_deviceid */ | 243 | /* balance the initial ref set in pnfs_insert_deviceid */ |
@@ -269,6 +272,11 @@ EXPORT_SYMBOL_GPL(nfs4_init_deviceid_node); | |||
269 | bool | 272 | bool |
270 | nfs4_put_deviceid_node(struct nfs4_deviceid_node *d) | 273 | nfs4_put_deviceid_node(struct nfs4_deviceid_node *d) |
271 | { | 274 | { |
275 | if (test_bit(NFS_DEVICEID_NOCACHE, &d->flags)) { | ||
276 | if (atomic_add_unless(&d->ref, -1, 2)) | ||
277 | return false; | ||
278 | nfs4_delete_deviceid(d->ld, d->nfs_client, &d->deviceid); | ||
279 | } | ||
272 | if (!atomic_dec_and_test(&d->ref)) | 280 | if (!atomic_dec_and_test(&d->ref)) |
273 | return false; | 281 | return false; |
274 | d->ld->free_deviceid_node(d); | 282 | d->ld->free_deviceid_node(d); |
@@ -312,6 +320,7 @@ _deviceid_purge_client(const struct nfs_client *clp, long hash) | |||
312 | if (d->nfs_client == clp && atomic_read(&d->ref)) { | 320 | if (d->nfs_client == clp && atomic_read(&d->ref)) { |
313 | hlist_del_init_rcu(&d->node); | 321 | hlist_del_init_rcu(&d->node); |
314 | hlist_add_head(&d->tmpnode, &tmp); | 322 | hlist_add_head(&d->tmpnode, &tmp); |
323 | clear_bit(NFS_DEVICEID_NOCACHE, &d->flags); | ||
315 | } | 324 | } |
316 | rcu_read_unlock(); | 325 | rcu_read_unlock(); |
317 | spin_unlock(&nfs4_deviceid_lock); | 326 | spin_unlock(&nfs4_deviceid_lock); |