| .. | .. |
|---|
| 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. |
|---|