[CIFS] Add support for legacy servers part 5
authorSteve French <sfrench@us.ibm.com>
Thu, 1 Sep 2005 04:50:37 +0000 (21:50 -0700)
committerSteve French <sfrench@us.ibm.com>
Thu, 1 Sep 2005 04:50:37 +0000 (21:50 -0700)
Handle small negotiated read sizes (under 4K) and finish up
read and write support.

Signed-off-by: Steve French <sfrench@us.ibm.com>
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/readdir.c

index 656b78ddf6743ace10d2aa6edeb99f56b021c607..6943f7c6de08468eb138ae41c833165ec8a67e69 100644 (file)
@@ -226,9 +226,6 @@ extern int SMBLegacyOpen(const int xid, struct cifsTconInfo *tcon,
 extern int CIFSSMBClose(const int xid, struct cifsTconInfo *tcon,
                        const int smb_file_id);
 
-extern int SMBLegacyRead(const int xid, struct cifsTconInfo *tcon,
-                       const int netfid, unsigned int count,
-                       const __u64 lseek, unsigned int *nbytes, char **buf);
 extern int CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
                        const int netfid, unsigned int count,
                        const __u64 lseek, unsigned int *nbytes, char **buf);
index 74733851cfad5f49e78cfc488475e1dca0916297..b8830118f09a0f755e1d733553c06be842ac43b8 100644 (file)
@@ -923,81 +923,6 @@ openRetry:
        return rc;
 }
 
-int
-SMBLegacyRead(const int xid, struct cifsTconInfo *tcon,
-            const int netfid, unsigned int count,
-            const __u64 lseek, unsigned int *nbytes, char **buf)
-{
-       int rc = -EACCES;
-       READX_REQ *pSMB = NULL;
-       READ_RSP *pSMBr = NULL;
-       char *pReadData = NULL;
-       int bytes_returned;
-
-       cFYI(1,("Legacy read %d bytes fid %d",count,netfid));
-
-       /* field is shorter in legacy read, only 16 bits */
-       if(count > 2048)
-               count = 2048;  /* BB FIXME make this configurable */
-
-       if(lseek > 0xFFFFFFFF)
-               return -EIO; /* can not read that far into file on old server */
-
-       *nbytes = 0;
-       rc = smb_init(SMB_COM_READ_ANDX, 10, tcon, (void **) &pSMB,
-                     (void **) &pSMBr);
-       if (rc)
-               return rc;
-
-       /* tcon and ses pointer are checked in smb_init */
-       if (tcon->ses->server == NULL)
-               return -ECONNABORTED;
-
-       pSMB->AndXCommand = 0xFF;       /* none */
-       pSMB->Fid = netfid;
-       pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
-       pSMB->Remaining = 0;
-       pSMB->MaxCount = cpu_to_le16(count);
-       pSMB->Reserved = 0; /* Must Be Zero */
-       pSMB->ByteCount = 0;  /* no need to do le conversion since it is 0 */
-
-       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
-                        (struct smb_hdr *) pSMBr, &bytes_returned, 0);
-       cifs_stats_inc(&tcon->num_reads);
-       if (rc) {
-               cERROR(1, ("Send error in legacy read = %d", rc));
-       } else {
-               int data_length = le16_to_cpu(pSMBr->DataLengthHigh);
-               data_length = data_length << 16;
-               data_length += le16_to_cpu(pSMBr->DataLength);
-               *nbytes = data_length;
-
-               /*check that DataLength would not go beyond end of SMB */
-               if ((data_length > CIFSMaxBufSize) || (data_length > count)) {
-                       cFYI(1,("bad length %d for count %d",data_length,count));
-                       rc = -EIO;
-                       *nbytes = 0;
-               } else {
-                       pReadData = (char *) (&pSMBr->hdr.Protocol) +
-                                               le16_to_cpu(pSMBr->DataOffset);
-/*                      if(rc = copy_to_user(buf, pReadData, data_length)) {
-                               cERROR(1,("Faulting on read rc = %d",rc));
-                               rc = -EFAULT;
-                       }*/ /* can not use copy_to_user when using page cache*/
-                       if(*buf)
-                               memcpy(*buf,pReadData,data_length);
-               }
-       }
-       if(*buf)
-               cifs_buf_release(pSMB);
-       else
-               *buf = (char *)pSMB;
-
-       /* Note: On -EAGAIN error only caller can retry on handle based calls
-               since file handle passed in no longer valid */
-       return rc;
-}
-
 /* If no buffer passed in, then caller wants to do the copy
        as in the case of readpages so the SMB buffer must be
        freed by the caller */
