#include "xfs.h"
#include "xfs_fs.h"
-#include "xfs_inum.h"
+#include "xfs_bit.h"
#include "xfs_log.h"
+#include "xfs_inum.h"
#include "xfs_trans.h"
#include "xfs_sb.h"
#include "xfs_ag.h"
#include "xfs_dmapi.h"
#include "xfs_quota.h"
#include "xfs_mount.h"
-#include "xfs_alloc_btree.h"
#include "xfs_bmap_btree.h"
+#include "xfs_alloc_btree.h"
#include "xfs_ialloc_btree.h"
-#include "xfs_btree.h"
-#include "xfs_ialloc.h"
-#include "xfs_attr_sf.h"
#include "xfs_dir_sf.h"
#include "xfs_dir2_sf.h"
+#include "xfs_attr_sf.h"
#include "xfs_dinode.h"
#include "xfs_inode.h"
+#include "xfs_btree.h"
+#include "xfs_ialloc.h"
#include "xfs_bmap.h"
-#include "xfs_bit.h"
#include "xfs_rtalloc.h"
#include "xfs_error.h"
#include "xfs_itable.h"
*/
STATIC int
xfs_qm_dqalloc(
- xfs_trans_t *tp,
+ xfs_trans_t **tpp,
xfs_mount_t *mp,
xfs_dquot_t *dqp,
xfs_inode_t *quotip,
xfs_bmbt_irec_t map;
int nmaps, error, committed;
xfs_buf_t *bp;
+ xfs_trans_t *tp = *tpp;
ASSERT(tp != NULL);
xfs_dqtrace_entry(dqp, "DQALLOC");
xfs_qm_init_dquot_blk(tp, mp, INT_GET(dqp->q_core.d_id, ARCH_CONVERT),
dqp->dq_flags & XFS_DQ_ALLTYPES, bp);
- if ((error = xfs_bmap_finish(&tp, &flist, firstblock, &committed))) {
+ /*
+ * xfs_bmap_finish() may commit the current transaction and
+ * start a second transaction if the freelist is not empty.
+ *
+ * Since we still want to modify this buffer, we need to
+ * ensure that the buffer is not released on commit of
+ * the first transaction and ensure the buffer is added to the
+ * second transaction.
+ *
+ * If there is only one transaction then don't stop the buffer
+ * from being released when it commits later on.
+ */
+
+ xfs_trans_bhold(tp, bp);
+
+ if ((error = xfs_bmap_finish(tpp, &flist, firstblock, &committed))) {
goto error1;
}
+ if (committed) {
+ tp = *tpp;
+ xfs_trans_bjoin(tp, bp);
+ } else {
+ xfs_trans_bhold_release(tp, bp);
+ }
+
*O_bpp = bp;
return 0;
*/
STATIC int
xfs_qm_dqtobp(
- xfs_trans_t *tp,
+ xfs_trans_t **tpp,
xfs_dquot_t *dqp,
xfs_disk_dquot_t **O_ddpp,
xfs_buf_t **O_bpp,
xfs_disk_dquot_t *ddq;
xfs_dqid_t id;
boolean_t newdquot;
+ xfs_trans_t *tp = (tpp ? *tpp : NULL);
mp = dqp->q_mount;
id = INT_GET(dqp->q_core.d_id, ARCH_CONVERT);
*/
if (dqp->q_blkno == (xfs_daddr_t) 0) {
/* We use the id as an index */
- dqp->q_fileoffset = (xfs_fileoff_t) ((uint)id /
- XFS_QM_DQPERBLK(mp));
+ dqp->q_fileoffset = (xfs_fileoff_t)id / XFS_QM_DQPERBLK(mp);
nmaps = 1;
quotip = XFS_DQ_TO_QIP(dqp);
xfs_ilock(quotip, XFS_ILOCK_SHARED);
return (ENOENT);
ASSERT(tp);
- if ((error = xfs_qm_dqalloc(tp, mp, dqp, quotip,
+ if ((error = xfs_qm_dqalloc(tpp, mp, dqp, quotip,
dqp->q_fileoffset, &bp)))
return (error);
+ tp = *tpp;
newdquot = B_TRUE;
} else {
/*
/* ARGSUSED */
STATIC int
xfs_qm_dqread(
- xfs_trans_t *tp,
+ xfs_trans_t **tpp,
xfs_dqid_t id,
xfs_dquot_t *dqp, /* dquot to get filled in */
uint flags)
xfs_disk_dquot_t *ddqp;
xfs_buf_t *bp;
int error;
+ xfs_trans_t *tp;
+
+ ASSERT(tpp);
/*
* get a pointer to the on-disk dquot and the buffer containing it
* dqp already knows its own type (GROUP/USER).
*/
xfs_dqtrace_entry(dqp, "DQREAD");
- if ((error = xfs_qm_dqtobp(tp, dqp, &ddqp, &bp, flags))) {
+ if ((error = xfs_qm_dqtobp(tpp, dqp, &ddqp, &bp, flags))) {
return (error);
}
+ tp = *tpp;
/* copy everything from disk dquot to the incore dquot */
memcpy(&dqp->q_core, ddqp, sizeof(xfs_disk_dquot_t));
* Read it from disk; xfs_dqread() takes care of
* all the necessary initialization of dquot's fields (locks, etc)
*/
- if ((error = xfs_qm_dqread(tp, id, dqp, flags))) {
+ if ((error = xfs_qm_dqread(&tp, id, dqp, flags))) {
/*
* This can happen if quotas got turned off (ESRCH),
* or if the dquot didn't exist on disk and we ask to