OSDN Git Service

h8300: Add missing symbol "BOOT_LINK_OFFSET"
[uclinux-h8/linux.git] / fs / xfs / xfs_trans.c
index 59e2f90..917a69f 100644 (file)
@@ -648,7 +648,7 @@ xfs_trans_add_item(
        struct xfs_trans        *tp,
        struct xfs_log_item     *lip)
 {
-       ASSERT(lip->li_mountp == tp->t_mountp);
+       ASSERT(lip->li_log == tp->t_mountp->m_log);
        ASSERT(lip->li_ailp == tp->t_mountp->m_ail);
        ASSERT(list_empty(&lip->li_trans));
        ASSERT(!test_bit(XFS_LI_DIRTY, &lip->li_flags));
@@ -775,7 +775,7 @@ xfs_trans_committed_bulk(
                 * object into the AIL as we are in a shutdown situation.
                 */
                if (aborted) {
-                       ASSERT(xfs_is_shutdown(ailp->ail_mount));
+                       ASSERT(xlog_is_shutdown(ailp->ail_log));
                        if (lip->li_ops->iop_unpin)
                                lip->li_ops->iop_unpin(lip, 1);
                        continue;
@@ -1210,3 +1210,89 @@ out_cancel:
        xfs_trans_cancel(tp);
        return error;
 }
+
+/*
+ * Allocate an transaction, lock and join the directory and child inodes to it,
+ * and reserve quota for a directory update.  If there isn't sufficient space,
+ * @dblocks will be set to zero for a reservationless directory update and
+ * @nospace_error will be set to a negative errno describing the space
+ * constraint we hit.
+ *
+ * The caller must ensure that the on-disk dquots attached to this inode have
+ * already been allocated and initialized.  The ILOCKs will be dropped when the
+ * transaction is committed or cancelled.
+ */
+int
+xfs_trans_alloc_dir(
+       struct xfs_inode        *dp,
+       struct xfs_trans_res    *resv,
+       struct xfs_inode        *ip,
+       unsigned int            *dblocks,
+       struct xfs_trans        **tpp,
+       int                     *nospace_error)
+{
+       struct xfs_trans        *tp;
+       struct xfs_mount        *mp = ip->i_mount;
+       unsigned int            resblks;
+       bool                    retried = false;
+       int                     error;
+
+retry:
+       *nospace_error = 0;
+       resblks = *dblocks;
+       error = xfs_trans_alloc(mp, resv, resblks, 0, 0, &tp);
+       if (error == -ENOSPC) {
+               *nospace_error = error;
+               resblks = 0;
+               error = xfs_trans_alloc(mp, resv, resblks, 0, 0, &tp);
+       }
+       if (error)
+               return error;
+
+       xfs_lock_two_inodes(dp, XFS_ILOCK_EXCL, ip, XFS_ILOCK_EXCL);
+
+       xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL);
+       xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+
+       error = xfs_qm_dqattach_locked(dp, false);
+       if (error) {
+               /* Caller should have allocated the dquots! */
+               ASSERT(error != -ENOENT);
+               goto out_cancel;
+       }
+
+       error = xfs_qm_dqattach_locked(ip, false);
+       if (error) {
+               /* Caller should have allocated the dquots! */
+               ASSERT(error != -ENOENT);
+               goto out_cancel;
+       }
+
+       if (resblks == 0)
+               goto done;
+
+       error = xfs_trans_reserve_quota_nblks(tp, dp, resblks, 0, false);
+       if (error == -EDQUOT || error == -ENOSPC) {
+               if (!retried) {
+                       xfs_trans_cancel(tp);
+                       xfs_blockgc_free_quota(dp, 0);
+                       retried = true;
+                       goto retry;
+               }
+
+               *nospace_error = error;
+               resblks = 0;
+               error = 0;
+       }
+       if (error)
+               goto out_cancel;
+
+done:
+       *tpp = tp;
+       *dblocks = resblks;
+       return 0;
+
+out_cancel:
+       xfs_trans_cancel(tp);
+       return error;
+}