Re: [PATCH v2 09/11] CIFS: Separate protocol-specific code from cifs_readv_receive code

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

 



20 марта 2012 г. 14:24 пользователь Jeff Layton <jlayton@xxxxxxxxxx> написал:
> On Tue, 20 Mar 2012 11:33:42 +0400
> Pavel Shilovsky <piastry@xxxxxxxxxxx> wrote:
>
>> 20 марта 2012 г. 0:17 пользователь Jeff Layton <jlayton@xxxxxxxxxx> написал:
>> > On Fri, 16 Mar 2012 18:09:32 +0300
>> > Pavel Shilovsky <piastry@xxxxxxxxxxx> wrote:
>> >
>> >> Signed-off-by: Pavel Shilovsky <piastry@xxxxxxxxxxx>
>> >> ---
>> >>  fs/cifs/cifsglob.h  |   12 ++++++++++
>> >>  fs/cifs/cifsproto.h |    2 +-
>> >>  fs/cifs/cifssmb.c   |   58 +++++++++++++++++++++++++++++++++-----------------
>> >>  fs/cifs/connect.c   |   12 ----------
>> >>  fs/cifs/netmisc.c   |    3 +-
>> >>  5 files changed, 53 insertions(+), 34 deletions(-)
>> >>
>> >> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
>> >> index 34a897e..a403398 100644
>> >> --- a/fs/cifs/cifsglob.h
>> >> +++ b/fs/cifs/cifsglob.h
>> >> @@ -341,6 +341,18 @@ has_credits(struct TCP_Server_Info *server, int *credits)
>> >>       return num > 0;
>> >>  }
>> >>
>> >> +static inline size_t
>> >> +header_size(void)
>> >> +{
>> >> +     return sizeof(struct smb_hdr);
>> >> +}
>> >> +
>> >> +static inline size_t
>> >> +max_header_size(void)
>> >> +{
>> >> +     return MAX_CIFS_HDR_SIZE;
>> >> +}
>> >> +
>> >>  /*
>> >>   * Macros to allow the TCP_Server_Info->net field and related code to drop out
>> >>   * when CONFIG_NET_NS isn't set.
>> >> diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
>> >> index 15c9b59..db38a40 100644
>> >> --- a/fs/cifs/cifsproto.h
>> >> +++ b/fs/cifs/cifsproto.h
>> >> @@ -106,7 +106,7 @@ extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len);
>> >>  extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port);
>> >>  extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len,
>> >>                               const unsigned short int port);
>> >> -extern int map_smb_to_linux_error(struct smb_hdr *smb, bool logErr);
>> >> +extern int map_smb_to_linux_error(char *buf, bool logErr);
>> >>  extern void header_assemble(struct smb_hdr *, char /* command */ ,
>> >>                           const struct cifs_tcon *, int /* length of
>> >>                           fixed section (word count) in two byte units */);
>> >> diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
>> >> index d3b8089..765f804 100644
>> >> --- a/fs/cifs/cifssmb.c
>> >> +++ b/fs/cifs/cifssmb.c
>> >> @@ -1415,8 +1415,7 @@ cifs_readdata_free(struct cifs_readdata *rdata)
>> >>  static int
>> >>  cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>> >>  {
>> >> -     READ_RSP *rsp = (READ_RSP *)server->smallbuf;
>> >> -     unsigned int rfclen = be32_to_cpu(rsp->hdr.smb_buf_length);
>> >> +     unsigned int rfclen = get_rfc1002_length(server->smallbuf);
>> >>       int remaining = rfclen + 4 - server->total_read;
>> >>       struct cifs_readdata *rdata = mid->callback_data;
>> >>
>> >> @@ -1425,7 +1424,7 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>> >>
>> >>               length = cifs_read_from_socket(server, server->bigbuf,
>> >>                               min_t(unsigned int, remaining,
>> >> -                                     CIFSMaxBufSize + MAX_CIFS_HDR_SIZE));
>> >> +                                     CIFSMaxBufSize + max_header_size()));
>> >>               if (length < 0)
>> >>                       return length;
>> >>               server->total_read += length;
>> >> @@ -1436,14 +1435,35 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>> >>       return 0;
>> >>  }
>> >>
>> >> +static inline size_t
>> >> +read_rsp_size(void)
>> >> +{
>> >> +     return sizeof(READ_RSP);
>> >> +}
>> >> +
>> >> +static inline unsigned int
>> >> +read_data_offset(char *buf)
>> >> +{
>> >> +     READ_RSP *rsp = (READ_RSP *)buf;
>> >> +     return le16_to_cpu(rsp->DataOffset);
>> >> +}
>> >> +
>> >> +static inline unsigned int
>> >> +read_data_length(char *buf)
>> >> +{
>> >> +     READ_RSP *rsp = (READ_RSP *)buf;
>> >> +     return (le16_to_cpu(rsp->DataLengthHigh) << 16) +
>> >> +            le16_to_cpu(rsp->DataLength);
>> >> +}
>> >> +
>> >>  static int
>> >>  cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>> >>  {
>> >>       int length, len;
>> >>       unsigned int data_offset, remaining, data_len;
>> >>       struct cifs_readdata *rdata = mid->callback_data;
>> >> -     READ_RSP *rsp = (READ_RSP *)server->smallbuf;
>> >> -     unsigned int rfclen = be32_to_cpu(rsp->hdr.smb_buf_length) + 4;
>> >> +     char *buf = server->smallbuf;
>> >> +     unsigned int buflen = get_rfc1002_length(buf) + 4;
>> >>       u64 eof;
>> >>       pgoff_t eof_index;
>> >>       struct page *page, *tpage;
>> >> @@ -1456,10 +1476,9 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>> >>        * can if there's not enough data. At this point, we've read down to
>> >>        * the Mid.
>> >>        */
>> >> -     len = min_t(unsigned int, rfclen, sizeof(*rsp)) -
>> >> -                     sizeof(struct smb_hdr) + 1;
>> >> +     len = min_t(unsigned int, buflen, read_rsp_size()) - header_size() + 1;
>> >>
>> >> -     rdata->iov[0].iov_base = server->smallbuf + sizeof(struct smb_hdr) - 1;
>> >> +     rdata->iov[0].iov_base = buf + header_size() - 1;
>> >>       rdata->iov[0].iov_len = len;
>> >>
>> >>       length = cifs_readv_from_socket(server, rdata->iov, 1, len);
>> >> @@ -1468,7 +1487,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>> >>       server->total_read += length;
>> >>
>> >>       /* Was the SMB read successful? */
>> >> -     rdata->result = map_smb_to_linux_error(&rsp->hdr, false);
>> >> +     rdata->result = map_smb_to_linux_error(buf, false);
>> >>       if (rdata->result != 0) {
>> >>               cFYI(1, "%s: server returned error %d", __func__,
>> >>                       rdata->result);
>> >> @@ -1476,14 +1495,14 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>> >>       }
>> >>
>> >>       /* Is there enough to get to the rest of the READ_RSP header? */
>> >> -     if (server->total_read < sizeof(READ_RSP)) {
>> >> +     if (server->total_read < read_rsp_size()) {
>> >>               cFYI(1, "%s: server returned short header. got=%u expected=%zu",
>> >> -                     __func__, server->total_read, sizeof(READ_RSP));
>> >> +                     __func__, server->total_read, read_rsp_size());
>> >>               rdata->result = -EIO;
>> >>               return cifs_readv_discard(server, mid);
>> >>       }
>> >>
>> >> -     data_offset = le16_to_cpu(rsp->DataOffset) + 4;
>> >> +     data_offset = read_data_offset(buf) + 4;
>> >>       if (data_offset < server->total_read) {
>> >>               /*
>> >>                * win2k8 sometimes sends an offset of 0 when the read
>> >> @@ -1507,7 +1526,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>> >>       len = data_offset - server->total_read;
>> >>       if (len > 0) {
>> >>               /* read any junk before data into the rest of smallbuf */
>> >> -             rdata->iov[0].iov_base = server->smallbuf + server->total_read;
>> >> +             rdata->iov[0].iov_base = buf + server->total_read;
>> >>               rdata->iov[0].iov_len = len;
>> >>               length = cifs_readv_from_socket(server, rdata->iov, 1, len);
>> >>               if (length < 0)
>> >> @@ -1516,15 +1535,14 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>> >>       }
>> >>
>> >>       /* set up first iov for signature check */
>> >> -     rdata->iov[0].iov_base = server->smallbuf;
>> >> +     rdata->iov[0].iov_base = buf;
>> >>       rdata->iov[0].iov_len = server->total_read;
>> >>       cFYI(1, "0: iov_base=%p iov_len=%zu",
>> >>               rdata->iov[0].iov_base, rdata->iov[0].iov_len);
>> >>
>> >>       /* how much data is in the response? */
>> >> -     data_len = le16_to_cpu(rsp->DataLengthHigh) << 16;
>> >> -     data_len += le16_to_cpu(rsp->DataLength);
>> >> -     if (data_offset + data_len > rfclen) {
>> >> +     data_len = read_data_length(buf);
>> >> +     if (data_offset + data_len > buflen) {
>> >>               /* data_len is corrupt -- discard frame */
>> >>               rdata->result = -EIO;
>> >>               return cifs_readv_discard(server, mid);
>> >> @@ -1603,11 +1621,11 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
>> >>
>> >>       rdata->bytes = length;
>> >>
>> >> -     cFYI(1, "total_read=%u rfclen=%u remaining=%u", server->total_read,
>> >> -             rfclen, remaining);
>> >> +     cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read,
>> >> +             buflen, remaining);
>> >>
>> >>       /* discard anything left over */
>> >> -     if (server->total_read < rfclen)
>> >> +     if (server->total_read < buflen)
>> >>               return cifs_readv_discard(server, mid);
>> >>
>> >>       dequeue_mid(mid, false);
>> >> diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
>> >> index 76cffc9..3d46493 100644
>> >> --- a/fs/cifs/connect.c
>> >> +++ b/fs/cifs/connect.c
>> >> @@ -338,18 +338,6 @@ requeue_echo:
>> >>       queue_delayed_work(system_nrt_wq, &server->echo, SMB_ECHO_INTERVAL);
>> >>  }
>> >>
>> >> -static inline size_t
>> >> -header_size(void)
>> >> -{
>> >> -     return sizeof(struct smb_hdr);
>> >> -}
>> >> -
>> >> -static inline size_t
>> >> -max_header_size(void)
>> >> -{
>> >> -     return MAX_CIFS_HDR_SIZE;
>> >> -}
>> >> -
>> >>  static bool
>> >>  allocate_buffers(struct TCP_Server_Info *server)
>> >>  {
>> >> diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c
>> >> index 73e47e8..dd23a32 100644
>> >> --- a/fs/cifs/netmisc.c
>> >> +++ b/fs/cifs/netmisc.c
>> >> @@ -836,8 +836,9 @@ ntstatus_to_dos(__u32 ntstatus, __u8 *eclass, __u16 *ecode)
>> >>  }
>> >>
>> >>  int
>> >> -map_smb_to_linux_error(struct smb_hdr *smb, bool logErr)
>> >> +map_smb_to_linux_error(char *buf, bool logErr)
>> >>  {
>> >> +     struct smb_hdr *smb = (struct smb_hdr *)buf;
>> >>       unsigned int i;
>> >>       int rc = -EIO;  /* if transport error smb error may not be set */
>> >>       __u8 smberrclass;
>> >
>> > You're changing the prototype of the above function, but are not
>> > changing both of the callers. If you expect to pass different pointer
>> > types in there in the future, then it might be best to call it a void
>> > pointer instead of a char?
>>
>> The first caller is cifs_readv_receive and it passes char pointer -
>> ok. The second caller is cifs_check_receive - passes void pointer - ok
>> too.
>>
>
> In my tree, cifs_check_receive does this:
>
>        return map_smb_to_linux_error(mid->resp_buf, log_error);
>
> ...and mid->resp_buf is:
>
>        struct smb_hdr *resp_buf;       /* pointer to received SMB header */
>
> ...not a void pointer.
>

Oh - yes, thanks - will respin it soon.

-- 
Best regards,
Pavel Shilovsky.
--
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