[PATCH] mutex subsystem, semaphore to mutex: VFS, ->i_sem
[pandora-kernel.git] / fs / cifs / inode.c
index ffc7305..3ebce94 100644 (file)
@@ -210,7 +210,7 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
        int oplock = FALSE;
        __u16 netfid;
        struct cifsTconInfo *pTcon = cifs_sb->tcon;
-       char buf[8];
+       char buf[24];
        unsigned int bytes_read;
        char * pbuf;
 
@@ -232,30 +232,43 @@ static int decode_sfu_inode(struct inode * inode, __u64 size,
                        /* Read header */
                rc = CIFSSMBRead(xid, pTcon,
                                 netfid,
-                                8 /* length */, 0 /* offset */,
+                                24 /* length */, 0 /* offset */,
                                 &bytes_read, &pbuf);
-               if((rc == 0) && (bytes_read == 8)) {
+               if((rc == 0) && (bytes_read >= 8)) {
                        if(memcmp("IntxBLK", pbuf, 8) == 0) {
                                cFYI(1,("Block device"));
                                inode->i_mode |= S_IFBLK;
+                               if(bytes_read == 24) {
+                                       /* we have enough to decode dev num */
+                                       __u64 mjr; /* major */
+                                       __u64 mnr; /* minor */
+                                       mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
+                                       mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
+                                       inode->i_rdev = MKDEV(mjr, mnr);
+                               }
                        } else if(memcmp("IntxCHR", pbuf, 8) == 0) {
                                cFYI(1,("Char device"));
                                inode->i_mode |= S_IFCHR;
+                               if(bytes_read == 24) {
+                                       /* we have enough to decode dev num */
+                                       __u64 mjr; /* major */
+                                       __u64 mnr; /* minor */
+                                       mjr = le64_to_cpu(*(__le64 *)(pbuf+8));
+                                       mnr = le64_to_cpu(*(__le64 *)(pbuf+16));
+                                       inode->i_rdev = MKDEV(mjr, mnr);
+                                }
                        } else if(memcmp("IntxLNK", pbuf, 7) == 0) {
                                cFYI(1,("Symlink"));
                                inode->i_mode |= S_IFLNK;
-                       } 
+                       } else {
+                               inode->i_mode |= S_IFREG; /* file? */
+                               rc = -EOPNOTSUPP; 
+                       }
                } else {
                        inode->i_mode |= S_IFREG; /* then it is a file */
                        rc = -EOPNOTSUPP; /* or some unknown SFU type */        
                }
-               
                CIFSSMBClose(xid, pTcon, netfid);
-       
-
-       /* inode->i_rdev = MKDEV(le64_to_cpu(DevMajor),
-                            le64_to_cpu(DevMinor) & MINORMASK);*/
-/*     inode->i_mode |= S_IFBLK; */
        }
        return rc;
        
@@ -279,6 +292,7 @@ static int get_sfu_uid_mode(struct inode * inode,
                return (int)rc;
        else if (rc > 3) {
                mode = le32_to_cpu(*((__le32 *)ea_value));
+               inode->i_mode &= ~SFBITS_MASK; 
                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));
@@ -696,7 +710,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
        char *full_path = NULL;
        struct inode *newinode = NULL;
 
-       cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p ", mode, inode));
+       cFYI(1, ("In cifs_mkdir, mode = 0x%x inode = 0x%p", mode, inode));
 
        xid = GetXid();
 
@@ -754,6 +768,17 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
                        /* BB to be implemented via Windows secrty descriptors
                           eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
                                                 -1, -1, local_nls); */
+                       if(direntry->d_inode) {
+                               direntry->d_inode->i_mode = mode;
+                               direntry->d_inode->i_mode |= S_IFDIR;
+                               if(cifs_sb->mnt_cifs_flags & 
+                                    CIFS_MOUNT_SET_UID) {
+                                       direntry->d_inode->i_uid = 
+                                               current->fsuid;
+                                       direntry->d_inode->i_gid = 
+                                               current->fsgid;
+                               }
+                       }
                }
        }
        kfree(full_path);
