Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.14 288 lines 7.8 kB view raw
1/* 2 * Copyright (c) 2000-2006 Silicon Graphics, Inc. 3 * Copyright (c) 2013 Red Hat, Inc. 4 * All Rights Reserved. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope that it would be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19#include "xfs.h" 20#include "xfs_fs.h" 21#include "xfs_shared.h" 22#include "xfs_format.h" 23#include "xfs_log_format.h" 24#include "xfs_trans_resv.h" 25#include "xfs_sb.h" 26#include "xfs_ag.h" 27#include "xfs_mount.h" 28#include "xfs_inode.h" 29#include "xfs_quota.h" 30#include "xfs_trans.h" 31#include "xfs_qm.h" 32#include "xfs_error.h" 33#include "xfs_cksum.h" 34#include "xfs_trace.h" 35 36int 37xfs_calc_dquots_per_chunk( 38 struct xfs_mount *mp, 39 unsigned int nbblks) /* basic block units */ 40{ 41 unsigned int ndquots; 42 43 ASSERT(nbblks > 0); 44 ndquots = BBTOB(nbblks); 45 do_div(ndquots, sizeof(xfs_dqblk_t)); 46 47 return ndquots; 48} 49 50/* 51 * Do some primitive error checking on ondisk dquot data structures. 52 */ 53int 54xfs_dqcheck( 55 struct xfs_mount *mp, 56 xfs_disk_dquot_t *ddq, 57 xfs_dqid_t id, 58 uint type, /* used only when IO_dorepair is true */ 59 uint flags, 60 char *str) 61{ 62 xfs_dqblk_t *d = (xfs_dqblk_t *)ddq; 63 int errs = 0; 64 65 /* 66 * We can encounter an uninitialized dquot buffer for 2 reasons: 67 * 1. If we crash while deleting the quotainode(s), and those blks got 68 * used for user data. This is because we take the path of regular 69 * file deletion; however, the size field of quotainodes is never 70 * updated, so all the tricks that we play in itruncate_finish 71 * don't quite matter. 72 * 73 * 2. We don't play the quota buffers when there's a quotaoff logitem. 74 * But the allocation will be replayed so we'll end up with an 75 * uninitialized quota block. 76 * 77 * This is all fine; things are still consistent, and we haven't lost 78 * any quota information. Just don't complain about bad dquot blks. 79 */ 80 if (ddq->d_magic != cpu_to_be16(XFS_DQUOT_MAGIC)) { 81 if (flags & XFS_QMOPT_DOWARN) 82 xfs_alert(mp, 83 "%s : XFS dquot ID 0x%x, magic 0x%x != 0x%x", 84 str, id, be16_to_cpu(ddq->d_magic), XFS_DQUOT_MAGIC); 85 errs++; 86 } 87 if (ddq->d_version != XFS_DQUOT_VERSION) { 88 if (flags & XFS_QMOPT_DOWARN) 89 xfs_alert(mp, 90 "%s : XFS dquot ID 0x%x, version 0x%x != 0x%x", 91 str, id, ddq->d_version, XFS_DQUOT_VERSION); 92 errs++; 93 } 94 95 if (ddq->d_flags != XFS_DQ_USER && 96 ddq->d_flags != XFS_DQ_PROJ && 97 ddq->d_flags != XFS_DQ_GROUP) { 98 if (flags & XFS_QMOPT_DOWARN) 99 xfs_alert(mp, 100 "%s : XFS dquot ID 0x%x, unknown flags 0x%x", 101 str, id, ddq->d_flags); 102 errs++; 103 } 104 105 if (id != -1 && id != be32_to_cpu(ddq->d_id)) { 106 if (flags & XFS_QMOPT_DOWARN) 107 xfs_alert(mp, 108 "%s : ondisk-dquot 0x%p, ID mismatch: " 109 "0x%x expected, found id 0x%x", 110 str, ddq, id, be32_to_cpu(ddq->d_id)); 111 errs++; 112 } 113 114 if (!errs && ddq->d_id) { 115 if (ddq->d_blk_softlimit && 116 be64_to_cpu(ddq->d_bcount) > 117 be64_to_cpu(ddq->d_blk_softlimit)) { 118 if (!ddq->d_btimer) { 119 if (flags & XFS_QMOPT_DOWARN) 120 xfs_alert(mp, 121 "%s : Dquot ID 0x%x (0x%p) BLK TIMER NOT STARTED", 122 str, (int)be32_to_cpu(ddq->d_id), ddq); 123 errs++; 124 } 125 } 126 if (ddq->d_ino_softlimit && 127 be64_to_cpu(ddq->d_icount) > 128 be64_to_cpu(ddq->d_ino_softlimit)) { 129 if (!ddq->d_itimer) { 130 if (flags & XFS_QMOPT_DOWARN) 131 xfs_alert(mp, 132 "%s : Dquot ID 0x%x (0x%p) INODE TIMER NOT STARTED", 133 str, (int)be32_to_cpu(ddq->d_id), ddq); 134 errs++; 135 } 136 } 137 if (ddq->d_rtb_softlimit && 138 be64_to_cpu(ddq->d_rtbcount) > 139 be64_to_cpu(ddq->d_rtb_softlimit)) { 140 if (!ddq->d_rtbtimer) { 141 if (flags & XFS_QMOPT_DOWARN) 142 xfs_alert(mp, 143 "%s : Dquot ID 0x%x (0x%p) RTBLK TIMER NOT STARTED", 144 str, (int)be32_to_cpu(ddq->d_id), ddq); 145 errs++; 146 } 147 } 148 } 149 150 if (!errs || !(flags & XFS_QMOPT_DQREPAIR)) 151 return errs; 152 153 if (flags & XFS_QMOPT_DOWARN) 154 xfs_notice(mp, "Re-initializing dquot ID 0x%x", id); 155 156 /* 157 * Typically, a repair is only requested by quotacheck. 158 */ 159 ASSERT(id != -1); 160 ASSERT(flags & XFS_QMOPT_DQREPAIR); 161 memset(d, 0, sizeof(xfs_dqblk_t)); 162 163 d->dd_diskdq.d_magic = cpu_to_be16(XFS_DQUOT_MAGIC); 164 d->dd_diskdq.d_version = XFS_DQUOT_VERSION; 165 d->dd_diskdq.d_flags = type; 166 d->dd_diskdq.d_id = cpu_to_be32(id); 167 168 if (xfs_sb_version_hascrc(&mp->m_sb)) { 169 uuid_copy(&d->dd_uuid, &mp->m_sb.sb_uuid); 170 xfs_update_cksum((char *)d, sizeof(struct xfs_dqblk), 171 XFS_DQUOT_CRC_OFF); 172 } 173 174 return errs; 175} 176 177STATIC bool 178xfs_dquot_buf_verify_crc( 179 struct xfs_mount *mp, 180 struct xfs_buf *bp) 181{ 182 struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr; 183 int ndquots; 184 int i; 185 186 if (!xfs_sb_version_hascrc(&mp->m_sb)) 187 return true; 188 189 /* 190 * if we are in log recovery, the quota subsystem has not been 191 * initialised so we have no quotainfo structure. In that case, we need 192 * to manually calculate the number of dquots in the buffer. 193 */ 194 if (mp->m_quotainfo) 195 ndquots = mp->m_quotainfo->qi_dqperchunk; 196 else 197 ndquots = xfs_calc_dquots_per_chunk(mp, 198 XFS_BB_TO_FSB(mp, bp->b_length)); 199 200 for (i = 0; i < ndquots; i++, d++) { 201 if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk), 202 XFS_DQUOT_CRC_OFF)) 203 return false; 204 if (!uuid_equal(&d->dd_uuid, &mp->m_sb.sb_uuid)) 205 return false; 206 } 207 return true; 208} 209 210STATIC bool 211xfs_dquot_buf_verify( 212 struct xfs_mount *mp, 213 struct xfs_buf *bp) 214{ 215 struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr; 216 xfs_dqid_t id = 0; 217 int ndquots; 218 int i; 219 220 /* 221 * if we are in log recovery, the quota subsystem has not been 222 * initialised so we have no quotainfo structure. In that case, we need 223 * to manually calculate the number of dquots in the buffer. 224 */ 225 if (mp->m_quotainfo) 226 ndquots = mp->m_quotainfo->qi_dqperchunk; 227 else 228 ndquots = xfs_calc_dquots_per_chunk(mp, bp->b_length); 229 230 /* 231 * On the first read of the buffer, verify that each dquot is valid. 232 * We don't know what the id of the dquot is supposed to be, just that 233 * they should be increasing monotonically within the buffer. If the 234 * first id is corrupt, then it will fail on the second dquot in the 235 * buffer so corruptions could point to the wrong dquot in this case. 236 */ 237 for (i = 0; i < ndquots; i++) { 238 struct xfs_disk_dquot *ddq; 239 int error; 240 241 ddq = &d[i].dd_diskdq; 242 243 if (i == 0) 244 id = be32_to_cpu(ddq->d_id); 245 246 error = xfs_dqcheck(mp, ddq, id + i, 0, XFS_QMOPT_DOWARN, 247 "xfs_dquot_buf_verify"); 248 if (error) 249 return false; 250 } 251 return true; 252} 253 254static void 255xfs_dquot_buf_read_verify( 256 struct xfs_buf *bp) 257{ 258 struct xfs_mount *mp = bp->b_target->bt_mount; 259 260 if (!xfs_dquot_buf_verify_crc(mp, bp) || !xfs_dquot_buf_verify(mp, bp)) { 261 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); 262 xfs_buf_ioerror(bp, EFSCORRUPTED); 263 } 264} 265 266/* 267 * we don't calculate the CRC here as that is done when the dquot is flushed to 268 * the buffer after the update is done. This ensures that the dquot in the 269 * buffer always has an up-to-date CRC value. 270 */ 271static void 272xfs_dquot_buf_write_verify( 273 struct xfs_buf *bp) 274{ 275 struct xfs_mount *mp = bp->b_target->bt_mount; 276 277 if (!xfs_dquot_buf_verify(mp, bp)) { 278 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr); 279 xfs_buf_ioerror(bp, EFSCORRUPTED); 280 return; 281 } 282} 283 284const struct xfs_buf_ops xfs_dquot_buf_ops = { 285 .verify_read = xfs_dquot_buf_read_verify, 286 .verify_write = xfs_dquot_buf_write_verify, 287}; 288