Merge with rsync://rsync.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git
authorSteve French <sfrench@us.ibm.com>
Thu, 23 Jun 2005 01:26:47 +0000 (20:26 -0500)
committerSteve French <sfrench@us.ibm.com>
Thu, 23 Jun 2005 01:26:47 +0000 (20:26 -0500)
1  2 
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/file.c

diff --combined fs/cifs/cifsproto.h
@@@ -40,17 -40,13 +40,17 @@@ extern unsigned int _GetXid(void)
  extern void _FreeXid(unsigned int);
  #define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__FUNCTION__, xid,current->fsuid));
  #define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__FUNCTION__,curr_xid,(int)rc));}
- extern char *build_path_from_dentry(struct dentry *);
+ extern char *build_path_from_dentry(struct dentry *, const struct cifs_sb_info *cifs_sb);
  extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
  extern void renew_parental_timestamps(struct dentry *direntry);
  extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
                        struct smb_hdr * /* input */ ,
                        struct smb_hdr * /* out */ ,
                        int * /* bytes returned */ , const int long_op);
 +extern int SendReceive2(const unsigned int /* xid */ , struct cifsSesInfo *,
 +                      struct smb_hdr * /* input */ , int hdr_len,
 +                      const char * /* SMB data to send */ , int data_len,
 +                      int * /* bytes returned */ , const int long_op);
  extern int checkSMBhdr(struct smb_hdr *smb, __u16 mid);
  extern int checkSMB(struct smb_hdr *smb, __u16 mid, int length);
  extern int is_valid_oplock_break(struct smb_hdr *smb);
@@@ -93,7 -89,7 +93,7 @@@ extern int CIFSTCon(unsigned int xid, s
  
  extern int CIFSFindFirst(const int xid, struct cifsTconInfo *tcon,
              const char *searchName, const struct nls_table *nls_codepage,
-             __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map);
+             __u16 *searchHandle, struct cifs_search_info * psrch_inf, int map, const char dirsep);
  
  extern int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
              __u16 searchHandle, struct cifs_search_info * psrch_inf);
@@@ -129,6 -125,9 +129,9 @@@ extern int get_dfs_path(int xid, struc
                        int remap);
  extern int CIFSSMBQFSInfo(const int xid, struct cifsTconInfo *tcon,
                        struct kstatfs *FSData);
+ extern int CIFSSMBSETFSUnixInfo(const int xid, struct cifsTconInfo *tcon,
+                       __u64 cap);
  extern int CIFSSMBQFSAttributeInfo(const int xid,
                        struct cifsTconInfo *tcon);
  extern int CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon);
@@@ -226,7 -225,7 +229,7 @@@ extern int CIFSSMBWrite(const int xid, 
  extern int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
                        const int netfid, const unsigned int count,
                        const __u64 offset, unsigned int *nbytes, 
 -                      const char __user *buf,const int long_op);
 +                      const char *buf,const int long_op);
  extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
                        const unsigned char *searchName, __u64 * inode_number,
                        const struct nls_table *nls_codepage, 
