Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc
[sfrench/cifs-2.6.git] / fs / xfs / xfs_inode.c
index 6d5641ff08f6517286b03858ed29bb72be041306..a550546a70832dc727dd117ef1c4bbc3f0ef5e90 100644 (file)
@@ -15,6 +15,8 @@
  * along with this program; if not, write the Free Software Foundation,
  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
+#include <linux/log2.h>
+
 #include "xfs.h"
 #include "xfs_fs.h"
 #include "xfs_types.h"
@@ -826,15 +828,17 @@ xfs_ip2xflags(
        xfs_icdinode_t          *dic = &ip->i_d;
 
        return _xfs_dic2xflags(dic->di_flags) |
-                               (XFS_CFORK_Q(dic) ? XFS_XFLAG_HASATTR : 0);
+                               (XFS_IFORK_Q(ip) ? XFS_XFLAG_HASATTR : 0);
 }
 
 uint
 xfs_dic2xflags(
-       xfs_dinode_core_t       *dic)
+       xfs_dinode_t            *dip)
 {
+       xfs_dinode_core_t       *dic = &dip->di_core;
+
        return _xfs_dic2xflags(be16_to_cpu(dic->di_flags)) |
-                               (XFS_CFORK_Q_DISK(dic) ? XFS_XFLAG_HASATTR : 0);
+                               (XFS_DFORK_Q(dip) ? XFS_XFLAG_HASATTR : 0);
 }
 
 /*
@@ -1296,7 +1300,10 @@ xfs_isize_check(
        if ((ip->i_d.di_mode & S_IFMT) != S_IFREG)
                return;
 
-       if (ip->i_d.di_flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_EXTSIZE))
+       if (XFS_IS_REALTIME_INODE(ip))
+               return;
+
+       if (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)
                return;
 
        nimaps = 2;
@@ -1953,24 +1960,6 @@ xfs_iunlink(
        ASSERT(agi->agi_unlinked[bucket_index]);
        ASSERT(be32_to_cpu(agi->agi_unlinked[bucket_index]) != agino);
 
-       error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
-       if (error)
-               return error;
-
-       /*
-        * Clear the on-disk di_nlink. This is to prevent xfs_bulkstat
-        * from picking up this inode when it is reclaimed (its incore state
-        * initialzed but not flushed to disk yet). The in-core di_nlink is
-        * already cleared in xfs_droplink() and a corresponding transaction
-        * logged. The hack here just synchronizes the in-core to on-disk
-        * di_nlink value in advance before the actual inode sync to disk.
-        * This is OK because the inode is already unlinked and would never
-        * change its di_nlink again for this inode generation.
-        * This is a temporary hack that would require a proper fix
-        * in the future.
-        */
-       dip->di_core.di_nlink = 0;
-
        if (be32_to_cpu(agi->agi_unlinked[bucket_index]) != NULLAGINO) {
                /*
                 * There is already another inode in the bucket we need
@@ -1978,6 +1967,10 @@ xfs_iunlink(
                 * Here we put the head pointer into our next pointer,
                 * and then we fall through to point the head at us.
                 */
+               error = xfs_itobp(mp, tp, ip, &dip, &ibp, 0, 0);
+               if (error)
+                       return error;
+
                ASSERT(be32_to_cpu(dip->di_next_unlinked) == NULLAGINO);
                /* both on-disk, don't endian flip twice */
                dip->di_next_unlinked = agi->agi_unlinked[bucket_index];
@@ -2367,6 +2360,8 @@ xfs_ifree(
        int                     error;
        int                     delete;
        xfs_ino_t               first_ino;
+       xfs_dinode_t            *dip;
+       xfs_buf_t               *ibp;
 
        ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE));
        ASSERT(ip->i_transp == tp);
