Commit | Line | Data |
---|---|---|
0b61f8a4 | 1 | // SPDX-License-Identifier: GPL-2.0 |
1da177e4 | 2 | /* |
4ce3121f NS |
3 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. |
4 | * All Rights Reserved. | |
1da177e4 LT |
5 | */ |
6 | #ifndef __XFS_DQUOT_H__ | |
7 | #define __XFS_DQUOT_H__ | |
8 | ||
9 | /* | |
10 | * Dquots are structures that hold quota information about a user or a group, | |
11 | * much like inodes are for files. In fact, dquots share many characteristics | |
12 | * with inodes. However, dquots can also be a centralized resource, relative | |
13 | * to a collection of inodes. In this respect, dquots share some characteristics | |
14 | * of the superblock. | |
15 | * XFS dquots exploit both those in its algorithms. They make every attempt | |
16 | * to not be a bottleneck when quotas are on and have minimal impact, if any, | |
17 | * when quotas are off. | |
18 | */ | |
19 | ||
1da177e4 LT |
20 | struct xfs_mount; |
21 | struct xfs_trans; | |
22 | ||
b1366451 BF |
23 | enum { |
24 | XFS_QLOWSP_1_PCNT = 0, | |
25 | XFS_QLOWSP_3_PCNT, | |
26 | XFS_QLOWSP_5_PCNT, | |
27 | XFS_QLOWSP_MAX | |
28 | }; | |
29 | ||
784e80f5 DW |
30 | struct xfs_dquot_res { |
31 | /* Total resources allocated and reserved. */ | |
32 | xfs_qcnt_t reserved; | |
d3537cf9 | 33 | |
be37d40c DW |
34 | /* Total resources allocated. */ |
35 | xfs_qcnt_t count; | |
36 | ||
d3537cf9 DW |
37 | /* Absolute and preferred limits. */ |
38 | xfs_qcnt_t hardlimit; | |
39 | xfs_qcnt_t softlimit; | |
c8c45fb2 | 40 | |
19dce7ea DW |
41 | /* |
42 | * For root dquots, this is the default grace period, in seconds. | |
43 | * Otherwise, this is when the quota grace period expires, | |
44 | * in seconds since the Unix epoch. | |
45 | */ | |
46 | time64_t timer; | |
47 | ||
c8c45fb2 DW |
48 | /* |
49 | * For root dquots, this is the maximum number of warnings that will | |
50 | * be issued for this quota type. Otherwise, this is the number of | |
51 | * warnings issued against this quota. Note that none of this is | |
52 | * implemented. | |
53 | */ | |
54 | xfs_qwarncnt_t warnings; | |
784e80f5 DW |
55 | }; |
56 | ||
108523b8 DW |
57 | static inline bool |
58 | xfs_dquot_res_over_limits( | |
59 | const struct xfs_dquot_res *qres) | |
60 | { | |
61 | if ((qres->softlimit && qres->softlimit < qres->reserved) || | |
62 | (qres->hardlimit && qres->hardlimit < qres->reserved)) | |
63 | return true; | |
64 | return false; | |
65 | } | |
66 | ||
1da177e4 LT |
67 | /* |
68 | * The incore dquot structure | |
69 | */ | |
aefe69a4 | 70 | struct xfs_dquot { |
aefe69a4 PR |
71 | struct list_head q_lru; |
72 | struct xfs_mount *q_mount; | |
1a7ed271 | 73 | xfs_dqtype_t q_type; |
985a78fd | 74 | uint16_t q_flags; |
c51df733 | 75 | xfs_dqid_t q_id; |
aefe69a4 | 76 | uint q_nrefs; |
aefe69a4 | 77 | int q_bufoffset; |
c51df733 | 78 | xfs_daddr_t q_blkno; |
aefe69a4 PR |
79 | xfs_fileoff_t q_fileoffset; |
80 | ||
784e80f5 DW |
81 | struct xfs_dquot_res q_blk; /* regular blocks */ |
82 | struct xfs_dquot_res q_ino; /* inodes */ | |
83 | struct xfs_dquot_res q_rtb; /* realtime blocks */ | |
84 | ||
fd8b81db | 85 | struct xfs_dq_logitem q_logitem; |
784e80f5 | 86 | |
aefe69a4 PR |
87 | xfs_qcnt_t q_prealloc_lo_wmark; |
88 | xfs_qcnt_t q_prealloc_hi_wmark; | |
89 | int64_t q_low_space[XFS_QLOWSP_MAX]; | |
90 | struct mutex q_qlock; | |
91 | struct completion q_flush; | |
92 | atomic_t q_pincount; | |
93 | struct wait_queue_head q_pinwait; | |
94 | }; | |
1da177e4 | 95 | |
5bb87a33 | 96 | /* |
af901ca1 | 97 | * Lock hierarchy for q_qlock: |
5bb87a33 | 98 | * XFS_QLOCK_NORMAL is the implicit default, |
aefe69a4 | 99 | * XFS_QLOCK_NESTED is the dquot with the higher id in xfs_dqlock2 |
5bb87a33 CH |
100 | */ |
101 | enum { | |
102 | XFS_QLOCK_NORMAL = 0, | |
103 | XFS_QLOCK_NESTED, | |
104 | }; | |
105 | ||
1da177e4 | 106 | /* |
aefe69a4 | 107 | * Manage the q_flush completion queue embedded in the dquot. This completion |
e1f49cf2 DC |
108 | * queue synchronizes processes attempting to flush the in-core dquot back to |
109 | * disk. | |
1da177e4 | 110 | */ |
aefe69a4 | 111 | static inline void xfs_dqflock(struct xfs_dquot *dqp) |
e1f49cf2 DC |
112 | { |
113 | wait_for_completion(&dqp->q_flush); | |
114 | } | |
115 | ||
aefe69a4 | 116 | static inline bool xfs_dqflock_nowait(struct xfs_dquot *dqp) |
e1f49cf2 DC |
117 | { |
118 | return try_wait_for_completion(&dqp->q_flush); | |
119 | } | |
120 | ||
aefe69a4 | 121 | static inline void xfs_dqfunlock(struct xfs_dquot *dqp) |
e1f49cf2 DC |
122 | { |
123 | complete(&dqp->q_flush); | |
124 | } | |
1da177e4 | 125 | |
800b484e CH |
126 | static inline int xfs_dqlock_nowait(struct xfs_dquot *dqp) |
127 | { | |
128 | return mutex_trylock(&dqp->q_qlock); | |
129 | } | |
130 | ||
131 | static inline void xfs_dqlock(struct xfs_dquot *dqp) | |
132 | { | |
133 | mutex_lock(&dqp->q_qlock); | |
134 | } | |
135 | ||
5b03ff1b | 136 | static inline void xfs_dqunlock(struct xfs_dquot *dqp) |
800b484e CH |
137 | { |
138 | mutex_unlock(&dqp->q_qlock); | |
139 | } | |
140 | ||
00a342e4 DW |
141 | static inline int |
142 | xfs_dquot_type(const struct xfs_dquot *dqp) | |
143 | { | |
1a7ed271 | 144 | return dqp->q_type & XFS_DQTYPE_REC_MASK; |
00a342e4 DW |
145 | } |
146 | ||
1a7ed271 | 147 | static inline int xfs_this_quota_on(struct xfs_mount *mp, xfs_dqtype_t type) |
6967b964 | 148 | { |
af1db8f1 | 149 | switch (type) { |
8cd4901d | 150 | case XFS_DQTYPE_USER: |
6967b964 | 151 | return XFS_IS_UQUOTA_ON(mp); |
8cd4901d | 152 | case XFS_DQTYPE_GROUP: |
92f8ff73 | 153 | return XFS_IS_GQUOTA_ON(mp); |
8cd4901d | 154 | case XFS_DQTYPE_PROJ: |
92f8ff73 | 155 | return XFS_IS_PQUOTA_ON(mp); |
6967b964 CS |
156 | default: |
157 | return 0; | |
158 | } | |
159 | } | |
160 | ||
1a7ed271 DW |
161 | static inline struct xfs_dquot *xfs_inode_dquot( |
162 | struct xfs_inode *ip, | |
163 | xfs_dqtype_t type) | |
36731410 | 164 | { |
af1db8f1 | 165 | switch (type) { |
8cd4901d | 166 | case XFS_DQTYPE_USER: |
36731410 | 167 | return ip->i_udquot; |
8cd4901d | 168 | case XFS_DQTYPE_GROUP: |
36731410 | 169 | return ip->i_gdquot; |
8cd4901d | 170 | case XFS_DQTYPE_PROJ: |
92f8ff73 | 171 | return ip->i_pdquot; |
36731410 CS |
172 | default: |
173 | return NULL; | |
174 | } | |
175 | } | |
176 | ||
dbcbc7b9 DW |
177 | /* Decide if the dquot's limits are actually being enforced. */ |
178 | static inline bool | |
179 | xfs_dquot_is_enforced( | |
180 | const struct xfs_dquot *dqp) | |
181 | { | |
0b04dd5d | 182 | switch (xfs_dquot_type(dqp)) { |
dbcbc7b9 DW |
183 | case XFS_DQTYPE_USER: |
184 | return XFS_IS_UQUOTA_ENFORCED(dqp->q_mount); | |
185 | case XFS_DQTYPE_GROUP: | |
186 | return XFS_IS_GQUOTA_ENFORCED(dqp->q_mount); | |
187 | case XFS_DQTYPE_PROJ: | |
188 | return XFS_IS_PQUOTA_ENFORCED(dqp->q_mount); | |
189 | } | |
190 | ASSERT(0); | |
191 | return false; | |
192 | } | |
193 | ||
dc06f398 BF |
194 | /* |
195 | * Check whether a dquot is under low free space conditions. We assume the quota | |
196 | * is enabled and enforced. | |
197 | */ | |
198 | static inline bool xfs_dquot_lowsp(struct xfs_dquot *dqp) | |
199 | { | |
200 | int64_t freesp; | |
201 | ||
d3537cf9 | 202 | freesp = dqp->q_blk.hardlimit - dqp->q_blk.reserved; |
dc06f398 BF |
203 | if (freesp < dqp->q_low_space[XFS_QLOWSP_1_PCNT]) |
204 | return true; | |
205 | ||
206 | return false; | |
207 | } | |
208 | ||
0b0fa1d1 DW |
209 | void xfs_dquot_to_disk(struct xfs_disk_dquot *ddqp, struct xfs_dquot *dqp); |
210 | ||
7201813b | 211 | #define XFS_DQ_IS_LOCKED(dqp) (mutex_is_locked(&((dqp)->q_qlock))) |
985a78fd | 212 | #define XFS_DQ_IS_DIRTY(dqp) ((dqp)->q_flags & XFS_DQFLAG_DIRTY) |
1da177e4 | 213 | |
aefe69a4 PR |
214 | void xfs_qm_dqdestroy(struct xfs_dquot *dqp); |
215 | int xfs_qm_dqflush(struct xfs_dquot *dqp, struct xfs_buf **bpp); | |
216 | void xfs_qm_dqunpin_wait(struct xfs_dquot *dqp); | |
c8c753e1 DW |
217 | void xfs_qm_adjust_dqtimers(struct xfs_dquot *d); |
218 | void xfs_qm_adjust_dqlimits(struct xfs_dquot *d); | |
219 | xfs_dqid_t xfs_qm_id_for_quotatype(struct xfs_inode *ip, | |
1a7ed271 | 220 | xfs_dqtype_t type); |
aefe69a4 | 221 | int xfs_qm_dqget(struct xfs_mount *mp, xfs_dqid_t id, |
1a7ed271 DW |
222 | xfs_dqtype_t type, bool can_alloc, |
223 | struct xfs_dquot **dqpp); | |
224 | int xfs_qm_dqget_inode(struct xfs_inode *ip, xfs_dqtype_t type, | |
225 | bool can_alloc, struct xfs_dquot **dqpp); | |
aefe69a4 | 226 | int xfs_qm_dqget_next(struct xfs_mount *mp, xfs_dqid_t id, |
1a7ed271 | 227 | xfs_dqtype_t type, struct xfs_dquot **dqpp); |
aefe69a4 | 228 | int xfs_qm_dqget_uncached(struct xfs_mount *mp, |
1a7ed271 DW |
229 | xfs_dqid_t id, xfs_dqtype_t type, |
230 | struct xfs_dquot **dqpp); | |
aefe69a4 | 231 | void xfs_qm_dqput(struct xfs_dquot *dqp); |
800b484e | 232 | |
aefe69a4 | 233 | void xfs_dqlock2(struct xfs_dquot *, struct xfs_dquot *); |
1da177e4 | 234 | |
aefe69a4 | 235 | void xfs_dquot_set_prealloc_limits(struct xfs_dquot *); |
b1366451 | 236 | |
78e55892 CH |
237 | static inline struct xfs_dquot *xfs_qm_dqhold(struct xfs_dquot *dqp) |
238 | { | |
239 | xfs_dqlock(dqp); | |
240 | dqp->q_nrefs++; | |
241 | xfs_dqunlock(dqp); | |
242 | return dqp; | |
243 | } | |
244 | ||
1a7ed271 DW |
245 | typedef int (*xfs_qm_dqiterate_fn)(struct xfs_dquot *dq, |
246 | xfs_dqtype_t type, void *priv); | |
247 | int xfs_qm_dqiterate(struct xfs_mount *mp, xfs_dqtype_t type, | |
554ba965 DW |
248 | xfs_qm_dqiterate_fn iter_fn, void *priv); |
249 | ||
11d8a919 | 250 | time64_t xfs_dquot_set_timeout(struct xfs_mount *mp, time64_t timeout); |
ccc8e771 | 251 | time64_t xfs_dquot_set_grace_period(time64_t grace); |
11d8a919 | 252 | |
1da177e4 | 253 | #endif /* __XFS_DQUOT_H__ */ |