10b61f8a4SDave Chinner // SPDX-License-Identifier: GPL-2.0 2c59d87c4SChristoph Hellwig /* 3c59d87c4SChristoph Hellwig * Copyright (c) 2000-2003 Silicon Graphics, Inc. 4c59d87c4SChristoph Hellwig * All Rights Reserved. 5c59d87c4SChristoph Hellwig */ 6c59d87c4SChristoph Hellwig #include "xfs.h" 7c59d87c4SChristoph Hellwig #include "xfs_fs.h" 85467b34bSDarrick J. Wong #include "xfs_shared.h" 96ca1c906SDave Chinner #include "xfs_format.h" 10239880efSDave Chinner #include "xfs_log_format.h" 11239880efSDave Chinner #include "xfs_trans_resv.h" 12c59d87c4SChristoph Hellwig #include "xfs_mount.h" 13c59d87c4SChristoph Hellwig #include "xfs_inode.h" 14a4fbe6abSDave Chinner #include "xfs_quota.h" 15239880efSDave Chinner #include "xfs_trans.h" 16c59d87c4SChristoph Hellwig #include "xfs_buf_item.h" 17c59d87c4SChristoph Hellwig #include "xfs_trans_priv.h" 18c59d87c4SChristoph Hellwig #include "xfs_qm.h" 19239880efSDave Chinner #include "xfs_log.h" 20c59d87c4SChristoph Hellwig 21c59d87c4SChristoph Hellwig static inline struct xfs_dq_logitem *DQUOT_ITEM(struct xfs_log_item *lip) 22c59d87c4SChristoph Hellwig { 23c59d87c4SChristoph Hellwig return container_of(lip, struct xfs_dq_logitem, qli_item); 24c59d87c4SChristoph Hellwig } 25c59d87c4SChristoph Hellwig 26c59d87c4SChristoph Hellwig /* 27c59d87c4SChristoph Hellwig * returns the number of iovecs needed to log the given dquot item. 28c59d87c4SChristoph Hellwig */ 29166d1368SDave Chinner STATIC void 30c59d87c4SChristoph Hellwig xfs_qm_dquot_logitem_size( 31166d1368SDave Chinner struct xfs_log_item *lip, 32166d1368SDave Chinner int *nvecs, 33166d1368SDave Chinner int *nbytes) 34c59d87c4SChristoph Hellwig { 35166d1368SDave Chinner *nvecs += 2; 36166d1368SDave Chinner *nbytes += sizeof(struct xfs_dq_logformat) + 37166d1368SDave Chinner sizeof(struct xfs_disk_dquot); 38c59d87c4SChristoph Hellwig } 39c59d87c4SChristoph Hellwig 40c59d87c4SChristoph Hellwig /* 41c59d87c4SChristoph Hellwig * fills in the vector of log iovecs for the given dquot log item. 42c59d87c4SChristoph Hellwig */ 43c59d87c4SChristoph Hellwig STATIC void 44c59d87c4SChristoph Hellwig xfs_qm_dquot_logitem_format( 45c59d87c4SChristoph Hellwig struct xfs_log_item *lip, 46bde7cff6SChristoph Hellwig struct xfs_log_vec *lv) 47c59d87c4SChristoph Hellwig { 48c59d87c4SChristoph Hellwig struct xfs_dq_logitem *qlip = DQUOT_ITEM(lip); 49bde7cff6SChristoph Hellwig struct xfs_log_iovec *vecp = NULL; 50ce8e9629SChristoph Hellwig struct xfs_dq_logformat *qlf; 51c59d87c4SChristoph Hellwig 52ce8e9629SChristoph Hellwig qlf = xlog_prepare_iovec(lv, &vecp, XLOG_REG_TYPE_QFORMAT); 53ce8e9629SChristoph Hellwig qlf->qlf_type = XFS_LI_DQUOT; 54ce8e9629SChristoph Hellwig qlf->qlf_size = 2; 55ce8e9629SChristoph Hellwig qlf->qlf_id = be32_to_cpu(qlip->qli_dquot->q_core.d_id); 56ce8e9629SChristoph Hellwig qlf->qlf_blkno = qlip->qli_dquot->q_blkno; 57ce8e9629SChristoph Hellwig qlf->qlf_len = 1; 58ce8e9629SChristoph Hellwig qlf->qlf_boffset = qlip->qli_dquot->q_bufoffset; 59ce8e9629SChristoph Hellwig xlog_finish_iovec(lv, vecp, sizeof(struct xfs_dq_logformat)); 60bde7cff6SChristoph Hellwig 61bde7cff6SChristoph Hellwig xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_DQUOT, 62bde7cff6SChristoph Hellwig &qlip->qli_dquot->q_core, 63bde7cff6SChristoph Hellwig sizeof(struct xfs_disk_dquot)); 64c59d87c4SChristoph Hellwig } 65c59d87c4SChristoph Hellwig 66c59d87c4SChristoph Hellwig /* 67c59d87c4SChristoph Hellwig * Increment the pin count of the given dquot. 68c59d87c4SChristoph Hellwig */ 69c59d87c4SChristoph Hellwig STATIC void 70c59d87c4SChristoph Hellwig xfs_qm_dquot_logitem_pin( 71c59d87c4SChristoph Hellwig struct xfs_log_item *lip) 72c59d87c4SChristoph Hellwig { 73c59d87c4SChristoph Hellwig struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; 74c59d87c4SChristoph Hellwig 75c59d87c4SChristoph Hellwig ASSERT(XFS_DQ_IS_LOCKED(dqp)); 76c59d87c4SChristoph Hellwig atomic_inc(&dqp->q_pincount); 77c59d87c4SChristoph Hellwig } 78c59d87c4SChristoph Hellwig 79c59d87c4SChristoph Hellwig /* 80c59d87c4SChristoph Hellwig * Decrement the pin count of the given dquot, and wake up 81c59d87c4SChristoph Hellwig * anyone in xfs_dqwait_unpin() if the count goes to 0. The 82c59d87c4SChristoph Hellwig * dquot must have been previously pinned with a call to 83c59d87c4SChristoph Hellwig * xfs_qm_dquot_logitem_pin(). 84c59d87c4SChristoph Hellwig */ 85c59d87c4SChristoph Hellwig STATIC void 86c59d87c4SChristoph Hellwig xfs_qm_dquot_logitem_unpin( 87c59d87c4SChristoph Hellwig struct xfs_log_item *lip, 88c59d87c4SChristoph Hellwig int remove) 89c59d87c4SChristoph Hellwig { 90c59d87c4SChristoph Hellwig struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; 91c59d87c4SChristoph Hellwig 92c59d87c4SChristoph Hellwig ASSERT(atomic_read(&dqp->q_pincount) > 0); 93c59d87c4SChristoph Hellwig if (atomic_dec_and_test(&dqp->q_pincount)) 94c59d87c4SChristoph Hellwig wake_up(&dqp->q_pinwait); 95c59d87c4SChristoph Hellwig } 96c59d87c4SChristoph Hellwig 97c59d87c4SChristoph Hellwig /* 98c59d87c4SChristoph Hellwig * This is called to wait for the given dquot to be unpinned. 99c59d87c4SChristoph Hellwig * Most of these pin/unpin routines are plagiarized from inode code. 100c59d87c4SChristoph Hellwig */ 101c59d87c4SChristoph Hellwig void 102c59d87c4SChristoph Hellwig xfs_qm_dqunpin_wait( 103c59d87c4SChristoph Hellwig struct xfs_dquot *dqp) 104c59d87c4SChristoph Hellwig { 105c59d87c4SChristoph Hellwig ASSERT(XFS_DQ_IS_LOCKED(dqp)); 106c59d87c4SChristoph Hellwig if (atomic_read(&dqp->q_pincount) == 0) 107c59d87c4SChristoph Hellwig return; 108c59d87c4SChristoph Hellwig 109c59d87c4SChristoph Hellwig /* 110c59d87c4SChristoph Hellwig * Give the log a push so we don't wait here too long. 111c59d87c4SChristoph Hellwig */ 112c59d87c4SChristoph Hellwig xfs_log_force(dqp->q_mount, 0); 113c59d87c4SChristoph Hellwig wait_event(dqp->q_pinwait, (atomic_read(&dqp->q_pincount) == 0)); 114c59d87c4SChristoph Hellwig } 115c59d87c4SChristoph Hellwig 116373b0589SCarlos Maiolino /* 117373b0589SCarlos Maiolino * Callback used to mark a buffer with XFS_LI_FAILED when items in the buffer 118373b0589SCarlos Maiolino * have been failed during writeback 119373b0589SCarlos Maiolino * 120373b0589SCarlos Maiolino * this informs the AIL that the dquot is already flush locked on the next push, 121373b0589SCarlos Maiolino * and acquires a hold on the buffer to ensure that it isn't reclaimed before 122373b0589SCarlos Maiolino * dirty data makes it to disk. 123373b0589SCarlos Maiolino */ 124373b0589SCarlos Maiolino STATIC void 125373b0589SCarlos Maiolino xfs_dquot_item_error( 126373b0589SCarlos Maiolino struct xfs_log_item *lip, 127373b0589SCarlos Maiolino struct xfs_buf *bp) 128373b0589SCarlos Maiolino { 12975d4a13bSDarrick J. Wong ASSERT(!completion_done(&DQUOT_ITEM(lip)->qli_dquot->q_flush)); 130373b0589SCarlos Maiolino xfs_set_li_failed(lip, bp); 131373b0589SCarlos Maiolino } 132373b0589SCarlos Maiolino 133c59d87c4SChristoph Hellwig STATIC uint 13443ff2122SChristoph Hellwig xfs_qm_dquot_logitem_push( 13543ff2122SChristoph Hellwig struct xfs_log_item *lip, 13657e80956SMatthew Wilcox struct list_head *buffer_list) 13757e80956SMatthew Wilcox __releases(&lip->li_ailp->ail_lock) 13857e80956SMatthew Wilcox __acquires(&lip->li_ailp->ail_lock) 139c59d87c4SChristoph Hellwig { 140c59d87c4SChristoph Hellwig struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; 141373b0589SCarlos Maiolino struct xfs_buf *bp = lip->li_buf; 14243ff2122SChristoph Hellwig uint rval = XFS_ITEM_SUCCESS; 14343ff2122SChristoph Hellwig int error; 144c59d87c4SChristoph Hellwig 145c59d87c4SChristoph Hellwig if (atomic_read(&dqp->q_pincount) > 0) 146c59d87c4SChristoph Hellwig return XFS_ITEM_PINNED; 147c59d87c4SChristoph Hellwig 148373b0589SCarlos Maiolino /* 149373b0589SCarlos Maiolino * The buffer containing this item failed to be written back 150373b0589SCarlos Maiolino * previously. Resubmit the buffer for IO 151373b0589SCarlos Maiolino */ 15222525c17SDave Chinner if (test_bit(XFS_LI_FAILED, &lip->li_flags)) { 153373b0589SCarlos Maiolino if (!xfs_buf_trylock(bp)) 154373b0589SCarlos Maiolino return XFS_ITEM_LOCKED; 155373b0589SCarlos Maiolino 156643c8c05SCarlos Maiolino if (!xfs_buf_resubmit_failed_buffers(bp, buffer_list)) 157373b0589SCarlos Maiolino rval = XFS_ITEM_FLUSHING; 158373b0589SCarlos Maiolino 159373b0589SCarlos Maiolino xfs_buf_unlock(bp); 160373b0589SCarlos Maiolino return rval; 161373b0589SCarlos Maiolino } 162373b0589SCarlos Maiolino 163800b484eSChristoph Hellwig if (!xfs_dqlock_nowait(dqp)) 164c59d87c4SChristoph Hellwig return XFS_ITEM_LOCKED; 165c59d87c4SChristoph Hellwig 166fe7257fdSChristoph Hellwig /* 167fe7257fdSChristoph Hellwig * Re-check the pincount now that we stabilized the value by 168fe7257fdSChristoph Hellwig * taking the quota lock. 169fe7257fdSChristoph Hellwig */ 170fe7257fdSChristoph Hellwig if (atomic_read(&dqp->q_pincount) > 0) { 17143ff2122SChristoph Hellwig rval = XFS_ITEM_PINNED; 17243ff2122SChristoph Hellwig goto out_unlock; 173fe7257fdSChristoph Hellwig } 174fe7257fdSChristoph Hellwig 175c59d87c4SChristoph Hellwig /* 17643ff2122SChristoph Hellwig * Someone else is already flushing the dquot. Nothing we can do 17743ff2122SChristoph Hellwig * here but wait for the flush to finish and remove the item from 17843ff2122SChristoph Hellwig * the AIL. 179c59d87c4SChristoph Hellwig */ 18043ff2122SChristoph Hellwig if (!xfs_dqflock_nowait(dqp)) { 18143ff2122SChristoph Hellwig rval = XFS_ITEM_FLUSHING; 18243ff2122SChristoph Hellwig goto out_unlock; 183c59d87c4SChristoph Hellwig } 184c59d87c4SChristoph Hellwig 18557e80956SMatthew Wilcox spin_unlock(&lip->li_ailp->ail_lock); 18643ff2122SChristoph Hellwig 18743ff2122SChristoph Hellwig error = xfs_qm_dqflush(dqp, &bp); 188609001bcSDarrick J. Wong if (!error) { 18943ff2122SChristoph Hellwig if (!xfs_buf_delwri_queue(bp, buffer_list)) 19043ff2122SChristoph Hellwig rval = XFS_ITEM_FLUSHING; 19143ff2122SChristoph Hellwig xfs_buf_relse(bp); 192*8d3d7e2bSBrian Foster } else if (error == -EAGAIN) 193*8d3d7e2bSBrian Foster rval = XFS_ITEM_LOCKED; 19443ff2122SChristoph Hellwig 19557e80956SMatthew Wilcox spin_lock(&lip->li_ailp->ail_lock); 19643ff2122SChristoph Hellwig out_unlock: 19743ff2122SChristoph Hellwig xfs_dqunlock(dqp); 19843ff2122SChristoph Hellwig return rval; 199c59d87c4SChristoph Hellwig } 200c59d87c4SChristoph Hellwig 201c59d87c4SChristoph Hellwig STATIC void 202ddf92053SChristoph Hellwig xfs_qm_dquot_logitem_release( 203c59d87c4SChristoph Hellwig struct xfs_log_item *lip) 204c59d87c4SChristoph Hellwig { 205c59d87c4SChristoph Hellwig struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; 206c59d87c4SChristoph Hellwig 207c59d87c4SChristoph Hellwig ASSERT(XFS_DQ_IS_LOCKED(dqp)); 208c59d87c4SChristoph Hellwig 209c59d87c4SChristoph Hellwig /* 210c59d87c4SChristoph Hellwig * dquots are never 'held' from getting unlocked at the end of 211c59d87c4SChristoph Hellwig * a transaction. Their locking and unlocking is hidden inside the 212c59d87c4SChristoph Hellwig * transaction layer, within trans_commit. Hence, no LI_HOLD flag 213c59d87c4SChristoph Hellwig * for the logitem. 214c59d87c4SChristoph Hellwig */ 215c59d87c4SChristoph Hellwig xfs_dqunlock(dqp); 216c59d87c4SChristoph Hellwig } 217c59d87c4SChristoph Hellwig 218ddf92053SChristoph Hellwig STATIC void 219ddf92053SChristoph Hellwig xfs_qm_dquot_logitem_committing( 220ddf92053SChristoph Hellwig struct xfs_log_item *lip, 221ddf92053SChristoph Hellwig xfs_lsn_t commit_lsn) 222ddf92053SChristoph Hellwig { 223ddf92053SChristoph Hellwig return xfs_qm_dquot_logitem_release(lip); 224ddf92053SChristoph Hellwig } 225ddf92053SChristoph Hellwig 226272e42b2SChristoph Hellwig static const struct xfs_item_ops xfs_dquot_item_ops = { 227c59d87c4SChristoph Hellwig .iop_size = xfs_qm_dquot_logitem_size, 228c59d87c4SChristoph Hellwig .iop_format = xfs_qm_dquot_logitem_format, 229c59d87c4SChristoph Hellwig .iop_pin = xfs_qm_dquot_logitem_pin, 230c59d87c4SChristoph Hellwig .iop_unpin = xfs_qm_dquot_logitem_unpin, 231ddf92053SChristoph Hellwig .iop_release = xfs_qm_dquot_logitem_release, 232ddf92053SChristoph Hellwig .iop_committing = xfs_qm_dquot_logitem_committing, 233c59d87c4SChristoph Hellwig .iop_push = xfs_qm_dquot_logitem_push, 234373b0589SCarlos Maiolino .iop_error = xfs_dquot_item_error 235c59d87c4SChristoph Hellwig }; 236c59d87c4SChristoph Hellwig 237c59d87c4SChristoph Hellwig /* 238c59d87c4SChristoph Hellwig * Initialize the dquot log item for a newly allocated dquot. 239c59d87c4SChristoph Hellwig * The dquot isn't locked at this point, but it isn't on any of the lists 240c59d87c4SChristoph Hellwig * either, so we don't care. 241c59d87c4SChristoph Hellwig */ 242c59d87c4SChristoph Hellwig void 243c59d87c4SChristoph Hellwig xfs_qm_dquot_logitem_init( 244c59d87c4SChristoph Hellwig struct xfs_dquot *dqp) 245c59d87c4SChristoph Hellwig { 246c59d87c4SChristoph Hellwig struct xfs_dq_logitem *lp = &dqp->q_logitem; 247c59d87c4SChristoph Hellwig 248c59d87c4SChristoph Hellwig xfs_log_item_init(dqp->q_mount, &lp->qli_item, XFS_LI_DQUOT, 249c59d87c4SChristoph Hellwig &xfs_dquot_item_ops); 250c59d87c4SChristoph Hellwig lp->qli_dquot = dqp; 251c59d87c4SChristoph Hellwig } 252c59d87c4SChristoph Hellwig 253c59d87c4SChristoph Hellwig /*------------------ QUOTAOFF LOG ITEMS -------------------*/ 254c59d87c4SChristoph Hellwig 255c59d87c4SChristoph Hellwig static inline struct xfs_qoff_logitem *QOFF_ITEM(struct xfs_log_item *lip) 256c59d87c4SChristoph Hellwig { 257c59d87c4SChristoph Hellwig return container_of(lip, struct xfs_qoff_logitem, qql_item); 258c59d87c4SChristoph Hellwig } 259c59d87c4SChristoph Hellwig 260c59d87c4SChristoph Hellwig 261c59d87c4SChristoph Hellwig /* 262c59d87c4SChristoph Hellwig * This returns the number of iovecs needed to log the given quotaoff item. 263c59d87c4SChristoph Hellwig * We only need 1 iovec for an quotaoff item. It just logs the 264c59d87c4SChristoph Hellwig * quotaoff_log_format structure. 265c59d87c4SChristoph Hellwig */ 266166d1368SDave Chinner STATIC void 267c59d87c4SChristoph Hellwig xfs_qm_qoff_logitem_size( 268166d1368SDave Chinner struct xfs_log_item *lip, 269166d1368SDave Chinner int *nvecs, 270166d1368SDave Chinner int *nbytes) 271c59d87c4SChristoph Hellwig { 272166d1368SDave Chinner *nvecs += 1; 273166d1368SDave Chinner *nbytes += sizeof(struct xfs_qoff_logitem); 274c59d87c4SChristoph Hellwig } 275c59d87c4SChristoph Hellwig 276c59d87c4SChristoph Hellwig STATIC void 277c59d87c4SChristoph Hellwig xfs_qm_qoff_logitem_format( 278c59d87c4SChristoph Hellwig struct xfs_log_item *lip, 279bde7cff6SChristoph Hellwig struct xfs_log_vec *lv) 280c59d87c4SChristoph Hellwig { 281c59d87c4SChristoph Hellwig struct xfs_qoff_logitem *qflip = QOFF_ITEM(lip); 282bde7cff6SChristoph Hellwig struct xfs_log_iovec *vecp = NULL; 283ffda4e83SChristoph Hellwig struct xfs_qoff_logformat *qlf; 284c59d87c4SChristoph Hellwig 285ffda4e83SChristoph Hellwig qlf = xlog_prepare_iovec(lv, &vecp, XLOG_REG_TYPE_QUOTAOFF); 286ffda4e83SChristoph Hellwig qlf->qf_type = XFS_LI_QUOTAOFF; 287ffda4e83SChristoph Hellwig qlf->qf_size = 1; 288ffda4e83SChristoph Hellwig qlf->qf_flags = qflip->qql_flags; 289ffda4e83SChristoph Hellwig xlog_finish_iovec(lv, vecp, sizeof(struct xfs_qoff_logitem)); 290c59d87c4SChristoph Hellwig } 291c59d87c4SChristoph Hellwig 292c59d87c4SChristoph Hellwig /* 29343ff2122SChristoph Hellwig * There isn't much you can do to push a quotaoff item. It is simply 29443ff2122SChristoph Hellwig * stuck waiting for the log to be flushed to disk. 295c59d87c4SChristoph Hellwig */ 296c59d87c4SChristoph Hellwig STATIC uint 29743ff2122SChristoph Hellwig xfs_qm_qoff_logitem_push( 29843ff2122SChristoph Hellwig struct xfs_log_item *lip, 29943ff2122SChristoph Hellwig struct list_head *buffer_list) 300c59d87c4SChristoph Hellwig { 301c59d87c4SChristoph Hellwig return XFS_ITEM_LOCKED; 302c59d87c4SChristoph Hellwig } 303c59d87c4SChristoph Hellwig 304c59d87c4SChristoph Hellwig STATIC xfs_lsn_t 305c59d87c4SChristoph Hellwig xfs_qm_qoffend_logitem_committed( 306c59d87c4SChristoph Hellwig struct xfs_log_item *lip, 307c59d87c4SChristoph Hellwig xfs_lsn_t lsn) 308c59d87c4SChristoph Hellwig { 309c59d87c4SChristoph Hellwig struct xfs_qoff_logitem *qfe = QOFF_ITEM(lip); 310c59d87c4SChristoph Hellwig struct xfs_qoff_logitem *qfs = qfe->qql_start_lip; 311c59d87c4SChristoph Hellwig 312854f82b1SBrian Foster xfs_qm_qoff_logitem_relse(qfs); 313c59d87c4SChristoph Hellwig 314b1c5ebb2SDave Chinner kmem_free(lip->li_lv_shadow); 315c59d87c4SChristoph Hellwig kmem_free(qfe); 316c59d87c4SChristoph Hellwig return (xfs_lsn_t)-1; 317c59d87c4SChristoph Hellwig } 318c59d87c4SChristoph Hellwig 3198a627143SBrian Foster STATIC void 3208a627143SBrian Foster xfs_qm_qoff_logitem_release( 3218a627143SBrian Foster struct xfs_log_item *lip) 3228a627143SBrian Foster { 3238a627143SBrian Foster struct xfs_qoff_logitem *qoff = QOFF_ITEM(lip); 3248a627143SBrian Foster 3258a627143SBrian Foster if (test_bit(XFS_LI_ABORTED, &lip->li_flags)) { 3268a627143SBrian Foster if (qoff->qql_start_lip) 3278a627143SBrian Foster xfs_qm_qoff_logitem_relse(qoff->qql_start_lip); 3288a627143SBrian Foster xfs_qm_qoff_logitem_relse(qoff); 3298a627143SBrian Foster } 3308a627143SBrian Foster } 3318a627143SBrian Foster 332272e42b2SChristoph Hellwig static const struct xfs_item_ops xfs_qm_qoffend_logitem_ops = { 333c59d87c4SChristoph Hellwig .iop_size = xfs_qm_qoff_logitem_size, 334c59d87c4SChristoph Hellwig .iop_format = xfs_qm_qoff_logitem_format, 335c59d87c4SChristoph Hellwig .iop_committed = xfs_qm_qoffend_logitem_committed, 336c59d87c4SChristoph Hellwig .iop_push = xfs_qm_qoff_logitem_push, 3378a627143SBrian Foster .iop_release = xfs_qm_qoff_logitem_release, 338c59d87c4SChristoph Hellwig }; 339c59d87c4SChristoph Hellwig 340272e42b2SChristoph Hellwig static const struct xfs_item_ops xfs_qm_qoff_logitem_ops = { 341c59d87c4SChristoph Hellwig .iop_size = xfs_qm_qoff_logitem_size, 342c59d87c4SChristoph Hellwig .iop_format = xfs_qm_qoff_logitem_format, 343c59d87c4SChristoph Hellwig .iop_push = xfs_qm_qoff_logitem_push, 3448a627143SBrian Foster .iop_release = xfs_qm_qoff_logitem_release, 345c59d87c4SChristoph Hellwig }; 346c59d87c4SChristoph Hellwig 347c59d87c4SChristoph Hellwig /* 348854f82b1SBrian Foster * Delete the quotaoff intent from the AIL and free it. On success, 349854f82b1SBrian Foster * this should only be called for the start item. It can be used for 350854f82b1SBrian Foster * either on shutdown or abort. 351854f82b1SBrian Foster */ 352854f82b1SBrian Foster void 353854f82b1SBrian Foster xfs_qm_qoff_logitem_relse( 354854f82b1SBrian Foster struct xfs_qoff_logitem *qoff) 355854f82b1SBrian Foster { 356854f82b1SBrian Foster struct xfs_log_item *lip = &qoff->qql_item; 357854f82b1SBrian Foster 358854f82b1SBrian Foster ASSERT(test_bit(XFS_LI_IN_AIL, &lip->li_flags) || 359854f82b1SBrian Foster test_bit(XFS_LI_ABORTED, &lip->li_flags) || 360854f82b1SBrian Foster XFS_FORCED_SHUTDOWN(lip->li_mountp)); 361854f82b1SBrian Foster xfs_trans_ail_remove(lip, SHUTDOWN_LOG_IO_ERROR); 362854f82b1SBrian Foster kmem_free(lip->li_lv_shadow); 363854f82b1SBrian Foster kmem_free(qoff); 364854f82b1SBrian Foster } 365854f82b1SBrian Foster 366854f82b1SBrian Foster /* 367c59d87c4SChristoph Hellwig * Allocate and initialize an quotaoff item of the correct quota type(s). 368c59d87c4SChristoph Hellwig */ 369c59d87c4SChristoph Hellwig struct xfs_qoff_logitem * 370c59d87c4SChristoph Hellwig xfs_qm_qoff_logitem_init( 371c59d87c4SChristoph Hellwig struct xfs_mount *mp, 372c59d87c4SChristoph Hellwig struct xfs_qoff_logitem *start, 373c59d87c4SChristoph Hellwig uint flags) 374c59d87c4SChristoph Hellwig { 375c59d87c4SChristoph Hellwig struct xfs_qoff_logitem *qf; 376c59d87c4SChristoph Hellwig 377707e0ddaSTetsuo Handa qf = kmem_zalloc(sizeof(struct xfs_qoff_logitem), 0); 378c59d87c4SChristoph Hellwig 379c59d87c4SChristoph Hellwig xfs_log_item_init(mp, &qf->qql_item, XFS_LI_QUOTAOFF, start ? 380c59d87c4SChristoph Hellwig &xfs_qm_qoffend_logitem_ops : &xfs_qm_qoff_logitem_ops); 381c59d87c4SChristoph Hellwig qf->qql_item.li_mountp = mp; 382c59d87c4SChristoph Hellwig qf->qql_start_lip = start; 383ffda4e83SChristoph Hellwig qf->qql_flags = flags; 384c59d87c4SChristoph Hellwig return qf; 385c59d87c4SChristoph Hellwig } 386