소스 검색

[CIFS] Do not time out posix brl requests when using new posix setfileinfo
request and do not time out slow requests to a server that is still responding
well to other threads

Suggested by jra of Samba team

Signed-off-by: Steve French <sfrench@us.ibm.com>
(cherry picked from 89b57148115479eef074b8d3f86c4c86c96ac969 commit)

Steve French 19 년 전
부모
커밋
3a5ff61c18
8개의 변경된 파일49개의 추가작업 그리고 18개의 파일을 삭제
  1. 6 0
      fs/cifs/CHANGES
  2. 1 5
      fs/cifs/cifsfs.c
  3. 1 1
      fs/cifs/cifsfs.h
  4. 2 1
      fs/cifs/cifsglob.h
  5. 8 3
      fs/cifs/cifssmb.c
  6. 16 1
      fs/cifs/connect.c
  7. 2 4
      fs/cifs/file.c
  8. 13 3
      fs/cifs/transport.c

+ 6 - 0
fs/cifs/CHANGES

@@ -1,3 +1,9 @@
+Version 1.45
+------------
+Do not time out lockw calls when using posix extensions. Do not
+time out requests if server still responding reasonably fast
+on requests on other threads
+
 Version 1.44
 Version 1.44
 ------------
 ------------
 Rewritten sessionsetup support, including support for legacy SMB
 Rewritten sessionsetup support, including support for legacy SMB

+ 1 - 5
fs/cifs/cifsfs.c

