ChangeSet 1.2202, 2005/03/28 22:50:11-06:00, [EMAIL PROTECTED](none)

        [CIFS] Return inode numbers (from server) more consistently on lookup 
and readdir to both types of servers 
        (whether they support Unix extensions or not) when serverino mount parm 
specified.
        
        Signed-off-by: Steve French ([EMAIL PROTECTED])



 CHANGES   |    8 +++++-
 cifssmb.c |   75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 inode.c   |   35 ++++++++++++++++++++--------
 readdir.c |   10 ++++----
 4 files changed, 107 insertions(+), 21 deletions(-)


diff -Nru a/fs/cifs/CHANGES b/fs/cifs/CHANGES
--- a/fs/cifs/CHANGES   2005-03-30 12:11:04 -08:00
+++ b/fs/cifs/CHANGES   2005-03-30 12:11:04 -08:00
@@ -5,7 +5,13 @@
 Fix updates of DOS attributes and time fields so that files on NT4 servers
 do not get marked delete on close. Display sizes of cifs buffer pools in
 cifs stats. Fix oops in unmount when cifsd thread being killed by 
-shutdown. Add generic readv/writev and aio support.
+shutdown. Add generic readv/writev and aio support. Report inode numbers 
+consistently in readdir and lookup (when serverino mount option is
+specified use the inode number that the server reports - for both lookup
+and readdir, otherwise by default the locally generated inode number is used
+for inodes created in either path since servers are not always able to 
+provide unique inode numbers when exporting multiple volumes from under one
+sharename).
 
 Version 1.30
 ------------
diff -Nru a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
--- a/fs/cifs/cifssmb.c 2005-03-30 12:11:04 -08:00
+++ b/fs/cifs/cifssmb.c 2005-03-30 12:11:04 -08:00
@@ -2613,23 +2613,86 @@
        int rc = 0;
        TRANSACTION2_QPI_REQ *pSMB = NULL;
        TRANSACTION2_QPI_RSP *pSMBr = NULL;
+       int name_len, bytes_returned;
+       __u16 params, byte_count;
 
-       cFYI(1,("In GetSrvInodeNumber for %s",searchName));
+       cFYI(1,("In GetSrvInodeNum for %s",searchName));
        if(tcon == NULL)
                return -ENODEV; 
 
-        cFYI(1, ("In QPathInfo path %s", searchName));
 GetInodeNumberRetry:
        rc = smb_init(SMB_COM_TRANSACTION2, 15, tcon, (void **) &pSMB,
                       (void **) &pSMBr);
        if (rc)
                return rc;
 
-/* BB add missing code here */
 
-       if (pSMB)
-               cifs_buf_release(pSMB);
-                                                                               
                                          
+       if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
+               name_len =
+                       cifs_strtoUCS((wchar_t *) pSMB->FileName, searchName, 
+                               PATH_MAX,nls_codepage);
+               name_len++;     /* trailing null */
+               name_len *= 2;
+       } else {                /* BB improve the check for buffer overruns BB 
*/
+               name_len = strnlen(searchName, PATH_MAX);
+               name_len++;     /* trailing null */
+               strncpy(pSMB->FileName, searchName, name_len);
+       }
+
+       params = 2 /* level */  + 4 /* rsrvd */  + name_len /* incl null */ ;
+       pSMB->TotalDataCount = 0;
+       pSMB->MaxParameterCount = cpu_to_le16(2);
+       /* BB find exact max data count below from sess structure BB */
+       pSMB->MaxDataCount = cpu_to_le16(4000);
+       pSMB->MaxSetupCount = 0;
+       pSMB->Reserved = 0;
+       pSMB->Flags = 0;
+       pSMB->Timeout = 0;
+       pSMB->Reserved2 = 0;
+       pSMB->ParameterOffset = cpu_to_le16(offsetof(
+               struct smb_com_transaction2_qpi_req ,InformationLevel) - 4);
+       pSMB->DataCount = 0;
+       pSMB->DataOffset = 0;
+       pSMB->SetupCount = 1;
+       pSMB->Reserved3 = 0;
+       pSMB->SubCommand = cpu_to_le16(TRANS2_QUERY_PATH_INFORMATION);
+       byte_count = params + 1 /* pad */ ;
+       pSMB->TotalParameterCount = cpu_to_le16(params);
+       pSMB->ParameterCount = pSMB->TotalParameterCount;
+       pSMB->InformationLevel = cpu_to_le16(SMB_QUERY_FILE_INTERNAL_INFO);
+       pSMB->Reserved4 = 0;
+       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) {
+               cFYI(1, ("error %d in QueryInternalInfo", rc));
+       } else {
+               /* decode response */
+               rc = validate_t2((struct smb_t2_rsp *)pSMBr);
+               if (rc || (pSMBr->ByteCount < 2))
+               /* BB also check enough total bytes returned */
+                       /* If rc should we check for EOPNOSUPP and
+                       disable the srvino flag? or in caller? */
+                       rc = -EIO;      /* bad smb */
+                else {
+                       __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
+                       __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+                       struct file_internal_info * pfinfo;
+                       /* BB Do we need a cast or hash here ? */
+                       if(count < 8) {
+                               cFYI(1, ("Illegal size ret in QryIntrnlInf"));
+                               rc = -EIO;
+                               goto GetInodeNumOut;
+                       }
+                       pfinfo = (struct file_internal_info *)
+                               (data_offset + (char *) &pSMBr->hdr.Protocol);
+                       *inode_number = pfinfo->UniqueId;
+               }
+       }
+GetInodeNumOut:
+       cifs_buf_release(pSMB);
        if (rc == -EAGAIN)
                goto GetInodeNumberRetry;
        return rc;