@@ -2402,8 +2397,27 @@ xfs_ifree(
         * by reincarnations of this inode.
         */
        ip->i_d.di_gen++;
+
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 
+       error = xfs_itobp(ip->i_mount, tp, ip, &dip, &ibp, 0, 0);
+       if (error)
+               return error;
+
+        /*
+       * Clear the on-disk di_mode. This is to prevent xfs_bulkstat
+       * from picking up this inode when it is reclaimed (its incore state
+       * initialzed but not flushed to disk yet). The in-core di_mode is
+       * already cleared  and a corresponding transaction logged.
+       * The hack here just synchronizes the in-core to on-disk
+       * di_mode value in advance before the actual inode sync to disk.
+       * This is OK because the inode is already unlinked and would never
+       * change its di_mode again for this inode generation.
+       * This is a temporary hack that would require a proper fix
+       * in the future.
+       */
+       dip->di_core.di_mode = 0;
+
        if (delete) {
                xfs_ifree_cluster(ip, tp, first_ino);
        }
@@ -2807,40 +2821,8 @@ xfs_iunpin(
 {
        ASSERT(atomic_read(&ip->i_pincount) > 0);
 
-       if (atomic_dec_and_lock(&ip->i_pincount, &ip->i_flags_lock)) {
-
-               /*
-                * If the inode is currently being reclaimed, the link between
-                * the bhv_vnode and the xfs_inode will be broken after the
-                * XFS_IRECLAIM* flag is set. Hence, if these flags are not
-                * set, then we can move forward and mark the linux inode dirty
-                * knowing that it is still valid as it won't freed until after
-                * the bhv_vnode<->xfs_inode link is broken in xfs_reclaim. The
-                * i_flags_lock is used to synchronise the setting of the
-                * XFS_IRECLAIM* flags and the breaking of the link, and so we
-                * can execute atomically w.r.t to reclaim by holding this lock
-                * here.
-                *
-                * However, we still need to issue the unpin wakeup call as the
-                * inode reclaim may be blocked waiting for the inode to become
-                * unpinned.
-                */
-
-               if (!__xfs_iflags_test(ip, XFS_IRECLAIM|XFS_IRECLAIMABLE)) {
-                       bhv_vnode_t     *vp = XFS_ITOV_NULL(ip);
-                       struct inode *inode = NULL;
-
-                       BUG_ON(vp == NULL);
-                       inode = vn_to_inode(vp);
-                       BUG_ON(inode->i_state & I_CLEAR);
-
-                       /* make sync come back and flush this inode */
-                       if (!(inode->i_state & (I_NEW|I_FREEING)))
-                               mark_inode_dirty_sync(inode);
-               }
-               spin_unlock(&ip->i_flags_lock);
+       if (atomic_dec_and_test(&ip->i_pincount))
                wake_up(&ip->i_ipin_wait);
-       }
 }
 
 /*
@@ -3601,95 +3583,6 @@ xfs_iflush_all(
        XFS_MOUNT_IUNLOCK(mp);
 }
 
-/*
- * xfs_iaccess: check accessibility of inode for mode.
- */
-int
-xfs_iaccess(
-       xfs_inode_t     *ip,
-       mode_t          mode,
-       cred_t          *cr)
-{
-       int             error;
-       mode_t          orgmode = mode;
-       struct inode    *inode = vn_to_inode(XFS_ITOV(ip));
-
-       if (mode & S_IWUSR) {
-               umode_t         imode = inode->i_mode;
-
-               if (IS_RDONLY(inode) &&
-                   (S_ISREG(imode) || S_ISDIR(imode) || S_ISLNK(imode)))
-                       return XFS_ERROR(EROFS);
-
-               if (IS_IMMUTABLE(inode))
-                       return XFS_ERROR(EACCES);
-       }
-
-       /*
-        * If there's an Access Control List it's used instead of
-        * the mode bits.
-        */
-       if ((error = _ACL_XFS_IACCESS(ip, mode, cr)) != -1)
-               return error ? XFS_ERROR(error) : 0;
-
-       if (current_fsuid(cr) != ip->i_d.di_uid) {
-               mode >>= 3;
-               if (!in_group_p((gid_t)ip->i_d.di_gid))
-                       mode >>= 3;
-       }
-
-       /*
-        * If the DACs are ok we don't need any capability check.
-        */
-       if ((ip->i_d.di_mode & mode) == mode)
-               return 0;
-       /*
-        * Read/write DACs are always overridable.
-        * Executable DACs are overridable if at least one exec bit is set.
-        */
-       if (!(orgmode & S_IXUSR) ||
-           (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode))
-               if (capable_cred(cr, CAP_DAC_OVERRIDE))
-                       return 0;
-
-       if ((orgmode == S_IRUSR) ||
-           (S_ISDIR(inode->i_mode) && (!(orgmode & S_IWUSR)))) {
-               if (capable_cred(cr, CAP_DAC_READ_SEARCH))
-                       return 0;
-#ifdef NOISE
-               cmn_err(CE_NOTE, "Ick: mode=%o, orgmode=%o", mode, orgmode);
-#endif /* NOISE */
-               return XFS_ERROR(EACCES);
-       }
-       return XFS_ERROR(EACCES);
-}
-
-/*
- * xfs_iroundup: round up argument to next power of two
- */
-uint
-xfs_iroundup(
-       uint    v)
-{
-       int i;
-       uint m;
-
-       if ((v & (v - 1)) == 0)
-               return v;
-       ASSERT((v & 0x80000000) == 0);
-       if ((v & (v + 1)) == 0)
-               return v + 1;
-       for (i = 0, m = 1; i < 31; i++, m <<= 1) {
-               if (v & m)
-                       continue;
-               v |= m;
-               if ((v & (v + 1)) == 0)
-                       return v + 1;
-       }
-       ASSERT(0);
-       return( 0 );
-}
-
 #ifdef XFS_ILOCK_TRACE
 ktrace_t       *xfs_ilock_trace_buf;
 
@@ -4196,7 +4089,7 @@ xfs_iext_realloc_direct(
                        return;
                }
                if (!is_power_of_2(new_size)){
-                       rnew_size = xfs_iroundup(new_size);
+                       rnew_size = roundup_pow_of_two(new_size);
                }
                if (rnew_size != ifp->if_real_bytes) {
                        ifp->if_u1.if_extents =
@@ -4219,7 +4112,7 @@ xfs_iext_realloc_direct(
        else {
                new_size += ifp->if_bytes;
                if (!is_power_of_2(new_size)) {
-                       rnew_size = xfs_iroundup(new_size);
+                       rnew_size = roundup_pow_of_two(new_size);
                }
                xfs_iext_inline_to_direct(ifp, rnew_size);
        }