1*c59d87c4SChristoph Hellwig /* 2*c59d87c4SChristoph Hellwig * Copyright (c) 2000-2003 Silicon Graphics, Inc. 3*c59d87c4SChristoph Hellwig * All Rights Reserved. 4*c59d87c4SChristoph Hellwig * 5*c59d87c4SChristoph Hellwig * This program is free software; you can redistribute it and/or 6*c59d87c4SChristoph Hellwig * modify it under the terms of the GNU General Public License as 7*c59d87c4SChristoph Hellwig * published by the Free Software Foundation. 8*c59d87c4SChristoph Hellwig * 9*c59d87c4SChristoph Hellwig * This program is distributed in the hope that it would be useful, 10*c59d87c4SChristoph Hellwig * but WITHOUT ANY WARRANTY; without even the implied warranty of 11*c59d87c4SChristoph Hellwig * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12*c59d87c4SChristoph Hellwig * GNU General Public License for more details. 13*c59d87c4SChristoph Hellwig * 14*c59d87c4SChristoph Hellwig * You should have received a copy of the GNU General Public License 15*c59d87c4SChristoph Hellwig * along with this program; if not, write the Free Software Foundation, 16*c59d87c4SChristoph Hellwig * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17*c59d87c4SChristoph Hellwig */ 18*c59d87c4SChristoph Hellwig #include "xfs.h" 19*c59d87c4SChristoph Hellwig #include "xfs_fs.h" 20*c59d87c4SChristoph Hellwig #include "xfs_bit.h" 21*c59d87c4SChristoph Hellwig #include "xfs_log.h" 22*c59d87c4SChristoph Hellwig #include "xfs_inum.h" 23*c59d87c4SChristoph Hellwig #include "xfs_trans.h" 24*c59d87c4SChristoph Hellwig #include "xfs_sb.h" 25*c59d87c4SChristoph Hellwig #include "xfs_ag.h" 26*c59d87c4SChristoph Hellwig #include "xfs_alloc.h" 27*c59d87c4SChristoph Hellwig #include "xfs_quota.h" 28*c59d87c4SChristoph Hellwig #include "xfs_mount.h" 29*c59d87c4SChristoph Hellwig #include "xfs_bmap_btree.h" 30*c59d87c4SChristoph Hellwig #include "xfs_inode.h" 31*c59d87c4SChristoph Hellwig #include "xfs_bmap.h" 32*c59d87c4SChristoph Hellwig #include "xfs_rtalloc.h" 33*c59d87c4SChristoph Hellwig #include "xfs_error.h" 34*c59d87c4SChristoph Hellwig #include "xfs_itable.h" 35*c59d87c4SChristoph Hellwig #include "xfs_attr.h" 36*c59d87c4SChristoph Hellwig #include "xfs_buf_item.h" 37*c59d87c4SChristoph Hellwig #include "xfs_trans_priv.h" 38*c59d87c4SChristoph Hellwig #include "xfs_qm.h" 39*c59d87c4SChristoph Hellwig 40*c59d87c4SChristoph Hellwig static inline struct xfs_dq_logitem *DQUOT_ITEM(struct xfs_log_item *lip) 41*c59d87c4SChristoph Hellwig { 42*c59d87c4SChristoph Hellwig return container_of(lip, struct xfs_dq_logitem, qli_item); 43*c59d87c4SChristoph Hellwig } 44*c59d87c4SChristoph Hellwig 45*c59d87c4SChristoph Hellwig /* 46*c59d87c4SChristoph Hellwig * returns the number of iovecs needed to log the given dquot item. 47*c59d87c4SChristoph Hellwig */ 48*c59d87c4SChristoph Hellwig STATIC uint 49*c59d87c4SChristoph Hellwig xfs_qm_dquot_logitem_size( 50*c59d87c4SChristoph Hellwig struct xfs_log_item *lip) 51*c59d87c4SChristoph Hellwig { 52*c59d87c4SChristoph Hellwig /* 53*c59d87c4SChristoph Hellwig * we need only two iovecs, one for the format, one for the real thing 54*c59d87c4SChristoph Hellwig */ 55*c59d87c4SChristoph Hellwig return 2; 56*c59d87c4SChristoph Hellwig } 57*c59d87c4SChristoph Hellwig 58*c59d87c4SChristoph Hellwig /* 59*c59d87c4SChristoph Hellwig * fills in the vector of log iovecs for the given dquot log item. 60*c59d87c4SChristoph Hellwig */ 61*c59d87c4SChristoph Hellwig STATIC void 62*c59d87c4SChristoph Hellwig xfs_qm_dquot_logitem_format( 63*c59d87c4SChristoph Hellwig struct xfs_log_item *lip, 64*c59d87c4SChristoph Hellwig struct xfs_log_iovec *logvec) 65*c59d87c4SChristoph Hellwig { 66*c59d87c4SChristoph Hellwig struct xfs_dq_logitem *qlip = DQUOT_ITEM(lip); 67*c59d87c4SChristoph Hellwig 68*c59d87c4SChristoph Hellwig logvec->i_addr = &qlip->qli_format; 69*c59d87c4SChristoph Hellwig logvec->i_len = sizeof(xfs_dq_logformat_t); 70*c59d87c4SChristoph Hellwig logvec->i_type = XLOG_REG_TYPE_QFORMAT; 71*c59d87c4SChristoph Hellwig logvec++; 72*c59d87c4SChristoph Hellwig logvec->i_addr = &qlip->qli_dquot->q_core; 73*c59d87c4SChristoph Hellwig logvec->i_len = sizeof(xfs_disk_dquot_t); 74*c59d87c4SChristoph Hellwig logvec->i_type = XLOG_REG_TYPE_DQUOT; 75*c59d87c4SChristoph Hellwig 76*c59d87c4SChristoph Hellwig ASSERT(2 == lip->li_desc->lid_size); 77*c59d87c4SChristoph Hellwig qlip->qli_format.qlf_size = 2; 78*c59d87c4SChristoph Hellwig 79*c59d87c4SChristoph Hellwig } 80*c59d87c4SChristoph Hellwig 81*c59d87c4SChristoph Hellwig /* 82*c59d87c4SChristoph Hellwig * Increment the pin count of the given dquot. 83*c59d87c4SChristoph Hellwig */ 84*c59d87c4SChristoph Hellwig STATIC void 85*c59d87c4SChristoph Hellwig xfs_qm_dquot_logitem_pin( 86*c59d87c4SChristoph Hellwig struct xfs_log_item *lip) 87*c59d87c4SChristoph Hellwig { 88*c59d87c4SChristoph Hellwig struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; 89*c59d87c4SChristoph Hellwig 90*c59d87c4SChristoph Hellwig ASSERT(XFS_DQ_IS_LOCKED(dqp)); 91*c59d87c4SChristoph Hellwig atomic_inc(&dqp->q_pincount); 92*c59d87c4SChristoph Hellwig } 93*c59d87c4SChristoph Hellwig 94*c59d87c4SChristoph Hellwig /* 95*c59d87c4SChristoph Hellwig * Decrement the pin count of the given dquot, and wake up 96*c59d87c4SChristoph Hellwig * anyone in xfs_dqwait_unpin() if the count goes to 0. The 97*c59d87c4SChristoph Hellwig * dquot must have been previously pinned with a call to 98*c59d87c4SChristoph Hellwig * xfs_qm_dquot_logitem_pin(). 99*c59d87c4SChristoph Hellwig */ 100*c59d87c4SChristoph Hellwig STATIC void 101*c59d87c4SChristoph Hellwig xfs_qm_dquot_logitem_unpin( 102*c59d87c4SChristoph Hellwig struct xfs_log_item *lip, 103*c59d87c4SChristoph Hellwig int remove) 104*c59d87c4SChristoph Hellwig { 105*c59d87c4SChristoph Hellwig struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; 106*c59d87c4SChristoph Hellwig 107*c59d87c4SChristoph Hellwig ASSERT(atomic_read(&dqp->q_pincount) > 0); 108*c59d87c4SChristoph Hellwig if (atomic_dec_and_test(&dqp->q_pincount)) 109*c59d87c4SChristoph Hellwig wake_up(&dqp->q_pinwait); 110*c59d87c4SChristoph Hellwig } 111*c59d87c4SChristoph Hellwig 112*c59d87c4SChristoph Hellwig /* 113*c59d87c4SChristoph Hellwig * Given the logitem, this writes the corresponding dquot entry to disk 114*c59d87c4SChristoph Hellwig * asynchronously. This is called with the dquot entry securely locked; 115*c59d87c4SChristoph Hellwig * we simply get xfs_qm_dqflush() to do the work, and unlock the dquot 116*c59d87c4SChristoph Hellwig * at the end. 117*c59d87c4SChristoph Hellwig */ 118*c59d87c4SChristoph Hellwig STATIC void 119*c59d87c4SChristoph Hellwig xfs_qm_dquot_logitem_push( 120*c59d87c4SChristoph Hellwig struct xfs_log_item *lip) 121*c59d87c4SChristoph Hellwig { 122*c59d87c4SChristoph Hellwig struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; 123*c59d87c4SChristoph Hellwig int error; 124*c59d87c4SChristoph Hellwig 125*c59d87c4SChristoph Hellwig ASSERT(XFS_DQ_IS_LOCKED(dqp)); 126*c59d87c4SChristoph Hellwig ASSERT(!completion_done(&dqp->q_flush)); 127*c59d87c4SChristoph Hellwig 128*c59d87c4SChristoph Hellwig /* 129*c59d87c4SChristoph Hellwig * Since we were able to lock the dquot's flush lock and 130*c59d87c4SChristoph Hellwig * we found it on the AIL, the dquot must be dirty. This 131*c59d87c4SChristoph Hellwig * is because the dquot is removed from the AIL while still 132*c59d87c4SChristoph Hellwig * holding the flush lock in xfs_dqflush_done(). Thus, if 133*c59d87c4SChristoph Hellwig * we found it in the AIL and were able to obtain the flush 134*c59d87c4SChristoph Hellwig * lock without sleeping, then there must not have been 135*c59d87c4SChristoph Hellwig * anyone in the process of flushing the dquot. 136*c59d87c4SChristoph Hellwig */ 137*c59d87c4SChristoph Hellwig error = xfs_qm_dqflush(dqp, 0); 138*c59d87c4SChristoph Hellwig if (error) 139*c59d87c4SChristoph Hellwig xfs_warn(dqp->q_mount, "%s: push error %d on dqp %p", 140*c59d87c4SChristoph Hellwig __func__, error, dqp); 141*c59d87c4SChristoph Hellwig xfs_dqunlock(dqp); 142*c59d87c4SChristoph Hellwig } 143*c59d87c4SChristoph Hellwig 144*c59d87c4SChristoph Hellwig STATIC xfs_lsn_t 145*c59d87c4SChristoph Hellwig xfs_qm_dquot_logitem_committed( 146*c59d87c4SChristoph Hellwig struct xfs_log_item *lip, 147*c59d87c4SChristoph Hellwig xfs_lsn_t lsn) 148*c59d87c4SChristoph Hellwig { 149*c59d87c4SChristoph Hellwig /* 150*c59d87c4SChristoph Hellwig * We always re-log the entire dquot when it becomes dirty, 151*c59d87c4SChristoph Hellwig * so, the latest copy _is_ the only one that matters. 152*c59d87c4SChristoph Hellwig */ 153*c59d87c4SChristoph Hellwig return lsn; 154*c59d87c4SChristoph Hellwig } 155*c59d87c4SChristoph Hellwig 156*c59d87c4SChristoph Hellwig /* 157*c59d87c4SChristoph Hellwig * This is called to wait for the given dquot to be unpinned. 158*c59d87c4SChristoph Hellwig * Most of these pin/unpin routines are plagiarized from inode code. 159*c59d87c4SChristoph Hellwig */ 160*c59d87c4SChristoph Hellwig void 161*c59d87c4SChristoph Hellwig xfs_qm_dqunpin_wait( 162*c59d87c4SChristoph Hellwig struct xfs_dquot *dqp) 163*c59d87c4SChristoph Hellwig { 164*c59d87c4SChristoph Hellwig ASSERT(XFS_DQ_IS_LOCKED(dqp)); 165*c59d87c4SChristoph Hellwig if (atomic_read(&dqp->q_pincount) == 0) 166*c59d87c4SChristoph Hellwig return; 167*c59d87c4SChristoph Hellwig 168*c59d87c4SChristoph Hellwig /* 169*c59d87c4SChristoph Hellwig * Give the log a push so we don't wait here too long. 170*c59d87c4SChristoph Hellwig */ 171*c59d87c4SChristoph Hellwig xfs_log_force(dqp->q_mount, 0); 172*c59d87c4SChristoph Hellwig wait_event(dqp->q_pinwait, (atomic_read(&dqp->q_pincount) == 0)); 173*c59d87c4SChristoph Hellwig } 174*c59d87c4SChristoph Hellwig 175*c59d87c4SChristoph Hellwig /* 176*c59d87c4SChristoph Hellwig * This is called when IOP_TRYLOCK returns XFS_ITEM_PUSHBUF to indicate that 177*c59d87c4SChristoph Hellwig * the dquot is locked by us, but the flush lock isn't. So, here we are 178*c59d87c4SChristoph Hellwig * going to see if the relevant dquot buffer is incore, waiting on DELWRI. 179*c59d87c4SChristoph Hellwig * If so, we want to push it out to help us take this item off the AIL as soon 180*c59d87c4SChristoph Hellwig * as possible. 181*c59d87c4SChristoph Hellwig * 182*c59d87c4SChristoph Hellwig * We must not be holding the AIL lock at this point. Calling incore() to 183*c59d87c4SChristoph Hellwig * search the buffer cache can be a time consuming thing, and AIL lock is a 184*c59d87c4SChristoph Hellwig * spinlock. 185*c59d87c4SChristoph Hellwig */ 186*c59d87c4SChristoph Hellwig STATIC void 187*c59d87c4SChristoph Hellwig xfs_qm_dquot_logitem_pushbuf( 188*c59d87c4SChristoph Hellwig struct xfs_log_item *lip) 189*c59d87c4SChristoph Hellwig { 190*c59d87c4SChristoph Hellwig struct xfs_dq_logitem *qlip = DQUOT_ITEM(lip); 191*c59d87c4SChristoph Hellwig struct xfs_dquot *dqp = qlip->qli_dquot; 192*c59d87c4SChristoph Hellwig struct xfs_buf *bp; 193*c59d87c4SChristoph Hellwig 194*c59d87c4SChristoph Hellwig ASSERT(XFS_DQ_IS_LOCKED(dqp)); 195*c59d87c4SChristoph Hellwig 196*c59d87c4SChristoph Hellwig /* 197*c59d87c4SChristoph Hellwig * If flushlock isn't locked anymore, chances are that the 198*c59d87c4SChristoph Hellwig * inode flush completed and the inode was taken off the AIL. 199*c59d87c4SChristoph Hellwig * So, just get out. 200*c59d87c4SChristoph Hellwig */ 201*c59d87c4SChristoph Hellwig if (completion_done(&dqp->q_flush) || 202*c59d87c4SChristoph Hellwig !(lip->li_flags & XFS_LI_IN_AIL)) { 203*c59d87c4SChristoph Hellwig xfs_dqunlock(dqp); 204*c59d87c4SChristoph Hellwig return; 205*c59d87c4SChristoph Hellwig } 206*c59d87c4SChristoph Hellwig 207*c59d87c4SChristoph Hellwig bp = xfs_incore(dqp->q_mount->m_ddev_targp, qlip->qli_format.qlf_blkno, 208*c59d87c4SChristoph Hellwig dqp->q_mount->m_quotainfo->qi_dqchunklen, XBF_TRYLOCK); 209*c59d87c4SChristoph Hellwig xfs_dqunlock(dqp); 210*c59d87c4SChristoph Hellwig if (!bp) 211*c59d87c4SChristoph Hellwig return; 212*c59d87c4SChristoph Hellwig if (XFS_BUF_ISDELAYWRITE(bp)) 213*c59d87c4SChristoph Hellwig xfs_buf_delwri_promote(bp); 214*c59d87c4SChristoph Hellwig xfs_buf_relse(bp); 215*c59d87c4SChristoph Hellwig } 216*c59d87c4SChristoph Hellwig 217*c59d87c4SChristoph Hellwig /* 218*c59d87c4SChristoph Hellwig * This is called to attempt to lock the dquot associated with this 219*c59d87c4SChristoph Hellwig * dquot log item. Don't sleep on the dquot lock or the flush lock. 220*c59d87c4SChristoph Hellwig * If the flush lock is already held, indicating that the dquot has 221*c59d87c4SChristoph Hellwig * been or is in the process of being flushed, then see if we can 222*c59d87c4SChristoph Hellwig * find the dquot's buffer in the buffer cache without sleeping. If 223*c59d87c4SChristoph Hellwig * we can and it is marked delayed write, then we want to send it out. 224*c59d87c4SChristoph Hellwig * We delay doing so until the push routine, though, to avoid sleeping 225*c59d87c4SChristoph Hellwig * in any device strategy routines. 226*c59d87c4SChristoph Hellwig */ 227*c59d87c4SChristoph Hellwig STATIC uint 228*c59d87c4SChristoph Hellwig xfs_qm_dquot_logitem_trylock( 229*c59d87c4SChristoph Hellwig struct xfs_log_item *lip) 230*c59d87c4SChristoph Hellwig { 231*c59d87c4SChristoph Hellwig struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; 232*c59d87c4SChristoph Hellwig 233*c59d87c4SChristoph Hellwig if (atomic_read(&dqp->q_pincount) > 0) 234*c59d87c4SChristoph Hellwig return XFS_ITEM_PINNED; 235*c59d87c4SChristoph Hellwig 236*c59d87c4SChristoph Hellwig if (!xfs_qm_dqlock_nowait(dqp)) 237*c59d87c4SChristoph Hellwig return XFS_ITEM_LOCKED; 238*c59d87c4SChristoph Hellwig 239*c59d87c4SChristoph Hellwig if (!xfs_dqflock_nowait(dqp)) { 240*c59d87c4SChristoph Hellwig /* 241*c59d87c4SChristoph Hellwig * dquot has already been flushed to the backing buffer, 242*c59d87c4SChristoph Hellwig * leave it locked, pushbuf routine will unlock it. 243*c59d87c4SChristoph Hellwig */ 244*c59d87c4SChristoph Hellwig return XFS_ITEM_PUSHBUF; 245*c59d87c4SChristoph Hellwig } 246*c59d87c4SChristoph Hellwig 247*c59d87c4SChristoph Hellwig ASSERT(lip->li_flags & XFS_LI_IN_AIL); 248*c59d87c4SChristoph Hellwig return XFS_ITEM_SUCCESS; 249*c59d87c4SChristoph Hellwig } 250*c59d87c4SChristoph Hellwig 251*c59d87c4SChristoph Hellwig /* 252*c59d87c4SChristoph Hellwig * Unlock the dquot associated with the log item. 253*c59d87c4SChristoph Hellwig * Clear the fields of the dquot and dquot log item that 254*c59d87c4SChristoph Hellwig * are specific to the current transaction. If the 255*c59d87c4SChristoph Hellwig * hold flags is set, do not unlock the dquot. 256*c59d87c4SChristoph Hellwig */ 257*c59d87c4SChristoph Hellwig STATIC void 258*c59d87c4SChristoph Hellwig xfs_qm_dquot_logitem_unlock( 259*c59d87c4SChristoph Hellwig struct xfs_log_item *lip) 260*c59d87c4SChristoph Hellwig { 261*c59d87c4SChristoph Hellwig struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot; 262*c59d87c4SChristoph Hellwig 263*c59d87c4SChristoph Hellwig ASSERT(XFS_DQ_IS_LOCKED(dqp)); 264*c59d87c4SChristoph Hellwig 265*c59d87c4SChristoph Hellwig /* 266*c59d87c4SChristoph Hellwig * Clear the transaction pointer in the dquot 267*c59d87c4SChristoph Hellwig */ 268*c59d87c4SChristoph Hellwig dqp->q_transp = NULL; 269*c59d87c4SChristoph Hellwig 270*c59d87c4SChristoph Hellwig /* 271*c59d87c4SChristoph Hellwig * dquots are never 'held' from getting unlocked at the end of 272*c59d87c4SChristoph Hellwig * a transaction. Their locking and unlocking is hidden inside the 273*c59d87c4SChristoph Hellwig * transaction layer, within trans_commit. Hence, no LI_HOLD flag 274*c59d87c4SChristoph Hellwig * for the logitem. 275*c59d87c4SChristoph Hellwig */ 276*c59d87c4SChristoph Hellwig xfs_dqunlock(dqp); 277*c59d87c4SChristoph Hellwig } 278*c59d87c4SChristoph Hellwig 279*c59d87c4SChristoph Hellwig /* 280*c59d87c4SChristoph Hellwig * this needs to stamp an lsn into the dquot, I think. 281*c59d87c4SChristoph Hellwig * rpc's that look at user dquot's would then have to 282*c59d87c4SChristoph Hellwig * push on the dependency recorded in the dquot 283*c59d87c4SChristoph Hellwig */ 284*c59d87c4SChristoph Hellwig STATIC void 285*c59d87c4SChristoph Hellwig xfs_qm_dquot_logitem_committing( 286*c59d87c4SChristoph Hellwig struct xfs_log_item *lip, 287*c59d87c4SChristoph Hellwig xfs_lsn_t lsn) 288*c59d87c4SChristoph Hellwig { 289*c59d87c4SChristoph Hellwig } 290*c59d87c4SChristoph Hellwig 291*c59d87c4SChristoph Hellwig /* 292*c59d87c4SChristoph Hellwig * This is the ops vector for dquots 293*c59d87c4SChristoph Hellwig */ 294*c59d87c4SChristoph Hellwig static struct xfs_item_ops xfs_dquot_item_ops = { 295*c59d87c4SChristoph Hellwig .iop_size = xfs_qm_dquot_logitem_size, 296*c59d87c4SChristoph Hellwig .iop_format = xfs_qm_dquot_logitem_format, 297*c59d87c4SChristoph Hellwig .iop_pin = xfs_qm_dquot_logitem_pin, 298*c59d87c4SChristoph Hellwig .iop_unpin = xfs_qm_dquot_logitem_unpin, 299*c59d87c4SChristoph Hellwig .iop_trylock = xfs_qm_dquot_logitem_trylock, 300*c59d87c4SChristoph Hellwig .iop_unlock = xfs_qm_dquot_logitem_unlock, 301*c59d87c4SChristoph Hellwig .iop_committed = xfs_qm_dquot_logitem_committed, 302*c59d87c4SChristoph Hellwig .iop_push = xfs_qm_dquot_logitem_push, 303*c59d87c4SChristoph Hellwig .iop_pushbuf = xfs_qm_dquot_logitem_pushbuf, 304*c59d87c4SChristoph Hellwig .iop_committing = xfs_qm_dquot_logitem_committing 305*c59d87c4SChristoph Hellwig }; 306*c59d87c4SChristoph Hellwig 307*c59d87c4SChristoph Hellwig /* 308*c59d87c4SChristoph Hellwig * Initialize the dquot log item for a newly allocated dquot. 309*c59d87c4SChristoph Hellwig * The dquot isn't locked at this point, but it isn't on any of the lists 310*c59d87c4SChristoph Hellwig * either, so we don't care. 311*c59d87c4SChristoph Hellwig */ 312*c59d87c4SChristoph Hellwig void 313*c59d87c4SChristoph Hellwig xfs_qm_dquot_logitem_init( 314*c59d87c4SChristoph Hellwig struct xfs_dquot *dqp) 315*c59d87c4SChristoph Hellwig { 316*c59d87c4SChristoph Hellwig struct xfs_dq_logitem *lp = &dqp->q_logitem; 317*c59d87c4SChristoph Hellwig 318*c59d87c4SChristoph Hellwig xfs_log_item_init(dqp->q_mount, &lp->qli_item, XFS_LI_DQUOT, 319*c59d87c4SChristoph Hellwig &xfs_dquot_item_ops); 320*c59d87c4SChristoph Hellwig lp->qli_dquot = dqp; 321*c59d87c4SChristoph Hellwig lp->qli_format.qlf_type = XFS_LI_DQUOT; 322*c59d87c4SChristoph Hellwig lp->qli_format.qlf_id = be32_to_cpu(dqp->q_core.d_id); 323*c59d87c4SChristoph Hellwig lp->qli_format.qlf_blkno = dqp->q_blkno; 324*c59d87c4SChristoph Hellwig lp->qli_format.qlf_len = 1; 325*c59d87c4SChristoph Hellwig /* 326*c59d87c4SChristoph Hellwig * This is just the offset of this dquot within its buffer 327*c59d87c4SChristoph Hellwig * (which is currently 1 FSB and probably won't change). 328*c59d87c4SChristoph Hellwig * Hence 32 bits for this offset should be just fine. 329*c59d87c4SChristoph Hellwig * Alternatively, we can store (bufoffset / sizeof(xfs_dqblk_t)) 330*c59d87c4SChristoph Hellwig * here, and recompute it at recovery time. 331*c59d87c4SChristoph Hellwig */ 332*c59d87c4SChristoph Hellwig lp->qli_format.qlf_boffset = (__uint32_t)dqp->q_bufoffset; 333*c59d87c4SChristoph Hellwig } 334*c59d87c4SChristoph Hellwig 335*c59d87c4SChristoph Hellwig /*------------------ QUOTAOFF LOG ITEMS -------------------*/ 336*c59d87c4SChristoph Hellwig 337*c59d87c4SChristoph Hellwig static inline struct xfs_qoff_logitem *QOFF_ITEM(struct xfs_log_item *lip) 338*c59d87c4SChristoph Hellwig { 339*c59d87c4SChristoph Hellwig return container_of(lip, struct xfs_qoff_logitem, qql_item); 340*c59d87c4SChristoph Hellwig } 341*c59d87c4SChristoph Hellwig 342*c59d87c4SChristoph Hellwig 343*c59d87c4SChristoph Hellwig /* 344*c59d87c4SChristoph Hellwig * This returns the number of iovecs needed to log the given quotaoff item. 345*c59d87c4SChristoph Hellwig * We only need 1 iovec for an quotaoff item. It just logs the 346*c59d87c4SChristoph Hellwig * quotaoff_log_format structure. 347*c59d87c4SChristoph Hellwig */ 348*c59d87c4SChristoph Hellwig STATIC uint 349*c59d87c4SChristoph Hellwig xfs_qm_qoff_logitem_size( 350*c59d87c4SChristoph Hellwig struct xfs_log_item *lip) 351*c59d87c4SChristoph Hellwig { 352*c59d87c4SChristoph Hellwig return 1; 353*c59d87c4SChristoph Hellwig } 354*c59d87c4SChristoph Hellwig 355*c59d87c4SChristoph Hellwig /* 356*c59d87c4SChristoph Hellwig * This is called to fill in the vector of log iovecs for the 357*c59d87c4SChristoph Hellwig * given quotaoff log item. We use only 1 iovec, and we point that 358*c59d87c4SChristoph Hellwig * at the quotaoff_log_format structure embedded in the quotaoff item. 359*c59d87c4SChristoph Hellwig * It is at this point that we assert that all of the extent 360*c59d87c4SChristoph Hellwig * slots in the quotaoff item have been filled. 361*c59d87c4SChristoph Hellwig */ 362*c59d87c4SChristoph Hellwig STATIC void 363*c59d87c4SChristoph Hellwig xfs_qm_qoff_logitem_format( 364*c59d87c4SChristoph Hellwig struct xfs_log_item *lip, 365*c59d87c4SChristoph Hellwig struct xfs_log_iovec *log_vector) 366*c59d87c4SChristoph Hellwig { 367*c59d87c4SChristoph Hellwig struct xfs_qoff_logitem *qflip = QOFF_ITEM(lip); 368*c59d87c4SChristoph Hellwig 369*c59d87c4SChristoph Hellwig ASSERT(qflip->qql_format.qf_type == XFS_LI_QUOTAOFF); 370*c59d87c4SChristoph Hellwig 371*c59d87c4SChristoph Hellwig log_vector->i_addr = &qflip->qql_format; 372*c59d87c4SChristoph Hellwig log_vector->i_len = sizeof(xfs_qoff_logitem_t); 373*c59d87c4SChristoph Hellwig log_vector->i_type = XLOG_REG_TYPE_QUOTAOFF; 374*c59d87c4SChristoph Hellwig qflip->qql_format.qf_size = 1; 375*c59d87c4SChristoph Hellwig } 376*c59d87c4SChristoph Hellwig 377*c59d87c4SChristoph Hellwig /* 378*c59d87c4SChristoph Hellwig * Pinning has no meaning for an quotaoff item, so just return. 379*c59d87c4SChristoph Hellwig */ 380*c59d87c4SChristoph Hellwig STATIC void 381*c59d87c4SChristoph Hellwig xfs_qm_qoff_logitem_pin( 382*c59d87c4SChristoph Hellwig struct xfs_log_item *lip) 383*c59d87c4SChristoph Hellwig { 384*c59d87c4SChristoph Hellwig } 385*c59d87c4SChristoph Hellwig 386*c59d87c4SChristoph Hellwig /* 387*c59d87c4SChristoph Hellwig * Since pinning has no meaning for an quotaoff item, unpinning does 388*c59d87c4SChristoph Hellwig * not either. 389*c59d87c4SChristoph Hellwig */ 390*c59d87c4SChristoph Hellwig STATIC void 391*c59d87c4SChristoph Hellwig xfs_qm_qoff_logitem_unpin( 392*c59d87c4SChristoph Hellwig struct xfs_log_item *lip, 393*c59d87c4SChristoph Hellwig int remove) 394*c59d87c4SChristoph Hellwig { 395*c59d87c4SChristoph Hellwig } 396*c59d87c4SChristoph Hellwig 397*c59d87c4SChristoph Hellwig /* 398*c59d87c4SChristoph Hellwig * Quotaoff items have no locking, so just return success. 399*c59d87c4SChristoph Hellwig */ 400*c59d87c4SChristoph Hellwig STATIC uint 401*c59d87c4SChristoph Hellwig xfs_qm_qoff_logitem_trylock( 402*c59d87c4SChristoph Hellwig struct xfs_log_item *lip) 403*c59d87c4SChristoph Hellwig { 404*c59d87c4SChristoph Hellwig return XFS_ITEM_LOCKED; 405*c59d87c4SChristoph Hellwig } 406*c59d87c4SChristoph Hellwig 407*c59d87c4SChristoph Hellwig /* 408*c59d87c4SChristoph Hellwig * Quotaoff items have no locking or pushing, so return failure 409*c59d87c4SChristoph Hellwig * so that the caller doesn't bother with us. 410*c59d87c4SChristoph Hellwig */ 411*c59d87c4SChristoph Hellwig STATIC void 412*c59d87c4SChristoph Hellwig xfs_qm_qoff_logitem_unlock( 413*c59d87c4SChristoph Hellwig struct xfs_log_item *lip) 414*c59d87c4SChristoph Hellwig { 415*c59d87c4SChristoph Hellwig } 416*c59d87c4SChristoph Hellwig 417*c59d87c4SChristoph Hellwig /* 418*c59d87c4SChristoph Hellwig * The quotaoff-start-item is logged only once and cannot be moved in the log, 419*c59d87c4SChristoph Hellwig * so simply return the lsn at which it's been logged. 420*c59d87c4SChristoph Hellwig */ 421*c59d87c4SChristoph Hellwig STATIC xfs_lsn_t 422*c59d87c4SChristoph Hellwig xfs_qm_qoff_logitem_committed( 423*c59d87c4SChristoph Hellwig struct xfs_log_item *lip, 424*c59d87c4SChristoph Hellwig xfs_lsn_t lsn) 425*c59d87c4SChristoph Hellwig { 426*c59d87c4SChristoph Hellwig return lsn; 427*c59d87c4SChristoph Hellwig } 428*c59d87c4SChristoph Hellwig 429*c59d87c4SChristoph Hellwig /* 430*c59d87c4SChristoph Hellwig * There isn't much you can do to push on an quotaoff item. It is simply 431*c59d87c4SChristoph Hellwig * stuck waiting for the log to be flushed to disk. 432*c59d87c4SChristoph Hellwig */ 433*c59d87c4SChristoph Hellwig STATIC void 434*c59d87c4SChristoph Hellwig xfs_qm_qoff_logitem_push( 435*c59d87c4SChristoph Hellwig struct xfs_log_item *lip) 436*c59d87c4SChristoph Hellwig { 437*c59d87c4SChristoph Hellwig } 438*c59d87c4SChristoph Hellwig 439*c59d87c4SChristoph Hellwig 440*c59d87c4SChristoph Hellwig STATIC xfs_lsn_t 441*c59d87c4SChristoph Hellwig xfs_qm_qoffend_logitem_committed( 442*c59d87c4SChristoph Hellwig struct xfs_log_item *lip, 443*c59d87c4SChristoph Hellwig xfs_lsn_t lsn) 444*c59d87c4SChristoph Hellwig { 445*c59d87c4SChristoph Hellwig struct xfs_qoff_logitem *qfe = QOFF_ITEM(lip); 446*c59d87c4SChristoph Hellwig struct xfs_qoff_logitem *qfs = qfe->qql_start_lip; 447*c59d87c4SChristoph Hellwig struct xfs_ail *ailp = qfs->qql_item.li_ailp; 448*c59d87c4SChristoph Hellwig 449*c59d87c4SChristoph Hellwig /* 450*c59d87c4SChristoph Hellwig * Delete the qoff-start logitem from the AIL. 451*c59d87c4SChristoph Hellwig * xfs_trans_ail_delete() drops the AIL lock. 452*c59d87c4SChristoph Hellwig */ 453*c59d87c4SChristoph Hellwig spin_lock(&ailp->xa_lock); 454*c59d87c4SChristoph Hellwig xfs_trans_ail_delete(ailp, (xfs_log_item_t *)qfs); 455*c59d87c4SChristoph Hellwig 456*c59d87c4SChristoph Hellwig kmem_free(qfs); 457*c59d87c4SChristoph Hellwig kmem_free(qfe); 458*c59d87c4SChristoph Hellwig return (xfs_lsn_t)-1; 459*c59d87c4SChristoph Hellwig } 460*c59d87c4SChristoph Hellwig 461*c59d87c4SChristoph Hellwig /* 462*c59d87c4SChristoph Hellwig * XXX rcc - don't know quite what to do with this. I think we can 463*c59d87c4SChristoph Hellwig * just ignore it. The only time that isn't the case is if we allow 464*c59d87c4SChristoph Hellwig * the client to somehow see that quotas have been turned off in which 465*c59d87c4SChristoph Hellwig * we can't allow that to get back until the quotaoff hits the disk. 466*c59d87c4SChristoph Hellwig * So how would that happen? Also, do we need different routines for 467*c59d87c4SChristoph Hellwig * quotaoff start and quotaoff end? I suspect the answer is yes but 468*c59d87c4SChristoph Hellwig * to be sure, I need to look at the recovery code and see how quota off 469*c59d87c4SChristoph Hellwig * recovery is handled (do we roll forward or back or do something else). 470*c59d87c4SChristoph Hellwig * If we roll forwards or backwards, then we need two separate routines, 471*c59d87c4SChristoph Hellwig * one that does nothing and one that stamps in the lsn that matters 472*c59d87c4SChristoph Hellwig * (truly makes the quotaoff irrevocable). If we do something else, 473*c59d87c4SChristoph Hellwig * then maybe we don't need two. 474*c59d87c4SChristoph Hellwig */ 475*c59d87c4SChristoph Hellwig STATIC void 476*c59d87c4SChristoph Hellwig xfs_qm_qoff_logitem_committing( 477*c59d87c4SChristoph Hellwig struct xfs_log_item *lip, 478*c59d87c4SChristoph Hellwig xfs_lsn_t commit_lsn) 479*c59d87c4SChristoph Hellwig { 480*c59d87c4SChristoph Hellwig } 481*c59d87c4SChristoph Hellwig 482*c59d87c4SChristoph Hellwig static struct xfs_item_ops xfs_qm_qoffend_logitem_ops = { 483*c59d87c4SChristoph Hellwig .iop_size = xfs_qm_qoff_logitem_size, 484*c59d87c4SChristoph Hellwig .iop_format = xfs_qm_qoff_logitem_format, 485*c59d87c4SChristoph Hellwig .iop_pin = xfs_qm_qoff_logitem_pin, 486*c59d87c4SChristoph Hellwig .iop_unpin = xfs_qm_qoff_logitem_unpin, 487*c59d87c4SChristoph Hellwig .iop_trylock = xfs_qm_qoff_logitem_trylock, 488*c59d87c4SChristoph Hellwig .iop_unlock = xfs_qm_qoff_logitem_unlock, 489*c59d87c4SChristoph Hellwig .iop_committed = xfs_qm_qoffend_logitem_committed, 490*c59d87c4SChristoph Hellwig .iop_push = xfs_qm_qoff_logitem_push, 491*c59d87c4SChristoph Hellwig .iop_committing = xfs_qm_qoff_logitem_committing 492*c59d87c4SChristoph Hellwig }; 493*c59d87c4SChristoph Hellwig 494*c59d87c4SChristoph Hellwig /* 495*c59d87c4SChristoph Hellwig * This is the ops vector shared by all quotaoff-start log items. 496*c59d87c4SChristoph Hellwig */ 497*c59d87c4SChristoph Hellwig static struct xfs_item_ops xfs_qm_qoff_logitem_ops = { 498*c59d87c4SChristoph Hellwig .iop_size = xfs_qm_qoff_logitem_size, 499*c59d87c4SChristoph Hellwig .iop_format = xfs_qm_qoff_logitem_format, 500*c59d87c4SChristoph Hellwig .iop_pin = xfs_qm_qoff_logitem_pin, 501*c59d87c4SChristoph Hellwig .iop_unpin = xfs_qm_qoff_logitem_unpin, 502*c59d87c4SChristoph Hellwig .iop_trylock = xfs_qm_qoff_logitem_trylock, 503*c59d87c4SChristoph Hellwig .iop_unlock = xfs_qm_qoff_logitem_unlock, 504*c59d87c4SChristoph Hellwig .iop_committed = xfs_qm_qoff_logitem_committed, 505*c59d87c4SChristoph Hellwig .iop_push = xfs_qm_qoff_logitem_push, 506*c59d87c4SChristoph Hellwig .iop_committing = xfs_qm_qoff_logitem_committing 507*c59d87c4SChristoph Hellwig }; 508*c59d87c4SChristoph Hellwig 509*c59d87c4SChristoph Hellwig /* 510*c59d87c4SChristoph Hellwig * Allocate and initialize an quotaoff item of the correct quota type(s). 511*c59d87c4SChristoph Hellwig */ 512*c59d87c4SChristoph Hellwig struct xfs_qoff_logitem * 513*c59d87c4SChristoph Hellwig xfs_qm_qoff_logitem_init( 514*c59d87c4SChristoph Hellwig struct xfs_mount *mp, 515*c59d87c4SChristoph Hellwig struct xfs_qoff_logitem *start, 516*c59d87c4SChristoph Hellwig uint flags) 517*c59d87c4SChristoph Hellwig { 518*c59d87c4SChristoph Hellwig struct xfs_qoff_logitem *qf; 519*c59d87c4SChristoph Hellwig 520*c59d87c4SChristoph Hellwig qf = kmem_zalloc(sizeof(struct xfs_qoff_logitem), KM_SLEEP); 521*c59d87c4SChristoph Hellwig 522*c59d87c4SChristoph Hellwig xfs_log_item_init(mp, &qf->qql_item, XFS_LI_QUOTAOFF, start ? 523*c59d87c4SChristoph Hellwig &xfs_qm_qoffend_logitem_ops : &xfs_qm_qoff_logitem_ops); 524*c59d87c4SChristoph Hellwig qf->qql_item.li_mountp = mp; 525*c59d87c4SChristoph Hellwig qf->qql_format.qf_type = XFS_LI_QUOTAOFF; 526*c59d87c4SChristoph Hellwig qf->qql_format.qf_flags = flags; 527*c59d87c4SChristoph Hellwig qf->qql_start_lip = start; 528*c59d87c4SChristoph Hellwig return qf; 529*c59d87c4SChristoph Hellwig } 530