aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_dir2_block.c
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2013-04-03 01:11:20 -0400
committerBen Myers <bpm@sgi.com>2013-04-27 12:51:56 -0400
commitf5f3d9b0161633e8943520e83df634ad540b3b7f (patch)
treebd1a014fd6472904e53d7680e5692b49431ca6ab /fs/xfs/xfs_dir2_block.c
parentf948dd76dde021c050c7c35720dc066a8b9a5e35 (diff)
xfs: add CRC checks to block format directory blocks
Now that directory buffers are made from a single struct xfs_buf, we can add CRC calculation and checking callbacks. While there, add all the fields to the on disk structures for future functionality such as d_type support, uuids, block numbers, owner inode, etc. To distinguish between the different on disk formats, change the magic numbers for the new format directory blocks. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Ben Myers <bpm@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_dir2_block.c')
-rw-r--r--fs/xfs/xfs_dir2_block.c132
1 files changed, 94 insertions, 38 deletions
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index 12afe07a91d7..79a3f1b2bc7d 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
3 * Copyright (c) 2013 Red Hat, Inc.
3 * All Rights Reserved. 4 * All Rights Reserved.
4 * 5 *
5 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -28,11 +29,13 @@
28#include "xfs_dinode.h" 29#include "xfs_dinode.h"
29#include "xfs_inode.h" 30#include "xfs_inode.h"
30#include "xfs_inode_item.h" 31#include "xfs_inode_item.h"
32#include "xfs_buf_item.h"
31#include "xfs_dir2.h" 33#include "xfs_dir2.h"
32#include "xfs_dir2_format.h" 34#include "xfs_dir2_format.h"
33#include "xfs_dir2_priv.h" 35#include "xfs_dir2_priv.h"
34#include "xfs_error.h" 36#include "xfs_error.h"
35#include "xfs_trace.h" 37#include "xfs_trace.h"
38#include "xfs_cksum.h"
36 39
37/* 40/*
38 * Local function prototypes. 41 * Local function prototypes.
@@ -56,44 +59,74 @@ xfs_dir_startup(void)
56 xfs_dir_hash_dotdot = xfs_da_hashname((unsigned char *)"..", 2); 59 xfs_dir_hash_dotdot = xfs_da_hashname((unsigned char *)"..", 2);
57} 60}
58 61
59static void 62static bool
60xfs_dir2_block_verify( 63xfs_dir3_block_verify(
61 struct xfs_buf *bp) 64 struct xfs_buf *bp)
62{ 65{
63 struct xfs_mount *mp = bp->b_target->bt_mount; 66 struct xfs_mount *mp = bp->b_target->bt_mount;
64 struct xfs_dir2_data_hdr *hdr = bp->b_addr; 67 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
65 int block_ok = 0; 68
66 69 if (xfs_sb_version_hascrc(&mp->m_sb)) {
67 block_ok = hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC); 70 if (hdr3->magic != cpu_to_be32(XFS_DIR3_BLOCK_MAGIC))
68 block_ok = block_ok && __xfs_dir2_data_check(NULL, bp) == 0; 71 return false;
69 72 if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_uuid))
70 if (!block_ok) { 73 return false;
71 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, hdr); 74 if (be64_to_cpu(hdr3->blkno) != bp->b_bn)
72 xfs_buf_ioerror(bp, EFSCORRUPTED); 75 return false;
76 } else {
77 if (hdr3->magic != cpu_to_be32(XFS_DIR2_BLOCK_MAGIC))
78 return false;
73 } 79 }
80 if (__xfs_dir2_data_check(NULL, bp))
81 return false;
82 return true;
74} 83}
75 84
76static void 85static void
77xfs_dir2_block_read_verify( 86xfs_dir3_block_read_verify(
78 struct xfs_buf *bp) 87 struct xfs_buf *bp)
79{ 88{
80 xfs_dir2_block_verify(bp); 89 struct xfs_mount *mp = bp->b_target->bt_mount;
90
91 if ((xfs_sb_version_hascrc(&mp->m_sb) &&
92 !xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
93 XFS_DIR3_DATA_CRC_OFF)) ||
94 !xfs_dir3_block_verify(bp)) {
95 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
96 xfs_buf_ioerror(bp, EFSCORRUPTED);
97 }
81} 98}
82 99
83static void 100static void
84xfs_dir2_block_write_verify( 101xfs_dir3_block_write_verify(
85 struct xfs_buf *bp) 102 struct xfs_buf *bp)
86{ 103{
87 xfs_dir2_block_verify(bp); 104 struct xfs_mount *mp = bp->b_target->bt_mount;
105 struct xfs_buf_log_item *bip = bp->b_fspriv;
106 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
107
108 if (!xfs_dir3_block_verify(bp)) {
109 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
110 xfs_buf_ioerror(bp, EFSCORRUPTED);
111 return;
112 }
113
114 if (!xfs_sb_version_hascrc(&mp->m_sb))
115 return;
116
117 if (bip)
118 hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn);
119
120 xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_DATA_CRC_OFF);
88} 121}
89 122
90const struct xfs_buf_ops xfs_dir2_block_buf_ops = { 123const struct xfs_buf_ops xfs_dir3_block_buf_ops = {
91 .verify_read = xfs_dir2_block_read_verify, 124 .verify_read = xfs_dir3_block_read_verify,
92 .verify_write = xfs_dir2_block_write_verify, 125 .verify_write = xfs_dir3_block_write_verify,
93}; 126};
94 127
95static int 128static int
96xfs_dir2_block_read( 129xfs_dir3_block_read(
97 struct xfs_trans *tp, 130 struct xfs_trans *tp,
98 struct xfs_inode *dp, 131 struct xfs_inode *dp,
99 struct xfs_buf **bpp) 132 struct xfs_buf **bpp)
@@ -101,7 +134,29 @@ xfs_dir2_block_read(
101 struct xfs_mount *mp = dp->i_mount; 134 struct xfs_mount *mp = dp->i_mount;
102 135
103 return xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, bpp, 136 return xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, bpp,
104 XFS_DATA_FORK, &xfs_dir2_block_buf_ops); 137 XFS_DATA_FORK, &xfs_dir3_block_buf_ops);
138}
139
140static void
141xfs_dir3_block_init(
142 struct xfs_mount *mp,
143 struct xfs_buf *bp,
144 struct xfs_inode *dp)
145{
146 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
147
148 bp->b_ops = &xfs_dir3_block_buf_ops;
149
150 if (xfs_sb_version_hascrc(&mp->m_sb)) {
151 memset(hdr3, 0, sizeof(*hdr3));
152 hdr3->magic = cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
153 hdr3->blkno = cpu_to_be64(bp->b_bn);
154 hdr3->owner = cpu_to_be64(dp->i_ino);
155 uuid_copy(&hdr3->uuid, &mp->m_sb.sb_uuid);
156 return;
157
158 }
159 hdr3->magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC);
105} 160}
106 161
107static void 162static void
@@ -121,7 +176,7 @@ xfs_dir2_block_need_space(
121 struct xfs_dir2_data_unused *enddup = NULL; 176 struct xfs_dir2_data_unused *enddup = NULL;
122 177
123 *compact = 0; 178 *compact = 0;
124 bf = hdr->bestfree; 179 bf = xfs_dir3_data_bestfree_p(hdr);
125 180
126 /* 181 /*
127 * If there are stale entries we'll use one for the leaf. 182 * If there are stale entries we'll use one for the leaf.
@@ -303,7 +358,7 @@ xfs_dir2_block_addname(
303 mp = dp->i_mount; 358 mp = dp->i_mount;
304 359
305 /* Read the (one and only) directory block into bp. */ 360 /* Read the (one and only) directory block into bp. */
306 error = xfs_dir2_block_read(tp, dp, &bp); 361 error = xfs_dir3_block_read(tp, dp, &bp);
307 if (error) 362 if (error)
308 return error; 363 return error;
309 364
@@ -531,7 +586,7 @@ xfs_dir2_block_getdents(
531 if (xfs_dir2_dataptr_to_db(mp, *offset) > mp->m_dirdatablk) 586 if (xfs_dir2_dataptr_to_db(mp, *offset) > mp->m_dirdatablk)
532 return 0; 587 return 0;
533 588
534 error = xfs_dir2_block_read(NULL, dp, &bp); 589 error = xfs_dir3_block_read(NULL, dp, &bp);
535 if (error) 590 if (error)
536 return error; 591 return error;
537 592
@@ -546,7 +601,7 @@ xfs_dir2_block_getdents(
546 * Set up values for the loop. 601 * Set up values for the loop.
547 */ 602 */
548 btp = xfs_dir2_block_tail_p(mp, hdr); 603 btp = xfs_dir2_block_tail_p(mp, hdr);
549 ptr = (char *)(hdr + 1); 604 ptr = (char *)xfs_dir3_data_entry_p(hdr);
550 endptr = (char *)xfs_dir2_block_leaf_p(btp); 605 endptr = (char *)xfs_dir2_block_leaf_p(btp);
551 606
552 /* 607 /*
@@ -711,7 +766,7 @@ xfs_dir2_block_lookup_int(
711 tp = args->trans; 766 tp = args->trans;
712 mp = dp->i_mount; 767 mp = dp->i_mount;
713 768
714 error = xfs_dir2_block_read(tp, dp, &bp); 769 error = xfs_dir3_block_read(tp, dp, &bp);
715 if (error) 770 if (error)
716 return error; 771 return error;
717 772
@@ -974,9 +1029,12 @@ xfs_dir2_leaf_to_block(
974 * These will show up in the leaf bests table. 1029 * These will show up in the leaf bests table.
975 */ 1030 */
976 while (dp->i_d.di_size > mp->m_dirblksize) { 1031 while (dp->i_d.di_size > mp->m_dirblksize) {
1032 int hdrsz;
1033
1034 hdrsz = xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
977 bestsp = xfs_dir2_leaf_bests_p(ltp); 1035 bestsp = xfs_dir2_leaf_bests_p(ltp);
978 if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) == 1036 if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) ==
979 mp->m_dirblksize - (uint)sizeof(*hdr)) { 1037 mp->m_dirblksize - hdrsz) {
980 if ((error = 1038 if ((error =
981 xfs_dir2_leaf_trim_data(args, lbp, 1039 xfs_dir2_leaf_trim_data(args, lbp,
982 (xfs_dir2_db_t)(be32_to_cpu(ltp->bestcount) - 1)))) 1040 (xfs_dir2_db_t)(be32_to_cpu(ltp->bestcount) - 1))))
@@ -1014,8 +1072,8 @@ xfs_dir2_leaf_to_block(
1014 /* 1072 /*
1015 * Start converting it to block form. 1073 * Start converting it to block form.
1016 */ 1074 */
1017 dbp->b_ops = &xfs_dir2_block_buf_ops; 1075 xfs_dir3_block_init(mp, dbp, dp);
1018 hdr->magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC); 1076
1019 needlog = 1; 1077 needlog = 1;
1020 needscan = 0; 1078 needscan = 0;
1021 /* 1079 /*
@@ -1137,16 +1195,16 @@ xfs_dir2_sf_to_block(
1137 return error; 1195 return error;
1138 } 1196 }
1139 /* 1197 /*
1140 * Initialize the data block. 1198 * Initialize the data block, then convert it to block format.
1141 */ 1199 */
1142 error = xfs_dir2_data_init(args, blkno, &bp); 1200 error = xfs_dir3_data_init(args, blkno, &bp);
1143 if (error) { 1201 if (error) {
1144 kmem_free(sfp); 1202 kmem_free(sfp);
1145 return error; 1203 return error;
1146 } 1204 }
1147 bp->b_ops = &xfs_dir2_block_buf_ops; 1205 xfs_dir3_block_init(mp, bp, dp);
1148 hdr = bp->b_addr; 1206 hdr = bp->b_addr;
1149 hdr->magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC); 1207
1150 /* 1208 /*
1151 * Compute size of block "tail" area. 1209 * Compute size of block "tail" area.
1152 */ 1210 */
@@ -1156,7 +1214,7 @@ xfs_dir2_sf_to_block(
1156 * The whole thing is initialized to free by the init routine. 1214 * The whole thing is initialized to free by the init routine.
1157 * Say we're using the leaf and tail area. 1215 * Say we're using the leaf and tail area.
1158 */ 1216 */
1159 dup = (xfs_dir2_data_unused_t *)(hdr + 1); 1217 dup = xfs_dir3_data_unused_p(hdr);
1160 needlog = needscan = 0; 1218 needlog = needscan = 0;
1161 xfs_dir2_data_use_free(tp, bp, dup, mp->m_dirblksize - i, i, &needlog, 1219 xfs_dir2_data_use_free(tp, bp, dup, mp->m_dirblksize - i, i, &needlog,
1162 &needscan); 1220 &needscan);
@@ -1178,8 +1236,7 @@ xfs_dir2_sf_to_block(
1178 /* 1236 /*
1179 * Create entry for . 1237 * Create entry for .
1180 */ 1238 */
1181 dep = (xfs_dir2_data_entry_t *) 1239 dep = xfs_dir3_data_dot_entry_p(hdr);
1182 ((char *)hdr + XFS_DIR2_DATA_DOT_OFFSET);
1183 dep->inumber = cpu_to_be64(dp->i_ino); 1240 dep->inumber = cpu_to_be64(dp->i_ino);
1184 dep->namelen = 1; 1241 dep->namelen = 1;
1185 dep->name[0] = '.'; 1242 dep->name[0] = '.';
@@ -1192,8 +1249,7 @@ xfs_dir2_sf_to_block(
1192 /* 1249 /*
1193 * Create entry for .. 1250 * Create entry for ..
1194 */ 1251 */
1195 dep = (xfs_dir2_data_entry_t *) 1252 dep = xfs_dir3_data_dotdot_entry_p(hdr);
1196 ((char *)hdr + XFS_DIR2_DATA_DOTDOT_OFFSET);
1197 dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp)); 1253 dep->inumber = cpu_to_be64(xfs_dir2_sf_get_parent_ino(sfp));
1198 dep->namelen = 2; 1254 dep->namelen = 2;
1199 dep->name[0] = dep->name[1] = '.'; 1255 dep->name[0] = dep->name[1] = '.';
@@ -1203,7 +1259,7 @@ xfs_dir2_sf_to_block(
1203 blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot); 1259 blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot);
1204 blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp, 1260 blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
1205 (char *)dep - (char *)hdr)); 1261 (char *)dep - (char *)hdr));
1206 offset = XFS_DIR2_DATA_FIRST_OFFSET; 1262 offset = xfs_dir3_data_first_offset(hdr);
1207 /* 1263 /*
1208 * Loop over existing entries, stuff them in. 1264 * Loop over existing entries, stuff them in.
1209 */ 1265 */