]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - fs/xfs/xfs_vnodeops.c
Merge branch 'tracing-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-omap-h63xx.git] / fs / xfs / xfs_vnodeops.c
index 4547608b46c47b678013bb135ff368730f8b39ed..0e55c5d7db5fd2bbcc13e88baa38a915c2db94b7 100644 (file)
@@ -70,7 +70,6 @@ xfs_setattr(
        gid_t                   gid=0, igid=0;
        int                     timeflags = 0;
        struct xfs_dquot        *udqp, *gdqp, *olddquot1, *olddquot2;
-       int                     file_owner;
        int                     need_iolock = 1;
 
        xfs_itrace_entry(ip);
@@ -81,6 +80,10 @@ xfs_setattr(
        if (XFS_FORCED_SHUTDOWN(mp))
                return XFS_ERROR(EIO);
 
+       code = -inode_change_ok(inode, iattr);
+       if (code)
+               return code;
+
        olddquot1 = olddquot2 = NULL;
        udqp = gdqp = NULL;
 
@@ -158,56 +161,6 @@ xfs_setattr(
 
        xfs_ilock(ip, lock_flags);
 
-       /* boolean: are we the file owner? */
-       file_owner = (current_fsuid() == ip->i_d.di_uid);
-
-       /*
-        * Change various properties of a file.
-        * Only the owner or users with CAP_FOWNER
-        * capability may do these things.
-        */
-       if (mask & (ATTR_MODE|ATTR_UID|ATTR_GID)) {
-               /*
-                * CAP_FOWNER overrides the following restrictions:
-                *
-                * The user ID of the calling process must be equal
-                * to the file owner ID, except in cases where the
-                * CAP_FSETID capability is applicable.
-                */
-               if (!file_owner && !capable(CAP_FOWNER)) {
-                       code = XFS_ERROR(EPERM);
-                       goto error_return;
-               }
-
-               /*
-                * CAP_FSETID overrides the following restrictions:
-                *
-                * The effective user ID of the calling process shall match
-                * the file owner when setting the set-user-ID and
-                * set-group-ID bits on that file.
-                *
-                * The effective group ID or one of the supplementary group
-                * IDs of the calling process shall match the group owner of
-                * the file when setting the set-group-ID bit on that file
-                */
-               if (mask & ATTR_MODE) {
-                       mode_t m = 0;
-
-                       if ((iattr->ia_mode & S_ISUID) && !file_owner)
-                               m |= S_ISUID;
-                       if ((iattr->ia_mode & S_ISGID) &&
-                           !in_group_p((gid_t)ip->i_d.di_gid))
-                               m |= S_ISGID;
-#if 0
-                       /* Linux allows this, Irix doesn't. */
-                       if ((iattr->ia_mode & S_ISVTX) && !S_ISDIR(ip->i_d.di_mode))
-                               m |= S_ISVTX;
-#endif
-                       if (m && !capable(CAP_FSETID))
-                               iattr->ia_mode &= ~m;
-               }
-       }
-
        /*
         * Change file ownership.  Must be the owner or privileged.
         */
@@ -223,22 +176,6 @@ xfs_setattr(
                gid = (mask & ATTR_GID) ? iattr->ia_gid : igid;
                uid = (mask & ATTR_UID) ? iattr->ia_uid : iuid;
 
-               /*
-                * CAP_CHOWN overrides the following restrictions:
-                *
-                * If _POSIX_CHOWN_RESTRICTED is defined, this capability
-                * shall override the restriction that a process cannot
-                * change the user ID of a file it owns and the restriction
-                * that the group ID supplied to the chown() function
-                * shall be equal to either the group ID or one of the
-                * supplementary group IDs of the calling process.
-                */
-               if ((iuid != uid ||
-                    (igid != gid && !in_group_p((gid_t)gid))) &&
-                   !capable(CAP_CHOWN)) {
-                       code = XFS_ERROR(EPERM);
-                       goto error_return;
-               }
                /*
                 * Do a quota reservation only if uid/gid is actually
                 * going to change.
@@ -276,36 +213,22 @@ xfs_setattr(
                        code = XFS_ERROR(EINVAL);
                        goto error_return;
                }
+
                /*
                 * Make sure that the dquots are attached to the inode.
                 */
-               if ((code = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED)))
+               code = XFS_QM_DQATTACH(mp, ip, XFS_QMOPT_ILOCKED);
+               if (code)
                        goto error_return;
-       }
 
-       /*
-        * Change file access or modified times.
-        */
-       if (mask & (ATTR_ATIME|ATTR_MTIME)) {
-               if (!file_owner) {
-                       if ((mask & (ATTR_MTIME_SET|ATTR_ATIME_SET)) &&
-                           !capable(CAP_FOWNER)) {
-                               code = XFS_ERROR(EPERM);
-                               goto error_return;
-                       }
-               }
-       }
-
-       /*
-        * Now we can make the changes.  Before we join the inode
-        * to the transaction, if ATTR_SIZE is set then take care of
-        * the part of the truncation that must be done without the
-        * inode lock.  This needs to be done before joining the inode
-        * to the transaction, because the inode cannot be unlocked
-        * once it is a part of the transaction.
-        */
-       if (mask & ATTR_SIZE) {
-               code = 0;
+               /*
+                * Now we can make the changes.  Before we join the inode
+                * to the transaction, if ATTR_SIZE is set then take care of
+                * the part of the truncation that must be done without the
+                * inode lock.  This needs to be done before joining the inode
+                * to the transaction, because the inode cannot be unlocked
+                * once it is a part of the transaction.
+                */
                if (iattr->ia_size > ip->i_size) {
                        /*
                         * Do the first part of growing a file: zero any data
@@ -360,17 +283,10 @@ xfs_setattr(
                }
                commit_flags = XFS_TRANS_RELEASE_LOG_RES;
                xfs_ilock(ip, XFS_ILOCK_EXCL);
-       }
 
-       if (tp) {
                xfs_trans_ijoin(tp, ip, lock_flags);
                xfs_trans_ihold(tp, ip);
-       }
 
-       /*
-        * Truncate file.  Must have write permission and not be a directory.
-        */
-       if (mask & ATTR_SIZE) {
                /*
                 * Only change the c/mtime if we are changing the size
                 * or we are explicitly asked to change it. This handles
@@ -410,20 +326,9 @@ xfs_setattr(
                         */
                        xfs_iflags_set(ip, XFS_ITRUNCATED);
                }
-       }
-
-       /*
-        * Change file access modes.
-        */
-       if (mask & ATTR_MODE) {
-               ip->i_d.di_mode &= S_IFMT;
-               ip->i_d.di_mode |= iattr->ia_mode & ~S_IFMT;
-
-               inode->i_mode &= S_IFMT;
-               inode->i_mode |= iattr->ia_mode & ~S_IFMT;
-
-               xfs_trans_log_inode (tp, ip, XFS_ILOG_CORE);
-               timeflags |= XFS_ICHGTIME_CHG;
+       } else if (tp) {
+               xfs_trans_ijoin(tp, ip, lock_flags);
+               xfs_trans_ihold(tp, ip);
        }
 
        /*
@@ -471,6 +376,24 @@ xfs_setattr(
                timeflags |= XFS_ICHGTIME_CHG;
        }
 
+       /*
+        * Change file access modes.
+        */
+       if (mask & ATTR_MODE) {
+               umode_t mode = iattr->ia_mode;
+
+               if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID))
+                       mode &= ~S_ISGID;
+
+               ip->i_d.di_mode &= S_IFMT;
+               ip->i_d.di_mode |= mode & ~S_IFMT;
+
+               inode->i_mode &= S_IFMT;
+               inode->i_mode |= mode & ~S_IFMT;
+
+               xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+               timeflags |= XFS_ICHGTIME_CHG;
+       }
 
        /*
         * Change file access or modified times.
@@ -939,7 +862,7 @@ xfs_inactive_symlink_rmt(
         * Find the block(s) so we can inval and unmap them.
         */
        done = 0;
-       XFS_BMAP_INIT(&free_list, &first_block);
+       xfs_bmap_init(&free_list, &first_block);
        nmaps = ARRAY_SIZE(mval);
        if ((error = xfs_bmapi(tp, ip, 0, XFS_B_TO_FSB(mp, size),
                        XFS_BMAPI_METADATA, &first_block, 0, mval, &nmaps,
@@ -1365,7 +1288,7 @@ xfs_inactive(
        /*
         * Free the inode.
         */
-       XFS_BMAP_INIT(&free_list, &first_block);
+       xfs_bmap_init(&free_list, &first_block);
        error = xfs_ifree(tp, ip, &free_list);
        if (error) {
                /*
@@ -1538,7 +1461,7 @@ xfs_create(
        xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
        unlock_dp_on_error = B_TRUE;
 
-       XFS_BMAP_INIT(&free_list, &first_block);
+       xfs_bmap_init(&free_list, &first_block);
 
        ASSERT(ip == NULL);
 
@@ -1956,7 +1879,7 @@ xfs_remove(
                }
        }
 
-       XFS_BMAP_INIT(&free_list, &first_block);
+       xfs_bmap_init(&free_list, &first_block);
        error = xfs_dir_removename(tp, dp, name, ip->i_ino,
                                        &first_block, &free_list, resblks);
        if (error) {
@@ -2136,7 +2059,7 @@ xfs_link(
        if (error)
                goto error_return;
 
-       XFS_BMAP_INIT(&free_list, &first_block);
+       xfs_bmap_init(&free_list, &first_block);
 
        error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino,
                                        &first_block, &free_list, resblks);
@@ -2308,7 +2231,7 @@ xfs_mkdir(
        xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
        unlock_dp_on_error = B_FALSE;
 
-       XFS_BMAP_INIT(&free_list, &first_block);
+       xfs_bmap_init(&free_list, &first_block);
 
        error = xfs_dir_createname(tp, dp, dir_name, cdp->i_ino,
                                        &first_block, &free_list, resblks ?
@@ -2515,7 +2438,7 @@ xfs_symlink(
         * Initialize the bmap freelist prior to calling either
         * bmapi or the directory create code.
         */
-       XFS_BMAP_INIT(&free_list, &first_block);
+       xfs_bmap_init(&free_list, &first_block);
 
        /*
         * Allocate an inode for the symlink.
@@ -2937,7 +2860,7 @@ retry:
                /*
                 * Issue the xfs_bmapi() call to allocate the blocks
                 */
-               XFS_BMAP_INIT(&free_list, &firstfsb);
+               xfs_bmap_init(&free_list, &firstfsb);
                error = xfs_bmapi(tp, ip, startoffset_fsb,
                                  allocatesize_fsb, bmapi_flag,
                                  &firstfsb, 0, imapp, &nimaps,
@@ -3057,7 +2980,7 @@ xfs_zero_remaining_bytes(
                XFS_BUF_UNDONE(bp);
                XFS_BUF_UNWRITE(bp);
                XFS_BUF_READ(bp);
-               XFS_BUF_SET_ADDR(bp, XFS_FSB_TO_DB(ip, imap.br_startblock));
+               XFS_BUF_SET_ADDR(bp, xfs_fsb_to_db(ip, imap.br_startblock));
                xfsbdstrat(mp, bp);
                error = xfs_iowait(bp);
                if (error) {
@@ -3263,7 +3186,7 @@ xfs_free_file_space(
                /*
                 * issue the bunmapi() call to free the blocks
                 */
-               XFS_BMAP_INIT(&free_list, &firstfsb);
+               xfs_bmap_init(&free_list, &firstfsb);
                error = xfs_bunmapi(tp, ip, startoffset_fsb,
                                  endoffset_fsb - startoffset_fsb,
                                  0, 2, &firstfsb, &free_list, NULL, &done);