diff --combined fs/cifs/cifssmb.c
@@@ -951,69 -951,56 +951,69 @@@ CIFSSMBWrite(const int xid, struct cifs
  }
  
  #ifdef CONFIG_CIFS_EXPERIMENTAL
 -int CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
 +int
 +CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
             const int netfid, const unsigned int count,
 -           const __u64 offset, unsigned int *nbytes, const char __user *buf,
 +           const __u64 offset, unsigned int *nbytes, const char *buf,
             const int long_op)
  {
        int rc = -EACCES;
        WRITE_REQ *pSMB = NULL;
 -      WRITE_RSP *pSMBr = NULL;
 -      /*int bytes_returned;*/
 -      unsigned bytes_sent;
 +      int bytes_returned;
 +      int smb_hdr_len;
 +      __u32 bytes_sent;
        __u16 byte_count;
  
 +      cERROR(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
        rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
 -    
        if (rc)
                return rc;
 -      
 -      pSMBr = (WRITE_RSP *)pSMB; /* BB removeme BB */
 -
        /* tcon and ses pointer are checked in smb_init */
        if (tcon->ses->server == NULL)
                return -ECONNABORTED;
  
 -      pSMB->AndXCommand = 0xFF; /* none */
 +      pSMB->AndXCommand = 0xFF;       /* none */
        pSMB->Fid = netfid;
        pSMB->OffsetLow = cpu_to_le32(offset & 0xFFFFFFFF);
        pSMB->OffsetHigh = cpu_to_le32(offset >> 32);
        pSMB->Reserved = 0xFFFFFFFF;
        pSMB->WriteMode = 0;
        pSMB->Remaining = 0;
 -      bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & ~0xFF;
 +
 +      /* Can increase buffer size if buffer is big enough in some cases - ie 
 +      can send more if LARGE_WRITE_X capability returned by the server and if
 +      our buffer is big enough or if we convert to iovecs on socket writes
 +      and eliminate the copy to the CIFS buffer */
 +      if(tcon->ses->capabilities & CAP_LARGE_WRITE_X) {
 +              bytes_sent = min_t(const unsigned int, CIFSMaxBufSize, count);
 +      } else {
 +              bytes_sent = (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)
 +                       & ~0xFF;
 +      }
 +
        if (bytes_sent > count)
                bytes_sent = count;
 -      pSMB->DataLengthHigh = 0;
        pSMB->DataOffset =
            cpu_to_le16(offsetof(struct smb_com_write_req,Data) - 4);
  
 -      byte_count = bytes_sent + 1 /* pad */ ;
 -      pSMB->DataLengthLow = cpu_to_le16(bytes_sent);
 -      pSMB->DataLengthHigh = 0;
 -      pSMB->hdr.smb_buf_length += byte_count;
 +      byte_count = bytes_sent + 1 /* pad */ ; /* BB fix this for sends > 64K */
 +      pSMB->DataLengthLow = cpu_to_le16(bytes_sent & 0xFFFF);
 +      pSMB->DataLengthHigh = cpu_to_le16(bytes_sent >> 16);
 +      smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
 +      pSMB->hdr.smb_buf_length += bytes_sent+1;
        pSMB->ByteCount = cpu_to_le16(byte_count);
  
 -/*    rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB,
 -                       (struct smb_hdr *) pSMBr, buf, buflen, &bytes_returned, long_op); */  /* BB fixme BB */
 +      rc = SendReceive2(xid, tcon->ses, (struct smb_hdr *) pSMB, smb_hdr_len,
 +                        buf, bytes_sent, &bytes_returned, long_op);
        if (rc) {
 -              cFYI(1, ("Send error in write2 (large write) = %d", rc));
 +              cFYI(1, ("Send error in write = %d", rc));
                *nbytes = 0;
 -      } else
 -              *nbytes = le16_to_cpu(pSMBr->Count);
 +      } else {
 +              WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
 +              *nbytes = le16_to_cpu(pSMBr->CountHigh);
 +              *nbytes = (*nbytes) << 16;
 +              *nbytes += le16_to_cpu(pSMBr->Count);
 +      }
  
        cifs_small_buf_release(pSMB);
  
  
        return rc;
  }
 +
 +
  #endif /* CIFS_EXPERIMENTAL */
  
  int
@@@ -2411,7 -2396,9 +2411,9 @@@ findUniqueRetry
        if (rc) {
                cFYI(1, ("Send error in FindFileDirInfo = %d", rc));
        } else {                /* decode response */
+ #ifdef CONFIG_CIFS_STATS
+               atomic_inc(&tcon->num_ffirst);
+ #endif
                /* BB fill in */
        }
  
