diff options
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r-- | fs/cifs/file.c | 57 |
1 files changed, 18 insertions, 39 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 45af003865d2..ae82159cf7fa 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -131,8 +131,7 @@ static inline int cifs_open_inode_helper(struct inode *inode, | |||
131 | /* BB no need to lock inode until after invalidate | 131 | /* BB no need to lock inode until after invalidate |
132 | since namei code should already have it locked? */ | 132 | since namei code should already have it locked? */ |
133 | rc = filemap_write_and_wait(inode->i_mapping); | 133 | rc = filemap_write_and_wait(inode->i_mapping); |
134 | if (rc != 0) | 134 | mapping_set_error(inode->i_mapping, rc); |
135 | pCifsInode->write_behind_rc = rc; | ||
136 | } | 135 | } |
137 | cFYI(1, "invalidating remote inode since open detected it " | 136 | cFYI(1, "invalidating remote inode since open detected it " |
138 | "changed"); | 137 | "changed"); |
@@ -232,6 +231,7 @@ cifs_new_fileinfo(__u16 fileHandle, struct file *file, | |||
232 | if (pCifsFile == NULL) | 231 | if (pCifsFile == NULL) |
233 | return pCifsFile; | 232 | return pCifsFile; |
234 | 233 | ||
234 | pCifsFile->count = 1; | ||
235 | pCifsFile->netfid = fileHandle; | 235 | pCifsFile->netfid = fileHandle; |
236 | pCifsFile->pid = current->tgid; | 236 | pCifsFile->pid = current->tgid; |
237 | pCifsFile->uid = current_fsuid(); | 237 | pCifsFile->uid = current_fsuid(); |
@@ -242,7 +242,6 @@ cifs_new_fileinfo(__u16 fileHandle, struct file *file, | |||
242 | mutex_init(&pCifsFile->fh_mutex); | 242 | mutex_init(&pCifsFile->fh_mutex); |
243 | mutex_init(&pCifsFile->lock_mutex); | 243 | mutex_init(&pCifsFile->lock_mutex); |
244 | INIT_LIST_HEAD(&pCifsFile->llist); | 244 | INIT_LIST_HEAD(&pCifsFile->llist); |
245 | atomic_set(&pCifsFile->count, 1); | ||
246 | INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break); | 245 | INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break); |
247 | 246 | ||
248 | spin_lock(&cifs_file_list_lock); | 247 | spin_lock(&cifs_file_list_lock); |
@@ -267,7 +266,8 @@ cifs_new_fileinfo(__u16 fileHandle, struct file *file, | |||
267 | 266 | ||
268 | /* | 267 | /* |
269 | * Release a reference on the file private data. This may involve closing | 268 | * Release a reference on the file private data. This may involve closing |
270 | * the filehandle out on the server. | 269 | * the filehandle out on the server. Must be called without holding |
270 | * cifs_file_list_lock. | ||
271 | */ | 271 | */ |
272 | void cifsFileInfo_put(struct cifsFileInfo *cifs_file) | 272 | void cifsFileInfo_put(struct cifsFileInfo *cifs_file) |
273 | { | 273 | { |
@@ -276,7 +276,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) | |||
276 | struct cifsLockInfo *li, *tmp; | 276 | struct cifsLockInfo *li, *tmp; |
277 | 277 | ||
278 | spin_lock(&cifs_file_list_lock); | 278 | spin_lock(&cifs_file_list_lock); |
279 | if (!atomic_dec_and_test(&cifs_file->count)) { | 279 | if (--cifs_file->count > 0) { |
280 | spin_unlock(&cifs_file_list_lock); | 280 | spin_unlock(&cifs_file_list_lock); |
281 | return; | 281 | return; |
282 | } | 282 | } |
@@ -605,8 +605,7 @@ reopen_success: | |||
605 | 605 | ||
606 | if (can_flush) { | 606 | if (can_flush) { |
607 | rc = filemap_write_and_wait(inode->i_mapping); | 607 | rc = filemap_write_and_wait(inode->i_mapping); |
608 | if (rc != 0) | 608 | mapping_set_error(inode->i_mapping, rc); |
609 | CIFS_I(inode)->write_behind_rc = rc; | ||
610 | 609 | ||
611 | pCifsInode->clientCanCacheAll = false; | 610 | pCifsInode->clientCanCacheAll = false; |
612 | pCifsInode->clientCanCacheRead = false; | 611 | pCifsInode->clientCanCacheRead = false; |
@@ -1353,6 +1352,7 @@ static int cifs_writepages(struct address_space *mapping, | |||
1353 | if (!experimEnabled && tcon->ses->server->secMode & | 1352 | if (!experimEnabled && tcon->ses->server->secMode & |
1354 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { | 1353 | (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { |
1355 | cifsFileInfo_put(open_file); | 1354 | cifsFileInfo_put(open_file); |
1355 | kfree(iov); | ||
1356 | return generic_writepages(mapping, wbc); | 1356 | return generic_writepages(mapping, wbc); |
1357 | } | 1357 | } |
1358 | cifsFileInfo_put(open_file); | 1358 | cifsFileInfo_put(open_file); |
@@ -1478,12 +1478,7 @@ retry: | |||
1478 | if (rc || bytes_written < bytes_to_write) { | 1478 | if (rc || bytes_written < bytes_to_write) { |
1479 | cERROR(1, "Write2 ret %d, wrote %d", | 1479 | cERROR(1, "Write2 ret %d, wrote %d", |
1480 | rc, bytes_written); | 1480 | rc, bytes_written); |
1481 | /* BB what if continued retry is | 1481 | mapping_set_error(mapping, rc); |
1482 | requested via mount flags? */ | ||
1483 | if (rc == -ENOSPC) | ||
1484 | set_bit(AS_ENOSPC, &mapping->flags); | ||
1485 | else | ||
1486 | set_bit(AS_EIO, &mapping->flags); | ||
1487 | } else { | 1482 | } else { |
1488 | cifs_stats_bytes_written(tcon, bytes_written); | 1483 | cifs_stats_bytes_written(tcon, bytes_written); |
1489 | } | 1484 | } |
@@ -1628,11 +1623,10 @@ int cifs_fsync(struct file *file, int datasync) | |||
1628 | 1623 | ||
1629 | rc = filemap_write_and_wait(inode->i_mapping); | 1624 | rc = filemap_write_and_wait(inode->i_mapping); |
1630 | if (rc == 0) { | 1625 | if (rc == 0) { |
1631 | rc = CIFS_I(inode)->write_behind_rc; | 1626 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); |
1632 | CIFS_I(inode)->write_behind_rc = 0; | 1627 | |
1633 | tcon = tlink_tcon(smbfile->tlink); | 1628 | tcon = tlink_tcon(smbfile->tlink); |
1634 | if (!rc && tcon && smbfile && | 1629 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) |
1635 | !(CIFS_SB(inode->i_sb)->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | ||
1636 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); | 1630 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); |
1637 | } | 1631 | } |
1638 | 1632 | ||
@@ -1677,21 +1671,8 @@ int cifs_flush(struct file *file, fl_owner_t id) | |||
1677 | struct inode *inode = file->f_path.dentry->d_inode; | 1671 | struct inode *inode = file->f_path.dentry->d_inode; |
1678 | int rc = 0; | 1672 | int rc = 0; |
1679 | 1673 | ||
1680 | /* Rather than do the steps manually: | 1674 | if (file->f_mode & FMODE_WRITE) |
1681 | lock the inode for writing | 1675 | rc = filemap_write_and_wait(inode->i_mapping); |
1682 | loop through pages looking for write behind data (dirty pages) | ||
1683 | coalesce into contiguous 16K (or smaller) chunks to write to server | ||
1684 | send to server (prefer in parallel) | ||
1685 | deal with writebehind errors | ||
1686 | unlock inode for writing | ||
1687 | filemapfdatawrite appears easier for the time being */ | ||
1688 | |||
1689 | rc = filemap_fdatawrite(inode->i_mapping); | ||
1690 | /* reset wb rc if we were able to write out dirty pages */ | ||
1691 | if (!rc) { | ||
1692 | rc = CIFS_I(inode)->write_behind_rc; | ||
1693 | CIFS_I(inode)->write_behind_rc = 0; | ||
1694 | } | ||
1695 | 1676 | ||
1696 | cFYI(1, "Flush inode %p file %p rc %d", inode, file, rc); | 1677 | cFYI(1, "Flush inode %p file %p rc %d", inode, file, rc); |
1697 | 1678 | ||
@@ -2270,7 +2251,7 @@ void cifs_oplock_break(struct work_struct *work) | |||
2270 | oplock_break); | 2251 | oplock_break); |
2271 | struct inode *inode = cfile->dentry->d_inode; | 2252 | struct inode *inode = cfile->dentry->d_inode; |
2272 | struct cifsInodeInfo *cinode = CIFS_I(inode); | 2253 | struct cifsInodeInfo *cinode = CIFS_I(inode); |
2273 | int rc, waitrc = 0; | 2254 | int rc = 0; |
2274 | 2255 | ||
2275 | if (inode && S_ISREG(inode->i_mode)) { | 2256 | if (inode && S_ISREG(inode->i_mode)) { |
2276 | if (cinode->clientCanCacheRead) | 2257 | if (cinode->clientCanCacheRead) |
@@ -2279,13 +2260,10 @@ void cifs_oplock_break(struct work_struct *work) | |||
2279 | break_lease(inode, O_WRONLY); | 2260 | break_lease(inode, O_WRONLY); |
2280 | rc = filemap_fdatawrite(inode->i_mapping); | 2261 | rc = filemap_fdatawrite(inode->i_mapping); |
2281 | if (cinode->clientCanCacheRead == 0) { | 2262 | if (cinode->clientCanCacheRead == 0) { |
2282 | waitrc = filemap_fdatawait(inode->i_mapping); | 2263 | rc = filemap_fdatawait(inode->i_mapping); |
2264 | mapping_set_error(inode->i_mapping, rc); | ||
2283 | invalidate_remote_inode(inode); | 2265 | invalidate_remote_inode(inode); |
2284 | } | 2266 | } |
2285 | if (!rc) | ||
2286 | rc = waitrc; | ||
2287 | if (rc) | ||
2288 | cinode->write_behind_rc = rc; | ||
2289 | cFYI(1, "Oplock flush inode %p rc %d", inode, rc); | 2267 | cFYI(1, "Oplock flush inode %p rc %d", inode, rc); |
2290 | } | 2268 | } |
2291 | 2269 | ||
@@ -2304,7 +2282,7 @@ void cifs_oplock_break(struct work_struct *work) | |||
2304 | /* | 2282 | /* |
2305 | * We might have kicked in before is_valid_oplock_break() | 2283 | * We might have kicked in before is_valid_oplock_break() |
2306 | * finished grabbing reference for us. Make sure it's done by | 2284 | * finished grabbing reference for us. Make sure it's done by |
2307 | * waiting for GlobalSMSSeslock. | 2285 | * waiting for cifs_file_list_lock. |
2308 | */ | 2286 | */ |
2309 | spin_lock(&cifs_file_list_lock); | 2287 | spin_lock(&cifs_file_list_lock); |
2310 | spin_unlock(&cifs_file_list_lock); | 2288 | spin_unlock(&cifs_file_list_lock); |
@@ -2312,6 +2290,7 @@ void cifs_oplock_break(struct work_struct *work) | |||
2312 | cifs_oplock_break_put(cfile); | 2290 | cifs_oplock_break_put(cfile); |
2313 | } | 2291 | } |
2314 | 2292 | ||
2293 | /* must be called while holding cifs_file_list_lock */ | ||
2315 | void cifs_oplock_break_get(struct cifsFileInfo *cfile) | 2294 | void cifs_oplock_break_get(struct cifsFileInfo *cfile) |
2316 | { | 2295 | { |
2317 | cifs_sb_active(cfile->dentry->d_sb); | 2296 | cifs_sb_active(cfile->dentry->d_sb); |