]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/xfs/quota/xfs_qm_syscalls.c
[XFS] kill di_mode checks after xfs_iget
[karo-tx-linux.git] / fs / xfs / quota / xfs_qm_syscalls.c
index ad5579d4eac479e1c26266a06fb9ad081211bdba..768a3b27d2b67c68a5361c853b277e778c8f0c8e 100644 (file)
@@ -200,7 +200,6 @@ xfs_qm_scall_quotaoff(
        boolean_t               force)
 {
        uint                    dqtype;
-       unsigned long   s;
        int                     error;
        uint                    inactivate_flags;
        xfs_qoff_logitem_t      *qoffstart;
@@ -237,9 +236,9 @@ xfs_qm_scall_quotaoff(
        if ((flags & XFS_ALL_QUOTA_ACCT) == 0) {
                mp->m_qflags &= ~(flags);
 
-               s = XFS_SB_LOCK(mp);
+               spin_lock(&mp->m_sb_lock);
                mp->m_sb.sb_qflags = mp->m_qflags;
-               XFS_SB_UNLOCK(mp, s);
+               spin_unlock(&mp->m_sb_lock);
                mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
 
                /* XXX what to do if error ? Revert back to old vals incore ? */
@@ -280,9 +279,12 @@ xfs_qm_scall_quotaoff(
 
        /*
         * Write the LI_QUOTAOFF log record, and do SB changes atomically,
-        * and synchronously.
+        * and synchronously. If we fail to write, we should abort the
+        * operation as it cannot be recovered safely if we crash.
         */
-       xfs_qm_log_quotaoff(mp, &qoffstart, flags);
+       error = xfs_qm_log_quotaoff(mp, &qoffstart, flags);
+       if (error)
+               goto out_error;
 
        /*
         * Next we clear the XFS_MOUNT_*DQ_ACTIVE bit(s) in the mount struct
@@ -338,7 +340,12 @@ xfs_qm_scall_quotaoff(
         * So, we have QUOTAOFF start and end logitems; the start
         * logitem won't get overwritten until the end logitem appears...
         */
-       xfs_qm_log_quotaoff_end(mp, qoffstart, flags);
+       error = xfs_qm_log_quotaoff_end(mp, qoffstart, flags);
+       if (error) {
+               /* We're screwed now. Shutdown is the only option. */
+               xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
+               goto out_error;
+       }
 
        /*
         * If quotas is completely disabled, close shop.
@@ -362,6 +369,7 @@ xfs_qm_scall_quotaoff(
                XFS_PURGE_INODE(XFS_QI_GQIP(mp));
                XFS_QI_GQIP(mp) = NULL;
        }
+out_error:
        mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
 
        return (error);
@@ -372,35 +380,34 @@ xfs_qm_scall_trunc_qfiles(
        xfs_mount_t     *mp,
        uint            flags)
 {
-       int             error;
+       int             error = 0, error2 = 0;
        xfs_inode_t     *qip;
 
        if (!capable(CAP_SYS_ADMIN))
                return XFS_ERROR(EPERM);
-       error = 0;
-       if (!XFS_SB_VERSION_HASQUOTA(&mp->m_sb) || flags == 0) {
+       if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) {
                qdprintk("qtrunc flags=%x m_qflags=%x\n", flags, mp->m_qflags);
                return XFS_ERROR(EINVAL);
        }
 
        if ((flags & XFS_DQ_USER) && mp->m_sb.sb_uquotino != NULLFSINO) {
                error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino, 0, 0, &qip, 0);
-               if (! error) {
-                       (void) xfs_truncate_file(mp, qip);
-                       VN_RELE(XFS_ITOV(qip));
+               if (!error) {
+                       error = xfs_truncate_file(mp, qip);
+                       IRELE(qip);
                }
        }
 
        if ((flags & (XFS_DQ_GROUP|XFS_DQ_PROJ)) &&
            mp->m_sb.sb_gquotino != NULLFSINO) {
-               error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0);
-               if (! error) {
-                       (void) xfs_truncate_file(mp, qip);
-                       VN_RELE(XFS_ITOV(qip));
+               error2 = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino, 0, 0, &qip, 0);
+               if (!error2) {
+                       error2 = xfs_truncate_file(mp, qip);
+                       IRELE(qip);
                }
        }
 
-       return (error);
+       return error ? error : error2;
 }
 
 
@@ -415,7 +422,6 @@ xfs_qm_scall_quotaon(
        uint            flags)
 {
        int             error;
-       unsigned long   s;
        uint            qf;
        uint            accflags;
        __int64_t       sbflags;
@@ -468,10 +474,10 @@ xfs_qm_scall_quotaon(
         * Change sb_qflags on disk but not incore mp->qflags
         * if this is the root filesystem.
         */
-       s = XFS_SB_LOCK(mp);
+       spin_lock(&mp->m_sb_lock);
        qf = mp->m_sb.sb_qflags;
        mp->m_sb.sb_qflags = qf | flags;
-       XFS_SB_UNLOCK(mp, s);
+       spin_unlock(&mp->m_sb_lock);
 
        /*
         * There's nothing to change if it's the same.
@@ -524,7 +530,7 @@ xfs_qm_scall_getqstat(
        memset(out, 0, sizeof(fs_quota_stat_t));
 
        out->qs_version = FS_QSTAT_VERSION;
-       if (! XFS_SB_VERSION_HASQUOTA(&mp->m_sb)) {
+       if (!xfs_sb_version_hasquota(&mp->m_sb)) {
                out->qs_uquota.qfs_ino = NULLFSINO;
                out->qs_gquota.qfs_ino = NULLFSINO;
                return (0);
@@ -554,13 +560,13 @@ xfs_qm_scall_getqstat(
                out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
                out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
                if (tempuqip)
-                       VN_RELE(XFS_ITOV(uip));
+                       IRELE(uip);
        }
        if (gip) {
                out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
                out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
                if (tempgqip)
-                       VN_RELE(XFS_ITOV(gip));
+                       IRELE(gip);
        }
        if (mp->m_quotainfo) {
                out->qs_incoredqs = XFS_QI_MPLNDQUOTS(mp);
@@ -728,12 +734,12 @@ xfs_qm_scall_setqlim(
        xfs_trans_log_dquot(tp, dqp);
 
        xfs_dqtrace_entry(dqp, "Q_SETQLIM: COMMIT");
-       xfs_trans_commit(tp, 0);
+       error = xfs_trans_commit(tp, 0);
        xfs_qm_dqprint(dqp);
        xfs_qm_dqrele(dqp);
        mutex_unlock(&(XFS_QI_QOFFLOCK(mp)));
 
-       return (0);
+       return error;
 }
 
 STATIC int
@@ -815,7 +821,6 @@ xfs_qm_log_quotaoff(
 {
        xfs_trans_t            *tp;
        int                     error;
-       unsigned long   s;
        xfs_qoff_logitem_t     *qoffi=NULL;
        uint                    oldsbqflag=0;
 
@@ -832,10 +837,10 @@ xfs_qm_log_quotaoff(
        qoffi = xfs_trans_get_qoff_item(tp, NULL, flags & XFS_ALL_QUOTA_ACCT);
        xfs_trans_log_quotaoff_item(tp, qoffi);
 
-       s = XFS_SB_LOCK(mp);
+       spin_lock(&mp->m_sb_lock);
        oldsbqflag = mp->m_sb.sb_qflags;
        mp->m_sb.sb_qflags = (mp->m_qflags & ~(flags)) & XFS_MOUNT_QUOTA_ALL;
-       XFS_SB_UNLOCK(mp, s);
+       spin_unlock(&mp->m_sb_lock);
 
        xfs_mod_sb(tp, XFS_SB_QFLAGS);
 
@@ -854,9 +859,9 @@ error0:
                 * No one else is modifying sb_qflags, so this is OK.
                 * We still hold the quotaofflock.
                 */
-               s = XFS_SB_LOCK(mp);
+               spin_lock(&mp->m_sb_lock);
                mp->m_sb.sb_qflags = oldsbqflag;
-               XFS_SB_UNLOCK(mp, s);
+               spin_unlock(&mp->m_sb_lock);
        }
        *qoffstartp = qoffi;
        return (error);
@@ -1098,7 +1103,7 @@ again:
                 * inactive code in hell.
                 */
                if (vnode_refd)
-                       VN_RELE(vp);
+                       IRELE(ip);
                XFS_MOUNT_ILOCK(mp);
                /*
                 * If an inode was inserted or removed, we gotta
@@ -1361,12 +1366,6 @@ xfs_qm_internalqcheck_adjust(
                return (error);
        }
 
-       if (ip->i_d.di_mode == 0) {
-               xfs_iput_new(ip, lock_flags);
-               *res = BULKSTAT_RV_NOTHING;
-               return XFS_ERROR(ENOENT);
-       }
-
        /*
         * This inode can have blocks after eof which can get released
         * when we send it to inactive. Since we don't check the dquot