diff options
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 51 |
1 files changed, 17 insertions, 34 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index dd922a5f9cae..d5f3007364e3 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1027,8 +1027,9 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
1027 | return total_written; | 1027 | return total_written; |
1028 | } | 1028 | } |
1029 | 1029 | ||
1030 | static ssize_t cifs_write(struct file *file, const char *write_data, | 1030 | static ssize_t cifs_write(struct cifsFileInfo *open_file, |
1031 | size_t write_size, loff_t *poffset) | 1031 | const char *write_data, size_t write_size, |
1032 | loff_t *poffset) | ||
1032 | { | 1033 | { |
1033 | int rc = 0; | 1034 | int rc = 0; |
1034 | unsigned int bytes_written = 0; | 1035 | unsigned int bytes_written = 0; |
@@ -1036,17 +1037,14 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
1036 | struct cifs_sb_info *cifs_sb; | 1037 | struct cifs_sb_info *cifs_sb; |
1037 | struct cifsTconInfo *pTcon; | 1038 | struct cifsTconInfo *pTcon; |
1038 | int xid, long_op; | 1039 | int xid, long_op; |
1039 | struct cifsFileInfo *open_file; | 1040 | struct dentry *dentry = open_file->dentry; |
1040 | struct cifsInodeInfo *cifsi = CIFS_I(file->f_path.dentry->d_inode); | 1041 | struct cifsInodeInfo *cifsi = CIFS_I(dentry->d_inode); |
1041 | 1042 | ||
1042 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 1043 | cifs_sb = CIFS_SB(dentry->d_sb); |
1043 | 1044 | ||
1044 | cFYI(1, "write %zd bytes to offset %lld of %s", write_size, | 1045 | cFYI(1, "write %zd bytes to offset %lld of %s", write_size, |
1045 | *poffset, file->f_path.dentry->d_name.name); | 1046 | *poffset, dentry->d_name.name); |
1046 | 1047 | ||
1047 | if (file->private_data == NULL) | ||
1048 | return -EBADF; | ||
1049 | open_file = file->private_data; | ||
1050 | pTcon = tlink_tcon(open_file->tlink); | 1048 | pTcon = tlink_tcon(open_file->tlink); |
1051 | 1049 | ||
1052 | xid = GetXid(); | 1050 | xid = GetXid(); |
@@ -1056,15 +1054,6 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
1056 | total_written += bytes_written) { | 1054 | total_written += bytes_written) { |
1057 | rc = -EAGAIN; | 1055 | rc = -EAGAIN; |
1058 | while (rc == -EAGAIN) { | 1056 | while (rc == -EAGAIN) { |
1059 | if (file->private_data == NULL) { | ||
1060 | /* file has been closed on us */ | ||
1061 | FreeXid(xid); | ||
1062 | /* if we have gotten here we have written some data | ||
1063 | and blocked, and the file has been freed on us | ||
1064 | while we blocked so return what we managed to | ||
1065 | write */ | ||
1066 | return total_written; | ||
1067 | } | ||
1068 | if (open_file->closePend) { | 1057 | if (open_file->closePend) { |
1069 | FreeXid(xid); | 1058 | FreeXid(xid); |
1070 | if (total_written) | 1059 | if (total_written) |
@@ -1124,20 +1113,13 @@ static ssize_t cifs_write(struct file *file, const char *write_data, | |||
1124 | 1113 | ||
1125 | cifs_stats_bytes_written(pTcon, total_written); | 1114 | cifs_stats_bytes_written(pTcon, total_written); |
1126 | 1115 | ||
1127 | /* since the write may have blocked check these pointers again */ | 1116 | if (total_written > 0) { |
1128 | if ((file->f_path.dentry) && (file->f_path.dentry->d_inode)) { | 1117 | spin_lock(&dentry->d_inode->i_lock); |
1129 | /*BB We could make this contingent on superblock ATIME flag too */ | 1118 | if (*poffset > dentry->d_inode->i_size) |
1130 | /* file->f_path.dentry->d_inode->i_ctime = | 1119 | i_size_write(dentry->d_inode, *poffset); |
1131 | file->f_path.dentry->d_inode->i_mtime = CURRENT_TIME;*/ | 1120 | spin_unlock(&dentry->d_inode->i_lock); |
1132 | if (total_written > 0) { | ||
1133 | spin_lock(&file->f_path.dentry->d_inode->i_lock); | ||
1134 | if (*poffset > file->f_path.dentry->d_inode->i_size) | ||
1135 | i_size_write(file->f_path.dentry->d_inode, | ||
1136 | *poffset); | ||
1137 | spin_unlock(&file->f_path.dentry->d_inode->i_lock); | ||
1138 | } | ||
1139 | mark_inode_dirty_sync(file->f_path.dentry->d_inode); | ||
1140 | } | 1121 | } |
1122 | mark_inode_dirty_sync(dentry->d_inode); | ||
1141 | FreeXid(xid); | 1123 | FreeXid(xid); |
1142 | return total_written; | 1124 | return total_written; |
1143 | } | 1125 | } |
@@ -1308,8 +1290,8 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) | |||
1308 | 1290 | ||
1309 | open_file = find_writable_file(CIFS_I(mapping->host), false); | 1291 | open_file = find_writable_file(CIFS_I(mapping->host), false); |
1310 | if (open_file) { | 1292 | if (open_file) { |
1311 | bytes_written = cifs_write(open_file->pfile, write_data, | 1293 | bytes_written = cifs_write(open_file, write_data, |
1312 | to-from, &offset); | 1294 | to - from, &offset); |
1313 | cifsFileInfo_put(open_file); | 1295 | cifsFileInfo_put(open_file); |
1314 | /* Does mm or vfs already set times? */ | 1296 | /* Does mm or vfs already set times? */ |
1315 | inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb); | 1297 | inode->i_atime = inode->i_mtime = current_fs_time(inode->i_sb); |
@@ -1624,7 +1606,8 @@ static int cifs_write_end(struct file *file, struct address_space *mapping, | |||
1624 | /* BB check if anything else missing out of ppw | 1606 | /* BB check if anything else missing out of ppw |
1625 | such as updating last write time */ | 1607 | such as updating last write time */ |
1626 | page_data = kmap(page); | 1608 | page_data = kmap(page); |
1627 | rc = cifs_write(file, page_data + offset, copied, &pos); | 1609 | rc = cifs_write(file->private_data, page_data + offset, |
1610 | copied, &pos); | ||
1628 | /* if (rc < 0) should we set writebehind rc? */ | 1611 | /* if (rc < 0) should we set writebehind rc? */ |
1629 | kunmap(page); | 1612 | kunmap(page); |
1630 | 1613 | ||