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.
|
sends, and also let tcp autotune the socket send and receive buffers.
|
||||||
This reduces the number of EAGAIN errors returned by TCP/IP in
|
This reduces the number of EAGAIN errors returned by TCP/IP in
|
||||||
high stress workloads (and the number of retries on socket writes
|
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
|
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.
|
* changes to the tcon->tidStatus should be done while holding this lock.
|
||||||
*/
|
*/
|
||||||
GLOBAL_EXTERN rwlock_t cifs_tcp_ses_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;
|
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
|
check for tcp and smb session status done differently
|
||||||
for those three - in the calling routine */
|
for those three - in the calling routine */
|
||||||
if (tcon) {
|
if (tcon) {
|
||||||
if (tcon->need_reconnect) {
|
if (tcon->tidStatus == CifsExiting) {
|
||||||
/* only tree disconnect, open, and write,
|
/* only tree disconnect, open, and write,
|
||||||
(and ulogoff which does not have tcon)
|
(and ulogoff which does not have tcon)
|
||||||
are allowed as we start force umount */
|
are allowed as we start force umount */
|
||||||
|
|
|
@ -488,12 +488,13 @@ int cifs_close(struct inode *inode, struct file *file)
|
||||||
pTcon = cifs_sb->tcon;
|
pTcon = cifs_sb->tcon;
|
||||||
if (pSMBFile) {
|
if (pSMBFile) {
|
||||||
struct cifsLockInfo *li, *tmp;
|
struct cifsLockInfo *li, *tmp;
|
||||||
|
write_lock(&GlobalSMBSeslock);
|
||||||
pSMBFile->closePend = true;
|
pSMBFile->closePend = true;
|
||||||
if (pTcon) {
|
if (pTcon) {
|
||||||
/* no sense reconnecting to close a file that is
|
/* no sense reconnecting to close a file that is
|
||||||
already closed */
|
already closed */
|
||||||
if (!pTcon->need_reconnect) {
|
if (!pTcon->need_reconnect) {
|
||||||
|
write_unlock(&GlobalSMBSeslock);
|
||||||
timeout = 2;
|
timeout = 2;
|
||||||
while ((atomic_read(&pSMBFile->wrtPending) != 0)
|
while ((atomic_read(&pSMBFile->wrtPending) != 0)
|
||||||
&& (timeout <= 2048)) {
|
&& (timeout <= 2048)) {
|
||||||
|
@ -510,12 +511,15 @@ int cifs_close(struct inode *inode, struct file *file)
|
||||||
timeout *= 4;
|
timeout *= 4;
|
||||||
}
|
}
|
||||||
if (atomic_read(&pSMBFile->wrtPending))
|
if (atomic_read(&pSMBFile->wrtPending))
|
||||||
cERROR(1,
|
cERROR(1, ("close with pending write"));
|
||||||
("close with pending writes"));
|
if (!pTcon->need_reconnect &&
|
||||||
rc = CIFSSMBClose(xid, pTcon,
|
!pSMBFile->invalidHandle)
|
||||||
|
rc = CIFSSMBClose(xid, pTcon,
|
||||||
pSMBFile->netfid);
|
pSMBFile->netfid);
|
||||||
}
|
} else
|
||||||
}
|
write_unlock(&GlobalSMBSeslock);
|
||||||
|
} else
|
||||||
|
write_unlock(&GlobalSMBSeslock);
|
||||||
|
|
||||||
/* Delete any outstanding lock records.
|
/* Delete any outstanding lock records.
|
||||||
We'll lose them when the file is closed anyway. */
|
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;
|
pTcon = cifs_sb->tcon;
|
||||||
|
|
||||||
cFYI(1, ("Freeing private data in close dir"));
|
cFYI(1, ("Freeing private data in close dir"));
|
||||||
|
write_lock(&GlobalSMBSeslock);
|
||||||
if (!pCFileStruct->srch_inf.endOfSearch &&
|
if (!pCFileStruct->srch_inf.endOfSearch &&
|
||||||
!pCFileStruct->invalidHandle) {
|
!pCFileStruct->invalidHandle) {
|
||||||
pCFileStruct->invalidHandle = true;
|
pCFileStruct->invalidHandle = true;
|
||||||
|
write_unlock(&GlobalSMBSeslock);
|
||||||
rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
|
rc = CIFSFindClose(xid, pTcon, pCFileStruct->netfid);
|
||||||
cFYI(1, ("Closing uncompleted readdir with rc %d",
|
cFYI(1, ("Closing uncompleted readdir with rc %d",
|
||||||
rc));
|
rc));
|
||||||
/* not much we can do if it fails anyway, ignore rc */
|
/* not much we can do if it fails anyway, ignore rc */
|
||||||
rc = 0;
|
rc = 0;
|
||||||
}
|
} else
|
||||||
|
write_unlock(&GlobalSMBSeslock);
|
||||||
ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
|
ptmp = pCFileStruct->srch_inf.ntwrk_buf_start;
|
||||||
if (ptmp) {
|
if (ptmp) {
|
||||||
cFYI(1, ("closedir free smb buf in srch struct"));
|
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;
|
continue;
|
||||||
|
|
||||||
cifs_stats_inc(&tcon->num_oplock_brks);
|
cifs_stats_inc(&tcon->num_oplock_brks);
|
||||||
|
write_lock(&GlobalSMBSeslock);
|
||||||
list_for_each(tmp2, &tcon->openFileList) {
|
list_for_each(tmp2, &tcon->openFileList) {
|
||||||
netfile = list_entry(tmp2, struct cifsFileInfo,
|
netfile = list_entry(tmp2, struct cifsFileInfo,
|
||||||
tlist);
|
tlist);
|
||||||
if (pSMB->Fid != netfile->netfid)
|
if (pSMB->Fid != netfile->netfid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
write_unlock(&GlobalSMBSeslock);
|
||||||
read_unlock(&cifs_tcp_ses_lock);
|
read_unlock(&cifs_tcp_ses_lock);
|
||||||
cFYI(1, ("file id match, oplock break"));
|
cFYI(1, ("file id match, oplock break"));
|
||||||
pCifsInode = CIFS_I(netfile->pInode);
|
pCifsInode = CIFS_I(netfile->pInode);
|
||||||
|
@ -576,6 +578,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
write_unlock(&GlobalSMBSeslock);
|
||||||
read_unlock(&cifs_tcp_ses_lock);
|
read_unlock(&cifs_tcp_ses_lock);
|
||||||
cFYI(1, ("No matching file for oplock break"));
|
cFYI(1, ("No matching file for oplock break"));
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -741,11 +741,14 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
|
||||||
(index_to_find < first_entry_in_buffer)) {
|
(index_to_find < first_entry_in_buffer)) {
|
||||||
/* close and restart search */
|
/* close and restart search */
|
||||||
cFYI(1, ("search backing up - close and restart search"));
|
cFYI(1, ("search backing up - close and restart search"));
|
||||||
|
write_lock(&GlobalSMBSeslock);
|
||||||
if (!cifsFile->srch_inf.endOfSearch &&
|
if (!cifsFile->srch_inf.endOfSearch &&
|
||||||
!cifsFile->invalidHandle) {
|
!cifsFile->invalidHandle) {
|
||||||
cifsFile->invalidHandle = true;
|
cifsFile->invalidHandle = true;
|
||||||
|
write_unlock(&GlobalSMBSeslock);
|
||||||
CIFSFindClose(xid, pTcon, cifsFile->netfid);
|
CIFSFindClose(xid, pTcon, cifsFile->netfid);
|
||||||
}
|
} else
|
||||||
|
write_unlock(&GlobalSMBSeslock);
|
||||||
if (cifsFile->srch_inf.ntwrk_buf_start) {
|
if (cifsFile->srch_inf.ntwrk_buf_start) {
|
||||||
cFYI(1, ("freeing SMB ff cache buf on search rewind"));
|
cFYI(1, ("freeing SMB ff cache buf on search rewind"));
|
||||||
if (cifsFile->srch_inf.smallBuf)
|
if (cifsFile->srch_inf.smallBuf)
|
||||||
|
|
Loading…
Reference in a new issue