1 /* page.c: general filesystem cache cookie management
3 * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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.
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"
18 /*****************************************************************************/
20 * set the data file size on an object in the cache
22 int __fscache_set_i_size(struct fscache_cookie *cookie, loff_t i_size)
24 struct fscache_object *object;
27 _enter("%p,%llu,", cookie, i_size);
29 if (hlist_empty(&cookie->backing_objects)) {
30 _leave(" = -ENOBUFS");
34 /* not supposed to use this for indexes */
35 BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
37 /* prevent the file from being uncached whilst we access it and exclude
38 * read and write attempts on pages
40 down_write(&cookie->sem);
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);
48 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
51 /* prevent the cache from being withdrawn */
52 if (object->cache->ops->set_i_size &&
53 fscache_operation_lock(object)
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,
60 object->cache->ops->put_object(object);
63 fscache_operation_unlock(object);
68 up_write(&cookie->sem);
73 EXPORT_SYMBOL(__fscache_set_i_size);
75 /*****************************************************************************/
77 * reserve space for an object
79 int __fscache_reserve_space(struct fscache_cookie *cookie, loff_t size)
81 struct fscache_object *object;
84 _enter("%p,%llu,", cookie, size);
86 if (hlist_empty(&cookie->backing_objects)) {
87 _leave(" = -ENOBUFS");
91 /* not supposed to use this for indexes */
92 BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
94 /* prevent the file from being uncached whilst we access it and exclude
95 * read and write attempts on pages
97 down_write(&cookie->sem);
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);
105 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
108 if (!object->cache->ops->reserve_space) {
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,
120 object->cache->ops->put_object(object);
123 fscache_operation_unlock(object);
128 up_write(&cookie->sem);
129 _leave(" = %d", ret);
133 EXPORT_SYMBOL(__fscache_reserve_space);
135 /*****************************************************************************/
137 * read a page from the cache or allocate a block in which to store it
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
145 int __fscache_read_or_alloc_page(struct fscache_cookie *cookie,
147 fscache_rw_complete_t end_io_func,
151 struct fscache_object *object;
154 _enter("%p,{%lu},", cookie, page->index);
156 if (hlist_empty(&cookie->backing_objects)) {
157 _leave(" -ENOBUFS [no backing objects]");
161 /* not supposed to use this for indexes */
162 BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
164 /* prevent the file from being uncached whilst we access it */
165 down_read(&cookie->sem);
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);
173 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
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(
187 object->cache->ops->put_object(object);
190 fscache_operation_unlock(object);
195 up_read(&cookie->sem);
196 _leave(" = %d", ret);
200 EXPORT_SYMBOL(__fscache_read_or_alloc_page);
202 /*****************************************************************************/
204 * read a list of page from the cache or allocate a block in which to store
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
213 * 0 - dispatched a read on all pages
215 * end_io_func() will be called for each page read from the cache as it is
216 * finishes being read
218 * any pages for which a read is dispatched will be removed from pages and
221 int __fscache_read_or_alloc_pages(struct fscache_cookie *cookie,
222 struct address_space *mapping,
223 struct list_head *pages,
225 fscache_rw_complete_t end_io_func,
229 struct fscache_object *object;
232 _enter("%p,,%d,,,", cookie, *nr_pages);
234 if (hlist_empty(&cookie->backing_objects)) {
235 _leave(" -ENOBUFS [no backing objects]");
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);
244 /* prevent the file from being uncached whilst we access it */
245 down_read(&cookie->sem);
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);
253 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
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(
269 object->cache->ops->put_object(object);
272 fscache_operation_unlock(object);
277 up_read(&cookie->sem);
278 _leave(" = %d", ret);
282 EXPORT_SYMBOL(__fscache_read_or_alloc_pages);
284 /*****************************************************************************/
286 * allocate a block in the cache on which to store a page
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
293 int __fscache_alloc_page(struct fscache_cookie *cookie,
297 struct fscache_object *object;
300 _enter("%p,{%lu},", cookie, page->index);
302 if (hlist_empty(&cookie->backing_objects)) {
303 _leave(" -ENOBUFS [no backing objects]");
307 /* not supposed to use this for indexes */
308 BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
310 /* prevent the file from being uncached whilst we access it */
311 down_read(&cookie->sem);
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);
319 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
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,
330 object->cache->ops->put_object(object);
333 fscache_operation_unlock(object);
338 up_read(&cookie->sem);
339 _leave(" = %d", ret);
343 EXPORT_SYMBOL(__fscache_alloc_page);
345 /*****************************************************************************/
347 * request a page be stored in the cache
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
354 int __fscache_write_page(struct fscache_cookie *cookie,
356 fscache_rw_complete_t end_io_func,
360 struct fscache_object *object;
363 _enter("%p,{%lu},", cookie, page->index);
365 /* not supposed to use this for indexes */
366 BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
368 /* prevent the file from been uncached whilst we deal with it */
369 down_read(&cookie->sem);
372 if (!hlist_empty(&cookie->backing_objects)) {
373 object = hlist_entry(cookie->backing_objects.first,
374 struct fscache_object, cookie_link);
376 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
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,
387 fscache_operation_unlock(object);
392 up_read(&cookie->sem);
393 _leave(" = %d", ret);
397 EXPORT_SYMBOL(__fscache_write_page);
399 /*****************************************************************************/
401 * request several pages be stored in the cache
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
408 int __fscache_write_pages(struct fscache_cookie *cookie,
409 struct pagevec *pagevec,
410 fscache_rw_complete_t end_io_func,
414 struct fscache_object *object;
417 _enter("%p,{%ld},", cookie, pagevec->nr);
419 /* not supposed to use this for indexes */
420 BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
422 /* prevent the file from been uncached whilst we deal with it */
423 down_read(&cookie->sem);
426 if (!hlist_empty(&cookie->backing_objects)) {
427 object = hlist_entry(cookie->backing_objects.first,
428 struct fscache_object, cookie_link);
430 if (test_bit(FSCACHE_IOERROR, &object->cache->flags))
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,
441 fscache_operation_unlock(object);
446 up_read(&cookie->sem);
447 _leave(" = %d", ret);
451 EXPORT_SYMBOL(__fscache_write_pages);
453 /*****************************************************************************/
455 * remove a page from the cache
457 void __fscache_uncache_page(struct fscache_cookie *cookie, struct page *page)
459 struct fscache_object *object;
460 struct pagevec pagevec;
462 _enter(",{%lu}", page->index);
464 /* not supposed to use this for indexes */
465 BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
467 if (hlist_empty(&cookie->backing_objects)) {
468 _leave(" [no backing]");
472 pagevec_init(&pagevec, 0);
473 pagevec_add(&pagevec, page);
475 /* ask the cache to honour the operation */
476 down_read(&cookie->sem);
478 if (!hlist_empty(&cookie->backing_objects)) {
479 object = hlist_entry(cookie->backing_objects.first,
480 struct fscache_object, cookie_link);
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);
489 up_read(&cookie->sem);
494 EXPORT_SYMBOL(__fscache_uncache_page);
496 /*****************************************************************************/
498 * remove a bunch of pages from the cache
500 void __fscache_uncache_pages(struct fscache_cookie *cookie,
501 struct pagevec *pagevec)
503 struct fscache_object *object;
505 _enter(",{%ld}", pagevec->nr);
507 BUG_ON(pagevec->nr <= 0);
508 BUG_ON(!pagevec->pages[0]);
510 /* not supposed to use this for indexes */
511 BUG_ON(cookie->def->type == FSCACHE_COOKIE_TYPE_INDEX);
513 if (hlist_empty(&cookie->backing_objects)) {
514 _leave(" [no backing]");
518 /* ask the cache to honour the operation */
519 down_read(&cookie->sem);
521 if (!hlist_empty(&cookie->backing_objects)) {
522 object = hlist_entry(cookie->backing_objects.first,
523 struct fscache_object, cookie_link);
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);
532 up_read(&cookie->sem);
537 EXPORT_SYMBOL(__fscache_uncache_pages);