aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fscache/object.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2013-09-20 19:09:31 -0400
committerDavid Howells <dhowells@redhat.com>2013-09-27 13:40:25 -0400
commit94d30ae90a00cafe686c1057be57f4885f963abf (patch)
tree2a4f927bcaf87e988f4f180d0a011856064186b5 /fs/fscache/object.c
parent8fb883f3e30065529e4f35d4b4f355193dcdb7a2 (diff)
FS-Cache: Provide the ability to enable/disable cookies
Provide the ability to enable and disable fscache cookies. A disabled cookie will reject or ignore further requests to: Acquire a child cookie Invalidate and update backing objects Check the consistency of a backing object Allocate storage for backing page Read backing pages Write to backing pages but still allows: Checks/waits on the completion of already in-progress objects Uncaching of pages Relinquishment of cookies Two new operations are provided: (1) Disable a cookie: void fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate); If the cookie is not already disabled, this locks the cookie against other dis/enablement ops, marks the cookie as being disabled, discards or invalidates any backing objects and waits for cessation of activity on any associated object. This is a wrapper around a chunk split out of fscache_relinquish_cookie(), but it reinitialises the cookie such that it can be reenabled. All possible failures are handled internally. The caller should consider calling fscache_uncache_all_inode_pages() afterwards to make sure all page markings are cleared up. (2) Enable a cookie: void fscache_enable_cookie(struct fscache_cookie *cookie, bool (*can_enable)(void *data), void *data) If the cookie is not already enabled, this locks the cookie against other dis/enablement ops, invokes can_enable() and, if the cookie is not an index cookie, will begin the procedure of acquiring backing objects. The optional can_enable() function is passed the data argument and returns a ruling as to whether or not enablement should actually be permitted to begin. All possible failures are handled internally. The cookie will only be marked as enabled if provisional backing objects are allocated. A later patch will introduce these to NFS. Cookie enablement during nfs_open() is then contingent on i_writecount <= 0. can_enable() checks for a race between open(O_RDONLY) and open(O_WRONLY/O_RDWR). This simplifies NFS's cookie handling and allows us to get rid of open(O_RDONLY) accidentally introducing caching to an inode that's open for writing already. One operation has its API modified: (3) Acquire a cookie. struct fscache_cookie *fscache_acquire_cookie( struct fscache_cookie *parent, const struct fscache_cookie_def *def, void *netfs_data, bool enable); This now has an additional argument that indicates whether the requested cookie should be enabled by default. It doesn't need the can_enable() function because the caller must prevent multiple calls for the same netfs object and it doesn't need to take the enablement lock because no one else can get at the cookie before this returns. Signed-off-by: David Howells <dhowells@redhat.com
Diffstat (limited to 'fs/fscache/object.c')
-rw-r--r--fs/fscache/object.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/fs/fscache/object.c b/fs/fscache/object.c
index 86d75a60b20c..dcb821617774 100644
--- a/fs/fscache/object.c
+++ b/fs/fscache/object.c
@@ -495,6 +495,7 @@ void fscache_object_lookup_negative(struct fscache_object *object)
495 * returning ENODATA. 495 * returning ENODATA.
496 */ 496 */
497 set_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags); 497 set_bit(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
498 clear_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);
498 499
499 _debug("wake up lookup %p", &cookie->flags); 500 _debug("wake up lookup %p", &cookie->flags);
500 clear_bit_unlock(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags); 501 clear_bit_unlock(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags);
@@ -527,6 +528,7 @@ void fscache_obtained_object(struct fscache_object *object)
527 528
528 /* We do (presumably) have data */ 529 /* We do (presumably) have data */
529 clear_bit_unlock(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags); 530 clear_bit_unlock(FSCACHE_COOKIE_NO_DATA_YET, &cookie->flags);
531 clear_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags);
530 532
531 /* Allow write requests to begin stacking up and read requests 533 /* Allow write requests to begin stacking up and read requests
532 * to begin shovelling data. 534 * to begin shovelling data.
@@ -679,7 +681,8 @@ static const struct fscache_state *fscache_drop_object(struct fscache_object *ob
679 */ 681 */
680 spin_lock(&cookie->lock); 682 spin_lock(&cookie->lock);
681 hlist_del_init(&object->cookie_link); 683 hlist_del_init(&object->cookie_link);
682 if (test_and_clear_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags)) 684 if (hlist_empty(&cookie->backing_objects) &&
685 test_and_clear_bit(FSCACHE_COOKIE_INVALIDATING, &cookie->flags))
683 awaken = true; 686 awaken = true;
684 spin_unlock(&cookie->lock); 687 spin_unlock(&cookie->lock);
685 688
@@ -927,7 +930,7 @@ static const struct fscache_state *_fscache_invalidate_object(struct fscache_obj
927 */ 930 */
928 if (!fscache_use_cookie(object)) { 931 if (!fscache_use_cookie(object)) {
929 ASSERT(object->cookie->stores.rnode == NULL); 932 ASSERT(object->cookie->stores.rnode == NULL);
930 set_bit(FSCACHE_COOKIE_RETIRED, &cookie->flags); 933 set_bit(FSCACHE_OBJECT_RETIRED, &object->flags);
931 _leave(" [no cookie]"); 934 _leave(" [no cookie]");
932 return transit_to(KILL_OBJECT); 935 return transit_to(KILL_OBJECT);
933 } 936 }