[CIFS] Add support for legacy servers part 4
authorSteve French <sfrench@us.ibm.com>
Wed, 31 Aug 2005 03:58:07 +0000 (20:58 -0700)
committerSteve French <sfrench@us.ibm.com>
Wed, 31 Aug 2005 03:58:07 +0000 (20:58 -0700)
Fix WriteX support for old servers which do not support large
files.

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

index c8ae3ef422baa4372ad0ab4e14d1ab53db2f73ba..74733851cfad5f49e78cfc488475e1dca0916297 100644 (file)
@@ -1082,12 +1082,20 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
        int rc = -EACCES;
        WRITE_REQ *pSMB = NULL;
        WRITE_RSP *pSMBr = NULL;
-       int bytes_returned;
+       int bytes_returned, wct;
        __u32 bytes_sent;
        __u16 byte_count;
 
        /* cFYI(1,("write at %lld %d bytes",offset,count));*/
-       rc = smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB,
+       if(tcon->ses == NULL)
+               return -ECONNABORTED;
+
+       if(tcon->ses->capabilities & CAP_LARGE_FILES)
+               wct = 14;
+       else
+               wct = 12;
+
+       rc = smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB,
                      (void **) &pSMBr);
        if (rc)
                return rc;
@@ -1098,7 +1106,11 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
        pSMB->AndXCommand = 0xFF;       /* none */
        pSMB->Fid = netfid;
        pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
-       pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
+       if(wct == 14) 
+               pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
+       else if((offset >> 32) > 0) /* can not handle this big offset for old */
+               return -EIO;
+       
        pSMB->Reserved = 0xFFFFFFFF;
        pSMB->WriteMode = 0;
        pSMB->Remaining = 0;
@@ -1135,7 +1147,14 @@ CIFSSMBWrite(const int xid, struct cifsTconInfo *tcon,
        pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
        pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
        pSMB->hdr.smb_buf_length += bytes_sent+1;
-       pSMB->ByteCount = cpu_to_le16(byte_count);
+
+       if(wct == 14)
+               pSMB->ByteCount = cpu_to_le16(byte_count);
+       else { /* old style write has byte count 4 bytes earlier */
+               struct smb_com_writex_req * pSMBW = 
+                       (struct smb_com_writex_req *)pSMB;
+               pSMBW->ByteCount = cpu_to_le16(byte_count);
+       }
 
        rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
                         (struct smb_hdr *) pSMBr, &bytes_returned, long_op);
index f784b70abfeb5b95597d0a9f40c6b1952322930b..196976049c00e12dce6dda11b8915be2450beaa6 100644 (file)
@@ -1079,7 +1079,7 @@ cifs_parse_mount_options(char *options, const char *devname,struct smb_vol *vol)
                } else if (strnicmp(data, "brl", 3) == 0) {
                        vol->nobrl =  0;
                } else if ((strnicmp(data, "nobrl", 5) == 0) || 
-                          (strnicmp(data, "nolock", 6)) {
+                          (strnicmp(data, "nolock", 6) == 0)) {
                        vol->nobrl =  1;
                        /* turn off mandatory locking in mode
                        if remote locking is turned off since the
index ef455dda0473c2551325212f5943a44c11f6a781..b6c303f6373f056e8de7a99f2e17fca2296e7214 100644 (file)
@@ -1183,11 +1183,16 @@ 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;
@@ -1212,16 +1217,21 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data,
                                if (rc != 0)
                                        break;
                        }
-
-                       rc = CIFSSMBRead(xid, pTcon,
-                                open_file->netfid,
-                                current_read_size, *poffset,
-                                &bytes_read, &smb_read_data);
-                       if(rc == -EINVAL) {
+                       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,
+                                       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, 
@@ -1266,6 +1276,7 @@ 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);
@@ -1276,6 +1287,9 @@ 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"));
@@ -1294,16 +1308,23 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
                                if (rc != 0)
                                        break;
                        }
-
-                       rc = CIFSSMBRead(xid, pTcon,
-                                open_file->netfid,
-                                current_read_size, *poffset,
-                                &bytes_read, &current_offset);
-                       if(rc == -EINVAL) {
+                       if(use_old_read) 
                                rc = SMBLegacyRead(xid, pTcon,
+                                        open_file->netfid,
+                                        current_read_size, *poffset,
+                                        &bytes_read, &current_offset);
+                       else {
+                               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)) {
@@ -1402,6 +1423,7 @@ 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) {
@@ -1411,7 +1433,9 @@ 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; ) {
@@ -1457,15 +1481,21 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
                                        break;
                        }
 
-                       rc = CIFSSMBRead(xid, pTcon,
-                               open_file->netfid,
-                               read_size, offset,
-                               &bytes_read, &smb_read_data);
-                       if (rc == -EINVAL) {
+                       if(use_old_read)
                                rc = SMBLegacyRead(xid, pTcon,
                                        open_file->netfid,
                                        read_size, offset,
                                        &bytes_read, &smb_read_data);
+                       else {
+                               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 ? */