@@@ -2429,7 -2416,7 +2431,7 @@@ CIFSFindFirst(const int xid, struct cif
              const char *searchName, 
              const struct nls_table *nls_codepage,
              __u16 *   pnetfid,
-             struct cifs_search_info * psrch_inf, int remap)
+             struct cifs_search_info * psrch_inf, int remap, const char dirsep)
  {
  /* level 257 SMB_ */
        TRANSACTION2_FFIRST_REQ *pSMB = NULL;
@@@ -2456,7 -2443,7 +2458,7 @@@ findFirstRetry
                it got remapped to 0xF03A as if it were part of the
                directory name instead of a wildcard */
                name_len *= 2;
-               pSMB->FileName[name_len] = '\\';
+               pSMB->FileName[name_len] = dirsep;
                pSMB->FileName[name_len+1] = 0;
                pSMB->FileName[name_len+2] = '*';
                pSMB->FileName[name_len+3] = 0;
                if(name_len > buffersize-header)
                        free buffer exit; BB */
                strncpy(pSMB->FileName, searchName, name_len);
-               pSMB->FileName[name_len] = '\\';
+               pSMB->FileName[name_len] = dirsep;
                pSMB->FileName[name_len+1] = '*';
                pSMB->FileName[name_len+2] = 0;
                name_len += 3;
                if (rc == -EAGAIN)
                        goto findFirstRetry;
        } else { /* decode response */
+ #ifdef CONFIG_CIFS_STATS
+               atomic_inc(&tcon->num_ffirst);
+ #endif
                /* BB remember to free buffer if error BB */
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
                if(rc == 0) {
@@@ -2637,6 -2627,9 +2642,9 @@@ int CIFSFindNext(const int xid, struct 
                } else
                        cFYI(1, ("FindNext returned = %d", rc));
        } else {                /* decode response */
+ #ifdef CONFIG_CIFS_STATS
+               atomic_inc(&tcon->num_fnext);
+ #endif
                rc = validate_t2((struct smb_t2_rsp *)pSMBr);
                
                if(rc == 0) {
@@@ -2706,6 -2699,9 +2714,9 @@@ CIFSFindClose(const int xid, struct cif
        if (rc) {
                cERROR(1, ("Send error in FindClose = %d", rc));
        }
+ #ifdef CONFIG_CIFS_STATS
+       atomic_inc(&tcon->num_fclose);
+ #endif
        cifs_small_buf_release(pSMB);
  
        /* Since session is dead, search handle closed on server already */
@@@ -3269,6 -3265,77 +3280,77 @@@ QFSUnixRetry
        return rc;
  }
  
+ int
+ CIFSSMBSETFSUnixInfo(const int xid, struct cifsTconInfo *tcon, __u64 cap)
+ {
+ /* level 0x200  SMB_SET_CIFS_UNIX_INFO */
+       TRANSACTION2_SETFSI_REQ *pSMB = NULL;
+       TRANSACTION2_SETFSI_RSP *pSMBr = NULL;
+       int rc = 0;
+       int bytes_returned = 0;
+       __u16 params, param_offset, offset, byte_count;
+       cFYI(1, ("In SETFSUnixInfo"));
+ SETFSUnixRetry:
+       rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
+                     (void **) &pSMBr);
+       if (rc)
+               return rc;
+       params = 4;     /* 2 bytes zero followed by info level. */
+       pSMB->MaxSetupCount = 0;
+       pSMB->Reserved = 0;
+       pSMB->Flags = 0;
+       pSMB->Timeout = 0;
+       pSMB->Reserved2 = 0;
+       param_offset = offsetof(struct smb_com_transaction2_setfsi_req, FileNum) - 4;
+       offset = param_offset + params;
+       pSMB->MaxParameterCount = cpu_to_le16(4);
+       pSMB->MaxDataCount = cpu_to_le16(100);  /* BB find exact max SMB PDU from sess structure BB */
+       pSMB->SetupCount = 1;
+       pSMB->Reserved3 = 0;
+       pSMB->SubCommand = cpu_to_le16(TRANS2_SET_FS_INFORMATION);
+       byte_count = 1 /* pad */ + params + 12;
+       pSMB->DataCount = cpu_to_le16(12);
+       pSMB->ParameterCount = cpu_to_le16(params);
+       pSMB->TotalDataCount = pSMB->DataCount;
+       pSMB->TotalParameterCount = pSMB->ParameterCount;
+       pSMB->ParameterOffset = cpu_to_le16(param_offset);
+       pSMB->DataOffset = cpu_to_le16(offset);
+       /* Params. */
+       pSMB->FileNum = 0;
+       pSMB->InformationLevel = cpu_to_le16(SMB_SET_CIFS_UNIX_INFO);
+       /* Data. */
+       pSMB->ClientUnixMajor = cpu_to_le16(CIFS_UNIX_MAJOR_VERSION);
+       pSMB->ClientUnixMinor = cpu_to_le16(CIFS_UNIX_MINOR_VERSION);
+       pSMB->ClientUnixCap = cpu_to_le64(cap);
+       pSMB->hdr.smb_buf_length += byte_count;
+       pSMB->ByteCount = cpu_to_le16(byte_count);
+       rc = SendReceive(xid, tcon->ses, (struct smb_hdr *) pSMB,
+                        (struct smb_hdr *) pSMBr, &bytes_returned, 0);
+       if (rc) {
+               cERROR(1, ("Send error in SETFSUnixInfo = %d", rc));
+       } else {                /* decode response */
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+               if (rc) {
+                       rc = -EIO;      /* bad smb */
+               }
+       }
+       cifs_buf_release(pSMB);
+       if (rc == -EAGAIN)
+               goto SETFSUnixRetry;
+       return rc;
+ }
  
  int
  CIFSSMBQFSPosixInfo(const int xid, struct cifsTconInfo *tcon,
diff --combined fs/cifs/file.c
@@@ -196,7 -196,7 +196,7 @@@ int cifs_open(struct inode *inode, stru
        }
  
        down(&inode->i_sb->s_vfs_rename_sem);
-       full_path = build_path_from_dentry(file->f_dentry);
+       full_path = build_path_from_dentry(file->f_dentry, cifs_sb);
        up(&inode->i_sb->s_vfs_rename_sem);
        if (full_path == NULL) {
                FreeXid(xid);
@@@ -359,7 -359,7 +359,7 @@@ static int cifs_reopen_file(struct inod
     those that already have the rename sem can end up causing writepage
     to get called and if the server was down that means we end up here,
     and we can never tell if the caller already has the rename_sem */
-       full_path = build_path_from_dentry(file->f_dentry);
+       full_path = build_path_from_dentry(file->f_dentry, cifs_sb);
        if (full_path == NULL) {
                up(&pCifsFile->fh_sem);
                FreeXid(xid);
@@@ -791,8 -791,9 +791,8 @@@ static ssize_t cifs_write(struct file *
  
        pTcon = cifs_sb->tcon;
  
 -      /* cFYI(1,
 -         (" write %d bytes to offset %lld of %s", write_size,
 -         *poffset, file->f_dentry->d_name.name)); */
 +      cFYI(1,(" write %d bytes to offset %lld of %s", write_size,
 +         *poffset, file->f_dentry->d_name.name)); /* BB removeme BB */
  
        if (file->private_data == NULL)
                return -EBADF;
                                if (rc != 0)
                                        break;
                        }
 -
 +#ifdef CIFS_EXPERIMENTAL
 +                      /* BB FIXME We can not sign across two buffers yet */
 +                      cERROR(1,("checking signing")); /* BB removeme BB */
 +                      if(pTcon->ses->server->secMode & 
 +                         (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED) == 0)
 +                              rc = CIFSSMBWrite2(xid, pTcon,
 +                                              open_file->netfid,
 +                                              min_t(const int, cifs_sb->wsize,
 +                                                  write_size - total_written),
 +                                              *poffset, &bytes_written,
 +                                              write_data + total_written, 
 +                                              long_op);
 +                      } else
 +                      /* BB FIXME fixup indentation of line below */
 +#endif                        
                        rc = CIFSSMBWrite(xid, pTcon,
                                 open_file->netfid,
                                 min_t(const int, cifs_sb->wsize,