소스 검색

CIFS: Optimize cifs_user_read() in a short read case on reconnects

by filling the output buffer with a data got from a partially received
response and requesting the remaining data from the server. This is
suitable for non-signed connections.

Signed-off-by: Pavel Shilovsky <pshilovsky@samba.org>
Signed-off-by: Steve French <smfrench@gmail.com>
Pavel Shilovsky 11 년 전
부모
커밋
d913ed17f0
3개의 변경된 파일32개의 추가작업 그리고 3개의 파일을 삭제
  1. 6 0
      fs/cifs/cifssmb.c
  2. 20 3
      fs/cifs/file.c
  3. 6 0
      fs/cifs/smb2pdu.c

+ 6 - 0
fs/cifs/cifssmb.c

@@ -1561,6 +1561,12 @@ cifs_readv_callback(struct mid_q_entry *mid)
 	case MID_REQUEST_SUBMITTED:
 	case MID_RETRY_NEEDED:
 		rdata->result = -EAGAIN;
+		if (server->sign && rdata->got_bytes)
+			/* reset bytes number since we can not check a sign */
+			rdata->got_bytes = 0;
+		/* FIXME: should this be counted toward the initiating task? */
+		task_io_account_read(rdata->got_bytes);
+		cifs_stats_bytes_read(tcon, rdata->got_bytes);
 		break;
 	default:
 		rdata->result = -EIO;

+ 20 - 3
fs/cifs/file.c

@@ -3030,13 +3030,30 @@ again:
 			else if (rdata->result == -EAGAIN) {
 				/* resend call if it's a retryable error */
 				struct list_head tmp_list;
+				unsigned int got_bytes = rdata->got_bytes;
 
 				list_del_init(&rdata->list);
 				INIT_LIST_HEAD(&tmp_list);
 
-				rc = cifs_send_async_read(rdata->offset,
-						rdata->bytes, rdata->cfile,
-						cifs_sb, &tmp_list);
+				/*
+				 * Got a part of data and then reconnect has
+				 * happened -- fill the buffer and continue
+				 * reading.
+				 */
+				if (got_bytes && got_bytes < rdata->bytes) {
+					rc = cifs_readdata_to_iov(rdata, to);
+					if (rc) {
+						kref_put(&rdata->refcount,
+						cifs_uncached_readdata_release);
+						continue;
+					}
+				}
+
+				rc = cifs_send_async_read(
+						rdata->offset + got_bytes,
+						rdata->bytes - got_bytes,
+						rdata->cfile, cifs_sb,
+						&tmp_list);
 
 				list_splice(&tmp_list, &rdata_list);
 

+ 6 - 0
fs/cifs/smb2pdu.c

@@ -1729,6 +1729,12 @@ smb2_readv_callback(struct mid_q_entry *mid)
 	case MID_REQUEST_SUBMITTED:
 	case MID_RETRY_NEEDED:
 		rdata->result = -EAGAIN;
+		if (server->sign && rdata->got_bytes)
+			/* reset bytes number since we can not check a sign */
+			rdata->got_bytes = 0;
+		/* FIXME: should this be counted toward the initiating task? */
+		task_io_account_read(rdata->got_bytes);
+		cifs_stats_bytes_read(tcon, rdata->got_bytes);
 		break;
 	default:
 		if (rdata->result != -ENODATA)