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
This commit is contained in:
commit
0cb39aa0ac
6 changed files with 36 additions and 11 deletions
|
@ -8,7 +8,11 @@ handling fcntl(F_SETLEASE). Convert cifs to using blocking tcp
|
|||
sends, and also let tcp autotune the socket send and receive buffers.
|
||||
This reduces the number of EAGAIN errors returned by TCP/IP in
|
||||
high stress workloads (and the number of retries on socket writes
|
||||
when sending large SMBWriteX requests).
|
||||
when sending large SMBWriteX requests). Fix case in which a portion of
|
||||
data can in some cases not get written to the file on the server before the
|
||||
file is closed. Fix DFS parsing to properly handle path consumed field,
|
||||
and to handle certain codepage conversions better. Fix mount and
|
||||
umount race that can cause oops in mount or umount or reconnect.
|
||||
|
||||
Version 1.54
|
||||
------------
|
||||
|
|
|
@ -606,7 +606,15 @@ GLOBAL_EXTERN struct list_head cifs_tcp_ses_list;
|
|||
* changes to the tcon->tidStatus should be done while holding this lock.
|
||||
*/
|
||||
GLOBAL_EXTERN rwlock_t cifs_tcp_ses_lock;
|
||||
GLOBAL_EXTERN rwlock_t GlobalSMBSeslock; /* protects list inserts on 3 above */
|
||||
|
||||
/*
|
||||
* This lock protects the cifs_file->llist and cifs_file->flist
|
||||
* list operations, and updates to some flags (cifs_file->invalidHandle)
|
||||
* It will be moved to either use the tcon->stat_lock or equivalent later.
|
||||
* If cifs_tcp_ses_lock and the lock below are both needed to be held, then
|
||||
* the cifs_tcp_ses_lock must be grabbed first and released last.
|
||||
*/
|
||||
GLOBAL_EXTERN rwlock_t GlobalSMBSeslock;
|
||||
|
||||
GLOBAL_EXTERN struct list_head GlobalOplock_Q;
|
||||
|
||||
|
|
|
@ -295,7 +295,7 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
|
|||
check for tcp and smb session status done differently
|
||||
for those three - in the calling routine */
|
||||
if (tcon) {
|
||||
if (tcon->need_reconnect) {
|
||||
if (tcon->tidStatus == CifsExiting) {
|
||||
/* only tree disconnect, open, and write,
|
||||
(and ulogoff which does not have tcon)
|
||||
are allowed as we start force umount */
|
||||
|
|
|
@ -488,12 +488,13 @@ int cifs_close(struct inode *inode, struct file *file)
|
|||
pTcon = cifs_sb->tcon;
|
||||
if (pSMBFile) {
|
||||
struct cifsLockInfo *li, *tmp;
|
||||
|
||||
write_lock(&GlobalSMBSeslock);
|
||||
pSMBFile->closePend = true;
|
||||
if (pTcon) {
|
||||
/* no sense reconnecting to close a file that is
|
||||
already closed */
|
||||
if (!pTcon->need_reconnect) {
|
||||
write_unlock(&GlobalSMBSeslock);
|
||||
timeout = 2;
|
||||
while ((atomic_read(&pSMBFile->wrtPending) != 0)
|
||||
&& (timeout <= 2048)) {
|
||||
|
@ -510,12 +511,15 @@ int cifs_close(struct inode *inode, struct file *file)
|
|||
timeout *= 4;
|
||||
}
|
||||
if (atomic_read(&pSMBFile->wrtPending))
|
||||
cERROR(1,
|
||||
("close with pending writes"));
|
||||
rc = CIFSSMBClose(xid, pTcon,
|
||||
cERROR(1, ("close with pending write"));
|
||||
if (!pTcon->need_reconnect &&
|
||||
!pSMBFile->invalidHandle)
|
||||
rc = CIFSSMBClose(xid, pTcon,
|
||||
pSMBFile->netfid);
|
||||
}
|
||||
}
|
||||
} else
|
||||
write_unlock(&GlobalSMBSeslock);
|
||||
} else
|
||||
write_unlock(&GlobalSMBSeslock);
|
||||
|
||||
/* Delete any outstanding lock records.
|
||||
We'll lose them when the file is closed anyway. */
|
||||
|
@ -587,15 +591,18 @@ int cifs_closedir(struct inode *inode, struct file *file)
|
|||
pTcon = cifs_sb->tcon;
|
||||
|
||||
cFYI(1, ("Freeing private data in close dir"));
|
||||
write_lock(&GlobalSMBSeslock);
|
||||
if (!pCFileStruct->srch_inf.endOfSearch &&
|
||||
!pCFileStruct->invalidHandle) {
|
||||
pCFileStruct->invalidHandle = true;
|
||||
write_unlock(&GlobalSMBSeslock);
|
||||
rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
|
||||
cFYI(1, ("Closing uncompleted readdir with rc %d",
|
||||
rc));
|
||||
/* not much we can do if it fails anyway, ignore rc */
|
||||
rc = 0;
|
||||
}
|
||||
} else
|
||||
write_unlock(&GlobalSMBSeslock);
|
||||
ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
|
||||
if (ptmp) {
|
||||
cFYI(1, ("closedir free smb buf in srch struct"));
|
||||
|
|
|
@ -555,12 +555,14 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
|
|||
continue;
|
||||
|
||||
cifs_stats_inc(&tcon->num_oplock_brks);
|
||||
write_lock(&GlobalSMBSeslock);
|
||||
list_for_each(tmp2, &tcon->openFileList) {
|
||||
netfile = list_entry(tmp2, struct cifsFileInfo,
|
||||
tlist);
|
||||
if (pSMB->Fid != netfile->netfid)
|
||||
continue;
|
||||
|
||||
write_unlock(&GlobalSMBSeslock);
|
||||
read_unlock(&cifs_tcp_ses_lock);
|
||||
cFYI(1, ("file id match, oplock break"));
|
||||
pCifsInode = CIFS_I(netfile->pInode);
|
||||
|
@ -576,6 +578,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
|
|||
|
||||
return true;
|
||||
}
|
||||
write_unlock(&GlobalSMBSeslock);
|
||||
read_unlock(&cifs_tcp_ses_lock);
|
||||
cFYI(1, ("No matching file for oplock break"));
|
||||
return true;
|
||||
|
|
|
@ -741,11 +741,14 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
|
|||
(index_to_find < first_entry_in_buffer)) {
|
||||
/* close and restart search */
|
||||
cFYI(1, ("search backing up - close and restart search"));
|
||||
write_lock(&GlobalSMBSeslock);
|
||||
if (!cifsFile->srch_inf.endOfSearch &&
|
||||
!cifsFile->invalidHandle) {
|
||||
cifsFile->invalidHandle = true;
|
||||
write_unlock(&GlobalSMBSeslock);
|
||||
CIFSFindClose(xid, pTcon, cifsFile->netfid);
|
||||
}
|
||||
} else
|
||||
write_unlock(&GlobalSMBSeslock);
|
||||
if (cifsFile->srch_inf.ntwrk_buf_start) {
|
||||
cFYI(1, ("freeing SMB ff cache buf on search rewind"));
|
||||
if (cifsFile->srch_inf.smallBuf)
|
||||
|
|
Loading…
Reference in a new issue