diff options
author | David Howells <dhowells@redhat.com> | 2009-11-19 13:11:52 -0500 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2009-11-19 13:11:52 -0500 |
commit | a17754fb8c28af19cd70dcbec6d5b0773b94e0c1 (patch) | |
tree | d7c25b217c684153eadbac78ab9b1bbff08b75f6 /include | |
parent | 868411be3f445a83fafbd734f3e426400138add5 (diff) |
CacheFiles: Don't write a full page if there's only a partial page to cache
cachefiles_write_page() writes a full page to the backing file for the last
page of the netfs file, even if the netfs file's last page is only a partial
page.
This causes the EOF on the backing file to be extended beyond the EOF of the
netfs, and thus the backing file will be truncated by cachefiles_attr_changed()
called from cachefiles_lookup_object().
So we need to limit the write we make to the backing file on that last page
such that it doesn't push the EOF too far.
Also, if a backing file that has a partial page at the end is expanded, we
discard the partial page and refetch it on the basis that we then have a hole
in the file with invalid data, and should the power go out... A better way to
deal with this could be to record a note that the partial page contains invalid
data until the correct data is written into it.
This isn't a problem for netfs's that discard the whole backing file if the
file size changes (such as NFS).
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/fscache-cache.h | 3 |
1 files changed, 3 insertions, 0 deletions
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h index 907bb56c5888..5db50002f3b5 100644 --- a/include/linux/fscache-cache.h +++ b/include/linux/fscache-cache.h | |||
@@ -395,6 +395,7 @@ struct fscache_object { | |||
395 | struct rb_node objlist_link; /* link in global object list */ | 395 | struct rb_node objlist_link; /* link in global object list */ |
396 | #endif | 396 | #endif |
397 | pgoff_t store_limit; /* current storage limit */ | 397 | pgoff_t store_limit; /* current storage limit */ |
398 | loff_t store_limit_l; /* current storage limit */ | ||
398 | }; | 399 | }; |
399 | 400 | ||
400 | extern const char *fscache_object_states[]; | 401 | extern const char *fscache_object_states[]; |
@@ -439,6 +440,7 @@ void fscache_object_init(struct fscache_object *object, | |||
439 | object->events = object->event_mask = 0; | 440 | object->events = object->event_mask = 0; |
440 | object->flags = 0; | 441 | object->flags = 0; |
441 | object->store_limit = 0; | 442 | object->store_limit = 0; |
443 | object->store_limit_l = 0; | ||
442 | object->cache = cache; | 444 | object->cache = cache; |
443 | object->cookie = cookie; | 445 | object->cookie = cookie; |
444 | object->parent = NULL; | 446 | object->parent = NULL; |
@@ -491,6 +493,7 @@ static inline void fscache_object_lookup_error(struct fscache_object *object) | |||
491 | static inline | 493 | static inline |
492 | void fscache_set_store_limit(struct fscache_object *object, loff_t i_size) | 494 | void fscache_set_store_limit(struct fscache_object *object, loff_t i_size) |
493 | { | 495 | { |
496 | object->store_limit_l = i_size; | ||
494 | object->store_limit = i_size >> PAGE_SHIFT; | 497 | object->store_limit = i_size >> PAGE_SHIFT; |
495 | if (i_size & ~PAGE_MASK) | 498 | if (i_size & ~PAGE_MASK) |
496 | object->store_limit++; | 499 | object->store_limit++; |