Merge git://github.com/rustyrussell/linux
[pandora-kernel.git] / fs / cifs / inode.c
index a7b2dcd..e851d5b 100644 (file)
@@ -132,7 +132,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
        inode->i_mtime = fattr->cf_mtime;
        inode->i_ctime = fattr->cf_ctime;
        inode->i_rdev = fattr->cf_rdev;
-       inode->i_nlink = fattr->cf_nlink;
+       set_nlink(inode, fattr->cf_nlink);
        inode->i_uid = fattr->cf_uid;
        inode->i_gid = fattr->cf_gid;
 
@@ -562,7 +562,16 @@ int cifs_get_file_info(struct file *filp)
 
        xid = GetXid();
        rc = CIFSSMBQFileInfo(xid, tcon, cfile->netfid, &find_data);
-       if (rc == -EOPNOTSUPP || rc == -EINVAL) {
+       switch (rc) {
+       case 0:
+               cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false);
+               break;
+       case -EREMOTE:
+               cifs_create_dfs_fattr(&fattr, inode->i_sb);
+               rc = 0;
+               break;
+       case -EOPNOTSUPP:
+       case -EINVAL:
                /*
                 * FIXME: legacy server -- fall back to path-based call?
                 * for now, just skip revalidating and mark inode for
@@ -570,18 +579,14 @@ int cifs_get_file_info(struct file *filp)
                 */
                rc = 0;
                CIFS_I(inode)->time = 0;
+       default:
                goto cgfi_exit;
-       } else if (rc == -EREMOTE) {
-               cifs_create_dfs_fattr(&fattr, inode->i_sb);
-               rc = 0;
-       } else if (rc)
-               goto cgfi_exit;
+       }
 
        /*
         * don't bother with SFU junk here -- just mark inode as needing
         * revalidation.
         */
-       cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false);
        fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
        fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
        cifs_fattr_to_inode(inode, &fattr);
@@ -900,7 +905,7 @@ struct inode *cifs_root_iget(struct super_block *sb)
        if (rc && tcon->ipc) {
                cFYI(1, "ipc connection - fake read inode");
                inode->i_mode |= S_IFDIR;
-               inode->i_nlink = 2;
+               set_nlink(inode, 2);
                inode->i_op = &cifs_ipc_inode_ops;
                inode->i_fop = &simple_dir_operations;
                inode->i_uid = cifs_sb->mnt_uid;
@@ -1362,7 +1367,7 @@ mkdir_get_info:
                 /* setting nlink not necessary except in cases where we
                  * failed to get it from the server or was set bogus */
                if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
-                               direntry->d_inode->i_nlink = 2;
+                       set_nlink(direntry->d_inode, 2);
 
                mode &= ~current_umask();
                /* must turn on setgid bit if parent dir has it */
@@ -2096,6 +2101,8 @@ static int
 cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
 {
        int xid;
+       uid_t uid = NO_CHANGE_32;
+       gid_t gid = NO_CHANGE_32;
        struct inode *inode = direntry->d_inode;
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct cifsInodeInfo *cifsInode = CIFS_I(inode);
@@ -2146,13 +2153,25 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
                        goto cifs_setattr_exit;
        }
 
-       /*
-        * Without unix extensions we can't send ownership changes to the
-        * server, so silently ignore them. This is consistent with how
-        * local DOS/Windows filesystems behave (VFAT, NTFS, etc). With
-        * CIFSACL support + proper Windows to Unix idmapping, we may be
-        * able to support this in the future.
-        */
+       if (attrs->ia_valid & ATTR_UID)
+               uid = attrs->ia_uid;
+
+       if (attrs->ia_valid & ATTR_GID)
+               gid = attrs->ia_gid;
+
+#ifdef CONFIG_CIFS_ACL
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
+               if (uid != NO_CHANGE_32 || gid != NO_CHANGE_32) {
+                       rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64,
+                                                       uid, gid);
+                       if (rc) {
+                               cFYI(1, "%s: Setting id failed with error: %d",
+                                       __func__, rc);
+                               goto cifs_setattr_exit;
+                       }
+               }
+       } else
+#endif /* CONFIG_CIFS_ACL */
        if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID))
                attrs->ia_valid &= ~(ATTR_UID | ATTR_GID);
 
@@ -2161,15 +2180,12 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
                attrs->ia_valid &= ~ATTR_MODE;
 
        if (attrs->ia_valid & ATTR_MODE) {
-               cFYI(1, "Mode changed to 0%o", attrs->ia_mode);
                mode = attrs->ia_mode;
-       }
-
-       if (attrs->ia_valid & ATTR_MODE) {
                rc = 0;
 #ifdef CONFIG_CIFS_ACL
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
-                       rc = mode_to_cifs_acl(inode, full_path, mode);
+                       rc = id_mode_to_cifs_acl(inode, full_path, mode,
+                                               NO_CHANGE_32, NO_CHANGE_32);
                        if (rc) {
                                cFYI(1, "%s: Setting ACL failed with error: %d",
                                        __func__, rc);