]> git.karo-electronics.de Git - karo-tx-linux.git/blob - fs/nfs/pagelist.c
Merge commit 'nfs-for-3.3-4' into nfs-for-next
[karo-tx-linux.git] / fs / nfs / pagelist.c
1 /*
2  * linux/fs/nfs/pagelist.c
3  *
4  * A set of helper functions for managing NFS read and write requests.
5  * The main purpose of these routines is to provide support for the
6  * coalescing of several requests into a single RPC call.
7  *
8  * Copyright 2000, 2001 (c) Trond Myklebust <trond.myklebust@fys.uio.no>
9  *
10  */
11
12 #include <linux/slab.h>
13 #include <linux/file.h>
14 #include <linux/sched.h>
15 #include <linux/sunrpc/clnt.h>
16 #include <linux/nfs.h>
17 #include <linux/nfs3.h>
18 #include <linux/nfs4.h>
19 #include <linux/nfs_page.h>
20 #include <linux/nfs_fs.h>
21 #include <linux/nfs_mount.h>
22 #include <linux/export.h>
23
24 #include "internal.h"
25 #include "pnfs.h"
26
27 static struct kmem_cache *nfs_page_cachep;
28
29 static inline struct nfs_page *
30 nfs_page_alloc(void)
31 {
32         struct nfs_page *p = kmem_cache_zalloc(nfs_page_cachep, GFP_KERNEL);
33         if (p)
34                 INIT_LIST_HEAD(&p->wb_list);
35         return p;
36 }
37
38 static inline void
39 nfs_page_free(struct nfs_page *p)
40 {
41         kmem_cache_free(nfs_page_cachep, p);
42 }
43
44 /**
45  * nfs_create_request - Create an NFS read/write request.
46  * @ctx: open context to use
47  * @inode: inode to which the request is attached
48  * @page: page to write
49  * @offset: starting offset within the page for the write
50  * @count: number of bytes to read/write
51  *
52  * The page must be locked by the caller. This makes sure we never
53  * create two different requests for the same page.
54  * User should ensure it is safe to sleep in this function.
55  */
56 struct nfs_page *
57 nfs_create_request(struct nfs_open_context *ctx, struct inode *inode,
58                    struct page *page,
59                    unsigned int offset, unsigned int count)
60 {
61         struct nfs_page         *req;
62
63         /* try to allocate the request struct */
64         req = nfs_page_alloc();
65         if (req == NULL)
66                 return ERR_PTR(-ENOMEM);
67
68         /* get lock context early so we can deal with alloc failures */
69         req->wb_lock_context = nfs_get_lock_context(ctx);
70         if (req->wb_lock_context == NULL) {
71                 nfs_page_free(req);
72                 return ERR_PTR(-ENOMEM);
73         }
74
75         /* Initialize the request struct. Initially, we assume a
76          * long write-back delay. This will be adjusted in
77          * update_nfs_request below if the region is not locked. */
78         req->wb_page    = page;
79         atomic_set(&req->wb_complete, 0);
80         req->wb_index   = page->index;
81         page_cache_get(page);
82         BUG_ON(PagePrivate(page));
83         BUG_ON(!PageLocked(page));
84         BUG_ON(page->mapping->host != inode);
85         req->wb_offset  = offset;
86         req->wb_pgbase  = offset;
87         req->wb_bytes   = count;
88         req->wb_context = get_nfs_open_context(ctx);
89         kref_init(&req->wb_kref);
90         return req;
91 }
92
93 /**
94  * nfs_unlock_request - Unlock request and wake up sleepers.
95  * @req:
96  */
97 void nfs_unlock_request(struct nfs_page *req)
98 {
99         if (!NFS_WBACK_BUSY(req)) {
100                 printk(KERN_ERR "NFS: Invalid unlock attempted\n");
101                 BUG();
102         }
103         smp_mb__before_clear_bit();
104         clear_bit(PG_BUSY, &req->wb_flags);
105         smp_mb__after_clear_bit();
106         wake_up_bit(&req->wb_flags, PG_BUSY);
107         nfs_release_request(req);
108 }
109
110 /**
111  * nfs_set_page_tag_locked - Tag a request as locked
112  * @req:
113  */
114 int nfs_set_page_tag_locked(struct nfs_page *req)
115 {
116         if (!nfs_lock_request_dontget(req))
117                 return 0;
118         if (test_bit(PG_MAPPED, &req->wb_flags))
119                 radix_tree_tag_set(&NFS_I(req->wb_context->dentry->d_inode)->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
120         return 1;
121 }
122
123 /**
124  * nfs_clear_page_tag_locked - Clear request tag and wake up sleepers
125  */
126 void nfs_clear_page_tag_locked(struct nfs_page *req)
127 {
128         if (test_bit(PG_MAPPED, &req->wb_flags)) {
129                 struct inode *inode = req->wb_context->dentry->d_inode;
130                 struct nfs_inode *nfsi = NFS_I(inode);
131
132                 spin_lock(&inode->i_lock);
133                 radix_tree_tag_clear(&nfsi->nfs_page_tree, req->wb_index, NFS_PAGE_TAG_LOCKED);
134                 nfs_unlock_request(req);
135                 spin_unlock(&inode->i_lock);
136         } else
137                 nfs_unlock_request(req);
138 }
139
140 /*
141  * nfs_clear_request - Free up all resources allocated to the request
142  * @req:
143  *
144  * Release page and open context resources associated with a read/write
145  * request after it has completed.
146  */
147 static void nfs_clear_request(struct nfs_page *req)
148 {
149         struct page *page = req->wb_page;
150         struct nfs_open_context *ctx = req->wb_context;
151         struct nfs_lock_context *l_ctx = req->wb_lock_context;
152
153         if (page != NULL) {
154                 page_cache_release(page);
155                 req->wb_page = NULL;
156         }
157         if (l_ctx != NULL) {
158                 nfs_put_lock_context(l_ctx);
159                 req->wb_lock_context = NULL;
160         }
161         if (ctx != NULL) {
162                 put_nfs_open_context(ctx);
163                 req->wb_context = NULL;
164         }
165 }
166
167
168 /**
169  * nfs_release_request - Release the count on an NFS read/write request
170  * @req: request to release
171  *
172  * Note: Should never be called with the spinlock held!
173  */
174 static void nfs_free_request(struct kref *kref)
175 {
176         struct nfs_page *req = container_of(kref, struct nfs_page, wb_kref);
177
178         /* Release struct file and open context */
179         nfs_clear_request(req);
180         nfs_page_free(req);
181 }
182
183 void nfs_release_request(struct nfs_page *req)
184 {
185         kref_put(&req->wb_kref, nfs_free_request);
186 }
187
188 static int nfs_wait_bit_uninterruptible(void *word)
189 {
190         io_schedule();
191         return 0;
192 }
193
194 /**
195  * nfs_wait_on_request - Wait for a request to complete.
196  * @req: request to wait upon.
197  *
198  * Interruptible by fatal signals only.
199  * The user is responsible for holding a count on the request.
200  */
201 int
202 nfs_wait_on_request(struct nfs_page *req)
203 {
204         return wait_on_bit(&req->wb_flags, PG_BUSY,
205                         nfs_wait_bit_uninterruptible,
206                         TASK_UNINTERRUPTIBLE);
207 }
208
209 bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_page *prev, struct nfs_page *req)
210 {
211         /*
212          * FIXME: ideally we should be able to coalesce all requests
213          * that are not block boundary aligned, but currently this
214          * is problematic for the case of bsize < PAGE_CACHE_SIZE,
215          * since nfs_flush_multi and nfs_pagein_multi assume you
216          * can have only one struct nfs_page.
217          */
218         if (desc->pg_bsize < PAGE_SIZE)
219                 return 0;
220
221         return desc->pg_count + req->wb_bytes <= desc->pg_bsize;
222 }
223 EXPORT_SYMBOL_GPL(nfs_generic_pg_test);
224
225 /**
226  * nfs_pageio_init - initialise a page io descriptor
227  * @desc: pointer to descriptor
228  * @inode: pointer to inode
229  * @doio: pointer to io function
230  * @bsize: io block size
231  * @io_flags: extra parameters for the io function
232  */
233 void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
234                      struct inode *inode,
235                      const struct nfs_pageio_ops *pg_ops,
236                      size_t bsize,
237                      int io_flags)
238 {
239         INIT_LIST_HEAD(&desc->pg_list);
240         desc->pg_bytes_written = 0;
241         desc->pg_count = 0;
242         desc->pg_bsize = bsize;
243         desc->pg_base = 0;
244         desc->pg_moreio = 0;
245         desc->pg_recoalesce = 0;
246         desc->pg_inode = inode;
247         desc->pg_ops = pg_ops;
248         desc->pg_ioflags = io_flags;
249         desc->pg_error = 0;
250         desc->pg_lseg = NULL;
251 }
252
253 /**
254  * nfs_can_coalesce_requests - test two requests for compatibility
255  * @prev: pointer to nfs_page
256  * @req: pointer to nfs_page
257  *
258  * The nfs_page structures 'prev' and 'req' are compared to ensure that the
259  * page data area they describe is contiguous, and that their RPC
260  * credentials, NFSv4 open state, and lockowners are the same.
261  *
262  * Return 'true' if this is the case, else return 'false'.
263  */
264 static bool nfs_can_coalesce_requests(struct nfs_page *prev,
265                                       struct nfs_page *req,
266                                       struct nfs_pageio_descriptor *pgio)
267 {
268         if (req->wb_context->cred != prev->wb_context->cred)
269                 return false;
270         if (req->wb_lock_context->lockowner != prev->wb_lock_context->lockowner)
271                 return false;
272         if (req->wb_context->state != prev->wb_context->state)
273                 return false;
274         if (req->wb_index != (prev->wb_index + 1))
275                 return false;
276         if (req->wb_pgbase != 0)
277                 return false;
278         if (prev->wb_pgbase + prev->wb_bytes != PAGE_CACHE_SIZE)
279                 return false;
280         return pgio->pg_ops->pg_test(pgio, prev, req);
281 }
282
283 /**
284  * nfs_pageio_do_add_request - Attempt to coalesce a request into a page list.
285  * @desc: destination io descriptor
286  * @req: request
287  *
288  * Returns true if the request 'req' was successfully coalesced into the
289  * existing list of pages 'desc'.
290  */
291 static int nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc,
292                                      struct nfs_page *req)
293 {
294         if (desc->pg_count != 0) {
295                 struct nfs_page *prev;
296
297                 prev = nfs_list_entry(desc->pg_list.prev);
298                 if (!nfs_can_coalesce_requests(prev, req, desc))
299                         return 0;
300         } else {
301                 if (desc->pg_ops->pg_init)
302                         desc->pg_ops->pg_init(desc, req);
303                 desc->pg_base = req->wb_pgbase;
304         }
305         nfs_list_remove_request(req);
306         nfs_list_add_request(req, &desc->pg_list);
307         desc->pg_count += req->wb_bytes;
308         return 1;
309 }
310
311 /*
312  * Helper for nfs_pageio_add_request and nfs_pageio_complete
313  */
314 static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc)
315 {
316         if (!list_empty(&desc->pg_list)) {
317                 int error = desc->pg_ops->pg_doio(desc);
318                 if (error < 0)
319                         desc->pg_error = error;
320                 else
321                         desc->pg_bytes_written += desc->pg_count;
322         }
323         if (list_empty(&desc->pg_list)) {
324                 desc->pg_count = 0;
325                 desc->pg_base = 0;
326         }
327 }
328
329 /**
330  * nfs_pageio_add_request - Attempt to coalesce a request into a page list.
331  * @desc: destination io descriptor
332  * @req: request
333  *
334  * Returns true if the request 'req' was successfully coalesced into the
335  * existing list of pages 'desc'.
336  */
337 static int __nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
338                            struct nfs_page *req)
339 {
340         while (!nfs_pageio_do_add_request(desc, req)) {
341                 desc->pg_moreio = 1;
342                 nfs_pageio_doio(desc);
343                 if (desc->pg_error < 0)
344                         return 0;
345                 desc->pg_moreio = 0;
346                 if (desc->pg_recoalesce)
347                         return 0;
348         }
349         return 1;
350 }
351
352 static int nfs_do_recoalesce(struct nfs_pageio_descriptor *desc)
353 {
354         LIST_HEAD(head);
355
356         do {
357                 list_splice_init(&desc->pg_list, &head);
358                 desc->pg_bytes_written -= desc->pg_count;
359                 desc->pg_count = 0;
360                 desc->pg_base = 0;
361                 desc->pg_recoalesce = 0;
362
363                 while (!list_empty(&head)) {
364                         struct nfs_page *req;
365
366                         req = list_first_entry(&head, struct nfs_page, wb_list);
367                         nfs_list_remove_request(req);
368                         if (__nfs_pageio_add_request(desc, req))
369                                 continue;
370                         if (desc->pg_error < 0)
371                                 return 0;
372                         break;
373                 }
374         } while (desc->pg_recoalesce);
375         return 1;
376 }
377
378 int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
379                 struct nfs_page *req)
380 {
381         int ret;
382
383         do {
384                 ret = __nfs_pageio_add_request(desc, req);
385                 if (ret)
386                         break;
387                 if (desc->pg_error < 0)
388                         break;
389                 ret = nfs_do_recoalesce(desc);
390         } while (ret);
391         return ret;
392 }
393
394 /**
395  * nfs_pageio_complete - Complete I/O on an nfs_pageio_descriptor
396  * @desc: pointer to io descriptor
397  */
398 void nfs_pageio_complete(struct nfs_pageio_descriptor *desc)
399 {
400         for (;;) {
401                 nfs_pageio_doio(desc);
402                 if (!desc->pg_recoalesce)
403                         break;
404                 if (!nfs_do_recoalesce(desc))
405                         break;
406         }
407 }
408
409 /**
410  * nfs_pageio_cond_complete - Conditional I/O completion
411  * @desc: pointer to io descriptor
412  * @index: page index
413  *
414  * It is important to ensure that processes don't try to take locks
415  * on non-contiguous ranges of pages as that might deadlock. This
416  * function should be called before attempting to wait on a locked
417  * nfs_page. It will complete the I/O if the page index 'index'
418  * is not contiguous with the existing list of pages in 'desc'.
419  */
420 void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *desc, pgoff_t index)
421 {
422         if (!list_empty(&desc->pg_list)) {
423                 struct nfs_page *prev = nfs_list_entry(desc->pg_list.prev);
424                 if (index != prev->wb_index + 1)
425                         nfs_pageio_complete(desc);
426         }
427 }
428
429 #define NFS_SCAN_MAXENTRIES 16
430 /**
431  * nfs_scan_list - Scan a list for matching requests
432  * @nfsi: NFS inode
433  * @dst: Destination list
434  * @idx_start: lower bound of page->index to scan
435  * @npages: idx_start + npages sets the upper bound to scan.
436  * @tag: tag to scan for
437  *
438  * Moves elements from one of the inode request lists.
439  * If the number of requests is set to 0, the entire address_space
440  * starting at index idx_start, is scanned.
441  * The requests are *not* checked to ensure that they form a contiguous set.
442  * You must be holding the inode's i_lock when calling this function
443  */
444 int nfs_scan_list(struct nfs_inode *nfsi,
445                 struct list_head *dst, pgoff_t idx_start,
446                 unsigned int npages, int tag)
447 {
448         struct nfs_page *pgvec[NFS_SCAN_MAXENTRIES];
449         struct nfs_page *req;
450         pgoff_t idx_end;
451         int found, i;
452         int res;
453         struct list_head *list;
454
455         res = 0;
456         if (npages == 0)
457                 idx_end = ~0;
458         else
459                 idx_end = idx_start + npages - 1;
460
461         for (;;) {
462                 found = radix_tree_gang_lookup_tag(&nfsi->nfs_page_tree,
463                                 (void **)&pgvec[0], idx_start,
464                                 NFS_SCAN_MAXENTRIES, tag);
465                 if (found <= 0)
466                         break;
467                 for (i = 0; i < found; i++) {
468                         req = pgvec[i];
469                         if (req->wb_index > idx_end)
470                                 goto out;
471                         idx_start = req->wb_index + 1;
472                         if (nfs_set_page_tag_locked(req)) {
473                                 kref_get(&req->wb_kref);
474                                 radix_tree_tag_clear(&nfsi->nfs_page_tree,
475                                                 req->wb_index, tag);
476                                 list = pnfs_choose_commit_list(req, dst);
477                                 nfs_list_add_request(req, list);
478                                 res++;
479                                 if (res == INT_MAX)
480                                         goto out;
481                         }
482                 }
483                 /* for latency reduction */
484                 cond_resched_lock(&nfsi->vfs_inode.i_lock);
485         }
486 out:
487         return res;
488 }
489
490 int __init nfs_init_nfspagecache(void)
491 {
492         nfs_page_cachep = kmem_cache_create("nfs_page",
493                                             sizeof(struct nfs_page),
494                                             0, SLAB_HWCACHE_ALIGN,
495                                             NULL);
496         if (nfs_page_cachep == NULL)
497                 return -ENOMEM;
498
499         return 0;
500 }
501
502 void nfs_destroy_nfspagecache(void)
503 {
504         kmem_cache_destroy(nfs_page_cachep);
505 }
506