summaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
authorJeff Layton2012-03-23 19:40:56 +0100
committerJeff Layton2012-03-23 19:40:56 +0100
commit597b027f694481ffeebcffe634c24b807198d46c (patch)
tree2dce2da017aa89c9e7465014ffa7aced11393b28 /fs/cifs/file.c
parentcifs: abstract out function to marshal up the iovec array for async writes (diff)
downloadkernel-qcow2-linux-597b027f694481ffeebcffe634c24b807198d46c.tar.gz
kernel-qcow2-linux-597b027f694481ffeebcffe634c24b807198d46c.tar.xz
kernel-qcow2-linux-597b027f694481ffeebcffe634c24b807198d46c.zip
cifs: call cifs_update_eof with i_lock held
cifs_update_eof has the potential to be racy if multiple threads are trying to modify it at the same time. Protect modifications of the server_eof value with the inode->i_lock. Signed-off-by: Jeff Layton <jlayton@redhat.com>
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r--fs/cifs/file.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 58ac0f0512e7..6883b08f848c 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -1399,7 +1399,10 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
return rc;
}
-/* update the file size (if needed) after a write */
+/*
+ * update the file size (if needed) after a write. Should be called with
+ * the inode->i_lock held
+ */
void
cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
unsigned int bytes_written)
@@ -1471,7 +1474,9 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid,
return rc;
}
} else {
+ spin_lock(&dentry->d_inode->i_lock);
cifs_update_eof(cifsi, *poffset, bytes_written);
+ spin_unlock(&dentry->d_inode->i_lock);
*poffset += bytes_written;
}
}
@@ -2197,7 +2202,9 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
if (written) {
len -= written;
total_written += written;
+ spin_lock(&inode->i_lock);
cifs_update_eof(CIFS_I(inode), *poffset, written);
+ spin_unlock(&inode->i_lock);
*poffset += written;
} else if (rc < 0) {
if (!total_written)