aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/file.c5
-rw-r--r--fs/nfs/inode.c3
-rw-r--r--fs/nfs/pnfs.c140
-rw-r--r--fs/nfs/pnfs.h39
-rw-r--r--fs/nfs/read.c3
5 files changed, 190 insertions, 0 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index c3f2477c16c1..91d019d39122 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -36,6 +36,7 @@
36#include "internal.h" 36#include "internal.h"
37#include "iostat.h" 37#include "iostat.h"
38#include "fscache.h" 38#include "fscache.h"
39#include "pnfs.h"
39 40
40#define NFSDBG_FACILITY NFSDBG_FILE 41#define NFSDBG_FACILITY NFSDBG_FILE
41 42
@@ -386,6 +387,10 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping,
386 file->f_path.dentry->d_name.name, 387 file->f_path.dentry->d_name.name,
387 mapping->host->i_ino, len, (long long) pos); 388 mapping->host->i_ino, len, (long long) pos);
388 389
390 pnfs_update_layout(mapping->host,
391 nfs_file_open_context(file),
392 IOMODE_RW);
393
389start: 394start:
390 /* 395 /*
391 * Prevent starvation issues if someone is doing a consistency 396 * Prevent starvation issues if someone is doing a consistency
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 6eec28656415..314f57164602 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -48,6 +48,7 @@
48#include "internal.h" 48#include "internal.h"
49#include "fscache.h" 49#include "fscache.h"
50#include "dns_resolve.h" 50#include "dns_resolve.h"
51#include "pnfs.h"
51 52
52#define NFSDBG_FACILITY NFSDBG_VFS 53#define NFSDBG_FACILITY NFSDBG_VFS
53 54
@@ -1410,6 +1411,7 @@ void nfs4_evict_inode(struct inode *inode)
1410{ 1411{
1411 truncate_inode_pages(&inode->i_data, 0); 1412 truncate_inode_pages(&inode->i_data, 0);
1412 end_writeback(inode); 1413 end_writeback(inode);
1414 pnfs_destroy_layout(NFS_I(inode));
1413 /* If we are holding a delegation, return it! */ 1415 /* If we are holding a delegation, return it! */
1414 nfs_inode_return_delegation_noreclaim(inode); 1416 nfs_inode_return_delegation_noreclaim(inode);
1415 /* First call standard NFS clear_inode() code */ 1417 /* First call standard NFS clear_inode() code */
@@ -1447,6 +1449,7 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi)
1447 nfsi->delegation = NULL; 1449 nfsi->delegation = NULL;
1448 nfsi->delegation_state = 0; 1450 nfsi->delegation_state = 0;
1449 init_rwsem(&nfsi->rwsem); 1451 init_rwsem(&nfsi->rwsem);
1452 nfsi->layout = NULL;
1450#endif 1453#endif
1451} 1454}
1452 1455
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index cf795625610e..c0cd954855b9 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -166,3 +166,143 @@ pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *ld_type)
166 spin_unlock(&pnfs_spinlock); 166 spin_unlock(&pnfs_spinlock);
167} 167}
168EXPORT_SYMBOL_GPL(pnfs_unregister_layoutdriver); 168EXPORT_SYMBOL_GPL(pnfs_unregister_layoutdriver);
169
170static void
171get_layout_hdr_locked(struct pnfs_layout_hdr *lo)
172{
173 assert_spin_locked(&lo->inode->i_lock);
174 lo->refcount++;
175}
176
177static void
178put_layout_hdr_locked(struct pnfs_layout_hdr *lo)
179{
180 assert_spin_locked(&lo->inode->i_lock);
181 BUG_ON(lo->refcount == 0);
182
183 lo->refcount--;
184 if (!lo->refcount) {
185 dprintk("%s: freeing layout cache %p\n", __func__, lo);
186 NFS_I(lo->inode)->layout = NULL;
187 kfree(lo);
188 }
189}
190
191void
192pnfs_destroy_layout(struct nfs_inode *nfsi)
193{
194 struct pnfs_layout_hdr *lo;
195
196 spin_lock(&nfsi->vfs_inode.i_lock);
197 lo = nfsi->layout;
198 if (lo) {
199 /* Matched by refcount set to 1 in alloc_init_layout_hdr */
200 put_layout_hdr_locked(lo);
201 }
202 spin_unlock(&nfsi->vfs_inode.i_lock);
203}
204
205/* STUB - pretend LAYOUTGET to server failed */
206static struct pnfs_layout_segment *
207send_layoutget(struct pnfs_layout_hdr *lo,
208 struct nfs_open_context *ctx,
209 u32 iomode)
210{
211 struct inode *ino = lo->inode;
212
213 set_bit(lo_fail_bit(iomode), &lo->state);
214 spin_lock(&ino->i_lock);
215 put_layout_hdr_locked(lo);
216 spin_unlock(&ino->i_lock);
217 return NULL;
218}
219
220static struct pnfs_layout_hdr *
221alloc_init_layout_hdr(struct inode *ino)
222{
223 struct pnfs_layout_hdr *lo;
224
225 lo = kzalloc(sizeof(struct pnfs_layout_hdr), GFP_KERNEL);
226 if (!lo)
227 return NULL;
228 lo->refcount = 1;
229 lo->inode = ino;
230 return lo;
231}
232
233static struct pnfs_layout_hdr *
234pnfs_find_alloc_layout(struct inode *ino)
235{
236 struct nfs_inode *nfsi = NFS_I(ino);
237 struct pnfs_layout_hdr *new = NULL;
238
239 dprintk("%s Begin ino=%p layout=%p\n", __func__, ino, nfsi->layout);
240
241 assert_spin_locked(&ino->i_lock);
242 if (nfsi->layout)
243 return nfsi->layout;
244
245 spin_unlock(&ino->i_lock);
246 new = alloc_init_layout_hdr(ino);
247 spin_lock(&ino->i_lock);
248
249 if (likely(nfsi->layout == NULL)) /* Won the race? */
250 nfsi->layout = new;
251 else
252 kfree(new);
253 return nfsi->layout;
254}
255
256/* STUB - LAYOUTGET never succeeds, so cache is empty */
257static struct pnfs_layout_segment *
258pnfs_has_layout(struct pnfs_layout_hdr *lo, u32 iomode)
259{
260 return NULL;
261}
262
263/*
264 * Layout segment is retreived from the server if not cached.
265 * The appropriate layout segment is referenced and returned to the caller.
266 */
267struct pnfs_layout_segment *
268pnfs_update_layout(struct inode *ino,
269 struct nfs_open_context *ctx,
270 enum pnfs_iomode iomode)
271{
272 struct nfs_inode *nfsi = NFS_I(ino);
273 struct pnfs_layout_hdr *lo;
274 struct pnfs_layout_segment *lseg = NULL;
275
276 if (!pnfs_enabled_sb(NFS_SERVER(ino)))
277 return NULL;
278 spin_lock(&ino->i_lock);
279 lo = pnfs_find_alloc_layout(ino);
280 if (lo == NULL) {
281 dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__);
282 goto out_unlock;
283 }
284
285 /* Check to see if the layout for the given range already exists */
286 lseg = pnfs_has_layout(lo, iomode);
287 if (lseg) {
288 dprintk("%s: Using cached lseg %p for iomode %d)\n",
289 __func__, lseg, iomode);
290 goto out_unlock;
291 }
292
293 /* if LAYOUTGET already failed once we don't try again */
294 if (test_bit(lo_fail_bit(iomode), &nfsi->layout->state))
295 goto out_unlock;
296
297 get_layout_hdr_locked(lo);
298 spin_unlock(&ino->i_lock);
299
300 lseg = send_layoutget(lo, ctx, iomode);
301out:
302 dprintk("%s end, state 0x%lx lseg %p\n", __func__,
303 nfsi->layout->state, lseg);
304 return lseg;
305out_unlock:
306 spin_unlock(&ino->i_lock);
307 goto out;
308}
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 61531f338576..4ed1b48c71b1 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -34,6 +34,11 @@
34 34
35#define LAYOUT_NFSV4_1_MODULE_PREFIX "nfs-layouttype4" 35#define LAYOUT_NFSV4_1_MODULE_PREFIX "nfs-layouttype4"
36 36
37enum {
38 NFS_LAYOUT_RO_FAILED = 0, /* get ro layout failed stop trying */
39 NFS_LAYOUT_RW_FAILED, /* get rw layout failed stop trying */
40};
41
37/* Per-layout driver specific registration structure */ 42/* Per-layout driver specific registration structure */
38struct pnfs_layoutdriver_type { 43struct pnfs_layoutdriver_type {
39 struct list_head pnfs_tblid; 44 struct list_head pnfs_tblid;
@@ -44,14 +49,48 @@ struct pnfs_layoutdriver_type {
44 int (*uninitialize_mountpoint) (struct nfs_server *); 49 int (*uninitialize_mountpoint) (struct nfs_server *);
45}; 50};
46 51
52struct pnfs_layout_hdr {
53 unsigned long refcount;
54 unsigned long state;
55 struct inode *inode;
56};
57
47extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *); 58extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *);
48extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *); 59extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *);
49 60
61struct pnfs_layout_segment *
62pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
63 enum pnfs_iomode access_type);
50void set_pnfs_layoutdriver(struct nfs_server *, u32 id); 64void set_pnfs_layoutdriver(struct nfs_server *, u32 id);
51void unset_pnfs_layoutdriver(struct nfs_server *); 65void unset_pnfs_layoutdriver(struct nfs_server *);
66void pnfs_destroy_layout(struct nfs_inode *);
67
68
69static inline int lo_fail_bit(u32 iomode)
70{
71 return iomode == IOMODE_RW ?
72 NFS_LAYOUT_RW_FAILED : NFS_LAYOUT_RO_FAILED;
73}
74
75/* Return true if a layout driver is being used for this mountpoint */
76static inline int pnfs_enabled_sb(struct nfs_server *nfss)
77{
78 return nfss->pnfs_curr_ld != NULL;
79}
52 80
53#else /* CONFIG_NFS_V4_1 */ 81#else /* CONFIG_NFS_V4_1 */
54 82
83static inline void pnfs_destroy_layout(struct nfs_inode *nfsi)
84{
85}
86
87static inline struct pnfs_layout_segment *
88pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
89 enum pnfs_iomode access_type)
90{
91 return NULL;
92}
93
55static inline void set_pnfs_layoutdriver(struct nfs_server *s, u32 id) 94static inline void set_pnfs_layoutdriver(struct nfs_server *s, u32 id)
56{ 95{
57} 96}
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 79859c81a943..e4b62c6f5a6e 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -25,6 +25,7 @@
25#include "internal.h" 25#include "internal.h"
26#include "iostat.h" 26#include "iostat.h"
27#include "fscache.h" 27#include "fscache.h"
28#include "pnfs.h"
28 29
29#define NFSDBG_FACILITY NFSDBG_PAGECACHE 30#define NFSDBG_FACILITY NFSDBG_PAGECACHE
30 31
@@ -120,6 +121,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
120 len = nfs_page_length(page); 121 len = nfs_page_length(page);
121 if (len == 0) 122 if (len == 0)
122 return nfs_return_empty_page(page); 123 return nfs_return_empty_page(page);
124 pnfs_update_layout(inode, ctx, IOMODE_READ);
123 new = nfs_create_request(ctx, inode, page, 0, len); 125 new = nfs_create_request(ctx, inode, page, 0, len);
124 if (IS_ERR(new)) { 126 if (IS_ERR(new)) {
125 unlock_page(page); 127 unlock_page(page);
@@ -624,6 +626,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
624 if (ret == 0) 626 if (ret == 0)
625 goto read_complete; /* all pages were read */ 627 goto read_complete; /* all pages were read */
626 628
629 pnfs_update_layout(inode, desc.ctx, IOMODE_READ);
627 if (rsize < PAGE_CACHE_SIZE) 630 if (rsize < PAGE_CACHE_SIZE)
628 nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0); 631 nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0);
629 else 632 else