[CIFS] Fix scheduling while atomic when pending writes at file close time
authorSteve French <sfrench@us.ibm.com>
Fri, 18 Nov 2005 19:31:10 +0000 (11:31 -0800)
committerSteve French <sfrench@us.ibm.com>
Fri, 18 Nov 2005 19:31:10 +0000 (11:31 -0800)
Fix the case in which readdir reset file type when SFU mount option
specified.

Also fix sfu related functions to not request EAs (xattrs) when not
configured in Kconfig

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

index 93dd705577bcaf8359c46eddf04891934eae07be..ffc7305841b3c27173f8890a82ad5c9a5c5666c6 100644 (file)
@@ -41,7 +41,7 @@ int cifs_get_inode_info_unix(struct inode **pinode,
        char *tmp_path;
 
        pTcon = cifs_sb->tcon;
-       cFYI(1, (" Getting info on %s ", search_path));
+       cFYI(1, ("Getting info on %s ", search_path));
        /* could have done a find first instead but this returns more info */
        rc = CIFSSMBUnixQPathInfo(xid, pTcon, search_path, &findData,
                                  cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
@@ -111,6 +111,9 @@ int cifs_get_inode_info_unix(struct inode **pinode,
                inode->i_ctime =
                    cifs_NTtimeToUnix(le64_to_cpu(findData.LastStatusChange));
                inode->i_mode = le64_to_cpu(findData.Permissions);
+               /* since we set the inode type below we need to mask off
+                   to avoid strange results if bits set above */
+                        inode->i_mode &= ~S_IFMT;
                if (type == UNIX_FILE) {
                        inode->i_mode |= S_IFREG;
                } else if (type == UNIX_SYMLINK) {
@@ -129,6 +132,10 @@ int cifs_get_inode_info_unix(struct inode **pinode,
                        inode->i_mode |= S_IFIFO;
                } else if (type == UNIX_SOCKET) {
                        inode->i_mode |= S_IFSOCK;
+               } else {
+                       /* safest to call it a file if we do not know */
+                       inode->i_mode |= S_IFREG;
+                       cFYI(1,("unknown type %d",type));
                }
                inode->i_uid = le64_to_cpu(findData.Uid);
                inode->i_gid = le64_to_cpu(findData.Gid);
@@ -228,20 +235,19 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
                                 8 /* length */, 0 /* offset */,
                                 &bytes_read, &pbuf);
                if((rc == 0) && (bytes_read == 8)) {
-                       cERROR(1,("intx %s" ,pbuf));
                        if(memcmp("IntxBLK", pbuf, 8) == 0) {
                                cFYI(1,("Block device"));
-                               inode->i_mode = S_IFBLK;
+                               inode->i_mode |= S_IFBLK;
                        } else if(memcmp("IntxCHR", pbuf, 8) == 0) {
                                cFYI(1,("Char device"));
-                               inode->i_mode = S_IFCHR;
+                               inode->i_mode |= S_IFCHR;
                        } else if(memcmp("IntxLNK", pbuf, 7) == 0) {
                                cFYI(1,("Symlink"));
-                               inode->i_mode = S_IFLNK;
-                       } else
-                               inode->i_mode = S_IFREG; /* then it is a file */
-                               rc = -EOPNOTSUPP; /* or some unknown SFU type */ 
-                        
+                               inode->i_mode |= S_IFLNK;
+                       } 
+               } else {
+                       inode->i_mode |= S_IFREG; /* then it is a file */
+                       rc = -EOPNOTSUPP; /* or some unknown SFU type */        
                }
                
                CIFSSMBClose(xid, pTcon, netfid);
@@ -261,6 +267,7 @@ static int get_sfu_uid_mode(struct inode * inode,
                        const unsigned char *path,
                        struct cifs_sb_info *cifs_sb, int xid)
 {
+#ifdef CONFIG_CIFS_XATTR
        ssize_t rc;
        char ea_value[4];
        __u32 mode;
@@ -272,12 +279,17 @@ static int get_sfu_uid_mode(struct inode * inode,
                return (int)rc;
        else if (rc > 3) {
                mode = le32_to_cpu(*((__le32 *)ea_value));
+               cFYI(1,("special bits 0%o org mode 0%o", mode, inode->i_mode));
                inode->i_mode = (mode &  SFBITS_MASK) | inode->i_mode;
                cFYI(1,("special mode bits 0%o", mode));
                return 0;
        } else {
                return 0;
        }
+#else
+       return -EOPNOTSUPP;
+#endif
+
                
 }
 
@@ -394,9 +406,9 @@ int cifs_get_inode_info(struct inode **pinode,
                inode = *pinode;
                cifsInfo = CIFS_I(inode);
                cifsInfo->cifsAttrs = attr;
-               cFYI(1, (" Old time %ld ", cifsInfo->time));
+               cFYI(1, ("Old time %ld ", cifsInfo->time));
                cifsInfo->time = jiffies;
-               cFYI(1, (" New time %ld ", cifsInfo->time));
+               cFYI(1, ("New time %ld ", cifsInfo->time));
 
                /* blksize needs to be multiple of two. So safer to default to
                blksize and blkbits set in superblock so 2**blkbits and blksize
@@ -410,13 +422,15 @@ int cifs_get_inode_info(struct inode **pinode,
                    cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastWriteTime));
                inode->i_ctime =
                    cifs_NTtimeToUnix(le64_to_cpu(pfindData->ChangeTime));
-               cFYI(0, (" Attributes came in as 0x%x ", attr));
+               cFYI(0, ("Attributes came in as 0x%x ", attr));
 
                /* set default mode. will override for dirs below */
                if (atomic_read(&cifsInfo->inUse) == 0)
                        /* new inode, can safely set these fields */
                        inode->i_mode = cifs_sb->mnt_file_mode;
-
+               else /* since we set the inode type below we need to mask off
+                    to avoid strange results if type changes and both get orred in */ 
+                       inode->i_mode &= ~S_IFMT; 
 /*             if (attr & ATTR_REPARSE)  */
                /* We no longer handle these as symlinks because we could not
                   follow them due to the absolute path with drive letter */
@@ -440,6 +454,7 @@ int cifs_get_inode_info(struct inode **pinode,
                                         cifs_sb, xid)) {
                                cFYI(1,("Unrecognized sfu inode type"));
                        }
+                       cFYI(1,("sfu mode 0%o",inode->i_mode));
                } else {
                        inode->i_mode |= S_IFREG;
                        /* treat the dos attribute of read-only as read-only
@@ -535,7 +550,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
        struct cifsInodeInfo *cifsInode;
        FILE_BASIC_INFO *pinfo_buf;
 
-       cFYI(1, (" cifs_unlink, inode = 0x%p with ", inode));
+       cFYI(1, ("cifs_unlink, inode = 0x%p with ", inode));
 
        xid = GetXid();
 
@@ -755,7 +770,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
        char *full_path = NULL;
        struct cifsInodeInfo *cifsInode;
 
-       cFYI(1, (" cifs_rmdir, inode = 0x%p with ", inode));
+       cFYI(1, ("cifs_rmdir, inode = 0x%p with ", inode));
 
        xid = GetXid();
 
@@ -1074,7 +1089,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
 
        xid = GetXid();
 
-       cFYI(1, (" In cifs_setattr, name = %s attrs->iavalid 0x%x ",
+       cFYI(1, ("In cifs_setattr, name = %s attrs->iavalid 0x%x ",
                 direntry->d_name.name, attrs->ia_valid));
        cifs_sb = CIFS_SB(direntry->d_inode->i_sb);
        pTcon = cifs_sb->tcon;
index 9b7e0ff9584b35c78f9c82a87ea49d8f110d52ad..9bdaaecae36f683ef52196b4d54cee256b006029 100644 (file)
@@ -142,6 +142,11 @@ static void fill_in_inode(struct inode *tmp_inode,
                tmp_inode->i_gid = cifs_sb->mnt_gid;
                /* set default mode. will override for dirs below */
                tmp_inode->i_mode = cifs_sb->mnt_file_mode;
+       } else {
+               /* mask off the type bits since it gets set
+               below and we do not want to get two type
+               bits set */
+               tmp_inode->i_mode &= ~S_IFMT;
        }
 
        if (attr & ATTR_DIRECTORY) {
@@ -152,12 +157,18 @@ static void fill_in_inode(struct inode *tmp_inode,
                }
                tmp_inode->i_mode |= S_IFDIR;
        } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) && 
-                  (attr & ATTR_SYSTEM) && (end_of_file == 0)) {
-               *pobject_type = DT_FIFO;
-               tmp_inode->i_mode |= S_IFIFO;
-/* BB Finish for SFU style symlinks and devies */
-/*     } else if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) &&
-               (attr & ATTR_SYSTEM) && ) { */
+                  (attr & ATTR_SYSTEM)) {
+               if (end_of_file == 0)  {
+                       *pobject_type = DT_FIFO;
+                       tmp_inode->i_mode |= S_IFIFO;
+               } else {
+                       /* rather than get the type here, we mark the
+                       inode as needing revalidate and get the real type
+                       (blk vs chr vs. symlink) later ie in lookup */
+                       *pobject_type = DT_REG;
+                       tmp_inode->i_mode |= S_IFREG; 
+                       cifsInfo->time = 0;     
+               }
 /* we no longer mark these because we could not follow them */
 /*        } else if (attr & ATTR_REPARSE) {
                 *pobject_type = DT_LNK;
@@ -264,6 +275,9 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
            cifs_NTtimeToUnix(le64_to_cpu(pfindData->LastStatusChange));
 
        tmp_inode->i_mode = le64_to_cpu(pfindData->Permissions);
+       /* since we set the inode type below we need to mask off type
+           to avoid strange results if bits above were corrupt */
+        tmp_inode->i_mode &= ~S_IFMT;
        if (type == UNIX_FILE) {
                *pobject_type = DT_REG;
                tmp_inode->i_mode |= S_IFREG;
@@ -289,6 +303,11 @@ static void unix_fill_in_inode(struct inode *tmp_inode,
        } else if (type == UNIX_SOCKET) {
                *pobject_type = DT_SOCK;
                tmp_inode->i_mode |= S_IFSOCK;
+       } else {
+               /* safest to just call it a file */
+               *pobject_type = DT_REG;
+               tmp_inode->i_mode |= S_IFREG;
+               cFYI(1,("unknown inode type %d",type)); 
        }
 
        tmp_inode->i_uid = le64_to_cpu(pfindData->Uid);