aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs
diff options
context:
space:
mode:
authorSteve French <sfrench@us.ibm.com>2010-10-21 18:46:14 -0400
committerSteve French <sfrench@us.ibm.com>2010-10-21 18:46:14 -0400
commitcdff08e76612e53580139653403aedea979aa639 (patch)
tree1ebd74be361b7e34158974242a2303f7833c983d /fs/cifs
parent3f9bcca7820a6711307b6499952b13cfcfc31dd6 (diff)
[CIFS] move close processing from cifs_close to cifsFileInfo_put
Now that it's feasible for a cifsFileInfo to outlive the filp under which it was created, move the close processing into cifsFileInfo_put. This means that the last user of the filehandle always does the actual on the wire close call. This also allows us to get rid of the closePend flag from cifsFileInfo. If we have an active reference to the file then it's never going to have a close pending. cifs_close is converted to simply put the filehandle. Signed-off-by: Jeff Layton <jlayton@redhat.com> Reviewed-by: Suresh Jayaraman <sjayaraman@suse.de> Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r--fs/cifs/cifsglob.h1
-rw-r--r--fs/cifs/file.c187
-rw-r--r--fs/cifs/misc.c10
3 files changed, 60 insertions, 138 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 28337cba0295..3365e77f6f24 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -393,7 +393,6 @@ struct cifsFileInfo {
393 struct tcon_link *tlink; 393 struct tcon_link *tlink;
394 struct mutex lock_mutex; 394 struct mutex lock_mutex;
395 struct list_head llist; /* list of byte range locks we have. */ 395 struct list_head llist; /* list of byte range locks we have. */
396 bool closePend:1; /* file is marked to close */
397 bool invalidHandle:1; /* file closed via session abend */ 396 bool invalidHandle:1; /* file closed via session abend */
398 bool oplock_break_cancelled:1; 397 bool oplock_break_cancelled:1;
399 atomic_t count; /* reference count */ 398 atomic_t count; /* reference count */
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 */
270void cifsFileInfo_put(struct cifsFileInfo *cifs_file) 272void 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
279int cifs_open(struct inode *inode, struct file *file) 319int cifs_open(struct inode *inode, struct file *file)
@@ -605,79 +645,11 @@ reopen_error_exit:
605 645
606int cifs_close(struct inode *inode, struct file *file) 646int 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
683int cifs_closedir(struct inode *inode, struct file *file) 655int 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);
1245refind_writable: 1201refind_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);
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index a7b492c213cd..1c681f6a6803 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -567,16 +567,6 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
567 if (pSMB->Fid != netfile->netfid) 567 if (pSMB->Fid != netfile->netfid)
568 continue; 568 continue;
569 569
570 /*
571 * don't do anything if file is about to be
572 * closed anyway.
573 */
574 if (netfile->closePend) {
575 spin_unlock(&cifs_file_list_lock);
576 spin_unlock(&cifs_tcp_ses_lock);
577 return true;
578 }
579
580 cFYI(1, "file id match, oplock break"); 570 cFYI(1, "file id match, oplock break");
581 pCifsInode = CIFS_I(netfile->dentry->d_inode); 571 pCifsInode = CIFS_I(netfile->dentry->d_inode);
582 pCifsInode->clientCanCacheAll = false; 572 pCifsInode->clientCanCacheAll = false;