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; | |
784e80f5 DW |
47 | }; |
48 | ||
108523b8 DW |
49 | static inline bool |
50 | xfs_dquot_res_over_limits( | |
51 | const struct xfs_dquot_res *qres) | |
52 | { | |
53 | if ((qres->softlimit && qres->softlimit < qres->reserved) || | |
54 | (qres->hardlimit && qres->hardlimit < qres->reserved)) | |
55 | return true; | |
56 | return false; | |
57 | } | |
58 | ||
1da177e4 LT |
59 | /* |
60 | * The incore dquot structure | |
61 | */ | |
aefe69a4 | 62 | struct xfs_dquot { |
aefe69a4 PR |
63 | struct list_head q_lru; |
64 | struct xfs_mount *q_mount; | |
1a7ed271 | 65 | xfs_dqtype_t q_type; |
985a78fd | 66 | uint16_t q_flags; |
c51df733 | 67 | xfs_dqid_t q_id; |
aefe69a4 | 68 | uint q_nrefs; |
aefe69a4 | 69 | int q_bufoffset; |
c51df733 | 70 | xfs_daddr_t q_blkno; |
aefe69a4 PR |
71 | xfs_fileoff_t q_fileoffset; |
72 | ||
784e80f5 DW |
73 | struct xfs_dquot_res q_blk; /* regular blocks */ |
74 | struct xfs_dquot_res q_ino; /* inodes */ | |
75 | struct xfs_dquot_res q_rtb; /* realtime blocks */ | |
76 | ||
fd8b81db | 77 | struct xfs_dq_logitem q_logitem; |
784e80f5 | 78 | |
aefe69a4 PR |
79 | xfs_qcnt_t q_prealloc_lo_wmark; |
80 | xfs_qcnt_t q_prealloc_hi_wmark; | |
81 | int64_t q_low_space[XFS_QLOWSP_MAX]; | |
82 | struct mutex q_qlock; | |
83 | struct completion q_flush; | |
84 | atomic_t q_pincount; | |
85 | struct wait_queue_head q_pinwait; | |
86 | }; | |
1da177e4 | 87 | |
5bb87a33 | 88 | /* |
af901ca1 | 89 | * Lock hierarchy for q_qlock: |
5bb87a33 | 90 | * XFS_QLOCK_NORMAL is the implicit default, |
aefe69a4 | 91 | * XFS_QLOCK_NESTED is the dquot with the higher id in xfs_dqlock2 |
5bb87a33 CH |
92 | */ |
93 | enum { | |
94 | XFS_QLOCK_NORMAL = 0, | |
95 | XFS_QLOCK_NESTED, | |
96 | }; | |
97 | ||
1da177e4 | 98 | /* |
aefe69a4 | 99 | * Manage the q_flush completion queue embedded in the dquot. This completion |
e1f49cf2 DC |
100 | * queue synchronizes processes attempting to flush the in-core dquot back to |
101 | * disk. | |
1da177e4 | 102 | */ |
aefe69a4 | 103 | static inline void xfs_dqflock(struct xfs_dquot *dqp) |
e1f49cf2 DC |
104 | { |
105 | wait_for_completion(&dqp->q_flush); | |
106 | } | |
107 | ||
aefe69a4 | 108 | static inline bool xfs_dqflock_nowait(struct xfs_dquot *dqp) |
e1f49cf2 DC |
109 | { |
110 | return try_wait_for_completion(&dqp->q_flush); | |
111 | } | |
112 | ||
aefe69a4 | 113 | static inline void xfs_dqfunlock(struct xfs_dquot *dqp) |
e1f49cf2 DC |
114 | { |
115 | complete(&dqp->q_flush); | |
116 | } | |
1da177e4 | 117 | |
800b484e CH |
118 | static inline int xfs_dqlock_nowait(struct xfs_dquot *dqp) |
119 | { | |
120 | return mutex_trylock(&dqp->q_qlock); | |
121 | } | |
122 | ||
123 | static inline void xfs_dqlock(struct xfs_dquot *dqp) | |
124 | { | |
125 | mutex_lock(&dqp->q_qlock); | |
126 | } | |
127 | ||
5b03ff1b | 128 | static inline void xfs_dqunlock(struct xfs_dquot *dqp) |
800b484e CH |
129 | { |
130 | mutex_unlock(&dqp->q_qlock); | |
131 | } | |
132 | ||
00a342e4 DW |
133 | static inline int |
134 | xfs_dquot_type(const struct xfs_dquot *dqp) | |
135 | { | |
1a7ed271 | 136 | return dqp->q_type & XFS_DQTYPE_REC_MASK; |
00a342e4 DW |
137 | } |
138 | ||
1a7ed271 | 139 | static inline int xfs_this_quota_on(struct xfs_mount *mp, xfs_dqtype_t type) |
6967b964 | 140 | { |
af1db8f1 | 141 | switch (type) { |
8cd4901d | 142 | case XFS_DQTYPE_USER: |
6967b964 | 143 | return XFS_IS_UQUOTA_ON(mp); |
8cd4901d | 144 | case XFS_DQTYPE_GROUP: |
92f8ff73 | 145 | return XFS_IS_GQUOTA_ON(mp); |
8cd4901d | 146 | case XFS_DQTYPE_PROJ: |
92f8ff73 | 147 | return XFS_IS_PQUOTA_ON(mp); |
6967b964 CS |
148 | default: |
149 | return 0; | |
150 | } | |
151 | } | |
152 | ||
1a7ed271 DW |
153 | static inline struct xfs_dquot *xfs_inode_dquot( |
154 | struct xfs_inode *ip, | |
155 | xfs_dqtype_t type) | |
36731410 | 156 | { |
af1db8f1 | 157 | switch (type) { |
8cd4901d | 158 | case XFS_DQTYPE_USER: |
36731410 | 159 | return ip->i_udquot; |
8cd4901d | 160 | case XFS_DQTYPE_GROUP: |
36731410 | 161 | return ip->i_gdquot; |
8cd4901d | 162 | case XFS_DQTYPE_PROJ: |
92f8ff73 | 163 | return ip->i_pdquot; |
36731410 CS |
164 | default: |
165 | return NULL; | |
166 | } | |
167 | } | |
168 | ||
dbcbc7b9 DW |
169 | /* Decide if the dquot's limits are actually being enforced. */ |
170 | static inline bool | |
171 | xfs_dquot_is_enforced( | |
172 | const struct xfs_dquot *dqp) | |
173 | { | |
0b04dd5d | 174 | switch (xfs_dquot_type(dqp)) { |
dbcbc7b9 DW |
175 | case XFS_DQTYPE_USER: |
176 | return XFS_IS_UQUOTA_ENFORCED(dqp->q_mount); | |
177 | case XFS_DQTYPE_GROUP: | |
178 | return XFS_IS_GQUOTA_ENFORCED(dqp->q_mount); | |
179 | case XFS_DQTYPE_PROJ: | |
180 | return XFS_IS_PQUOTA_ENFORCED(dqp->q_mount); | |
181 | } | |
182 | ASSERT(0); | |
183 | return false; | |
184 | } | |
185 | ||
dc06f398 BF |
186 | /* |
187 | * Check whether a dquot is under low free space conditions. We assume the quota | |
188 | * is enabled and enforced. | |
189 | */ | |
190 | static inline bool xfs_dquot_lowsp(struct xfs_dquot *dqp) | |
191 | { | |
192 | int64_t freesp; | |
193 | ||
d3537cf9 | 194 | freesp = dqp->q_blk.hardlimit - dqp->q_blk.reserved; |
dc06f398 BF |
195 | if (freesp < dqp->q_low_space[XFS_QLOWSP_1_PCNT]) |
196 | return true; | |
197 | ||
198 | return false; | |
199 | } | |
200 | ||
0b0fa1d1 DW |
201 | void xfs_dquot_to_disk(struct xfs_disk_dquot *ddqp, struct xfs_dquot *dqp); |
202 | ||
7201813b | 203 | #define XFS_DQ_IS_LOCKED(dqp) (mutex_is_locked(&((dqp)->q_qlock))) |
985a78fd | 204 | #define XFS_DQ_IS_DIRTY(dqp) ((dqp)->q_flags & XFS_DQFLAG_DIRTY) |
1da177e4 | 205 | |
aefe69a4 PR |
206 | void xfs_qm_dqdestroy(struct xfs_dquot *dqp); |
207 | int xfs_qm_dqflush(struct xfs_dquot *dqp, struct xfs_buf **bpp); | |
208 | void xfs_qm_dqunpin_wait(struct xfs_dquot *dqp); | |
c8c753e1 DW |
209 | void xfs_qm_adjust_dqtimers(struct xfs_dquot *d); |
210 | void xfs_qm_adjust_dqlimits(struct xfs_dquot *d); | |
211 | xfs_dqid_t xfs_qm_id_for_quotatype(struct xfs_inode *ip, | |
1a7ed271 | 212 | xfs_dqtype_t type); |
aefe69a4 | 213 | int xfs_qm_dqget(struct xfs_mount *mp, xfs_dqid_t id, |
1a7ed271 DW |
214 | xfs_dqtype_t type, bool can_alloc, |
215 | struct xfs_dquot **dqpp); | |
216 | int xfs_qm_dqget_inode(struct xfs_inode *ip, xfs_dqtype_t type, | |
217 | bool can_alloc, struct xfs_dquot **dqpp); | |
aefe69a4 | 218 | int xfs_qm_dqget_next(struct xfs_mount *mp, xfs_dqid_t id, |
1a7ed271 | 219 | xfs_dqtype_t type, struct xfs_dquot **dqpp); |
aefe69a4 | 220 | int xfs_qm_dqget_uncached(struct xfs_mount *mp, |
1a7ed271 DW |
221 | xfs_dqid_t id, xfs_dqtype_t type, |
222 | struct xfs_dquot **dqpp); | |
aefe69a4 | 223 | void xfs_qm_dqput(struct xfs_dquot *dqp); |
800b484e | 224 | |
aefe69a4 | 225 | void xfs_dqlock2(struct xfs_dquot *, struct xfs_dquot *); |
1da177e4 | 226 | |
aefe69a4 | 227 | void xfs_dquot_set_prealloc_limits(struct xfs_dquot *); |
b1366451 | 228 | |
78e55892 CH |
229 | static inline struct xfs_dquot *xfs_qm_dqhold(struct xfs_dquot *dqp) |
230 | { | |
231 | xfs_dqlock(dqp); | |
232 | dqp->q_nrefs++; | |
233 | xfs_dqunlock(dqp); | |
234 | return dqp; | |
235 | } | |
236 | ||
1a7ed271 DW |
237 | typedef int (*xfs_qm_dqiterate_fn)(struct xfs_dquot *dq, |
238 | xfs_dqtype_t type, void *priv); | |
239 | int xfs_qm_dqiterate(struct xfs_mount *mp, xfs_dqtype_t type, | |
554ba965 DW |
240 | xfs_qm_dqiterate_fn iter_fn, void *priv); |
241 | ||
11d8a919 | 242 | time64_t xfs_dquot_set_timeout(struct xfs_mount *mp, time64_t timeout); |
ccc8e771 | 243 | time64_t xfs_dquot_set_grace_period(time64_t grace); |
11d8a919 | 244 | |
1da177e4 | 245 | #endif /* __XFS_DQUOT_H__ */ |