aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/pnfs.c
diff options
context:
space:
mode:
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}