diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c index 4d44e74c22fd345ae8ffa2d8d7952ac17ee29fcd..c384b6939a3e6ac210b855c01f66e02a2d7f1f88 100644 --- a/fs/cachefiles/interface.c +++ b/fs/cachefiles/interface.c @@ -338,6 +338,9 @@ static void cachefiles_clean_up_object(struct cachefiles_object *object, struct cachefiles_cache *cache) { struct file *file; + const struct cred *saved_cred; + + cachefiles_begin_secure(cache, &saved_cred); if (test_bit(FSCACHE_COOKIE_RETIRED, &object->cookie->flags)) { if (!test_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags)) { @@ -362,6 +365,8 @@ static void cachefiles_clean_up_object(struct cachefiles_object *object, if (file) fput(file); + + cachefiles_end_secure(cache, saved_cred); } /* @@ -371,7 +376,7 @@ static void cachefiles_withdraw_cookie(struct fscache_cookie *cookie) { struct cachefiles_object *object = cookie->cache_priv; struct cachefiles_cache *cache = object->volume->cache; - const struct cred *saved_cred; + bool unmark_early = fscache_test_inode_unmark_early(cache->cache); _enter("o=%x", object->debug_id); cachefiles_see_object(object, cachefiles_obj_see_withdraw_cookie); @@ -383,13 +388,13 @@ static void cachefiles_withdraw_cookie(struct fscache_cookie *cookie) spin_unlock(&cache->object_list_lock); } + if (unmark_early && object->file) + cachefiles_clean_up_object(object, cache); + cachefiles_ondemand_clean_object(object); - if (object->file) { - cachefiles_begin_secure(cache, &saved_cred); + if (!unmark_early && object->file) cachefiles_clean_up_object(object, cache); - cachefiles_end_secure(cache, saved_cred); - } cookie->cache_priv = NULL; cachefiles_put_object(object, cachefiles_obj_put_detach); diff --git a/fs/erofs/fscache.c b/fs/erofs/fscache.c index 7bcd1d261e7df45a1d23284d058e672f91f61941..37289680888a44912e69d80f7f8bb761b4ad3b2a 100644 --- a/fs/erofs/fscache.c +++ b/fs/erofs/fscache.c @@ -370,6 +370,8 @@ static int erofs_fscache_register_volume(struct super_block *sb) } else { /* enable synchronous unhashing for the associated volumes */ fscache_set_sync_volume_unhash(volume->cache); + /* enable to set inode unmark inuse early before send close req */ + fscache_set_inode_unmark_early(volume->cache); } sbi->volume = volume; diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h index 642fc1276c632954a3e7013c7f4c96777cf119cd..a1c5fa1a52149a3a93f6130921c25b4f419d80a4 100644 --- a/include/linux/fscache-cache.h +++ b/include/linux/fscache-cache.h @@ -46,6 +46,7 @@ struct fscache_cache { char *name; KABI_USE(1, unsigned long flags) #define FSCACHE_CACHE_SYNC_VOLUME_UNHASH 0 /* Mark to enable volume sync unhash */ +#define FSCACHE_CACHE_EARLY_UNMARK_INUSE 1 /* Need to unmark earlier */ KABI_RESERVE(2) KABI_RESERVE(3) @@ -225,6 +226,29 @@ static inline bool fscache_test_sync_volume_unhash(struct fscache_cache *cache) return test_bit(FSCACHE_CACHE_SYNC_VOLUME_UNHASH, &cache->flags); } +/** + * fscache_set_inode_unmark_early - Early unmark the inode inuse + * @cache: The cache to set + * + * Unmark the inode inuse before send close req. + */ +static inline void fscache_set_inode_unmark_early(struct fscache_cache *cache) +{ + set_bit(FSCACHE_CACHE_EARLY_UNMARK_INUSE, &cache->flags); +} + +/** + * fscache_test_inode_unmark_early - Check whether the inode need to + * unmark early + * @cache: The cache to query + * + * Indicates whether we need to unmark the inode inuse early. + */ +static inline bool fscache_test_inode_unmark_early(struct fscache_cache *cache) +{ + return test_bit(FSCACHE_CACHE_EARLY_UNMARK_INUSE, &cache->flags); +} + #ifdef CONFIG_FSCACHE_STATS extern atomic_t fscache_n_read; extern atomic_t fscache_n_write;