1/* 2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. 3 * All Rights Reserved. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it would be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18#ifndef __XFS_DQUOT_H__ 19#define __XFS_DQUOT_H__ 20 21/* 22 * Dquots are structures that hold quota information about a user or a group, 23 * much like inodes are for files. In fact, dquots share many characteristics 24 * with inodes. However, dquots can also be a centralized resource, relative 25 * to a collection of inodes. In this respect, dquots share some characteristics 26 * of the superblock. 27 * XFS dquots exploit both those in its algorithms. They make every attempt 28 * to not be a bottleneck when quotas are on and have minimal impact, if any, 29 * when quotas are off. 30 */ 31 32/* 33 * The hash chain headers (hash buckets) 34 */ 35typedef struct xfs_dqhash { 36 struct xfs_dquot *qh_next; 37 mutex_t qh_lock; 38 uint qh_version; /* ever increasing version */ 39 uint qh_nelems; /* number of dquots on the list */ 40} xfs_dqhash_t; 41 42typedef struct xfs_dqlink { 43 struct xfs_dquot *ql_next; /* forward link */ 44 struct xfs_dquot **ql_prevp; /* pointer to prev ql_next */ 45} xfs_dqlink_t; 46 47struct xfs_mount; 48struct xfs_trans; 49 50/* 51 * This is the marker which is designed to occupy the first few 52 * bytes of the xfs_dquot_t structure. Even inside this, the freelist pointers 53 * must come first. 54 * This serves as the marker ("sentinel") when we have to restart list 55 * iterations because of locking considerations. 56 */ 57typedef struct xfs_dqmarker { 58 struct xfs_dquot*dqm_flnext; /* link to freelist: must be first */ 59 struct xfs_dquot*dqm_flprev; 60 xfs_dqlink_t dqm_mplist; /* link to mount's list of dquots */ 61 xfs_dqlink_t dqm_hashlist; /* link to the hash chain */ 62 uint dqm_flags; /* various flags (XFS_DQ_*) */ 63} xfs_dqmarker_t; 64 65/* 66 * The incore dquot structure 67 */ 68typedef struct xfs_dquot { 69 xfs_dqmarker_t q_lists; /* list ptrs, q_flags (marker) */ 70 xfs_dqhash_t *q_hash; /* the hashchain header */ 71 struct xfs_mount*q_mount; /* filesystem this relates to */ 72 struct xfs_trans*q_transp; /* trans this belongs to currently */ 73 uint q_nrefs; /* # active refs from inodes */ 74 xfs_daddr_t q_blkno; /* blkno of dquot buffer */ 75 int q_bufoffset; /* off of dq in buffer (# dquots) */ 76 xfs_fileoff_t q_fileoffset; /* offset in quotas file */ 77 78 struct xfs_dquot*q_gdquot; /* group dquot, hint only */ 79 xfs_disk_dquot_t q_core; /* actual usage & quotas */ 80 xfs_dq_logitem_t q_logitem; /* dquot log item */ 81 xfs_qcnt_t q_res_bcount; /* total regular nblks used+reserved */ 82 xfs_qcnt_t q_res_icount; /* total inos allocd+reserved */ 83 xfs_qcnt_t q_res_rtbcount;/* total realtime blks used+reserved */ 84 mutex_t q_qlock; /* quota lock */ 85 sema_t q_flock; /* flush lock */ 86 uint q_pincount; /* pin count for this dquot */ 87 sv_t q_pinwait; /* sync var for pinning */ 88#ifdef XFS_DQUOT_TRACE 89 struct ktrace *q_trace; /* trace header structure */ 90#endif 91} xfs_dquot_t; 92 93 94#define dq_flnext q_lists.dqm_flnext 95#define dq_flprev q_lists.dqm_flprev 96#define dq_mplist q_lists.dqm_mplist 97#define dq_hashlist q_lists.dqm_hashlist 98#define dq_flags q_lists.dqm_flags 99 100#define XFS_DQHOLD(dqp) ((dqp)->q_nrefs++) 101 102#ifdef DEBUG 103static inline int 104XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp) 105{ 106 if (mutex_trylock(&dqp->q_qlock)) { 107 mutex_unlock(&dqp->q_qlock); 108 return 0; 109 } 110 return 1; 111} 112#endif 113 114 115/* 116 * The following three routines simply manage the q_flock 117 * semaphore embedded in the dquot. This semaphore synchronizes 118 * processes attempting to flush the in-core dquot back to disk. 119 */ 120#define xfs_dqflock(dqp) { psema(&((dqp)->q_flock), PINOD | PRECALC);\ 121 (dqp)->dq_flags |= XFS_DQ_FLOCKED; } 122#define xfs_dqfunlock(dqp) { ASSERT(issemalocked(&((dqp)->q_flock))); \ 123 vsema(&((dqp)->q_flock)); \ 124 (dqp)->dq_flags &= ~(XFS_DQ_FLOCKED); } 125 126#define XFS_DQ_PINLOCK(dqp) mutex_spinlock( \ 127 &(XFS_DQ_TO_QINF(dqp)->qi_pinlock)) 128#define XFS_DQ_PINUNLOCK(dqp, s) mutex_spinunlock( \ 129 &(XFS_DQ_TO_QINF(dqp)->qi_pinlock), s) 130 131#define XFS_DQ_IS_FLUSH_LOCKED(dqp) (issemalocked(&((dqp)->q_flock))) 132#define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp)) 133#define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY) 134#define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER) 135#define XFS_QM_ISPDQ(dqp) ((dqp)->dq_flags & XFS_DQ_PROJ) 136#define XFS_QM_ISGDQ(dqp) ((dqp)->dq_flags & XFS_DQ_GROUP) 137#define XFS_DQ_TO_QINF(dqp) ((dqp)->q_mount->m_quotainfo) 138#define XFS_DQ_TO_QIP(dqp) (XFS_QM_ISUDQ(dqp) ? \ 139 XFS_DQ_TO_QINF(dqp)->qi_uquotaip : \ 140 XFS_DQ_TO_QINF(dqp)->qi_gquotaip) 141 142#define XFS_IS_THIS_QUOTA_OFF(d) (! (XFS_QM_ISUDQ(d) ? \ 143 (XFS_IS_UQUOTA_ON((d)->q_mount)) : \ 144 (XFS_IS_OQUOTA_ON((d)->q_mount)))) 145 146#ifdef XFS_DQUOT_TRACE 147/* 148 * Dquot Tracing stuff. 149 */ 150#define DQUOT_TRACE_SIZE 64 151#define DQUOT_KTRACE_ENTRY 1 152 153extern void __xfs_dqtrace_entry(xfs_dquot_t *dqp, char *func, 154 void *, xfs_inode_t *); 155#define xfs_dqtrace_entry_ino(a,b,ip) \ 156 __xfs_dqtrace_entry((a), (b), (void*)__return_address, (ip)) 157#define xfs_dqtrace_entry(a,b) \ 158 __xfs_dqtrace_entry((a), (b), (void*)__return_address, NULL) 159#else 160#define xfs_dqtrace_entry(a,b) 161#define xfs_dqtrace_entry_ino(a,b,ip) 162#endif 163 164#ifdef QUOTADEBUG 165extern void xfs_qm_dqprint(xfs_dquot_t *); 166#else 167#define xfs_qm_dqprint(a) 168#endif 169 170extern void xfs_qm_dqdestroy(xfs_dquot_t *); 171extern int xfs_qm_dqflush(xfs_dquot_t *, uint); 172extern int xfs_qm_dqpurge(xfs_dquot_t *, uint); 173extern void xfs_qm_dqunpin_wait(xfs_dquot_t *); 174extern int xfs_qm_dqlock_nowait(xfs_dquot_t *); 175extern int xfs_qm_dqflock_nowait(xfs_dquot_t *); 176extern void xfs_qm_dqflock_pushbuf_wait(xfs_dquot_t *dqp); 177extern void xfs_qm_adjust_dqtimers(xfs_mount_t *, 178 xfs_disk_dquot_t *); 179extern void xfs_qm_adjust_dqlimits(xfs_mount_t *, 180 xfs_disk_dquot_t *); 181extern int xfs_qm_dqget(xfs_mount_t *, xfs_inode_t *, 182 xfs_dqid_t, uint, uint, xfs_dquot_t **); 183extern void xfs_qm_dqput(xfs_dquot_t *); 184extern void xfs_qm_dqrele(xfs_dquot_t *); 185extern void xfs_dqlock(xfs_dquot_t *); 186extern void xfs_dqlock2(xfs_dquot_t *, xfs_dquot_t *); 187extern void xfs_dqunlock(xfs_dquot_t *); 188extern void xfs_dqunlock_nonotify(xfs_dquot_t *); 189 190#endif /* __XFS_DQUOT_H__ */ 191