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