@@ -1012,11 +937,16 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
        READ_RSP *pSMBr = NULL;
        char *pReadData = NULL;
        int bytes_returned;
+       int wct;
 
        cFYI(1,("Reading %d bytes on fid %d",count,netfid));
+       if(tcon->ses->capabilities & CAP_LARGE_FILES)
+               wct = 12;
+       else
+               wct = 10; /* old style read */
 
        *nbytes = 0;
-       rc = smb_init(SMB_COM_READ_ANDX, 12, tcon, (void **) &pSMB,
+       rc = smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
        if (rc)
                return rc;
@@ -1028,12 +958,23 @@ CIFSSMBRead(const int xid, struct cifsTconInfo *tcon,
        pSMB->AndXCommand = 0xFF;       /* none */
        pSMB->Fid = netfid;
        pSMB->OffsetLow = cpu_to_le32(lseek & 0xFFFFFFFF);
-       pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
+       if(wct == 12)
+               pSMB->OffsetHigh = cpu_to_le32(lseek >> 32);
+        else if((lseek >> 32) > 0) /* can not handle this big offset for old */
+                return -EIO;
+
        pSMB->Remaining = 0;
        pSMB->MaxCount = cpu_to_le16(count & 0xFFFF);
        pSMB->MaxCountHigh = cpu_to_le32(count >> 16);
-       pSMB->ByteCount = 0;  /* no need to do le conversion since it is 0 */
-
+       if(wct == 12)
+               pSMB->ByteCount = 0;  /* no need to do le conversion since 0 */
+       else {
+               /* old style read */
+               struct smb_com_readx_req * pSMBW = 
+                       (struct smb_com_readx_req *)pSMB;
+               pSMBW->ByteCount = 0;   
+       }
+       
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, 0);
        cifs_stats_inc(&tcon->num_reads);
index b6c303f6373f056e8de7a99f2e17fca2296e7214..5ecda554f9130f9c386cdbff1e5c6ca9f0808015 100644 (file)
@@ -1183,16 +1183,11 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
        char *smb_read_data;
        char __user *current_offset;
        struct smb_com_read_rsp *pSMBr;
-       int use_old_read = FALSE;
 
        xid = GetXid();
        cifs_sb = CIFS_SB(file->f_dentry->d_sb);
        pTcon = cifs_sb->tcon;
 
-       if(pTcon->ses)
-               if((pTcon->ses->capabilities & CAP_LARGE_FILES) == 0)
-                       use_old_read = TRUE;
-
        if (file->private_data == NULL) {
                FreeXid(xid);
                return -EBADF;
@@ -1217,22 +1212,10 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
                                if (rc != 0)
                                        break;
                        }
-                       if(use_old_read)
-                               rc = SMBLegacyRead(xid, pTcon,
-                                       open_file->netfid,
-                                       current_read_size, *poffset,
-                                       &bytes_read, &smb_read_data);
-                       else {
-                               rc = CIFSSMBRead(xid, pTcon,
+                       rc = CIFSSMBRead(xid, pTcon,
                                        open_file->netfid,
                                        current_read_size, *poffset,
                                        &bytes_read, &smb_read_data);
-                               if(rc == -EINVAL) {
-                                       use_old_read = TRUE;
-                                       rc = -EAGAIN;
-                                       continue;
-                               }
-                       }
                        pSMBr = (struct smb_com_read_rsp *)smb_read_data;
                        if (copy_to_user(current_offset, 
                                         smb_read_data + 4 /* RFC1001 hdr */
@@ -1276,7 +1259,6 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
        int xid;
        char *current_offset;
        struct cifsFileInfo *open_file;
-       int use_old_read = FALSE;
 
        xid = GetXid();
        cifs_sb = CIFS_SB(file->f_dentry->d_sb);
@@ -1287,9 +1269,6 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
                return -EBADF;
        }
        open_file = (struct cifsFileInfo *)file->private_data;
-       if(pTcon->ses)
-               if((pTcon->ses->capabilities & CAP_LARGE_FILES) == 0)
-                       use_old_read = TRUE;
 
        if ((file->f_flags & O_ACCMODE) == O_WRONLY)
                cFYI(1, ("attempting read on write only file instance"));
@@ -1308,24 +1287,10 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
                                if (rc != 0)
                                        break;
                        }
-                       if(use_old_read) 
-                               rc = SMBLegacyRead(xid, pTcon,
-                                        open_file->netfid,
-                                        current_read_size, *poffset,
-                                        &bytes_read, &current_offset);
-                       else {
-                               rc = CIFSSMBRead(xid, pTcon,
+                       rc = CIFSSMBRead(xid, pTcon,
                                        open_file->netfid,
                                        current_read_size, *poffset,
                                        &bytes_read, &current_offset);
-                               /* check if server disavows support for
-                                  64 bit offsets */
-                               if(rc == -EINVAL) {
-                                       rc = -EAGAIN;
-                                       use_old_read = TRUE;
-                                       continue;
-                               }
-                       }
                }
                if (rc || (bytes_read == 0)) {
                        if (total_read) {
@@ -1423,7 +1388,6 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
        struct smb_com_read_rsp *pSMBr;
        struct pagevec lru_pvec;
        struct cifsFileInfo *open_file;
-       int use_old_read = FALSE;
 
        xid = GetXid();
        if (file->private_data == NULL) {
@@ -1433,9 +1397,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
        open_file = (struct cifsFileInfo *)file->private_data;
        cifs_sb = CIFS_SB(file->f_dentry->d_sb);
        pTcon = cifs_sb->tcon;
-       if(pTcon->ses)
-               if((pTcon->ses->capabilities & CAP_LARGE_FILES) == 0)
-                       use_old_read = TRUE;
+
        pagevec_init(&lru_pvec, 0);
 
        for (i = 0; i < num_pages; ) {
@@ -1481,22 +1443,10 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
                                        break;
                        }
 
-                       if(use_old_read)
-                               rc = SMBLegacyRead(xid, pTcon,
-                                       open_file->netfid,
-                                       read_size, offset,
-                                       &bytes_read, &smb_read_data);
-                       else {
-                               rc = CIFSSMBRead(xid, pTcon,
+                       rc = CIFSSMBRead(xid, pTcon,
                                        open_file->netfid,
                                        read_size, offset,
                                        &bytes_read, &smb_read_data);
-                               if(rc == -EINVAL) {
-                                       use_old_read = TRUE;
-                                       rc = -EAGAIN;
-                                       continue;
-                               }
-                       }
 
                        /* BB more RC checks ? */
                        if (rc== -EAGAIN) {
index 0485c6d6ecd525b0080021898a27aaf551f44cf4..0fbe02ebc0335498bdc648287358e900662a8a87 100644 (file)
@@ -169,6 +169,10 @@ int cifs_get_inode_info_unix(struct inode **pinode,
                        if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
                                inode->i_fop->lock = NULL;
                        inode->i_data.a_ops = &cifs_addr_ops;
+                       /* check if server can support readpages */
+                       if(pTcon->ses->server->maxBuf < 
+                           4096 + MAX_CIFS_HDR_SIZE)
+                               inode->i_data.a_ops->readpages = NULL;
                } else if (S_ISDIR(inode->i_mode)) {
                        cFYI(1, (" Directory inode"));
                        inode->i_op = &cifs_dir_inode_ops;
@@ -384,6 +388,9 @@ int cifs_get_inode_info(struct inode **pinode,
                        if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
                                inode->i_fop->lock = NULL;
                        inode->i_data.a_ops = &cifs_addr_ops;
+                       if(pTcon->ses->server->maxBuf < 
+                            4096 + MAX_CIFS_HDR_SIZE)
+                               inode->i_data.a_ops->readpages = NULL;
                } else if (S_ISDIR(inode->i_mode)) {
                        cFYI(1, (" Directory inode "));
                        inode->i_op = &cifs_dir_inode_ops;
index 9780f4ee7f1285bf1dff4fd6627ebefafdc41de9..a1e8dc901de46d161dc8865732c0ba31593fcb5d 100644 (file)
@@ -200,7 +200,10 @@ static void fill_in_inode(struct inode *tmp_inode,
                if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
                        tmp_inode->i_fop->lock = NULL;
                tmp_inode->i_data.a_ops = &cifs_addr_ops;
-
+               if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
+                  (cifs_sb->tcon->ses->server->maxBuf <
+                       4096 + MAX_CIFS_HDR_SIZE))
+                       tmp_inode->i_data.a_ops->readpages = NULL;
                if(isNewInode)
                        return; /* No sense invalidating pages for new inode
                                   since have not started caching readahead file
@@ -306,6 +309,10 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
                if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
                        tmp_inode->i_fop->lock = NULL;
                tmp_inode->i_data.a_ops = &cifs_addr_ops;
+               if((cifs_sb->tcon) && (cifs_sb->tcon->ses) &&
+                  (cifs_sb->tcon->ses->server->maxBuf < 
+                       4096 + MAX_CIFS_HDR_SIZE))
+                       tmp_inode->i_data.a_ops->readpages = NULL;
 
                if(isNewInode)
                        return; /* No sense invalidating pages for new inode since we