diff options
Diffstat (limited to 'fs/cifs/file.c')
| -rw-r--r-- | fs/cifs/file.c | 187 |
1 files changed, 60 insertions, 127 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index a3634e43bd4f..8c81e7b14d53 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -238,7 +238,6 @@ cifs_new_fileinfo(__u16 fileHandle, struct file *file, | |||
| 238 | pCifsFile->dentry = dget(dentry); | 238 | pCifsFile->dentry = dget(dentry); |
| 239 | pCifsFile->f_flags = file->f_flags; | 239 | pCifsFile->f_flags = file->f_flags; |
| 240 | pCifsFile->invalidHandle = false; | 240 | pCifsFile->invalidHandle = false; |
| 241 | pCifsFile->closePend = false; | ||
| 242 | pCifsFile->tlink = cifs_get_tlink(tlink); | 241 | pCifsFile->tlink = cifs_get_tlink(tlink); |
| 243 | mutex_init(&pCifsFile->fh_mutex); | 242 | mutex_init(&pCifsFile->fh_mutex); |
| 244 | mutex_init(&pCifsFile->lock_mutex); | 243 | mutex_init(&pCifsFile->lock_mutex); |
| @@ -266,14 +265,55 @@ cifs_new_fileinfo(__u16 fileHandle, struct file *file, | |||
| 266 | return pCifsFile; | 265 | return pCifsFile; |
| 267 | } | 266 | } |
| 268 | 267 | ||
| 269 | /* Release a reference on the file private data */ | 268 | /* |
| 269 | * Release a reference on the file private data. This may involve closing | ||
| 270 | * the filehandle out on the server. | ||
| 271 | */ | ||
| 270 | void cifsFileInfo_put(struct cifsFileInfo *cifs_file) | 272 | void cifsFileInfo_put(struct cifsFileInfo *cifs_file) |
| 271 | { | 273 | { |
| 272 | if (atomic_dec_and_test(&cifs_file->count)) { | 274 | struct cifsTconInfo *tcon = tlink_tcon(cifs_file->tlink); |
| 273 | cifs_put_tlink(cifs_file->tlink); | 275 | struct cifsInodeInfo *cifsi = CIFS_I(cifs_file->dentry->d_inode); |
| 274 | dput(cifs_file->dentry); | 276 | struct cifsLockInfo *li, *tmp; |
| 275 | kfree(cifs_file); | 277 | |
| 278 | spin_lock(&cifs_file_list_lock); | ||
| 279 | if (!atomic_dec_and_test(&cifs_file->count)) { | ||
| 280 | spin_unlock(&cifs_file_list_lock); | ||
| 281 | return; | ||
| 282 | } | ||
| 283 | |||
| 284 | /* remove it from the lists */ | ||
| 285 | list_del(&cifs_file->flist); | ||
| 286 | list_del(&cifs_file->tlist); | ||
| 287 | |||
| 288 | if (list_empty(&cifsi->openFileList)) { | ||
| 289 | cFYI(1, "closing last open instance for inode %p", | ||
| 290 | cifs_file->dentry->d_inode); | ||
| 291 | cifsi->clientCanCacheRead = false; | ||
| 292 | cifsi->clientCanCacheAll = false; | ||
| 293 | } | ||
| 294 | spin_unlock(&cifs_file_list_lock); | ||
| 295 | |||
| 296 | if (!tcon->need_reconnect && !cifs_file->invalidHandle) { | ||
| 297 | int xid, rc; | ||
| 298 | |||
| 299 | xid = GetXid(); | ||
| 300 | rc = CIFSSMBClose(xid, tcon, cifs_file->netfid); | ||
| 301 | FreeXid(xid); | ||
| 302 | } | ||
| 303 | |||
| 304 | /* Delete any outstanding lock records. We'll lose them when the file | ||
| 305 | * is closed anyway. | ||
| 306 | */ | ||
| 307 | mutex_lock(&cifs_file->lock_mutex); | ||
| 308 | list_for_each_entry_safe(li, tmp, &cifs_file->llist, llist) { | ||
| 309 | list_del(&li->llist); | ||
| 310 | kfree(li); | ||
| 276 | } | 311 | } |
| 312 | mutex_unlock(&cifs_file->lock_mutex); | ||
| 313 | |||
| 314 | cifs_put_tlink(cifs_file->tlink); | ||
| 315 | dput(cifs_file->dentry); | ||
| 316 | kfree(cifs_file); | ||
| 277 | } | 317 | } |
| 278 | 318 | ||
| 279 | int cifs_open(struct inode *inode, struct file *file) | 319 | int cifs_open(struct inode *inode, struct file *file) |
| @@ -605,79 +645,11 @@ reopen_error_exit: | |||
| 605 | 645 | ||
| 606 | int cifs_close(struct inode *inode, struct file *file) | 646 | int cifs_close(struct inode *inode, struct file *file) |
| 607 | { | 647 | { |
| 608 | int rc = 0; | 648 | cifsFileInfo_put(file->private_data); |
| 609 | int xid, timeout; | 649 | file->private_data = NULL; |
| 610 | struct cifs_sb_info *cifs_sb; | ||
| 611 | struct cifsTconInfo *pTcon; | ||
| 612 | struct cifsFileInfo *pSMBFile = file->private_data; | ||
| 613 | |||
| 614 | xid = GetXid(); | ||
| 615 | |||
| 616 | cifs_sb = CIFS_SB(inode->i_sb); | ||
| 617 | pTcon = tlink_tcon(pSMBFile->tlink); | ||
| 618 | if (pSMBFile) { | ||
| 619 | struct cifsLockInfo *li, *tmp; | ||
| 620 | spin_lock(&cifs_file_list_lock); | ||
| 621 | pSMBFile->closePend = true; | ||
| 622 | if (pTcon) { | ||
| 623 | /* no sense reconnecting to close a file that is | ||
| 624 | already closed */ | ||
| 625 | if (!pTcon->need_reconnect) { | ||
| 626 | spin_unlock(&cifs_file_list_lock); | ||
| 627 | timeout = 2; | ||
| 628 | while ((atomic_read(&pSMBFile->count) != 1) | ||
| 629 | && (timeout <= 2048)) { | ||
| 630 | /* Give write a better chance to get to | ||
| 631 | server ahead of the close. We do not | ||
| 632 | want to add a wait_q here as it would | ||
| 633 | increase the memory utilization as | ||
| 634 | the struct would be in each open file, | ||
| 635 | but this should give enough time to | ||
| 636 | clear the socket */ | ||
| 637 | cFYI(DBG2, "close delay, write pending"); | ||
| 638 | msleep(timeout); | ||
| 639 | timeout *= 4; | ||
| 640 | } | ||
| 641 | if (!pTcon->need_reconnect && | ||
| 642 | !pSMBFile->invalidHandle) | ||
| 643 | rc = CIFSSMBClose(xid, pTcon, | ||
| 644 | pSMBFile->netfid); | ||
| 645 | } else | ||
| 646 | spin_unlock(&cifs_file_list_lock); | ||
| 647 | } else | ||
| 648 | spin_unlock(&cifs_file_list_lock); | ||
| 649 | |||
| 650 | /* Delete any outstanding lock records. | ||
| 651 | We'll lose them when the file is closed anyway. */ | ||
| 652 | mutex_lock(&pSMBFile->lock_mutex); | ||
| 653 | list_for_each_entry_safe(li, tmp, &pSMBFile->llist, llist) { | ||
| 654 | list_del(&li->llist); | ||
| 655 | kfree(li); | ||
| 656 | } | ||
| 657 | mutex_unlock(&pSMBFile->lock_mutex); | ||
| 658 | 650 | ||
| 659 | spin_lock(&cifs_file_list_lock); | 651 | /* return code from the ->release op is always ignored */ |
| 660 | list_del(&pSMBFile->flist); | 652 | return 0; |
| 661 | list_del(&pSMBFile->tlist); | ||
| 662 | spin_unlock(&cifs_file_list_lock); | ||
| 663 | cifsFileInfo_put(file->private_data); | ||
| 664 | file->private_data = NULL; | ||
| 665 | } else | ||
| 666 | rc = -EBADF; | ||
| 667 | |||
| 668 | spin_lock(&cifs_file_list_lock); | ||
| 669 | if (list_empty(&(CIFS_I(inode)->openFileList))) { | ||
| 670 | cFYI(1, "closing last open instance for inode %p", inode); | ||
| 671 | /* if the file is not open we do not know if we can cache info | ||
| 672 | on this inode, much less write behind and read ahead */ | ||
| 673 | CIFS_I(inode)->clientCanCacheRead = false; | ||
| 674 | CIFS_I(inode)->clientCanCacheAll = false; | ||
| 675 | } | ||
| 676 | spin_unlock(&cifs_file_list_lock); | ||
| 677 | if ((rc == 0) && CIFS_I(inode)->write_behind_rc) | ||
| 678 | rc = CIFS_I(inode)->write_behind_rc; | ||
| 679 | FreeXid(xid); | ||
| 680 | return rc; | ||
| 681 | } | 653 | } |
| 682 | 654 | ||
| 683 | int cifs_closedir(struct inode *inode, struct file *file) | 655 | int cifs_closedir(struct inode *inode, struct file *file) |
| @@ -1024,13 +996,6 @@ ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
| 1024 | we blocked so return what we managed to write */ | 996 | we blocked so return what we managed to write */ |
| 1025 | return total_written; | 997 | return total_written; |
| 1026 | } | 998 | } |
| 1027 | if (open_file->closePend) { | ||
| 1028 | FreeXid(xid); | ||
| 1029 | if (total_written) | ||
| 1030 | return total_written; | ||
| 1031 | else | ||
| 1032 | return -EBADF; | ||
| 1033 | } | ||
| 1034 | if (open_file->invalidHandle) { | 999 | if (open_file->invalidHandle) { |
| 1035 | /* we could deadlock if we called | 1000 | /* we could deadlock if we called |
| 1036 | filemap_fdatawait from here so tell | 1001 | filemap_fdatawait from here so tell |
| @@ -1111,13 +1076,6 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, | |||
| 1111 | total_written += bytes_written) { | 1076 | total_written += bytes_written) { |
| 1112 | rc = -EAGAIN; | 1077 | rc = -EAGAIN; |
| 1113 | while (rc == -EAGAIN) { | 1078 | while (rc == -EAGAIN) { |
| 1114 | if (open_file->closePend) { | ||
| 1115 | FreeXid(xid); | ||
| 1116 | if (total_written) | ||
| 1117 | return total_written; | ||
| 1118 | else | ||
| 1119 | return -EBADF; | ||
| 1120 | } | ||
| 1121 | if (open_file->invalidHandle) { | 1079 | if (open_file->invalidHandle) { |
| 1122 | /* we could deadlock if we called | 1080 | /* we could deadlock if we called |
| 1123 | filemap_fdatawait from here so tell | 1081 | filemap_fdatawait from here so tell |
| @@ -1197,8 +1155,6 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, | |||
| 1197 | are always at the end of the list but since the first entry might | 1155 | are always at the end of the list but since the first entry might |
| 1198 | have a close pending, we go through the whole list */ | 1156 | have a close pending, we go through the whole list */ |
| 1199 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { | 1157 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { |
| 1200 | if (open_file->closePend) | ||
| 1201 | continue; | ||
| 1202 | if (fsuid_only && open_file->uid != current_fsuid()) | 1158 | if (fsuid_only && open_file->uid != current_fsuid()) |
| 1203 | continue; | 1159 | continue; |
| 1204 | if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) { | 1160 | if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) { |
| @@ -1244,8 +1200,6 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, | |||
| 1244 | spin_lock(&cifs_file_list_lock); | 1200 | spin_lock(&cifs_file_list_lock); |
| 1245 | refind_writable: | 1201 | refind_writable: |
| 1246 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { | 1202 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { |
| 1247 | if (open_file->closePend) | ||
| 1248 | continue; | ||
| 1249 | if (!any_available && open_file->pid != current->tgid) | 1203 | if (!any_available && open_file->pid != current->tgid) |
| 1250 | continue; | 1204 | continue; |
| 1251 | if (fsuid_only && open_file->uid != current_fsuid()) | 1205 | if (fsuid_only && open_file->uid != current_fsuid()) |
| @@ -1260,34 +1214,18 @@ refind_writable: | |||
| 1260 | } | 1214 | } |
| 1261 | 1215 | ||
| 1262 | spin_unlock(&cifs_file_list_lock); | 1216 | spin_unlock(&cifs_file_list_lock); |
| 1217 | |||
| 1263 | /* Had to unlock since following call can block */ | 1218 | /* Had to unlock since following call can block */ |
| 1264 | rc = cifs_reopen_file(open_file, false); | 1219 | rc = cifs_reopen_file(open_file, false); |
| 1265 | if (!rc) { | 1220 | if (!rc) |
| 1266 | if (!open_file->closePend) | 1221 | return open_file; |
| 1267 | return open_file; | ||
| 1268 | else { /* start over in case this was deleted */ | ||
| 1269 | /* since the list could be modified */ | ||
| 1270 | spin_lock(&cifs_file_list_lock); | ||
| 1271 | cifsFileInfo_put(open_file); | ||
| 1272 | goto refind_writable; | ||
| 1273 | } | ||
| 1274 | } | ||
| 1275 | 1222 | ||
| 1276 | /* if it fails, try another handle if possible - | 1223 | /* if it fails, try another handle if possible */ |
| 1277 | (we can not do this if closePending since | ||
| 1278 | loop could be modified - in which case we | ||
| 1279 | have to start at the beginning of the list | ||
| 1280 | again. Note that it would be bad | ||
| 1281 | to hold up writepages here (rather than | ||
| 1282 | in caller) with continuous retries */ | ||
| 1283 | cFYI(1, "wp failed on reopen file"); | 1224 | cFYI(1, "wp failed on reopen file"); |
| 1284 | spin_lock(&cifs_file_list_lock); | ||
| 1285 | /* can not use this handle, no write | ||
| 1286 | pending on this one after all */ | ||
| 1287 | cifsFileInfo_put(open_file); | 1225 | cifsFileInfo_put(open_file); |
| 1288 | 1226 | ||
| 1289 | if (open_file->closePend) /* list could have changed */ | 1227 | spin_lock(&cifs_file_list_lock); |
| 1290 | goto refind_writable; | 1228 | |
| 1291 | /* else we simply continue to the next entry. Thus | 1229 | /* else we simply continue to the next entry. Thus |
| 1292 | we do not loop on reopen errors. If we | 1230 | we do not loop on reopen errors. If we |
| 1293 | can not reopen the file, for example if we | 1231 | can not reopen the file, for example if we |
| @@ -1808,8 +1746,7 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
| 1808 | smb_read_data = NULL; | 1746 | smb_read_data = NULL; |
| 1809 | while (rc == -EAGAIN) { | 1747 | while (rc == -EAGAIN) { |
| 1810 | int buf_type = CIFS_NO_BUFFER; | 1748 | int buf_type = CIFS_NO_BUFFER; |
| 1811 | if ((open_file->invalidHandle) && | 1749 | if (open_file->invalidHandle) { |
| 1812 | (!open_file->closePend)) { | ||
| 1813 | rc = cifs_reopen_file(open_file, true); | 1750 | rc = cifs_reopen_file(open_file, true); |
| 1814 | if (rc != 0) | 1751 | if (rc != 0) |
| 1815 | break; | 1752 | break; |
| @@ -1894,8 +1831,7 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
| 1894 | } | 1831 | } |
| 1895 | rc = -EAGAIN; | 1832 | rc = -EAGAIN; |
| 1896 | while (rc == -EAGAIN) { | 1833 | while (rc == -EAGAIN) { |
| 1897 | if ((open_file->invalidHandle) && | 1834 | if (open_file->invalidHandle) { |
| 1898 | (!open_file->closePend)) { | ||
| 1899 | rc = cifs_reopen_file(open_file, true); | 1835 | rc = cifs_reopen_file(open_file, true); |
| 1900 | if (rc != 0) | 1836 | if (rc != 0) |
| 1901 | break; | 1837 | break; |
| @@ -2059,8 +1995,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
| 2059 | read_size, contig_pages); | 1995 | read_size, contig_pages); |
| 2060 | rc = -EAGAIN; | 1996 | rc = -EAGAIN; |
| 2061 | while (rc == -EAGAIN) { | 1997 | while (rc == -EAGAIN) { |
| 2062 | if ((open_file->invalidHandle) && | 1998 | if (open_file->invalidHandle) { |
| 2063 | (!open_file->closePend)) { | ||
| 2064 | rc = cifs_reopen_file(open_file, true); | 1999 | rc = cifs_reopen_file(open_file, true); |
| 2065 | if (rc != 0) | 2000 | if (rc != 0) |
| 2066 | break; | 2001 | break; |
| @@ -2212,8 +2147,6 @@ static int is_inode_writable(struct cifsInodeInfo *cifs_inode) | |||
| 2212 | 2147 | ||
| 2213 | spin_lock(&cifs_file_list_lock); | 2148 | spin_lock(&cifs_file_list_lock); |
| 2214 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { | 2149 | list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { |
| 2215 | if (open_file->closePend) | ||
| 2216 | continue; | ||
| 2217 | if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { | 2150 | if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { |
| 2218 | spin_unlock(&cifs_file_list_lock); | 2151 | spin_unlock(&cifs_file_list_lock); |
| 2219 | return 1; | 2152 | return 1; |
| @@ -2372,7 +2305,7 @@ void cifs_oplock_break(struct work_struct *work) | |||
| 2372 | * not bother sending an oplock release if session to server still is | 2305 | * not bother sending an oplock release if session to server still is |
| 2373 | * disconnected since oplock already released by the server | 2306 | * disconnected since oplock already released by the server |
| 2374 | */ | 2307 | */ |
| 2375 | if (!cfile->closePend && !cfile->oplock_break_cancelled) { | 2308 | if (!cfile->oplock_break_cancelled) { |
| 2376 | rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0, | 2309 | rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0, |
| 2377 | 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false); | 2310 | 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false); |
| 2378 | cFYI(1, "Oplock release rc = %d", rc); | 2311 | cFYI(1, "Oplock release rc = %d", rc); |
