.. | .. |
---|
6 | 6 | */ |
---|
7 | 7 | #include "xfs.h" |
---|
8 | 8 | #include "xfs_fs.h" |
---|
| 9 | +#include "xfs_shared.h" |
---|
9 | 10 | #include "xfs_format.h" |
---|
10 | 11 | #include "xfs_log_format.h" |
---|
11 | 12 | #include "xfs_trans_resv.h" |
---|
12 | 13 | #include "xfs_mount.h" |
---|
13 | | -#include "xfs_da_format.h" |
---|
14 | | -#include "xfs_da_btree.h" |
---|
15 | 14 | #include "xfs_inode.h" |
---|
16 | 15 | #include "xfs_bmap.h" |
---|
17 | 16 | #include "xfs_dir2.h" |
---|
.. | .. |
---|
20 | 19 | #include "xfs_trace.h" |
---|
21 | 20 | #include "xfs_trans.h" |
---|
22 | 21 | #include "xfs_buf_item.h" |
---|
23 | | -#include "xfs_cksum.h" |
---|
24 | 22 | #include "xfs_log.h" |
---|
25 | 23 | |
---|
26 | 24 | /* |
---|
.. | .. |
---|
34 | 32 | static int xfs_dir2_leafn_remove(xfs_da_args_t *args, struct xfs_buf *bp, |
---|
35 | 33 | int index, xfs_da_state_blk_t *dblk, |
---|
36 | 34 | int *rval); |
---|
37 | | -static int xfs_dir2_node_addname_int(xfs_da_args_t *args, |
---|
38 | | - xfs_da_state_blk_t *fblk); |
---|
| 35 | + |
---|
| 36 | +/* |
---|
| 37 | + * Convert data space db to the corresponding free db. |
---|
| 38 | + */ |
---|
| 39 | +static xfs_dir2_db_t |
---|
| 40 | +xfs_dir2_db_to_fdb(struct xfs_da_geometry *geo, xfs_dir2_db_t db) |
---|
| 41 | +{ |
---|
| 42 | + return xfs_dir2_byte_to_db(geo, XFS_DIR2_FREE_OFFSET) + |
---|
| 43 | + (db / geo->free_max_bests); |
---|
| 44 | +} |
---|
| 45 | + |
---|
| 46 | +/* |
---|
| 47 | + * Convert data space db to the corresponding index in a free db. |
---|
| 48 | + */ |
---|
| 49 | +static int |
---|
| 50 | +xfs_dir2_db_to_fdindex(struct xfs_da_geometry *geo, xfs_dir2_db_t db) |
---|
| 51 | +{ |
---|
| 52 | + return db % geo->free_max_bests; |
---|
| 53 | +} |
---|
39 | 54 | |
---|
40 | 55 | /* |
---|
41 | 56 | * Check internal consistency of a leafn block. |
---|
.. | .. |
---|
49 | 64 | struct xfs_dir2_leaf *leaf = bp->b_addr; |
---|
50 | 65 | struct xfs_dir3_icleaf_hdr leafhdr; |
---|
51 | 66 | |
---|
52 | | - dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); |
---|
| 67 | + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, leaf); |
---|
53 | 68 | |
---|
54 | 69 | if (leafhdr.magic == XFS_DIR3_LEAFN_MAGIC) { |
---|
55 | 70 | struct xfs_dir3_leaf_hdr *leaf3 = bp->b_addr; |
---|
.. | .. |
---|
58 | 73 | } else if (leafhdr.magic != XFS_DIR2_LEAFN_MAGIC) |
---|
59 | 74 | return __this_address; |
---|
60 | 75 | |
---|
61 | | - return xfs_dir3_leaf_check_int(dp->i_mount, dp, &leafhdr, leaf); |
---|
| 76 | + return xfs_dir3_leaf_check_int(dp->i_mount, &leafhdr, leaf); |
---|
62 | 77 | } |
---|
63 | 78 | |
---|
64 | 79 | static inline void |
---|
.. | .. |
---|
84 | 99 | xfs_dir3_free_verify( |
---|
85 | 100 | struct xfs_buf *bp) |
---|
86 | 101 | { |
---|
87 | | - struct xfs_mount *mp = bp->b_target->bt_mount; |
---|
| 102 | + struct xfs_mount *mp = bp->b_mount; |
---|
88 | 103 | struct xfs_dir2_free_hdr *hdr = bp->b_addr; |
---|
| 104 | + |
---|
| 105 | + if (!xfs_verify_magic(bp, hdr->magic)) |
---|
| 106 | + return __this_address; |
---|
89 | 107 | |
---|
90 | 108 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
---|
91 | 109 | struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; |
---|
92 | 110 | |
---|
93 | | - if (hdr3->magic != cpu_to_be32(XFS_DIR3_FREE_MAGIC)) |
---|
94 | | - return __this_address; |
---|
95 | 111 | if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_meta_uuid)) |
---|
96 | 112 | return __this_address; |
---|
97 | 113 | if (be64_to_cpu(hdr3->blkno) != bp->b_bn) |
---|
98 | 114 | return __this_address; |
---|
99 | 115 | if (!xfs_log_check_lsn(mp, be64_to_cpu(hdr3->lsn))) |
---|
100 | | - return __this_address; |
---|
101 | | - } else { |
---|
102 | | - if (hdr->magic != cpu_to_be32(XFS_DIR2_FREE_MAGIC)) |
---|
103 | 116 | return __this_address; |
---|
104 | 117 | } |
---|
105 | 118 | |
---|
.. | .. |
---|
112 | 125 | xfs_dir3_free_read_verify( |
---|
113 | 126 | struct xfs_buf *bp) |
---|
114 | 127 | { |
---|
115 | | - struct xfs_mount *mp = bp->b_target->bt_mount; |
---|
| 128 | + struct xfs_mount *mp = bp->b_mount; |
---|
116 | 129 | xfs_failaddr_t fa; |
---|
117 | 130 | |
---|
118 | 131 | if (xfs_sb_version_hascrc(&mp->m_sb) && |
---|
.. | .. |
---|
129 | 142 | xfs_dir3_free_write_verify( |
---|
130 | 143 | struct xfs_buf *bp) |
---|
131 | 144 | { |
---|
132 | | - struct xfs_mount *mp = bp->b_target->bt_mount; |
---|
| 145 | + struct xfs_mount *mp = bp->b_mount; |
---|
133 | 146 | struct xfs_buf_log_item *bip = bp->b_log_item; |
---|
134 | 147 | struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr; |
---|
135 | 148 | xfs_failaddr_t fa; |
---|
.. | .. |
---|
151 | 164 | |
---|
152 | 165 | const struct xfs_buf_ops xfs_dir3_free_buf_ops = { |
---|
153 | 166 | .name = "xfs_dir3_free", |
---|
| 167 | + .magic = { cpu_to_be32(XFS_DIR2_FREE_MAGIC), |
---|
| 168 | + cpu_to_be32(XFS_DIR3_FREE_MAGIC) }, |
---|
154 | 169 | .verify_read = xfs_dir3_free_read_verify, |
---|
155 | 170 | .verify_write = xfs_dir3_free_write_verify, |
---|
156 | 171 | .verify_struct = xfs_dir3_free_verify, |
---|
.. | .. |
---|
164 | 179 | struct xfs_buf *bp) |
---|
165 | 180 | { |
---|
166 | 181 | struct xfs_mount *mp = dp->i_mount; |
---|
| 182 | + int maxbests = mp->m_dir_geo->free_max_bests; |
---|
167 | 183 | unsigned int firstdb; |
---|
168 | | - int maxbests; |
---|
169 | 184 | |
---|
170 | | - maxbests = dp->d_ops->free_max_bests(mp->m_dir_geo); |
---|
171 | 185 | firstdb = (xfs_dir2_da_to_db(mp->m_dir_geo, fbno) - |
---|
172 | 186 | xfs_dir2_byte_to_db(mp->m_dir_geo, XFS_DIR2_FREE_OFFSET)) * |
---|
173 | 187 | maxbests; |
---|
.. | .. |
---|
179 | 193 | if (be32_to_cpu(hdr3->nvalid) > maxbests) |
---|
180 | 194 | return __this_address; |
---|
181 | 195 | if (be32_to_cpu(hdr3->nvalid) < be32_to_cpu(hdr3->nused)) |
---|
| 196 | + return __this_address; |
---|
| 197 | + if (be64_to_cpu(hdr3->hdr.owner) != dp->i_ino) |
---|
182 | 198 | return __this_address; |
---|
183 | 199 | } else { |
---|
184 | 200 | struct xfs_dir2_free_hdr *hdr = bp->b_addr; |
---|
.. | .. |
---|
198 | 214 | struct xfs_trans *tp, |
---|
199 | 215 | struct xfs_inode *dp, |
---|
200 | 216 | xfs_dablk_t fbno, |
---|
201 | | - xfs_daddr_t mappedbno, |
---|
| 217 | + unsigned int flags, |
---|
202 | 218 | struct xfs_buf **bpp) |
---|
203 | 219 | { |
---|
204 | 220 | xfs_failaddr_t fa; |
---|
205 | 221 | int err; |
---|
206 | 222 | |
---|
207 | | - err = xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp, |
---|
208 | | - XFS_DATA_FORK, &xfs_dir3_free_buf_ops); |
---|
| 223 | + err = xfs_da_read_buf(tp, dp, fbno, flags, bpp, XFS_DATA_FORK, |
---|
| 224 | + &xfs_dir3_free_buf_ops); |
---|
209 | 225 | if (err || !*bpp) |
---|
210 | 226 | return err; |
---|
211 | 227 | |
---|
212 | 228 | /* Check things that we can't do in the verifier. */ |
---|
213 | 229 | fa = xfs_dir3_free_header_check(dp, fbno, *bpp); |
---|
214 | 230 | if (fa) { |
---|
215 | | - xfs_verifier_error(*bpp, -EFSCORRUPTED, fa); |
---|
| 231 | + __xfs_buf_mark_corrupt(*bpp, fa); |
---|
216 | 232 | xfs_trans_brelse(tp, *bpp); |
---|
217 | 233 | *bpp = NULL; |
---|
218 | 234 | return -EFSCORRUPTED; |
---|
.. | .. |
---|
225 | 241 | return 0; |
---|
226 | 242 | } |
---|
227 | 243 | |
---|
| 244 | +void |
---|
| 245 | +xfs_dir2_free_hdr_from_disk( |
---|
| 246 | + struct xfs_mount *mp, |
---|
| 247 | + struct xfs_dir3_icfree_hdr *to, |
---|
| 248 | + struct xfs_dir2_free *from) |
---|
| 249 | +{ |
---|
| 250 | + if (xfs_sb_version_hascrc(&mp->m_sb)) { |
---|
| 251 | + struct xfs_dir3_free *from3 = (struct xfs_dir3_free *)from; |
---|
| 252 | + |
---|
| 253 | + to->magic = be32_to_cpu(from3->hdr.hdr.magic); |
---|
| 254 | + to->firstdb = be32_to_cpu(from3->hdr.firstdb); |
---|
| 255 | + to->nvalid = be32_to_cpu(from3->hdr.nvalid); |
---|
| 256 | + to->nused = be32_to_cpu(from3->hdr.nused); |
---|
| 257 | + to->bests = from3->bests; |
---|
| 258 | + |
---|
| 259 | + ASSERT(to->magic == XFS_DIR3_FREE_MAGIC); |
---|
| 260 | + } else { |
---|
| 261 | + to->magic = be32_to_cpu(from->hdr.magic); |
---|
| 262 | + to->firstdb = be32_to_cpu(from->hdr.firstdb); |
---|
| 263 | + to->nvalid = be32_to_cpu(from->hdr.nvalid); |
---|
| 264 | + to->nused = be32_to_cpu(from->hdr.nused); |
---|
| 265 | + to->bests = from->bests; |
---|
| 266 | + |
---|
| 267 | + ASSERT(to->magic == XFS_DIR2_FREE_MAGIC); |
---|
| 268 | + } |
---|
| 269 | +} |
---|
| 270 | + |
---|
| 271 | +static void |
---|
| 272 | +xfs_dir2_free_hdr_to_disk( |
---|
| 273 | + struct xfs_mount *mp, |
---|
| 274 | + struct xfs_dir2_free *to, |
---|
| 275 | + struct xfs_dir3_icfree_hdr *from) |
---|
| 276 | +{ |
---|
| 277 | + if (xfs_sb_version_hascrc(&mp->m_sb)) { |
---|
| 278 | + struct xfs_dir3_free *to3 = (struct xfs_dir3_free *)to; |
---|
| 279 | + |
---|
| 280 | + ASSERT(from->magic == XFS_DIR3_FREE_MAGIC); |
---|
| 281 | + |
---|
| 282 | + to3->hdr.hdr.magic = cpu_to_be32(from->magic); |
---|
| 283 | + to3->hdr.firstdb = cpu_to_be32(from->firstdb); |
---|
| 284 | + to3->hdr.nvalid = cpu_to_be32(from->nvalid); |
---|
| 285 | + to3->hdr.nused = cpu_to_be32(from->nused); |
---|
| 286 | + } else { |
---|
| 287 | + ASSERT(from->magic == XFS_DIR2_FREE_MAGIC); |
---|
| 288 | + |
---|
| 289 | + to->hdr.magic = cpu_to_be32(from->magic); |
---|
| 290 | + to->hdr.firstdb = cpu_to_be32(from->firstdb); |
---|
| 291 | + to->hdr.nvalid = cpu_to_be32(from->nvalid); |
---|
| 292 | + to->hdr.nused = cpu_to_be32(from->nused); |
---|
| 293 | + } |
---|
| 294 | +} |
---|
| 295 | + |
---|
228 | 296 | int |
---|
229 | 297 | xfs_dir2_free_read( |
---|
230 | 298 | struct xfs_trans *tp, |
---|
.. | .. |
---|
232 | 300 | xfs_dablk_t fbno, |
---|
233 | 301 | struct xfs_buf **bpp) |
---|
234 | 302 | { |
---|
235 | | - return __xfs_dir3_free_read(tp, dp, fbno, -1, bpp); |
---|
| 303 | + return __xfs_dir3_free_read(tp, dp, fbno, 0, bpp); |
---|
236 | 304 | } |
---|
237 | 305 | |
---|
238 | 306 | static int |
---|
.. | .. |
---|
242 | 310 | xfs_dablk_t fbno, |
---|
243 | 311 | struct xfs_buf **bpp) |
---|
244 | 312 | { |
---|
245 | | - return __xfs_dir3_free_read(tp, dp, fbno, -2, bpp); |
---|
| 313 | + return __xfs_dir3_free_read(tp, dp, fbno, XFS_DABUF_MAP_HOLE_OK, bpp); |
---|
246 | 314 | } |
---|
247 | 315 | |
---|
248 | 316 | static int |
---|
.. | .. |
---|
259 | 327 | struct xfs_dir3_icfree_hdr hdr; |
---|
260 | 328 | |
---|
261 | 329 | error = xfs_da_get_buf(tp, dp, xfs_dir2_db_to_da(args->geo, fbno), |
---|
262 | | - -1, &bp, XFS_DATA_FORK); |
---|
| 330 | + &bp, XFS_DATA_FORK); |
---|
263 | 331 | if (error) |
---|
264 | 332 | return error; |
---|
265 | 333 | |
---|
.. | .. |
---|
283 | 351 | uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_meta_uuid); |
---|
284 | 352 | } else |
---|
285 | 353 | hdr.magic = XFS_DIR2_FREE_MAGIC; |
---|
286 | | - dp->d_ops->free_hdr_to_disk(bp->b_addr, &hdr); |
---|
| 354 | + xfs_dir2_free_hdr_to_disk(mp, bp->b_addr, &hdr); |
---|
287 | 355 | *bpp = bp; |
---|
288 | 356 | return 0; |
---|
289 | 357 | } |
---|
.. | .. |
---|
294 | 362 | STATIC void |
---|
295 | 363 | xfs_dir2_free_log_bests( |
---|
296 | 364 | struct xfs_da_args *args, |
---|
| 365 | + struct xfs_dir3_icfree_hdr *hdr, |
---|
297 | 366 | struct xfs_buf *bp, |
---|
298 | 367 | int first, /* first entry to log */ |
---|
299 | 368 | int last) /* last entry to log */ |
---|
300 | 369 | { |
---|
301 | | - xfs_dir2_free_t *free; /* freespace structure */ |
---|
302 | | - __be16 *bests; |
---|
| 370 | + struct xfs_dir2_free *free = bp->b_addr; |
---|
303 | 371 | |
---|
304 | | - free = bp->b_addr; |
---|
305 | | - bests = args->dp->d_ops->free_bests_p(free); |
---|
306 | 372 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || |
---|
307 | 373 | free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); |
---|
308 | 374 | xfs_trans_log_buf(args->trans, bp, |
---|
309 | | - (uint)((char *)&bests[first] - (char *)free), |
---|
310 | | - (uint)((char *)&bests[last] - (char *)free + |
---|
311 | | - sizeof(bests[0]) - 1)); |
---|
| 375 | + (char *)&hdr->bests[first] - (char *)free, |
---|
| 376 | + (char *)&hdr->bests[last] - (char *)free + |
---|
| 377 | + sizeof(hdr->bests[0]) - 1); |
---|
312 | 378 | } |
---|
313 | 379 | |
---|
314 | 380 | /* |
---|
.. | .. |
---|
327 | 393 | free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); |
---|
328 | 394 | #endif |
---|
329 | 395 | xfs_trans_log_buf(args->trans, bp, 0, |
---|
330 | | - args->dp->d_ops->free_hdr_size - 1); |
---|
| 396 | + args->geo->free_hdr_size - 1); |
---|
331 | 397 | } |
---|
332 | 398 | |
---|
333 | 399 | /* |
---|
.. | .. |
---|
344 | 410 | int error; /* error return value */ |
---|
345 | 411 | struct xfs_buf *fbp; /* freespace buffer */ |
---|
346 | 412 | xfs_dir2_db_t fdb; /* freespace block number */ |
---|
347 | | - xfs_dir2_free_t *free; /* freespace structure */ |
---|
348 | 413 | __be16 *from; /* pointer to freespace entry */ |
---|
349 | 414 | int i; /* leaf freespace index */ |
---|
350 | 415 | xfs_dir2_leaf_t *leaf; /* leaf structure */ |
---|
351 | 416 | xfs_dir2_leaf_tail_t *ltp; /* leaf tail structure */ |
---|
352 | 417 | int n; /* count of live freespc ents */ |
---|
353 | 418 | xfs_dir2_data_off_t off; /* freespace entry value */ |
---|
354 | | - __be16 *to; /* pointer to freespace entry */ |
---|
355 | 419 | xfs_trans_t *tp; /* transaction pointer */ |
---|
356 | 420 | struct xfs_dir3_icfree_hdr freehdr; |
---|
357 | 421 | |
---|
.. | .. |
---|
373 | 437 | if (error) |
---|
374 | 438 | return error; |
---|
375 | 439 | |
---|
376 | | - free = fbp->b_addr; |
---|
377 | | - dp->d_ops->free_hdr_from_disk(&freehdr, free); |
---|
| 440 | + xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, fbp->b_addr); |
---|
378 | 441 | leaf = lbp->b_addr; |
---|
379 | 442 | ltp = xfs_dir2_leaf_tail_p(args->geo, leaf); |
---|
380 | 443 | if (be32_to_cpu(ltp->bestcount) > |
---|
381 | | - (uint)dp->i_d.di_size / args->geo->blksize) |
---|
| 444 | + (uint)dp->i_d.di_size / args->geo->blksize) { |
---|
| 445 | + xfs_buf_mark_corrupt(lbp); |
---|
382 | 446 | return -EFSCORRUPTED; |
---|
| 447 | + } |
---|
383 | 448 | |
---|
384 | 449 | /* |
---|
385 | 450 | * Copy freespace entries from the leaf block to the new block. |
---|
386 | 451 | * Count active entries. |
---|
387 | 452 | */ |
---|
388 | 453 | from = xfs_dir2_leaf_bests_p(ltp); |
---|
389 | | - to = dp->d_ops->free_bests_p(free); |
---|
390 | | - for (i = n = 0; i < be32_to_cpu(ltp->bestcount); i++, from++, to++) { |
---|
391 | | - if ((off = be16_to_cpu(*from)) != NULLDATAOFF) |
---|
| 454 | + for (i = n = 0; i < be32_to_cpu(ltp->bestcount); i++, from++) { |
---|
| 455 | + off = be16_to_cpu(*from); |
---|
| 456 | + if (off != NULLDATAOFF) |
---|
392 | 457 | n++; |
---|
393 | | - *to = cpu_to_be16(off); |
---|
| 458 | + freehdr.bests[i] = cpu_to_be16(off); |
---|
394 | 459 | } |
---|
395 | 460 | |
---|
396 | 461 | /* |
---|
.. | .. |
---|
399 | 464 | freehdr.nused = n; |
---|
400 | 465 | freehdr.nvalid = be32_to_cpu(ltp->bestcount); |
---|
401 | 466 | |
---|
402 | | - dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr); |
---|
403 | | - xfs_dir2_free_log_bests(args, fbp, 0, freehdr.nvalid - 1); |
---|
| 467 | + xfs_dir2_free_hdr_to_disk(dp->i_mount, fbp->b_addr, &freehdr); |
---|
| 468 | + xfs_dir2_free_log_bests(args, &freehdr, fbp, 0, freehdr.nvalid - 1); |
---|
404 | 469 | xfs_dir2_free_log_header(args, fbp); |
---|
405 | 470 | |
---|
406 | 471 | /* |
---|
.. | .. |
---|
427 | 492 | static int /* error */ |
---|
428 | 493 | xfs_dir2_leafn_add( |
---|
429 | 494 | struct xfs_buf *bp, /* leaf buffer */ |
---|
430 | | - xfs_da_args_t *args, /* operation arguments */ |
---|
| 495 | + struct xfs_da_args *args, /* operation arguments */ |
---|
431 | 496 | int index) /* insertion pt for new entry */ |
---|
432 | 497 | { |
---|
| 498 | + struct xfs_dir3_icleaf_hdr leafhdr; |
---|
| 499 | + struct xfs_inode *dp = args->dp; |
---|
| 500 | + struct xfs_dir2_leaf *leaf = bp->b_addr; |
---|
| 501 | + struct xfs_dir2_leaf_entry *lep; |
---|
| 502 | + struct xfs_dir2_leaf_entry *ents; |
---|
433 | 503 | int compact; /* compacting stale leaves */ |
---|
434 | | - xfs_inode_t *dp; /* incore directory inode */ |
---|
435 | | - int highstale; /* next stale entry */ |
---|
436 | | - xfs_dir2_leaf_t *leaf; /* leaf structure */ |
---|
437 | | - xfs_dir2_leaf_entry_t *lep; /* leaf entry */ |
---|
| 504 | + int highstale = 0; /* next stale entry */ |
---|
438 | 505 | int lfloghigh; /* high leaf entry logging */ |
---|
439 | 506 | int lfloglow; /* low leaf entry logging */ |
---|
440 | | - int lowstale; /* previous stale entry */ |
---|
441 | | - struct xfs_dir3_icleaf_hdr leafhdr; |
---|
442 | | - struct xfs_dir2_leaf_entry *ents; |
---|
| 507 | + int lowstale = 0; /* previous stale entry */ |
---|
443 | 508 | |
---|
444 | 509 | trace_xfs_dir2_leafn_add(args, index); |
---|
445 | 510 | |
---|
446 | | - dp = args->dp; |
---|
447 | | - leaf = bp->b_addr; |
---|
448 | | - dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); |
---|
449 | | - ents = dp->d_ops->leaf_ents_p(leaf); |
---|
| 511 | + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, leaf); |
---|
| 512 | + ents = leafhdr.ents; |
---|
450 | 513 | |
---|
451 | 514 | /* |
---|
452 | 515 | * Quick check just to make sure we are not going to index |
---|
453 | 516 | * into other peoples memory |
---|
454 | 517 | */ |
---|
455 | | - if (index < 0) |
---|
| 518 | + if (index < 0) { |
---|
| 519 | + xfs_buf_mark_corrupt(bp); |
---|
456 | 520 | return -EFSCORRUPTED; |
---|
| 521 | + } |
---|
457 | 522 | |
---|
458 | 523 | /* |
---|
459 | 524 | * If there are already the maximum number of leaf entries in |
---|
.. | .. |
---|
462 | 527 | * a compact. |
---|
463 | 528 | */ |
---|
464 | 529 | |
---|
465 | | - if (leafhdr.count == dp->d_ops->leaf_max_ents(args->geo)) { |
---|
| 530 | + if (leafhdr.count == args->geo->leaf_max_ents) { |
---|
466 | 531 | if (!leafhdr.stale) |
---|
467 | 532 | return -ENOSPC; |
---|
468 | 533 | compact = leafhdr.stale > 1; |
---|
.. | .. |
---|
500 | 565 | lep->address = cpu_to_be32(xfs_dir2_db_off_to_dataptr(args->geo, |
---|
501 | 566 | args->blkno, args->index)); |
---|
502 | 567 | |
---|
503 | | - dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); |
---|
| 568 | + xfs_dir2_leaf_hdr_to_disk(dp->i_mount, leaf, &leafhdr); |
---|
504 | 569 | xfs_dir3_leaf_log_header(args, bp); |
---|
505 | | - xfs_dir3_leaf_log_ents(args, bp, lfloglow, lfloghigh); |
---|
| 570 | + xfs_dir3_leaf_log_ents(args, &leafhdr, bp, lfloglow, lfloghigh); |
---|
506 | 571 | xfs_dir3_leaf_check(dp, bp); |
---|
507 | 572 | return 0; |
---|
508 | 573 | } |
---|
.. | .. |
---|
516 | 581 | { |
---|
517 | 582 | struct xfs_dir3_icfree_hdr hdr; |
---|
518 | 583 | |
---|
519 | | - dp->d_ops->free_hdr_from_disk(&hdr, bp->b_addr); |
---|
| 584 | + xfs_dir2_free_hdr_from_disk(dp->i_mount, &hdr, bp->b_addr); |
---|
520 | 585 | |
---|
521 | | - ASSERT((hdr.firstdb % |
---|
522 | | - dp->d_ops->free_max_bests(dp->i_mount->m_dir_geo)) == 0); |
---|
| 586 | + ASSERT((hdr.firstdb % dp->i_mount->m_dir_geo->free_max_bests) == 0); |
---|
523 | 587 | ASSERT(hdr.firstdb <= db); |
---|
524 | 588 | ASSERT(db < hdr.firstdb + hdr.nvalid); |
---|
525 | 589 | } |
---|
.. | .. |
---|
537 | 601 | struct xfs_buf *bp, /* leaf buffer */ |
---|
538 | 602 | int *count) /* count of entries in leaf */ |
---|
539 | 603 | { |
---|
540 | | - struct xfs_dir2_leaf *leaf = bp->b_addr; |
---|
541 | | - struct xfs_dir2_leaf_entry *ents; |
---|
542 | 604 | struct xfs_dir3_icleaf_hdr leafhdr; |
---|
543 | 605 | |
---|
544 | | - dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); |
---|
| 606 | + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, bp->b_addr); |
---|
545 | 607 | |
---|
546 | 608 | ASSERT(leafhdr.magic == XFS_DIR2_LEAFN_MAGIC || |
---|
547 | 609 | leafhdr.magic == XFS_DIR3_LEAFN_MAGIC || |
---|
.. | .. |
---|
552 | 614 | *count = leafhdr.count; |
---|
553 | 615 | if (!leafhdr.count) |
---|
554 | 616 | return 0; |
---|
555 | | - |
---|
556 | | - ents = dp->d_ops->leaf_ents_p(leaf); |
---|
557 | | - return be32_to_cpu(ents[leafhdr.count - 1].hashval); |
---|
| 617 | + return be32_to_cpu(leafhdr.ents[leafhdr.count - 1].hashval); |
---|
558 | 618 | } |
---|
559 | 619 | |
---|
560 | 620 | /* |
---|
.. | .. |
---|
583 | 643 | xfs_dir2_db_t newdb; /* new data block number */ |
---|
584 | 644 | xfs_dir2_db_t newfdb; /* new free block number */ |
---|
585 | 645 | xfs_trans_t *tp; /* transaction pointer */ |
---|
586 | | - struct xfs_dir2_leaf_entry *ents; |
---|
587 | 646 | struct xfs_dir3_icleaf_hdr leafhdr; |
---|
588 | 647 | |
---|
589 | 648 | dp = args->dp; |
---|
590 | 649 | tp = args->trans; |
---|
591 | 650 | mp = dp->i_mount; |
---|
592 | 651 | leaf = bp->b_addr; |
---|
593 | | - dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); |
---|
594 | | - ents = dp->d_ops->leaf_ents_p(leaf); |
---|
| 652 | + xfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf); |
---|
595 | 653 | |
---|
596 | 654 | xfs_dir3_leaf_check(dp, bp); |
---|
597 | 655 | ASSERT(leafhdr.count > 0); |
---|
.. | .. |
---|
611 | 669 | ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC) || |
---|
612 | 670 | free->hdr.magic == cpu_to_be32(XFS_DIR3_FREE_MAGIC)); |
---|
613 | 671 | } |
---|
614 | | - length = dp->d_ops->data_entsize(args->namelen); |
---|
| 672 | + length = xfs_dir2_data_entsize(mp, args->namelen); |
---|
615 | 673 | /* |
---|
616 | 674 | * Loop over leaf entries with the right hash value. |
---|
617 | 675 | */ |
---|
618 | | - for (lep = &ents[index]; |
---|
| 676 | + for (lep = &leafhdr.ents[index]; |
---|
619 | 677 | index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval; |
---|
620 | 678 | lep++, index++) { |
---|
621 | 679 | /* |
---|
.. | .. |
---|
637 | 695 | * in hand, take a look at it. |
---|
638 | 696 | */ |
---|
639 | 697 | if (newdb != curdb) { |
---|
640 | | - __be16 *bests; |
---|
| 698 | + struct xfs_dir3_icfree_hdr freehdr; |
---|
641 | 699 | |
---|
642 | 700 | curdb = newdb; |
---|
643 | 701 | /* |
---|
644 | 702 | * Convert the data block to the free block |
---|
645 | 703 | * holding its freespace information. |
---|
646 | 704 | */ |
---|
647 | | - newfdb = dp->d_ops->db_to_fdb(args->geo, newdb); |
---|
| 705 | + newfdb = xfs_dir2_db_to_fdb(args->geo, newdb); |
---|
648 | 706 | /* |
---|
649 | 707 | * If it's not the one we have in hand, read it in. |
---|
650 | 708 | */ |
---|
.. | .. |
---|
668 | 726 | /* |
---|
669 | 727 | * Get the index for our entry. |
---|
670 | 728 | */ |
---|
671 | | - fi = dp->d_ops->db_to_fdindex(args->geo, curdb); |
---|
| 729 | + fi = xfs_dir2_db_to_fdindex(args->geo, curdb); |
---|
672 | 730 | /* |
---|
673 | 731 | * If it has room, return it. |
---|
674 | 732 | */ |
---|
675 | | - bests = dp->d_ops->free_bests_p(free); |
---|
676 | | - if (unlikely(bests[fi] == cpu_to_be16(NULLDATAOFF))) { |
---|
677 | | - XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", |
---|
678 | | - XFS_ERRLEVEL_LOW, mp); |
---|
| 733 | + xfs_dir2_free_hdr_from_disk(mp, &freehdr, free); |
---|
| 734 | + if (XFS_IS_CORRUPT(mp, |
---|
| 735 | + freehdr.bests[fi] == |
---|
| 736 | + cpu_to_be16(NULLDATAOFF))) { |
---|
679 | 737 | if (curfdb != newfdb) |
---|
680 | 738 | xfs_trans_brelse(tp, curbp); |
---|
681 | 739 | return -EFSCORRUPTED; |
---|
682 | 740 | } |
---|
683 | 741 | curfdb = newfdb; |
---|
684 | | - if (be16_to_cpu(bests[fi]) >= length) |
---|
| 742 | + if (be16_to_cpu(freehdr.bests[fi]) >= length) |
---|
685 | 743 | goto out; |
---|
686 | 744 | } |
---|
687 | 745 | } |
---|
.. | .. |
---|
735 | 793 | xfs_dir2_db_t newdb; /* new data block number */ |
---|
736 | 794 | xfs_trans_t *tp; /* transaction pointer */ |
---|
737 | 795 | enum xfs_dacmp cmp; /* comparison result */ |
---|
738 | | - struct xfs_dir2_leaf_entry *ents; |
---|
739 | 796 | struct xfs_dir3_icleaf_hdr leafhdr; |
---|
740 | 797 | |
---|
741 | 798 | dp = args->dp; |
---|
742 | 799 | tp = args->trans; |
---|
743 | 800 | mp = dp->i_mount; |
---|
744 | 801 | leaf = bp->b_addr; |
---|
745 | | - dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); |
---|
746 | | - ents = dp->d_ops->leaf_ents_p(leaf); |
---|
| 802 | + xfs_dir2_leaf_hdr_from_disk(mp, &leafhdr, leaf); |
---|
747 | 803 | |
---|
748 | 804 | xfs_dir3_leaf_check(dp, bp); |
---|
749 | | - ASSERT(leafhdr.count > 0); |
---|
| 805 | + if (leafhdr.count <= 0) { |
---|
| 806 | + xfs_buf_mark_corrupt(bp); |
---|
| 807 | + return -EFSCORRUPTED; |
---|
| 808 | + } |
---|
750 | 809 | |
---|
751 | 810 | /* |
---|
752 | 811 | * Look up the hash value in the leaf entries. |
---|
.. | .. |
---|
762 | 821 | /* |
---|
763 | 822 | * Loop over leaf entries with the right hash value. |
---|
764 | 823 | */ |
---|
765 | | - for (lep = &ents[index]; |
---|
| 824 | + for (lep = &leafhdr.ents[index]; |
---|
766 | 825 | index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval; |
---|
767 | 826 | lep++, index++) { |
---|
768 | 827 | /* |
---|
.. | .. |
---|
801 | 860 | error = xfs_dir3_data_read(tp, dp, |
---|
802 | 861 | xfs_dir2_db_to_da(args->geo, |
---|
803 | 862 | newdb), |
---|
804 | | - -1, &curbp); |
---|
| 863 | + 0, &curbp); |
---|
805 | 864 | if (error) |
---|
806 | 865 | return error; |
---|
807 | 866 | } |
---|
.. | .. |
---|
819 | 878 | * EEXIST immediately. If it's the first case-insensitive |
---|
820 | 879 | * match, store the block & inode number and continue looking. |
---|
821 | 880 | */ |
---|
822 | | - cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen); |
---|
| 881 | + cmp = xfs_dir2_compname(args, dep->name, dep->namelen); |
---|
823 | 882 | if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) { |
---|
824 | 883 | /* If there is a CI match block, drop it */ |
---|
825 | 884 | if (args->cmpresult != XFS_CMP_DIFFERENT && |
---|
.. | .. |
---|
827 | 886 | xfs_trans_brelse(tp, state->extrablk.bp); |
---|
828 | 887 | args->cmpresult = cmp; |
---|
829 | 888 | args->inumber = be64_to_cpu(dep->inumber); |
---|
830 | | - args->filetype = dp->d_ops->data_get_ftype(dep); |
---|
| 889 | + args->filetype = xfs_dir2_data_get_ftype(mp, dep); |
---|
831 | 890 | *indexp = index; |
---|
832 | 891 | state->extravalid = 1; |
---|
833 | 892 | state->extrablk.bp = curbp; |
---|
.. | .. |
---|
917 | 976 | if (start_d < dhdr->count) { |
---|
918 | 977 | memmove(&dents[start_d + count], &dents[start_d], |
---|
919 | 978 | (dhdr->count - start_d) * sizeof(xfs_dir2_leaf_entry_t)); |
---|
920 | | - xfs_dir3_leaf_log_ents(args, bp_d, start_d + count, |
---|
| 979 | + xfs_dir3_leaf_log_ents(args, dhdr, bp_d, start_d + count, |
---|
921 | 980 | count + dhdr->count - 1); |
---|
922 | 981 | } |
---|
923 | 982 | /* |
---|
.. | .. |
---|
939 | 998 | */ |
---|
940 | 999 | memcpy(&dents[start_d], &sents[start_s], |
---|
941 | 1000 | count * sizeof(xfs_dir2_leaf_entry_t)); |
---|
942 | | - xfs_dir3_leaf_log_ents(args, bp_d, start_d, start_d + count - 1); |
---|
| 1001 | + xfs_dir3_leaf_log_ents(args, dhdr, bp_d, start_d, start_d + count - 1); |
---|
943 | 1002 | |
---|
944 | 1003 | /* |
---|
945 | 1004 | * If there are source entries after the ones we copied, |
---|
.. | .. |
---|
948 | 1007 | if (start_s + count < shdr->count) { |
---|
949 | 1008 | memmove(&sents[start_s], &sents[start_s + count], |
---|
950 | 1009 | count * sizeof(xfs_dir2_leaf_entry_t)); |
---|
951 | | - xfs_dir3_leaf_log_ents(args, bp_s, start_s, start_s + count - 1); |
---|
| 1010 | + xfs_dir3_leaf_log_ents(args, shdr, bp_s, start_s, |
---|
| 1011 | + start_s + count - 1); |
---|
952 | 1012 | } |
---|
953 | 1013 | |
---|
954 | 1014 | /* |
---|
.. | .. |
---|
977 | 1037 | struct xfs_dir3_icleaf_hdr hdr1; |
---|
978 | 1038 | struct xfs_dir3_icleaf_hdr hdr2; |
---|
979 | 1039 | |
---|
980 | | - dp->d_ops->leaf_hdr_from_disk(&hdr1, leaf1); |
---|
981 | | - dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf2); |
---|
982 | | - ents1 = dp->d_ops->leaf_ents_p(leaf1); |
---|
983 | | - ents2 = dp->d_ops->leaf_ents_p(leaf2); |
---|
| 1040 | + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr1, leaf1); |
---|
| 1041 | + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr2, leaf2); |
---|
| 1042 | + ents1 = hdr1.ents; |
---|
| 1043 | + ents2 = hdr2.ents; |
---|
984 | 1044 | |
---|
985 | 1045 | if (hdr1.count > 0 && hdr2.count > 0 && |
---|
986 | 1046 | (be32_to_cpu(ents2[0].hashval) < be32_to_cpu(ents1[0].hashval) || |
---|
.. | .. |
---|
1030 | 1090 | |
---|
1031 | 1091 | leaf1 = blk1->bp->b_addr; |
---|
1032 | 1092 | leaf2 = blk2->bp->b_addr; |
---|
1033 | | - dp->d_ops->leaf_hdr_from_disk(&hdr1, leaf1); |
---|
1034 | | - dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf2); |
---|
1035 | | - ents1 = dp->d_ops->leaf_ents_p(leaf1); |
---|
1036 | | - ents2 = dp->d_ops->leaf_ents_p(leaf2); |
---|
| 1093 | + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr1, leaf1); |
---|
| 1094 | + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr2, leaf2); |
---|
| 1095 | + ents1 = hdr1.ents; |
---|
| 1096 | + ents2 = hdr2.ents; |
---|
1037 | 1097 | |
---|
1038 | 1098 | oldsum = hdr1.count + hdr2.count; |
---|
1039 | 1099 | #if defined(DEBUG) || defined(XFS_WARN) |
---|
.. | .. |
---|
1079 | 1139 | ASSERT(hdr1.stale + hdr2.stale == oldstale); |
---|
1080 | 1140 | |
---|
1081 | 1141 | /* log the changes made when moving the entries */ |
---|
1082 | | - dp->d_ops->leaf_hdr_to_disk(leaf1, &hdr1); |
---|
1083 | | - dp->d_ops->leaf_hdr_to_disk(leaf2, &hdr2); |
---|
| 1142 | + xfs_dir2_leaf_hdr_to_disk(dp->i_mount, leaf1, &hdr1); |
---|
| 1143 | + xfs_dir2_leaf_hdr_to_disk(dp->i_mount, leaf2, &hdr2); |
---|
1084 | 1144 | xfs_dir3_leaf_log_header(args, blk1->bp); |
---|
1085 | 1145 | xfs_dir3_leaf_log_header(args, blk2->bp); |
---|
1086 | 1146 | |
---|
.. | .. |
---|
1126 | 1186 | int longest) |
---|
1127 | 1187 | { |
---|
1128 | 1188 | int logfree = 0; |
---|
1129 | | - __be16 *bests; |
---|
1130 | 1189 | struct xfs_dir3_icfree_hdr freehdr; |
---|
1131 | 1190 | struct xfs_inode *dp = args->dp; |
---|
1132 | 1191 | |
---|
1133 | | - dp->d_ops->free_hdr_from_disk(&freehdr, free); |
---|
1134 | | - bests = dp->d_ops->free_bests_p(free); |
---|
| 1192 | + xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, free); |
---|
1135 | 1193 | if (hdr) { |
---|
1136 | 1194 | /* |
---|
1137 | 1195 | * Data block is not empty, just set the free entry to the new |
---|
1138 | 1196 | * value. |
---|
1139 | 1197 | */ |
---|
1140 | | - bests[findex] = cpu_to_be16(longest); |
---|
1141 | | - xfs_dir2_free_log_bests(args, fbp, findex, findex); |
---|
| 1198 | + freehdr.bests[findex] = cpu_to_be16(longest); |
---|
| 1199 | + xfs_dir2_free_log_bests(args, &freehdr, fbp, findex, findex); |
---|
1142 | 1200 | return 0; |
---|
1143 | 1201 | } |
---|
1144 | 1202 | |
---|
.. | .. |
---|
1154 | 1212 | int i; /* free entry index */ |
---|
1155 | 1213 | |
---|
1156 | 1214 | for (i = findex - 1; i >= 0; i--) { |
---|
1157 | | - if (bests[i] != cpu_to_be16(NULLDATAOFF)) |
---|
| 1215 | + if (freehdr.bests[i] != cpu_to_be16(NULLDATAOFF)) |
---|
1158 | 1216 | break; |
---|
1159 | 1217 | } |
---|
1160 | 1218 | freehdr.nvalid = i + 1; |
---|
1161 | 1219 | logfree = 0; |
---|
1162 | 1220 | } else { |
---|
1163 | 1221 | /* Not the last entry, just punch it out. */ |
---|
1164 | | - bests[findex] = cpu_to_be16(NULLDATAOFF); |
---|
| 1222 | + freehdr.bests[findex] = cpu_to_be16(NULLDATAOFF); |
---|
1165 | 1223 | logfree = 1; |
---|
1166 | 1224 | } |
---|
1167 | 1225 | |
---|
1168 | | - dp->d_ops->free_hdr_to_disk(free, &freehdr); |
---|
| 1226 | + xfs_dir2_free_hdr_to_disk(dp->i_mount, free, &freehdr); |
---|
1169 | 1227 | xfs_dir2_free_log_header(args, fbp); |
---|
1170 | 1228 | |
---|
1171 | 1229 | /* |
---|
.. | .. |
---|
1190 | 1248 | |
---|
1191 | 1249 | /* Log the free entry that changed, unless we got rid of it. */ |
---|
1192 | 1250 | if (logfree) |
---|
1193 | | - xfs_dir2_free_log_bests(args, fbp, findex, findex); |
---|
| 1251 | + xfs_dir2_free_log_bests(args, &freehdr, fbp, findex, findex); |
---|
1194 | 1252 | return 0; |
---|
1195 | 1253 | } |
---|
1196 | 1254 | |
---|
.. | .. |
---|
1207 | 1265 | xfs_da_state_blk_t *dblk, /* data block */ |
---|
1208 | 1266 | int *rval) /* resulting block needs join */ |
---|
1209 | 1267 | { |
---|
| 1268 | + struct xfs_da_geometry *geo = args->geo; |
---|
1210 | 1269 | xfs_dir2_data_hdr_t *hdr; /* data block header */ |
---|
1211 | 1270 | xfs_dir2_db_t db; /* data block number */ |
---|
1212 | 1271 | struct xfs_buf *dbp; /* data block buffer */ |
---|
.. | .. |
---|
1221 | 1280 | xfs_trans_t *tp; /* transaction pointer */ |
---|
1222 | 1281 | struct xfs_dir2_data_free *bf; /* bestfree table */ |
---|
1223 | 1282 | struct xfs_dir3_icleaf_hdr leafhdr; |
---|
1224 | | - struct xfs_dir2_leaf_entry *ents; |
---|
1225 | 1283 | |
---|
1226 | 1284 | trace_xfs_dir2_leafn_remove(args, index); |
---|
1227 | 1285 | |
---|
1228 | 1286 | dp = args->dp; |
---|
1229 | 1287 | tp = args->trans; |
---|
1230 | 1288 | leaf = bp->b_addr; |
---|
1231 | | - dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); |
---|
1232 | | - ents = dp->d_ops->leaf_ents_p(leaf); |
---|
| 1289 | + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, leaf); |
---|
1233 | 1290 | |
---|
1234 | 1291 | /* |
---|
1235 | 1292 | * Point to the entry we're removing. |
---|
1236 | 1293 | */ |
---|
1237 | | - lep = &ents[index]; |
---|
| 1294 | + lep = &leafhdr.ents[index]; |
---|
1238 | 1295 | |
---|
1239 | 1296 | /* |
---|
1240 | 1297 | * Extract the data block and offset from the entry. |
---|
1241 | 1298 | */ |
---|
1242 | | - db = xfs_dir2_dataptr_to_db(args->geo, be32_to_cpu(lep->address)); |
---|
| 1299 | + db = xfs_dir2_dataptr_to_db(geo, be32_to_cpu(lep->address)); |
---|
1243 | 1300 | ASSERT(dblk->blkno == db); |
---|
1244 | | - off = xfs_dir2_dataptr_to_off(args->geo, be32_to_cpu(lep->address)); |
---|
| 1301 | + off = xfs_dir2_dataptr_to_off(geo, be32_to_cpu(lep->address)); |
---|
1245 | 1302 | ASSERT(dblk->index == off); |
---|
1246 | 1303 | |
---|
1247 | 1304 | /* |
---|
.. | .. |
---|
1249 | 1306 | * Log the leaf block changes. |
---|
1250 | 1307 | */ |
---|
1251 | 1308 | leafhdr.stale++; |
---|
1252 | | - dp->d_ops->leaf_hdr_to_disk(leaf, &leafhdr); |
---|
| 1309 | + xfs_dir2_leaf_hdr_to_disk(dp->i_mount, leaf, &leafhdr); |
---|
1253 | 1310 | xfs_dir3_leaf_log_header(args, bp); |
---|
1254 | 1311 | |
---|
1255 | 1312 | lep->address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR); |
---|
1256 | | - xfs_dir3_leaf_log_ents(args, bp, index, index); |
---|
| 1313 | + xfs_dir3_leaf_log_ents(args, &leafhdr, bp, index, index); |
---|
1257 | 1314 | |
---|
1258 | 1315 | /* |
---|
1259 | 1316 | * Make the data entry free. Keep track of the longest freespace |
---|
.. | .. |
---|
1262 | 1319 | dbp = dblk->bp; |
---|
1263 | 1320 | hdr = dbp->b_addr; |
---|
1264 | 1321 | dep = (xfs_dir2_data_entry_t *)((char *)hdr + off); |
---|
1265 | | - bf = dp->d_ops->data_bestfree_p(hdr); |
---|
| 1322 | + bf = xfs_dir2_data_bestfree_p(dp->i_mount, hdr); |
---|
1266 | 1323 | longest = be16_to_cpu(bf[0].length); |
---|
1267 | 1324 | needlog = needscan = 0; |
---|
1268 | 1325 | xfs_dir2_data_make_free(args, dbp, off, |
---|
1269 | | - dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan); |
---|
| 1326 | + xfs_dir2_data_entsize(dp->i_mount, dep->namelen), &needlog, |
---|
| 1327 | + &needscan); |
---|
1270 | 1328 | /* |
---|
1271 | 1329 | * Rescan the data block freespaces for bestfree. |
---|
1272 | 1330 | * Log the data block header if needed. |
---|
1273 | 1331 | */ |
---|
1274 | 1332 | if (needscan) |
---|
1275 | | - xfs_dir2_data_freescan(dp, hdr, &needlog); |
---|
| 1333 | + xfs_dir2_data_freescan(dp->i_mount, hdr, &needlog); |
---|
1276 | 1334 | if (needlog) |
---|
1277 | 1335 | xfs_dir2_data_log_header(args, dbp); |
---|
1278 | 1336 | xfs_dir3_data_check(dp, dbp); |
---|
.. | .. |
---|
1291 | 1349 | * Convert the data block number to a free block, |
---|
1292 | 1350 | * read in the free block. |
---|
1293 | 1351 | */ |
---|
1294 | | - fdb = dp->d_ops->db_to_fdb(args->geo, db); |
---|
1295 | | - error = xfs_dir2_free_read(tp, dp, |
---|
1296 | | - xfs_dir2_db_to_da(args->geo, fdb), |
---|
| 1352 | + fdb = xfs_dir2_db_to_fdb(geo, db); |
---|
| 1353 | + error = xfs_dir2_free_read(tp, dp, xfs_dir2_db_to_da(geo, fdb), |
---|
1297 | 1354 | &fbp); |
---|
1298 | 1355 | if (error) |
---|
1299 | 1356 | return error; |
---|
.. | .. |
---|
1301 | 1358 | #ifdef DEBUG |
---|
1302 | 1359 | { |
---|
1303 | 1360 | struct xfs_dir3_icfree_hdr freehdr; |
---|
1304 | | - dp->d_ops->free_hdr_from_disk(&freehdr, free); |
---|
1305 | | - ASSERT(freehdr.firstdb == dp->d_ops->free_max_bests(args->geo) * |
---|
1306 | | - (fdb - xfs_dir2_byte_to_db(args->geo, |
---|
1307 | | - XFS_DIR2_FREE_OFFSET))); |
---|
| 1361 | + |
---|
| 1362 | + xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, free); |
---|
| 1363 | + ASSERT(freehdr.firstdb == geo->free_max_bests * |
---|
| 1364 | + (fdb - xfs_dir2_byte_to_db(geo, XFS_DIR2_FREE_OFFSET))); |
---|
1308 | 1365 | } |
---|
1309 | 1366 | #endif |
---|
1310 | 1367 | /* |
---|
1311 | 1368 | * Calculate which entry we need to fix. |
---|
1312 | 1369 | */ |
---|
1313 | | - findex = dp->d_ops->db_to_fdindex(args->geo, db); |
---|
| 1370 | + findex = xfs_dir2_db_to_fdindex(geo, db); |
---|
1314 | 1371 | longest = be16_to_cpu(bf[0].length); |
---|
1315 | 1372 | /* |
---|
1316 | 1373 | * If the data block is now empty we can get rid of it |
---|
1317 | 1374 | * (usually). |
---|
1318 | 1375 | */ |
---|
1319 | | - if (longest == args->geo->blksize - |
---|
1320 | | - dp->d_ops->data_entry_offset) { |
---|
| 1376 | + if (longest == geo->blksize - geo->data_entry_offset) { |
---|
1321 | 1377 | /* |
---|
1322 | 1378 | * Try to punch out the data block. |
---|
1323 | 1379 | */ |
---|
.. | .. |
---|
1349 | 1405 | * Return indication of whether this leaf block is empty enough |
---|
1350 | 1406 | * to justify trying to join it with a neighbor. |
---|
1351 | 1407 | */ |
---|
1352 | | - *rval = (dp->d_ops->leaf_hdr_size + |
---|
1353 | | - (uint)sizeof(ents[0]) * (leafhdr.count - leafhdr.stale)) < |
---|
1354 | | - args->geo->magicpct; |
---|
| 1408 | + *rval = (geo->leaf_hdr_size + |
---|
| 1409 | + (uint)sizeof(leafhdr.ents) * (leafhdr.count - leafhdr.stale)) < |
---|
| 1410 | + geo->magicpct; |
---|
1355 | 1411 | return 0; |
---|
1356 | 1412 | } |
---|
1357 | 1413 | |
---|
.. | .. |
---|
1450 | 1506 | */ |
---|
1451 | 1507 | blk = &state->path.blk[state->path.active - 1]; |
---|
1452 | 1508 | leaf = blk->bp->b_addr; |
---|
1453 | | - dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf); |
---|
1454 | | - ents = dp->d_ops->leaf_ents_p(leaf); |
---|
| 1509 | + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &leafhdr, leaf); |
---|
| 1510 | + ents = leafhdr.ents; |
---|
1455 | 1511 | xfs_dir3_leaf_check(dp, blk->bp); |
---|
1456 | 1512 | |
---|
1457 | 1513 | count = leafhdr.count - leafhdr.stale; |
---|
1458 | | - bytes = dp->d_ops->leaf_hdr_size + count * sizeof(ents[0]); |
---|
| 1514 | + bytes = state->args->geo->leaf_hdr_size + count * sizeof(ents[0]); |
---|
1459 | 1515 | if (bytes > (state->args->geo->blksize >> 1)) { |
---|
1460 | 1516 | /* |
---|
1461 | 1517 | * Blk over 50%, don't try to join. |
---|
.. | .. |
---|
1500 | 1556 | /* |
---|
1501 | 1557 | * Read the sibling leaf block. |
---|
1502 | 1558 | */ |
---|
1503 | | - error = xfs_dir3_leafn_read(state->args->trans, dp, |
---|
1504 | | - blkno, -1, &bp); |
---|
| 1559 | + error = xfs_dir3_leafn_read(state->args->trans, dp, blkno, &bp); |
---|
1505 | 1560 | if (error) |
---|
1506 | 1561 | return error; |
---|
1507 | 1562 | |
---|
.. | .. |
---|
1513 | 1568 | (state->args->geo->blksize >> 2); |
---|
1514 | 1569 | |
---|
1515 | 1570 | leaf = bp->b_addr; |
---|
1516 | | - dp->d_ops->leaf_hdr_from_disk(&hdr2, leaf); |
---|
1517 | | - ents = dp->d_ops->leaf_ents_p(leaf); |
---|
| 1571 | + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &hdr2, leaf); |
---|
| 1572 | + ents = hdr2.ents; |
---|
1518 | 1573 | count += hdr2.count - hdr2.stale; |
---|
1519 | 1574 | bytes -= count * sizeof(ents[0]); |
---|
1520 | 1575 | |
---|
.. | .. |
---|
1576 | 1631 | drop_leaf = drop_blk->bp->b_addr; |
---|
1577 | 1632 | save_leaf = save_blk->bp->b_addr; |
---|
1578 | 1633 | |
---|
1579 | | - dp->d_ops->leaf_hdr_from_disk(&savehdr, save_leaf); |
---|
1580 | | - dp->d_ops->leaf_hdr_from_disk(&drophdr, drop_leaf); |
---|
1581 | | - sents = dp->d_ops->leaf_ents_p(save_leaf); |
---|
1582 | | - dents = dp->d_ops->leaf_ents_p(drop_leaf); |
---|
| 1634 | + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &savehdr, save_leaf); |
---|
| 1635 | + xfs_dir2_leaf_hdr_from_disk(dp->i_mount, &drophdr, drop_leaf); |
---|
| 1636 | + sents = savehdr.ents; |
---|
| 1637 | + dents = drophdr.ents; |
---|
1583 | 1638 | |
---|
1584 | 1639 | /* |
---|
1585 | 1640 | * If there are any stale leaf entries, take this opportunity |
---|
.. | .. |
---|
1605 | 1660 | save_blk->hashval = be32_to_cpu(sents[savehdr.count - 1].hashval); |
---|
1606 | 1661 | |
---|
1607 | 1662 | /* log the changes made when moving the entries */ |
---|
1608 | | - dp->d_ops->leaf_hdr_to_disk(save_leaf, &savehdr); |
---|
1609 | | - dp->d_ops->leaf_hdr_to_disk(drop_leaf, &drophdr); |
---|
| 1663 | + xfs_dir2_leaf_hdr_to_disk(dp->i_mount, save_leaf, &savehdr); |
---|
| 1664 | + xfs_dir2_leaf_hdr_to_disk(dp->i_mount, drop_leaf, &drophdr); |
---|
1610 | 1665 | xfs_dir3_leaf_log_header(args, save_blk->bp); |
---|
1611 | 1666 | xfs_dir3_leaf_log_header(args, drop_blk->bp); |
---|
1612 | 1667 | |
---|
1613 | 1668 | xfs_dir3_leaf_check(dp, save_blk->bp); |
---|
1614 | 1669 | xfs_dir3_leaf_check(dp, drop_blk->bp); |
---|
| 1670 | +} |
---|
| 1671 | + |
---|
| 1672 | +/* |
---|
| 1673 | + * Add a new data block to the directory at the free space index that the caller |
---|
| 1674 | + * has specified. |
---|
| 1675 | + */ |
---|
| 1676 | +static int |
---|
| 1677 | +xfs_dir2_node_add_datablk( |
---|
| 1678 | + struct xfs_da_args *args, |
---|
| 1679 | + struct xfs_da_state_blk *fblk, |
---|
| 1680 | + xfs_dir2_db_t *dbno, |
---|
| 1681 | + struct xfs_buf **dbpp, |
---|
| 1682 | + struct xfs_buf **fbpp, |
---|
| 1683 | + struct xfs_dir3_icfree_hdr *hdr, |
---|
| 1684 | + int *findex) |
---|
| 1685 | +{ |
---|
| 1686 | + struct xfs_inode *dp = args->dp; |
---|
| 1687 | + struct xfs_trans *tp = args->trans; |
---|
| 1688 | + struct xfs_mount *mp = dp->i_mount; |
---|
| 1689 | + struct xfs_dir2_data_free *bf; |
---|
| 1690 | + xfs_dir2_db_t fbno; |
---|
| 1691 | + struct xfs_buf *fbp; |
---|
| 1692 | + struct xfs_buf *dbp; |
---|
| 1693 | + int error; |
---|
| 1694 | + |
---|
| 1695 | + /* Not allowed to allocate, return failure. */ |
---|
| 1696 | + if (args->total == 0) |
---|
| 1697 | + return -ENOSPC; |
---|
| 1698 | + |
---|
| 1699 | + /* Allocate and initialize the new data block. */ |
---|
| 1700 | + error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, dbno); |
---|
| 1701 | + if (error) |
---|
| 1702 | + return error; |
---|
| 1703 | + error = xfs_dir3_data_init(args, *dbno, &dbp); |
---|
| 1704 | + if (error) |
---|
| 1705 | + return error; |
---|
| 1706 | + |
---|
| 1707 | + /* |
---|
| 1708 | + * Get the freespace block corresponding to the data block |
---|
| 1709 | + * that was just allocated. |
---|
| 1710 | + */ |
---|
| 1711 | + fbno = xfs_dir2_db_to_fdb(args->geo, *dbno); |
---|
| 1712 | + error = xfs_dir2_free_try_read(tp, dp, |
---|
| 1713 | + xfs_dir2_db_to_da(args->geo, fbno), &fbp); |
---|
| 1714 | + if (error) |
---|
| 1715 | + return error; |
---|
| 1716 | + |
---|
| 1717 | + /* |
---|
| 1718 | + * If there wasn't a freespace block, the read will |
---|
| 1719 | + * return a NULL fbp. Allocate and initialize a new one. |
---|
| 1720 | + */ |
---|
| 1721 | + if (!fbp) { |
---|
| 1722 | + error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE, &fbno); |
---|
| 1723 | + if (error) |
---|
| 1724 | + return error; |
---|
| 1725 | + |
---|
| 1726 | + if (XFS_IS_CORRUPT(mp, |
---|
| 1727 | + xfs_dir2_db_to_fdb(args->geo, *dbno) != |
---|
| 1728 | + fbno)) { |
---|
| 1729 | + xfs_alert(mp, |
---|
| 1730 | +"%s: dir ino %llu needed freesp block %lld for data block %lld, got %lld", |
---|
| 1731 | + __func__, (unsigned long long)dp->i_ino, |
---|
| 1732 | + (long long)xfs_dir2_db_to_fdb(args->geo, *dbno), |
---|
| 1733 | + (long long)*dbno, (long long)fbno); |
---|
| 1734 | + if (fblk) { |
---|
| 1735 | + xfs_alert(mp, |
---|
| 1736 | + " fblk "PTR_FMT" blkno %llu index %d magic 0x%x", |
---|
| 1737 | + fblk, (unsigned long long)fblk->blkno, |
---|
| 1738 | + fblk->index, fblk->magic); |
---|
| 1739 | + } else { |
---|
| 1740 | + xfs_alert(mp, " ... fblk is NULL"); |
---|
| 1741 | + } |
---|
| 1742 | + return -EFSCORRUPTED; |
---|
| 1743 | + } |
---|
| 1744 | + |
---|
| 1745 | + /* Get a buffer for the new block. */ |
---|
| 1746 | + error = xfs_dir3_free_get_buf(args, fbno, &fbp); |
---|
| 1747 | + if (error) |
---|
| 1748 | + return error; |
---|
| 1749 | + xfs_dir2_free_hdr_from_disk(mp, hdr, fbp->b_addr); |
---|
| 1750 | + |
---|
| 1751 | + /* Remember the first slot as our empty slot. */ |
---|
| 1752 | + hdr->firstdb = (fbno - xfs_dir2_byte_to_db(args->geo, |
---|
| 1753 | + XFS_DIR2_FREE_OFFSET)) * |
---|
| 1754 | + args->geo->free_max_bests; |
---|
| 1755 | + } else { |
---|
| 1756 | + xfs_dir2_free_hdr_from_disk(mp, hdr, fbp->b_addr); |
---|
| 1757 | + } |
---|
| 1758 | + |
---|
| 1759 | + /* Set the freespace block index from the data block number. */ |
---|
| 1760 | + *findex = xfs_dir2_db_to_fdindex(args->geo, *dbno); |
---|
| 1761 | + |
---|
| 1762 | + /* Extend the freespace table if the new data block is off the end. */ |
---|
| 1763 | + if (*findex >= hdr->nvalid) { |
---|
| 1764 | + ASSERT(*findex < args->geo->free_max_bests); |
---|
| 1765 | + hdr->nvalid = *findex + 1; |
---|
| 1766 | + hdr->bests[*findex] = cpu_to_be16(NULLDATAOFF); |
---|
| 1767 | + } |
---|
| 1768 | + |
---|
| 1769 | + /* |
---|
| 1770 | + * If this entry was for an empty data block (this should always be |
---|
| 1771 | + * true) then update the header. |
---|
| 1772 | + */ |
---|
| 1773 | + if (hdr->bests[*findex] == cpu_to_be16(NULLDATAOFF)) { |
---|
| 1774 | + hdr->nused++; |
---|
| 1775 | + xfs_dir2_free_hdr_to_disk(mp, fbp->b_addr, hdr); |
---|
| 1776 | + xfs_dir2_free_log_header(args, fbp); |
---|
| 1777 | + } |
---|
| 1778 | + |
---|
| 1779 | + /* Update the freespace value for the new block in the table. */ |
---|
| 1780 | + bf = xfs_dir2_data_bestfree_p(mp, dbp->b_addr); |
---|
| 1781 | + hdr->bests[*findex] = bf[0].length; |
---|
| 1782 | + |
---|
| 1783 | + *dbpp = dbp; |
---|
| 1784 | + *fbpp = fbp; |
---|
| 1785 | + return 0; |
---|
| 1786 | +} |
---|
| 1787 | + |
---|
| 1788 | +static int |
---|
| 1789 | +xfs_dir2_node_find_freeblk( |
---|
| 1790 | + struct xfs_da_args *args, |
---|
| 1791 | + struct xfs_da_state_blk *fblk, |
---|
| 1792 | + xfs_dir2_db_t *dbnop, |
---|
| 1793 | + struct xfs_buf **fbpp, |
---|
| 1794 | + struct xfs_dir3_icfree_hdr *hdr, |
---|
| 1795 | + int *findexp, |
---|
| 1796 | + int length) |
---|
| 1797 | +{ |
---|
| 1798 | + struct xfs_inode *dp = args->dp; |
---|
| 1799 | + struct xfs_trans *tp = args->trans; |
---|
| 1800 | + struct xfs_buf *fbp = NULL; |
---|
| 1801 | + xfs_dir2_db_t firstfbno; |
---|
| 1802 | + xfs_dir2_db_t lastfbno; |
---|
| 1803 | + xfs_dir2_db_t ifbno = -1; |
---|
| 1804 | + xfs_dir2_db_t dbno = -1; |
---|
| 1805 | + xfs_dir2_db_t fbno; |
---|
| 1806 | + xfs_fileoff_t fo; |
---|
| 1807 | + int findex = 0; |
---|
| 1808 | + int error; |
---|
| 1809 | + |
---|
| 1810 | + /* |
---|
| 1811 | + * If we came in with a freespace block that means that lookup |
---|
| 1812 | + * found an entry with our hash value. This is the freespace |
---|
| 1813 | + * block for that data entry. |
---|
| 1814 | + */ |
---|
| 1815 | + if (fblk) { |
---|
| 1816 | + fbp = fblk->bp; |
---|
| 1817 | + findex = fblk->index; |
---|
| 1818 | + xfs_dir2_free_hdr_from_disk(dp->i_mount, hdr, fbp->b_addr); |
---|
| 1819 | + if (findex >= 0) { |
---|
| 1820 | + /* caller already found the freespace for us. */ |
---|
| 1821 | + ASSERT(findex < hdr->nvalid); |
---|
| 1822 | + ASSERT(be16_to_cpu(hdr->bests[findex]) != NULLDATAOFF); |
---|
| 1823 | + ASSERT(be16_to_cpu(hdr->bests[findex]) >= length); |
---|
| 1824 | + dbno = hdr->firstdb + findex; |
---|
| 1825 | + goto found_block; |
---|
| 1826 | + } |
---|
| 1827 | + |
---|
| 1828 | + /* |
---|
| 1829 | + * The data block looked at didn't have enough room. |
---|
| 1830 | + * We'll start at the beginning of the freespace entries. |
---|
| 1831 | + */ |
---|
| 1832 | + ifbno = fblk->blkno; |
---|
| 1833 | + xfs_trans_brelse(tp, fbp); |
---|
| 1834 | + fbp = NULL; |
---|
| 1835 | + fblk->bp = NULL; |
---|
| 1836 | + } |
---|
| 1837 | + |
---|
| 1838 | + /* |
---|
| 1839 | + * If we don't have a data block yet, we're going to scan the freespace |
---|
| 1840 | + * data for a data block with enough free space in it. |
---|
| 1841 | + */ |
---|
| 1842 | + error = xfs_bmap_last_offset(dp, &fo, XFS_DATA_FORK); |
---|
| 1843 | + if (error) |
---|
| 1844 | + return error; |
---|
| 1845 | + lastfbno = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)fo); |
---|
| 1846 | + firstfbno = xfs_dir2_byte_to_db(args->geo, XFS_DIR2_FREE_OFFSET); |
---|
| 1847 | + |
---|
| 1848 | + for (fbno = lastfbno - 1; fbno >= firstfbno; fbno--) { |
---|
| 1849 | + /* If it's ifbno we already looked at it. */ |
---|
| 1850 | + if (fbno == ifbno) |
---|
| 1851 | + continue; |
---|
| 1852 | + |
---|
| 1853 | + /* |
---|
| 1854 | + * Read the block. There can be holes in the freespace blocks, |
---|
| 1855 | + * so this might not succeed. This should be really rare, so |
---|
| 1856 | + * there's no reason to avoid it. |
---|
| 1857 | + */ |
---|
| 1858 | + error = xfs_dir2_free_try_read(tp, dp, |
---|
| 1859 | + xfs_dir2_db_to_da(args->geo, fbno), |
---|
| 1860 | + &fbp); |
---|
| 1861 | + if (error) |
---|
| 1862 | + return error; |
---|
| 1863 | + if (!fbp) |
---|
| 1864 | + continue; |
---|
| 1865 | + |
---|
| 1866 | + xfs_dir2_free_hdr_from_disk(dp->i_mount, hdr, fbp->b_addr); |
---|
| 1867 | + |
---|
| 1868 | + /* Scan the free entry array for a large enough free space. */ |
---|
| 1869 | + for (findex = hdr->nvalid - 1; findex >= 0; findex--) { |
---|
| 1870 | + if (be16_to_cpu(hdr->bests[findex]) != NULLDATAOFF && |
---|
| 1871 | + be16_to_cpu(hdr->bests[findex]) >= length) { |
---|
| 1872 | + dbno = hdr->firstdb + findex; |
---|
| 1873 | + goto found_block; |
---|
| 1874 | + } |
---|
| 1875 | + } |
---|
| 1876 | + |
---|
| 1877 | + /* Didn't find free space, go on to next free block */ |
---|
| 1878 | + xfs_trans_brelse(tp, fbp); |
---|
| 1879 | + } |
---|
| 1880 | + |
---|
| 1881 | +found_block: |
---|
| 1882 | + *dbnop = dbno; |
---|
| 1883 | + *fbpp = fbp; |
---|
| 1884 | + *findexp = findex; |
---|
| 1885 | + return 0; |
---|
| 1886 | +} |
---|
| 1887 | + |
---|
| 1888 | +/* |
---|
| 1889 | + * Add the data entry for a node-format directory name addition. |
---|
| 1890 | + * The leaf entry is added in xfs_dir2_leafn_add. |
---|
| 1891 | + * We may enter with a freespace block that the lookup found. |
---|
| 1892 | + */ |
---|
| 1893 | +static int |
---|
| 1894 | +xfs_dir2_node_addname_int( |
---|
| 1895 | + struct xfs_da_args *args, /* operation arguments */ |
---|
| 1896 | + struct xfs_da_state_blk *fblk) /* optional freespace block */ |
---|
| 1897 | +{ |
---|
| 1898 | + struct xfs_dir2_data_unused *dup; /* data unused entry pointer */ |
---|
| 1899 | + struct xfs_dir2_data_entry *dep; /* data entry pointer */ |
---|
| 1900 | + struct xfs_dir2_data_hdr *hdr; /* data block header */ |
---|
| 1901 | + struct xfs_dir2_data_free *bf; |
---|
| 1902 | + struct xfs_trans *tp = args->trans; |
---|
| 1903 | + struct xfs_inode *dp = args->dp; |
---|
| 1904 | + struct xfs_dir3_icfree_hdr freehdr; |
---|
| 1905 | + struct xfs_buf *dbp; /* data block buffer */ |
---|
| 1906 | + struct xfs_buf *fbp; /* freespace buffer */ |
---|
| 1907 | + xfs_dir2_data_aoff_t aoff; |
---|
| 1908 | + xfs_dir2_db_t dbno; /* data block number */ |
---|
| 1909 | + int error; /* error return value */ |
---|
| 1910 | + int findex; /* freespace entry index */ |
---|
| 1911 | + int length; /* length of the new entry */ |
---|
| 1912 | + int logfree = 0; /* need to log free entry */ |
---|
| 1913 | + int needlog = 0; /* need to log data header */ |
---|
| 1914 | + int needscan = 0; /* need to rescan data frees */ |
---|
| 1915 | + __be16 *tagp; /* data entry tag pointer */ |
---|
| 1916 | + |
---|
| 1917 | + length = xfs_dir2_data_entsize(dp->i_mount, args->namelen); |
---|
| 1918 | + error = xfs_dir2_node_find_freeblk(args, fblk, &dbno, &fbp, &freehdr, |
---|
| 1919 | + &findex, length); |
---|
| 1920 | + if (error) |
---|
| 1921 | + return error; |
---|
| 1922 | + |
---|
| 1923 | + /* |
---|
| 1924 | + * Now we know if we must allocate blocks, so if we are checking whether |
---|
| 1925 | + * we can insert without allocation then we can return now. |
---|
| 1926 | + */ |
---|
| 1927 | + if (args->op_flags & XFS_DA_OP_JUSTCHECK) { |
---|
| 1928 | + if (dbno == -1) |
---|
| 1929 | + return -ENOSPC; |
---|
| 1930 | + return 0; |
---|
| 1931 | + } |
---|
| 1932 | + |
---|
| 1933 | + /* |
---|
| 1934 | + * If we don't have a data block, we need to allocate one and make |
---|
| 1935 | + * the freespace entries refer to it. |
---|
| 1936 | + */ |
---|
| 1937 | + if (dbno == -1) { |
---|
| 1938 | + /* we're going to have to log the free block index later */ |
---|
| 1939 | + logfree = 1; |
---|
| 1940 | + error = xfs_dir2_node_add_datablk(args, fblk, &dbno, &dbp, &fbp, |
---|
| 1941 | + &freehdr, &findex); |
---|
| 1942 | + } else { |
---|
| 1943 | + /* Read the data block in. */ |
---|
| 1944 | + error = xfs_dir3_data_read(tp, dp, |
---|
| 1945 | + xfs_dir2_db_to_da(args->geo, dbno), |
---|
| 1946 | + 0, &dbp); |
---|
| 1947 | + } |
---|
| 1948 | + if (error) |
---|
| 1949 | + return error; |
---|
| 1950 | + |
---|
| 1951 | + /* setup for data block up now */ |
---|
| 1952 | + hdr = dbp->b_addr; |
---|
| 1953 | + bf = xfs_dir2_data_bestfree_p(dp->i_mount, hdr); |
---|
| 1954 | + ASSERT(be16_to_cpu(bf[0].length) >= length); |
---|
| 1955 | + |
---|
| 1956 | + /* Point to the existing unused space. */ |
---|
| 1957 | + dup = (xfs_dir2_data_unused_t *) |
---|
| 1958 | + ((char *)hdr + be16_to_cpu(bf[0].offset)); |
---|
| 1959 | + |
---|
| 1960 | + /* Mark the first part of the unused space, inuse for us. */ |
---|
| 1961 | + aoff = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr); |
---|
| 1962 | + error = xfs_dir2_data_use_free(args, dbp, dup, aoff, length, |
---|
| 1963 | + &needlog, &needscan); |
---|
| 1964 | + if (error) { |
---|
| 1965 | + xfs_trans_brelse(tp, dbp); |
---|
| 1966 | + return error; |
---|
| 1967 | + } |
---|
| 1968 | + |
---|
| 1969 | + /* Fill in the new entry and log it. */ |
---|
| 1970 | + dep = (xfs_dir2_data_entry_t *)dup; |
---|
| 1971 | + dep->inumber = cpu_to_be64(args->inumber); |
---|
| 1972 | + dep->namelen = args->namelen; |
---|
| 1973 | + memcpy(dep->name, args->name, dep->namelen); |
---|
| 1974 | + xfs_dir2_data_put_ftype(dp->i_mount, dep, args->filetype); |
---|
| 1975 | + tagp = xfs_dir2_data_entry_tag_p(dp->i_mount, dep); |
---|
| 1976 | + *tagp = cpu_to_be16((char *)dep - (char *)hdr); |
---|
| 1977 | + xfs_dir2_data_log_entry(args, dbp, dep); |
---|
| 1978 | + |
---|
| 1979 | + /* Rescan the freespace and log the data block if needed. */ |
---|
| 1980 | + if (needscan) |
---|
| 1981 | + xfs_dir2_data_freescan(dp->i_mount, hdr, &needlog); |
---|
| 1982 | + if (needlog) |
---|
| 1983 | + xfs_dir2_data_log_header(args, dbp); |
---|
| 1984 | + |
---|
| 1985 | + /* If the freespace block entry is now wrong, update it. */ |
---|
| 1986 | + if (freehdr.bests[findex] != bf[0].length) { |
---|
| 1987 | + freehdr.bests[findex] = bf[0].length; |
---|
| 1988 | + logfree = 1; |
---|
| 1989 | + } |
---|
| 1990 | + |
---|
| 1991 | + /* Log the freespace entry if needed. */ |
---|
| 1992 | + if (logfree) |
---|
| 1993 | + xfs_dir2_free_log_bests(args, &freehdr, fbp, findex, findex); |
---|
| 1994 | + |
---|
| 1995 | + /* Return the data block and offset in args. */ |
---|
| 1996 | + args->blkno = (xfs_dablk_t)dbno; |
---|
| 1997 | + args->index = be16_to_cpu(*tagp); |
---|
| 1998 | + return 0; |
---|
1615 | 1999 | } |
---|
1616 | 2000 | |
---|
1617 | 2001 | /* |
---|
.. | .. |
---|
1631 | 2015 | /* |
---|
1632 | 2016 | * Allocate and initialize the state (btree cursor). |
---|
1633 | 2017 | */ |
---|
1634 | | - state = xfs_da_state_alloc(); |
---|
1635 | | - state->args = args; |
---|
1636 | | - state->mp = args->dp->i_mount; |
---|
| 2018 | + state = xfs_da_state_alloc(args); |
---|
1637 | 2019 | /* |
---|
1638 | 2020 | * Look up the name. We're not supposed to find it, but |
---|
1639 | 2021 | * this gives us the insertion point. |
---|
.. | .. |
---|
1684 | 2066 | } |
---|
1685 | 2067 | |
---|
1686 | 2068 | /* |
---|
1687 | | - * Add the data entry for a node-format directory name addition. |
---|
1688 | | - * The leaf entry is added in xfs_dir2_leafn_add. |
---|
1689 | | - * We may enter with a freespace block that the lookup found. |
---|
1690 | | - */ |
---|
1691 | | -static int /* error */ |
---|
1692 | | -xfs_dir2_node_addname_int( |
---|
1693 | | - xfs_da_args_t *args, /* operation arguments */ |
---|
1694 | | - xfs_da_state_blk_t *fblk) /* optional freespace block */ |
---|
1695 | | -{ |
---|
1696 | | - xfs_dir2_data_hdr_t *hdr; /* data block header */ |
---|
1697 | | - xfs_dir2_db_t dbno; /* data block number */ |
---|
1698 | | - struct xfs_buf *dbp; /* data block buffer */ |
---|
1699 | | - xfs_dir2_data_entry_t *dep; /* data entry pointer */ |
---|
1700 | | - xfs_inode_t *dp; /* incore directory inode */ |
---|
1701 | | - xfs_dir2_data_unused_t *dup; /* data unused entry pointer */ |
---|
1702 | | - int error; /* error return value */ |
---|
1703 | | - xfs_dir2_db_t fbno; /* freespace block number */ |
---|
1704 | | - struct xfs_buf *fbp; /* freespace buffer */ |
---|
1705 | | - int findex; /* freespace entry index */ |
---|
1706 | | - xfs_dir2_free_t *free=NULL; /* freespace block structure */ |
---|
1707 | | - xfs_dir2_db_t ifbno; /* initial freespace block no */ |
---|
1708 | | - xfs_dir2_db_t lastfbno=0; /* highest freespace block no */ |
---|
1709 | | - int length; /* length of the new entry */ |
---|
1710 | | - int logfree; /* need to log free entry */ |
---|
1711 | | - xfs_mount_t *mp; /* filesystem mount point */ |
---|
1712 | | - int needlog; /* need to log data header */ |
---|
1713 | | - int needscan; /* need to rescan data frees */ |
---|
1714 | | - __be16 *tagp; /* data entry tag pointer */ |
---|
1715 | | - xfs_trans_t *tp; /* transaction pointer */ |
---|
1716 | | - __be16 *bests; |
---|
1717 | | - struct xfs_dir3_icfree_hdr freehdr; |
---|
1718 | | - struct xfs_dir2_data_free *bf; |
---|
1719 | | - xfs_dir2_data_aoff_t aoff; |
---|
1720 | | - |
---|
1721 | | - dp = args->dp; |
---|
1722 | | - mp = dp->i_mount; |
---|
1723 | | - tp = args->trans; |
---|
1724 | | - length = dp->d_ops->data_entsize(args->namelen); |
---|
1725 | | - /* |
---|
1726 | | - * If we came in with a freespace block that means that lookup |
---|
1727 | | - * found an entry with our hash value. This is the freespace |
---|
1728 | | - * block for that data entry. |
---|
1729 | | - */ |
---|
1730 | | - if (fblk) { |
---|
1731 | | - fbp = fblk->bp; |
---|
1732 | | - /* |
---|
1733 | | - * Remember initial freespace block number. |
---|
1734 | | - */ |
---|
1735 | | - ifbno = fblk->blkno; |
---|
1736 | | - free = fbp->b_addr; |
---|
1737 | | - findex = fblk->index; |
---|
1738 | | - bests = dp->d_ops->free_bests_p(free); |
---|
1739 | | - dp->d_ops->free_hdr_from_disk(&freehdr, free); |
---|
1740 | | - |
---|
1741 | | - /* |
---|
1742 | | - * This means the free entry showed that the data block had |
---|
1743 | | - * space for our entry, so we remembered it. |
---|
1744 | | - * Use that data block. |
---|
1745 | | - */ |
---|
1746 | | - if (findex >= 0) { |
---|
1747 | | - ASSERT(findex < freehdr.nvalid); |
---|
1748 | | - ASSERT(be16_to_cpu(bests[findex]) != NULLDATAOFF); |
---|
1749 | | - ASSERT(be16_to_cpu(bests[findex]) >= length); |
---|
1750 | | - dbno = freehdr.firstdb + findex; |
---|
1751 | | - } else { |
---|
1752 | | - /* |
---|
1753 | | - * The data block looked at didn't have enough room. |
---|
1754 | | - * We'll start at the beginning of the freespace entries. |
---|
1755 | | - */ |
---|
1756 | | - dbno = -1; |
---|
1757 | | - findex = 0; |
---|
1758 | | - } |
---|
1759 | | - } else { |
---|
1760 | | - /* |
---|
1761 | | - * Didn't come in with a freespace block, so no data block. |
---|
1762 | | - */ |
---|
1763 | | - ifbno = dbno = -1; |
---|
1764 | | - fbp = NULL; |
---|
1765 | | - findex = 0; |
---|
1766 | | - } |
---|
1767 | | - |
---|
1768 | | - /* |
---|
1769 | | - * If we don't have a data block yet, we're going to scan the |
---|
1770 | | - * freespace blocks looking for one. Figure out what the |
---|
1771 | | - * highest freespace block number is. |
---|
1772 | | - */ |
---|
1773 | | - if (dbno == -1) { |
---|
1774 | | - xfs_fileoff_t fo; /* freespace block number */ |
---|
1775 | | - |
---|
1776 | | - if ((error = xfs_bmap_last_offset(dp, &fo, XFS_DATA_FORK))) |
---|
1777 | | - return error; |
---|
1778 | | - lastfbno = xfs_dir2_da_to_db(args->geo, (xfs_dablk_t)fo); |
---|
1779 | | - fbno = ifbno; |
---|
1780 | | - } |
---|
1781 | | - /* |
---|
1782 | | - * While we haven't identified a data block, search the freeblock |
---|
1783 | | - * data for a good data block. If we find a null freeblock entry, |
---|
1784 | | - * indicating a hole in the data blocks, remember that. |
---|
1785 | | - */ |
---|
1786 | | - while (dbno == -1) { |
---|
1787 | | - /* |
---|
1788 | | - * If we don't have a freeblock in hand, get the next one. |
---|
1789 | | - */ |
---|
1790 | | - if (fbp == NULL) { |
---|
1791 | | - /* |
---|
1792 | | - * Happens the first time through unless lookup gave |
---|
1793 | | - * us a freespace block to start with. |
---|
1794 | | - */ |
---|
1795 | | - if (++fbno == 0) |
---|
1796 | | - fbno = xfs_dir2_byte_to_db(args->geo, |
---|
1797 | | - XFS_DIR2_FREE_OFFSET); |
---|
1798 | | - /* |
---|
1799 | | - * If it's ifbno we already looked at it. |
---|
1800 | | - */ |
---|
1801 | | - if (fbno == ifbno) |
---|
1802 | | - fbno++; |
---|
1803 | | - /* |
---|
1804 | | - * If it's off the end we're done. |
---|
1805 | | - */ |
---|
1806 | | - if (fbno >= lastfbno) |
---|
1807 | | - break; |
---|
1808 | | - /* |
---|
1809 | | - * Read the block. There can be holes in the |
---|
1810 | | - * freespace blocks, so this might not succeed. |
---|
1811 | | - * This should be really rare, so there's no reason |
---|
1812 | | - * to avoid it. |
---|
1813 | | - */ |
---|
1814 | | - error = xfs_dir2_free_try_read(tp, dp, |
---|
1815 | | - xfs_dir2_db_to_da(args->geo, fbno), |
---|
1816 | | - &fbp); |
---|
1817 | | - if (error) |
---|
1818 | | - return error; |
---|
1819 | | - if (!fbp) |
---|
1820 | | - continue; |
---|
1821 | | - free = fbp->b_addr; |
---|
1822 | | - findex = 0; |
---|
1823 | | - } |
---|
1824 | | - /* |
---|
1825 | | - * Look at the current free entry. Is it good enough? |
---|
1826 | | - * |
---|
1827 | | - * The bests initialisation should be where the bufer is read in |
---|
1828 | | - * the above branch. But gcc is too stupid to realise that bests |
---|
1829 | | - * and the freehdr are actually initialised if they are placed |
---|
1830 | | - * there, so we have to do it here to avoid warnings. Blech. |
---|
1831 | | - */ |
---|
1832 | | - bests = dp->d_ops->free_bests_p(free); |
---|
1833 | | - dp->d_ops->free_hdr_from_disk(&freehdr, free); |
---|
1834 | | - if (be16_to_cpu(bests[findex]) != NULLDATAOFF && |
---|
1835 | | - be16_to_cpu(bests[findex]) >= length) |
---|
1836 | | - dbno = freehdr.firstdb + findex; |
---|
1837 | | - else { |
---|
1838 | | - /* |
---|
1839 | | - * Are we done with the freeblock? |
---|
1840 | | - */ |
---|
1841 | | - if (++findex == freehdr.nvalid) { |
---|
1842 | | - /* |
---|
1843 | | - * Drop the block. |
---|
1844 | | - */ |
---|
1845 | | - xfs_trans_brelse(tp, fbp); |
---|
1846 | | - fbp = NULL; |
---|
1847 | | - if (fblk && fblk->bp) |
---|
1848 | | - fblk->bp = NULL; |
---|
1849 | | - } |
---|
1850 | | - } |
---|
1851 | | - } |
---|
1852 | | - /* |
---|
1853 | | - * If we don't have a data block, we need to allocate one and make |
---|
1854 | | - * the freespace entries refer to it. |
---|
1855 | | - */ |
---|
1856 | | - if (unlikely(dbno == -1)) { |
---|
1857 | | - /* |
---|
1858 | | - * Not allowed to allocate, return failure. |
---|
1859 | | - */ |
---|
1860 | | - if ((args->op_flags & XFS_DA_OP_JUSTCHECK) || args->total == 0) |
---|
1861 | | - return -ENOSPC; |
---|
1862 | | - |
---|
1863 | | - /* |
---|
1864 | | - * Allocate and initialize the new data block. |
---|
1865 | | - */ |
---|
1866 | | - if (unlikely((error = xfs_dir2_grow_inode(args, |
---|
1867 | | - XFS_DIR2_DATA_SPACE, |
---|
1868 | | - &dbno)) || |
---|
1869 | | - (error = xfs_dir3_data_init(args, dbno, &dbp)))) |
---|
1870 | | - return error; |
---|
1871 | | - |
---|
1872 | | - /* |
---|
1873 | | - * If (somehow) we have a freespace block, get rid of it. |
---|
1874 | | - */ |
---|
1875 | | - if (fbp) |
---|
1876 | | - xfs_trans_brelse(tp, fbp); |
---|
1877 | | - if (fblk && fblk->bp) |
---|
1878 | | - fblk->bp = NULL; |
---|
1879 | | - |
---|
1880 | | - /* |
---|
1881 | | - * Get the freespace block corresponding to the data block |
---|
1882 | | - * that was just allocated. |
---|
1883 | | - */ |
---|
1884 | | - fbno = dp->d_ops->db_to_fdb(args->geo, dbno); |
---|
1885 | | - error = xfs_dir2_free_try_read(tp, dp, |
---|
1886 | | - xfs_dir2_db_to_da(args->geo, fbno), |
---|
1887 | | - &fbp); |
---|
1888 | | - if (error) |
---|
1889 | | - return error; |
---|
1890 | | - |
---|
1891 | | - /* |
---|
1892 | | - * If there wasn't a freespace block, the read will |
---|
1893 | | - * return a NULL fbp. Allocate and initialize a new one. |
---|
1894 | | - */ |
---|
1895 | | - if (!fbp) { |
---|
1896 | | - error = xfs_dir2_grow_inode(args, XFS_DIR2_FREE_SPACE, |
---|
1897 | | - &fbno); |
---|
1898 | | - if (error) |
---|
1899 | | - return error; |
---|
1900 | | - |
---|
1901 | | - if (dp->d_ops->db_to_fdb(args->geo, dbno) != fbno) { |
---|
1902 | | - xfs_alert(mp, |
---|
1903 | | -"%s: dir ino %llu needed freesp block %lld for data block %lld, got %lld ifbno %llu lastfbno %d", |
---|
1904 | | - __func__, (unsigned long long)dp->i_ino, |
---|
1905 | | - (long long)dp->d_ops->db_to_fdb( |
---|
1906 | | - args->geo, dbno), |
---|
1907 | | - (long long)dbno, (long long)fbno, |
---|
1908 | | - (unsigned long long)ifbno, lastfbno); |
---|
1909 | | - if (fblk) { |
---|
1910 | | - xfs_alert(mp, |
---|
1911 | | - " fblk "PTR_FMT" blkno %llu index %d magic 0x%x", |
---|
1912 | | - fblk, |
---|
1913 | | - (unsigned long long)fblk->blkno, |
---|
1914 | | - fblk->index, |
---|
1915 | | - fblk->magic); |
---|
1916 | | - } else { |
---|
1917 | | - xfs_alert(mp, " ... fblk is NULL"); |
---|
1918 | | - } |
---|
1919 | | - XFS_ERROR_REPORT("xfs_dir2_node_addname_int", |
---|
1920 | | - XFS_ERRLEVEL_LOW, mp); |
---|
1921 | | - return -EFSCORRUPTED; |
---|
1922 | | - } |
---|
1923 | | - |
---|
1924 | | - /* |
---|
1925 | | - * Get a buffer for the new block. |
---|
1926 | | - */ |
---|
1927 | | - error = xfs_dir3_free_get_buf(args, fbno, &fbp); |
---|
1928 | | - if (error) |
---|
1929 | | - return error; |
---|
1930 | | - free = fbp->b_addr; |
---|
1931 | | - bests = dp->d_ops->free_bests_p(free); |
---|
1932 | | - dp->d_ops->free_hdr_from_disk(&freehdr, free); |
---|
1933 | | - |
---|
1934 | | - /* |
---|
1935 | | - * Remember the first slot as our empty slot. |
---|
1936 | | - */ |
---|
1937 | | - freehdr.firstdb = |
---|
1938 | | - (fbno - xfs_dir2_byte_to_db(args->geo, |
---|
1939 | | - XFS_DIR2_FREE_OFFSET)) * |
---|
1940 | | - dp->d_ops->free_max_bests(args->geo); |
---|
1941 | | - } else { |
---|
1942 | | - free = fbp->b_addr; |
---|
1943 | | - bests = dp->d_ops->free_bests_p(free); |
---|
1944 | | - dp->d_ops->free_hdr_from_disk(&freehdr, free); |
---|
1945 | | - } |
---|
1946 | | - |
---|
1947 | | - /* |
---|
1948 | | - * Set the freespace block index from the data block number. |
---|
1949 | | - */ |
---|
1950 | | - findex = dp->d_ops->db_to_fdindex(args->geo, dbno); |
---|
1951 | | - /* |
---|
1952 | | - * If it's after the end of the current entries in the |
---|
1953 | | - * freespace block, extend that table. |
---|
1954 | | - */ |
---|
1955 | | - if (findex >= freehdr.nvalid) { |
---|
1956 | | - ASSERT(findex < dp->d_ops->free_max_bests(args->geo)); |
---|
1957 | | - freehdr.nvalid = findex + 1; |
---|
1958 | | - /* |
---|
1959 | | - * Tag new entry so nused will go up. |
---|
1960 | | - */ |
---|
1961 | | - bests[findex] = cpu_to_be16(NULLDATAOFF); |
---|
1962 | | - } |
---|
1963 | | - /* |
---|
1964 | | - * If this entry was for an empty data block |
---|
1965 | | - * (this should always be true) then update the header. |
---|
1966 | | - */ |
---|
1967 | | - if (bests[findex] == cpu_to_be16(NULLDATAOFF)) { |
---|
1968 | | - freehdr.nused++; |
---|
1969 | | - dp->d_ops->free_hdr_to_disk(fbp->b_addr, &freehdr); |
---|
1970 | | - xfs_dir2_free_log_header(args, fbp); |
---|
1971 | | - } |
---|
1972 | | - /* |
---|
1973 | | - * Update the real value in the table. |
---|
1974 | | - * We haven't allocated the data entry yet so this will |
---|
1975 | | - * change again. |
---|
1976 | | - */ |
---|
1977 | | - hdr = dbp->b_addr; |
---|
1978 | | - bf = dp->d_ops->data_bestfree_p(hdr); |
---|
1979 | | - bests[findex] = bf[0].length; |
---|
1980 | | - logfree = 1; |
---|
1981 | | - } |
---|
1982 | | - /* |
---|
1983 | | - * We had a data block so we don't have to make a new one. |
---|
1984 | | - */ |
---|
1985 | | - else { |
---|
1986 | | - /* |
---|
1987 | | - * If just checking, we succeeded. |
---|
1988 | | - */ |
---|
1989 | | - if (args->op_flags & XFS_DA_OP_JUSTCHECK) |
---|
1990 | | - return 0; |
---|
1991 | | - |
---|
1992 | | - /* |
---|
1993 | | - * Read the data block in. |
---|
1994 | | - */ |
---|
1995 | | - error = xfs_dir3_data_read(tp, dp, |
---|
1996 | | - xfs_dir2_db_to_da(args->geo, dbno), |
---|
1997 | | - -1, &dbp); |
---|
1998 | | - if (error) |
---|
1999 | | - return error; |
---|
2000 | | - hdr = dbp->b_addr; |
---|
2001 | | - bf = dp->d_ops->data_bestfree_p(hdr); |
---|
2002 | | - logfree = 0; |
---|
2003 | | - } |
---|
2004 | | - ASSERT(be16_to_cpu(bf[0].length) >= length); |
---|
2005 | | - /* |
---|
2006 | | - * Point to the existing unused space. |
---|
2007 | | - */ |
---|
2008 | | - dup = (xfs_dir2_data_unused_t *) |
---|
2009 | | - ((char *)hdr + be16_to_cpu(bf[0].offset)); |
---|
2010 | | - needscan = needlog = 0; |
---|
2011 | | - /* |
---|
2012 | | - * Mark the first part of the unused space, inuse for us. |
---|
2013 | | - */ |
---|
2014 | | - aoff = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr); |
---|
2015 | | - error = xfs_dir2_data_use_free(args, dbp, dup, aoff, length, |
---|
2016 | | - &needlog, &needscan); |
---|
2017 | | - if (error) { |
---|
2018 | | - xfs_trans_brelse(tp, dbp); |
---|
2019 | | - return error; |
---|
2020 | | - } |
---|
2021 | | - /* |
---|
2022 | | - * Fill in the new entry and log it. |
---|
2023 | | - */ |
---|
2024 | | - dep = (xfs_dir2_data_entry_t *)dup; |
---|
2025 | | - dep->inumber = cpu_to_be64(args->inumber); |
---|
2026 | | - dep->namelen = args->namelen; |
---|
2027 | | - memcpy(dep->name, args->name, dep->namelen); |
---|
2028 | | - dp->d_ops->data_put_ftype(dep, args->filetype); |
---|
2029 | | - tagp = dp->d_ops->data_entry_tag_p(dep); |
---|
2030 | | - *tagp = cpu_to_be16((char *)dep - (char *)hdr); |
---|
2031 | | - xfs_dir2_data_log_entry(args, dbp, dep); |
---|
2032 | | - /* |
---|
2033 | | - * Rescan the block for bestfree if needed. |
---|
2034 | | - */ |
---|
2035 | | - if (needscan) |
---|
2036 | | - xfs_dir2_data_freescan(dp, hdr, &needlog); |
---|
2037 | | - /* |
---|
2038 | | - * Log the data block header if needed. |
---|
2039 | | - */ |
---|
2040 | | - if (needlog) |
---|
2041 | | - xfs_dir2_data_log_header(args, dbp); |
---|
2042 | | - /* |
---|
2043 | | - * If the freespace entry is now wrong, update it. |
---|
2044 | | - */ |
---|
2045 | | - bests = dp->d_ops->free_bests_p(free); /* gcc is so stupid */ |
---|
2046 | | - if (be16_to_cpu(bests[findex]) != be16_to_cpu(bf[0].length)) { |
---|
2047 | | - bests[findex] = bf[0].length; |
---|
2048 | | - logfree = 1; |
---|
2049 | | - } |
---|
2050 | | - /* |
---|
2051 | | - * Log the freespace entry if needed. |
---|
2052 | | - */ |
---|
2053 | | - if (logfree) |
---|
2054 | | - xfs_dir2_free_log_bests(args, fbp, findex, findex); |
---|
2055 | | - /* |
---|
2056 | | - * Return the data block and offset in args, then drop the data block. |
---|
2057 | | - */ |
---|
2058 | | - args->blkno = (xfs_dablk_t)dbno; |
---|
2059 | | - args->index = be16_to_cpu(*tagp); |
---|
2060 | | - return 0; |
---|
2061 | | -} |
---|
2062 | | - |
---|
2063 | | -/* |
---|
2064 | 2069 | * Lookup an entry in a node-format directory. |
---|
2065 | 2070 | * All the real work happens in xfs_da3_node_lookup_int. |
---|
2066 | 2071 | * The only real output is the inode number of the entry. |
---|
.. | .. |
---|
2079 | 2084 | /* |
---|
2080 | 2085 | * Allocate and initialize the btree cursor. |
---|
2081 | 2086 | */ |
---|
2082 | | - state = xfs_da_state_alloc(); |
---|
2083 | | - state->args = args; |
---|
2084 | | - state->mp = args->dp->i_mount; |
---|
| 2087 | + state = xfs_da_state_alloc(args); |
---|
| 2088 | + |
---|
2085 | 2089 | /* |
---|
2086 | 2090 | * Fill in the path to the entry in the cursor. |
---|
2087 | 2091 | */ |
---|
.. | .. |
---|
2132 | 2136 | /* |
---|
2133 | 2137 | * Allocate and initialize the btree cursor. |
---|
2134 | 2138 | */ |
---|
2135 | | - state = xfs_da_state_alloc(); |
---|
2136 | | - state->args = args; |
---|
2137 | | - state->mp = args->dp->i_mount; |
---|
| 2139 | + state = xfs_da_state_alloc(args); |
---|
2138 | 2140 | |
---|
2139 | 2141 | /* Look up the entry we're deleting, set up the cursor. */ |
---|
2140 | 2142 | error = xfs_da3_node_lookup_int(state, &rval); |
---|
.. | .. |
---|
2191 | 2193 | int i; /* btree level */ |
---|
2192 | 2194 | xfs_ino_t inum; /* new inode number */ |
---|
2193 | 2195 | int ftype; /* new file type */ |
---|
2194 | | - xfs_dir2_leaf_t *leaf; /* leaf structure */ |
---|
2195 | | - xfs_dir2_leaf_entry_t *lep; /* leaf entry being changed */ |
---|
2196 | 2196 | int rval; /* internal return value */ |
---|
2197 | 2197 | xfs_da_state_t *state; /* btree cursor */ |
---|
2198 | 2198 | |
---|
.. | .. |
---|
2201 | 2201 | /* |
---|
2202 | 2202 | * Allocate and initialize the btree cursor. |
---|
2203 | 2203 | */ |
---|
2204 | | - state = xfs_da_state_alloc(); |
---|
2205 | | - state->args = args; |
---|
2206 | | - state->mp = args->dp->i_mount; |
---|
| 2204 | + state = xfs_da_state_alloc(args); |
---|
2207 | 2205 | |
---|
2208 | 2206 | /* |
---|
2209 | 2207 | * We have to save new inode number and ftype since |
---|
.. | .. |
---|
2224 | 2222 | * and locked it. But paranoia is good. |
---|
2225 | 2223 | */ |
---|
2226 | 2224 | if (rval == -EEXIST) { |
---|
2227 | | - struct xfs_dir2_leaf_entry *ents; |
---|
| 2225 | + struct xfs_dir3_icleaf_hdr leafhdr; |
---|
| 2226 | + |
---|
2228 | 2227 | /* |
---|
2229 | 2228 | * Find the leaf entry. |
---|
2230 | 2229 | */ |
---|
2231 | 2230 | blk = &state->path.blk[state->path.active - 1]; |
---|
2232 | 2231 | ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC); |
---|
2233 | | - leaf = blk->bp->b_addr; |
---|
2234 | | - ents = args->dp->d_ops->leaf_ents_p(leaf); |
---|
2235 | | - lep = &ents[blk->index]; |
---|
2236 | 2232 | ASSERT(state->extravalid); |
---|
| 2233 | + |
---|
| 2234 | + xfs_dir2_leaf_hdr_from_disk(state->mp, &leafhdr, |
---|
| 2235 | + blk->bp->b_addr); |
---|
2237 | 2236 | /* |
---|
2238 | 2237 | * Point to the data entry. |
---|
2239 | 2238 | */ |
---|
.. | .. |
---|
2243 | 2242 | dep = (xfs_dir2_data_entry_t *) |
---|
2244 | 2243 | ((char *)hdr + |
---|
2245 | 2244 | xfs_dir2_dataptr_to_off(args->geo, |
---|
2246 | | - be32_to_cpu(lep->address))); |
---|
| 2245 | + be32_to_cpu(leafhdr.ents[blk->index].address))); |
---|
2247 | 2246 | ASSERT(inum != be64_to_cpu(dep->inumber)); |
---|
2248 | 2247 | /* |
---|
2249 | 2248 | * Fill in the new inode number and log the entry. |
---|
2250 | 2249 | */ |
---|
2251 | 2250 | dep->inumber = cpu_to_be64(inum); |
---|
2252 | | - args->dp->d_ops->data_put_ftype(dep, ftype); |
---|
| 2251 | + xfs_dir2_data_put_ftype(state->mp, dep, ftype); |
---|
2253 | 2252 | xfs_dir2_data_log_entry(args, state->extrablk.bp, dep); |
---|
2254 | 2253 | rval = 0; |
---|
2255 | 2254 | } |
---|
.. | .. |
---|
2306 | 2305 | if (!bp) |
---|
2307 | 2306 | return 0; |
---|
2308 | 2307 | free = bp->b_addr; |
---|
2309 | | - dp->d_ops->free_hdr_from_disk(&freehdr, free); |
---|
| 2308 | + xfs_dir2_free_hdr_from_disk(dp->i_mount, &freehdr, free); |
---|
2310 | 2309 | |
---|
2311 | 2310 | /* |
---|
2312 | 2311 | * If there are used entries, there's nothing to do. |
---|