.. | .. |
---|
14 | 14 | #include "xfs_defer.h" |
---|
15 | 15 | #include "xfs_inode.h" |
---|
16 | 16 | #include "xfs_bmap.h" |
---|
17 | | -#include "xfs_bmap_util.h" |
---|
18 | | -#include "xfs_alloc.h" |
---|
19 | 17 | #include "xfs_quota.h" |
---|
20 | | -#include "xfs_error.h" |
---|
21 | 18 | #include "xfs_trans.h" |
---|
22 | 19 | #include "xfs_buf_item.h" |
---|
23 | 20 | #include "xfs_trans_space.h" |
---|
24 | 21 | #include "xfs_trans_priv.h" |
---|
25 | 22 | #include "xfs_qm.h" |
---|
26 | | -#include "xfs_cksum.h" |
---|
27 | 23 | #include "xfs_trace.h" |
---|
28 | 24 | #include "xfs_log.h" |
---|
29 | 25 | #include "xfs_bmap_btree.h" |
---|
| 26 | +#include "xfs_error.h" |
---|
30 | 27 | |
---|
31 | 28 | /* |
---|
32 | 29 | * Lock order: |
---|
.. | .. |
---|
52 | 49 | */ |
---|
53 | 50 | void |
---|
54 | 51 | xfs_qm_dqdestroy( |
---|
55 | | - xfs_dquot_t *dqp) |
---|
| 52 | + struct xfs_dquot *dqp) |
---|
56 | 53 | { |
---|
57 | 54 | ASSERT(list_empty(&dqp->q_lru)); |
---|
58 | 55 | |
---|
.. | .. |
---|
60 | 57 | mutex_destroy(&dqp->q_qlock); |
---|
61 | 58 | |
---|
62 | 59 | XFS_STATS_DEC(dqp->q_mount, xs_qm_dquot); |
---|
63 | | - kmem_zone_free(xfs_qm_dqzone, dqp); |
---|
| 60 | + kmem_cache_free(xfs_qm_dqzone, dqp); |
---|
64 | 61 | } |
---|
65 | 62 | |
---|
66 | 63 | /* |
---|
.. | .. |
---|
70 | 67 | */ |
---|
71 | 68 | void |
---|
72 | 69 | xfs_qm_adjust_dqlimits( |
---|
73 | | - struct xfs_mount *mp, |
---|
74 | 70 | struct xfs_dquot *dq) |
---|
75 | 71 | { |
---|
| 72 | + struct xfs_mount *mp = dq->q_mount; |
---|
76 | 73 | struct xfs_quotainfo *q = mp->m_quotainfo; |
---|
77 | | - struct xfs_disk_dquot *d = &dq->q_core; |
---|
78 | 74 | struct xfs_def_quota *defq; |
---|
79 | 75 | int prealloc = 0; |
---|
80 | 76 | |
---|
81 | | - ASSERT(d->d_id); |
---|
82 | | - defq = xfs_get_defquota(dq, q); |
---|
| 77 | + ASSERT(dq->q_id); |
---|
| 78 | + defq = xfs_get_defquota(q, xfs_dquot_type(dq)); |
---|
83 | 79 | |
---|
84 | | - if (defq->bsoftlimit && !d->d_blk_softlimit) { |
---|
85 | | - d->d_blk_softlimit = cpu_to_be64(defq->bsoftlimit); |
---|
| 80 | + if (!dq->q_blk.softlimit) { |
---|
| 81 | + dq->q_blk.softlimit = defq->blk.soft; |
---|
86 | 82 | prealloc = 1; |
---|
87 | 83 | } |
---|
88 | | - if (defq->bhardlimit && !d->d_blk_hardlimit) { |
---|
89 | | - d->d_blk_hardlimit = cpu_to_be64(defq->bhardlimit); |
---|
| 84 | + if (!dq->q_blk.hardlimit) { |
---|
| 85 | + dq->q_blk.hardlimit = defq->blk.hard; |
---|
90 | 86 | prealloc = 1; |
---|
91 | 87 | } |
---|
92 | | - if (defq->isoftlimit && !d->d_ino_softlimit) |
---|
93 | | - d->d_ino_softlimit = cpu_to_be64(defq->isoftlimit); |
---|
94 | | - if (defq->ihardlimit && !d->d_ino_hardlimit) |
---|
95 | | - d->d_ino_hardlimit = cpu_to_be64(defq->ihardlimit); |
---|
96 | | - if (defq->rtbsoftlimit && !d->d_rtb_softlimit) |
---|
97 | | - d->d_rtb_softlimit = cpu_to_be64(defq->rtbsoftlimit); |
---|
98 | | - if (defq->rtbhardlimit && !d->d_rtb_hardlimit) |
---|
99 | | - d->d_rtb_hardlimit = cpu_to_be64(defq->rtbhardlimit); |
---|
| 88 | + if (!dq->q_ino.softlimit) |
---|
| 89 | + dq->q_ino.softlimit = defq->ino.soft; |
---|
| 90 | + if (!dq->q_ino.hardlimit) |
---|
| 91 | + dq->q_ino.hardlimit = defq->ino.hard; |
---|
| 92 | + if (!dq->q_rtb.softlimit) |
---|
| 93 | + dq->q_rtb.softlimit = defq->rtb.soft; |
---|
| 94 | + if (!dq->q_rtb.hardlimit) |
---|
| 95 | + dq->q_rtb.hardlimit = defq->rtb.hard; |
---|
100 | 96 | |
---|
101 | 97 | if (prealloc) |
---|
102 | 98 | xfs_dquot_set_prealloc_limits(dq); |
---|
| 99 | +} |
---|
| 100 | + |
---|
| 101 | +/* Set the expiration time of a quota's grace period. */ |
---|
| 102 | +time64_t |
---|
| 103 | +xfs_dquot_set_timeout( |
---|
| 104 | + struct xfs_mount *mp, |
---|
| 105 | + time64_t timeout) |
---|
| 106 | +{ |
---|
| 107 | + struct xfs_quotainfo *qi = mp->m_quotainfo; |
---|
| 108 | + |
---|
| 109 | + return clamp_t(time64_t, timeout, qi->qi_expiry_min, |
---|
| 110 | + qi->qi_expiry_max); |
---|
| 111 | +} |
---|
| 112 | + |
---|
| 113 | +/* Set the length of the default grace period. */ |
---|
| 114 | +time64_t |
---|
| 115 | +xfs_dquot_set_grace_period( |
---|
| 116 | + time64_t grace) |
---|
| 117 | +{ |
---|
| 118 | + return clamp_t(time64_t, grace, XFS_DQ_GRACE_MIN, XFS_DQ_GRACE_MAX); |
---|
| 119 | +} |
---|
| 120 | + |
---|
| 121 | +/* |
---|
| 122 | + * Determine if this quota counter is over either limit and set the quota |
---|
| 123 | + * timers as appropriate. |
---|
| 124 | + */ |
---|
| 125 | +static inline void |
---|
| 126 | +xfs_qm_adjust_res_timer( |
---|
| 127 | + struct xfs_mount *mp, |
---|
| 128 | + struct xfs_dquot_res *res, |
---|
| 129 | + struct xfs_quota_limits *qlim) |
---|
| 130 | +{ |
---|
| 131 | + ASSERT(res->hardlimit == 0 || res->softlimit <= res->hardlimit); |
---|
| 132 | + |
---|
| 133 | + if ((res->softlimit && res->count > res->softlimit) || |
---|
| 134 | + (res->hardlimit && res->count > res->hardlimit)) { |
---|
| 135 | + if (res->timer == 0) |
---|
| 136 | + res->timer = xfs_dquot_set_timeout(mp, |
---|
| 137 | + ktime_get_real_seconds() + qlim->time); |
---|
| 138 | + } else { |
---|
| 139 | + if (res->timer == 0) |
---|
| 140 | + res->warnings = 0; |
---|
| 141 | + else |
---|
| 142 | + res->timer = 0; |
---|
| 143 | + } |
---|
103 | 144 | } |
---|
104 | 145 | |
---|
105 | 146 | /* |
---|
.. | .. |
---|
117 | 158 | */ |
---|
118 | 159 | void |
---|
119 | 160 | xfs_qm_adjust_dqtimers( |
---|
120 | | - xfs_mount_t *mp, |
---|
121 | | - xfs_disk_dquot_t *d) |
---|
| 161 | + struct xfs_dquot *dq) |
---|
122 | 162 | { |
---|
123 | | - ASSERT(d->d_id); |
---|
| 163 | + struct xfs_mount *mp = dq->q_mount; |
---|
| 164 | + struct xfs_quotainfo *qi = mp->m_quotainfo; |
---|
| 165 | + struct xfs_def_quota *defq; |
---|
124 | 166 | |
---|
125 | | -#ifdef DEBUG |
---|
126 | | - if (d->d_blk_hardlimit) |
---|
127 | | - ASSERT(be64_to_cpu(d->d_blk_softlimit) <= |
---|
128 | | - be64_to_cpu(d->d_blk_hardlimit)); |
---|
129 | | - if (d->d_ino_hardlimit) |
---|
130 | | - ASSERT(be64_to_cpu(d->d_ino_softlimit) <= |
---|
131 | | - be64_to_cpu(d->d_ino_hardlimit)); |
---|
132 | | - if (d->d_rtb_hardlimit) |
---|
133 | | - ASSERT(be64_to_cpu(d->d_rtb_softlimit) <= |
---|
134 | | - be64_to_cpu(d->d_rtb_hardlimit)); |
---|
135 | | -#endif |
---|
| 167 | + ASSERT(dq->q_id); |
---|
| 168 | + defq = xfs_get_defquota(qi, xfs_dquot_type(dq)); |
---|
136 | 169 | |
---|
137 | | - if (!d->d_btimer) { |
---|
138 | | - if ((d->d_blk_softlimit && |
---|
139 | | - (be64_to_cpu(d->d_bcount) > |
---|
140 | | - be64_to_cpu(d->d_blk_softlimit))) || |
---|
141 | | - (d->d_blk_hardlimit && |
---|
142 | | - (be64_to_cpu(d->d_bcount) > |
---|
143 | | - be64_to_cpu(d->d_blk_hardlimit)))) { |
---|
144 | | - d->d_btimer = cpu_to_be32(get_seconds() + |
---|
145 | | - mp->m_quotainfo->qi_btimelimit); |
---|
146 | | - } else { |
---|
147 | | - d->d_bwarns = 0; |
---|
148 | | - } |
---|
149 | | - } else { |
---|
150 | | - if ((!d->d_blk_softlimit || |
---|
151 | | - (be64_to_cpu(d->d_bcount) <= |
---|
152 | | - be64_to_cpu(d->d_blk_softlimit))) && |
---|
153 | | - (!d->d_blk_hardlimit || |
---|
154 | | - (be64_to_cpu(d->d_bcount) <= |
---|
155 | | - be64_to_cpu(d->d_blk_hardlimit)))) { |
---|
156 | | - d->d_btimer = 0; |
---|
157 | | - } |
---|
158 | | - } |
---|
159 | | - |
---|
160 | | - if (!d->d_itimer) { |
---|
161 | | - if ((d->d_ino_softlimit && |
---|
162 | | - (be64_to_cpu(d->d_icount) > |
---|
163 | | - be64_to_cpu(d->d_ino_softlimit))) || |
---|
164 | | - (d->d_ino_hardlimit && |
---|
165 | | - (be64_to_cpu(d->d_icount) > |
---|
166 | | - be64_to_cpu(d->d_ino_hardlimit)))) { |
---|
167 | | - d->d_itimer = cpu_to_be32(get_seconds() + |
---|
168 | | - mp->m_quotainfo->qi_itimelimit); |
---|
169 | | - } else { |
---|
170 | | - d->d_iwarns = 0; |
---|
171 | | - } |
---|
172 | | - } else { |
---|
173 | | - if ((!d->d_ino_softlimit || |
---|
174 | | - (be64_to_cpu(d->d_icount) <= |
---|
175 | | - be64_to_cpu(d->d_ino_softlimit))) && |
---|
176 | | - (!d->d_ino_hardlimit || |
---|
177 | | - (be64_to_cpu(d->d_icount) <= |
---|
178 | | - be64_to_cpu(d->d_ino_hardlimit)))) { |
---|
179 | | - d->d_itimer = 0; |
---|
180 | | - } |
---|
181 | | - } |
---|
182 | | - |
---|
183 | | - if (!d->d_rtbtimer) { |
---|
184 | | - if ((d->d_rtb_softlimit && |
---|
185 | | - (be64_to_cpu(d->d_rtbcount) > |
---|
186 | | - be64_to_cpu(d->d_rtb_softlimit))) || |
---|
187 | | - (d->d_rtb_hardlimit && |
---|
188 | | - (be64_to_cpu(d->d_rtbcount) > |
---|
189 | | - be64_to_cpu(d->d_rtb_hardlimit)))) { |
---|
190 | | - d->d_rtbtimer = cpu_to_be32(get_seconds() + |
---|
191 | | - mp->m_quotainfo->qi_rtbtimelimit); |
---|
192 | | - } else { |
---|
193 | | - d->d_rtbwarns = 0; |
---|
194 | | - } |
---|
195 | | - } else { |
---|
196 | | - if ((!d->d_rtb_softlimit || |
---|
197 | | - (be64_to_cpu(d->d_rtbcount) <= |
---|
198 | | - be64_to_cpu(d->d_rtb_softlimit))) && |
---|
199 | | - (!d->d_rtb_hardlimit || |
---|
200 | | - (be64_to_cpu(d->d_rtbcount) <= |
---|
201 | | - be64_to_cpu(d->d_rtb_hardlimit)))) { |
---|
202 | | - d->d_rtbtimer = 0; |
---|
203 | | - } |
---|
204 | | - } |
---|
| 170 | + xfs_qm_adjust_res_timer(dq->q_mount, &dq->q_blk, &defq->blk); |
---|
| 171 | + xfs_qm_adjust_res_timer(dq->q_mount, &dq->q_ino, &defq->ino); |
---|
| 172 | + xfs_qm_adjust_res_timer(dq->q_mount, &dq->q_rtb, &defq->rtb); |
---|
205 | 173 | } |
---|
206 | 174 | |
---|
207 | 175 | /* |
---|
.. | .. |
---|
209 | 177 | */ |
---|
210 | 178 | STATIC void |
---|
211 | 179 | xfs_qm_init_dquot_blk( |
---|
212 | | - xfs_trans_t *tp, |
---|
213 | | - xfs_mount_t *mp, |
---|
214 | | - xfs_dqid_t id, |
---|
215 | | - uint type, |
---|
216 | | - xfs_buf_t *bp) |
---|
| 180 | + struct xfs_trans *tp, |
---|
| 181 | + struct xfs_mount *mp, |
---|
| 182 | + xfs_dqid_t id, |
---|
| 183 | + xfs_dqtype_t type, |
---|
| 184 | + struct xfs_buf *bp) |
---|
217 | 185 | { |
---|
218 | 186 | struct xfs_quotainfo *q = mp->m_quotainfo; |
---|
219 | | - xfs_dqblk_t *d; |
---|
220 | | - xfs_dqid_t curid; |
---|
221 | | - int i; |
---|
| 187 | + struct xfs_dqblk *d; |
---|
| 188 | + xfs_dqid_t curid; |
---|
| 189 | + unsigned int qflag; |
---|
| 190 | + unsigned int blftype; |
---|
| 191 | + int i; |
---|
222 | 192 | |
---|
223 | 193 | ASSERT(tp); |
---|
224 | 194 | ASSERT(xfs_buf_islocked(bp)); |
---|
| 195 | + |
---|
| 196 | + switch (type) { |
---|
| 197 | + case XFS_DQTYPE_USER: |
---|
| 198 | + qflag = XFS_UQUOTA_CHKD; |
---|
| 199 | + blftype = XFS_BLF_UDQUOT_BUF; |
---|
| 200 | + break; |
---|
| 201 | + case XFS_DQTYPE_PROJ: |
---|
| 202 | + qflag = XFS_PQUOTA_CHKD; |
---|
| 203 | + blftype = XFS_BLF_PDQUOT_BUF; |
---|
| 204 | + break; |
---|
| 205 | + case XFS_DQTYPE_GROUP: |
---|
| 206 | + qflag = XFS_GQUOTA_CHKD; |
---|
| 207 | + blftype = XFS_BLF_GDQUOT_BUF; |
---|
| 208 | + break; |
---|
| 209 | + default: |
---|
| 210 | + ASSERT(0); |
---|
| 211 | + return; |
---|
| 212 | + } |
---|
225 | 213 | |
---|
226 | 214 | d = bp->b_addr; |
---|
227 | 215 | |
---|
.. | .. |
---|
234 | 222 | d->dd_diskdq.d_magic = cpu_to_be16(XFS_DQUOT_MAGIC); |
---|
235 | 223 | d->dd_diskdq.d_version = XFS_DQUOT_VERSION; |
---|
236 | 224 | d->dd_diskdq.d_id = cpu_to_be32(curid); |
---|
237 | | - d->dd_diskdq.d_flags = type; |
---|
| 225 | + d->dd_diskdq.d_type = type; |
---|
| 226 | + if (curid > 0 && xfs_sb_version_hasbigtime(&mp->m_sb)) |
---|
| 227 | + d->dd_diskdq.d_type |= XFS_DQTYPE_BIGTIME; |
---|
238 | 228 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
---|
239 | 229 | uuid_copy(&d->dd_uuid, &mp->m_sb.sb_meta_uuid); |
---|
240 | 230 | xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk), |
---|
.. | .. |
---|
242 | 232 | } |
---|
243 | 233 | } |
---|
244 | 234 | |
---|
245 | | - xfs_trans_dquot_buf(tp, bp, |
---|
246 | | - (type & XFS_DQ_USER ? XFS_BLF_UDQUOT_BUF : |
---|
247 | | - ((type & XFS_DQ_PROJ) ? XFS_BLF_PDQUOT_BUF : |
---|
248 | | - XFS_BLF_GDQUOT_BUF))); |
---|
249 | | - xfs_trans_log_buf(tp, bp, 0, BBTOB(q->qi_dqchunklen) - 1); |
---|
| 235 | + xfs_trans_dquot_buf(tp, bp, blftype); |
---|
| 236 | + |
---|
| 237 | + /* |
---|
| 238 | + * quotacheck uses delayed writes to update all the dquots on disk in an |
---|
| 239 | + * efficient manner instead of logging the individual dquot changes as |
---|
| 240 | + * they are made. However if we log the buffer allocated here and crash |
---|
| 241 | + * after quotacheck while the logged initialisation is still in the |
---|
| 242 | + * active region of the log, log recovery can replay the dquot buffer |
---|
| 243 | + * initialisation over the top of the checked dquots and corrupt quota |
---|
| 244 | + * accounting. |
---|
| 245 | + * |
---|
| 246 | + * To avoid this problem, quotacheck cannot log the initialised buffer. |
---|
| 247 | + * We must still dirty the buffer and write it back before the |
---|
| 248 | + * allocation transaction clears the log. Therefore, mark the buffer as |
---|
| 249 | + * ordered instead of logging it directly. This is safe for quotacheck |
---|
| 250 | + * because it detects and repairs allocated but initialized dquot blocks |
---|
| 251 | + * in the quota inodes. |
---|
| 252 | + */ |
---|
| 253 | + if (!(mp->m_qflags & qflag)) |
---|
| 254 | + xfs_trans_ordered_buf(tp, bp); |
---|
| 255 | + else |
---|
| 256 | + xfs_trans_log_buf(tp, bp, 0, BBTOB(q->qi_dqchunklen) - 1); |
---|
250 | 257 | } |
---|
251 | 258 | |
---|
252 | 259 | /* |
---|
.. | .. |
---|
259 | 266 | { |
---|
260 | 267 | uint64_t space; |
---|
261 | 268 | |
---|
262 | | - dqp->q_prealloc_hi_wmark = be64_to_cpu(dqp->q_core.d_blk_hardlimit); |
---|
263 | | - dqp->q_prealloc_lo_wmark = be64_to_cpu(dqp->q_core.d_blk_softlimit); |
---|
| 269 | + dqp->q_prealloc_hi_wmark = dqp->q_blk.hardlimit; |
---|
| 270 | + dqp->q_prealloc_lo_wmark = dqp->q_blk.softlimit; |
---|
264 | 271 | if (!dqp->q_prealloc_lo_wmark) { |
---|
265 | 272 | dqp->q_prealloc_lo_wmark = dqp->q_prealloc_hi_wmark; |
---|
266 | 273 | do_div(dqp->q_prealloc_lo_wmark, 100); |
---|
.. | .. |
---|
290 | 297 | struct xfs_trans *tp = *tpp; |
---|
291 | 298 | struct xfs_mount *mp = tp->t_mountp; |
---|
292 | 299 | struct xfs_buf *bp; |
---|
293 | | - struct xfs_inode *quotip = xfs_quota_inode(mp, dqp->dq_flags); |
---|
| 300 | + xfs_dqtype_t qtype = xfs_dquot_type(dqp); |
---|
| 301 | + struct xfs_inode *quotip = xfs_quota_inode(mp, qtype); |
---|
294 | 302 | int nmaps = 1; |
---|
295 | 303 | int error; |
---|
296 | 304 | |
---|
297 | 305 | trace_xfs_dqalloc(dqp); |
---|
298 | 306 | |
---|
299 | 307 | xfs_ilock(quotip, XFS_ILOCK_EXCL); |
---|
300 | | - if (!xfs_this_quota_on(dqp->q_mount, dqp->dq_flags)) { |
---|
| 308 | + if (!xfs_this_quota_on(dqp->q_mount, qtype)) { |
---|
301 | 309 | /* |
---|
302 | 310 | * Return if this type of quotas is turned off while we didn't |
---|
303 | 311 | * have an inode lock |
---|
.. | .. |
---|
309 | 317 | /* Create the block mapping. */ |
---|
310 | 318 | xfs_trans_ijoin(tp, quotip, XFS_ILOCK_EXCL); |
---|
311 | 319 | error = xfs_bmapi_write(tp, quotip, dqp->q_fileoffset, |
---|
312 | | - XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA, |
---|
313 | | - XFS_QM_DQALLOC_SPACE_RES(mp), &map, &nmaps); |
---|
| 320 | + XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA, 0, &map, |
---|
| 321 | + &nmaps); |
---|
314 | 322 | if (error) |
---|
315 | 323 | return error; |
---|
316 | 324 | ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB); |
---|
.. | .. |
---|
324 | 332 | dqp->q_blkno = XFS_FSB_TO_DADDR(mp, map.br_startblock); |
---|
325 | 333 | |
---|
326 | 334 | /* now we can just get the buffer (there's nothing to read yet) */ |
---|
327 | | - bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, dqp->q_blkno, |
---|
328 | | - mp->m_quotainfo->qi_dqchunklen, 0); |
---|
329 | | - if (!bp) |
---|
330 | | - return -ENOMEM; |
---|
| 335 | + error = xfs_trans_get_buf(tp, mp->m_ddev_targp, dqp->q_blkno, |
---|
| 336 | + mp->m_quotainfo->qi_dqchunklen, 0, &bp); |
---|
| 337 | + if (error) |
---|
| 338 | + return error; |
---|
331 | 339 | bp->b_ops = &xfs_dquot_buf_ops; |
---|
332 | 340 | |
---|
333 | 341 | /* |
---|
334 | 342 | * Make a chunk of dquots out of this buffer and log |
---|
335 | 343 | * the entire thing. |
---|
336 | 344 | */ |
---|
337 | | - xfs_qm_init_dquot_blk(tp, mp, be32_to_cpu(dqp->q_core.d_id), |
---|
338 | | - dqp->dq_flags & XFS_DQ_ALLTYPES, bp); |
---|
| 345 | + xfs_qm_init_dquot_blk(tp, mp, dqp->q_id, qtype, bp); |
---|
339 | 346 | xfs_buf_set_ref(bp, XFS_DQUOT_REF); |
---|
340 | 347 | |
---|
341 | 348 | /* |
---|
.. | .. |
---|
382 | 389 | { |
---|
383 | 390 | struct xfs_bmbt_irec map; |
---|
384 | 391 | struct xfs_buf *bp; |
---|
385 | | - struct xfs_inode *quotip = xfs_quota_inode(mp, dqp->dq_flags); |
---|
| 392 | + xfs_dqtype_t qtype = xfs_dquot_type(dqp); |
---|
| 393 | + struct xfs_inode *quotip = xfs_quota_inode(mp, qtype); |
---|
386 | 394 | uint lock_mode; |
---|
387 | 395 | int nmaps = 1; |
---|
388 | 396 | int error; |
---|
389 | 397 | |
---|
390 | 398 | lock_mode = xfs_ilock_data_map_shared(quotip); |
---|
391 | | - if (!xfs_this_quota_on(mp, dqp->dq_flags)) { |
---|
| 399 | + if (!xfs_this_quota_on(mp, qtype)) { |
---|
392 | 400 | /* |
---|
393 | 401 | * Return if this type of quotas is turned off while we |
---|
394 | 402 | * didn't have the quota inode lock. |
---|
.. | .. |
---|
440 | 448 | xfs_dquot_alloc( |
---|
441 | 449 | struct xfs_mount *mp, |
---|
442 | 450 | xfs_dqid_t id, |
---|
443 | | - uint type) |
---|
| 451 | + xfs_dqtype_t type) |
---|
444 | 452 | { |
---|
445 | 453 | struct xfs_dquot *dqp; |
---|
446 | 454 | |
---|
447 | | - dqp = kmem_zone_zalloc(xfs_qm_dqzone, KM_SLEEP); |
---|
| 455 | + dqp = kmem_cache_zalloc(xfs_qm_dqzone, GFP_KERNEL | __GFP_NOFAIL); |
---|
448 | 456 | |
---|
449 | | - dqp->dq_flags = type; |
---|
450 | | - dqp->q_core.d_id = cpu_to_be32(id); |
---|
| 457 | + dqp->q_type = type; |
---|
| 458 | + dqp->q_id = id; |
---|
451 | 459 | dqp->q_mount = mp; |
---|
452 | 460 | INIT_LIST_HEAD(&dqp->q_lru); |
---|
453 | 461 | mutex_init(&dqp->q_qlock); |
---|
.. | .. |
---|
472 | 480 | * quotas. |
---|
473 | 481 | */ |
---|
474 | 482 | switch (type) { |
---|
475 | | - case XFS_DQ_USER: |
---|
| 483 | + case XFS_DQTYPE_USER: |
---|
476 | 484 | /* uses the default lock class */ |
---|
477 | 485 | break; |
---|
478 | | - case XFS_DQ_GROUP: |
---|
| 486 | + case XFS_DQTYPE_GROUP: |
---|
479 | 487 | lockdep_set_class(&dqp->q_qlock, &xfs_dquot_group_class); |
---|
480 | 488 | break; |
---|
481 | | - case XFS_DQ_PROJ: |
---|
| 489 | + case XFS_DQTYPE_PROJ: |
---|
482 | 490 | lockdep_set_class(&dqp->q_qlock, &xfs_dquot_project_class); |
---|
483 | 491 | break; |
---|
484 | 492 | default: |
---|
.. | .. |
---|
492 | 500 | return dqp; |
---|
493 | 501 | } |
---|
494 | 502 | |
---|
| 503 | +/* Check the ondisk dquot's id and type match what the incore dquot expects. */ |
---|
| 504 | +static bool |
---|
| 505 | +xfs_dquot_check_type( |
---|
| 506 | + struct xfs_dquot *dqp, |
---|
| 507 | + struct xfs_disk_dquot *ddqp) |
---|
| 508 | +{ |
---|
| 509 | + uint8_t ddqp_type; |
---|
| 510 | + uint8_t dqp_type; |
---|
| 511 | + |
---|
| 512 | + ddqp_type = ddqp->d_type & XFS_DQTYPE_REC_MASK; |
---|
| 513 | + dqp_type = xfs_dquot_type(dqp); |
---|
| 514 | + |
---|
| 515 | + if (be32_to_cpu(ddqp->d_id) != dqp->q_id) |
---|
| 516 | + return false; |
---|
| 517 | + |
---|
| 518 | + /* |
---|
| 519 | + * V5 filesystems always expect an exact type match. V4 filesystems |
---|
| 520 | + * expect an exact match for user dquots and for non-root group and |
---|
| 521 | + * project dquots. |
---|
| 522 | + */ |
---|
| 523 | + if (xfs_sb_version_hascrc(&dqp->q_mount->m_sb) || |
---|
| 524 | + dqp_type == XFS_DQTYPE_USER || dqp->q_id != 0) |
---|
| 525 | + return ddqp_type == dqp_type; |
---|
| 526 | + |
---|
| 527 | + /* |
---|
| 528 | + * V4 filesystems support either group or project quotas, but not both |
---|
| 529 | + * at the same time. The non-user quota file can be switched between |
---|
| 530 | + * group and project quota uses depending on the mount options, which |
---|
| 531 | + * means that we can encounter the other type when we try to load quota |
---|
| 532 | + * defaults. Quotacheck will soon reset the the entire quota file |
---|
| 533 | + * (including the root dquot) anyway, but don't log scary corruption |
---|
| 534 | + * reports to dmesg. |
---|
| 535 | + */ |
---|
| 536 | + return ddqp_type == XFS_DQTYPE_GROUP || ddqp_type == XFS_DQTYPE_PROJ; |
---|
| 537 | +} |
---|
| 538 | + |
---|
495 | 539 | /* Copy the in-core quota fields in from the on-disk buffer. */ |
---|
496 | | -STATIC void |
---|
| 540 | +STATIC int |
---|
497 | 541 | xfs_dquot_from_disk( |
---|
498 | 542 | struct xfs_dquot *dqp, |
---|
499 | 543 | struct xfs_buf *bp) |
---|
500 | 544 | { |
---|
501 | 545 | struct xfs_disk_dquot *ddqp = bp->b_addr + dqp->q_bufoffset; |
---|
502 | 546 | |
---|
| 547 | + /* |
---|
| 548 | + * Ensure that we got the type and ID we were looking for. |
---|
| 549 | + * Everything else was checked by the dquot buffer verifier. |
---|
| 550 | + */ |
---|
| 551 | + if (!xfs_dquot_check_type(dqp, ddqp)) { |
---|
| 552 | + xfs_alert_tag(bp->b_mount, XFS_PTAG_VERIFIER_ERROR, |
---|
| 553 | + "Metadata corruption detected at %pS, quota %u", |
---|
| 554 | + __this_address, dqp->q_id); |
---|
| 555 | + xfs_alert(bp->b_mount, "Unmount and run xfs_repair"); |
---|
| 556 | + return -EFSCORRUPTED; |
---|
| 557 | + } |
---|
| 558 | + |
---|
503 | 559 | /* copy everything from disk dquot to the incore dquot */ |
---|
504 | | - memcpy(&dqp->q_core, ddqp, sizeof(xfs_disk_dquot_t)); |
---|
| 560 | + dqp->q_type = ddqp->d_type; |
---|
| 561 | + dqp->q_blk.hardlimit = be64_to_cpu(ddqp->d_blk_hardlimit); |
---|
| 562 | + dqp->q_blk.softlimit = be64_to_cpu(ddqp->d_blk_softlimit); |
---|
| 563 | + dqp->q_ino.hardlimit = be64_to_cpu(ddqp->d_ino_hardlimit); |
---|
| 564 | + dqp->q_ino.softlimit = be64_to_cpu(ddqp->d_ino_softlimit); |
---|
| 565 | + dqp->q_rtb.hardlimit = be64_to_cpu(ddqp->d_rtb_hardlimit); |
---|
| 566 | + dqp->q_rtb.softlimit = be64_to_cpu(ddqp->d_rtb_softlimit); |
---|
| 567 | + |
---|
| 568 | + dqp->q_blk.count = be64_to_cpu(ddqp->d_bcount); |
---|
| 569 | + dqp->q_ino.count = be64_to_cpu(ddqp->d_icount); |
---|
| 570 | + dqp->q_rtb.count = be64_to_cpu(ddqp->d_rtbcount); |
---|
| 571 | + |
---|
| 572 | + dqp->q_blk.warnings = be16_to_cpu(ddqp->d_bwarns); |
---|
| 573 | + dqp->q_ino.warnings = be16_to_cpu(ddqp->d_iwarns); |
---|
| 574 | + dqp->q_rtb.warnings = be16_to_cpu(ddqp->d_rtbwarns); |
---|
| 575 | + |
---|
| 576 | + dqp->q_blk.timer = xfs_dquot_from_disk_ts(ddqp, ddqp->d_btimer); |
---|
| 577 | + dqp->q_ino.timer = xfs_dquot_from_disk_ts(ddqp, ddqp->d_itimer); |
---|
| 578 | + dqp->q_rtb.timer = xfs_dquot_from_disk_ts(ddqp, ddqp->d_rtbtimer); |
---|
505 | 579 | |
---|
506 | 580 | /* |
---|
507 | 581 | * Reservation counters are defined as reservation plus current usage |
---|
508 | 582 | * to avoid having to add every time. |
---|
509 | 583 | */ |
---|
510 | | - dqp->q_res_bcount = be64_to_cpu(ddqp->d_bcount); |
---|
511 | | - dqp->q_res_icount = be64_to_cpu(ddqp->d_icount); |
---|
512 | | - dqp->q_res_rtbcount = be64_to_cpu(ddqp->d_rtbcount); |
---|
| 584 | + dqp->q_blk.reserved = dqp->q_blk.count; |
---|
| 585 | + dqp->q_ino.reserved = dqp->q_ino.count; |
---|
| 586 | + dqp->q_rtb.reserved = dqp->q_rtb.count; |
---|
513 | 587 | |
---|
514 | 588 | /* initialize the dquot speculative prealloc thresholds */ |
---|
515 | 589 | xfs_dquot_set_prealloc_limits(dqp); |
---|
| 590 | + return 0; |
---|
| 591 | +} |
---|
| 592 | + |
---|
| 593 | +/* Copy the in-core quota fields into the on-disk buffer. */ |
---|
| 594 | +void |
---|
| 595 | +xfs_dquot_to_disk( |
---|
| 596 | + struct xfs_disk_dquot *ddqp, |
---|
| 597 | + struct xfs_dquot *dqp) |
---|
| 598 | +{ |
---|
| 599 | + ddqp->d_magic = cpu_to_be16(XFS_DQUOT_MAGIC); |
---|
| 600 | + ddqp->d_version = XFS_DQUOT_VERSION; |
---|
| 601 | + ddqp->d_type = dqp->q_type; |
---|
| 602 | + ddqp->d_id = cpu_to_be32(dqp->q_id); |
---|
| 603 | + ddqp->d_pad0 = 0; |
---|
| 604 | + ddqp->d_pad = 0; |
---|
| 605 | + |
---|
| 606 | + ddqp->d_blk_hardlimit = cpu_to_be64(dqp->q_blk.hardlimit); |
---|
| 607 | + ddqp->d_blk_softlimit = cpu_to_be64(dqp->q_blk.softlimit); |
---|
| 608 | + ddqp->d_ino_hardlimit = cpu_to_be64(dqp->q_ino.hardlimit); |
---|
| 609 | + ddqp->d_ino_softlimit = cpu_to_be64(dqp->q_ino.softlimit); |
---|
| 610 | + ddqp->d_rtb_hardlimit = cpu_to_be64(dqp->q_rtb.hardlimit); |
---|
| 611 | + ddqp->d_rtb_softlimit = cpu_to_be64(dqp->q_rtb.softlimit); |
---|
| 612 | + |
---|
| 613 | + ddqp->d_bcount = cpu_to_be64(dqp->q_blk.count); |
---|
| 614 | + ddqp->d_icount = cpu_to_be64(dqp->q_ino.count); |
---|
| 615 | + ddqp->d_rtbcount = cpu_to_be64(dqp->q_rtb.count); |
---|
| 616 | + |
---|
| 617 | + ddqp->d_bwarns = cpu_to_be16(dqp->q_blk.warnings); |
---|
| 618 | + ddqp->d_iwarns = cpu_to_be16(dqp->q_ino.warnings); |
---|
| 619 | + ddqp->d_rtbwarns = cpu_to_be16(dqp->q_rtb.warnings); |
---|
| 620 | + |
---|
| 621 | + ddqp->d_btimer = xfs_dquot_to_disk_ts(dqp, dqp->q_blk.timer); |
---|
| 622 | + ddqp->d_itimer = xfs_dquot_to_disk_ts(dqp, dqp->q_ino.timer); |
---|
| 623 | + ddqp->d_rtbtimer = xfs_dquot_to_disk_ts(dqp, dqp->q_rtb.timer); |
---|
516 | 624 | } |
---|
517 | 625 | |
---|
518 | 626 | /* Allocate and initialize the dquot buffer for this in-core dquot. */ |
---|
.. | .. |
---|
561 | 669 | xfs_qm_dqread( |
---|
562 | 670 | struct xfs_mount *mp, |
---|
563 | 671 | xfs_dqid_t id, |
---|
564 | | - uint type, |
---|
| 672 | + xfs_dqtype_t type, |
---|
565 | 673 | bool can_alloc, |
---|
566 | 674 | struct xfs_dquot **dqpp) |
---|
567 | 675 | { |
---|
.. | .. |
---|
586 | 694 | * further. |
---|
587 | 695 | */ |
---|
588 | 696 | ASSERT(xfs_buf_islocked(bp)); |
---|
589 | | - xfs_dquot_from_disk(dqp, bp); |
---|
590 | | - |
---|
| 697 | + error = xfs_dquot_from_disk(dqp, bp); |
---|
591 | 698 | xfs_buf_relse(bp); |
---|
| 699 | + if (error) |
---|
| 700 | + goto err; |
---|
| 701 | + |
---|
592 | 702 | *dqpp = dqp; |
---|
593 | 703 | return error; |
---|
594 | 704 | |
---|
.. | .. |
---|
607 | 717 | static int |
---|
608 | 718 | xfs_dq_get_next_id( |
---|
609 | 719 | struct xfs_mount *mp, |
---|
610 | | - uint type, |
---|
| 720 | + xfs_dqtype_t type, |
---|
611 | 721 | xfs_dqid_t *id) |
---|
612 | 722 | { |
---|
613 | 723 | struct xfs_inode *quotip = xfs_quota_inode(mp, type); |
---|
.. | .. |
---|
675 | 785 | } |
---|
676 | 786 | |
---|
677 | 787 | xfs_dqlock(dqp); |
---|
678 | | - if (dqp->dq_flags & XFS_DQ_FREEING) { |
---|
| 788 | + if (dqp->q_flags & XFS_DQFLAG_FREEING) { |
---|
679 | 789 | xfs_dqunlock(dqp); |
---|
680 | 790 | mutex_unlock(&qi->qi_tree_lock); |
---|
681 | 791 | trace_xfs_dqget_freeing(dqp); |
---|
.. | .. |
---|
731 | 841 | static int |
---|
732 | 842 | xfs_qm_dqget_checks( |
---|
733 | 843 | struct xfs_mount *mp, |
---|
734 | | - uint type) |
---|
| 844 | + xfs_dqtype_t type) |
---|
735 | 845 | { |
---|
736 | 846 | if (WARN_ON_ONCE(!XFS_IS_QUOTA_RUNNING(mp))) |
---|
737 | 847 | return -ESRCH; |
---|
738 | 848 | |
---|
739 | 849 | switch (type) { |
---|
740 | | - case XFS_DQ_USER: |
---|
| 850 | + case XFS_DQTYPE_USER: |
---|
741 | 851 | if (!XFS_IS_UQUOTA_ON(mp)) |
---|
742 | 852 | return -ESRCH; |
---|
743 | 853 | return 0; |
---|
744 | | - case XFS_DQ_GROUP: |
---|
| 854 | + case XFS_DQTYPE_GROUP: |
---|
745 | 855 | if (!XFS_IS_GQUOTA_ON(mp)) |
---|
746 | 856 | return -ESRCH; |
---|
747 | 857 | return 0; |
---|
748 | | - case XFS_DQ_PROJ: |
---|
| 858 | + case XFS_DQTYPE_PROJ: |
---|
749 | 859 | if (!XFS_IS_PQUOTA_ON(mp)) |
---|
750 | 860 | return -ESRCH; |
---|
751 | 861 | return 0; |
---|
.. | .. |
---|
756 | 866 | } |
---|
757 | 867 | |
---|
758 | 868 | /* |
---|
759 | | - * Given the file system, id, and type (UDQUOT/GDQUOT), return a a locked |
---|
760 | | - * dquot, doing an allocation (if requested) as needed. |
---|
| 869 | + * Given the file system, id, and type (UDQUOT/GDQUOT/PDQUOT), return a |
---|
| 870 | + * locked dquot, doing an allocation (if requested) as needed. |
---|
761 | 871 | */ |
---|
762 | 872 | int |
---|
763 | 873 | xfs_qm_dqget( |
---|
764 | 874 | struct xfs_mount *mp, |
---|
765 | 875 | xfs_dqid_t id, |
---|
766 | | - uint type, |
---|
| 876 | + xfs_dqtype_t type, |
---|
767 | 877 | bool can_alloc, |
---|
768 | 878 | struct xfs_dquot **O_dqpp) |
---|
769 | 879 | { |
---|
.. | .. |
---|
813 | 923 | xfs_qm_dqget_uncached( |
---|
814 | 924 | struct xfs_mount *mp, |
---|
815 | 925 | xfs_dqid_t id, |
---|
816 | | - uint type, |
---|
| 926 | + xfs_dqtype_t type, |
---|
817 | 927 | struct xfs_dquot **dqpp) |
---|
818 | 928 | { |
---|
819 | 929 | int error; |
---|
.. | .. |
---|
829 | 939 | xfs_dqid_t |
---|
830 | 940 | xfs_qm_id_for_quotatype( |
---|
831 | 941 | struct xfs_inode *ip, |
---|
832 | | - uint type) |
---|
| 942 | + xfs_dqtype_t type) |
---|
833 | 943 | { |
---|
834 | 944 | switch (type) { |
---|
835 | | - case XFS_DQ_USER: |
---|
836 | | - return ip->i_d.di_uid; |
---|
837 | | - case XFS_DQ_GROUP: |
---|
838 | | - return ip->i_d.di_gid; |
---|
839 | | - case XFS_DQ_PROJ: |
---|
840 | | - return xfs_get_projid(ip); |
---|
| 945 | + case XFS_DQTYPE_USER: |
---|
| 946 | + return i_uid_read(VFS_I(ip)); |
---|
| 947 | + case XFS_DQTYPE_GROUP: |
---|
| 948 | + return i_gid_read(VFS_I(ip)); |
---|
| 949 | + case XFS_DQTYPE_PROJ: |
---|
| 950 | + return ip->i_d.di_projid; |
---|
841 | 951 | } |
---|
842 | 952 | ASSERT(0); |
---|
843 | 953 | return 0; |
---|
.. | .. |
---|
851 | 961 | int |
---|
852 | 962 | xfs_qm_dqget_inode( |
---|
853 | 963 | struct xfs_inode *ip, |
---|
854 | | - uint type, |
---|
| 964 | + xfs_dqtype_t type, |
---|
855 | 965 | bool can_alloc, |
---|
856 | 966 | struct xfs_dquot **O_dqpp) |
---|
857 | 967 | { |
---|
.. | .. |
---|
937 | 1047 | xfs_qm_dqget_next( |
---|
938 | 1048 | struct xfs_mount *mp, |
---|
939 | 1049 | xfs_dqid_t id, |
---|
940 | | - uint type, |
---|
| 1050 | + xfs_dqtype_t type, |
---|
941 | 1051 | struct xfs_dquot **dqpp) |
---|
942 | 1052 | { |
---|
943 | 1053 | struct xfs_dquot *dqp; |
---|
.. | .. |
---|
993 | 1103 | */ |
---|
994 | 1104 | void |
---|
995 | 1105 | xfs_qm_dqrele( |
---|
996 | | - xfs_dquot_t *dqp) |
---|
| 1106 | + struct xfs_dquot *dqp) |
---|
997 | 1107 | { |
---|
998 | 1108 | if (!dqp) |
---|
999 | 1109 | return; |
---|
.. | .. |
---|
1017 | 1127 | * from the AIL if it has not been re-logged, and unlocking the dquot's |
---|
1018 | 1128 | * flush lock. This behavior is very similar to that of inodes.. |
---|
1019 | 1129 | */ |
---|
1020 | | -STATIC void |
---|
| 1130 | +static void |
---|
1021 | 1131 | xfs_qm_dqflush_done( |
---|
1022 | | - struct xfs_buf *bp, |
---|
1023 | 1132 | struct xfs_log_item *lip) |
---|
1024 | 1133 | { |
---|
1025 | | - xfs_dq_logitem_t *qip = (struct xfs_dq_logitem *)lip; |
---|
1026 | | - xfs_dquot_t *dqp = qip->qli_dquot; |
---|
| 1134 | + struct xfs_dq_logitem *qip = (struct xfs_dq_logitem *)lip; |
---|
| 1135 | + struct xfs_dquot *dqp = qip->qli_dquot; |
---|
1027 | 1136 | struct xfs_ail *ailp = lip->li_ailp; |
---|
| 1137 | + xfs_lsn_t tail_lsn; |
---|
1028 | 1138 | |
---|
1029 | 1139 | /* |
---|
1030 | 1140 | * We only want to pull the item from the AIL if its |
---|
.. | .. |
---|
1038 | 1148 | ((lip->li_lsn == qip->qli_flush_lsn) || |
---|
1039 | 1149 | test_bit(XFS_LI_FAILED, &lip->li_flags))) { |
---|
1040 | 1150 | |
---|
1041 | | - /* xfs_trans_ail_delete() drops the AIL lock. */ |
---|
1042 | 1151 | spin_lock(&ailp->ail_lock); |
---|
| 1152 | + xfs_clear_li_failed(lip); |
---|
1043 | 1153 | if (lip->li_lsn == qip->qli_flush_lsn) { |
---|
1044 | | - xfs_trans_ail_delete(ailp, lip, SHUTDOWN_CORRUPT_INCORE); |
---|
| 1154 | + /* xfs_ail_update_finish() drops the AIL lock */ |
---|
| 1155 | + tail_lsn = xfs_ail_delete_one(ailp, lip); |
---|
| 1156 | + xfs_ail_update_finish(ailp, tail_lsn); |
---|
1045 | 1157 | } else { |
---|
1046 | | - /* |
---|
1047 | | - * Clear the failed state since we are about to drop the |
---|
1048 | | - * flush lock |
---|
1049 | | - */ |
---|
1050 | | - xfs_clear_li_failed(lip); |
---|
1051 | 1158 | spin_unlock(&ailp->ail_lock); |
---|
1052 | 1159 | } |
---|
1053 | 1160 | } |
---|
.. | .. |
---|
1056 | 1163 | * Release the dq's flush lock since we're done with it. |
---|
1057 | 1164 | */ |
---|
1058 | 1165 | xfs_dqfunlock(dqp); |
---|
| 1166 | +} |
---|
| 1167 | + |
---|
| 1168 | +void |
---|
| 1169 | +xfs_buf_dquot_iodone( |
---|
| 1170 | + struct xfs_buf *bp) |
---|
| 1171 | +{ |
---|
| 1172 | + struct xfs_log_item *lip, *n; |
---|
| 1173 | + |
---|
| 1174 | + list_for_each_entry_safe(lip, n, &bp->b_li_list, li_bio_list) { |
---|
| 1175 | + list_del_init(&lip->li_bio_list); |
---|
| 1176 | + xfs_qm_dqflush_done(lip); |
---|
| 1177 | + } |
---|
| 1178 | +} |
---|
| 1179 | + |
---|
| 1180 | +void |
---|
| 1181 | +xfs_buf_dquot_io_fail( |
---|
| 1182 | + struct xfs_buf *bp) |
---|
| 1183 | +{ |
---|
| 1184 | + struct xfs_log_item *lip; |
---|
| 1185 | + |
---|
| 1186 | + spin_lock(&bp->b_mount->m_ail->ail_lock); |
---|
| 1187 | + list_for_each_entry(lip, &bp->b_li_list, li_bio_list) |
---|
| 1188 | + xfs_set_li_failed(lip, bp); |
---|
| 1189 | + spin_unlock(&bp->b_mount->m_ail->ail_lock); |
---|
| 1190 | +} |
---|
| 1191 | + |
---|
| 1192 | +/* Check incore dquot for errors before we flush. */ |
---|
| 1193 | +static xfs_failaddr_t |
---|
| 1194 | +xfs_qm_dqflush_check( |
---|
| 1195 | + struct xfs_dquot *dqp) |
---|
| 1196 | +{ |
---|
| 1197 | + xfs_dqtype_t type = xfs_dquot_type(dqp); |
---|
| 1198 | + |
---|
| 1199 | + if (type != XFS_DQTYPE_USER && |
---|
| 1200 | + type != XFS_DQTYPE_GROUP && |
---|
| 1201 | + type != XFS_DQTYPE_PROJ) |
---|
| 1202 | + return __this_address; |
---|
| 1203 | + |
---|
| 1204 | + if (dqp->q_id == 0) |
---|
| 1205 | + return NULL; |
---|
| 1206 | + |
---|
| 1207 | + if (dqp->q_blk.softlimit && dqp->q_blk.count > dqp->q_blk.softlimit && |
---|
| 1208 | + !dqp->q_blk.timer) |
---|
| 1209 | + return __this_address; |
---|
| 1210 | + |
---|
| 1211 | + if (dqp->q_ino.softlimit && dqp->q_ino.count > dqp->q_ino.softlimit && |
---|
| 1212 | + !dqp->q_ino.timer) |
---|
| 1213 | + return __this_address; |
---|
| 1214 | + |
---|
| 1215 | + if (dqp->q_rtb.softlimit && dqp->q_rtb.count > dqp->q_rtb.softlimit && |
---|
| 1216 | + !dqp->q_rtb.timer) |
---|
| 1217 | + return __this_address; |
---|
| 1218 | + |
---|
| 1219 | + /* bigtime flag should never be set on root dquots */ |
---|
| 1220 | + if (dqp->q_type & XFS_DQTYPE_BIGTIME) { |
---|
| 1221 | + if (!xfs_sb_version_hasbigtime(&dqp->q_mount->m_sb)) |
---|
| 1222 | + return __this_address; |
---|
| 1223 | + if (dqp->q_id == 0) |
---|
| 1224 | + return __this_address; |
---|
| 1225 | + } |
---|
| 1226 | + |
---|
| 1227 | + return NULL; |
---|
1059 | 1228 | } |
---|
1060 | 1229 | |
---|
1061 | 1230 | /* |
---|
.. | .. |
---|
1072 | 1241 | struct xfs_buf **bpp) |
---|
1073 | 1242 | { |
---|
1074 | 1243 | struct xfs_mount *mp = dqp->q_mount; |
---|
| 1244 | + struct xfs_log_item *lip = &dqp->q_logitem.qli_item; |
---|
1075 | 1245 | struct xfs_buf *bp; |
---|
1076 | | - struct xfs_dqblk *dqb; |
---|
1077 | | - struct xfs_disk_dquot *ddqp; |
---|
| 1246 | + struct xfs_dqblk *dqblk; |
---|
1078 | 1247 | xfs_failaddr_t fa; |
---|
1079 | 1248 | int error; |
---|
1080 | 1249 | |
---|
.. | .. |
---|
1088 | 1257 | xfs_qm_dqunpin_wait(dqp); |
---|
1089 | 1258 | |
---|
1090 | 1259 | /* |
---|
1091 | | - * This may have been unpinned because the filesystem is shutting |
---|
1092 | | - * down forcibly. If that's the case we must not write this dquot |
---|
1093 | | - * to disk, because the log record didn't make it to disk. |
---|
1094 | | - * |
---|
1095 | | - * We also have to remove the log item from the AIL in this case, |
---|
1096 | | - * as we wait for an emptry AIL as part of the unmount process. |
---|
1097 | | - */ |
---|
1098 | | - if (XFS_FORCED_SHUTDOWN(mp)) { |
---|
1099 | | - struct xfs_log_item *lip = &dqp->q_logitem.qli_item; |
---|
1100 | | - dqp->dq_flags &= ~XFS_DQ_DIRTY; |
---|
1101 | | - |
---|
1102 | | - xfs_trans_ail_remove(lip, SHUTDOWN_CORRUPT_INCORE); |
---|
1103 | | - |
---|
1104 | | - error = -EIO; |
---|
1105 | | - goto out_unlock; |
---|
1106 | | - } |
---|
1107 | | - |
---|
1108 | | - /* |
---|
1109 | 1260 | * Get the buffer containing the on-disk dquot |
---|
1110 | 1261 | */ |
---|
1111 | 1262 | error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno, |
---|
1112 | | - mp->m_quotainfo->qi_dqchunklen, 0, &bp, |
---|
1113 | | - &xfs_dquot_buf_ops); |
---|
1114 | | - if (error) |
---|
| 1263 | + mp->m_quotainfo->qi_dqchunklen, XBF_TRYLOCK, |
---|
| 1264 | + &bp, &xfs_dquot_buf_ops); |
---|
| 1265 | + if (error == -EAGAIN) |
---|
1115 | 1266 | goto out_unlock; |
---|
| 1267 | + if (error) |
---|
| 1268 | + goto out_abort; |
---|
1116 | 1269 | |
---|
1117 | | - /* |
---|
1118 | | - * Calculate the location of the dquot inside the buffer. |
---|
1119 | | - */ |
---|
1120 | | - dqb = bp->b_addr + dqp->q_bufoffset; |
---|
1121 | | - ddqp = &dqb->dd_diskdq; |
---|
1122 | | - |
---|
1123 | | - /* sanity check the in-core structure before we flush */ |
---|
1124 | | - fa = xfs_dquot_verify(mp, &dqp->q_core, be32_to_cpu(dqp->q_core.d_id), |
---|
1125 | | - 0); |
---|
| 1270 | + fa = xfs_qm_dqflush_check(dqp); |
---|
1126 | 1271 | if (fa) { |
---|
1127 | 1272 | xfs_alert(mp, "corrupt dquot ID 0x%x in memory at %pS", |
---|
1128 | | - be32_to_cpu(dqp->q_core.d_id), fa); |
---|
| 1273 | + dqp->q_id, fa); |
---|
1129 | 1274 | xfs_buf_relse(bp); |
---|
1130 | | - xfs_dqfunlock(dqp); |
---|
1131 | | - xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); |
---|
1132 | | - return -EIO; |
---|
| 1275 | + error = -EFSCORRUPTED; |
---|
| 1276 | + goto out_abort; |
---|
1133 | 1277 | } |
---|
1134 | 1278 | |
---|
1135 | | - /* This is the only portion of data that needs to persist */ |
---|
1136 | | - memcpy(ddqp, &dqp->q_core, sizeof(xfs_disk_dquot_t)); |
---|
| 1279 | + /* Flush the incore dquot to the ondisk buffer. */ |
---|
| 1280 | + dqblk = bp->b_addr + dqp->q_bufoffset; |
---|
| 1281 | + xfs_dquot_to_disk(&dqblk->dd_diskdq, dqp); |
---|
1137 | 1282 | |
---|
1138 | 1283 | /* |
---|
1139 | 1284 | * Clear the dirty field and remember the flush lsn for later use. |
---|
1140 | 1285 | */ |
---|
1141 | | - dqp->dq_flags &= ~XFS_DQ_DIRTY; |
---|
| 1286 | + dqp->q_flags &= ~XFS_DQFLAG_DIRTY; |
---|
1142 | 1287 | |
---|
1143 | 1288 | xfs_trans_ail_copy_lsn(mp->m_ail, &dqp->q_logitem.qli_flush_lsn, |
---|
1144 | 1289 | &dqp->q_logitem.qli_item.li_lsn); |
---|
.. | .. |
---|
1153 | 1298 | * of a dquot without an up-to-date CRC getting to disk. |
---|
1154 | 1299 | */ |
---|
1155 | 1300 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
---|
1156 | | - dqb->dd_lsn = cpu_to_be64(dqp->q_logitem.qli_item.li_lsn); |
---|
1157 | | - xfs_update_cksum((char *)dqb, sizeof(struct xfs_dqblk), |
---|
| 1301 | + dqblk->dd_lsn = cpu_to_be64(dqp->q_logitem.qli_item.li_lsn); |
---|
| 1302 | + xfs_update_cksum((char *)dqblk, sizeof(struct xfs_dqblk), |
---|
1158 | 1303 | XFS_DQUOT_CRC_OFF); |
---|
1159 | 1304 | } |
---|
1160 | 1305 | |
---|
1161 | 1306 | /* |
---|
1162 | | - * Attach an iodone routine so that we can remove this dquot from the |
---|
1163 | | - * AIL and release the flush lock once the dquot is synced to disk. |
---|
| 1307 | + * Attach the dquot to the buffer so that we can remove this dquot from |
---|
| 1308 | + * the AIL and release the flush lock once the dquot is synced to disk. |
---|
1164 | 1309 | */ |
---|
1165 | | - xfs_buf_attach_iodone(bp, xfs_qm_dqflush_done, |
---|
1166 | | - &dqp->q_logitem.qli_item); |
---|
| 1310 | + bp->b_flags |= _XBF_DQUOTS; |
---|
| 1311 | + list_add_tail(&dqp->q_logitem.qli_item.li_bio_list, &bp->b_li_list); |
---|
1167 | 1312 | |
---|
1168 | 1313 | /* |
---|
1169 | 1314 | * If the buffer is pinned then push on the log so we won't |
---|
.. | .. |
---|
1178 | 1323 | *bpp = bp; |
---|
1179 | 1324 | return 0; |
---|
1180 | 1325 | |
---|
| 1326 | +out_abort: |
---|
| 1327 | + dqp->q_flags &= ~XFS_DQFLAG_DIRTY; |
---|
| 1328 | + xfs_trans_ail_delete(lip, 0); |
---|
| 1329 | + xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); |
---|
1181 | 1330 | out_unlock: |
---|
1182 | 1331 | xfs_dqfunlock(dqp); |
---|
1183 | | - return -EIO; |
---|
| 1332 | + return error; |
---|
1184 | 1333 | } |
---|
1185 | 1334 | |
---|
1186 | 1335 | /* |
---|
.. | .. |
---|
1191 | 1340 | */ |
---|
1192 | 1341 | void |
---|
1193 | 1342 | xfs_dqlock2( |
---|
1194 | | - xfs_dquot_t *d1, |
---|
1195 | | - xfs_dquot_t *d2) |
---|
| 1343 | + struct xfs_dquot *d1, |
---|
| 1344 | + struct xfs_dquot *d2) |
---|
1196 | 1345 | { |
---|
1197 | 1346 | if (d1 && d2) { |
---|
1198 | 1347 | ASSERT(d1 != d2); |
---|
1199 | | - if (be32_to_cpu(d1->q_core.d_id) > |
---|
1200 | | - be32_to_cpu(d2->q_core.d_id)) { |
---|
| 1348 | + if (d1->q_id > d2->q_id) { |
---|
1201 | 1349 | mutex_lock(&d2->q_qlock); |
---|
1202 | 1350 | mutex_lock_nested(&d1->q_qlock, XFS_QLOCK_NESTED); |
---|
1203 | 1351 | } else { |
---|
.. | .. |
---|
1214 | 1362 | int __init |
---|
1215 | 1363 | xfs_qm_init(void) |
---|
1216 | 1364 | { |
---|
1217 | | - xfs_qm_dqzone = |
---|
1218 | | - kmem_zone_init(sizeof(struct xfs_dquot), "xfs_dquot"); |
---|
| 1365 | + xfs_qm_dqzone = kmem_cache_create("xfs_dquot", |
---|
| 1366 | + sizeof(struct xfs_dquot), |
---|
| 1367 | + 0, 0, NULL); |
---|
1219 | 1368 | if (!xfs_qm_dqzone) |
---|
1220 | 1369 | goto out; |
---|
1221 | 1370 | |
---|
1222 | | - xfs_qm_dqtrxzone = |
---|
1223 | | - kmem_zone_init(sizeof(struct xfs_dquot_acct), "xfs_dqtrx"); |
---|
| 1371 | + xfs_qm_dqtrxzone = kmem_cache_create("xfs_dqtrx", |
---|
| 1372 | + sizeof(struct xfs_dquot_acct), |
---|
| 1373 | + 0, 0, NULL); |
---|
1224 | 1374 | if (!xfs_qm_dqtrxzone) |
---|
1225 | 1375 | goto out_free_dqzone; |
---|
1226 | 1376 | |
---|
1227 | 1377 | return 0; |
---|
1228 | 1378 | |
---|
1229 | 1379 | out_free_dqzone: |
---|
1230 | | - kmem_zone_destroy(xfs_qm_dqzone); |
---|
| 1380 | + kmem_cache_destroy(xfs_qm_dqzone); |
---|
1231 | 1381 | out: |
---|
1232 | 1382 | return -ENOMEM; |
---|
1233 | 1383 | } |
---|
.. | .. |
---|
1235 | 1385 | void |
---|
1236 | 1386 | xfs_qm_exit(void) |
---|
1237 | 1387 | { |
---|
1238 | | - kmem_zone_destroy(xfs_qm_dqtrxzone); |
---|
1239 | | - kmem_zone_destroy(xfs_qm_dqzone); |
---|
| 1388 | + kmem_cache_destroy(xfs_qm_dqtrxzone); |
---|
| 1389 | + kmem_cache_destroy(xfs_qm_dqzone); |
---|
1240 | 1390 | } |
---|
1241 | 1391 | |
---|
1242 | 1392 | /* |
---|
1243 | 1393 | * Iterate every dquot of a particular type. The caller must ensure that the |
---|
1244 | 1394 | * particular quota type is active. iter_fn can return negative error codes, |
---|
1245 | | - * or XFS_BTREE_QUERY_RANGE_ABORT to indicate that it wants to stop iterating. |
---|
| 1395 | + * or -ECANCELED to indicate that it wants to stop iterating. |
---|
1246 | 1396 | */ |
---|
1247 | 1397 | int |
---|
1248 | 1398 | xfs_qm_dqiterate( |
---|
1249 | 1399 | struct xfs_mount *mp, |
---|
1250 | | - uint dqtype, |
---|
| 1400 | + xfs_dqtype_t type, |
---|
1251 | 1401 | xfs_qm_dqiterate_fn iter_fn, |
---|
1252 | 1402 | void *priv) |
---|
1253 | 1403 | { |
---|
.. | .. |
---|
1256 | 1406 | int error; |
---|
1257 | 1407 | |
---|
1258 | 1408 | do { |
---|
1259 | | - error = xfs_qm_dqget_next(mp, id, dqtype, &dq); |
---|
| 1409 | + error = xfs_qm_dqget_next(mp, id, type, &dq); |
---|
1260 | 1410 | if (error == -ENOENT) |
---|
1261 | 1411 | return 0; |
---|
1262 | 1412 | if (error) |
---|
1263 | 1413 | return error; |
---|
1264 | 1414 | |
---|
1265 | | - error = iter_fn(dq, dqtype, priv); |
---|
1266 | | - id = be32_to_cpu(dq->q_core.d_id); |
---|
| 1415 | + error = iter_fn(dq, type, priv); |
---|
| 1416 | + id = dq->q_id; |
---|
1267 | 1417 | xfs_qm_dqput(dq); |
---|
1268 | | - id++; |
---|
1269 | 1418 | } while (error == 0 && id != 0); |
---|
1270 | 1419 | |
---|
1271 | 1420 | return error; |
---|