]> err.no Git - linux-2.6/blobdiff - fs/cifs/cifssmb.c
[PATCH] exportfs: add find_acceptable_alias helper
[linux-2.6] / fs / cifs / cifssmb.c
index 365949c1464691bd32d2d10207073cd0d642c1f8..6867e556d37e51485a4e9d35fb7ea332fc971b6d 100644 (file)
@@ -90,6 +90,18 @@ small_smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
           check for tcp and smb session status done differently
           for those three - in the calling routine */
        if(tcon) {
+               if(tcon->tidStatus == CifsExiting) {
+                       /* only tree disconnect, open, and write,
+                       (and ulogoff which does not have tcon)
+                       are allowed as we start force umount */
+                       if((smb_command != SMB_COM_WRITE_ANDX) && 
+                          (smb_command != SMB_COM_OPEN_ANDX) && 
+                          (smb_command != SMB_COM_TREE_DISCONNECT)) {
+                               cFYI(1,("can not send cmd %d while umounting",
+                                       smb_command));
+                               return -ENODEV;
+                       }
+               }
                if((tcon->ses) && (tcon->ses->status != CifsExiting) &&
                                  (tcon->ses->server)){
                        struct nls_table *nls_codepage;
@@ -187,6 +199,19 @@ smb_init(int smb_command, int wct, struct cifsTconInfo *tcon,
           check for tcp and smb session status done differently
           for those three - in the calling routine */
        if(tcon) {
+               if(tcon->tidStatus == CifsExiting) {
+                       /* only tree disconnect, open, and write,
+                         (and ulogoff which does not have tcon)
+                         are allowed as we start force umount */
+                       if((smb_command != SMB_COM_WRITE_ANDX) &&
+                          (smb_command != SMB_COM_OPEN_ANDX) &&
+                          (smb_command != SMB_COM_TREE_DISCONNECT)) {
+                               cFYI(1,("can not send cmd %d while umounting",
+                                       smb_command));
+                               return -ENODEV;
+                       }
+               }
+
                if((tcon->ses) && (tcon->ses->status != CifsExiting) && 
                                  (tcon->ses->server)){
                        struct nls_table *nls_codepage;
@@ -1139,11 +1164,17 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
 {
        int rc = -EACCES;
        WRITE_REQ *pSMB = NULL;
-       int bytes_returned;
+       int bytes_returned, wct;
        int smb_hdr_len;
 
-       cFYI(1,("write2 at %lld %d bytes",offset,count)); /* BB removeme BB */
-       rc = small_smb_init(SMB_COM_WRITE_ANDX, 14, tcon, (void **) &pSMB);
+       /* BB removeme BB */
+       cFYI(1,("write2 at %lld %d bytes", (long long)offset, count));
+
+       if(tcon->ses->capabilities & CAP_LARGE_FILES)
+               wct = 14;
+       else
+               wct = 12;
+       rc = small_smb_init(SMB_COM_WRITE_ANDX, wct, tcon, (void **) &pSMB);
        if (rc)
                return rc;
        /* tcon and ses pointer are checked in smb_init */
@@ -1153,7 +1184,10 @@ CIFSSMBWrite2(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;
@@ -1164,9 +1198,17 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
        pSMB->DataLengthLow = cpu_to_le16(count & 0xFFFF);
        pSMB->DataLengthHigh = cpu_to_le16(count >> 16);
        smb_hdr_len = pSMB->hdr.smb_buf_length + 1; /* hdr + 1 byte pad */
-       pSMB->hdr.smb_buf_length += count+1;
-       pSMB->ByteCount = cpu_to_le16(count + 1);
-
+       if(wct == 14)
+               pSMB->hdr.smb_buf_length += count+1;
+       else /* wct == 12 */
+               pSMB->hdr.smb_buf_length += count+5; /* smb data starts later */ 
+       if(wct == 14)
+               pSMB->ByteCount = cpu_to_le16(count + 1);
+       else /* wct == 12 */ /* bigger pad, smaller smb hdr, keep offset ok */ {
+               struct smb_com_writex_req * pSMBW =
+                               (struct smb_com_writex_req *)pSMB;
+               pSMBW->ByteCount = cpu_to_le16(count + 5);
+       }
        iov[0].iov_base = pSMB;
        iov[0].iov_len = smb_hdr_len + 4;
 
@@ -1174,7 +1216,7 @@ CIFSSMBWrite2(const int xid, struct cifsTconInfo *tcon,
                          long_op);
        cifs_stats_inc(&tcon->num_writes);
        if (rc) {
-               cFYI(1, ("Send error in write = %d", rc));
+               cFYI(1, ("Send error Write2 = %d", rc));
                *nbytes = 0;
        } else {
                WRITE_RSP * pSMBr = (WRITE_RSP *)pSMB;
@@ -1538,7 +1580,7 @@ createSymLinkRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, fromName, PATH_MAX
+                   cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
@@ -1562,7 +1604,7 @@ createSymLinkRetry:
        data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len_target =
-                   cifs_strtoUCS((wchar_t *) data_offset, toName, PATH_MAX
+                   cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len_target++;      /* trailing null */
@@ -1788,7 +1830,7 @@ querySymLinkRetry:
 
        if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
                name_len =
-                   cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
+                   cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
                                  /* find define for this maxpathcomponent */
                                  , nls_codepage);
                name_len++;     /* trailing null */
@@ -1845,7 +1887,7 @@ querySymLinkRetry:
                                        min_t(const int, buflen,count) / 2);
                        /* BB FIXME investigate remapping reserved chars here */
                                cifs_strfromUCS_le(symlinkinfo,
-                                       (wchar_t *) ((char *)&pSMBr->hdr.Protocol +
+                                       (__le16 *) ((char *)&pSMBr->hdr.Protocol +
                                                data_offset),
                                        name_len, nls_codepage);
                        } else {
@@ -1936,7 +1978,7 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
                                                        reparse_buf->TargetNameOffset),
                                                        min(buflen/2, reparse_buf->TargetNameLen / 2)); 
                                        cifs_strfromUCS_le(symlinkinfo,
-                                               (wchar_t *) (reparse_buf->LinkNamesBuf + 
+                                               (__le16 *) (reparse_buf->LinkNamesBuf + 
                                                reparse_buf->TargetNameOffset),
                                                name_len, nls_codepage);
                                } else { /* ASCII names */
@@ -1968,9 +2010,9 @@ qreparse_out:
 static void cifs_convert_ace(posix_acl_xattr_entry * ace, struct cifs_posix_ace * cifs_ace)
 {
        /* u8 cifs fields do not need le conversion */
-       ace->e_perm = (__u16)cifs_ace->cifs_e_perm; 
-       ace->e_tag  = (__u16)cifs_ace->cifs_e_tag;
-       ace->e_id   = (__u32)le64_to_cpu(cifs_ace->cifs_uid);
+       ace->e_perm = cpu_to_le16(cifs_ace->cifs_e_perm);
+       ace->e_tag  = cpu_to_le16(cifs_ace->cifs_e_tag);
+       ace->e_id   = cpu_to_le32(le64_to_cpu(cifs_ace->cifs_uid));
        /* cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id)); */
 
        return;
@@ -2022,7 +2064,7 @@ static int cifs_copy_posix_acl(char * trgt,char * src, const int buflen,
        } else if(size > buflen) {
                return -ERANGE;
        } else /* buffer big enough */ {
-               local_acl->a_version = POSIX_ACL_XATTR_VERSION;
+               local_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION);
                for(i = 0;i < count ;i++) {
                        cifs_convert_ace(&local_acl->a_entries[i],pACE);
                        pACE ++;
@@ -2036,14 +2078,14 @@ static __u16 convert_ace_to_cifs_ace(struct cifs_posix_ace * cifs_ace,
 {
        __u16 rc = 0; /* 0 = ACL converted ok */
 
-       cifs_ace->cifs_e_perm = (__u8)cpu_to_le16(local_ace->e_perm);
-       cifs_ace->cifs_e_tag =  (__u8)cpu_to_le16(local_ace->e_tag);
+       cifs_ace->cifs_e_perm = le16_to_cpu(local_ace->e_perm);
+       cifs_ace->cifs_e_tag =  le16_to_cpu(local_ace->e_tag);
        /* BB is there a better way to handle the large uid? */
-       if(local_ace->e_id == -1) {
+       if(local_ace->e_id == cpu_to_le32(-1)) {
        /* Probably no need to le convert -1 on any arch but can not hurt */
                cifs_ace->cifs_uid = cpu_to_le64(-1);
        } else 
-               cifs_ace->cifs_uid = (__u64)cpu_to_le32(local_ace->e_id);
+               cifs_ace->cifs_uid = cpu_to_le64(le32_to_cpu(local_ace->e_id));
         /*cFYI(1,("perm %d tag %d id %d",ace->e_perm,ace->e_tag,ace->e_id));*/
        return rc;
 }
@@ -2063,16 +2105,17 @@ static __u16 ACL_to_cifs_posix(char * parm_data,const char * pACL,const int bufl
 
        count = posix_acl_xattr_count((size_t)buflen);
        cFYI(1,("setting acl with %d entries from buf of length %d and version of %d",
-               count,buflen,local_acl->a_version));
-       if(local_acl->a_version != 2) {
-               cFYI(1,("unknown POSIX ACL version %d",local_acl->a_version));
+               count, buflen, le32_to_cpu(local_acl->a_version)));
+       if(le32_to_cpu(local_acl->a_version) != 2) {
+               cFYI(1,("unknown POSIX ACL version %d",
+                    le32_to_cpu(local_acl->a_version)));
                return 0;
        }
        cifs_acl->version = cpu_to_le16(1);
        if(acl_type == ACL_TYPE_ACCESS) 
-               cifs_acl->access_entry_count = count;
+               cifs_acl->access_entry_count = cpu_to_le16(count);
        else if(acl_type == ACL_TYPE_DEFAULT)
-               cifs_acl->default_entry_count = count;
+               cifs_acl->default_entry_count = cpu_to_le16(count);
        else {
                cFYI(1,("unknown ACL type %d",acl_type));
                return 0;
@@ -2944,7 +2987,6 @@ CIFSFindClose(const int xid, struct cifsTconInfo *tcon, const __u16 searchHandle
        return rc;
 }
 
-#ifdef CONFIG_CIFS_EXPERIMENTAL
 int
 CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
                 const unsigned char *searchName,
@@ -3038,7 +3080,6 @@ GetInodeNumOut:
                goto GetInodeNumberRetry;
        return rc;
 }
-#endif /* CIFS_EXPERIMENTAL */
 
 int
 CIFSGetDFSRefer(const int xid, struct cifsSesInfo *ses,
@@ -3190,7 +3231,7 @@ getDFSRetry:
                                temp = ((char *)referrals) + le16_to_cpu(referrals->DfsPathOffset);
                                if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
                                        cifs_strfromUCS_le(*targetUNCs,
-                                               (wchar_t *) temp, name_len, nls_codepage);
+                                               (__le16 *) temp, name_len, nls_codepage);
                                } else {
                                        strncpy(*targetUNCs,temp,name_len);
                                }
@@ -4279,20 +4320,26 @@ int CIFSSMBNotify(const int xid, struct cifsTconInfo *tcon,
                cFYI(1, ("Error in Notify = %d", rc));
        } else {
                /* Add file to outstanding requests */
+               /* BB change to kmem cache alloc */     
                dnotify_req = (struct dir_notify_req *) kmalloc(
-                                               sizeof(struct dir_notify_req), GFP_KERNEL);
-               dnotify_req->Pid = pSMB->hdr.Pid;
-               dnotify_req->PidHigh = pSMB->hdr.PidHigh;
-               dnotify_req->Mid = pSMB->hdr.Mid;
-               dnotify_req->Tid = pSMB->hdr.Tid;
-               dnotify_req->Uid = pSMB->hdr.Uid;
-               dnotify_req->netfid = netfid;
-               dnotify_req->pfile = pfile;
-               dnotify_req->filter = filter;
-               dnotify_req->multishot = multishot;
-               spin_lock(&GlobalMid_Lock);
-               list_add_tail(&dnotify_req->lhead, &GlobalDnotifyReqList);
-               spin_unlock(&GlobalMid_Lock);
+                                               sizeof(struct dir_notify_req),
+                                                GFP_KERNEL);
+               if(dnotify_req) {
+                       dnotify_req->Pid = pSMB->hdr.Pid;
+                       dnotify_req->PidHigh = pSMB->hdr.PidHigh;
+                       dnotify_req->Mid = pSMB->hdr.Mid;
+                       dnotify_req->Tid = pSMB->hdr.Tid;
+                       dnotify_req->Uid = pSMB->hdr.Uid;
+                       dnotify_req->netfid = netfid;
+                       dnotify_req->pfile = pfile;
+                       dnotify_req->filter = filter;
+                       dnotify_req->multishot = multishot;
+                       spin_lock(&GlobalMid_Lock);
+                       list_add_tail(&dnotify_req->lhead, 
+                                       &GlobalDnotifyReqList);
+                       spin_unlock(&GlobalMid_Lock);
+               } else 
+                       rc = -ENOMEM;
        }
        cifs_buf_release(pSMB);
        return rc;