aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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
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')
-rw-r--r--fs/xfs/xfs_dir2_block.c132
-rw-r--r--fs/xfs/xfs_dir2_data.c160
-rw-r--r--fs/xfs/xfs_dir2_format.h143
-rw-r--r--fs/xfs/xfs_dir2_leaf.c6
-rw-r--r--fs/xfs/xfs_dir2_node.c2
-rw-r--r--fs/xfs/xfs_dir2_priv.h4
-rw-r--r--fs/xfs/xfs_dir2_sf.c2
7 files changed, 344 insertions, 105 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 */
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c
index ffcf1774152e..8484ec4848ea 100644
--- a/fs/xfs/xfs_dir2_data.c
+++ b/fs/xfs/xfs_dir2_data.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2002,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
@@ -65,10 +66,11 @@ __xfs_dir2_data_check(
65 66
66 mp = bp->b_target->bt_mount; 67 mp = bp->b_target->bt_mount;
67 hdr = bp->b_addr; 68 hdr = bp->b_addr;
68 bf = hdr->bestfree; 69 bf = xfs_dir3_data_bestfree_p(hdr);
69 p = (char *)(hdr + 1); 70 p = (char *)xfs_dir3_data_entry_p(hdr);
70 71
71 switch (hdr->magic) { 72 switch (hdr->magic) {
73 case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC):
72 case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC): 74 case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):
73 btp = xfs_dir2_block_tail_p(mp, hdr); 75 btp = xfs_dir2_block_tail_p(mp, hdr);
74 lep = xfs_dir2_block_leaf_p(btp); 76 lep = xfs_dir2_block_leaf_p(btp);
@@ -148,7 +150,8 @@ __xfs_dir2_data_check(
148 (char *)dep - (char *)hdr); 150 (char *)dep - (char *)hdr);
149 count++; 151 count++;
150 lastfree = 0; 152 lastfree = 0;
151 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) { 153 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
154 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
152 addr = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, 155 addr = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
153 (xfs_dir2_data_aoff_t) 156 (xfs_dir2_data_aoff_t)
154 ((char *)dep - (char *)hdr)); 157 ((char *)dep - (char *)hdr));
@@ -168,7 +171,8 @@ __xfs_dir2_data_check(
168 * Need to have seen all the entries and all the bestfree slots. 171 * Need to have seen all the entries and all the bestfree slots.
169 */ 172 */
170 XFS_WANT_CORRUPTED_RETURN(freeseen == 7); 173 XFS_WANT_CORRUPTED_RETURN(freeseen == 7);
171 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) { 174 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
175 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
172 for (i = stale = 0; i < be32_to_cpu(btp->count); i++) { 176 for (i = stale = 0; i < be32_to_cpu(btp->count); i++) {
173 if (lep[i].address == 177 if (lep[i].address ==
174 cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) 178 cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
@@ -216,7 +220,8 @@ xfs_dir2_data_reada_verify(
216 220
217 switch (hdr->magic) { 221 switch (hdr->magic) {
218 case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC): 222 case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):
219 bp->b_ops = &xfs_dir2_block_buf_ops; 223 case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC):
224 bp->b_ops = &xfs_dir3_block_buf_ops;
220 bp->b_ops->verify_read(bp); 225 bp->b_ops->verify_read(bp);
221 return; 226 return;
222 case cpu_to_be32(XFS_DIR2_DATA_MAGIC): 227 case cpu_to_be32(XFS_DIR2_DATA_MAGIC):
@@ -288,12 +293,15 @@ xfs_dir2_data_freefind(
288{ 293{
289 xfs_dir2_data_free_t *dfp; /* bestfree entry */ 294 xfs_dir2_data_free_t *dfp; /* bestfree entry */
290 xfs_dir2_data_aoff_t off; /* offset value needed */ 295 xfs_dir2_data_aoff_t off; /* offset value needed */
296 struct xfs_dir2_data_free *bf;
291#if defined(DEBUG) && defined(__KERNEL__) 297#if defined(DEBUG) && defined(__KERNEL__)
292 int matched; /* matched the value */ 298 int matched; /* matched the value */
293 int seenzero; /* saw a 0 bestfree entry */ 299 int seenzero; /* saw a 0 bestfree entry */
294#endif 300#endif
295 301
296 off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr); 302 off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr);
303 bf = xfs_dir3_data_bestfree_p(hdr);
304
297#if defined(DEBUG) && defined(__KERNEL__) 305#if defined(DEBUG) && defined(__KERNEL__)
298 /* 306 /*
299 * Validate some consistency in the bestfree table. 307 * Validate some consistency in the bestfree table.
@@ -301,9 +309,10 @@ xfs_dir2_data_freefind(
301 * one we're looking for it has to be exact. 309 * one we're looking for it has to be exact.
302 */ 310 */
303 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 311 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
304 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)); 312 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
305 for (dfp = &hdr->bestfree[0], seenzero = matched = 0; 313 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
306 dfp < &hdr->bestfree[XFS_DIR2_DATA_FD_COUNT]; 314 for (dfp = &bf[0], seenzero = matched = 0;
315 dfp < &bf[XFS_DIR2_DATA_FD_COUNT];
307 dfp++) { 316 dfp++) {
308 if (!dfp->offset) { 317 if (!dfp->offset) {
309 ASSERT(!dfp->length); 318 ASSERT(!dfp->length);
@@ -319,7 +328,7 @@ xfs_dir2_data_freefind(
319 else 328 else
320 ASSERT(be16_to_cpu(dfp->offset) + be16_to_cpu(dfp->length) <= off); 329 ASSERT(be16_to_cpu(dfp->offset) + be16_to_cpu(dfp->length) <= off);
321 ASSERT(matched || be16_to_cpu(dfp->length) >= be16_to_cpu(dup->length)); 330 ASSERT(matched || be16_to_cpu(dfp->length) >= be16_to_cpu(dup->length));
322 if (dfp > &hdr->bestfree[0]) 331 if (dfp > &bf[0])
323 ASSERT(be16_to_cpu(dfp[-1].length) >= be16_to_cpu(dfp[0].length)); 332 ASSERT(be16_to_cpu(dfp[-1].length) >= be16_to_cpu(dfp[0].length));
324 } 333 }
325#endif 334#endif
@@ -328,14 +337,12 @@ xfs_dir2_data_freefind(
328 * it can't be there since they're sorted. 337 * it can't be there since they're sorted.
329 */ 338 */
330 if (be16_to_cpu(dup->length) < 339 if (be16_to_cpu(dup->length) <
331 be16_to_cpu(hdr->bestfree[XFS_DIR2_DATA_FD_COUNT - 1].length)) 340 be16_to_cpu(bf[XFS_DIR2_DATA_FD_COUNT - 1].length))
332 return NULL; 341 return NULL;
333 /* 342 /*
334 * Look at the three bestfree entries for our guy. 343 * Look at the three bestfree entries for our guy.
335 */ 344 */
336 for (dfp = &hdr->bestfree[0]; 345 for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) {
337 dfp < &hdr->bestfree[XFS_DIR2_DATA_FD_COUNT];
338 dfp++) {
339 if (!dfp->offset) 346 if (!dfp->offset)
340 return NULL; 347 return NULL;
341 if (be16_to_cpu(dfp->offset) == off) 348 if (be16_to_cpu(dfp->offset) == off)
@@ -359,11 +366,12 @@ xfs_dir2_data_freeinsert(
359 xfs_dir2_data_free_t *dfp; /* bestfree table pointer */ 366 xfs_dir2_data_free_t *dfp; /* bestfree table pointer */
360 xfs_dir2_data_free_t new; /* new bestfree entry */ 367 xfs_dir2_data_free_t new; /* new bestfree entry */
361 368
362#ifdef __KERNEL__
363 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 369 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
364 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)); 370 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
365#endif 371 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
366 dfp = hdr->bestfree; 372 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
373
374 dfp = xfs_dir3_data_bestfree_p(hdr);
367 new.length = dup->length; 375 new.length = dup->length;
368 new.offset = cpu_to_be16((char *)dup - (char *)hdr); 376 new.offset = cpu_to_be16((char *)dup - (char *)hdr);
369 377
@@ -400,32 +408,36 @@ xfs_dir2_data_freeremove(
400 xfs_dir2_data_free_t *dfp, /* bestfree entry pointer */ 408 xfs_dir2_data_free_t *dfp, /* bestfree entry pointer */
401 int *loghead) /* out: log data header */ 409 int *loghead) /* out: log data header */
402{ 410{
403#ifdef __KERNEL__ 411 struct xfs_dir2_data_free *bf;
412
404 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 413 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
405 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)); 414 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
406#endif 415 hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
416 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
417
407 /* 418 /*
408 * It's the first entry, slide the next 2 up. 419 * It's the first entry, slide the next 2 up.
409 */ 420 */
410 if (dfp == &hdr->bestfree[0]) { 421 bf = xfs_dir3_data_bestfree_p(hdr);
411 hdr->bestfree[0] = hdr->bestfree[1]; 422 if (dfp == &bf[0]) {
412 hdr->bestfree[1] = hdr->bestfree[2]; 423 bf[0] = bf[1];
424 bf[1] = bf[2];
413 } 425 }
414 /* 426 /*
415 * It's the second entry, slide the 3rd entry up. 427 * It's the second entry, slide the 3rd entry up.
416 */ 428 */
417 else if (dfp == &hdr->bestfree[1]) 429 else if (dfp == &bf[1])
418 hdr->bestfree[1] = hdr->bestfree[2]; 430 bf[1] = bf[2];
419 /* 431 /*
420 * Must be the last entry. 432 * Must be the last entry.
421 */ 433 */
422 else 434 else
423 ASSERT(dfp == &hdr->bestfree[2]); 435 ASSERT(dfp == &bf[2]);
424 /* 436 /*
425 * Clear the 3rd entry, must be zero now. 437 * Clear the 3rd entry, must be zero now.
426 */ 438 */
427 hdr->bestfree[2].length = 0; 439 bf[2].length = 0;
428 hdr->bestfree[2].offset = 0; 440 bf[2].offset = 0;
429 *loghead = 1; 441 *loghead = 1;
430} 442}
431 443
@@ -441,23 +453,26 @@ xfs_dir2_data_freescan(
441 xfs_dir2_block_tail_t *btp; /* block tail */ 453 xfs_dir2_block_tail_t *btp; /* block tail */
442 xfs_dir2_data_entry_t *dep; /* active data entry */ 454 xfs_dir2_data_entry_t *dep; /* active data entry */
443 xfs_dir2_data_unused_t *dup; /* unused data entry */ 455 xfs_dir2_data_unused_t *dup; /* unused data entry */
456 struct xfs_dir2_data_free *bf;
444 char *endp; /* end of block's data */ 457 char *endp; /* end of block's data */
445 char *p; /* current entry pointer */ 458 char *p; /* current entry pointer */
446 459
447#ifdef __KERNEL__
448 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 460 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
449 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)); 461 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
450#endif 462 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
463
451 /* 464 /*
452 * Start by clearing the table. 465 * Start by clearing the table.
453 */ 466 */
454 memset(hdr->bestfree, 0, sizeof(hdr->bestfree)); 467 bf = xfs_dir3_data_bestfree_p(hdr);
468 memset(bf, 0, sizeof(*bf) * XFS_DIR2_DATA_FD_COUNT);
455 *loghead = 1; 469 *loghead = 1;
456 /* 470 /*
457 * Set up pointers. 471 * Set up pointers.
458 */ 472 */
459 p = (char *)(hdr + 1); 473 p = (char *)xfs_dir3_data_entry_p(hdr);
460 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)) { 474 if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
475 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
461 btp = xfs_dir2_block_tail_p(mp, hdr); 476 btp = xfs_dir2_block_tail_p(mp, hdr);
462 endp = (char *)xfs_dir2_block_leaf_p(btp); 477 endp = (char *)xfs_dir2_block_leaf_p(btp);
463 } else 478 } else
@@ -493,7 +508,7 @@ xfs_dir2_data_freescan(
493 * Give back the buffer for the created block. 508 * Give back the buffer for the created block.
494 */ 509 */
495int /* error */ 510int /* error */
496xfs_dir2_data_init( 511xfs_dir3_data_init(
497 xfs_da_args_t *args, /* directory operation args */ 512 xfs_da_args_t *args, /* directory operation args */
498 xfs_dir2_db_t blkno, /* logical dir block number */ 513 xfs_dir2_db_t blkno, /* logical dir block number */
499 struct xfs_buf **bpp) /* output block buffer */ 514 struct xfs_buf **bpp) /* output block buffer */
@@ -502,6 +517,7 @@ xfs_dir2_data_init(
502 xfs_dir2_data_hdr_t *hdr; /* data block header */ 517 xfs_dir2_data_hdr_t *hdr; /* data block header */
503 xfs_inode_t *dp; /* incore directory inode */ 518 xfs_inode_t *dp; /* incore directory inode */
504 xfs_dir2_data_unused_t *dup; /* unused entry pointer */ 519 xfs_dir2_data_unused_t *dup; /* unused entry pointer */
520 struct xfs_dir2_data_free *bf;
505 int error; /* error return value */ 521 int error; /* error return value */
506 int i; /* bestfree index */ 522 int i; /* bestfree index */
507 xfs_mount_t *mp; /* filesystem mount point */ 523 xfs_mount_t *mp; /* filesystem mount point */
@@ -524,21 +540,34 @@ xfs_dir2_data_init(
524 * Initialize the header. 540 * Initialize the header.
525 */ 541 */
526 hdr = bp->b_addr; 542 hdr = bp->b_addr;
527 hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC); 543
528 hdr->bestfree[0].offset = cpu_to_be16(sizeof(*hdr)); 544 if (xfs_sb_version_hascrc(&mp->m_sb)) {
545 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
546
547 memset(hdr3, 0, sizeof(*hdr3));
548 hdr3->magic = cpu_to_be32(XFS_DIR3_DATA_MAGIC);
549 hdr3->blkno = cpu_to_be64(bp->b_bn);
550 hdr3->owner = cpu_to_be64(dp->i_ino);
551 uuid_copy(&hdr3->uuid, &mp->m_sb.sb_uuid);
552
553 } else
554 hdr->magic = cpu_to_be32(XFS_DIR2_DATA_MAGIC);
555
556 bf = xfs_dir3_data_bestfree_p(hdr);
557 bf[0].offset = cpu_to_be16(xfs_dir3_data_entry_offset(hdr));
529 for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) { 558 for (i = 1; i < XFS_DIR2_DATA_FD_COUNT; i++) {
530 hdr->bestfree[i].length = 0; 559 bf[i].length = 0;
531 hdr->bestfree[i].offset = 0; 560 bf[i].offset = 0;
532 } 561 }
533 562
534 /* 563 /*
535 * Set up an unused entry for the block's body. 564 * Set up an unused entry for the block's body.
536 */ 565 */
537 dup = (xfs_dir2_data_unused_t *)(hdr + 1); 566 dup = xfs_dir3_data_unused_p(hdr);
538 dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG); 567 dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
539 568
540 t = mp->m_dirblksize - (uint)sizeof(*hdr); 569 t = mp->m_dirblksize - (uint)xfs_dir3_data_entry_offset(hdr);
541 hdr->bestfree[0].length = cpu_to_be16(t); 570 bf[0].length = cpu_to_be16(t);
542 dup->length = cpu_to_be16(t); 571 dup->length = cpu_to_be16(t);
543 *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)hdr); 572 *xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16((char *)dup - (char *)hdr);
544 /* 573 /*
@@ -562,7 +591,8 @@ xfs_dir2_data_log_entry(
562 xfs_dir2_data_hdr_t *hdr = bp->b_addr; 591 xfs_dir2_data_hdr_t *hdr = bp->b_addr;
563 592
564 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 593 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
565 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)); 594 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
595 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
566 596
567 xfs_trans_log_buf(tp, bp, (uint)((char *)dep - (char *)hdr), 597 xfs_trans_log_buf(tp, bp, (uint)((char *)dep - (char *)hdr),
568 (uint)((char *)(xfs_dir2_data_entry_tag_p(dep) + 1) - 598 (uint)((char *)(xfs_dir2_data_entry_tag_p(dep) + 1) -
@@ -580,9 +610,10 @@ xfs_dir2_data_log_header(
580 xfs_dir2_data_hdr_t *hdr = bp->b_addr; 610 xfs_dir2_data_hdr_t *hdr = bp->b_addr;
581 611
582 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 612 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
583 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)); 613 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
614 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
584 615
585 xfs_trans_log_buf(tp, bp, 0, sizeof(*hdr) - 1); 616 xfs_trans_log_buf(tp, bp, 0, xfs_dir3_data_entry_offset(hdr) - 1);
586} 617}
587 618
588/* 619/*
@@ -597,7 +628,8 @@ xfs_dir2_data_log_unused(
597 xfs_dir2_data_hdr_t *hdr = bp->b_addr; 628 xfs_dir2_data_hdr_t *hdr = bp->b_addr;
598 629
599 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 630 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
600 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)); 631 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
632 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
601 633
602 /* 634 /*
603 * Log the first part of the unused entry. 635 * Log the first part of the unused entry.
@@ -635,6 +667,7 @@ xfs_dir2_data_make_free(
635 xfs_dir2_data_unused_t *newdup; /* new unused entry */ 667 xfs_dir2_data_unused_t *newdup; /* new unused entry */
636 xfs_dir2_data_unused_t *postdup; /* unused entry after us */ 668 xfs_dir2_data_unused_t *postdup; /* unused entry after us */
637 xfs_dir2_data_unused_t *prevdup; /* unused entry before us */ 669 xfs_dir2_data_unused_t *prevdup; /* unused entry before us */
670 struct xfs_dir2_data_free *bf;
638 671
639 mp = tp->t_mountp; 672 mp = tp->t_mountp;
640 hdr = bp->b_addr; 673 hdr = bp->b_addr;
@@ -647,7 +680,8 @@ xfs_dir2_data_make_free(
647 else { 680 else {
648 xfs_dir2_block_tail_t *btp; /* block tail */ 681 xfs_dir2_block_tail_t *btp; /* block tail */
649 682
650 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)); 683 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
684 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
651 btp = xfs_dir2_block_tail_p(mp, hdr); 685 btp = xfs_dir2_block_tail_p(mp, hdr);
652 endptr = (char *)xfs_dir2_block_leaf_p(btp); 686 endptr = (char *)xfs_dir2_block_leaf_p(btp);
653 } 687 }
@@ -655,7 +689,7 @@ xfs_dir2_data_make_free(
655 * If this isn't the start of the block, then back up to 689 * If this isn't the start of the block, then back up to
656 * the previous entry and see if it's free. 690 * the previous entry and see if it's free.
657 */ 691 */
658 if (offset > sizeof(*hdr)) { 692 if (offset > xfs_dir3_data_entry_offset(hdr)) {
659 __be16 *tagp; /* tag just before us */ 693 __be16 *tagp; /* tag just before us */
660 694
661 tagp = (__be16 *)((char *)hdr + offset) - 1; 695 tagp = (__be16 *)((char *)hdr + offset) - 1;
@@ -681,6 +715,7 @@ xfs_dir2_data_make_free(
681 * Previous and following entries are both free, 715 * Previous and following entries are both free,
682 * merge everything into a single free entry. 716 * merge everything into a single free entry.
683 */ 717 */
718 bf = xfs_dir3_data_bestfree_p(hdr);
684 if (prevdup && postdup) { 719 if (prevdup && postdup) {
685 xfs_dir2_data_free_t *dfp2; /* another bestfree pointer */ 720 xfs_dir2_data_free_t *dfp2; /* another bestfree pointer */
686 721
@@ -695,7 +730,7 @@ xfs_dir2_data_make_free(
695 * since the third bestfree is there, there might be more 730 * since the third bestfree is there, there might be more
696 * entries. 731 * entries.
697 */ 732 */
698 needscan = (hdr->bestfree[2].length != 0); 733 needscan = (bf[2].length != 0);
699 /* 734 /*
700 * Fix up the new big freespace. 735 * Fix up the new big freespace.
701 */ 736 */
@@ -711,10 +746,10 @@ xfs_dir2_data_make_free(
711 * Remove entry 1 first then entry 0. 746 * Remove entry 1 first then entry 0.
712 */ 747 */
713 ASSERT(dfp && dfp2); 748 ASSERT(dfp && dfp2);
714 if (dfp == &hdr->bestfree[1]) { 749 if (dfp == &bf[1]) {
715 dfp = &hdr->bestfree[0]; 750 dfp = &bf[0];
716 ASSERT(dfp2 == dfp); 751 ASSERT(dfp2 == dfp);
717 dfp2 = &hdr->bestfree[1]; 752 dfp2 = &bf[1];
718 } 753 }
719 xfs_dir2_data_freeremove(hdr, dfp2, needlogp); 754 xfs_dir2_data_freeremove(hdr, dfp2, needlogp);
720 xfs_dir2_data_freeremove(hdr, dfp, needlogp); 755 xfs_dir2_data_freeremove(hdr, dfp, needlogp);
@@ -722,7 +757,7 @@ xfs_dir2_data_make_free(
722 * Now insert the new entry. 757 * Now insert the new entry.
723 */ 758 */
724 dfp = xfs_dir2_data_freeinsert(hdr, prevdup, needlogp); 759 dfp = xfs_dir2_data_freeinsert(hdr, prevdup, needlogp);
725 ASSERT(dfp == &hdr->bestfree[0]); 760 ASSERT(dfp == &bf[0]);
726 ASSERT(dfp->length == prevdup->length); 761 ASSERT(dfp->length == prevdup->length);
727 ASSERT(!dfp[1].length); 762 ASSERT(!dfp[1].length);
728 ASSERT(!dfp[2].length); 763 ASSERT(!dfp[2].length);
@@ -751,7 +786,7 @@ xfs_dir2_data_make_free(
751 */ 786 */
752 else { 787 else {
753 needscan = be16_to_cpu(prevdup->length) > 788 needscan = be16_to_cpu(prevdup->length) >
754 be16_to_cpu(hdr->bestfree[2].length); 789 be16_to_cpu(bf[2].length);
755 } 790 }
756 } 791 }
757 /* 792 /*
@@ -779,7 +814,7 @@ xfs_dir2_data_make_free(
779 */ 814 */
780 else { 815 else {
781 needscan = be16_to_cpu(newdup->length) > 816 needscan = be16_to_cpu(newdup->length) >
782 be16_to_cpu(hdr->bestfree[2].length); 817 be16_to_cpu(bf[2].length);
783 } 818 }
784 } 819 }
785 /* 820 /*
@@ -818,10 +853,12 @@ xfs_dir2_data_use_free(
818 xfs_dir2_data_unused_t *newdup; /* new unused entry */ 853 xfs_dir2_data_unused_t *newdup; /* new unused entry */
819 xfs_dir2_data_unused_t *newdup2; /* another new unused entry */ 854 xfs_dir2_data_unused_t *newdup2; /* another new unused entry */
820 int oldlen; /* old unused entry's length */ 855 int oldlen; /* old unused entry's length */
856 struct xfs_dir2_data_free *bf;
821 857
822 hdr = bp->b_addr; 858 hdr = bp->b_addr;
823 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || 859 ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
824 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC)); 860 hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
861 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
825 ASSERT(be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG); 862 ASSERT(be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG);
826 ASSERT(offset >= (char *)dup - (char *)hdr); 863 ASSERT(offset >= (char *)dup - (char *)hdr);
827 ASSERT(offset + len <= (char *)dup + be16_to_cpu(dup->length) - (char *)hdr); 864 ASSERT(offset + len <= (char *)dup + be16_to_cpu(dup->length) - (char *)hdr);
@@ -831,7 +868,8 @@ xfs_dir2_data_use_free(
831 */ 868 */
832 dfp = xfs_dir2_data_freefind(hdr, dup); 869 dfp = xfs_dir2_data_freefind(hdr, dup);
833 oldlen = be16_to_cpu(dup->length); 870 oldlen = be16_to_cpu(dup->length);
834 ASSERT(dfp || oldlen <= be16_to_cpu(hdr->bestfree[2].length)); 871 bf = xfs_dir3_data_bestfree_p(hdr);
872 ASSERT(dfp || oldlen <= be16_to_cpu(bf[2].length));
835 /* 873 /*
836 * Check for alignment with front and back of the entry. 874 * Check for alignment with front and back of the entry.
837 */ 875 */
@@ -845,7 +883,7 @@ xfs_dir2_data_use_free(
845 */ 883 */
846 if (matchfront && matchback) { 884 if (matchfront && matchback) {
847 if (dfp) { 885 if (dfp) {
848 needscan = (hdr->bestfree[2].offset != 0); 886 needscan = (bf[2].offset != 0);
849 if (!needscan) 887 if (!needscan)
850 xfs_dir2_data_freeremove(hdr, dfp, needlogp); 888 xfs_dir2_data_freeremove(hdr, dfp, needlogp);
851 } 889 }
@@ -875,7 +913,7 @@ xfs_dir2_data_use_free(
875 * that means we don't know if there was a better 913 * that means we don't know if there was a better
876 * choice for the last slot, or not. Rescan. 914 * choice for the last slot, or not. Rescan.
877 */ 915 */
878 needscan = dfp == &hdr->bestfree[2]; 916 needscan = dfp == &bf[2];
879 } 917 }
880 } 918 }
881 /* 919 /*
@@ -902,7 +940,7 @@ xfs_dir2_data_use_free(
902 * that means we don't know if there was a better 940 * that means we don't know if there was a better
903 * choice for the last slot, or not. Rescan. 941 * choice for the last slot, or not. Rescan.
904 */ 942 */
905 needscan = dfp == &hdr->bestfree[2]; 943 needscan = dfp == &bf[2];
906 } 944 }
907 } 945 }
908 /* 946 /*
@@ -930,7 +968,7 @@ xfs_dir2_data_use_free(
930 * the 2 new will work. 968 * the 2 new will work.
931 */ 969 */
932 if (dfp) { 970 if (dfp) {
933 needscan = (hdr->bestfree[2].length != 0); 971 needscan = (bf[2].length != 0);
934 if (!needscan) { 972 if (!needscan) {
935 xfs_dir2_data_freeremove(hdr, dfp, needlogp); 973 xfs_dir2_data_freeremove(hdr, dfp, needlogp);
936 xfs_dir2_data_freeinsert(hdr, newdup, needlogp); 974 xfs_dir2_data_freeinsert(hdr, newdup, needlogp);
diff --git a/fs/xfs/xfs_dir2_format.h b/fs/xfs/xfs_dir2_format.h
index 07270981f48f..845979a4ee96 100644
--- a/fs/xfs/xfs_dir2_format.h
+++ b/fs/xfs/xfs_dir2_format.h
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-2001,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
@@ -36,6 +37,37 @@
36#define XFS_DIR2_FREE_MAGIC 0x58443246 /* XD2F: free index blocks */ 37#define XFS_DIR2_FREE_MAGIC 0x58443246 /* XD2F: free index blocks */
37 38
38/* 39/*
40 * Directory Version 3 With CRCs.
41 *
42 * The tree formats are the same as for version 2 directories. The difference
43 * is in the block header and dirent formats. In many cases the v3 structures
44 * use v2 definitions as they are no different and this makes code sharing much
45 * easier.
46 *
47 * Also, the xfs_dir3_*() functions handle both v2 and v3 formats - if the
48 * format is v2 then they switch to the existing v2 code, or the format is v3
49 * they implement the v3 functionality. This means the existing dir2 is a mix of
50 * xfs_dir2/xfs_dir3 calls and functions. The xfs_dir3 functions are called
51 * where there is a difference in the formats, otherwise the code is unchanged.
52 *
53 * Where it is possible, the code decides what to do based on the magic numbers
54 * in the blocks rather than feature bits in the superblock. This means the code
55 * is as independent of the external XFS code as possible as doesn't require
56 * passing struct xfs_mount pointers into places where it isn't really
57 * necessary.
58 *
59 * Version 3 includes:
60 *
61 * - a larger block header for CRC and identification purposes and so the
62 * offsets of all the structures inside the blocks are different.
63 *
64 * - new magic numbers to be able to detect the v2/v3 types on the fly.
65 */
66
67#define XFS_DIR3_BLOCK_MAGIC 0x58444233 /* XDB3: single block dirs */
68#define XFS_DIR3_DATA_MAGIC 0x58444433 /* XDD3: multiblock dirs */
69
70/*
39 * Byte offset in data block and shortform entry. 71 * Byte offset in data block and shortform entry.
40 */ 72 */
41typedef __uint16_t xfs_dir2_data_off_t; 73typedef __uint16_t xfs_dir2_data_off_t;
@@ -226,6 +258,38 @@ typedef struct xfs_dir2_data_hdr {
226} xfs_dir2_data_hdr_t; 258} xfs_dir2_data_hdr_t;
227 259
228/* 260/*
261 * define a structure for all the verification fields we are adding to the
262 * directory block structures. This will be used in several structures.
263 * The magic number must be the first entry to align with all the dir2
264 * structures so we determine how to decode them just by the magic number.
265 */
266struct xfs_dir3_blk_hdr {
267 __be32 magic; /* magic number */
268 __be32 crc; /* CRC of block */
269 __be64 blkno; /* first block of the buffer */
270 __be64 lsn; /* sequence number of last write */
271 uuid_t uuid; /* filesystem we belong to */
272 __be64 owner; /* inode that owns the block */
273};
274
275struct xfs_dir3_data_hdr {
276 struct xfs_dir3_blk_hdr hdr;
277 xfs_dir2_data_free_t best_free[XFS_DIR2_DATA_FD_COUNT];
278};
279
280#define XFS_DIR3_DATA_CRC_OFF offsetof(struct xfs_dir3_data_hdr, hdr.crc)
281
282static inline struct xfs_dir2_data_free *
283xfs_dir3_data_bestfree_p(struct xfs_dir2_data_hdr *hdr)
284{
285 if (hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
286 struct xfs_dir3_data_hdr *hdr3 = (struct xfs_dir3_data_hdr *)hdr;
287 return hdr3->best_free;
288 }
289 return hdr->bestfree;
290}
291
292/*
229 * Active entry in a data block. 293 * Active entry in a data block.
230 * 294 *
231 * Aligned to 8 bytes. After the variable length name field there is a 295 * Aligned to 8 bytes. After the variable length name field there is a
@@ -280,6 +344,85 @@ xfs_dir2_data_unused_tag_p(struct xfs_dir2_data_unused *dup)
280 be16_to_cpu(dup->length) - sizeof(__be16)); 344 be16_to_cpu(dup->length) - sizeof(__be16));
281} 345}
282 346
347static inline struct xfs_dir2_data_unused *
348xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr)
349{
350 if (hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
351 return (struct xfs_dir2_data_unused *)
352 ((char *)hdr + sizeof(struct xfs_dir3_data_hdr));
353 }
354 return (struct xfs_dir2_data_unused *)
355 ((char *)hdr + sizeof(struct xfs_dir2_data_hdr));
356}
357
358static inline size_t
359xfs_dir3_data_hdr_size(bool dir3)
360{
361 if (dir3)
362 return sizeof(struct xfs_dir3_data_hdr);
363 return sizeof(struct xfs_dir2_data_hdr);
364}
365
366static inline size_t
367xfs_dir3_data_entry_offset(struct xfs_dir2_data_hdr *hdr)
368{
369 bool dir3 = hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
370 hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
371 return xfs_dir3_data_hdr_size(dir3);
372}
373
374static inline struct xfs_dir2_data_entry *
375xfs_dir3_data_entry_p(struct xfs_dir2_data_hdr *hdr)
376{
377 return (struct xfs_dir2_data_entry *)
378 ((char *)hdr + xfs_dir3_data_entry_offset(hdr));
379}
380
381/*
382 * Offsets of . and .. in data space (always block 0)
383 */
384static inline xfs_dir2_data_aoff_t
385xfs_dir3_data_dot_offset(struct xfs_dir2_data_hdr *hdr)
386{
387 return xfs_dir3_data_entry_offset(hdr);
388}
389
390static inline xfs_dir2_data_aoff_t
391xfs_dir3_data_dotdot_offset(struct xfs_dir2_data_hdr *hdr)
392{
393 return xfs_dir3_data_dot_offset(hdr) + xfs_dir2_data_entsize(1);
394}
395
396static inline xfs_dir2_data_aoff_t
397xfs_dir3_data_first_offset(struct xfs_dir2_data_hdr *hdr)
398{
399 return xfs_dir3_data_dotdot_offset(hdr) + xfs_dir2_data_entsize(2);
400}
401
402/*
403 * location of . and .. in data space (always block 0)
404 */
405static inline struct xfs_dir2_data_entry *
406xfs_dir3_data_dot_entry_p(struct xfs_dir2_data_hdr *hdr)
407{
408 return (struct xfs_dir2_data_entry *)
409 ((char *)hdr + xfs_dir3_data_dot_offset(hdr));
410}
411
412static inline struct xfs_dir2_data_entry *
413xfs_dir3_data_dotdot_entry_p(struct xfs_dir2_data_hdr *hdr)
414{
415 return (struct xfs_dir2_data_entry *)
416 ((char *)hdr + xfs_dir3_data_dotdot_offset(hdr));
417}
418
419static inline struct xfs_dir2_data_entry *
420xfs_dir3_data_first_entry_p(struct xfs_dir2_data_hdr *hdr)
421{
422 return (struct xfs_dir2_data_entry *)
423 ((char *)hdr + xfs_dir3_data_first_offset(hdr));
424}
425
283/* 426/*
284 * Leaf block structures. 427 * Leaf block structures.
285 * 428 *
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 60cd2fa4e047..ef163f06fd16 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -149,6 +149,7 @@ xfs_dir2_block_to_leaf(
149 int needlog; /* need to log block header */ 149 int needlog; /* need to log block header */
150 int needscan; /* need to rescan bestfree */ 150 int needscan; /* need to rescan bestfree */
151 xfs_trans_t *tp; /* transaction pointer */ 151 xfs_trans_t *tp; /* transaction pointer */
152 struct xfs_dir2_data_free *bf;
152 153
153 trace_xfs_dir2_block_to_leaf(args); 154 trace_xfs_dir2_block_to_leaf(args);
154 155
@@ -177,6 +178,7 @@ xfs_dir2_block_to_leaf(
177 xfs_dir2_data_check(dp, dbp); 178 xfs_dir2_data_check(dp, dbp);
178 btp = xfs_dir2_block_tail_p(mp, hdr); 179 btp = xfs_dir2_block_tail_p(mp, hdr);
179 blp = xfs_dir2_block_leaf_p(btp); 180 blp = xfs_dir2_block_leaf_p(btp);
181 bf = xfs_dir3_data_bestfree_p(hdr);
180 /* 182 /*
181 * Set the counts in the leaf header. 183 * Set the counts in the leaf header.
182 */ 184 */
@@ -212,7 +214,7 @@ xfs_dir2_block_to_leaf(
212 ltp = xfs_dir2_leaf_tail_p(mp, leaf); 214 ltp = xfs_dir2_leaf_tail_p(mp, leaf);
213 ltp->bestcount = cpu_to_be32(1); 215 ltp->bestcount = cpu_to_be32(1);
214 bestsp = xfs_dir2_leaf_bests_p(ltp); 216 bestsp = xfs_dir2_leaf_bests_p(ltp);
215 bestsp[0] = hdr->bestfree[0].length; 217 bestsp[0] = bf[0].length;
216 /* 218 /*
217 * Log the data header and leaf bests table. 219 * Log the data header and leaf bests table.
218 */ 220 */
@@ -544,7 +546,7 @@ xfs_dir2_leaf_addname(
544 /* 546 /*
545 * Initialize the block. 547 * Initialize the block.
546 */ 548 */
547 if ((error = xfs_dir2_data_init(args, use_block, &dbp))) { 549 if ((error = xfs_dir3_data_init(args, use_block, &dbp))) {
548 xfs_trans_brelse(tp, lbp); 550 xfs_trans_brelse(tp, lbp);
549 return error; 551 return error;
550 } 552 }
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index 5980f9b7fa9b..985d70bc391d 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -1588,7 +1588,7 @@ xfs_dir2_node_addname_int(
1588 if (unlikely((error = xfs_dir2_grow_inode(args, 1588 if (unlikely((error = xfs_dir2_grow_inode(args,
1589 XFS_DIR2_DATA_SPACE, 1589 XFS_DIR2_DATA_SPACE,
1590 &dbno)) || 1590 &dbno)) ||
1591 (error = xfs_dir2_data_init(args, dbno, &dbp)))) 1591 (error = xfs_dir3_data_init(args, dbno, &dbp))))
1592 return error; 1592 return error;
1593 1593
1594 /* 1594 /*
diff --git a/fs/xfs/xfs_dir2_priv.h b/fs/xfs/xfs_dir2_priv.h
index 7da79f6515fd..e6f2e0a7bb65 100644
--- a/fs/xfs/xfs_dir2_priv.h
+++ b/fs/xfs/xfs_dir2_priv.h
@@ -30,7 +30,7 @@ extern int xfs_dir_cilookup_result(struct xfs_da_args *args,
30 const unsigned char *name, int len); 30 const unsigned char *name, int len);
31 31
32/* xfs_dir2_block.c */ 32/* xfs_dir2_block.c */
33extern const struct xfs_buf_ops xfs_dir2_block_buf_ops; 33extern const struct xfs_buf_ops xfs_dir3_block_buf_ops;
34 34
35extern int xfs_dir2_block_addname(struct xfs_da_args *args); 35extern int xfs_dir2_block_addname(struct xfs_da_args *args);
36extern int xfs_dir2_block_getdents(struct xfs_inode *dp, void *dirent, 36extern int xfs_dir2_block_getdents(struct xfs_inode *dp, void *dirent,
@@ -61,7 +61,7 @@ xfs_dir2_data_freeinsert(struct xfs_dir2_data_hdr *hdr,
61 struct xfs_dir2_data_unused *dup, int *loghead); 61 struct xfs_dir2_data_unused *dup, int *loghead);
62extern void xfs_dir2_data_freescan(struct xfs_mount *mp, 62extern void xfs_dir2_data_freescan(struct xfs_mount *mp,
63 struct xfs_dir2_data_hdr *hdr, int *loghead); 63 struct xfs_dir2_data_hdr *hdr, int *loghead);
64extern int xfs_dir2_data_init(struct xfs_da_args *args, xfs_dir2_db_t blkno, 64extern int xfs_dir3_data_init(struct xfs_da_args *args, xfs_dir2_db_t blkno,
65 struct xfs_buf **bpp); 65 struct xfs_buf **bpp);
66extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_buf *bp, 66extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_buf *bp,
67 struct xfs_dir2_data_entry *dep); 67 struct xfs_dir2_data_entry *dep);
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c
index 1b9fc3ec7e4b..b9756228e9c0 100644
--- a/fs/xfs/xfs_dir2_sf.c
+++ b/fs/xfs/xfs_dir2_sf.c
@@ -278,7 +278,7 @@ xfs_dir2_block_to_sf(
278 * Set up to loop over the block's entries. 278 * Set up to loop over the block's entries.
279 */ 279 */
280 btp = xfs_dir2_block_tail_p(mp, hdr); 280 btp = xfs_dir2_block_tail_p(mp, hdr);
281 ptr = (char *)(hdr + 1); 281 ptr = (char *)xfs_dir3_data_entry_p(hdr);
282 endptr = (char *)xfs_dir2_block_leaf_p(btp); 282 endptr = (char *)xfs_dir2_block_leaf_p(btp);
283 sfep = xfs_dir2_sf_firstentry(sfp); 283 sfep = xfs_dir2_sf_firstentry(sfp);
284 /* 284 /*