Skip to content

Commit 0cb39aa

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6: [CIFS] Do not attempt to close invalidated file handles [CIFS] fix check for dead tcon in smb_init
2 parents c93fc28 + ddb4cbf commit 0cb39aa

File tree

6 files changed

+36
-11
lines changed

6 files changed

+36
-11
lines changed

fs/cifs/CHANGES

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ handling fcntl(F_SETLEASE). Convert cifs to using blocking tcp
88
sends, and also let tcp autotune the socket send and receive buffers.
99
This reduces the number of EAGAIN errors returned by TCP/IP in
1010
high stress workloads (and the number of retries on socket writes
11-
when sending large SMBWriteX requests).
11+
when sending large SMBWriteX requests). Fix case in which a portion of
12+
data can in some cases not get written to the file on the server before the
13+
file is closed. Fix DFS parsing to properly handle path consumed field,
14+
and to handle certain codepage conversions better. Fix mount and
15+
umount race that can cause oops in mount or umount or reconnect.
1216

1317
Version 1.54
1418
------------

fs/cifs/cifsglob.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,15 @@ GLOBAL_EXTERN struct list_head cifs_tcp_ses_list;
606606
* changes to the tcon->tidStatus should be done while holding this lock.
607607
*/
608608
GLOBAL_EXTERN rwlock_t cifs_tcp_ses_lock;
609-
GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
609+
610+
/*
611+
* This lock protects the cifs_file->llist and cifs_file->flist
612+
* list operations, and updates to some flags (cifs_file->invalidHandle)
613+
* It will be moved to either use the tcon->stat_lock or equivalent later.
614+
* If cifs_tcp_ses_lock and the lock below are both needed to be held, then
615+
* the cifs_tcp_ses_lock must be grabbed first and released last.
616+
*/
617+
GLOBAL_EXTERN rwlock_t GlobalSMBSeslock;
610618

611619
GLOBAL_EXTERN struct list_head GlobalOplock_Q;
612620

fs/cifs/cifssmb.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
295295
check for tcp and smb session status done differently
296296
for those three - in the calling routine */
297297
if (tcon) {
298-
if (tcon->need_reconnect) {
298+
if (tcon->tidStatus == CifsExiting) {
299299
/* only tree disconnect, open, and write,
300300
(and ulogoff which does not have tcon)
301301
are allowed as we start force umount */

fs/cifs/file.c

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -488,12 +488,13 @@ int cifs_close(struct inode *inode, struct file *file)
488488
pTcon = cifs_sb->tcon;
489489
if (pSMBFile) {
490490
struct cifsLockInfo *li, *tmp;
491-
491+
write_lock(&GlobalSMBSeslock);
492492
pSMBFile->closePend = true;
493493
if (pTcon) {
494494
/* no sense reconnecting to close a file that is
495495
already closed */
496496
if (!pTcon->need_reconnect) {
497+
write_unlock(&GlobalSMBSeslock);
497498
timeout = 2;
498499
while ((atomic_read(&pSMBFile->wrtPending) != 0)
499500
&& (timeout <= 2048)) {
@@ -510,12 +511,15 @@ int cifs_close(struct inode *inode, struct file *file)
510511
timeout *= 4;
511512
}
512513
if (atomic_read(&pSMBFile->wrtPending))
513-
cERROR(1,
514-
("close with pending writes"));
515-
rc = CIFSSMBClose(xid, pTcon,
514+
cERROR(1, ("close with pending write"));
515+
if (!pTcon->need_reconnect &&
516+
!pSMBFile->invalidHandle)
517+
rc = CIFSSMBClose(xid, pTcon,
516518
pSMBFile->netfid);
517-
}
518-
}
519+
} else
520+
write_unlock(&GlobalSMBSeslock);
521+
} else
522+
write_unlock(&GlobalSMBSeslock);
519523

520524
/* Delete any outstanding lock records.
521525
We'll lose them when the file is closed anyway. */
@@ -587,15 +591,18 @@ int cifs_closedir(struct inode *inode, struct file *file)
587591
pTcon = cifs_sb->tcon;
588592

589593
cFYI(1, ("Freeing private data in close dir"));
594+
write_lock(&GlobalSMBSeslock);
590595
if (!pCFileStruct->srch_inf.endOfSearch &&
591596
!pCFileStruct->invalidHandle) {
592597
pCFileStruct->invalidHandle = true;
598+
write_unlock(&GlobalSMBSeslock);
593599
rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
594600
cFYI(1, ("Closing uncompleted readdir with rc %d",
595601
rc));
596602
/* not much we can do if it fails anyway, ignore rc */
597603
rc = 0;
598-
}
604+
} else
605+
write_unlock(&GlobalSMBSeslock);
599606
ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
600607
if (ptmp) {
601608
cFYI(1, ("closedir free smb buf in srch struct"));

fs/cifs/misc.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,12 +555,14 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
555555
continue;
556556

557557
cifs_stats_inc(&tcon->num_oplock_brks);
558+
write_lock(&GlobalSMBSeslock);
558559
list_for_each(tmp2, &tcon->openFileList) {
559560
netfile = list_entry(tmp2, struct cifsFileInfo,
560561
tlist);
561562
if (pSMB->Fid != netfile->netfid)
562563
continue;
563564

565+
write_unlock(&GlobalSMBSeslock);
564566
read_unlock(&cifs_tcp_ses_lock);
565567
cFYI(1, ("file id match, oplock break"));
566568
pCifsInode = CIFS_I(netfile->pInode);
@@ -576,6 +578,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
576578

577579
return true;
578580
}
581+
write_unlock(&GlobalSMBSeslock);
579582
read_unlock(&cifs_tcp_ses_lock);
580583
cFYI(1, ("No matching file for oplock break"));
581584
return true;

fs/cifs/readdir.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,11 +741,14 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
741741
(index_to_find < first_entry_in_buffer)) {
742742
/* close and restart search */
743743
cFYI(1, ("search backing up - close and restart search"));
744+
write_lock(&GlobalSMBSeslock);
744745
if (!cifsFile->srch_inf.endOfSearch &&
745746
!cifsFile->invalidHandle) {
746747
cifsFile->invalidHandle = true;
748+
write_unlock(&GlobalSMBSeslock);
747749
CIFSFindClose(xid, pTcon, cifsFile->netfid);
748-
}
750+
} else
751+
write_unlock(&GlobalSMBSeslock);
749752
if (cifsFile->srch_inf.ntwrk_buf_start) {
750753
cFYI(1, ("freeing SMB ff cache buf on search rewind"));
751754
if (cifsFile->srch_inf.smallBuf)

0 commit comments

Comments
 (0)