Loading fs/cifs/CHANGES +5 −1 Original line number Diff line number Diff line Loading @@ -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 ------------ Loading fs/cifs/cifsglob.h +9 −1 Original line number Diff line number Diff line Loading @@ -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; Loading fs/cifs/cifssmb.c +1 −1 Original line number Diff line number Diff line Loading @@ -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 */ Loading fs/cifs/file.c +14 −7 Original line number Diff line number Diff line Loading @@ -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)) { Loading @@ -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")); 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. */ Loading Loading @@ -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")); Loading fs/cifs/misc.c +3 −0 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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; Loading Loading
fs/cifs/CHANGES +5 −1 Original line number Diff line number Diff line Loading @@ -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 ------------ Loading
fs/cifs/cifsglob.h +9 −1 Original line number Diff line number Diff line Loading @@ -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; Loading
fs/cifs/cifssmb.c +1 −1 Original line number Diff line number Diff line Loading @@ -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 */ Loading
fs/cifs/file.c +14 −7 Original line number Diff line number Diff line Loading @@ -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)) { Loading @@ -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")); 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. */ Loading Loading @@ -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")); Loading
fs/cifs/misc.c +3 −0 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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; Loading