aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2012-11-12 06:54:11 -0500
committerBen Myers <bpm@sgi.com>2012-11-15 22:34:39 -0500
commit20f7e9f3726a27cccade65c28265eef8ca50eecb (patch)
tree0f3a297d5218d628a9263609fe624c33755f79bc /fs
parent4bb20a83a2a5ac4dcb62780c9950e47939956126 (diff)
xfs: factor dir2 block read operations
In preparation for verifying dir2 block format buffers, factor the read operations out of the block operations (lookup, addname, getdents) and some of the additional logic to make it easier to understand an dmodify the code. 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.c386
1 files changed, 209 insertions, 177 deletions
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index 53666ca6c953..25ce409487be 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -56,6 +56,178 @@ xfs_dir_startup(void)
56 xfs_dir_hash_dotdot = xfs_da_hashname((unsigned char *)"..", 2); 56 xfs_dir_hash_dotdot = xfs_da_hashname((unsigned char *)"..", 2);
57} 57}
58 58
59static int
60xfs_dir2_block_read(
61 struct xfs_trans *tp,
62 struct xfs_inode *dp,
63 struct xfs_buf **bpp)
64{
65 struct xfs_mount *mp = dp->i_mount;
66
67 return xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, bpp,
68 XFS_DATA_FORK, NULL);
69}
70
71static void
72xfs_dir2_block_need_space(
73 struct xfs_dir2_data_hdr *hdr,
74 struct xfs_dir2_block_tail *btp,
75 struct xfs_dir2_leaf_entry *blp,
76 __be16 **tagpp,
77 struct xfs_dir2_data_unused **dupp,
78 struct xfs_dir2_data_unused **enddupp,
79 int *compact,
80 int len)
81{
82 struct xfs_dir2_data_free *bf;
83 __be16 *tagp = NULL;
84 struct xfs_dir2_data_unused *dup = NULL;
85 struct xfs_dir2_data_unused *enddup = NULL;
86
87 *compact = 0;
88 bf = hdr->bestfree;
89
90 /*
91 * If there are stale entries we'll use one for the leaf.
92 */
93 if (btp->stale) {
94 if (be16_to_cpu(bf[0].length) >= len) {
95 /*
96 * The biggest entry enough to avoid compaction.
97 */
98 dup = (xfs_dir2_data_unused_t *)
99 ((char *)hdr + be16_to_cpu(bf[0].offset));
100 goto out;
101 }
102
103 /*
104 * Will need to compact to make this work.
105 * Tag just before the first leaf entry.
106 */
107 *compact = 1;
108 tagp = (__be16 *)blp - 1;
109
110 /* Data object just before the first leaf entry. */
111 dup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
112
113 /*
114 * If it's not free then the data will go where the
115 * leaf data starts now, if it works at all.
116 */
117 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
118 if (be16_to_cpu(dup->length) + (be32_to_cpu(btp->stale) - 1) *
119 (uint)sizeof(*blp) < len)
120 dup = NULL;
121 } else if ((be32_to_cpu(btp->stale) - 1) * (uint)sizeof(*blp) < len)
122 dup = NULL;
123 else
124 dup = (xfs_dir2_data_unused_t *)blp;
125 goto out;
126 }
127
128 /*
129 * no stale entries, so just use free space.
130 * Tag just before the first leaf entry.
131 */
132 tagp = (__be16 *)blp - 1;
133
134 /* Data object just before the first leaf entry. */
135 enddup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
136
137 /*
138 * If it's not free then can't do this add without cleaning up:
139 * the space before the first leaf entry needs to be free so it
140 * can be expanded to hold the pointer to the new entry.
141 */
142 if (be16_to_cpu(enddup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
143 /*
144 * Check out the biggest freespace and see if it's the same one.
145 */
146 dup = (xfs_dir2_data_unused_t *)
147 ((char *)hdr + be16_to_cpu(bf[0].offset));
148 if (dup != enddup) {
149 /*
150 * Not the same free entry, just check its length.
151 */
152 if (be16_to_cpu(dup->length) < len)
153 dup = NULL;
154 goto out;
155 }
156
157 /*
158 * It is the biggest freespace, can it hold the leaf too?
159 */
160 if (be16_to_cpu(dup->length) < len + (uint)sizeof(*blp)) {
161 /*
162 * Yes, use the second-largest entry instead if it works.
163 */
164 if (be16_to_cpu(bf[1].length) >= len)
165 dup = (xfs_dir2_data_unused_t *)
166 ((char *)hdr + be16_to_cpu(bf[1].offset));
167 else
168 dup = NULL;
169 }
170 }
171out:
172 *tagpp = tagp;
173 *dupp = dup;
174 *enddupp = enddup;
175}
176
177/*
178 * compact the leaf entries.
179 * Leave the highest-numbered stale entry stale.
180 * XXX should be the one closest to mid but mid is not yet computed.
181 */
182static void
183xfs_dir2_block_compact(
184 struct xfs_trans *tp,
185 struct xfs_buf *bp,
186 struct xfs_dir2_data_hdr *hdr,
187 struct xfs_dir2_block_tail *btp,
188 struct xfs_dir2_leaf_entry *blp,
189 int *needlog,
190 int *lfloghigh,
191 int *lfloglow)
192{
193 int fromidx; /* source leaf index */
194 int toidx; /* target leaf index */
195 int needscan = 0;
196 int highstale; /* high stale index */
197
198 fromidx = toidx = be32_to_cpu(btp->count) - 1;
199 highstale = *lfloghigh = -1;
200 for (; fromidx >= 0; fromidx--) {
201 if (blp[fromidx].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) {
202 if (highstale == -1)
203 highstale = toidx;
204 else {
205 if (*lfloghigh == -1)
206 *lfloghigh = toidx;
207 continue;
208 }
209 }
210 if (fromidx < toidx)
211 blp[toidx] = blp[fromidx];
212 toidx--;
213 }
214 *lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1);
215 *lfloghigh -= be32_to_cpu(btp->stale) - 1;
216 be32_add_cpu(&btp->count, -(be32_to_cpu(btp->stale) - 1));
217 xfs_dir2_data_make_free(tp, bp,
218 (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr),
219 (xfs_dir2_data_aoff_t)((be32_to_cpu(btp->stale) - 1) * sizeof(*blp)),
220 needlog, &needscan);
221 blp += be32_to_cpu(btp->stale) - 1;
222 btp->stale = cpu_to_be32(1);
223 /*
224 * If we now need to rebuild the bestfree map, do so.
225 * This needs to happen before the next call to use_free.
226 */
227 if (needscan)
228 xfs_dir2_data_freescan(tp->t_mountp, hdr, needlog);
229}
230
59/* 231/*
60 * Add an entry to a block directory. 232 * Add an entry to a block directory.
61 */ 233 */
@@ -63,7 +235,6 @@ int /* error */
63xfs_dir2_block_addname( 235xfs_dir2_block_addname(
64 xfs_da_args_t *args) /* directory op arguments */ 236 xfs_da_args_t *args) /* directory op arguments */
65{ 237{
66 xfs_dir2_data_free_t *bf; /* bestfree table in block */
67 xfs_dir2_data_hdr_t *hdr; /* block header */ 238 xfs_dir2_data_hdr_t *hdr; /* block header */
68 xfs_dir2_leaf_entry_t *blp; /* block leaf entries */ 239 xfs_dir2_leaf_entry_t *blp; /* block leaf entries */
69 struct xfs_buf *bp; /* buffer for block */ 240 struct xfs_buf *bp; /* buffer for block */
@@ -94,134 +265,44 @@ xfs_dir2_block_addname(
94 dp = args->dp; 265 dp = args->dp;
95 tp = args->trans; 266 tp = args->trans;
96 mp = dp->i_mount; 267 mp = dp->i_mount;
97 /* 268
98 * Read the (one and only) directory block into dabuf bp. 269 /* Read the (one and only) directory block into bp. */
99 */ 270 error = xfs_dir2_block_read(tp, dp, &bp);
100 error = xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, &bp,
101 XFS_DATA_FORK, NULL);
102 if (error) 271 if (error)
103 return error; 272 return error;
104 ASSERT(bp != NULL); 273
105 hdr = bp->b_addr;
106 /*
107 * Check the magic number, corrupted if wrong.
108 */
109 if (unlikely(hdr->magic != cpu_to_be32(XFS_DIR2_BLOCK_MAGIC))) {
110 XFS_CORRUPTION_ERROR("xfs_dir2_block_addname",
111 XFS_ERRLEVEL_LOW, mp, hdr);
112 xfs_trans_brelse(tp, bp);
113 return XFS_ERROR(EFSCORRUPTED);
114 }
115 len = xfs_dir2_data_entsize(args->namelen); 274 len = xfs_dir2_data_entsize(args->namelen);
275
116 /* 276 /*
117 * Set up pointers to parts of the block. 277 * Set up pointers to parts of the block.
118 */ 278 */
119 bf = hdr->bestfree; 279 hdr = bp->b_addr;
120 btp = xfs_dir2_block_tail_p(mp, hdr); 280 btp = xfs_dir2_block_tail_p(mp, hdr);
121 blp = xfs_dir2_block_leaf_p(btp); 281 blp = xfs_dir2_block_leaf_p(btp);
282
122 /* 283 /*
123 * No stale entries? Need space for entry and new leaf. 284 * Find out if we can reuse stale entries or whether we need extra
124 */ 285 * space for entry and new leaf.
125 if (!btp->stale) {
126 /*
127 * Tag just before the first leaf entry.
128 */
129 tagp = (__be16 *)blp - 1;
130 /*
131 * Data object just before the first leaf entry.
132 */
133 enddup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
134 /*
135 * If it's not free then can't do this add without cleaning up:
136 * the space before the first leaf entry needs to be free so it
137 * can be expanded to hold the pointer to the new entry.
138 */
139 if (be16_to_cpu(enddup->freetag) != XFS_DIR2_DATA_FREE_TAG)
140 dup = enddup = NULL;
141 /*
142 * Check out the biggest freespace and see if it's the same one.
143 */
144 else {
145 dup = (xfs_dir2_data_unused_t *)
146 ((char *)hdr + be16_to_cpu(bf[0].offset));
147 if (dup == enddup) {
148 /*
149 * It is the biggest freespace, is it too small
150 * to hold the new leaf too?
151 */
152 if (be16_to_cpu(dup->length) < len + (uint)sizeof(*blp)) {
153 /*
154 * Yes, we use the second-largest
155 * entry instead if it works.
156 */
157 if (be16_to_cpu(bf[1].length) >= len)
158 dup = (xfs_dir2_data_unused_t *)
159 ((char *)hdr +
160 be16_to_cpu(bf[1].offset));
161 else
162 dup = NULL;
163 }
164 } else {
165 /*
166 * Not the same free entry,
167 * just check its length.
168 */
169 if (be16_to_cpu(dup->length) < len) {
170 dup = NULL;
171 }
172 }
173 }
174 compact = 0;
175 }
176 /*
177 * If there are stale entries we'll use one for the leaf.
178 * Is the biggest entry enough to avoid compaction?
179 */
180 else if (be16_to_cpu(bf[0].length) >= len) {
181 dup = (xfs_dir2_data_unused_t *)
182 ((char *)hdr + be16_to_cpu(bf[0].offset));
183 compact = 0;
184 }
185 /*
186 * Will need to compact to make this work.
187 */ 286 */
188 else { 287 xfs_dir2_block_need_space(hdr, btp, blp, &tagp, &dup,
189 /* 288 &enddup, &compact, len);
190 * Tag just before the first leaf entry. 289
191 */
192 tagp = (__be16 *)blp - 1;
193 /*
194 * Data object just before the first leaf entry.
195 */
196 dup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
197 /*
198 * If it's not free then the data will go where the
199 * leaf data starts now, if it works at all.
200 */
201 if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
202 if (be16_to_cpu(dup->length) + (be32_to_cpu(btp->stale) - 1) *
203 (uint)sizeof(*blp) < len)
204 dup = NULL;
205 } else if ((be32_to_cpu(btp->stale) - 1) * (uint)sizeof(*blp) < len)
206 dup = NULL;
207 else
208 dup = (xfs_dir2_data_unused_t *)blp;
209 compact = 1;
210 }
211 /* 290 /*
212 * If this isn't a real add, we're done with the buffer. 291 * Done everything we need for a space check now.
213 */ 292 */
214 if (args->op_flags & XFS_DA_OP_JUSTCHECK) 293 if (args->op_flags & XFS_DA_OP_JUSTCHECK) {
215 xfs_trans_brelse(tp, bp); 294 xfs_trans_brelse(tp, bp);
295 if (!dup)
296 return XFS_ERROR(ENOSPC);
297 return 0;
298 }
299
216 /* 300 /*
217 * If we don't have space for the new entry & leaf ... 301 * If we don't have space for the new entry & leaf ...
218 */ 302 */
219 if (!dup) { 303 if (!dup) {
220 /* 304 /* Don't have a space reservation: return no-space. */
221 * Not trying to actually do anything, or don't have 305 if (args->total == 0)
222 * a space reservation: return no-space.
223 */
224 if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0)
225 return XFS_ERROR(ENOSPC); 306 return XFS_ERROR(ENOSPC);
226 /* 307 /*
227 * Convert to the next larger format. 308 * Convert to the next larger format.
@@ -232,65 +313,24 @@ xfs_dir2_block_addname(
232 return error; 313 return error;
233 return xfs_dir2_leaf_addname(args); 314 return xfs_dir2_leaf_addname(args);
234 } 315 }
235 /* 316
236 * Just checking, and it would work, so say so.
237 */
238 if (args->op_flags & XFS_DA_OP_JUSTCHECK)
239 return 0;
240 needlog = needscan = 0; 317 needlog = needscan = 0;
318
241 /* 319 /*
242 * If need to compact the leaf entries, do it now. 320 * If need to compact the leaf entries, do it now.
243 * Leave the highest-numbered stale entry stale.
244 * XXX should be the one closest to mid but mid is not yet computed.
245 */
246 if (compact) {
247 int fromidx; /* source leaf index */
248 int toidx; /* target leaf index */
249
250 for (fromidx = toidx = be32_to_cpu(btp->count) - 1,
251 highstale = lfloghigh = -1;
252 fromidx >= 0;
253 fromidx--) {
254 if (blp[fromidx].address ==
255 cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) {
256 if (highstale == -1)
257 highstale = toidx;
258 else {
259 if (lfloghigh == -1)
260 lfloghigh = toidx;
261 continue;
262 }
263 }
264 if (fromidx < toidx)
265 blp[toidx] = blp[fromidx];
266 toidx--;
267 }
268 lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1);
269 lfloghigh -= be32_to_cpu(btp->stale) - 1;
270 be32_add_cpu(&btp->count, -(be32_to_cpu(btp->stale) - 1));
271 xfs_dir2_data_make_free(tp, bp,
272 (xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr),
273 (xfs_dir2_data_aoff_t)((be32_to_cpu(btp->stale) - 1) * sizeof(*blp)),
274 &needlog, &needscan);
275 blp += be32_to_cpu(btp->stale) - 1;
276 btp->stale = cpu_to_be32(1);
277 /*
278 * If we now need to rebuild the bestfree map, do so.
279 * This needs to happen before the next call to use_free.
280 */
281 if (needscan) {
282 xfs_dir2_data_freescan(mp, hdr, &needlog);
283 needscan = 0;
284 }
285 }
286 /*
287 * Set leaf logging boundaries to impossible state.
288 * For the no-stale case they're set explicitly.
289 */ 321 */
322 if (compact)
323 xfs_dir2_block_compact(tp, bp, hdr, btp, blp, &needlog,
324 &lfloghigh, &lfloglow);
290 else if (btp->stale) { 325 else if (btp->stale) {
326 /*
327 * Set leaf logging boundaries to impossible state.
328 * For the no-stale case they're set explicitly.
329 */
291 lfloglow = be32_to_cpu(btp->count); 330 lfloglow = be32_to_cpu(btp->count);
292 lfloghigh = -1; 331 lfloghigh = -1;
293 } 332 }
333
294 /* 334 /*
295 * Find the slot that's first lower than our hash value, -1 if none. 335 * Find the slot that's first lower than our hash value, -1 if none.
296 */ 336 */
@@ -450,18 +490,13 @@ xfs_dir2_block_getdents(
450 /* 490 /*
451 * If the block number in the offset is out of range, we're done. 491 * If the block number in the offset is out of range, we're done.
452 */ 492 */
453 if (xfs_dir2_dataptr_to_db(mp, *offset) > mp->m_dirdatablk) { 493 if (xfs_dir2_dataptr_to_db(mp, *offset) > mp->m_dirdatablk)
454 return 0; 494 return 0;
455 } 495
456 /* 496 error = xfs_dir2_block_read(NULL, dp, &bp);
457 * Can't read the block, give up, else get dabuf in bp.
458 */
459 error = xfs_da_read_buf(NULL, dp, mp->m_dirdatablk, -1,
460 &bp, XFS_DATA_FORK, NULL);
461 if (error) 497 if (error)
462 return error; 498 return error;
463 499
464 ASSERT(bp != NULL);
465 /* 500 /*
466 * Extract the byte offset we start at from the seek pointer. 501 * Extract the byte offset we start at from the seek pointer.
467 * We'll skip entries before this. 502 * We'll skip entries before this.
@@ -637,14 +672,11 @@ xfs_dir2_block_lookup_int(
637 dp = args->dp; 672 dp = args->dp;
638 tp = args->trans; 673 tp = args->trans;
639 mp = dp->i_mount; 674 mp = dp->i_mount;
640 /* 675
641 * Read the buffer, return error if we can't get it. 676 error = xfs_dir2_block_read(tp, dp, &bp);
642 */
643 error = xfs_da_read_buf(tp, dp, mp->m_dirdatablk, -1, &bp,
644 XFS_DATA_FORK, NULL);
645 if (error) 677 if (error)
646 return error; 678 return error;
647 ASSERT(bp != NULL); 679
648 hdr = bp->b_addr; 680 hdr = bp->b_addr;
649 xfs_dir2_data_check(dp, bp); 681 xfs_dir2_data_check(dp, bp);
650 btp = xfs_dir2_block_tail_p(mp, hdr); 682 btp = xfs_dir2_block_tail_p(mp, hdr);