diff -Nru a/fs/cifs/inode.c b/fs/cifs/inode.c
--- a/fs/cifs/inode.c   2005-03-30 12:11:04 -08:00
+++ b/fs/cifs/inode.c   2005-03-30 12:11:04 -08:00
@@ -246,21 +246,36 @@
                        *pinode = new_inode(sb);
                        if (*pinode == NULL)
                                return -ENOMEM;
-                       /* Is an i_ino of zero legal? */
-                       /* Are there sanity checks we can use to ensure that
+                       /* Is an i_ino of zero legal? Can we use that to check
+                          if the server supports returning inode numbers?  Are
+                          there other sanity checks we can use to ensure that
                           the server is really filling in that field? */
 
-                       /* We can not use the IndexNumber from either Windows
-                          or Samba as it is frequently set to zero */
+                       /* We can not use the IndexNumber field by default from
+                          Windows or Samba (in ALL_INFO buf) but we can request
+                          it explicitly.  It may not be unique presumably if
+                          the server has multiple devices mounted under one
+                          share */
+
                        /* There may be higher info levels that work but are
                           there Windows server or network appliances for which
                           IndexNumber field is not guaranteed unique? */
-               
-                       /* if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
-                               (*pinode)->i_ino = 
-                                       (unsigned long)pfindData->IndexNumber;
-                       } */ /*NB: ino incremented to unique num in new_inode*/
 
+#ifdef CONFIG_CIFS_EXPERIMENTAL                
+                       if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM){
+                               int rc1 = 0;
+                               __u64 inode_num;
+
+                               rc1 = CIFSGetSrvInodeNumber(xid, pTcon, 
+                                       search_path, &inode_num, 
+                                       cifs_sb->local_nls);
+                               if(rc1) {
+                                       cFYI(1,("GetSrvInodeNum rc %d", rc1));
+                                       /* BB EOPNOSUPP disable SERVER_INUM? */
+                               } else /* do we need cast or hash to ino? */
+                                       (*pinode)->i_ino = inode_num;
+                       } /* else ino incremented to unique num in new_inode*/
+#endif /* CIFS_EXPERIMENTAL */
                        insert_inode_hash(*pinode);
                }
                inode = *pinode;
@@ -677,7 +692,7 @@
        }
 
        if (rc) {
-               cFYI(1, ("rename rc %d", rc)); /* BB removeme BB */
+               cFYI(1, ("rename rc %d", rc));
        }
 
        if ((rc == -EIO) || (rc == -EEXIST)) {
diff -Nru a/fs/cifs/readdir.c b/fs/cifs/readdir.c
--- a/fs/cifs/readdir.c 2005-03-30 12:11:04 -08:00
+++ b/fs/cifs/readdir.c 2005-03-30 12:11:04 -08:00
@@ -325,7 +325,7 @@
 
        /* test for Unix extensions */
        if (pTcon->ses->capabilities & CAP_UNIX) {
-               cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX;
+               cifsFile->srch_inf.info_level = SMB_FIND_FILE_UNIX; 
        } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
                cifsFile->srch_inf.info_level = SMB_FIND_FILE_ID_FULL_DIR_INFO;
        } else /* not srvinos - BB fixme add check for backlevel? */ {
@@ -543,11 +543,12 @@
 /* inode num, inode type and filename returned */
 static int cifs_get_name_from_search_buf(struct qstr *pqst,
        char *current_entry, __u16 level, unsigned int unicode,
-       struct nls_table *nlt, ino_t *pinum)
+       struct cifs_sb_info * cifs_sb, ino_t *pinum)
 {
        int rc = 0;
        unsigned int len = 0;
        char * filename;
+       struct nls_table * nlt = cifs_sb->local_nls;
 
        *pinum = 0;
 
@@ -563,7 +564,8 @@
                }
 
                /* BB fixme - hash low and high 32 bits if not 64 bit arch BB 
fixme */
-               *pinum = pFindData->UniqueId;
+               if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
+                       *pinum = pFindData->UniqueId;
        } else if(level == SMB_FIND_FILE_DIRECTORY_INFO) {
                FILE_DIRECTORY_INFO * pFindData = 
                        (FILE_DIRECTORY_INFO *)current_entry;
@@ -633,7 +635,7 @@
        qstring.name = scratch_buf;
        rc = cifs_get_name_from_search_buf(&qstring,pfindEntry,
                        pCifsF->srch_inf.info_level,
-                       pCifsF->srch_inf.unicode,cifs_sb->local_nls,
+                       pCifsF->srch_inf.unicode,cifs_sb,
                        &inum /* returned */);
 
        if(rc)
-
To unsubscribe from this list: send the line "unsubscribe bk-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to