aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/pnfs.c
diff options
context:
space:
mode:
authorBenny Halevy <bhalevy@panasas.com>2010-10-20 00:18:01 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-10-24 18:07:10 -0400
commite5e940170b2136ad4d5483ef293ae284b9cc8d53 (patch)
tree1568bf55addee6a6fdc091026083426b087e68df /fs/nfs/pnfs.c
parent7ab672ce312133ee4a5d85b71447b2b334403681 (diff)
NFS: create and destroy inode's layout cache
At the start of the io paths, try to grab the relevant layout information. This will initiate the inode's layout cache, but stubs ensure the cache stays empty. Signed-off-by: Benny Halevy <bhalevy@panasas.com> Signed-off-by: Dean Hildebrand <dhildebz@umich.edu> Signed-off-by: Marc Eshel <eshel@almaden.ibm.com> Signed-off-by: Tao Guo <guotao@nrchpc.ac.cn> Signed-off-by: Ricardo Labiaga <ricardo.labiaga@netapp.com> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Fred Isaman <iisaman@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r--fs/nfs/pnfs.c140
1 files changed, 140 insertions, 0 deletions
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}