@@ -402,7 +402,6 @@ static struct quotactl_ops cifs_quotactl_ops = {
 };
 };
 #endif
 #endif
 
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
 static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
 {
 {
 	struct cifs_sb_info *cifs_sb;
 	struct cifs_sb_info *cifs_sb;
@@ -422,7 +421,7 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
 		tcon->tidStatus = CifsExiting;
 		tcon->tidStatus = CifsExiting;
 	up(&tcon->tconSem);
 	up(&tcon->tconSem);
 
 
-	/* cancel_brl_requests(tcon); */
+	/* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */
 	/* cancel_notify_requests(tcon); */
 	/* cancel_notify_requests(tcon); */
 	if(tcon->ses && tcon->ses->server)
 	if(tcon->ses && tcon->ses->server)
 	{
 	{
@@ -438,7 +437,6 @@ static void cifs_umount_begin(struct vfsmount * vfsmnt, int flags)
 
 
 	return;
 	return;
 }
 }
-#endif	
 
 
 static int cifs_remount(struct super_block *sb, int *flags, char *data)
 static int cifs_remount(struct super_block *sb, int *flags, char *data)
 {
 {
@@ -457,9 +455,7 @@ struct super_operations cifs_super_ops = {
    unless later we add lazy close of inodes or unless the kernel forgets to call
    unless later we add lazy close of inodes or unless the kernel forgets to call
    us with the same number of releases (closes) as opens */
    us with the same number of releases (closes) as opens */
 	.show_options = cifs_show_options,
 	.show_options = cifs_show_options,
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 	.umount_begin   = cifs_umount_begin,
 	.umount_begin   = cifs_umount_begin,
-#endif
 	.remount_fs = cifs_remount,
 	.remount_fs = cifs_remount,
 };
 };
 
 

+ 1 - 1
fs/cifs/cifsfs.h

@@ -100,5 +100,5 @@ extern ssize_t	cifs_getxattr(struct dentry *, const char *, void *, size_t);
 extern ssize_t	cifs_listxattr(struct dentry *, char *, size_t);
 extern ssize_t	cifs_listxattr(struct dentry *, char *, size_t);
 extern int cifs_ioctl (struct inode * inode, struct file * filep,
 extern int cifs_ioctl (struct inode * inode, struct file * filep,
 		       unsigned int command, unsigned long arg);
 		       unsigned int command, unsigned long arg);
-#define CIFS_VERSION   "1.44"
+#define CIFS_VERSION   "1.45"
 #endif				/* _CIFSFS_H */
 #endif				/* _CIFSFS_H */

+ 2 - 1
fs/cifs/cifsglob.h

@@ -158,7 +158,8 @@ struct TCP_Server_Info {
 	/* 16th byte of RFC1001 workstation name is always null */
 	/* 16th byte of RFC1001 workstation name is always null */
 	char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
 	char workstation_RFC1001_name[SERVER_NAME_LEN_WITH_NULL];
 	__u32 sequence_number; /* needed for CIFS PDU signature */
 	__u32 sequence_number; /* needed for CIFS PDU signature */
-	char mac_signing_key[CIFS_SESS_KEY_SIZE + 16]; 
+	char mac_signing_key[CIFS_SESS_KEY_SIZE + 16];
+	unsigned long lstrp; /* when we got last response from this server */
 };
 };
 
 
 /*
 /*

+ 8 - 3
fs/cifs/cifssmb.c

@@ -1484,6 +1484,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
 	char *data_offset;
 	char *data_offset;
 	struct cifs_posix_lock *parm_data;
 	struct cifs_posix_lock *parm_data;
 	int rc = 0;
 	int rc = 0;
+	int timeout = 0;
 	int bytes_returned = 0;
 	int bytes_returned = 0;
 	__u16 params, param_offset, offset, byte_count, count;
 	__u16 params, param_offset, offset, byte_count, count;
 
 
@@ -1503,7 +1504,6 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
 	pSMB->MaxSetupCount = 0;
 	pSMB->MaxSetupCount = 0;
 	pSMB->Reserved = 0;
 	pSMB->Reserved = 0;
 	pSMB->Flags = 0;
 	pSMB->Flags = 0;
-	pSMB->Timeout = 0;
 	pSMB->Reserved2 = 0;
 	pSMB->Reserved2 = 0;
 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
 	param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4;
 	offset = param_offset + params;
 	offset = param_offset + params;
@@ -1529,8 +1529,13 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
 			(((char *) &pSMB->hdr.Protocol) + offset);
 			(((char *) &pSMB->hdr.Protocol) + offset);
 
 
 	parm_data->lock_type = cpu_to_le16(lock_type);
 	parm_data->lock_type = cpu_to_le16(lock_type);
-	if(waitFlag)
+	if(waitFlag) {
+		timeout = 3;  /* blocking operation, no timeout */
 		parm_data->lock_flags = cpu_to_le16(1);
 		parm_data->lock_flags = cpu_to_le16(1);
+		pSMB->Timeout = cpu_to_le32(-1);
+	} else
+		pSMB->Timeout = 0;
+
 	parm_data->pid = cpu_to_le32(current->tgid);
 	parm_data->pid = cpu_to_le32(current->tgid);
 	parm_data->start = cpu_to_le64(pLockData->fl_start);
 	parm_data->start = cpu_to_le64(pLockData->fl_start);
 	parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
 	parm_data->length = cpu_to_le64(len);  /* normalize negative numbers */
@@ -1542,7 +1547,7 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
 	pSMB->hdr.smb_buf_length += byte_count;
 	pSMB->hdr.smb_buf_length += byte_count;
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 	pSMB->ByteCount = cpu_to_le16(byte_count);
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
 	rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-			(struct smb_hdr *) pSMBr, &bytes_returned, 0);
+			(struct smb_hdr *) pSMBr, &bytes_returned, timeout);
 	if (rc) {
 	if (rc) {
 		cFYI(1, ("Send error in Posix Lock = %d", rc));
 		cFYI(1, ("Send error in Posix Lock = %d", rc));
 	} else if (get_flag) {
 	} else if (get_flag) {

+ 16 - 1
fs/cifs/connect.c

@@ -612,6 +612,10 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
 #ifdef CONFIG_CIFS_STATS2
 #ifdef CONFIG_CIFS_STATS2
 				mid_entry->when_received = jiffies;
 				mid_entry->when_received = jiffies;
 #endif
 #endif
+				/* so we do not time out requests to  server
+				which is still responding (since server could
+				be busy but not dead) */
+				server->lstrp = jiffies;
 				break;
 				break;
 			}
 			}
 		}
 		}
@@ -1969,7 +1973,18 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
 				}
 				}
 					
 					
 				cFYI(1,("Negotiate caps 0x%x",(int)cap));
 				cFYI(1,("Negotiate caps 0x%x",(int)cap));
