aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2013-04-03 01:11:21 -0400
committerBen Myers <bpm@sgi.com>2013-04-27 12:58:16 -0400
commitcbc8adf89724b961c08b823d8bfb6dadbfa8733d (patch)
tree31a43d0f0445c69b446f3091ab9666d5934c115d
parentf5f3d9b0161633e8943520e83df634ad540b3b7f (diff)
xfs: add CRC checking to dir2 free blocks
This addition follows the same pattern as the dir2 block CRCs, but with a few differences. The main difference is that the free block header is different between the v2 and v3 formats, so an "in-core" free block header has been added and _todisk/_from_disk functions used to abstract the differences in structure format from the code. This is similar to the on-disk superblock versus the in-core superblock setup. The in-core strucutre is populated when the buffer is read from disk, all the in memory checks and modifications are done on the in-core version of the structure which is written back to the buffer before the buffer is logged. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Ben Myers <bpm@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
-rw-r--r--fs/xfs/xfs_dir2_format.h55
-rw-r--r--fs/xfs/xfs_dir2_leaf.c15
-rw-r--r--fs/xfs/xfs_dir2_node.c474
3 files changed, 382 insertions, 162 deletions
diff --git a/fs/xfs/xfs_dir2_format.h b/fs/xfs/xfs_dir2_format.h
index 845979a4ee96..ec5044a92b70 100644
--- a/fs/xfs/xfs_dir2_format.h
+++ b/fs/xfs/xfs_dir2_format.h
@@ -66,6 +66,7 @@
66 66
67#define XFS_DIR3_BLOCK_MAGIC 0x58444233 /* XDB3: single block dirs */ 67#define XFS_DIR3_BLOCK_MAGIC 0x58444233 /* XDB3: single block dirs */
68#define XFS_DIR3_DATA_MAGIC 0x58444433 /* XDD3: multiblock dirs */ 68#define XFS_DIR3_DATA_MAGIC 0x58444433 /* XDD3: multiblock dirs */
69#define XFS_DIR3_FREE_MAGIC 0x58444633 /* XDF3: free index blocks */
69 70
70/* 71/*
71 * Byte offset in data block and shortform entry. 72 * Byte offset in data block and shortform entry.
@@ -663,19 +664,65 @@ typedef struct xfs_dir2_free {
663 /* unused entries are -1 */ 664 /* unused entries are -1 */
664} xfs_dir2_free_t; 665} xfs_dir2_free_t;
665 666
666static inline int xfs_dir2_free_max_bests(struct xfs_mount *mp) 667struct xfs_dir3_free_hdr {
668 struct xfs_dir3_blk_hdr hdr;
669 __be32 firstdb; /* db of first entry */
670 __be32 nvalid; /* count of valid entries */
671 __be32 nused; /* count of used entries */
672};
673
674struct xfs_dir3_free {
675 struct xfs_dir3_free_hdr hdr;
676 __be16 bests[]; /* best free counts */
677 /* unused entries are -1 */
678};
679
680#define XFS_DIR3_FREE_CRC_OFF offsetof(struct xfs_dir3_free, hdr.hdr.crc)
681
682/*
683 * In core version of the free block header, abstracted away from on-disk format
684 * differences. Use this in the code, and convert to/from the disk version using
685 * xfs_dir3_free_hdr_from_disk/xfs_dir3_free_hdr_to_disk.
686 */
687struct xfs_dir3_icfree_hdr {
688 __uint32_t magic;
689 __uint32_t firstdb;
690 __uint32_t nvalid;
691 __uint32_t nused;
692
693};
694
695void xfs_dir3_free_hdr_from_disk(struct xfs_dir3_icfree_hdr *to,
696 struct xfs_dir2_free *from);
697
698static inline int
699xfs_dir3_free_hdr_size(struct xfs_mount *mp)
667{ 700{
668 return (mp->m_dirblksize - sizeof(struct xfs_dir2_free_hdr)) / 701 if (xfs_sb_version_hascrc(&mp->m_sb))
702 return sizeof(struct xfs_dir3_free_hdr);
703 return sizeof(struct xfs_dir2_free_hdr);
704}
705
706static inline int
707xfs_dir3_free_max_bests(struct xfs_mount *mp)
708{
709 return (mp->m_dirblksize - xfs_dir3_free_hdr_size(mp)) /
669 sizeof(xfs_dir2_data_off_t); 710 sizeof(xfs_dir2_data_off_t);
670} 711}
671 712
713static inline __be16 *
714xfs_dir3_free_bests_p(struct xfs_mount *mp, struct xfs_dir2_free *free)
715{
716 return (__be16 *)((char *)free + xfs_dir3_free_hdr_size(mp));
717}
718
672/* 719/*
673 * Convert data space db to the corresponding free db. 720 * Convert data space db to the corresponding free db.
674 */ 721 */
675static inline xfs_dir2_db_t 722static inline xfs_dir2_db_t
676xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db) 723xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
677{ 724{
678 return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir2_free_max_bests(mp); 725 return XFS_DIR2_FREE_FIRSTDB(mp) + db / xfs_dir3_free_max_bests(mp);
679} 726}
680 727
681/* 728/*
@@ -684,7 +731,7 @@ xfs_dir2_db_to_fdb(struct xfs_mount *mp, xfs_dir2_db_t db)
684static inline int 731static inline int
685xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db) 732xfs_dir2_db_to_fdindex(struct xfs_mount *mp, xfs_dir2_db_t db)
686{ 733{
687 return db % xfs_dir2_free_max_bests(mp); 734 return db % xfs_dir3_free_max_bests(mp);
688} 735}
689 736
690/* 737/*
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index ef163f06fd16..979735b0c76d 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -1881,6 +1881,7 @@ xfs_dir2_node_to_leaf(
1881 xfs_mount_t *mp; /* filesystem mount point */ 1881 xfs_mount_t *mp; /* filesystem mount point */
1882 int rval; /* successful free trim? */ 1882 int rval; /* successful free trim? */
1883 xfs_trans_t *tp; /* transaction pointer */ 1883 xfs_trans_t *tp; /* transaction pointer */
1884 struct xfs_dir3_icfree_hdr freehdr;
1884 1885
1885 /* 1886 /*
1886 * There's more than a leaf level in the btree, so there must 1887 * There's more than a leaf level in the btree, so there must
@@ -1938,15 +1939,15 @@ xfs_dir2_node_to_leaf(
1938 if (error) 1939 if (error)
1939 return error; 1940 return error;
1940 free = fbp->b_addr; 1941 free = fbp->b_addr;
1941 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); 1942 xfs_dir3_free_hdr_from_disk(&freehdr, free);
1942 ASSERT(!free->hdr.firstdb); 1943
1944 ASSERT(!freehdr.firstdb);
1943 1945
1944 /* 1946 /*
1945 * Now see if the leafn and free data will fit in a leaf1. 1947 * Now see if the leafn and free data will fit in a leaf1.
1946 * If not, release the buffer and give up. 1948 * If not, release the buffer and give up.
1947 */ 1949 */
1948 if (xfs_dir2_leaf_size(&leaf->hdr, be32_to_cpu(free->hdr.nvalid)) > 1950 if (xfs_dir2_leaf_size(&leaf->hdr, freehdr.nvalid) > mp->m_dirblksize) {
1949 mp->m_dirblksize) {
1950 xfs_trans_brelse(tp, fbp); 1951 xfs_trans_brelse(tp, fbp);
1951 return 0; 1952 return 0;
1952 } 1953 }
@@ -1967,12 +1968,12 @@ xfs_dir2_node_to_leaf(
1967 * Set up the leaf tail from the freespace block. 1968 * Set up the leaf tail from the freespace block.
1968 */ 1969 */
1969 ltp = xfs_dir2_leaf_tail_p(mp, leaf); 1970 ltp = xfs_dir2_leaf_tail_p(mp, leaf);
1970 ltp->bestcount = free->hdr.nvalid; 1971 ltp->bestcount = cpu_to_be32(freehdr.nvalid);
1971 /* 1972 /*
1972 * Set up the leaf bests table. 1973 * Set up the leaf bests table.
1973 */ 1974 */
1974 memcpy(xfs_dir2_leaf_bests_p(ltp), free->bests, 1975 memcpy(xfs_dir2_leaf_bests_p(ltp), xfs_dir3_free_bests_p(mp, free),
1975 be32_to_cpu(ltp->bestcount) * sizeof(xfs_dir2_data_off_t)); 1976 freehdr.nvalid * sizeof(xfs_dir2_data_off_t));
1976 xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1); 1977 xfs_dir2_leaf_log_bests(tp, lbp, 0, be32_to_cpu(ltp->bestcount) - 1);
1977 xfs_dir2_leaf_log_tail(tp, lbp); 1978 xfs_dir2_leaf_log_tail(tp, lbp);
1978 xfs_dir2_leaf_check(dp, lbp); 1979 xfs_dir2_leaf_check(dp, lbp);
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index 985d70bc391d..0fe39b9fde7e 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -1,5 +1,6 @@
1/* 1/*
2 * Copyright (c) 2000-2005 Silicon Graphics, Inc. 2 * Copyright (c) 2000-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
@@ -32,6 +33,8 @@
32#include "xfs_dir2_priv.h" 33#include "xfs_dir2_priv.h"
33#include "xfs_error.h" 34#include "xfs_error.h"
34#include "xfs_trace.h" 35#include "xfs_trace.h"
36#include "xfs_buf_item.h"
37#include "xfs_cksum.h"
35 38
36/* 39/*
37 * Function declarations. 40 * Function declarations.
@@ -55,44 +58,78 @@ static int xfs_dir2_leafn_remove(xfs_da_args_t *args, struct xfs_buf *bp,
55static int xfs_dir2_node_addname_int(xfs_da_args_t *args, 58static int xfs_dir2_node_addname_int(xfs_da_args_t *args,
56 xfs_da_state_blk_t *fblk); 59 xfs_da_state_blk_t *fblk);
57 60
58static void 61static bool
59xfs_dir2_free_verify( 62xfs_dir3_free_verify(
60 struct xfs_buf *bp) 63 struct xfs_buf *bp)
61{ 64{
62 struct xfs_mount *mp = bp->b_target->bt_mount; 65 struct xfs_mount *mp = bp->b_target->bt_mount;
63 struct xfs_dir2_free_hdr *hdr = bp->b_addr; 66 struct xfs_dir2_free_hdr *hdr = bp->b_addr;
64 int block_ok = 0;
65 67
66 block_ok = hdr->magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC); 68 if (xfs_sb_version_hascrc(&mp->m_sb)) {
67 if (!block_ok) { 69 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
68 XFS_CORRUPTION_ERROR("xfs_dir2_free_verify magic", 70
69 XFS_ERRLEVEL_LOW, mp, hdr); 71 if (hdr3->magic != cpu_to_be32(XFS_DIR3_FREE_MAGIC))
70 xfs_buf_ioerror(bp, EFSCORRUPTED); 72 return false;
73 if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_uuid))
74 return false;
75 if (be64_to_cpu(hdr3->blkno) != bp->b_bn)
76 return false;
77 } else {
78 if (hdr->magic != cpu_to_be32(XFS_DIR2_FREE_MAGIC))
79 return false;
71 } 80 }
81
82 /* XXX: should bounds check the xfs_dir3_icfree_hdr here */
83
84 return true;
72} 85}
73 86
74static void 87static void
75xfs_dir2_free_read_verify( 88xfs_dir3_free_read_verify(
76 struct xfs_buf *bp) 89 struct xfs_buf *bp)
77{ 90{
78 xfs_dir2_free_verify(bp); 91 struct xfs_mount *mp = bp->b_target->bt_mount;
92
93 if ((xfs_sb_version_hascrc(&mp->m_sb) &&
94 !xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
95 XFS_DIR3_FREE_CRC_OFF)) ||
96 !xfs_dir3_free_verify(bp)) {
97 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
98 xfs_buf_ioerror(bp, EFSCORRUPTED);
99 }
79} 100}
80 101
81static void 102static void
82xfs_dir2_free_write_verify( 103xfs_dir3_free_write_verify(
83 struct xfs_buf *bp) 104 struct xfs_buf *bp)
84{ 105{
85 xfs_dir2_free_verify(bp); 106 struct xfs_mount *mp = bp->b_target->bt_mount;
107 struct xfs_buf_log_item *bip = bp->b_fspriv;
108 struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
109
110 if (!xfs_dir3_free_verify(bp)) {
111 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
112 xfs_buf_ioerror(bp, EFSCORRUPTED);
113 return;
114 }
115
116 if (!xfs_sb_version_hascrc(&mp->m_sb))
117 return;
118
119 if (bip)
120 hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn);
121
122 xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length), XFS_DIR3_FREE_CRC_OFF);
86} 123}
87 124
88static const struct xfs_buf_ops xfs_dir2_free_buf_ops = { 125static const struct xfs_buf_ops xfs_dir3_free_buf_ops = {
89 .verify_read = xfs_dir2_free_read_verify, 126 .verify_read = xfs_dir3_free_read_verify,
90 .verify_write = xfs_dir2_free_write_verify, 127 .verify_write = xfs_dir3_free_write_verify,
91}; 128};
92 129
93 130
94static int 131static int
95__xfs_dir2_free_read( 132__xfs_dir3_free_read(
96 struct xfs_trans *tp, 133 struct xfs_trans *tp,
97 struct xfs_inode *dp, 134 struct xfs_inode *dp,
98 xfs_dablk_t fbno, 135 xfs_dablk_t fbno,
@@ -100,7 +137,7 @@ __xfs_dir2_free_read(
100 struct xfs_buf **bpp) 137 struct xfs_buf **bpp)
101{ 138{
102 return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, 139 return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
103 XFS_DATA_FORK, &xfs_dir2_free_buf_ops); 140 XFS_DATA_FORK, &xfs_dir3_free_buf_ops);
104} 141}
105 142
106int 143int
@@ -110,7 +147,7 @@ xfs_dir2_free_read(
110 xfs_dablk_t fbno, 147 xfs_dablk_t fbno,
111 struct xfs_buf **bpp) 148 struct xfs_buf **bpp)
112{ 149{
113 return __xfs_dir2_free_read(tp, dp, fbno, -1, bpp); 150 return __xfs_dir3_free_read(tp, dp, fbno, -1, bpp);
114} 151}
115 152
116static int 153static int
@@ -120,7 +157,94 @@ xfs_dir2_free_try_read(
120 xfs_dablk_t fbno, 157 xfs_dablk_t fbno,
121 struct xfs_buf **bpp) 158 struct xfs_buf **bpp)
122{ 159{
123 return __xfs_dir2_free_read(tp, dp, fbno, -2, bpp); 160 return __xfs_dir3_free_read(tp, dp, fbno, -2, bpp);
161}
162
163
164void
165xfs_dir3_free_hdr_from_disk(
166 struct xfs_dir3_icfree_hdr *to,
167 struct xfs_dir2_free *from)
168{
169 if (from->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)) {
170 to->magic = be32_to_cpu(from->hdr.magic);
171 to->firstdb = be32_to_cpu(from->hdr.firstdb);
172 to->nvalid = be32_to_cpu(from->hdr.nvalid);
173 to->nused = be32_to_cpu(from->hdr.nused);
174 } else {
175 struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)from;
176
177 to->magic = be32_to_cpu(hdr3->hdr.magic);
178 to->firstdb = be32_to_cpu(hdr3->firstdb);
179 to->nvalid = be32_to_cpu(hdr3->nvalid);
180 to->nused = be32_to_cpu(hdr3->nused);
181 }
182
183 ASSERT(to->magic == XFS_DIR2_FREE_MAGIC ||
184 to->magic == XFS_DIR3_FREE_MAGIC);
185}
186
187static void
188xfs_dir3_free_hdr_to_disk(
189 struct xfs_dir2_free *to,
190 struct xfs_dir3_icfree_hdr *from)
191{
192 ASSERT(from->magic == XFS_DIR2_FREE_MAGIC ||
193 from->magic == XFS_DIR3_FREE_MAGIC);
194
195 if (from->magic == XFS_DIR2_FREE_MAGIC) {
196 to->hdr.magic = cpu_to_be32(from->magic);
197 to->hdr.firstdb = cpu_to_be32(from->firstdb);
198 to->hdr.nvalid = cpu_to_be32(from->nvalid);
199 to->hdr.nused = cpu_to_be32(from->nused);
200 } else {
201 struct xfs_dir3_free_hdr *hdr3 = (struct xfs_dir3_free_hdr *)to;
202
203 hdr3->hdr.magic = cpu_to_be32(from->magic);
204 hdr3->firstdb = cpu_to_be32(from->firstdb);
205 hdr3->nvalid = cpu_to_be32(from->nvalid);
206 hdr3->nused = cpu_to_be32(from->nused);
207 }
208}
209
210static int
211xfs_dir3_free_get_buf(
212 struct xfs_trans *tp,
213 struct xfs_inode *dp,
214 xfs_dir2_db_t fbno,
215 struct xfs_buf **bpp)
216{
217 struct xfs_mount *mp = dp->i_mount;
218 struct xfs_buf *bp;
219 int error;
220 struct xfs_dir3_icfree_hdr hdr;
221
222 error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, fbno),
223 -1, &bp, XFS_DATA_FORK);
224 if (error)
225 return error;
226
227 bp->b_ops = &xfs_dir3_free_buf_ops;
228
229 /*
230 * Initialize the new block to be empty, and remember
231 * its first slot as our empty slot.
232 */
233 hdr.magic = XFS_DIR2_FREE_MAGIC;
234 hdr.firstdb = 0;
235 hdr.nused = 0;
236 hdr.nvalid = 0;
237 if (xfs_sb_version_hascrc(&mp->m_sb)) {
238 struct xfs_dir3_free_hdr *hdr3 = bp->b_addr;
239
240 hdr.magic = XFS_DIR3_FREE_MAGIC;
241 hdr3->hdr.blkno = cpu_to_be64(bp->b_bn);
242 hdr3->hdr.owner = cpu_to_be64(dp->i_ino);
243 uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_uuid);
244 }
245 xfs_dir3_free_hdr_to_disk(bp->b_addr, &hdr);
246 *bpp = bp;
247 return 0;
124} 248}
125 249
126/* 250/*
@@ -134,13 +258,16 @@ xfs_dir2_free_log_bests(
134 int last) /* last entry to log */ 258 int last) /* last entry to log */
135{ 259{
136 xfs_dir2_free_t *free; /* freespace structure */ 260 xfs_dir2_free_t *free; /* freespace structure */
261 __be16 *bests;
137 262
138 free = bp->b_addr; 263 free = bp->b_addr;
139 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); 264 bests = xfs_dir3_free_bests_p(tp->t_mountp, free);
265 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) ||
266 free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC));
140 xfs_trans_log_buf(tp, bp, 267 xfs_trans_log_buf(tp, bp,
141 (uint)((char *)&free->bests[first] - (char *)free), 268 (uint)((char *)&bests[first] - (char *)free),
142 (uint)((char *)&free->bests[last] - (char *)free + 269 (uint)((char *)&bests[last] - (char *)free +
143 sizeof(free->bests[0]) - 1)); 270 sizeof(bests[0]) - 1));
144} 271}
145 272
146/* 273/*
@@ -154,9 +281,9 @@ xfs_dir2_free_log_header(
154 xfs_dir2_free_t *free; /* freespace structure */ 281 xfs_dir2_free_t *free; /* freespace structure */
155 282
156 free = bp->b_addr; 283 free = bp->b_addr;
157 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); 284 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) ||
158 xfs_trans_log_buf(tp, bp, (uint)((char *)&free->hdr - (char *)free), 285 free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC));
159 (uint)(sizeof(xfs_dir2_free_hdr_t) - 1)); 286 xfs_trans_log_buf(tp, bp, 0, xfs_dir3_free_hdr_size(tp->t_mountp) - 1);
160} 287}
161 288
162/* 289/*
@@ -183,6 +310,7 @@ xfs_dir2_leaf_to_node(
183 xfs_dir2_data_off_t off; /* freespace entry value */ 310 xfs_dir2_data_off_t off; /* freespace entry value */
184 __be16 *to; /* pointer to freespace entry */ 311 __be16 *to; /* pointer to freespace entry */
185 xfs_trans_t *tp; /* transaction pointer */ 312 xfs_trans_t *tp; /* transaction pointer */
313 struct xfs_dir3_icfree_hdr freehdr;
186 314
187 trace_xfs_dir2_leaf_to_node(args); 315 trace_xfs_dir2_leaf_to_node(args);
188 316
@@ -199,43 +327,43 @@ xfs_dir2_leaf_to_node(
199 /* 327 /*
200 * Get the buffer for the new freespace block. 328 * Get the buffer for the new freespace block.
201 */ 329 */
202 error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb), -1, &fbp, 330 error = xfs_dir3_free_get_buf(tp, dp, fdb, &fbp);
203 XFS_DATA_FORK);
204 if (error) 331 if (error)
205 return error; 332 return error;
206 fbp->b_ops = &xfs_dir2_free_buf_ops;
207 333
208 free = fbp->b_addr; 334 free = fbp->b_addr;
335 xfs_dir3_free_hdr_from_disk(&freehdr, free);
209 leaf = lbp->b_addr; 336 leaf = lbp->b_addr;
210 ltp = xfs_dir2_leaf_tail_p(mp, leaf); 337 ltp = xfs_dir2_leaf_tail_p(mp, leaf);
211 /* 338 ASSERT(be32_to_cpu(ltp->bestcount) <=
212 * Initialize the freespace block header. 339 (uint)dp->i_d.di_size / mp->m_dirblksize);
213 */ 340
214 free->hdr.magic = cpu_to_be32(XFS_DIR2_FREE_MAGIC);
215 free->hdr.firstdb = 0;
216 ASSERT(be32_to_cpu(ltp->bestcount) <= (uint)dp->i_d.di_size / mp->m_dirblksize);
217 free->hdr.nvalid = ltp->bestcount;
218 /* 341 /*
219 * Copy freespace entries from the leaf block to the new block. 342 * Copy freespace entries from the leaf block to the new block.
220 * Count active entries. 343 * Count active entries.
221 */ 344 */
222 for (i = n = 0, from = xfs_dir2_leaf_bests_p(ltp), to = free->bests; 345 from = xfs_dir2_leaf_bests_p(ltp);
223 i < be32_to_cpu(ltp->bestcount); i++, from++, to++) { 346 to = xfs_dir3_free_bests_p(mp, free);
347 for (i = n = 0; i < be32_to_cpu(ltp->bestcount); i++, from++, to++) {
224 if ((off = be16_to_cpu(*from)) != NULLDATAOFF) 348 if ((off = be16_to_cpu(*from)) != NULLDATAOFF)
225 n++; 349 n++;
226 *to = cpu_to_be16(off); 350 *to = cpu_to_be16(off);
227 } 351 }
228 free->hdr.nused = cpu_to_be32(n);
229
230 lbp->b_ops = &xfs_dir2_leafn_buf_ops;
231 leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAFN_MAGIC);
232 352
233 /* 353 /*
234 * Log everything. 354 * Now initialize the freespace block header.
235 */ 355 */
236 xfs_dir2_leaf_log_header(tp, lbp); 356 freehdr.nused = n;
357 freehdr.nvalid = be32_to_cpu(ltp->bestcount);
358
359 xfs_dir3_free_hdr_to_disk(fbp->b_addr, &freehdr);
360 xfs_dir2_free_log_bests(tp, fbp, 0, freehdr.nvalid - 1);
237 xfs_dir2_free_log_header(tp, fbp); 361 xfs_dir2_free_log_header(tp, fbp);
238 xfs_dir2_free_log_bests(tp, fbp, 0, be32_to_cpu(free->hdr.nvalid) - 1); 362
363 /* convert the leaf to a leafnode */
364 leaf->hdr.info.magic = cpu_to_be16(XFS_DIR2_LEAFN_MAGIC);
365 lbp->b_ops = &xfs_dir2_leafn_buf_ops;
366 xfs_dir2_leaf_log_header(tp, lbp);
239 xfs_dir2_leafn_check(dp, lbp); 367 xfs_dir2_leafn_check(dp, lbp);
240 return 0; 368 return 0;
241} 369}
@@ -354,6 +482,23 @@ xfs_dir2_leafn_check(
354 } 482 }
355 ASSERT(be16_to_cpu(leaf->hdr.stale) == stale); 483 ASSERT(be16_to_cpu(leaf->hdr.stale) == stale);
356} 484}
485
486static void
487xfs_dir2_free_hdr_check(
488 struct xfs_mount *mp,
489 struct xfs_buf *bp,
490 xfs_dir2_db_t db)
491{
492 struct xfs_dir3_icfree_hdr hdr;
493
494 xfs_dir3_free_hdr_from_disk(&hdr, bp->b_addr);
495
496 ASSERT((hdr.firstdb % xfs_dir3_free_max_bests(mp)) == 0);
497 ASSERT(hdr.firstdb <= db);
498 ASSERT(db < hdr.firstdb + hdr.nvalid);
499}
500#else
501#define xfs_dir2_free_hdr_check(mp, dp, db)
357#endif /* DEBUG */ 502#endif /* DEBUG */
358 503
359/* 504/*
@@ -424,7 +569,8 @@ xfs_dir2_leafn_lookup_for_addname(
424 curbp = state->extrablk.bp; 569 curbp = state->extrablk.bp;
425 curfdb = state->extrablk.blkno; 570 curfdb = state->extrablk.blkno;
426 free = curbp->b_addr; 571 free = curbp->b_addr;
427 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); 572 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) ||
573 free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC));
428 } 574 }
429 length = xfs_dir2_data_entsize(args->namelen); 575 length = xfs_dir2_data_entsize(args->namelen);
430 /* 576 /*
@@ -451,6 +597,8 @@ xfs_dir2_leafn_lookup_for_addname(
451 * in hand, take a look at it. 597 * in hand, take a look at it.
452 */ 598 */
453 if (newdb != curdb) { 599 if (newdb != curdb) {
600 __be16 *bests;
601
454 curdb = newdb; 602 curdb = newdb;
455 /* 603 /*
456 * Convert the data block to the free block 604 * Convert the data block to the free block
@@ -473,13 +621,8 @@ xfs_dir2_leafn_lookup_for_addname(
473 if (error) 621 if (error)
474 return error; 622 return error;
475 free = curbp->b_addr; 623 free = curbp->b_addr;
476 ASSERT(be32_to_cpu(free->hdr.magic) == 624
477 XFS_DIR2_FREE_MAGIC); 625 xfs_dir2_free_hdr_check(mp, curbp, curdb);
478 ASSERT((be32_to_cpu(free->hdr.firstdb) %
479 xfs_dir2_free_max_bests(mp)) == 0);
480 ASSERT(be32_to_cpu(free->hdr.firstdb) <= curdb);
481 ASSERT(curdb < be32_to_cpu(free->hdr.firstdb) +
482 be32_to_cpu(free->hdr.nvalid));
483 } 626 }
484 /* 627 /*
485 * Get the index for our entry. 628 * Get the index for our entry.
@@ -488,8 +631,8 @@ xfs_dir2_leafn_lookup_for_addname(
488 /* 631 /*
489 * If it has room, return it. 632 * If it has room, return it.
490 */ 633 */
491 if (unlikely(free->bests[fi] == 634 bests = xfs_dir3_free_bests_p(mp, free);
492 cpu_to_be16(NULLDATAOFF))) { 635 if (unlikely(bests[fi] == cpu_to_be16(NULLDATAOFF))) {
493 XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", 636 XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int",
494 XFS_ERRLEVEL_LOW, mp); 637 XFS_ERRLEVEL_LOW, mp);
495 if (curfdb != newfdb) 638 if (curfdb != newfdb)
@@ -497,7 +640,7 @@ xfs_dir2_leafn_lookup_for_addname(
497 return XFS_ERROR(EFSCORRUPTED); 640 return XFS_ERROR(EFSCORRUPTED);
498 } 641 }
499 curfdb = newfdb; 642 curfdb = newfdb;
500 if (be16_to_cpu(free->bests[fi]) >= length) 643 if (be16_to_cpu(bests[fi]) >= length)
501 goto out; 644 goto out;
502 } 645 }
503 } 646 }
@@ -511,6 +654,12 @@ out:
511 state->extrablk.bp = curbp; 654 state->extrablk.bp = curbp;
512 state->extrablk.index = fi; 655 state->extrablk.index = fi;
513 state->extrablk.blkno = curfdb; 656 state->extrablk.blkno = curfdb;
657
658 /*
659 * Important: this magic number is not in the buffer - it's for
660 * buffer type information and therefore only the free/data type
661 * matters here, not whether CRCs are enabled or not.
662 */
514 state->extrablk.magic = XFS_DIR2_FREE_MAGIC; 663 state->extrablk.magic = XFS_DIR2_FREE_MAGIC;
515 } else { 664 } else {
516 state->extravalid = 0; 665 state->extravalid = 0;
@@ -898,7 +1047,7 @@ xfs_dir2_leafn_rebalance(
898} 1047}
899 1048
900static int 1049static int
901xfs_dir2_data_block_free( 1050xfs_dir3_data_block_free(
902 xfs_da_args_t *args, 1051 xfs_da_args_t *args,
903 struct xfs_dir2_data_hdr *hdr, 1052 struct xfs_dir2_data_hdr *hdr,
904 struct xfs_dir2_free *free, 1053 struct xfs_dir2_free *free,
@@ -909,57 +1058,66 @@ xfs_dir2_data_block_free(
909{ 1058{
910 struct xfs_trans *tp = args->trans; 1059 struct xfs_trans *tp = args->trans;
911 int logfree = 0; 1060 int logfree = 0;
1061 __be16 *bests;
1062 struct xfs_dir3_icfree_hdr freehdr;
912 1063
913 if (!hdr) { 1064 xfs_dir3_free_hdr_from_disk(&freehdr, free);
914 /* One less used entry in the free table. */
915 be32_add_cpu(&free->hdr.nused, -1);
916 xfs_dir2_free_log_header(tp, fbp);
917 1065
1066 bests = xfs_dir3_free_bests_p(tp->t_mountp, free);
1067 if (hdr) {
918 /* 1068 /*
919 * If this was the last entry in the table, we can trim the 1069 * Data block is not empty, just set the free entry to the new
920 * table size back. There might be other entries at the end 1070 * value.
921 * referring to non-existent data blocks, get those too.
922 */ 1071 */
923 if (findex == be32_to_cpu(free->hdr.nvalid) - 1) { 1072 bests[findex] = cpu_to_be16(longest);
924 int i; /* free entry index */ 1073 xfs_dir2_free_log_bests(tp, fbp, findex, findex);
1074 return 0;
1075 }
925 1076
926 for (i = findex - 1; i >= 0; i--) { 1077 /* One less used entry in the free table. */
927 if (free->bests[i] != cpu_to_be16(NULLDATAOFF)) 1078 freehdr.nused--;
928 break;
929 }
930 free->hdr.nvalid = cpu_to_be32(i + 1);
931 logfree = 0;
932 } else {
933 /* Not the last entry, just punch it out. */
934 free->bests[findex] = cpu_to_be16(NULLDATAOFF);
935 logfree = 1;
936 }
937 /*
938 * If there are no useful entries left in the block,
939 * get rid of the block if we can.
940 */
941 if (!free->hdr.nused) {
942 int error;
943 1079
944 error = xfs_dir2_shrink_inode(args, fdb, fbp); 1080 /*
945 if (error == 0) { 1081 * If this was the last entry in the table, we can trim the table size
946 fbp = NULL; 1082 * back. There might be other entries at the end referring to
947 logfree = 0; 1083 * non-existent data blocks, get those too.
948 } else if (error != ENOSPC || args->total != 0) 1084 */
949 return error; 1085 if (findex == freehdr.nvalid - 1) {
950 /* 1086 int i; /* free entry index */
951 * It's possible to get ENOSPC if there is no 1087
952 * space reservation. In this case some one 1088 for (i = findex - 1; i >= 0; i--) {
953 * else will eventually get rid of this block. 1089 if (bests[i] != cpu_to_be16(NULLDATAOFF))
954 */ 1090 break;
955 } 1091 }
1092 freehdr.nvalid = i + 1;
1093 logfree = 0;
956 } else { 1094 } else {
1095 /* Not the last entry, just punch it out. */
1096 bests[findex] = cpu_to_be16(NULLDATAOFF);
1097 logfree = 1;
1098 }
1099
1100 xfs_dir3_free_hdr_to_disk(free, &freehdr);
1101 xfs_dir2_free_log_header(tp, fbp);
1102
1103 /*
1104 * If there are no useful entries left in the block, get rid of the
1105 * block if we can.
1106 */
1107 if (!freehdr.nused) {
1108 int error;
1109
1110 error = xfs_dir2_shrink_inode(args, fdb, fbp);
1111 if (error == 0) {
1112 fbp = NULL;
1113 logfree = 0;
1114 } else if (error != ENOSPC || args->total != 0)
1115 return error;
957 /* 1116 /*
958 * Data block is not empty, just set the free entry to the new 1117 * It's possible to get ENOSPC if there is no
959 * value. 1118 * space reservation. In this case some one
1119 * else will eventually get rid of this block.
960 */ 1120 */
961 free->bests[findex] = cpu_to_be16(longest);
962 logfree = 1;
963 } 1121 }
964 1122
965 /* Log the free entry that changed, unless we got rid of it. */ 1123 /* Log the free entry that changed, unless we got rid of it. */
@@ -1062,10 +1220,14 @@ xfs_dir2_leafn_remove(
1062 if (error) 1220 if (error)
1063 return error; 1221 return error;
1064 free = fbp->b_addr; 1222 free = fbp->b_addr;
1065 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); 1223#ifdef DEBUG
1066 ASSERT(be32_to_cpu(free->hdr.firstdb) == 1224 {
1067 xfs_dir2_free_max_bests(mp) * 1225 struct xfs_dir3_icfree_hdr freehdr;
1068 (fdb - XFS_DIR2_FREE_FIRSTDB(mp))); 1226 xfs_dir3_free_hdr_from_disk(&freehdr, free);
1227 ASSERT(freehdr.firstdb == xfs_dir3_free_max_bests(mp) *
1228 (fdb - XFS_DIR2_FREE_FIRSTDB(mp)));
1229 }
1230#endif
1069 /* 1231 /*
1070 * Calculate which entry we need to fix. 1232 * Calculate which entry we need to fix.
1071 */ 1233 */
@@ -1096,7 +1258,7 @@ xfs_dir2_leafn_remove(
1096 * If we got rid of the data block, we can eliminate that entry 1258 * If we got rid of the data block, we can eliminate that entry
1097 * in the free block. 1259 * in the free block.
1098 */ 1260 */
1099 error = xfs_dir2_data_block_free(args, hdr, free, 1261 error = xfs_dir3_data_block_free(args, hdr, free,
1100 fdb, findex, fbp, longest); 1262 fdb, findex, fbp, longest);
1101 if (error) 1263 if (error)
1102 return error; 1264 return error;
@@ -1447,6 +1609,8 @@ xfs_dir2_node_addname_int(
1447 int needscan; /* need to rescan data frees */ 1609 int needscan; /* need to rescan data frees */
1448 __be16 *tagp; /* data entry tag pointer */ 1610 __be16 *tagp; /* data entry tag pointer */
1449 xfs_trans_t *tp; /* transaction pointer */ 1611 xfs_trans_t *tp; /* transaction pointer */
1612 __be16 *bests;
1613 struct xfs_dir3_icfree_hdr freehdr;
1450 1614
1451 dp = args->dp; 1615 dp = args->dp;
1452 mp = dp->i_mount; 1616 mp = dp->i_mount;
@@ -1464,36 +1628,37 @@ xfs_dir2_node_addname_int(
1464 */ 1628 */
1465 ifbno = fblk->blkno; 1629 ifbno = fblk->blkno;
1466 free = fbp->b_addr; 1630 free = fbp->b_addr;
1467 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
1468 findex = fblk->index; 1631 findex = fblk->index;
1632 bests = xfs_dir3_free_bests_p(mp, free);
1633 xfs_dir3_free_hdr_from_disk(&freehdr, free);
1634
1469 /* 1635 /*
1470 * This means the free entry showed that the data block had 1636 * This means the free entry showed that the data block had
1471 * space for our entry, so we remembered it. 1637 * space for our entry, so we remembered it.
1472 * Use that data block. 1638 * Use that data block.
1473 */ 1639 */
1474 if (findex >= 0) { 1640 if (findex >= 0) {
1475 ASSERT(findex < be32_to_cpu(free->hdr.nvalid)); 1641 ASSERT(findex < freehdr.nvalid);
1476 ASSERT(be16_to_cpu(free->bests[findex]) != NULLDATAOFF); 1642 ASSERT(be16_to_cpu(bests[findex]) != NULLDATAOFF);
1477 ASSERT(be16_to_cpu(free->bests[findex]) >= length); 1643 ASSERT(be16_to_cpu(bests[findex]) >= length);
1478 dbno = be32_to_cpu(free->hdr.firstdb) + findex; 1644 dbno = freehdr.firstdb + findex;
1479 } 1645 } else {
1480 /* 1646 /*
1481 * The data block looked at didn't have enough room. 1647 * The data block looked at didn't have enough room.
1482 * We'll start at the beginning of the freespace entries. 1648 * We'll start at the beginning of the freespace entries.
1483 */ 1649 */
1484 else {
1485 dbno = -1; 1650 dbno = -1;
1486 findex = 0; 1651 findex = 0;
1487 } 1652 }
1488 } 1653 } else {
1489 /* 1654 /*
1490 * Didn't come in with a freespace block, so don't have a data block. 1655 * Didn't come in with a freespace block, so no data block.
1491 */ 1656 */
1492 else {
1493 ifbno = dbno = -1; 1657 ifbno = dbno = -1;
1494 fbp = NULL; 1658 fbp = NULL;
1495 findex = 0; 1659 findex = 0;
1496 } 1660 }
1661
1497 /* 1662 /*
1498 * If we don't have a data block yet, we're going to scan the 1663 * If we don't have a data block yet, we're going to scan the
1499 * freespace blocks looking for one. Figure out what the 1664 * freespace blocks looking for one. Figure out what the
@@ -1547,20 +1712,26 @@ xfs_dir2_node_addname_int(
1547 if (!fbp) 1712 if (!fbp)
1548 continue; 1713 continue;
1549 free = fbp->b_addr; 1714 free = fbp->b_addr;
1550 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
1551 findex = 0; 1715 findex = 0;
1552 } 1716 }
1553 /* 1717 /*
1554 * Look at the current free entry. Is it good enough? 1718 * Look at the current free entry. Is it good enough?
1719 *
1720 * The bests initialisation should be where the bufer is read in
1721 * the above branch. But gcc is too stupid to realise that bests
1722 * and the freehdr are actually initialised if they are placed
1723 * there, so we have to do it here to avoid warnings. Blech.
1555 */ 1724 */
1556 if (be16_to_cpu(free->bests[findex]) != NULLDATAOFF && 1725 bests = xfs_dir3_free_bests_p(mp, free);
1557 be16_to_cpu(free->bests[findex]) >= length) 1726 xfs_dir3_free_hdr_from_disk(&freehdr, free);
1558 dbno = be32_to_cpu(free->hdr.firstdb) + findex; 1727 if (be16_to_cpu(bests[findex]) != NULLDATAOFF &&
1728 be16_to_cpu(bests[findex]) >= length)
1729 dbno = freehdr.firstdb + findex;
1559 else { 1730 else {
1560 /* 1731 /*
1561 * Are we done with the freeblock? 1732 * Are we done with the freeblock?
1562 */ 1733 */
1563 if (++findex == be32_to_cpu(free->hdr.nvalid)) { 1734 if (++findex == freehdr.nvalid) {
1564 /* 1735 /*
1565 * Drop the block. 1736 * Drop the block.
1566 */ 1737 */
@@ -1614,11 +1785,11 @@ xfs_dir2_node_addname_int(
1614 * If there wasn't a freespace block, the read will 1785 * If there wasn't a freespace block, the read will
1615 * return a NULL fbp. Allocate and initialize a new one. 1786 * return a NULL fbp. Allocate and initialize a new one.
1616 */ 1787 */
1617 if( fbp == NULL ) { 1788 if (!fbp) {
1618 if ((error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE, 1789 error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE,
1619 &fbno))) { 1790 &fbno);
1791 if (error)
1620 return error; 1792 return error;
1621 }
1622 1793
1623 if (unlikely(xfs_dir2_db_to_fdb(mp, dbno) != fbno)) { 1794 if (unlikely(xfs_dir2_db_to_fdb(mp, dbno) != fbno)) {
1624 xfs_alert(mp, 1795 xfs_alert(mp,
@@ -1646,27 +1817,24 @@ xfs_dir2_node_addname_int(
1646 /* 1817 /*
1647 * Get a buffer for the new block. 1818 * Get a buffer for the new block.
1648 */ 1819 */
1649 error = xfs_da_get_buf(tp, dp, 1820 error = xfs_dir3_free_get_buf(tp, dp, fbno, &fbp);
1650 xfs_dir2_db_to_da(mp, fbno),
1651 -1, &fbp, XFS_DATA_FORK);
1652 if (error) 1821 if (error)
1653 return error; 1822 return error;
1654 fbp->b_ops = &xfs_dir2_free_buf_ops; 1823 free = fbp->b_addr;
1824 bests = xfs_dir3_free_bests_p(mp, free);
1825 xfs_dir3_free_hdr_from_disk(&freehdr, free);
1655 1826
1656 /* 1827 /*
1657 * Initialize the new block to be empty, and remember 1828 * Remember the first slot as our empty slot.
1658 * its first slot as our empty slot.
1659 */ 1829 */
1660 free = fbp->b_addr; 1830 freehdr.firstdb = (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) *
1661 free->hdr.magic = cpu_to_be32(XFS_DIR2_FREE_MAGIC); 1831 xfs_dir3_free_max_bests(mp);
1662 free->hdr.firstdb = cpu_to_be32(
1663 (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) *
1664 xfs_dir2_free_max_bests(mp));
1665 free->hdr.nvalid = 0; 1832 free->hdr.nvalid = 0;
1666 free->hdr.nused = 0; 1833 free->hdr.nused = 0;
1667 } else { 1834 } else {
1668 free = fbp->b_addr; 1835 free = fbp->b_addr;
1669 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); 1836 bests = xfs_dir3_free_bests_p(mp, free);
1837 xfs_dir3_free_hdr_from_disk(&freehdr, free);
1670 } 1838 }
1671 1839
1672 /* 1840 /*
@@ -1677,20 +1845,21 @@ xfs_dir2_node_addname_int(
1677 * If it's after the end of the current entries in the 1845 * If it's after the end of the current entries in the
1678 * freespace block, extend that table. 1846 * freespace block, extend that table.
1679 */ 1847 */
1680 if (findex >= be32_to_cpu(free->hdr.nvalid)) { 1848 if (findex >= freehdr.nvalid) {
1681 ASSERT(findex < xfs_dir2_free_max_bests(mp)); 1849 ASSERT(findex < xfs_dir3_free_max_bests(mp));
1682 free->hdr.nvalid = cpu_to_be32(findex + 1); 1850 freehdr.nvalid = findex + 1;
1683 /* 1851 /*
1684 * Tag new entry so nused will go up. 1852 * Tag new entry so nused will go up.
1685 */ 1853 */
1686 free->bests[findex] = cpu_to_be16(NULLDATAOFF); 1854 bests[findex] = cpu_to_be16(NULLDATAOFF);
1687 } 1855 }
1688 /* 1856 /*
1689 * If this entry was for an empty data block 1857 * If this entry was for an empty data block
1690 * (this should always be true) then update the header. 1858 * (this should always be true) then update the header.
1691 */ 1859 */
1692 if (free->bests[findex] == cpu_to_be16(NULLDATAOFF)) { 1860 if (bests[findex] == cpu_to_be16(NULLDATAOFF)) {
1693 be32_add_cpu(&free->hdr.nused, 1); 1861 freehdr.nused++;
1862 xfs_dir3_free_hdr_to_disk(fbp->b_addr, &freehdr);
1694 xfs_dir2_free_log_header(tp, fbp); 1863 xfs_dir2_free_log_header(tp, fbp);
1695 } 1864 }
1696 /* 1865 /*
@@ -1699,7 +1868,7 @@ xfs_dir2_node_addname_int(
1699 * change again. 1868 * change again.
1700 */ 1869 */
1701 hdr = dbp->b_addr; 1870 hdr = dbp->b_addr;
1702 free->bests[findex] = hdr->bestfree[0].length; 1871 bests[findex] = hdr->bestfree[0].length;
1703 logfree = 1; 1872 logfree = 1;
1704 } 1873 }
1705 /* 1874 /*
@@ -1758,8 +1927,9 @@ xfs_dir2_node_addname_int(
1758 /* 1927 /*
1759 * If the freespace entry is now wrong, update it. 1928 * If the freespace entry is now wrong, update it.
1760 */ 1929 */
1761 if (be16_to_cpu(free->bests[findex]) != be16_to_cpu(hdr->bestfree[0].length)) { 1930 bests = xfs_dir3_free_bests_p(mp, free); /* gcc is so stupid */
1762 free->bests[findex] = hdr->bestfree[0].length; 1931 if (be16_to_cpu(bests[findex]) != be16_to_cpu(hdr->bestfree[0].length)) {
1932 bests[findex] = hdr->bestfree[0].length;
1763 logfree = 1; 1933 logfree = 1;
1764 } 1934 }
1765 /* 1935 /*
@@ -1995,6 +2165,7 @@ xfs_dir2_node_trim_free(
1995 xfs_dir2_free_t *free; /* freespace structure */ 2165 xfs_dir2_free_t *free; /* freespace structure */
1996 xfs_mount_t *mp; /* filesystem mount point */ 2166 xfs_mount_t *mp; /* filesystem mount point */
1997 xfs_trans_t *tp; /* transaction pointer */ 2167 xfs_trans_t *tp; /* transaction pointer */
2168 struct xfs_dir3_icfree_hdr freehdr;
1998 2169
1999 dp = args->dp; 2170 dp = args->dp;
2000 mp = dp->i_mount; 2171 mp = dp->i_mount;
@@ -2012,11 +2183,12 @@ xfs_dir2_node_trim_free(
2012 if (!bp) 2183 if (!bp)
2013 return 0; 2184 return 0;
2014 free = bp->b_addr; 2185 free = bp->b_addr;
2015 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); 2186 xfs_dir3_free_hdr_from_disk(&freehdr, free);
2187
2016 /* 2188 /*
2017 * If there are used entries, there's nothing to do. 2189 * If there are used entries, there's nothing to do.
2018 */ 2190 */
2019 if (be32_to_cpu(free->hdr.nused) > 0) { 2191 if (freehdr.nused > 0) {
2020 xfs_trans_brelse(tp, bp); 2192 xfs_trans_brelse(tp, bp);
2021 *rvalp = 0; 2193 *rvalp = 0;
2022 return 0; 2194 return 0;