summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/caching/backend-api.rst2
-rw-r--r--Documentation/filesystems/caching/netfs-api.rst2
-rw-r--r--fs/9p/vfs_inode.c6
-rw-r--r--fs/9p/vfs_inode_dotl.c5
-rw-r--r--fs/afs/inode.c4
-rw-r--r--fs/cachefiles/interface.c8
-rw-r--r--fs/ceph/cache.h6
-rw-r--r--fs/ceph/inode.c16
-rw-r--r--fs/ceph/super.h3
-rw-r--r--fs/netfs/fscache_io.c4
-rw-r--r--fs/smb/client/cifsfs.c6
-rw-r--r--fs/smb/client/inode.c2
-rw-r--r--fs/smb/client/smb2ops.c9
-rw-r--r--include/linux/fscache-cache.h2
-rw-r--r--include/linux/fscache.h11
15 files changed, 51 insertions, 35 deletions
diff --git a/Documentation/filesystems/caching/backend-api.rst b/Documentation/filesystems/caching/backend-api.rst
index 3a199fc50828..df837531b3fd 100644
--- a/Documentation/filesystems/caching/backend-api.rst
+++ b/Documentation/filesystems/caching/backend-api.rst
@@ -339,7 +339,7 @@ pointers to methods to allow fscache to request management of the cache:
* Change the size of a data storage object [mandatory]::
void (*resize_cookie)(struct netfs_cache_resources *cres,
- loff_t new_size);
+ loff_t new_size, bool shrank);
This method is called to inform the cache backend of a change in size of
the netfs file due to local truncation. The cache backend should make all
diff --git a/Documentation/filesystems/caching/netfs-api.rst b/Documentation/filesystems/caching/netfs-api.rst
index 665b27f1556e..3154a1686480 100644
--- a/Documentation/filesystems/caching/netfs-api.rst
+++ b/Documentation/filesystems/caching/netfs-api.rst
@@ -226,7 +226,7 @@ If a network filesystem file is resized locally by truncation, the following
should be called to notify the cache::
void fscache_resize_cookie(struct fscache_cookie *cookie,
- loff_t new_size);
+ loff_t new_size, bool shrank);
The caller must have first marked the cookie in-use. The cookie and the new
size are passed in and the cache is synchronously resized. This is expected to
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 3829554ca369..2d33c53da8d9 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1022,6 +1022,9 @@ static int v9fs_vfs_setattr(struct mnt_idmap *idmap,
struct v9fs_session_info *v9ses;
struct p9_fid *fid = NULL;
struct p9_wstat wstat;
+#ifdef CONFIG_9P_FSCACHE
+ uoff_t old_size = i_size_read(inode);
+#endif
p9_debug(P9_DEBUG_VFS, "\n");
retval = setattr_prepare(&nop_mnt_idmap, dentry, iattr);
@@ -1086,7 +1089,8 @@ static int v9fs_vfs_setattr(struct mnt_idmap *idmap,
if (v9ses->cache & CACHE_FSCACHE) {
struct v9fs_inode *v9inode = V9FS_I(inode);
- fscache_resize_cookie(v9fs_inode_cookie(v9inode), iattr->ia_size);
+ fscache_resize_cookie(v9fs_inode_cookie(v9inode),
+ iattr->ia_size, iattr->ia_size < old_size);
}
#endif
}
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 116b29e95f21..dde0dbea2685 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -519,6 +519,9 @@ int v9fs_vfs_setattr_dotl(struct mnt_idmap *idmap,
.uid = INVALID_UID,
.gid = INVALID_GID,
};
+#ifdef CONFIG_9P_FSCACHE
+ uoff_t old_size = i_size_read(inode);
+#endif
p9_debug(P9_DEBUG_VFS, "\n");
@@ -580,7 +583,7 @@ int v9fs_vfs_setattr_dotl(struct mnt_idmap *idmap,
#ifdef CONFIG_9P_FSCACHE
if (v9ses->cache & CACHE_FSCACHE)
fscache_resize_cookie(v9fs_inode_cookie(V9FS_I(inode)),
- iattr->ia_size);
+ iattr->ia_size, iattr->ia_size < old_size);
#endif
}
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 14f39a9bea6c..40baa35c8656 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -744,7 +744,7 @@ static void afs_setattr_edit_file(struct afs_operation *op)
if (size != old) {
truncate_pagecache(inode, size);
netfs_resize_file(&vnode->netfs, size, true);
- fscache_resize_cookie(afs_vnode_cache(vnode), size);
+ fscache_resize_cookie(afs_vnode_cache(vnode), size, size < old);
}
}
}
@@ -817,7 +817,7 @@ int afs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
truncate_setsize(inode, attr->ia_size);
netfs_resize_file(&vnode->netfs, size, false);
fscache_resize_cookie(afs_vnode_cache(vnode),
- attr->ia_size);
+ attr->ia_size, attr->ia_size < i_size);
ret = 0;
goto out_unlock;
}
diff --git a/fs/cachefiles/interface.c b/fs/cachefiles/interface.c
index 789ff6abe926..4a31904aaf0e 100644
--- a/fs/cachefiles/interface.c
+++ b/fs/cachefiles/interface.c
@@ -204,7 +204,7 @@ static bool cachefiles_shorten_object(struct cachefiles_object *object,
* Resize the backing object.
*/
static void cachefiles_resize_cookie(struct netfs_cache_resources *cres,
- uoff_t new_size)
+ uoff_t new_size, bool shrank)
{
struct cachefiles_object *object = cachefiles_cres_object(cres);
struct cachefiles_cache *cache = object->volume->cache;
@@ -215,10 +215,10 @@ static void cachefiles_resize_cookie(struct netfs_cache_resources *cres,
_enter("%llu->%llu", object->object_size, new_size);
- /* If the file is being shrunk, we need to downsize the backing file
- * and clear the end of the final block.
+ /* If the file shrank, we need to downsize the backing file and clear
+ * the end of the final block.
*/
- if (new_size < object->object_size) {
+ if (shrank) {
if (new_size >= i_size)
goto out;
cachefiles_begin_secure(cache, &saved_cred);
diff --git a/fs/ceph/cache.h b/fs/ceph/cache.h
index 20efac020394..892b18c31741 100644
--- a/fs/ceph/cache.h
+++ b/fs/ceph/cache.h
@@ -31,14 +31,14 @@ static inline struct fscache_cookie *ceph_fscache_cookie(struct ceph_inode_info
return netfs_i_cookie(&ci->netfs);
}
-static inline void ceph_fscache_resize(struct inode *inode, loff_t to)
+static inline void ceph_fscache_resize(struct inode *inode, loff_t to, bool shrank)
{
struct ceph_inode_info *ci = ceph_inode(inode);
struct fscache_cookie *cookie = ceph_fscache_cookie(ci);
if (cookie) {
ceph_fscache_use_cookie(inode, true);
- fscache_resize_cookie(cookie, to);
+ fscache_resize_cookie(cookie, to, shrank);
ceph_fscache_unuse_cookie(inode, true);
}
}
@@ -96,7 +96,7 @@ static inline struct fscache_cookie *ceph_fscache_cookie(struct ceph_inode_info
return NULL;
}
-static inline void ceph_fscache_resize(struct inode *inode, loff_t to)
+static inline void ceph_fscache_resize(struct inode *inode, loff_t to, bool shrank)
{
}
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index d52e2b389e0b..8ed63659ae58 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -680,7 +680,8 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
mutex_init(&ci->i_truncate_mutex);
ci->i_truncate_seq = 0;
ci->i_truncate_size = 0;
- ci->i_truncate_pending = 0;
+ ci->i_truncate_pending = false;
+ ci->i_truncate_shrank = false;
ci->i_truncate_pagecache_size = 0;
ci->i_max_size = 0;
@@ -847,7 +848,9 @@ int ceph_fill_file_size(struct inode *inode, int issued,
CEPH_CAP_FILE_BUFFER)) ||
mapping_mapped(inode->i_mapping) ||
__ceph_is_file_opened(ci)) {
- ci->i_truncate_pending++;
+ ci->i_truncate_pending = true;
+ if (size < isize)
+ ci->i_truncate_shrank = true;
queue_trunc = 1;
}
}
@@ -2304,12 +2307,13 @@ void __ceph_do_pending_vmtruncate(struct inode *inode)
struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
u64 to;
+ bool shrank;
int wrbuffer_refs, finish = 0;
mutex_lock(&ci->i_truncate_mutex);
retry:
spin_lock(&ci->i_ceph_lock);
- if (ci->i_truncate_pending == 0) {
+ if (!ci->i_truncate_pending) {
doutc(cl, "%p %llx.%llx none pending\n", inode,
ceph_vinop(inode));
spin_unlock(&ci->i_ceph_lock);
@@ -2333,18 +2337,20 @@ retry:
/* there should be no reader or writer */
WARN_ON_ONCE(ci->i_rd_ref || ci->i_wr_ref);
+ shrank = ci->i_truncate_shrank;
to = ci->i_truncate_pagecache_size;
wrbuffer_refs = ci->i_wrbuffer_ref;
doutc(cl, "%p %llx.%llx (%d) to %lld\n", inode, ceph_vinop(inode),
ci->i_truncate_pending, to);
spin_unlock(&ci->i_ceph_lock);
- ceph_fscache_resize(inode, to);
+ ceph_fscache_resize(inode, to, shrank);
truncate_pagecache(inode, to);
spin_lock(&ci->i_ceph_lock);
if (to == ci->i_truncate_pagecache_size) {
- ci->i_truncate_pending = 0;
+ ci->i_truncate_shrank = false;
+ ci->i_truncate_pending = false;
finish = 1;
}
spin_unlock(&ci->i_ceph_lock);
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 72d4e30304dc..e6eaf1647fe5 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -481,7 +481,8 @@ struct ceph_inode_info {
struct mutex i_truncate_mutex;
u32 i_truncate_seq; /* last truncate to smaller size */
u64 i_truncate_size; /* and the size we last truncated down to */
- int i_truncate_pending; /* still need to call vmtruncate */
+ bool i_truncate_pending; /* still need to call vmtruncate */
+ bool i_truncate_shrank; /* Truncate shrank the file */
/*
* For none fscrypt case it equals to i_truncate_size or it will
* equals to fscrypt_file_size
diff --git a/fs/netfs/fscache_io.c b/fs/netfs/fscache_io.c
index 056a2bae5d99..ea0b11807034 100644
--- a/fs/netfs/fscache_io.c
+++ b/fs/netfs/fscache_io.c
@@ -267,7 +267,7 @@ EXPORT_SYMBOL(__fscache_write_to_cache);
/*
* Change the size of a backing object.
*/
-void __fscache_resize_cookie(struct fscache_cookie *cookie, uoff_t new_size)
+void __fscache_resize_cookie(struct fscache_cookie *cookie, uoff_t new_size, bool shrank)
{
struct netfs_cache_resources cres;
@@ -281,7 +281,7 @@ void __fscache_resize_cookie(struct fscache_cookie *cookie, uoff_t new_size)
* netfs's inode lock so that we're serialised with respect to
* writes.
*/
- cookie->volume->cache->ops->resize_cookie(&cres, new_size);
+ cookie->volume->cache->ops->resize_cookie(&cres, new_size, shrank);
fscache_end_operation(&cres);
} else {
fscache_stat(&fscache_n_resizes_null);
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index 98b610b2a114..a60956a40aa9 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -1332,7 +1332,7 @@ static int cifs_precopy_set_eof(struct inode *src_inode, struct cifsInodeInfo *s
goto set_failed;
netfs_resize_file(&src_cifsi->netfs, src_end, true);
- fscache_resize_cookie(cifs_inode_cookie(src_inode), src_end);
+ fscache_resize_cookie(cifs_inode_cookie(src_inode), src_end, false);
return 0;
set_failed:
@@ -1626,9 +1626,9 @@ ssize_t cifs_file_copychunk_range(unsigned int xid,
if (rc > 0 && destoff + rc > i_size_read(target_inode)) {
truncate_setsize(target_inode, destoff + rc);
netfs_resize_file(&target_cifsi->netfs,
- i_size_read(target_inode), true);
+ destoff + rc, true);
fscache_resize_cookie(cifs_inode_cookie(target_inode),
- i_size_read(target_inode));
+ destoff + rc, false);
}
if (rc > 0) {
spin_lock(&target_inode->i_lock);
diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
index f29555f3c7d0..fb1afe72e6d2 100644
--- a/fs/smb/client/inode.c
+++ b/fs/smb/client/inode.c
@@ -3097,7 +3097,7 @@ void cifs_resize_file_locked(struct inode *inode, loff_t old_size,
return;
fscache_use_cookie(cookie, true);
- fscache_resize_cookie(cookie, offset);
+ fscache_resize_cookie(cookie, offset, offset < old_size);
cifs_fscache_unuse_inode_cookie(inode, true);
}
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 583ab4c4d773..279c41893f8e 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -3611,7 +3611,8 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
if (offset < cifsi->netfs._zero_point)
netfs_write_zero_point(inode, offset);
spin_unlock(&inode->i_lock);
- fscache_resize_cookie(cifs_inode_cookie(inode), new_size);
+ fscache_resize_cookie(cifs_inode_cookie(inode),
+ new_size, false);
}
}
@@ -4146,7 +4147,7 @@ static long smb3_collapse_range(struct file *file, struct cifs_tcon *tcon,
netfs_resize_file(&cifsi->netfs, new_eof, true);
netfs_write_zero_point(inode, new_eof);
spin_unlock(&inode->i_lock);
- fscache_resize_cookie(cifs_inode_cookie(inode), new_eof);
+ fscache_resize_cookie(cifs_inode_cookie(inode), new_eof, true);
out_2:
filemap_invalidate_unlock(inode->i_mapping);
out:
@@ -4206,9 +4207,9 @@ static long smb3_insert_range(struct file *file, struct cifs_tcon *tcon,
truncate_setsize(inode, new_eof);
spin_lock(&inode->i_lock);
- netfs_resize_file(&cifsi->netfs, i_size_read(inode), true);
+ netfs_resize_file(&cifsi->netfs, new_eof, true);
spin_unlock(&inode->i_lock);
- fscache_resize_cookie(cifs_inode_cookie(inode), i_size_read(inode));
+ fscache_resize_cookie(cifs_inode_cookie(inode), new_eof, false);
/*
* Move [off, old_eof) right by len. The helper copies backwards if the
diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h
index ee524c863fa9..2b83ffa4510e 100644
--- a/include/linux/fscache-cache.h
+++ b/include/linux/fscache-cache.h
@@ -67,7 +67,7 @@ struct fscache_cache_ops {
/* Change the size of a data object */
void (*resize_cookie)(struct netfs_cache_resources *cres,
- uoff_t new_size);
+ uoff_t new_size, bool shrank);
/* Invalidate an object */
bool (*invalidate_cookie)(struct fscache_cookie *cookie);
diff --git a/include/linux/fscache.h b/include/linux/fscache.h
index f2d958bd1f48..ecd14d645690 100644
--- a/include/linux/fscache.h
+++ b/include/linux/fscache.h
@@ -184,7 +184,7 @@ extern struct fscache_cookie *__fscache_acquire_cookie(
extern void __fscache_use_cookie(struct fscache_cookie *, bool);
extern void __fscache_unuse_cookie(struct fscache_cookie *, const void *, const uoff_t *);
extern void __fscache_relinquish_cookie(struct fscache_cookie *, bool);
-extern void __fscache_resize_cookie(struct fscache_cookie *, uoff_t);
+void __fscache_resize_cookie(struct fscache_cookie *cookie, uoff_t new_size, bool shrank);
extern void __fscache_invalidate(struct fscache_cookie *, const void *, uoff_t, unsigned int);
extern int __fscache_begin_read_operation(struct netfs_cache_resources *, struct fscache_cookie *);
extern int __fscache_begin_write_operation(struct netfs_cache_resources *, struct fscache_cookie *);
@@ -394,8 +394,9 @@ void fscache_update_cookie(struct fscache_cookie *cookie, const void *aux_data,
/**
* fscache_resize_cookie - Request that a cache object be resized
- * @cookie: The cookie representing the cache object
- * @new_size: The new size of the object (may be NULL)
+ * @cookie: The cookie representing the cache object (may be NULL)
+ * @new_size: The new size of the object
+ * @shrank: True if the file shrank; false if it expanded
*
* Request that the size of an object be changed.
*
@@ -403,10 +404,10 @@ void fscache_update_cookie(struct fscache_cookie *cookie, const void *aux_data,
* description.
*/
static inline
-void fscache_resize_cookie(struct fscache_cookie *cookie, uoff_t new_size)
+void fscache_resize_cookie(struct fscache_cookie *cookie, uoff_t new_size, bool shrank)
{
if (fscache_cookie_enabled(cookie))
- __fscache_resize_cookie(cookie, new_size);
+ __fscache_resize_cookie(cookie, new_size, shrank);
}
/**