-
+#ifdef CONFIG_CIFS_DEBUG2
+				if(cap & CIFS_UNIX_FCNTL_CAP)
+					cFYI(1,("FCNTL cap"));
+				if(cap & CIFS_UNIX_EXTATTR_CAP)
+					cFYI(1,("EXTATTR cap"));
+				if(cap & CIFS_UNIX_POSIX_PATHNAMES_CAP)
+					cFYI(1,("POSIX path cap"));
+				if(cap & CIFS_UNIX_XATTR_CAP)
+					cFYI(1,("XATTR cap"));
+				if(cap & CIFS_UNIX_POSIX_ACL_CAP)
+					cFYI(1,("POSIX ACL cap"));
+#endif /* CIFS_DEBUG2 */
 				if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
 				if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
 					cFYI(1,("setting capabilities failed"));
 					cFYI(1,("setting capabilities failed"));
 				}
 				}

+ 2 - 4
fs/cifs/file.c

@@ -644,8 +644,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
 	account for negative length which we can not accept over the
 	account for negative length which we can not accept over the
 	wire */
 	wire */
 	if (IS_GETLK(cmd)) {
 	if (IS_GETLK(cmd)) {
-		if(experimEnabled && 
-		   (cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
+		if((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
 		   (CIFS_UNIX_FCNTL_CAP & 
 		   (CIFS_UNIX_FCNTL_CAP & 
 			le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
 			le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
 			int posix_lock_type;
 			int posix_lock_type;
@@ -683,8 +682,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock)
 		FreeXid(xid);
 		FreeXid(xid);
 		return rc;
 		return rc;
 	}
 	}
-	if (experimEnabled &&
-		(cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
+	if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
 		(CIFS_UNIX_FCNTL_CAP &
 		(CIFS_UNIX_FCNTL_CAP &
 			 le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
 			 le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) {
 		int posix_lock_type;
 		int posix_lock_type;

+ 13 - 3
fs/cifs/transport.c

@@ -444,8 +444,9 @@ SendReceive2(const unsigned int xid, struct cifsSesInfo *ses,
 	if(timeout != MAX_SCHEDULE_TIMEOUT) {
 	if(timeout != MAX_SCHEDULE_TIMEOUT) {
 		timeout += jiffies;
 		timeout += jiffies;
 		wait_event(ses->server->response_q,
 		wait_event(ses->server->response_q,
-			(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
-			time_after(jiffies, timeout) || 
+			(!(midQ->midState & MID_REQUEST_SUBMITTED)) ||
+			(time_after(jiffies, timeout) &&
+				time_after(jiffies, ses->server->lstrp + HZ)) ||
 			((ses->server->tcpStatus != CifsGood) &&
 			((ses->server->tcpStatus != CifsGood) &&
 			 (ses->server->tcpStatus != CifsNew)));
 			 (ses->server->tcpStatus != CifsNew)));
 	} else {
 	} else {
@@ -710,9 +711,18 @@ SendReceive(const unsigned int xid, struct cifsSesInfo *ses,
 	/* No user interrupts in wait - wreaks havoc with performance */
 	/* No user interrupts in wait - wreaks havoc with performance */
 	if(timeout != MAX_SCHEDULE_TIMEOUT) {
 	if(timeout != MAX_SCHEDULE_TIMEOUT) {
 		timeout += jiffies;
 		timeout += jiffies;
+		/* although we prefer not to time out if the server is still
+		responding - we will time out if the server takes
+		more than 15 (or 45 or 180) seconds to respond to this request
+		and has not responded to any request from other threads
+		on this client within a second (note that it is not worth
+		grabbing the GlobalMid_Lock and slowing things down in this
+		wait event to more accurately check the lstrsp field on some 
+		arch since we are already in an error path that will retry */
 		wait_event(ses->server->response_q,
 		wait_event(ses->server->response_q,
 			(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
 			(!(midQ->midState & MID_REQUEST_SUBMITTED)) || 
-			time_after(jiffies, timeout) || 
+			(time_after(jiffies, timeout) &&
+				time_after(jiffies, ses->server->lstrp + HZ)) ||
 			((ses->server->tcpStatus != CifsGood) &&
 			((ses->server->tcpStatus != CifsGood) &&
 			 (ses->server->tcpStatus != CifsNew)));
 			 (ses->server->tcpStatus != CifsNew)));
 	} else {
 	} else {