Re: [PATCH 02/16] cifs: remove rfc1002 header from all SMB2 response structures

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



--
Best regards,
Pavel Shilovsky


2018-03-21 21:23 GMT-07:00 Ronnie Sahlberg <lsahlber@xxxxxxxxxx>:
> Separate out all the 4 byte rfc1002 headers so that they are no longer
> part of the SMB2 header structures to prepare for future work to add
> compounding support.
>
> Signed-off-by: Ronnie Sahlberg <lsahlber@xxxxxxxxxx>
> ---
>  fs/cifs/cifsglob.h      |   3 +
>  fs/cifs/cifssmb.c       |   2 +-
>  fs/cifs/connect.c       |  10 +++-
>  fs/cifs/misc.c          |   2 +-
>  fs/cifs/smb2glob.h      |   5 --
>  fs/cifs/smb2maperror.c  |   2 +-
>  fs/cifs/smb2misc.c      |  90 +++++++++++++----------------
>  fs/cifs/smb2ops.c       | 146 +++++++++++++++++++++++++++---------------------
>  fs/cifs/smb2pdu.c       | 103 ++++++++++++++++------------------
>  fs/cifs/smb2pdu.h       |  65 +++++++--------------
>  fs/cifs/smb2proto.h     |   5 +-
>  fs/cifs/smb2transport.c |  12 ++--
>  fs/cifs/transport.c     |   3 +-
>  13 files changed, 213 insertions(+), 235 deletions(-)
>
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index 3e3f86841372..0045d85ec76d 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -665,6 +665,8 @@ struct TCP_Server_Info {
>         struct delayed_work     echo; /* echo ping workqueue job */
>         char    *smallbuf;      /* pointer to current "small" buffer */
>         char    *bigbuf;        /* pointer to current "big" buffer */
> +       /* Total size of this PDU. Only valid from cifs_demultiplex_thread */
> +       unsigned int pdu_size;
>         unsigned int total_read; /* total amount of data read in this pass */
>  #ifdef CONFIG_CIFS_FSCACHE
>         struct fscache_cookie   *fscache; /* client index cache cookie */
> @@ -1373,6 +1375,7 @@ struct mid_q_entry {
>         mid_handle_t *handle; /* call handle mid callback */
>         void *callback_data;      /* general purpose pointer for callback */
>         void *resp_buf;         /* pointer to received SMB header */
> +       unsigned int resp_buf_size;
>         int mid_state;  /* wish this were enum but can not pass to wait_event */
>         unsigned int mid_flags;
>         __le16 command;         /* smb command code */
> diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
> index 59c09a596c0a..991e9d9ef90a 100644
> --- a/fs/cifs/cifssmb.c
> +++ b/fs/cifs/cifssmb.c
> @@ -1454,7 +1454,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>         unsigned int data_offset, data_len;
>         struct cifs_readdata *rdata = mid->callback_data;
>         char *buf = server->smallbuf;
> -       unsigned int buflen = get_rfc1002_length(buf) +
> +       unsigned int buflen = server->pdu_size +
>                 server->vals->header_preamble_size;
>         bool use_rdma_mr = false;
>
> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
> index 1f2e3b15b2b1..0fad48d081d8 100644
> --- a/fs/cifs/connect.c
> +++ b/fs/cifs/connect.c
> @@ -772,7 +772,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>  {
>         int length;
>         char *buf = server->smallbuf;
> -       unsigned int pdu_length = get_rfc1002_length(buf);
> +       unsigned int pdu_length = server->pdu_size;
>
>         /* make sure this will fit in a large buffer */
>         if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
> @@ -874,13 +874,18 @@ cifs_demultiplex_thread(void *p)
>                 length = cifs_read_from_socket(server, buf, pdu_length);
>                 if (length < 0)
>                         continue;
> -               server->total_read = length;
> +
> +               if (server->vals->header_preamble_size == 0)
> +                       server->total_read = 0;
> +               else
> +                       server->total_read = length;
>
>                 /*
>                  * The right amount was read from socket - 4 bytes,
>                  * so we can now interpret the length field.
>                  */
>                 pdu_length = get_rfc1002_length(buf);
> +               server->pdu_size = pdu_length;
>
>                 cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
>                 if (!is_smb_response(server, buf[0]))
> @@ -927,6 +932,7 @@ cifs_demultiplex_thread(void *p)
>
>                 server->lstrp = jiffies;
>                 if (mid_entry != NULL) {
> +                       mid_entry->resp_buf_size = server->pdu_size;
>                         if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) &&
>                              mid_entry->mid_state == MID_RESPONSE_RECEIVED &&
>                                         server->ops->handle_cancelled_mid)
> diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
> index 460084a8eac5..d5d7eb2ae3c4 100644
> --- a/fs/cifs/misc.c
> +++ b/fs/cifs/misc.c
> @@ -145,7 +145,7 @@ cifs_buf_get(void)
>          * SMB2 header is bigger than CIFS one - no problems to clean some
>          * more bytes for CIFS.
>          */
> -       size_t buf_size = sizeof(struct smb2_hdr);
> +       size_t buf_size = sizeof(struct smb2_sync_hdr);
>
>         /*
>          * We could use negotiated size instead of max_msgsize -
> diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h
> index 401a5d856636..0ffa18094335 100644
> --- a/fs/cifs/smb2glob.h
> +++ b/fs/cifs/smb2glob.h
> @@ -61,9 +61,4 @@
>  /* Maximum buffer size value we can send with 1 credit */
>  #define SMB2_MAX_BUFFER_SIZE 65536
>
> -static inline struct smb2_sync_hdr *get_sync_hdr(void *buf)
> -{
> -       return &(((struct smb2_hdr *)buf)->sync_hdr);
> -}
> -
>  #endif /* _SMB2_GLOB_H */
> diff --git a/fs/cifs/smb2maperror.c b/fs/cifs/smb2maperror.c
> index 62c88dfed57b..8fe30288805f 100644
> --- a/fs/cifs/smb2maperror.c
> +++ b/fs/cifs/smb2maperror.c
> @@ -2450,7 +2450,7 @@ smb2_print_status(__le32 status)
>  int
>  map_smb2_to_linux_error(char *buf, bool log_err)
>  {
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>         unsigned int i;
>         int rc = -EIO;
>         __le32 smb2err = shdr->Status;
> diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
> index 566871185b98..cb79c2433844 100644
> --- a/fs/cifs/smb2misc.c
> +++ b/fs/cifs/smb2misc.c
> @@ -94,25 +94,20 @@ static const __le16 smb2_rsp_struct_sizes[NUMBER_OF_SMB2_COMMANDS] = {
>  };
>
>  int
> -smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
> +smb2_check_message(char *buf, unsigned int len, struct TCP_Server_Info *srvr)
>  {
> -       struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
> -       struct smb2_hdr *hdr = &pdu->hdr;
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
> +       struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)shdr;
>         __u64 mid;
> -       __u32 len = get_rfc1002_length(buf);
>         __u32 clc_len;  /* calculated length */
>         int command;
> -
> -       /* BB disable following printk later */
> -       cifs_dbg(FYI, "%s length: 0x%x, smb_buf_length: 0x%x\n",
> -                __func__, length, len);
> +       int pdu_size = sizeof(struct smb2_sync_pdu);
> +       int hdr_size = sizeof(struct smb2_sync_hdr);
>
>         /*
>          * Add function to do table lookup of StructureSize by command
>          * ie Validate the wct via smb2_struct_sizes table above
>          */
> -
>         if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
>                 struct smb2_transform_hdr *thdr =
>                         (struct smb2_transform_hdr *)buf;
> @@ -136,8 +131,8 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
>         }
>
>         mid = le64_to_cpu(shdr->MessageId);
> -       if (length < sizeof(struct smb2_pdu)) {
> -               if ((length >= sizeof(struct smb2_hdr))
> +       if (len < pdu_size) {
> +               if ((len >= hdr_size)
>                     && (shdr->Status != 0)) {
>                         pdu->StructureSize2 = 0;
>                         /*
> @@ -190,13 +185,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
>                 }
>         }
>
> -       if (srvr->vals->header_preamble_size + len != length) {
> -               cifs_dbg(VFS, "Total length %u RFC1002 length %u mismatch mid %llu\n",
> -                        length, srvr->vals->header_preamble_size + len, mid);
> -               return 1;
> -       }
> -
> -       clc_len = smb2_calc_size(hdr);
> +       clc_len = smb2_calc_size(buf);
>
>         if (srvr->vals->header_preamble_size + len != clc_len) {
>                 cifs_dbg(FYI, "Calculated size %u length %u mismatch mid %llu\n",
> @@ -206,7 +195,7 @@ smb2_check_message(char *buf, unsigned int length, struct TCP_Server_Info *srvr)
>                     shdr->Status == STATUS_STOPPED_ON_SYMLINK)
>                         return 0;
>                 /* Windows 7 server returns 24 bytes more */
> -               if (clc_len + 20 == len && command == SMB2_OPLOCK_BREAK_HE)
> +               if (clc_len + 24 == len && command == SMB2_OPLOCK_BREAK_HE)

We have a srvr pointer here, so, we can use header_preamble_size
instead and move this to patch #1.

>                         return 0;
>                 /* server can return one byte more due to implied bcc[0] */
>                 if (clc_len == srvr->vals->header_preamble_size + len + 1)
> @@ -263,15 +252,14 @@ static const bool has_smb2_data_area[NUMBER_OF_SMB2_COMMANDS] = {
>   * area and the offset to it (from the beginning of the smb are also returned.
>   */
>  char *
> -smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
> +smb2_get_data_area_len(int *off, int *len, struct smb2_sync_hdr *shdr)
>  {
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(hdr);
>         *off = 0;
>         *len = 0;
>
>         /* error responses do not have data area */
>         if (shdr->Status && shdr->Status != STATUS_MORE_PROCESSING_REQUIRED &&
> -           (((struct smb2_err_rsp *)hdr)->StructureSize) ==
> +           (((struct smb2_err_rsp *)shdr)->StructureSize) ==
>                                                 SMB2_ERROR_STRUCTURE_SIZE2)
>                 return NULL;
>
> @@ -283,42 +271,44 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
>         switch (shdr->Command) {
>         case SMB2_NEGOTIATE:
>                 *off = le16_to_cpu(
> -                   ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferOffset);
> +                 ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset);
>                 *len = le16_to_cpu(
> -                   ((struct smb2_negotiate_rsp *)hdr)->SecurityBufferLength);
> +                 ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength);
>                 break;
>         case SMB2_SESSION_SETUP:
>                 *off = le16_to_cpu(
> -                   ((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferOffset);
> +                 ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferOffset);
>                 *len = le16_to_cpu(
> -                   ((struct smb2_sess_setup_rsp *)hdr)->SecurityBufferLength);
> +                 ((struct smb2_sess_setup_rsp *)shdr)->SecurityBufferLength);
>                 break;
>         case SMB2_CREATE:
>                 *off = le32_to_cpu(
> -                   ((struct smb2_create_rsp *)hdr)->CreateContextsOffset);
> +                   ((struct smb2_create_rsp *)shdr)->CreateContextsOffset);
>                 *len = le32_to_cpu(
> -                   ((struct smb2_create_rsp *)hdr)->CreateContextsLength);
> +                   ((struct smb2_create_rsp *)shdr)->CreateContextsLength);
>                 break;
>         case SMB2_QUERY_INFO:
>                 *off = le16_to_cpu(
> -                   ((struct smb2_query_info_rsp *)hdr)->OutputBufferOffset);
> +                   ((struct smb2_query_info_rsp *)shdr)->OutputBufferOffset);
>                 *len = le32_to_cpu(
> -                   ((struct smb2_query_info_rsp *)hdr)->OutputBufferLength);
> +                   ((struct smb2_query_info_rsp *)shdr)->OutputBufferLength);
>                 break;
>         case SMB2_READ:
> -               *off = ((struct smb2_read_rsp *)hdr)->DataOffset;
> -               *len = le32_to_cpu(((struct smb2_read_rsp *)hdr)->DataLength);
> +               /* TODO: is this a bug ? */
> +               *off = ((struct smb2_read_rsp *)shdr)->DataOffset;
> +               *len = le32_to_cpu(((struct smb2_read_rsp *)shdr)->DataLength);
>                 break;
>         case SMB2_QUERY_DIRECTORY:
>                 *off = le16_to_cpu(
> -                 ((struct smb2_query_directory_rsp *)hdr)->OutputBufferOffset);
> +                 ((struct smb2_query_directory_rsp *)shdr)->OutputBufferOffset);
>                 *len = le32_to_cpu(
> -                 ((struct smb2_query_directory_rsp *)hdr)->OutputBufferLength);
> +                 ((struct smb2_query_directory_rsp *)shdr)->OutputBufferLength);
>                 break;
>         case SMB2_IOCTL:
>                 *off = le32_to_cpu(
> -                 ((struct smb2_ioctl_rsp *)hdr)->OutputOffset);
> -               *len = le32_to_cpu(((struct smb2_ioctl_rsp *)hdr)->OutputCount);
> +                 ((struct smb2_ioctl_rsp *)shdr)->OutputOffset);
> +               *len = le32_to_cpu(
> +                 ((struct smb2_ioctl_rsp *)shdr)->OutputCount);
>                 break;
>         case SMB2_CHANGE_NOTIFY:
>         default:
> @@ -363,13 +353,12 @@ smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr)
>  unsigned int
>  smb2_calc_size(void *buf)
>  {
> -       struct smb2_pdu *pdu = (struct smb2_pdu *)buf;
> -       struct smb2_hdr *hdr = &pdu->hdr;
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(hdr);
> +       struct smb2_sync_pdu *pdu = (struct smb2_sync_pdu *)buf;
> +       struct smb2_sync_hdr *shdr = &pdu->sync_hdr;
>         int offset; /* the offset from the beginning of SMB to data area */
>         int data_length; /* the length of the variable length data area */
>         /* Structure Size has already been checked to make sure it is 64 */
> -       int len = 4 + le16_to_cpu(shdr->StructureSize);
> +       int len = le16_to_cpu(shdr->StructureSize);
>
>         /*
>          * StructureSize2, ie length of fixed parameter area has already
> @@ -380,7 +369,7 @@ smb2_calc_size(void *buf)
>         if (has_smb2_data_area[le16_to_cpu(shdr->Command)] == false)
>                 goto calc_size_exit;
>
> -       smb2_get_data_area_len(&offset, &data_length, hdr);
> +       smb2_get_data_area_len(&offset, &data_length, shdr);
>         cifs_dbg(FYI, "SMB2 data length %d offset %d\n", data_length, offset);
>
>         if (data_length > 0) {
> @@ -388,15 +377,14 @@ smb2_calc_size(void *buf)
>                  * Check to make sure that data area begins after fixed area,
>                  * Note that last byte of the fixed area is part of data area
>                  * for some commands, typically those with odd StructureSize,
> -                * so we must add one to the calculation (and 4 to account for
> -                * the size of the RFC1001 hdr.
> +                * so we must add one to the calculation.
>                  */
> -               if (offset + 4 + 1 < len) {
> +               if (offset + 1 < len) {
>                         cifs_dbg(VFS, "data area offset %d overlaps SMB2 header %d\n",
> -                                offset + 4 + 1, len);
> +                                offset + 1, len);
>                         data_length = 0;
>                 } else {
> -                       len = 4 + offset + data_length;
> +                       len = offset + data_length;
>                 }
>         }
>  calc_size_exit:
> @@ -579,7 +567,7 @@ smb2_is_valid_lease_break(char *buffer)
>  bool
>  smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
>  {
> -       struct smb2_oplock_break_rsp *rsp = (struct smb2_oplock_break_rsp *)buffer;
> +       struct smb2_oplock_break *rsp = (struct smb2_oplock_break *)buffer;
>         struct list_head *tmp, *tmp1, *tmp2;
>         struct cifs_ses *ses;
>         struct cifs_tcon *tcon;
> @@ -588,7 +576,7 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
>
>         cifs_dbg(FYI, "Checking for oplock break\n");
>
> -       if (rsp->hdr.sync_hdr.Command != SMB2_OPLOCK_BREAK)
> +       if (rsp->sync_hdr.Command != SMB2_OPLOCK_BREAK)
>                 return false;
>
>         if (rsp->StructureSize !=
> @@ -679,8 +667,8 @@ smb2_cancelled_close_fid(struct work_struct *work)
>  int
>  smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server)
>  {
> -       struct smb2_sync_hdr *sync_hdr = get_sync_hdr(buffer);
> -       struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer;
> +       struct smb2_sync_hdr *sync_hdr = (struct smb2_sync_hdr *)buffer;
> +       struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)sync_hdr;
>         struct cifs_tcon *tcon;
>         struct close_cancelled_open *cancelled;
>
> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
> index 09d3a2912869..48ee237c3fdf 100644
> --- a/fs/cifs/smb2ops.c
> +++ b/fs/cifs/smb2ops.c
> @@ -123,7 +123,8 @@ smb2_get_credits_field(struct TCP_Server_Info *server, const int optype)
>  static unsigned int
>  smb2_get_credits(struct mid_q_entry *mid)
>  {
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(mid->resp_buf);
> +       char *buf = mid->resp_buf;
> +       struct smb2_sync_hdr *shdr  = (struct smb2_sync_hdr *)buf;
>
>         return le16_to_cpu(shdr->CreditRequest);
>  }
> @@ -190,7 +191,7 @@ static struct mid_q_entry *
>  smb2_find_mid(struct TCP_Server_Info *server, char *buf)
>  {
>         struct mid_q_entry *mid;
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>         __u64 wire_mid = le64_to_cpu(shdr->MessageId);
>
>         if (shdr->ProtocolId == SMB2_TRANSFORM_PROTO_NUM) {
> @@ -215,7 +216,7 @@ static void
>  smb2_dump_detail(void *buf)
>  {
>  #ifdef CONFIG_CIFS_DEBUG2
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>
>         cifs_dbg(VFS, "Cmd: %d Err: 0x%x Flags: 0x%x Mid: %llu Pid: %d\n",
>                  shdr->Command, shdr->Status, shdr->Flags, shdr->MessageId,
> @@ -1241,7 +1242,7 @@ smb2_close_dir(const unsigned int xid, struct cifs_tcon *tcon,
>  static bool
>  smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length)
>  {
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>
>         if (shdr->Status != STATUS_PENDING)
>                 return false;
> @@ -1259,7 +1260,7 @@ smb2_is_status_pending(char *buf, struct TCP_Server_Info *server, int length)
>  static bool
>  smb2_is_session_expired(char *buf)
>  {
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>
>         if (shdr->Status != STATUS_NETWORK_SESSION_EXPIRED)
>                 return false;
> @@ -1451,6 +1452,7 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
>         __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
>         struct cifs_open_parms oparms;
>         struct cifs_fid fid;
> +       struct kvec err_iov = {NULL, 0};
>         struct smb2_err_rsp *err_buf = NULL;
>         struct smb2_symlink_err_rsp *symlink;
>         unsigned int sub_len;
> @@ -1473,15 +1475,16 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
>         oparms.fid = &fid;
>         oparms.reconnect = false;
>
> -       rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_buf);
> +       rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov);
>
>         if (!rc || !err_buf) {
>                 kfree(utf16_path);
>                 return -ENOENT;
>         }
>
> +       err_buf = err_iov.iov_base;
>         if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
> -           get_rfc1002_length(err_buf) + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) {
> +           err_iov.iov_len + server->vals->header_preamble_size < SMB2_SYMLINK_STRUCT_SIZE) {
>                 kfree(utf16_path);
>                 return -ENOENT;
>         }
> @@ -1494,13 +1497,13 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
>         print_len = le16_to_cpu(symlink->PrintNameLength);
>         print_offset = le16_to_cpu(symlink->PrintNameOffset);
>
> -       if (get_rfc1002_length(err_buf) + server->vals->header_preamble_size <
> +       if (err_iov.iov_len + server->vals->header_preamble_size <
>                         SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
>                 kfree(utf16_path);
>                 return -ENOENT;
>         }
>
> -       if (get_rfc1002_length(err_buf) + server->vals->header_preamble_size <
> +       if (err_iov.iov_len + server->vals->header_preamble_size <
>                         SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
>                 kfree(utf16_path);
>                 return -ENOENT;
> @@ -2052,12 +2055,11 @@ smb2_dir_needs_close(struct cifsFileInfo *cfile)
>  }
>
>  static void
> -fill_transform_hdr(struct TCP_Server_Info *server,
> -                  struct smb2_transform_hdr *tr_hdr, struct smb_rqst *old_rq)
> +fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
> +                  struct smb_rqst *old_rq)
>  {
>         struct smb2_sync_hdr *shdr =
>                         (struct smb2_sync_hdr *)old_rq->rq_iov[1].iov_base;
> -       unsigned int orig_len = get_rfc1002_length(old_rq->rq_iov[0].iov_base);
>
>         memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr));
>         tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM;
> @@ -2065,8 +2067,6 @@ fill_transform_hdr(struct TCP_Server_Info *server,
>         tr_hdr->Flags = cpu_to_le16(0x01);
>         get_random_bytes(&tr_hdr->Nonce, SMB3_AES128CMM_NONCE);
>         memcpy(&tr_hdr->SessionId, &shdr->SessionId, 8);
> -       inc_rfc1001_len(tr_hdr, sizeof(struct smb2_transform_hdr) - server->vals->header_preamble_size);
> -       inc_rfc1001_len(tr_hdr, orig_len);
>  }
>
>  /* We can not use the normal sg_set_buf() as we will sometimes pass a
> @@ -2078,11 +2078,16 @@ static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
>         sg_set_page(sg, virt_to_page(buf), buflen, offset_in_page(buf));
>  }
>
> +/* Assumes:
> + * rqst->rq_iov[0]  is rfc1002 length
> + * rqst->rq_iov[1]  is tranform header
> + * rqst->rq_iov[2+] data to be encrypted/decrypted
> + */
>  static struct scatterlist *
>  init_sg(struct smb_rqst *rqst, u8 *sign)
>  {
> -       unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages + 1;
> -       unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24;
> +       unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages;
> +       unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
>         struct scatterlist *sg;
>         unsigned int i;
>         unsigned int j;
> @@ -2092,10 +2097,10 @@ init_sg(struct smb_rqst *rqst, u8 *sign)
>                 return NULL;
>
>         sg_init_table(sg, sg_len);
> -       smb2_sg_set_buf(&sg[0], rqst->rq_iov[0].iov_base + 24, assoc_data_len);
> -       for (i = 1; i < rqst->rq_nvec; i++)
> -               smb2_sg_set_buf(&sg[i], rqst->rq_iov[i].iov_base,
> -                                               rqst->rq_iov[i].iov_len);
> +       smb2_sg_set_buf(&sg[0], rqst->rq_iov[1].iov_base + 20, assoc_data_len);
> +       for (i = 1; i < rqst->rq_nvec - 1; i++)
> +               smb2_sg_set_buf(&sg[i], rqst->rq_iov[i+1].iov_base,
> +                                               rqst->rq_iov[i+1].iov_len);
>         for (j = 0; i < sg_len - 1; i++, j++) {
>                 unsigned int len = (j < rqst->rq_npages - 1) ? rqst->rq_pagesz
>                                                         : rqst->rq_tailsz;
> @@ -2127,17 +2132,18 @@ smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key)
>  }
>  /*
>   * Encrypt or decrypt @rqst message. @rqst has the following format:
> - * iov[0] - transform header (associate data),
> - * iov[1-N] and pages - data to encrypt.
> - * On success return encrypted data in iov[1-N] and pages, leave iov[0]
> + * iov[0] - rfc1002 length
> + * iov[1] - transform header (associate data),
> + * iov[2-N] and pages - data to encrypt.
> + * On success return encrypted data in iov[2-N] and pages, leave iov[0-1]
>   * untouched.
>   */
>  static int
>  crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)
>  {
>         struct smb2_transform_hdr *tr_hdr =
> -                       (struct smb2_transform_hdr *)rqst->rq_iov[0].iov_base;
> -       unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 24;
> +                       (struct smb2_transform_hdr *)rqst->rq_iov[1].iov_base;
> +       unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;

The same here: please use header_preamble_size.

>         int rc = 0;
>         struct scatterlist *sg;
>         u8 sign[SMB2_SIGNATURE_SIZE] = {};
> @@ -2224,6 +2230,9 @@ crypt_message(struct TCP_Server_Info *server, struct smb_rqst *rqst, int enc)
>         return rc;
>  }
>
> +/* This is called from smb_send_rqst. At this point we have the rfc1002
> + * header as the first element in the vector.
> + */

The comment style should be:
/*
 * text
 */

>  static int
>  smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
>                        struct smb_rqst *old_rq)
> @@ -2232,6 +2241,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
>         struct page **pages;
>         struct smb2_transform_hdr *tr_hdr;
>         unsigned int npages = old_rq->rq_npages;
> +       unsigned int orig_len = get_rfc1002_length(old_rq->rq_iov[0].iov_base);
>         int i;
>         int rc = -ENOMEM;
>
> @@ -2250,24 +2260,34 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
>                         goto err_free_pages;
>         }
>
> -       iov = kmalloc_array(old_rq->rq_nvec, sizeof(struct kvec), GFP_KERNEL);
> +       /* Make space for one extra iov to hold the transform header */
> +       iov = kmalloc_array(old_rq->rq_nvec + 1, sizeof(struct kvec),
> +                           GFP_KERNEL);
>         if (!iov)
>                 goto err_free_pages;
>
>         /* copy all iovs from the old except the 1st one (rfc1002 length) */
> -       memcpy(&iov[1], &old_rq->rq_iov[1],
> +       memcpy(&iov[2], &old_rq->rq_iov[1],
>                                 sizeof(struct kvec) * (old_rq->rq_nvec - 1));
> +       /* copy the rfc1002 iov */
> +       iov[0].iov_base = old_rq->rq_iov[0].iov_base;
> +       iov[0].iov_len  = old_rq->rq_iov[0].iov_len;
> +
>         new_rq->rq_iov = iov;
> -       new_rq->rq_nvec = old_rq->rq_nvec;
> +       new_rq->rq_nvec = old_rq->rq_nvec + 1;
>
>         tr_hdr = kmalloc(sizeof(struct smb2_transform_hdr), GFP_KERNEL);
>         if (!tr_hdr)
>                 goto err_free_iov;
>
> -       /* fill the 1st iov with a transform header */
> -       fill_transform_hdr(server, tr_hdr, old_rq);
> -       new_rq->rq_iov[0].iov_base = tr_hdr;
> -       new_rq->rq_iov[0].iov_len = sizeof(struct smb2_transform_hdr);
> +       /* fill the 2nd iov with a transform header */
> +       fill_transform_hdr(tr_hdr, orig_len, old_rq);
> +       new_rq->rq_iov[1].iov_base = tr_hdr;
> +       new_rq->rq_iov[1].iov_len = sizeof(struct smb2_transform_hdr);
> +
> +       /* Update rfc1002 header */
> +       inc_rfc1001_len(new_rq->rq_iov[0].iov_base,
> +                       sizeof(struct smb2_transform_hdr));
>
>         /* copy pages form the old */
>         for (i = 0; i < npages; i++) {
> @@ -2307,7 +2327,7 @@ smb3_free_transform_rq(struct smb_rqst *rqst)
>                 put_page(rqst->rq_pages[i]);
>         kfree(rqst->rq_pages);
>         /* free transform header */
> -       kfree(rqst->rq_iov[0].iov_base);
> +       kfree(rqst->rq_iov[1].iov_base);
>         kfree(rqst->rq_iov);
>  }
>
> @@ -2324,18 +2344,19 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
>                  unsigned int buf_data_size, struct page **pages,
>                  unsigned int npages, unsigned int page_data_size)
>  {
> -       struct kvec iov[2];
> +       struct kvec iov[3];
>         struct smb_rqst rqst = {NULL};
> -       struct smb2_hdr *hdr;
>         int rc;
>
> -       iov[0].iov_base = buf;
> -       iov[0].iov_len = sizeof(struct smb2_transform_hdr);
> -       iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr);
> -       iov[1].iov_len = buf_data_size;
> +       iov[0].iov_base = NULL;
> +       iov[0].iov_len = 0;
> +       iov[1].iov_base = buf;
> +       iov[1].iov_len = sizeof(struct smb2_transform_hdr);
> +       iov[2].iov_base = buf + sizeof(struct smb2_transform_hdr);
> +       iov[2].iov_len = buf_data_size;
>
>         rqst.rq_iov = iov;
> -       rqst.rq_nvec = 2;
> +       rqst.rq_nvec = 3;
>         rqst.rq_pages = pages;
>         rqst.rq_npages = npages;
>         rqst.rq_pagesz = PAGE_SIZE;
> @@ -2347,10 +2368,9 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
>         if (rc)
>                 return rc;
>
> -       memmove(buf + server->vals->header_preamble_size, iov[1].iov_base, buf_data_size);
> -       hdr = (struct smb2_hdr *)buf;
> -       hdr->smb2_buf_length = cpu_to_be32(buf_data_size + page_data_size);
> -       server->total_read = buf_data_size + page_data_size + server->vals->header_preamble_size;
> +       memmove(buf + server->vals->header_preamble_size, iov[2].iov_base, buf_data_size);
> +
> +       server->total_read = buf_data_size + page_data_size;
>
>         return rc;
>  }
> @@ -2423,7 +2443,7 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
>         unsigned int cur_page_idx;
>         unsigned int pad_len;
>         struct cifs_readdata *rdata = mid->callback_data;
> -       struct smb2_sync_hdr *shdr = get_sync_hdr(buf);
> +       struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
>         struct bio_vec *bvec = NULL;
>         struct iov_iter iter;
>         struct kvec iov;
> @@ -2550,7 +2570,7 @@ receive_encrypted_read(struct TCP_Server_Info *server, struct mid_q_entry **mid)
>         unsigned int npages;
>         struct page **pages;
>         unsigned int len;
> -       unsigned int buflen = get_rfc1002_length(buf) + server->vals->header_preamble_size;
> +       unsigned int buflen = server->pdu_size + server->vals->header_preamble_size;
>         int rc;
>         int i = 0;
>
> @@ -2624,7 +2644,7 @@ receive_encrypted_standard(struct TCP_Server_Info *server,
>  {
>         int length;
>         char *buf = server->smallbuf;
> -       unsigned int pdu_length = get_rfc1002_length(buf);
> +       unsigned int pdu_length = server->pdu_size;
>         unsigned int buf_size;
>         struct mid_q_entry *mid_entry;
>
> @@ -2668,7 +2688,7 @@ static int
>  smb3_receive_transform(struct TCP_Server_Info *server, struct mid_q_entry **mid)
>  {
>         char *buf = server->smallbuf;
> -       unsigned int pdu_length = get_rfc1002_length(buf);
> +       unsigned int pdu_length = server->pdu_size;
>         struct smb2_transform_hdr *tr_hdr = (struct smb2_transform_hdr *)buf;
>         unsigned int orig_len = le32_to_cpu(tr_hdr->OriginalMessageSize);
>
> @@ -2699,7 +2719,7 @@ smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>  {
>         char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
>
> -       return handle_read_data(server, mid, buf, get_rfc1002_length(buf) +
> +       return handle_read_data(server, mid, buf, server->total_read +

Should we use server->pdu_size here instead?

>                                 server->vals->header_preamble_size,
>                                 NULL, 0, 0);
>  }
> @@ -3104,8 +3124,8 @@ struct smb_version_values smb20_values = {
>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
> -       .header_size = sizeof(struct smb2_hdr),
> -       .header_preamble_size = 4,
> +       .header_size = sizeof(struct smb2_sync_hdr),
> +       .header_preamble_size = 0,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> @@ -3125,8 +3145,8 @@ struct smb_version_values smb21_values = {
>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
> -       .header_size = sizeof(struct smb2_hdr),
> -       .header_preamble_size = 4,
> +       .header_size = sizeof(struct smb2_sync_hdr),
> +       .header_preamble_size = 0,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> @@ -3146,8 +3166,8 @@ struct smb_version_values smb3any_values = {
>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
> -       .header_size = sizeof(struct smb2_hdr),
> -       .header_preamble_size = 4,
> +       .header_size = sizeof(struct smb2_sync_hdr),
> +       .header_preamble_size = 0,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> @@ -3167,8 +3187,8 @@ struct smb_version_values smbdefault_values = {
>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
> -       .header_size = sizeof(struct smb2_hdr),
> -       .header_preamble_size = 4,
> +       .header_size = sizeof(struct smb2_sync_hdr),
> +       .header_preamble_size = 0,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> @@ -3188,8 +3208,8 @@ struct smb_version_values smb30_values = {
>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
> -       .header_size = sizeof(struct smb2_hdr),
> -       .header_preamble_size = 4,
> +       .header_size = sizeof(struct smb2_sync_hdr),
> +       .header_preamble_size = 0,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> @@ -3209,8 +3229,8 @@ struct smb_version_values smb302_values = {
>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
> -       .header_size = sizeof(struct smb2_hdr),
> -       .header_preamble_size = 4,
> +       .header_size = sizeof(struct smb2_sync_hdr),
> +       .header_preamble_size = 0,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> @@ -3231,8 +3251,8 @@ struct smb_version_values smb311_values = {
>         .exclusive_lock_type = SMB2_LOCKFLAG_EXCLUSIVE_LOCK,
>         .shared_lock_type = SMB2_LOCKFLAG_SHARED_LOCK,
>         .unlock_lock_type = SMB2_LOCKFLAG_UNLOCK,
> -       .header_size = sizeof(struct smb2_hdr),
> -       .header_preamble_size = 4,
> +       .header_size = sizeof(struct smb2_sync_hdr),
> +       .header_preamble_size = 0,
>         .max_header_size = MAX_SMB2_HDR_SIZE,
>         .read_rsp_size = sizeof(struct smb2_read_rsp) - 1,
>         .lock_cmd = SMB2_LOCK,
> diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
> index 4b6920de2541..b20348f72a6f 100644
> --- a/fs/cifs/smb2pdu.c
> +++ b/fs/cifs/smb2pdu.c
> @@ -591,7 +591,7 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
>         server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES;
>
>         security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
> -                                              &rsp->hdr);
> +                                              (struct smb2_sync_hdr *)rsp);
>         /*
>          * See MS-SMB2 section 2.2.4: if no blob, client picks default which
>          * for us will be
> @@ -942,7 +942,7 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data)
>                 goto out_put_spnego_key;
>
>         rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
> -       ses->Suid = rsp->hdr.sync_hdr.SessionId;
> +       ses->Suid = rsp->sync_hdr.SessionId;
>
>         ses->session_flags = le16_to_cpu(rsp->SessionFlags);
>
> @@ -1018,13 +1018,13 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
>
>         /* If true, rc here is expected and not an error */
>         if (sess_data->buf0_type != CIFS_NO_BUFFER &&
> -               rsp->hdr.sync_hdr.Status == STATUS_MORE_PROCESSING_REQUIRED)
> +               rsp->sync_hdr.Status == STATUS_MORE_PROCESSING_REQUIRED)
>                 rc = 0;
>
>         if (rc)
>                 goto out;
>
> -       if (offsetof(struct smb2_sess_setup_rsp, Buffer) - 4 !=
> +       if (offsetof(struct smb2_sess_setup_rsp, Buffer) !=
>                         le16_to_cpu(rsp->SecurityBufferOffset)) {
>                 cifs_dbg(VFS, "Invalid security buffer offset %d\n",
>                         le16_to_cpu(rsp->SecurityBufferOffset));
> @@ -1039,7 +1039,7 @@ SMB2_sess_auth_rawntlmssp_negotiate(struct SMB2_sess_data *sess_data)
>         cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n");
>
>
> -       ses->Suid = rsp->hdr.sync_hdr.SessionId;
> +       ses->Suid = rsp->sync_hdr.SessionId;
>         ses->session_flags = le16_to_cpu(rsp->SessionFlags);
>
>  out:
> @@ -1097,7 +1097,7 @@ SMB2_sess_auth_rawntlmssp_authenticate(struct SMB2_sess_data *sess_data)
>
>         rsp = (struct smb2_sess_setup_rsp *)sess_data->iov[0].iov_base;
>
> -       ses->Suid = rsp->hdr.sync_hdr.SessionId;
> +       ses->Suid = rsp->sync_hdr.SessionId;
>         ses->session_flags = le16_to_cpu(rsp->SessionFlags);
>
>         rc = SMB2_sess_establish_session(sess_data);
> @@ -1340,7 +1340,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
>         tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess);
>         tcon->tidStatus = CifsGood;
>         tcon->need_reconnect = false;
> -       tcon->tid = rsp->hdr.sync_hdr.TreeId;
> +       tcon->tid = rsp->sync_hdr.TreeId;
>         strlcpy(tcon->treeName, tree, sizeof(tcon->treeName));
>
>         if ((rsp->Capabilities & SMB2_SHARE_CAP_DFS) &&
> @@ -1360,7 +1360,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
>         return rc;
>
>  tcon_error_exit:
> -       if (rsp && rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
> +       if (rsp && rsp->sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
>                 cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
>         }
>         goto tcon_exit;
> @@ -1466,7 +1466,7 @@ parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp,
>         unsigned int remaining;
>         char *name;
>
> -       data_offset = (char *)rsp + 4 + le32_to_cpu(rsp->CreateContextsOffset);
> +       data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset);

the same as above.

>         remaining = le32_to_cpu(rsp->CreateContextsLength);
>         cc = (struct create_context *)data_offset;
>         while (remaining >= sizeof(struct create_context)) {
> @@ -1694,7 +1694,7 @@ alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
>  int
>  SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
>           __u8 *oplock, struct smb2_file_all_info *buf,
> -         struct smb2_err_rsp **err_buf)
> +         struct kvec *err_iov)
>  {
>         struct smb2_create_req *req;
>         struct smb2_create_rsp *rsp;
> @@ -1834,9 +1834,10 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
>
>         if (rc != 0) {
>                 cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
> -               if (err_buf && rsp)
> -                       *err_buf = kmemdup(rsp, get_rfc1002_length(rsp) + 4,
> -                                          GFP_KERNEL);
> +               if (err_iov && rsp) {
> +                       *err_iov = rsp_iov;
> +                       rsp = NULL;
> +               }
>                 goto creat_exit;
>         }
>
> @@ -1875,7 +1876,6 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
>  {
>         struct smb2_ioctl_req *req;
>         struct smb2_ioctl_rsp *rsp;
> -       struct smb2_sync_hdr *shdr;
>         struct cifs_ses *ses;
>         struct kvec iov[2];
>         struct kvec rsp_iov;
> @@ -1996,7 +1996,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
>                 goto ioctl_exit;
>         }
>
> -       if (get_rfc1002_length(rsp) < le32_to_cpu(rsp->OutputOffset) + *plen) {
> +       if (rsp_iov.iov_len < le32_to_cpu(rsp->OutputOffset) + *plen) {
>                 cifs_dbg(VFS, "Malformed ioctl resp: len %d offset %d\n", *plen,
>                         le32_to_cpu(rsp->OutputOffset));
>                 *plen = 0;
> @@ -2010,8 +2010,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
>                 goto ioctl_exit;
>         }
>
> -       shdr = get_sync_hdr(rsp);
> -       memcpy(*out_data, (char *)shdr + le32_to_cpu(rsp->OutputOffset), *plen);
> +       memcpy(*out_data, (char *)rsp + le32_to_cpu(rsp->OutputOffset), *plen);
>  ioctl_exit:
>         free_rsp_buf(resp_buftype, rsp);
>         return rc;
> @@ -2091,13 +2090,12 @@ SMB2_close(const unsigned int xid, struct cifs_tcon *tcon,
>  }
>
>  static int
> -validate_buf(unsigned int offset, unsigned int buffer_length,
> -            struct smb2_hdr *hdr, unsigned int min_buf_size)
> -
> +validate_iov(unsigned int offset, unsigned int buffer_length,
> +            struct kvec *iov, unsigned int min_buf_size)
>  {
> -       unsigned int smb_len = be32_to_cpu(hdr->smb2_buf_length);
> -       char *end_of_smb = smb_len + 4 /* RFC1001 length field */ + (char *)hdr;
> -       char *begin_of_buf = 4 /* RFC1001 len field */ + offset + (char *)hdr;
> +       unsigned int smb_len = iov->iov_len;
> +       char *end_of_smb = smb_len + (char *)iov->iov_base;
> +       char *begin_of_buf = offset + (char *)iov->iov_base;
>         char *end_of_buf = begin_of_buf + buffer_length;
>
>
> @@ -2127,18 +2125,17 @@ validate_buf(unsigned int offset, unsigned int buffer_length,
>   * Caller must free buffer.
>   */
>  static int
> -validate_and_copy_buf(unsigned int offset, unsigned int buffer_length,
> -                     struct smb2_hdr *hdr, unsigned int minbufsize,
> +validate_and_copy_iov(unsigned int offset, unsigned int buffer_length,
> +                     struct kvec *iov, unsigned int minbufsize,
>                       char *data)
> -
>  {
> -       char *begin_of_buf = 4 /* RFC1001 len field */ + offset + (char *)hdr;
> +       char *begin_of_buf = offset + (char *)iov->iov_base;
>         int rc;
>
>         if (!data)
>                 return -EINVAL;
>
> -       rc = validate_buf(offset, buffer_length, hdr, minbufsize);
> +       rc = validate_iov(offset, buffer_length, iov, minbufsize);
>         if (rc)
>                 return rc;
>
> @@ -2216,9 +2213,9 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
>                 }
>         }
>
> -       rc = validate_and_copy_buf(le16_to_cpu(rsp->OutputBufferOffset),
> +       rc = validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset),
>                                    le32_to_cpu(rsp->OutputBufferLength),
> -                                  &rsp->hdr, min_len, *data);
> +                                  &rsp_iov, min_len, *data);
>
>  qinf_exit:
>         free_rsp_buf(resp_buftype, rsp);
> @@ -2287,7 +2284,7 @@ smb2_echo_callback(struct mid_q_entry *mid)
>         unsigned int credits_received = 1;
>
>         if (mid->mid_state == MID_RESPONSE_RECEIVED)
> -               credits_received = le16_to_cpu(rsp->hdr.sync_hdr.CreditRequest);
> +               credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
>
>         DeleteMidQEntry(mid);
>         add_credits(server, credits_received, CIFS_ECHO_OP);
> @@ -2684,7 +2681,6 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
>         int resp_buftype, rc = -EACCES;
>         struct smb2_read_plain_req *req = NULL;
>         struct smb2_read_rsp *rsp = NULL;
> -       struct smb2_sync_hdr *shdr;
>         struct kvec iov[1];
>         struct kvec rsp_iov;
>         unsigned int total_len;
> @@ -2725,10 +2721,8 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
>                 *nbytes = 0;
>         }
>
> -       shdr = get_sync_hdr(rsp);
> -
>         if (*buf) {
> -               memcpy(*buf, (char *)shdr + rsp->DataOffset, *nbytes);
> +               memcpy(*buf, (char *)rsp + rsp->DataOffset, *nbytes);
>                 free_rsp_buf(resp_buftype, rsp_iov.iov_base);
>         } else if (resp_buftype != CIFS_NO_BUFFER) {
>                 *buf = rsp_iov.iov_base;
> @@ -2755,7 +2749,7 @@ smb2_writev_callback(struct mid_q_entry *mid)
>
>         switch (mid->mid_state) {
>         case MID_RESPONSE_RECEIVED:
> -               credits_received = le16_to_cpu(rsp->hdr.sync_hdr.CreditRequest);
> +               credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
>                 wdata->result = smb2_check_receive(mid, tcon->ses->server, 0);
>                 if (wdata->result != 0)
>                         break;
> @@ -3131,7 +3125,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
>
>         if (rc) {
>                 if (rc == -ENODATA &&
> -                   rsp->hdr.sync_hdr.Status == STATUS_NO_MORE_FILES) {
> +                   rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) {
>                         srch_inf->endOfSearch = true;
>                         rc = 0;
>                 }
> @@ -3139,8 +3133,8 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
>                 goto qdir_exit;
>         }
>
> -       rc = validate_buf(le16_to_cpu(rsp->OutputBufferOffset),
> -                         le32_to_cpu(rsp->OutputBufferLength), &rsp->hdr,
> +       rc = validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
> +                         le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
>                           info_buf_size);
>         if (rc)
>                 goto qdir_exit;
> @@ -3154,10 +3148,9 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
>                         cifs_buf_release(srch_inf->ntwrk_buf_start);
>         }
>         srch_inf->ntwrk_buf_start = (char *)rsp;
> -       srch_inf->srch_entries_start = srch_inf->last_entry = 4 /* rfclen */ +
> -               (char *)&rsp->hdr + le16_to_cpu(rsp->OutputBufferOffset);
> -       /* 4 for rfc1002 length field */
> -       end_of_smb = get_rfc1002_length(rsp) + 4 + (char *)&rsp->hdr;
> +       srch_inf->srch_entries_start = srch_inf->last_entry =
> +               (char *)rsp + le16_to_cpu(rsp->OutputBufferOffset);
> +       end_of_smb = rsp_iov.iov_len + (char *)rsp;
>         srch_inf->entries_in_buffer =
>                         num_entries(srch_inf->srch_entries_start, end_of_smb,
>                                     &srch_inf->last_entry, info_buf_size);
> @@ -3393,7 +3386,7 @@ SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
>                   __u8 oplock_level)
>  {
>         int rc;
> -       struct smb2_oplock_break_req *req = NULL;
> +       struct smb2_oplock_break *req = NULL;
>         struct cifs_ses *ses = tcon->ses;
>         int flags = CIFS_OBREAK_OP;
>         unsigned int total_len;
> @@ -3469,7 +3462,7 @@ build_qfs_info_req(struct kvec *iov, struct cifs_tcon *tcon, int level,
>         req->InputBufferOffset =
>                         cpu_to_le16(sizeof(struct smb2_query_info_req) - 1);
>         req->OutputBufferLength = cpu_to_le32(
> -               outbuf_len + sizeof(struct smb2_query_info_rsp) - 1 - 4);
> +               outbuf_len + sizeof(struct smb2_query_info_rsp) - 1);

the same.

>
>         iov->iov_base = (char *)req;
>         iov->iov_len = total_len;
> @@ -3506,10 +3499,10 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
>         }
>         rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
>
> -       info = (struct smb2_fs_full_size_info *)(4 /* RFC1001 len */ +

here as well.

> -               le16_to_cpu(rsp->OutputBufferOffset) + (char *)&rsp->hdr);
> -       rc = validate_buf(le16_to_cpu(rsp->OutputBufferOffset),
> -                         le32_to_cpu(rsp->OutputBufferLength), &rsp->hdr,
> +       info = (struct smb2_fs_full_size_info *)(
> +               le16_to_cpu(rsp->OutputBufferOffset) + (char *)rsp);
> +       rc = validate_iov(le16_to_cpu(rsp->OutputBufferOffset),
> +                         le32_to_cpu(rsp->OutputBufferLength), &rsp_iov,
>                           sizeof(struct smb2_fs_full_size_info));
>         if (!rc)
>                 copy_fs_info_to_kstatfs(info, fsdata);
> @@ -3564,20 +3557,20 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
>
>         rsp_len = le32_to_cpu(rsp->OutputBufferLength);
>         offset = le16_to_cpu(rsp->OutputBufferOffset);
> -       rc = validate_buf(offset, rsp_len, &rsp->hdr, min_len);
> +       rc = validate_iov(offset, rsp_len, &rsp_iov, min_len);
>         if (rc)
>                 goto qfsattr_exit;
>
>         if (level == FS_ATTRIBUTE_INFORMATION)
> -               memcpy(&tcon->fsAttrInfo, 4 /* RFC1001 len */ + offset
> -                       + (char *)&rsp->hdr, min_t(unsigned int,
> +               memcpy(&tcon->fsAttrInfo, offset
> +                       + (char *)rsp, min_t(unsigned int,
>                         rsp_len, max_len));
>         else if (level == FS_DEVICE_INFORMATION)
> -               memcpy(&tcon->fsDevInfo, 4 /* RFC1001 len */ + offset

the same as above.

> -                       + (char *)&rsp->hdr, sizeof(FILE_SYSTEM_DEVICE_INFO));
> +               memcpy(&tcon->fsDevInfo, offset
> +                       + (char *)rsp, sizeof(FILE_SYSTEM_DEVICE_INFO));
>         else if (level == FS_SECTOR_SIZE_INFORMATION) {
>                 struct smb3_fs_ss_info *ss_info = (struct smb3_fs_ss_info *)
> -                       (4 /* RFC1001 len */ + offset + (char *)&rsp->hdr);
> +                       (offset + (char *)rsp);
>                 tcon->ss_flags = le32_to_cpu(ss_info->Flags);
>                 tcon->perf_sector_size =
>                         le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf);
> diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
> index 8b901c69a65a..6bf243a45d64 100644
> --- a/fs/cifs/smb2pdu.h
> +++ b/fs/cifs/smb2pdu.h
> @@ -122,25 +122,10 @@ struct smb2_sync_pdu {
>         __le16 StructureSize2; /* size of wct area (varies, request specific) */
>  } __packed;
>
> -struct smb2_hdr {
> -       __be32 smb2_buf_length; /* big endian on wire */
> -                               /* length is only two or three bytes - with */
> -                               /* one or two byte type preceding it that MBZ */
> -       struct smb2_sync_hdr sync_hdr;
> -} __packed;
> -
> -struct smb2_pdu {
> -       struct smb2_hdr hdr;
> -       __le16 StructureSize2; /* size of wct area (varies, request specific) */
> -} __packed;
> -
>  #define SMB3_AES128CMM_NONCE 11
>  #define SMB3_AES128GCM_NONCE 12
>
>  struct smb2_transform_hdr {
> -       __be32 smb2_buf_length; /* big endian on wire */
> -                               /* length is only two or three bytes - with
> -                                one or two byte type preceding it that MBZ */
>         __le32 ProtocolId;      /* 0xFD 'S' 'M' 'B' */
>         __u8   Signature[16];
>         __u8   Nonce[16];
> @@ -171,7 +156,7 @@ struct smb2_transform_hdr {
>  #define SMB2_ERROR_STRUCTURE_SIZE2 cpu_to_le16(9)
>
>  struct smb2_err_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize;
>         __le16 Reserved; /* MBZ */
>         __le32 ByteCount;  /* even if zero, at least one byte follows */
> @@ -289,7 +274,7 @@ struct smb2_encryption_neg_context {
>  } __packed;
>
>  struct smb2_negotiate_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize;   /* Must be 65 */
>         __le16 SecurityMode;
>         __le16 DialectRevision;
> @@ -329,7 +314,7 @@ struct smb2_sess_setup_req {
>  #define SMB2_SESSION_FLAG_IS_NULL      0x0002
>  #define SMB2_SESSION_FLAG_ENCRYPT_DATA 0x0004
>  struct smb2_sess_setup_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* Must be 9 */
>         __le16 SessionFlags;
>         __le16 SecurityBufferOffset;
> @@ -344,7 +329,7 @@ struct smb2_logoff_req {
>  } __packed;
>
>  struct smb2_logoff_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize;   /* Must be 4 */
>         __le16 Reserved;
>  } __packed;
> @@ -440,7 +425,7 @@ struct smb2_tree_connect_req_extension {
>  } __packed;
>
>  struct smb2_tree_connect_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize;   /* Must be 16 */
>         __u8   ShareType;  /* see below */
>         __u8   Reserved;
> @@ -491,7 +476,7 @@ struct smb2_tree_disconnect_req {
>  } __packed;
>
>  struct smb2_tree_disconnect_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize;   /* Must be 4 */
>         __le16 Reserved;
>  } __packed;
> @@ -626,7 +611,7 @@ struct smb2_create_req {
>  } __packed;
>
>  struct smb2_create_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize;   /* Must be 89 */
>         __u8   OplockLevel;
>         __u8   Reserved;
> @@ -882,7 +867,7 @@ struct smb2_ioctl_req {
>  } __packed;
>
>  struct smb2_ioctl_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize;   /* Must be 57 */
>         __u16 Reserved;
>         __le32 CtlCode;
> @@ -909,7 +894,7 @@ struct smb2_close_req {
>  } __packed;
>
>  struct smb2_close_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* 60 */
>         __le16 Flags;
>         __le32 Reserved;
> @@ -932,7 +917,7 @@ struct smb2_flush_req {
>  } __packed;
>
>  struct smb2_flush_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize;
>         __le16 Reserved;
>  } __packed;
> @@ -964,7 +949,7 @@ struct smb2_read_plain_req {
>  } __packed;
>
>  struct smb2_read_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* Must be 17 */
>         __u8   DataOffset;
>         __u8   Reserved;
> @@ -995,7 +980,7 @@ struct smb2_write_req {
>  } __packed;
>
>  struct smb2_write_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* Must be 17 */
>         __u8   DataOffset;
>         __u8   Reserved;
> @@ -1029,7 +1014,7 @@ struct smb2_lock_req {
>  } __packed;
>
>  struct smb2_lock_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* Must be 4 */
>         __le16 Reserved;
>  } __packed;
> @@ -1041,7 +1026,7 @@ struct smb2_echo_req {
>  } __packed;
>
>  struct smb2_echo_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize;   /* Must be 4 */
>         __u16  Reserved;
>  } __packed;
> @@ -1067,7 +1052,7 @@ struct smb2_query_directory_req {
>  } __packed;
>
>  struct smb2_query_directory_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* Must be 9 */
>         __le16 OutputBufferOffset;
>         __le32 OutputBufferLength;
> @@ -1116,7 +1101,7 @@ struct smb2_query_info_req {
>  } __packed;
>
>  struct smb2_query_info_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* Must be 9 */
>         __le16 OutputBufferOffset;
>         __le32 OutputBufferLength;
> @@ -1138,12 +1123,11 @@ struct smb2_set_info_req {
>  } __packed;
>
>  struct smb2_set_info_rsp {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* Must be 2 */
>  } __packed;
>
> -/* oplock break without an rfc1002 header */
> -struct smb2_oplock_break_req {
> +struct smb2_oplock_break {
>         struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* Must be 24 */
>         __u8   OplockLevel;
> @@ -1153,21 +1137,10 @@ struct smb2_oplock_break_req {
>         __u64  VolatileFid;
>  } __packed;
>
> -/* oplock break with an rfc1002 header */
> -struct smb2_oplock_break_rsp {
> -       struct smb2_hdr hdr;
> -       __le16 StructureSize; /* Must be 24 */
> -       __u8   OplockLevel;
> -       __u8   Reserved;
> -       __le32 Reserved2;
> -       __u64  PersistentFid;
> -       __u64  VolatileFid;
> -} __packed;
> -
>  #define SMB2_NOTIFY_BREAK_LEASE_FLAG_ACK_REQUIRED cpu_to_le32(0x01)
>
>  struct smb2_lease_break {
> -       struct smb2_hdr hdr;
> +       struct smb2_sync_hdr sync_hdr;
>         __le16 StructureSize; /* Must be 44 */
>         __le16 Reserved;
>         __le32 Flags;
> diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
> index cbcce3f7e86f..30cdc0aa4e8e 100644
> --- a/fs/cifs/smb2proto.h
> +++ b/fs/cifs/smb2proto.h
> @@ -37,7 +37,8 @@ extern int map_smb2_to_linux_error(char *buf, bool log_err);
>  extern int smb2_check_message(char *buf, unsigned int length,
>                               struct TCP_Server_Info *server);
>  extern unsigned int smb2_calc_size(void *buf);
> -extern char *smb2_get_data_area_len(int *off, int *len, struct smb2_hdr *hdr);
> +extern char *smb2_get_data_area_len(int *off, int *len,
> +                                   struct smb2_sync_hdr *shdr);
>  extern __le16 *cifs_convert_path_to_utf16(const char *from,
>                                           struct cifs_sb_info *cifs_sb);
>
> @@ -122,7 +123,7 @@ extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon);
>  extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
>                      __le16 *path, __u8 *oplock,
>                      struct smb2_file_all_info *buf,
> -                    struct smb2_err_rsp **err_buf);
> +                    struct kvec *err_iov);
>  extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
>                      u64 persistent_fid, u64 volatile_fid, u32 opcode,
>                      bool is_fsctl, char *in_data, u32 indatalen,
> diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
> index bf49cb73b9e6..8372a0cecdb0 100644
> --- a/fs/cifs/smb2transport.c
> +++ b/fs/cifs/smb2transport.c
> @@ -480,7 +480,7 @@ smb2_verify_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
>         unsigned int rc;
>         char server_response_sig[16];
>         struct smb2_sync_hdr *shdr =
> -                       (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
> +                       (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
>
>         if ((shdr->Command == SMB2_NEGOTIATE) ||
>             (shdr->Command == SMB2_SESSION_SETUP) ||
> @@ -604,15 +604,13 @@ int
>  smb2_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
>                    bool log_error)
>  {
> -       unsigned int len = get_rfc1002_length(mid->resp_buf);
> -       struct kvec iov[2];
> +       unsigned int len = server->total_read;
> +       struct kvec iov[1];
>         struct smb_rqst rqst = { .rq_iov = iov,
> -                                .rq_nvec = 2 };
> +                                .rq_nvec = 1 };
>
>         iov[0].iov_base = (char *)mid->resp_buf;
> -       iov[0].iov_len = 4;
> -       iov[1].iov_base = (char *)mid->resp_buf + 4;
> -       iov[1].iov_len = len;
> +       iov[0].iov_len = mid->resp_buf_size;
>
>         dump_smb(mid->resp_buf, min_t(u32, 80, len));
>         /* convert the length into a more usable form */
> diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
> index 279718dcb2ed..3abce580b056 100644
> --- a/fs/cifs/transport.c
> +++ b/fs/cifs/transport.c
> @@ -790,8 +790,9 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
>
>         buf = (char *)midQ->resp_buf;
>         resp_iov->iov_base = buf;
> -       resp_iov->iov_len = get_rfc1002_length(buf) +
> +       resp_iov->iov_len = midQ->resp_buf_size +
>                 ses->server->vals->header_preamble_size;
> +
>         if (midQ->large_buf)
>                 *resp_buf_type = CIFS_LARGE_BUFFER;
>         else
> --
> 2.13.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux