| .. | .. |
|---|
| 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; |
|---|