This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / fs / fscache / page.c
1 /* page.c: general filesystem cache cookie management
2  *
3  * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version
9  * 2 of the License, or (at your option) any later version.
10  */
11
12 #include <linux/module.h>
13 #include <linux/fscache-cache.h>
14 #include <linux/buffer_head.h>
15 #include <linux/pagevec.h>
16 #include "fscache-int.h"
17
18 /*****************************************************************************/
19 /*
20  * set the data file size on an object in the cache
21  */
22 int __fscache_set_i_size(struct fscache_cookie *cookie, loff_t i_size)
23 {
24         struct fscache_object *object;
25         int ret;
26
27         _enter("%p,%llu,", cookie, i_size);
28
29         if (hlist_empty(&cookie->backing_objects)) {
30                 _leave(" = -ENOBUFS");
31                 return -ENOBUFS;
32         }
33
34         /* not supposed to use this for indexes */
35         BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
36
37         /* prevent the file from being uncached whilst we access it and exclude
38          * read and write attempts on pages
39          */
40         down_write(&cookie->sem);
41
42         ret = -ENOBUFS;
43         if (!hlist_empty(&cookie->backing_objects)) {
44                 /* get and pin the backing object */
45                 object = hlist_entry(cookie->backing_objects.first,
46                                      struct fscache_object, cookie_link);
47
48                 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
49                         goto out;
50
51                 /* prevent the cache from being withdrawn */
52                 if (object->cache->ops->set_i_size &&
53                     fscache_operation_lock(object)
54                     ) {
55                         if (object->cache->ops->grab_object(object)) {
56                                 /* ask the cache to honour the operation */
57                                 ret = object->cache->ops->set_i_size(object,
58                                                                      i_size);
59
60                                 object->cache->ops->put_object(object);
61                         }
62
63                         fscache_operation_unlock(object);
64                 }
65         }
66
67 out:
68         up_write(&cookie->sem);
69         _leave(" = %d", ret);
70         return ret;
71 }
72
73 EXPORT_SYMBOL(__fscache_set_i_size);
74
75 /*****************************************************************************/
76 /*
77  * reserve space for an object
78  */
79 int __fscache_reserve_space(struct fscache_cookie *cookie, loff_t size)
80 {
81         struct fscache_object *object;
82         int ret;
83
84         _enter("%p,%llu,", cookie, size);
85
86         if (hlist_empty(&cookie->backing_objects)) {
87                 _leave(" = -ENOBUFS");
88                 return -ENOBUFS;
89         }
90
91         /* not supposed to use this for indexes */
92         BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
93
94         /* prevent the file from being uncached whilst we access it and exclude
95          * read and write attempts on pages
96          */
97         down_write(&cookie->sem);
98
99         ret = -ENOBUFS;
100         if (!hlist_empty(&cookie->backing_objects)) {
101                 /* get and pin the backing object */
102                 object = hlist_entry(cookie->backing_objects.first,
103                                      struct fscache_object, cookie_link);
104
105                 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
106                         goto out;
107
108                 if (!object->cache->ops->reserve_space) {
109                         ret = -EOPNOTSUPP;
110                         goto out;
111                 }
112
113                 /* prevent the cache from being withdrawn */
114                 if (fscache_operation_lock(object)) {
115                         if (object->cache->ops->grab_object(object)) {
116                                 /* ask the cache to honour the operation */
117                                 ret = object->cache->ops->reserve_space(object,
118                                                                         size);
119
120                                 object->cache->ops->put_object(object);
121                         }
122
123                         fscache_operation_unlock(object);
124                 }
125         }
126
127 out:
128         up_write(&cookie->sem);
129         _leave(" = %d", ret);
130         return ret;
131 }
132
133 EXPORT_SYMBOL(__fscache_reserve_space);
134
135 /*****************************************************************************/
136 /*
137  * read a page from the cache or allocate a block in which to store it
138  * - we return:
139  *   -ENOMEM    - out of memory, nothing done
140  *   -EINTR     - interrupted
141  *   -ENOBUFS   - no backing object available in which to cache the block
142  *   -ENODATA   - no data available in the backing object for this block
143  *   0          - dispatched a read - it'll call end_io_func() when finished
144  */
145 int __fscache_read_or_alloc_page(struct fscache_cookie *cookie,
146                                  struct page *page,
147                                  fscache_rw_complete_t end_io_func,
148                                  void *context,
149                                  gfp_t gfp)
150 {
151         struct fscache_object *object;
152         int ret;
153
154         _enter("%p,{%lu},", cookie, page->index);
155
156         if (hlist_empty(&cookie->backing_objects)) {
157                 _leave(" -ENOBUFS [no backing objects]");
158                 return -ENOBUFS;
159         }
160
161         /* not supposed to use this for indexes */
162         BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
163
164         /* prevent the file from being uncached whilst we access it */
165         down_read(&cookie->sem);
166
167         ret = -ENOBUFS;
168         if (!hlist_empty(&cookie->backing_objects)) {
169                 /* get and pin the backing object */
170                 object = hlist_entry(cookie->backing_objects.first,
171                                      struct fscache_object, cookie_link);
172
173                 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
174                         goto out;
175
176                 /* prevent the cache from being withdrawn */
177                 if (fscache_operation_lock(object)) {
178                         if (object->cache->ops->grab_object(object)) {
179                                 /* ask the cache to honour the operation */
180                                 ret = object->cache->ops->read_or_alloc_page(
181                                         object,
182                                         page,
183                                         end_io_func,
184                                         context,
185                                         gfp);
186
187                                 object->cache->ops->put_object(object);
188                         }
189
190                         fscache_operation_unlock(object);
191                 }
192         }
193
194 out:
195         up_read(&cookie->sem);
196         _leave(" = %d", ret);
197         return ret;
198 }
199
200 EXPORT_SYMBOL(__fscache_read_or_alloc_page);
201
202 /*****************************************************************************/
203 /*
204  * read a list of page from the cache or allocate a block in which to store
205  * them
206  * - we return:
207  *   -ENOMEM    - out of memory, some pages may be being read
208  *   -EINTR     - interrupted, some pages may be being read
209  *   -ENOBUFS   - no backing object or space available in which to cache any
210  *                pages not being read
211  *   -ENODATA   - no data available in the backing object for some or all of
212  *                the pages
213  *   0          - dispatched a read on all pages
214  *
215  * end_io_func() will be called for each page read from the cache as it is
216  * finishes being read
217  *
218  * any pages for which a read is dispatched will be removed from pages and
219  * nr_pages
220  */
221 int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
222                                   struct address_space *mapping,
223                                   struct list_head *pages,
224                                   unsigned *nr_pages,
225                                   fscache_rw_complete_t end_io_func,
226                                   void *context,
227                                   gfp_t gfp)
228 {
229         struct fscache_object *object;
230         int ret;
231
232         _enter("%p,,%d,,,", cookie, *nr_pages);
233
234         if (hlist_empty(&cookie->backing_objects)) {
235                 _leave(" -ENOBUFS [no backing objects]");
236                 return -ENOBUFS;
237         }
238
239         /* not supposed to use this for indexes */
240         BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
241         BUG_ON(list_empty(pages));
242         BUG_ON(*nr_pages <= 0);
243
244         /* prevent the file from being uncached whilst we access it */
245         down_read(&cookie->sem);
246
247         ret = -ENOBUFS;
248         if (!hlist_empty(&cookie->backing_objects)) {
249                 /* get and pin the backing object */
250                 object = hlist_entry(cookie->backing_objects.first,
251                                      struct fscache_object, cookie_link);
252
253                 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
254                         goto out;
255
256                 /* prevent the cache from being withdrawn */
257                 if (fscache_operation_lock(object)) {
258                         if (object->cache->ops->grab_object(object)) {
259                                 /* ask the cache to honour the operation */
260                                 ret = object->cache->ops->read_or_alloc_pages(
261                                         object,
262                                         mapping,
263                                         pages,
264                                         nr_pages,
265                                         end_io_func,
266                                         context,
267                                         gfp);
268
269                                 object->cache->ops->put_object(object);
270                         }
271
272                         fscache_operation_unlock(object);
273                 }
274         }
275
276 out:
277         up_read(&cookie->sem);
278         _leave(" = %d", ret);
279         return ret;
280 }
281
282 EXPORT_SYMBOL(__fscache_read_or_alloc_pages);
283
284 /*****************************************************************************/
285 /*
286  * allocate a block in the cache on which to store a page
287  * - we return:
288  *   -ENOMEM    - out of memory, nothing done
289  *   -EINTR     - interrupted
290  *   -ENOBUFS   - no backing object available in which to cache the block
291  *   0          - block allocated
292  */
293 int __fscache_alloc_page(struct fscache_cookie *cookie,
294                          struct page *page,
295                          gfp_t gfp)
296 {
297         struct fscache_object *object;
298         int ret;
299
300         _enter("%p,{%lu},", cookie, page->index);
301
302         if (hlist_empty(&cookie->backing_objects)) {
303                 _leave(" -ENOBUFS [no backing objects]");
304                 return -ENOBUFS;
305         }
306
307         /* not supposed to use this for indexes */
308         BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
309
310         /* prevent the file from being uncached whilst we access it */
311         down_read(&cookie->sem);
312
313         ret = -ENOBUFS;
314         if (!hlist_empty(&cookie->backing_objects)) {
315                 /* get and pin the backing object */
316                 object = hlist_entry(cookie->backing_objects.first,
317                                      struct fscache_object, cookie_link);
318
319                 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
320                         goto out;
321
322                 /* prevent the cache from being withdrawn */
323                 if (fscache_operation_lock(object)) {
324                         if (object->cache->ops->grab_object(object)) {
325                                 /* ask the cache to honour the operation */
326                                 ret = object->cache->ops->allocate_page(object,
327                                                                         page,
328                                                                         gfp);
329
330                                 object->cache->ops->put_object(object);
331                         }
332
333                         fscache_operation_unlock(object);
334                 }
335         }
336
337 out:
338         up_read(&cookie->sem);
339         _leave(" = %d", ret);
340         return ret;
341 }
342
343 EXPORT_SYMBOL(__fscache_alloc_page);
344
345 /*****************************************************************************/
346 /*
347  * request a page be stored in the cache
348  * - returns:
349  *   -ENOMEM    - out of memory, nothing done
350  *   -EINTR     - interrupted
351  *   -ENOBUFS   - no backing object available in which to cache the page
352  *   0          - dispatched a write - it'll call end_io_func() when finished
353  */
354 int __fscache_write_page(struct fscache_cookie *cookie,
355                          struct page *page,
356                          fscache_rw_complete_t end_io_func,
357                          void *context,
358                          gfp_t gfp)
359 {
360         struct fscache_object *object;
361         int ret;
362
363         _enter("%p,{%lu},", cookie, page->index);
364
365         /* not supposed to use this for indexes */
366         BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
367
368         /* prevent the file from been uncached whilst we deal with it */
369         down_read(&cookie->sem);
370
371         ret = -ENOBUFS;
372         if (!hlist_empty(&cookie->backing_objects)) {
373                 object = hlist_entry(cookie->backing_objects.first,
374                                      struct fscache_object, cookie_link);
375
376                 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
377                         goto out;
378
379                 /* prevent the cache from being withdrawn */
380                 if (fscache_operation_lock(object)) {
381                         /* ask the cache to honour the operation */
382                         ret = object->cache->ops->write_page(object,
383                                                              page,
384                                                              end_io_func,
385                                                              context,
386                                                              gfp);
387                         fscache_operation_unlock(object);
388                 }
389         }
390
391 out:
392         up_read(&cookie->sem);
393         _leave(" = %d", ret);
394         return ret;
395 }
396
397 EXPORT_SYMBOL(__fscache_write_page);
398
399 /*****************************************************************************/
400 /*
401  * request several pages be stored in the cache
402  * - returns:
403  *   -ENOMEM    - out of memory, nothing done
404  *   -EINTR     - interrupted
405  *   -ENOBUFS   - no backing object available in which to cache the page
406  *   0          - dispatched a write - it'll call end_io_func() when finished
407  */
408 int __fscache_write_pages(struct fscache_cookie *cookie,
409                           struct pagevec *pagevec,
410                           fscache_rw_complete_t end_io_func,
411                           void *context,
412                           gfp_t gfp)
413 {
414         struct fscache_object *object;
415         int ret;
416
417         _enter("%p,{%ld},", cookie, pagevec->nr);
418
419         /* not supposed to use this for indexes */
420         BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
421
422         /* prevent the file from been uncached whilst we deal with it */
423         down_read(&cookie->sem);
424
425         ret = -ENOBUFS;
426         if (!hlist_empty(&cookie->backing_objects)) {
427                 object = hlist_entry(cookie->backing_objects.first,
428                                      struct fscache_object, cookie_link);
429
430                 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
431                         goto out;
432
433                 /* prevent the cache from being withdrawn */
434                 if (fscache_operation_lock(object)) {
435                         /* ask the cache to honour the operation */
436                         ret = object->cache->ops->write_pages(object,
437                                                               pagevec,
438                                                               end_io_func,
439                                                               context,
440                                                               gfp);
441                         fscache_operation_unlock(object);
442                 }
443         }
444
445 out:
446         up_read(&cookie->sem);
447         _leave(" = %d", ret);
448         return ret;
449 }
450
451 EXPORT_SYMBOL(__fscache_write_pages);
452
453 /*****************************************************************************/
454 /*
455  * remove a page from the cache
456  */
457 void __fscache_uncache_page(struct fscache_cookie *cookie, struct page *page)
458 {
459         struct fscache_object *object;
460         struct pagevec pagevec;
461
462         _enter(",{%lu}", page->index);
463
464         /* not supposed to use this for indexes */
465         BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
466
467         if (hlist_empty(&cookie->backing_objects)) {
468                 _leave(" [no backing]");
469                 return;
470         }
471
472         pagevec_init(&pagevec, 0);
473         pagevec_add(&pagevec, page);
474
475         /* ask the cache to honour the operation */
476         down_read(&cookie->sem);
477
478         if (!hlist_empty(&cookie->backing_objects)) {
479                 object = hlist_entry(cookie->backing_objects.first,
480                                      struct fscache_object, cookie_link);
481
482                 /* prevent the cache from being withdrawn */
483                 if (fscache_operation_lock(object)) {
484                         object->cache->ops->uncache_pages(object, &pagevec);
485                         fscache_operation_unlock(object);
486                 }
487         }
488
489         up_read(&cookie->sem);
490
491         _leave("");
492 }
493
494 EXPORT_SYMBOL(__fscache_uncache_page);
495
496 /*****************************************************************************/
497 /*
498  * remove a bunch of pages from the cache
499  */
500 void __fscache_uncache_pages(struct fscache_cookie *cookie,
501                              struct pagevec *pagevec)
502 {
503         struct fscache_object *object;
504
505         _enter(",{%ld}", pagevec->nr);
506
507         BUG_ON(pagevec->nr <= 0);
508         BUG_ON(!pagevec->pages[0]);
509
510         /* not supposed to use this for indexes */
511         BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
512
513         if (hlist_empty(&cookie->backing_objects)) {
514                 _leave(" [no backing]");
515                 return;
516         }
517
518         /* ask the cache to honour the operation */
519         down_read(&cookie->sem);
520
521         if (!hlist_empty(&cookie->backing_objects)) {
522                 object = hlist_entry(cookie->backing_objects.first,
523                                      struct fscache_object, cookie_link);
524
525                 /* prevent the cache from being withdrawn */
526                 if (fscache_operation_lock(object)) {
527                         object->cache->ops->uncache_pages(object, pagevec);
528                         fscache_operation_unlock(object);
529                 }
530         }
531
532         up_read(&cookie->sem);
533
534         _leave("");
535 }
536
537 EXPORT_SYMBOL(__fscache_uncache_pages);