aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2012-03-23 14:40:56 -0400
committerJeff Layton <jlayton@redhat.com>2012-03-23 14:40:56 -0400
commit597b027f694481ffeebcffe634c24b807198d46c (patch)
tree2dce2da017aa89c9e7465014ffa7aced11393b28 /fs/cifs
parente9492871fb0546f1b73f309d9e8c0f030bfdfdca (diff)
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')
-rw-r--r--fs/cifs/cifsglob.h2
-rw-r--r--fs/cifs/cifssmb.c2
-rw-r--r--fs/cifs/file.c9
3 files changed, 11 insertions, 2 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index d7e39b0de5b0..4ff6313f0a91 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -626,7 +626,7 @@ struct cifsInodeInfo {
626 bool delete_pending; /* DELETE_ON_CLOSE is set */ 626 bool delete_pending; /* DELETE_ON_CLOSE is set */
627 bool invalid_mapping; /* pagecache is invalid */ 627 bool invalid_mapping; /* pagecache is invalid */
628 unsigned long time; /* jiffies of last update of inode */ 628 unsigned long time; /* jiffies of last update of inode */
629 u64 server_eof; /* current file size on server */ 629 u64 server_eof; /* current file size on server -- protected by i_lock */
630 u64 uniqueid; /* server inode number */ 630 u64 uniqueid; /* server inode number */
631 u64 createtime; /* creation time on server */ 631 u64 createtime; /* creation time on server */
632#ifdef CONFIG_CIFS_FSCACHE 632#ifdef CONFIG_CIFS_FSCACHE
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 5ec0b90b0444..b63bf5f0698a 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -2044,7 +2044,9 @@ cifs_writev_complete(struct work_struct *work)
2044 int i = 0; 2044 int i = 0;
2045 2045
2046 if (wdata->result == 0) { 2046 if (wdata->result == 0) {
2047 spin_lock(&inode->i_lock);
2047 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes); 2048 cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes);
2049 spin_unlock(&inode->i_lock);
2048 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink), 2050 cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink),
2049 wdata->bytes); 2051 wdata->bytes);
2050 } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN) 2052 } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN)
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)
1399 return rc; 1399 return rc;
1400} 1400}
1401 1401
1402/* update the file size (if needed) after a write */ 1402/*
1403 * update the file size (if needed) after a write. Should be called with
1404 * the inode->i_lock held
1405 */
1403void 1406void
1404cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, 1407cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
1405 unsigned int bytes_written) 1408 unsigned int bytes_written)
@@ -1471,7 +1474,9 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid,
1471 return rc; 1474 return rc;
1472 } 1475 }
1473 } else { 1476 } else {
1477 spin_lock(&dentry->d_inode->i_lock);
1474 cifs_update_eof(cifsi, *poffset, bytes_written); 1478 cifs_update_eof(cifsi, *poffset, bytes_written);
1479 spin_unlock(&dentry->d_inode->i_lock);
1475 *poffset += bytes_written; 1480 *poffset += bytes_written;
1476 } 1481 }
1477 } 1482 }
@@ -2197,7 +2202,9 @@ cifs_iovec_write(struct file *file, const struct iovec *iov,
2197 if (written) { 2202 if (written) {
2198 len -= written; 2203 len -= written;
2199 total_written += written; 2204 total_written += written;
2205 spin_lock(&inode->i_lock);
2200 cifs_update_eof(CIFS_I(inode), *poffset, written); 2206 cifs_update_eof(CIFS_I(inode), *poffset, written);
2207 spin_unlock(&inode->i_lock);
2201 *poffset += written; 2208 *poffset += written;
2202 } else if (rc < 0) { 2209 } else if (rc < 0) {
2203 if (!total_written) 2210 if (!total_written)