summaryrefslogtreecommitdiff
path: root/fs/afs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/afs/file.c')
-rw-r--r--fs/afs/file.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/fs/afs/file.c b/fs/afs/file.c
index 74d04af51ff4..650595e1c3f3 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -424,21 +424,35 @@ static void afs_free_request(struct netfs_io_request *rreq)
afs_put_wb_key(rreq->netfs_priv2);
}
-static void afs_update_i_size(struct inode *inode, loff_t new_i_size)
+/*
+ * Set the file size and block count, taking ->cb_lock and ->i_lock to maintain
+ * coherency and prevent 64-bit tearing on 32-bit arches.
+ *
+ * Also, estimate the number of 512 bytes blocks used, rounded up to nearest 1K
+ * for consistency with other AFS clients.
+ */
+void afs_set_i_size(struct afs_vnode *vnode, loff_t new_i_size)
{
- struct afs_vnode *vnode = AFS_FS_I(inode);
+ struct inode *inode = &vnode->netfs.inode;
loff_t i_size;
write_seqlock(&vnode->cb_lock);
- i_size = i_size_read(&vnode->netfs.inode);
+ spin_lock(&inode->i_lock);
+ i_size = i_size_read(inode);
if (new_i_size > i_size) {
- i_size_write(&vnode->netfs.inode, new_i_size);
- inode_set_bytes(&vnode->netfs.inode, new_i_size);
+ i_size_write(inode, new_i_size);
+ inode_set_bytes(inode, round_up(new_i_size, 1024));
}
+ spin_unlock(&inode->i_lock);
write_sequnlock(&vnode->cb_lock);
fscache_update_cookie(afs_vnode_cache(vnode), NULL, &new_i_size);
}
+static void afs_update_i_size(struct inode *inode, loff_t new_i_size)
+{
+ afs_set_i_size(AFS_FS_I(inode), new_i_size);
+}
+
static void afs_netfs_invalidate_cache(struct netfs_io_request *wreq)
{
struct afs_vnode *vnode = AFS_FS_I(wreq->inode);