@@ -1015,9 +1040,9 @@ int cifs_revalidate(struct dentry *direntry)
        }
 
        /* can not grab this sem since kernel filesys locking documentation
-          indicates i_sem may be taken by the kernel on lookup and rename
-          which could deadlock if we grab the i_sem here as well */
-/*     down(&direntry->d_inode->i_sem);*/
+          indicates i_mutex may be taken by the kernel on lookup and rename
+          which could deadlock if we grab the i_mutex here as well */
+/*     mutex_lock(&direntry->d_inode->i_mutex);*/
        /* need to write out dirty pages here  */
        if (direntry->d_inode->i_mapping) {
                /* do we need to lock inode until after invalidate completes
@@ -1025,17 +1050,23 @@ int cifs_revalidate(struct dentry *direntry)
                filemap_fdatawrite(direntry->d_inode->i_mapping);
        }
        if (invalidate_inode) {
-               if (direntry->d_inode->i_mapping)
-                       filemap_fdatawait(direntry->d_inode->i_mapping);
-               /* may eventually have to do this for open files too */
-               if (list_empty(&(cifsInode->openFileList))) {
-                       /* Has changed on server - flush read ahead pages */
-                       cFYI(1, ("Invalidating read ahead data on "
-                                "closed file"));
-                       invalidate_remote_inode(direntry->d_inode);
+       /* shrink_dcache not necessary now that cifs dentry ops
+       are exported for negative dentries */
+/*             if(S_ISDIR(direntry->d_inode->i_mode)) 
+                       shrink_dcache_parent(direntry); */
+               if (S_ISREG(direntry->d_inode->i_mode)) {
+                       if (direntry->d_inode->i_mapping)
+                               filemap_fdatawait(direntry->d_inode->i_mapping);
+                       /* may eventually have to do this for open files too */
+                       if (list_empty(&(cifsInode->openFileList))) {
+                               /* changed on server - flush read ahead pages */
+                               cFYI(1, ("Invalidating read ahead data on "
+                                        "closed file"));
+                               invalidate_remote_inode(direntry->d_inode);
+                       }
                }
        }
-/*     up(&direntry->d_inode->i_sem); */
+/*     mutex_unlock(&direntry->d_inode->i_mutex); */
        
        kfree(full_path);
        FreeXid(xid);
@@ -1091,9 +1122,20 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
 
        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;
 
+       if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) == 0) {
+               /* check if we have permission to change attrs */
+               rc = inode_change_ok(direntry->d_inode, attrs);
+               if(rc < 0) {
+                       FreeXid(xid);
+                       return rc;
+               } else
+                       rc = 0;
+       }
+               
        down(&direntry->d_sb->s_vfs_rename_sem);
        full_path = build_path_from_dentry(direntry);
        up(&direntry->d_sb->s_vfs_rename_sem);
@@ -1106,8 +1148,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
        /* BB check if we need to refresh inode from server now ? BB */
 
        /* need to flush data before changing file size on server */
-       filemap_fdatawrite(direntry->d_inode->i_mapping);
-       filemap_fdatawait(direntry->d_inode->i_mapping);
+       filemap_write_and_wait(direntry->d_inode->i_mapping);
 
        if (attrs->ia_valid & ATTR_SIZE) {
                /* To avoid spurious oplock breaks from server, in the case of
@@ -1133,7 +1174,9 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
                                                  1 /* 45 seconds */);
                                cFYI(1,("Wrt seteof rc %d", rc));
                        }
-               }
+               } else 
+                       rc = -EINVAL;
+
                if (rc != 0) {
                        /* Set file size by pathname rather than by handle
                           either because no valid, writeable file handle for
@@ -1205,6 +1248,7 @@ int cifs_setattr(struct dentry *direntry, struct iattr *attrs)
                                         cifs_sb->mnt_cifs_flags & 
                                                CIFS_MOUNT_MAP_SPECIAL_CHR);
        else if (attrs->ia_valid & ATTR_MODE) {
+               rc = 0;
                if ((mode & S_IWUGO) == 0) /* not writeable */ {
                        if ((cifsInode->cifsAttrs & ATTR_READONLY) == 0)
                                time_buf.Attributes =