| .. | .. |
|---|
| 3 | 3 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. |
|---|
| 4 | 4 | * All Rights Reserved. |
|---|
| 5 | 5 | */ |
|---|
| 6 | | -#include <linux/log2.h> |
|---|
| 7 | 6 | |
|---|
| 8 | 7 | #include "xfs.h" |
|---|
| 9 | 8 | #include "xfs_fs.h" |
|---|
| 9 | +#include "xfs_shared.h" |
|---|
| 10 | 10 | #include "xfs_format.h" |
|---|
| 11 | 11 | #include "xfs_log_format.h" |
|---|
| 12 | 12 | #include "xfs_trans_resv.h" |
|---|
| .. | .. |
|---|
| 19 | 19 | #include "xfs_bmap.h" |
|---|
| 20 | 20 | #include "xfs_error.h" |
|---|
| 21 | 21 | #include "xfs_trace.h" |
|---|
| 22 | | -#include "xfs_attr_sf.h" |
|---|
| 23 | 22 | #include "xfs_da_format.h" |
|---|
| 24 | 23 | #include "xfs_da_btree.h" |
|---|
| 25 | 24 | #include "xfs_dir2_priv.h" |
|---|
| 26 | 25 | #include "xfs_attr_leaf.h" |
|---|
| 27 | | -#include "xfs_shared.h" |
|---|
| 28 | 26 | |
|---|
| 29 | 27 | kmem_zone_t *xfs_ifork_zone; |
|---|
| 30 | | - |
|---|
| 31 | | -STATIC int xfs_iformat_local(xfs_inode_t *, xfs_dinode_t *, int, int); |
|---|
| 32 | | -STATIC int xfs_iformat_extents(xfs_inode_t *, xfs_dinode_t *, int); |
|---|
| 33 | | -STATIC int xfs_iformat_btree(xfs_inode_t *, xfs_dinode_t *, int); |
|---|
| 34 | | - |
|---|
| 35 | | -/* |
|---|
| 36 | | - * Copy inode type and data and attr format specific information from the |
|---|
| 37 | | - * on-disk inode to the in-core inode and fork structures. For fifos, devices, |
|---|
| 38 | | - * and sockets this means set i_rdev to the proper value. For files, |
|---|
| 39 | | - * directories, and symlinks this means to bring in the in-line data or extent |
|---|
| 40 | | - * pointers as well as the attribute fork. For a fork in B-tree format, only |
|---|
| 41 | | - * the root is immediately brought in-core. The rest will be read in later when |
|---|
| 42 | | - * first referenced (see xfs_iread_extents()). |
|---|
| 43 | | - */ |
|---|
| 44 | | -int |
|---|
| 45 | | -xfs_iformat_fork( |
|---|
| 46 | | - struct xfs_inode *ip, |
|---|
| 47 | | - struct xfs_dinode *dip) |
|---|
| 48 | | -{ |
|---|
| 49 | | - struct inode *inode = VFS_I(ip); |
|---|
| 50 | | - struct xfs_attr_shortform *atp; |
|---|
| 51 | | - int size; |
|---|
| 52 | | - int error = 0; |
|---|
| 53 | | - xfs_fsize_t di_size; |
|---|
| 54 | | - |
|---|
| 55 | | - switch (inode->i_mode & S_IFMT) { |
|---|
| 56 | | - case S_IFIFO: |
|---|
| 57 | | - case S_IFCHR: |
|---|
| 58 | | - case S_IFBLK: |
|---|
| 59 | | - case S_IFSOCK: |
|---|
| 60 | | - ip->i_d.di_size = 0; |
|---|
| 61 | | - inode->i_rdev = xfs_to_linux_dev_t(xfs_dinode_get_rdev(dip)); |
|---|
| 62 | | - break; |
|---|
| 63 | | - |
|---|
| 64 | | - case S_IFREG: |
|---|
| 65 | | - case S_IFLNK: |
|---|
| 66 | | - case S_IFDIR: |
|---|
| 67 | | - switch (dip->di_format) { |
|---|
| 68 | | - case XFS_DINODE_FMT_LOCAL: |
|---|
| 69 | | - di_size = be64_to_cpu(dip->di_size); |
|---|
| 70 | | - size = (int)di_size; |
|---|
| 71 | | - error = xfs_iformat_local(ip, dip, XFS_DATA_FORK, size); |
|---|
| 72 | | - break; |
|---|
| 73 | | - case XFS_DINODE_FMT_EXTENTS: |
|---|
| 74 | | - error = xfs_iformat_extents(ip, dip, XFS_DATA_FORK); |
|---|
| 75 | | - break; |
|---|
| 76 | | - case XFS_DINODE_FMT_BTREE: |
|---|
| 77 | | - error = xfs_iformat_btree(ip, dip, XFS_DATA_FORK); |
|---|
| 78 | | - break; |
|---|
| 79 | | - default: |
|---|
| 80 | | - return -EFSCORRUPTED; |
|---|
| 81 | | - } |
|---|
| 82 | | - break; |
|---|
| 83 | | - |
|---|
| 84 | | - default: |
|---|
| 85 | | - return -EFSCORRUPTED; |
|---|
| 86 | | - } |
|---|
| 87 | | - if (error) |
|---|
| 88 | | - return error; |
|---|
| 89 | | - |
|---|
| 90 | | - if (xfs_is_reflink_inode(ip)) { |
|---|
| 91 | | - ASSERT(ip->i_cowfp == NULL); |
|---|
| 92 | | - xfs_ifork_init_cow(ip); |
|---|
| 93 | | - } |
|---|
| 94 | | - |
|---|
| 95 | | - if (!XFS_DFORK_Q(dip)) |
|---|
| 96 | | - return 0; |
|---|
| 97 | | - |
|---|
| 98 | | - ASSERT(ip->i_afp == NULL); |
|---|
| 99 | | - ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP | KM_NOFS); |
|---|
| 100 | | - |
|---|
| 101 | | - switch (dip->di_aformat) { |
|---|
| 102 | | - case XFS_DINODE_FMT_LOCAL: |
|---|
| 103 | | - atp = (xfs_attr_shortform_t *)XFS_DFORK_APTR(dip); |
|---|
| 104 | | - size = be16_to_cpu(atp->hdr.totsize); |
|---|
| 105 | | - |
|---|
| 106 | | - error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK, size); |
|---|
| 107 | | - break; |
|---|
| 108 | | - case XFS_DINODE_FMT_EXTENTS: |
|---|
| 109 | | - error = xfs_iformat_extents(ip, dip, XFS_ATTR_FORK); |
|---|
| 110 | | - break; |
|---|
| 111 | | - case XFS_DINODE_FMT_BTREE: |
|---|
| 112 | | - error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK); |
|---|
| 113 | | - break; |
|---|
| 114 | | - default: |
|---|
| 115 | | - error = -EFSCORRUPTED; |
|---|
| 116 | | - break; |
|---|
| 117 | | - } |
|---|
| 118 | | - if (error) { |
|---|
| 119 | | - kmem_zone_free(xfs_ifork_zone, ip->i_afp); |
|---|
| 120 | | - ip->i_afp = NULL; |
|---|
| 121 | | - if (ip->i_cowfp) |
|---|
| 122 | | - kmem_zone_free(xfs_ifork_zone, ip->i_cowfp); |
|---|
| 123 | | - ip->i_cowfp = NULL; |
|---|
| 124 | | - xfs_idestroy_fork(ip, XFS_DATA_FORK); |
|---|
| 125 | | - } |
|---|
| 126 | | - return error; |
|---|
| 127 | | -} |
|---|
| 128 | 28 | |
|---|
| 129 | 29 | void |
|---|
| 130 | 30 | xfs_init_local_fork( |
|---|
| 131 | 31 | struct xfs_inode *ip, |
|---|
| 132 | 32 | int whichfork, |
|---|
| 133 | 33 | const void *data, |
|---|
| 134 | | - int size) |
|---|
| 34 | + int64_t size) |
|---|
| 135 | 35 | { |
|---|
| 136 | 36 | struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); |
|---|
| 137 | 37 | int mem_size = size, real_size = 0; |
|---|
| .. | .. |
|---|
| 149 | 49 | |
|---|
| 150 | 50 | if (size) { |
|---|
| 151 | 51 | real_size = roundup(mem_size, 4); |
|---|
| 152 | | - ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP | KM_NOFS); |
|---|
| 52 | + ifp->if_u1.if_data = kmem_alloc(real_size, KM_NOFS); |
|---|
| 153 | 53 | memcpy(ifp->if_u1.if_data, data, size); |
|---|
| 154 | 54 | if (zero_terminate) |
|---|
| 155 | 55 | ifp->if_u1.if_data[size] = '\0'; |
|---|
| .. | .. |
|---|
| 179 | 79 | */ |
|---|
| 180 | 80 | if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) { |
|---|
| 181 | 81 | xfs_warn(ip->i_mount, |
|---|
| 182 | | - "corrupt inode %Lu (bad size %d for local fork, size = %d).", |
|---|
| 82 | + "corrupt inode %Lu (bad size %d for local fork, size = %zd).", |
|---|
| 183 | 83 | (unsigned long long) ip->i_ino, size, |
|---|
| 184 | 84 | XFS_DFORK_SIZE(dip, ip->i_mount, whichfork)); |
|---|
| 185 | 85 | xfs_inode_verifier_error(ip, -EFSCORRUPTED, |
|---|
| .. | .. |
|---|
| 288 | 188 | * or the number of extents is greater than the number of |
|---|
| 289 | 189 | * blocks. |
|---|
| 290 | 190 | */ |
|---|
| 291 | | - if (unlikely(XFS_IFORK_NEXTENTS(ip, whichfork) <= |
|---|
| 292 | | - XFS_IFORK_MAXEXT(ip, whichfork) || |
|---|
| 191 | + if (unlikely(ifp->if_nextents <= XFS_IFORK_MAXEXT(ip, whichfork) || |
|---|
| 293 | 192 | nrecs == 0 || |
|---|
| 294 | 193 | XFS_BMDR_SPACE_CALC(nrecs) > |
|---|
| 295 | 194 | XFS_DFORK_SIZE(dip, mp, whichfork) || |
|---|
| 296 | | - XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks) || |
|---|
| 195 | + ifp->if_nextents > ip->i_d.di_nblocks) || |
|---|
| 297 | 196 | level == 0 || level > XFS_BTREE_MAXLEVELS) { |
|---|
| 298 | 197 | xfs_warn(mp, "corrupt inode %Lu (btree).", |
|---|
| 299 | 198 | (unsigned long long) ip->i_ino); |
|---|
| .. | .. |
|---|
| 304 | 203 | } |
|---|
| 305 | 204 | |
|---|
| 306 | 205 | ifp->if_broot_bytes = size; |
|---|
| 307 | | - ifp->if_broot = kmem_alloc(size, KM_SLEEP | KM_NOFS); |
|---|
| 206 | + ifp->if_broot = kmem_alloc(size, KM_NOFS); |
|---|
| 308 | 207 | ASSERT(ifp->if_broot != NULL); |
|---|
| 309 | 208 | /* |
|---|
| 310 | 209 | * Copy and convert from the on-disk structure |
|---|
| .. | .. |
|---|
| 319 | 218 | ifp->if_u1.if_root = NULL; |
|---|
| 320 | 219 | ifp->if_height = 0; |
|---|
| 321 | 220 | return 0; |
|---|
| 221 | +} |
|---|
| 222 | + |
|---|
| 223 | +int |
|---|
| 224 | +xfs_iformat_data_fork( |
|---|
| 225 | + struct xfs_inode *ip, |
|---|
| 226 | + struct xfs_dinode *dip) |
|---|
| 227 | +{ |
|---|
| 228 | + struct inode *inode = VFS_I(ip); |
|---|
| 229 | + int error; |
|---|
| 230 | + |
|---|
| 231 | + /* |
|---|
| 232 | + * Initialize the extent count early, as the per-format routines may |
|---|
| 233 | + * depend on it. |
|---|
| 234 | + */ |
|---|
| 235 | + ip->i_df.if_format = dip->di_format; |
|---|
| 236 | + ip->i_df.if_nextents = be32_to_cpu(dip->di_nextents); |
|---|
| 237 | + |
|---|
| 238 | + switch (inode->i_mode & S_IFMT) { |
|---|
| 239 | + case S_IFIFO: |
|---|
| 240 | + case S_IFCHR: |
|---|
| 241 | + case S_IFBLK: |
|---|
| 242 | + case S_IFSOCK: |
|---|
| 243 | + ip->i_d.di_size = 0; |
|---|
| 244 | + inode->i_rdev = xfs_to_linux_dev_t(xfs_dinode_get_rdev(dip)); |
|---|
| 245 | + return 0; |
|---|
| 246 | + case S_IFREG: |
|---|
| 247 | + case S_IFLNK: |
|---|
| 248 | + case S_IFDIR: |
|---|
| 249 | + switch (ip->i_df.if_format) { |
|---|
| 250 | + case XFS_DINODE_FMT_LOCAL: |
|---|
| 251 | + error = xfs_iformat_local(ip, dip, XFS_DATA_FORK, |
|---|
| 252 | + be64_to_cpu(dip->di_size)); |
|---|
| 253 | + if (!error) |
|---|
| 254 | + error = xfs_ifork_verify_local_data(ip); |
|---|
| 255 | + return error; |
|---|
| 256 | + case XFS_DINODE_FMT_EXTENTS: |
|---|
| 257 | + return xfs_iformat_extents(ip, dip, XFS_DATA_FORK); |
|---|
| 258 | + case XFS_DINODE_FMT_BTREE: |
|---|
| 259 | + return xfs_iformat_btree(ip, dip, XFS_DATA_FORK); |
|---|
| 260 | + default: |
|---|
| 261 | + xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, |
|---|
| 262 | + dip, sizeof(*dip), __this_address); |
|---|
| 263 | + return -EFSCORRUPTED; |
|---|
| 264 | + } |
|---|
| 265 | + break; |
|---|
| 266 | + default: |
|---|
| 267 | + xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip, |
|---|
| 268 | + sizeof(*dip), __this_address); |
|---|
| 269 | + return -EFSCORRUPTED; |
|---|
| 270 | + } |
|---|
| 271 | +} |
|---|
| 272 | + |
|---|
| 273 | +static uint16_t |
|---|
| 274 | +xfs_dfork_attr_shortform_size( |
|---|
| 275 | + struct xfs_dinode *dip) |
|---|
| 276 | +{ |
|---|
| 277 | + struct xfs_attr_shortform *atp = |
|---|
| 278 | + (struct xfs_attr_shortform *)XFS_DFORK_APTR(dip); |
|---|
| 279 | + |
|---|
| 280 | + return be16_to_cpu(atp->hdr.totsize); |
|---|
| 281 | +} |
|---|
| 282 | + |
|---|
| 283 | +int |
|---|
| 284 | +xfs_iformat_attr_fork( |
|---|
| 285 | + struct xfs_inode *ip, |
|---|
| 286 | + struct xfs_dinode *dip) |
|---|
| 287 | +{ |
|---|
| 288 | + int error = 0; |
|---|
| 289 | + |
|---|
| 290 | + /* |
|---|
| 291 | + * Initialize the extent count early, as the per-format routines may |
|---|
| 292 | + * depend on it. |
|---|
| 293 | + */ |
|---|
| 294 | + ip->i_afp = kmem_cache_zalloc(xfs_ifork_zone, GFP_NOFS | __GFP_NOFAIL); |
|---|
| 295 | + ip->i_afp->if_format = dip->di_aformat; |
|---|
| 296 | + if (unlikely(ip->i_afp->if_format == 0)) /* pre IRIX 6.2 file system */ |
|---|
| 297 | + ip->i_afp->if_format = XFS_DINODE_FMT_EXTENTS; |
|---|
| 298 | + ip->i_afp->if_nextents = be16_to_cpu(dip->di_anextents); |
|---|
| 299 | + |
|---|
| 300 | + switch (ip->i_afp->if_format) { |
|---|
| 301 | + case XFS_DINODE_FMT_LOCAL: |
|---|
| 302 | + error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK, |
|---|
| 303 | + xfs_dfork_attr_shortform_size(dip)); |
|---|
| 304 | + if (!error) |
|---|
| 305 | + error = xfs_ifork_verify_local_attr(ip); |
|---|
| 306 | + break; |
|---|
| 307 | + case XFS_DINODE_FMT_EXTENTS: |
|---|
| 308 | + error = xfs_iformat_extents(ip, dip, XFS_ATTR_FORK); |
|---|
| 309 | + break; |
|---|
| 310 | + case XFS_DINODE_FMT_BTREE: |
|---|
| 311 | + error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK); |
|---|
| 312 | + break; |
|---|
| 313 | + default: |
|---|
| 314 | + xfs_inode_verifier_error(ip, error, __func__, dip, |
|---|
| 315 | + sizeof(*dip), __this_address); |
|---|
| 316 | + error = -EFSCORRUPTED; |
|---|
| 317 | + break; |
|---|
| 318 | + } |
|---|
| 319 | + |
|---|
| 320 | + if (error) { |
|---|
| 321 | + kmem_cache_free(xfs_ifork_zone, ip->i_afp); |
|---|
| 322 | + ip->i_afp = NULL; |
|---|
| 323 | + } |
|---|
| 324 | + return error; |
|---|
| 322 | 325 | } |
|---|
| 323 | 326 | |
|---|
| 324 | 327 | /* |
|---|
| .. | .. |
|---|
| 369 | 372 | */ |
|---|
| 370 | 373 | if (ifp->if_broot_bytes == 0) { |
|---|
| 371 | 374 | new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, rec_diff); |
|---|
| 372 | | - ifp->if_broot = kmem_alloc(new_size, KM_SLEEP | KM_NOFS); |
|---|
| 375 | + ifp->if_broot = kmem_alloc(new_size, KM_NOFS); |
|---|
| 373 | 376 | ifp->if_broot_bytes = (int)new_size; |
|---|
| 374 | 377 | return; |
|---|
| 375 | 378 | } |
|---|
| .. | .. |
|---|
| 383 | 386 | cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0); |
|---|
| 384 | 387 | new_max = cur_max + rec_diff; |
|---|
| 385 | 388 | new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max); |
|---|
| 386 | | - ifp->if_broot = kmem_realloc(ifp->if_broot, new_size, |
|---|
| 387 | | - KM_SLEEP | KM_NOFS); |
|---|
| 389 | + ifp->if_broot = krealloc(ifp->if_broot, new_size, |
|---|
| 390 | + GFP_NOFS | __GFP_NOFAIL); |
|---|
| 388 | 391 | op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, |
|---|
| 389 | 392 | ifp->if_broot_bytes); |
|---|
| 390 | 393 | np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, |
|---|
| .. | .. |
|---|
| 410 | 413 | else |
|---|
| 411 | 414 | new_size = 0; |
|---|
| 412 | 415 | if (new_size > 0) { |
|---|
| 413 | | - new_broot = kmem_alloc(new_size, KM_SLEEP | KM_NOFS); |
|---|
| 416 | + new_broot = kmem_alloc(new_size, KM_NOFS); |
|---|
| 414 | 417 | /* |
|---|
| 415 | 418 | * First copy over the btree block header. |
|---|
| 416 | 419 | */ |
|---|
| .. | .. |
|---|
| 469 | 472 | void |
|---|
| 470 | 473 | xfs_idata_realloc( |
|---|
| 471 | 474 | struct xfs_inode *ip, |
|---|
| 472 | | - int byte_diff, |
|---|
| 475 | + int64_t byte_diff, |
|---|
| 473 | 476 | int whichfork) |
|---|
| 474 | 477 | { |
|---|
| 475 | 478 | struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); |
|---|
| 476 | | - int new_size = (int)ifp->if_bytes + byte_diff; |
|---|
| 479 | + int64_t new_size = ifp->if_bytes + byte_diff; |
|---|
| 477 | 480 | |
|---|
| 478 | 481 | ASSERT(new_size >= 0); |
|---|
| 479 | 482 | ASSERT(new_size <= XFS_IFORK_SIZE(ip, whichfork)); |
|---|
| .. | .. |
|---|
| 493 | 496 | * in size so that it can be logged and stay on word boundaries. |
|---|
| 494 | 497 | * We enforce that here. |
|---|
| 495 | 498 | */ |
|---|
| 496 | | - ifp->if_u1.if_data = kmem_realloc(ifp->if_u1.if_data, |
|---|
| 497 | | - roundup(new_size, 4), KM_SLEEP | KM_NOFS); |
|---|
| 499 | + ifp->if_u1.if_data = krealloc(ifp->if_u1.if_data, roundup(new_size, 4), |
|---|
| 500 | + GFP_NOFS | __GFP_NOFAIL); |
|---|
| 498 | 501 | ifp->if_bytes = new_size; |
|---|
| 499 | 502 | } |
|---|
| 500 | 503 | |
|---|
| 501 | 504 | void |
|---|
| 502 | 505 | xfs_idestroy_fork( |
|---|
| 503 | | - xfs_inode_t *ip, |
|---|
| 504 | | - int whichfork) |
|---|
| 506 | + struct xfs_ifork *ifp) |
|---|
| 505 | 507 | { |
|---|
| 506 | | - struct xfs_ifork *ifp; |
|---|
| 507 | | - |
|---|
| 508 | | - ifp = XFS_IFORK_PTR(ip, whichfork); |
|---|
| 509 | 508 | if (ifp->if_broot != NULL) { |
|---|
| 510 | 509 | kmem_free(ifp->if_broot); |
|---|
| 511 | 510 | ifp->if_broot = NULL; |
|---|
| 512 | 511 | } |
|---|
| 513 | 512 | |
|---|
| 514 | 513 | /* |
|---|
| 515 | | - * If the format is local, then we can't have an extents |
|---|
| 516 | | - * array so just look for an inline data array. If we're |
|---|
| 517 | | - * not local then we may or may not have an extents list, |
|---|
| 518 | | - * so check and free it up if we do. |
|---|
| 514 | + * If the format is local, then we can't have an extents array so just |
|---|
| 515 | + * look for an inline data array. If we're not local then we may or may |
|---|
| 516 | + * not have an extents list, so check and free it up if we do. |
|---|
| 519 | 517 | */ |
|---|
| 520 | | - if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) { |
|---|
| 521 | | - if (ifp->if_u1.if_data != NULL) { |
|---|
| 522 | | - kmem_free(ifp->if_u1.if_data); |
|---|
| 523 | | - ifp->if_u1.if_data = NULL; |
|---|
| 524 | | - } |
|---|
| 525 | | - } else if ((ifp->if_flags & XFS_IFEXTENTS) && ifp->if_height) { |
|---|
| 526 | | - xfs_iext_destroy(ifp); |
|---|
| 527 | | - } |
|---|
| 528 | | - |
|---|
| 529 | | - if (whichfork == XFS_ATTR_FORK) { |
|---|
| 530 | | - kmem_zone_free(xfs_ifork_zone, ip->i_afp); |
|---|
| 531 | | - ip->i_afp = NULL; |
|---|
| 532 | | - } else if (whichfork == XFS_COW_FORK) { |
|---|
| 533 | | - kmem_zone_free(xfs_ifork_zone, ip->i_cowfp); |
|---|
| 534 | | - ip->i_cowfp = NULL; |
|---|
| 518 | + if (ifp->if_format == XFS_DINODE_FMT_LOCAL) { |
|---|
| 519 | + kmem_free(ifp->if_u1.if_data); |
|---|
| 520 | + ifp->if_u1.if_data = NULL; |
|---|
| 521 | + } else if (ifp->if_flags & XFS_IFEXTENTS) { |
|---|
| 522 | + if (ifp->if_height) |
|---|
| 523 | + xfs_iext_destroy(ifp); |
|---|
| 535 | 524 | } |
|---|
| 536 | 525 | } |
|---|
| 537 | 526 | |
|---|
| .. | .. |
|---|
| 554 | 543 | struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); |
|---|
| 555 | 544 | struct xfs_iext_cursor icur; |
|---|
| 556 | 545 | struct xfs_bmbt_irec rec; |
|---|
| 557 | | - int copied = 0; |
|---|
| 546 | + int64_t copied = 0; |
|---|
| 558 | 547 | |
|---|
| 559 | 548 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL | XFS_ILOCK_SHARED)); |
|---|
| 560 | 549 | ASSERT(ifp->if_bytes > 0); |
|---|
| .. | .. |
|---|
| 588 | 577 | xfs_iflush_fork( |
|---|
| 589 | 578 | xfs_inode_t *ip, |
|---|
| 590 | 579 | xfs_dinode_t *dip, |
|---|
| 591 | | - xfs_inode_log_item_t *iip, |
|---|
| 580 | + struct xfs_inode_log_item *iip, |
|---|
| 592 | 581 | int whichfork) |
|---|
| 593 | 582 | { |
|---|
| 594 | 583 | char *cp; |
|---|
| .. | .. |
|---|
| 614 | 603 | } |
|---|
| 615 | 604 | cp = XFS_DFORK_PTR(dip, whichfork); |
|---|
| 616 | 605 | mp = ip->i_mount; |
|---|
| 617 | | - switch (XFS_IFORK_FORMAT(ip, whichfork)) { |
|---|
| 606 | + switch (ifp->if_format) { |
|---|
| 618 | 607 | case XFS_DINODE_FMT_LOCAL: |
|---|
| 619 | 608 | if ((iip->ili_fields & dataflag[whichfork]) && |
|---|
| 620 | 609 | (ifp->if_bytes > 0)) { |
|---|
| .. | .. |
|---|
| 629 | 618 | !(iip->ili_fields & extflag[whichfork])); |
|---|
| 630 | 619 | if ((iip->ili_fields & extflag[whichfork]) && |
|---|
| 631 | 620 | (ifp->if_bytes > 0)) { |
|---|
| 632 | | - ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) > 0); |
|---|
| 621 | + ASSERT(ifp->if_nextents > 0); |
|---|
| 633 | 622 | (void)xfs_iextents_copy(ip, (xfs_bmbt_rec_t *)cp, |
|---|
| 634 | 623 | whichfork); |
|---|
| 635 | 624 | } |
|---|
| .. | .. |
|---|
| 684 | 673 | if (ip->i_cowfp) |
|---|
| 685 | 674 | return; |
|---|
| 686 | 675 | |
|---|
| 687 | | - ip->i_cowfp = kmem_zone_zalloc(xfs_ifork_zone, |
|---|
| 688 | | - KM_SLEEP | KM_NOFS); |
|---|
| 676 | + ip->i_cowfp = kmem_cache_zalloc(xfs_ifork_zone, |
|---|
| 677 | + GFP_NOFS | __GFP_NOFAIL); |
|---|
| 689 | 678 | ip->i_cowfp->if_flags = XFS_IFEXTENTS; |
|---|
| 690 | | - ip->i_cformat = XFS_DINODE_FMT_EXTENTS; |
|---|
| 691 | | - ip->i_cnextents = 0; |
|---|
| 679 | + ip->i_cowfp->if_format = XFS_DINODE_FMT_EXTENTS; |
|---|
| 692 | 680 | } |
|---|
| 693 | 681 | |
|---|
| 694 | | -/* Default fork content verifiers. */ |
|---|
| 695 | | -struct xfs_ifork_ops xfs_default_ifork_ops = { |
|---|
| 696 | | - .verify_attr = xfs_attr_shortform_verify, |
|---|
| 697 | | - .verify_dir = xfs_dir2_sf_verify, |
|---|
| 698 | | - .verify_symlink = xfs_symlink_shortform_verify, |
|---|
| 699 | | -}; |
|---|
| 700 | | - |
|---|
| 701 | 682 | /* Verify the inline contents of the data fork of an inode. */ |
|---|
| 702 | | -xfs_failaddr_t |
|---|
| 703 | | -xfs_ifork_verify_data( |
|---|
| 704 | | - struct xfs_inode *ip, |
|---|
| 705 | | - struct xfs_ifork_ops *ops) |
|---|
| 683 | +int |
|---|
| 684 | +xfs_ifork_verify_local_data( |
|---|
| 685 | + struct xfs_inode *ip) |
|---|
| 706 | 686 | { |
|---|
| 707 | | - /* Non-local data fork, we're done. */ |
|---|
| 708 | | - if (ip->i_d.di_format != XFS_DINODE_FMT_LOCAL) |
|---|
| 709 | | - return NULL; |
|---|
| 687 | + xfs_failaddr_t fa = NULL; |
|---|
| 710 | 688 | |
|---|
| 711 | | - /* Check the inline data fork if there is one. */ |
|---|
| 712 | 689 | switch (VFS_I(ip)->i_mode & S_IFMT) { |
|---|
| 713 | 690 | case S_IFDIR: |
|---|
| 714 | | - return ops->verify_dir(ip); |
|---|
| 691 | + fa = xfs_dir2_sf_verify(ip); |
|---|
| 692 | + break; |
|---|
| 715 | 693 | case S_IFLNK: |
|---|
| 716 | | - return ops->verify_symlink(ip); |
|---|
| 694 | + fa = xfs_symlink_shortform_verify(ip); |
|---|
| 695 | + break; |
|---|
| 717 | 696 | default: |
|---|
| 718 | | - return NULL; |
|---|
| 697 | + break; |
|---|
| 719 | 698 | } |
|---|
| 699 | + |
|---|
| 700 | + if (fa) { |
|---|
| 701 | + xfs_inode_verifier_error(ip, -EFSCORRUPTED, "data fork", |
|---|
| 702 | + ip->i_df.if_u1.if_data, ip->i_df.if_bytes, fa); |
|---|
| 703 | + return -EFSCORRUPTED; |
|---|
| 704 | + } |
|---|
| 705 | + |
|---|
| 706 | + return 0; |
|---|
| 720 | 707 | } |
|---|
| 721 | 708 | |
|---|
| 722 | 709 | /* Verify the inline contents of the attr fork of an inode. */ |
|---|
| 723 | | -xfs_failaddr_t |
|---|
| 724 | | -xfs_ifork_verify_attr( |
|---|
| 725 | | - struct xfs_inode *ip, |
|---|
| 726 | | - struct xfs_ifork_ops *ops) |
|---|
| 710 | +int |
|---|
| 711 | +xfs_ifork_verify_local_attr( |
|---|
| 712 | + struct xfs_inode *ip) |
|---|
| 727 | 713 | { |
|---|
| 728 | | - /* There has to be an attr fork allocated if aformat is local. */ |
|---|
| 729 | | - if (ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL) |
|---|
| 730 | | - return NULL; |
|---|
| 731 | | - if (!XFS_IFORK_PTR(ip, XFS_ATTR_FORK)) |
|---|
| 732 | | - return __this_address; |
|---|
| 733 | | - return ops->verify_attr(ip); |
|---|
| 714 | + struct xfs_ifork *ifp = ip->i_afp; |
|---|
| 715 | + xfs_failaddr_t fa; |
|---|
| 716 | + |
|---|
| 717 | + if (!ifp) |
|---|
| 718 | + fa = __this_address; |
|---|
| 719 | + else |
|---|
| 720 | + fa = xfs_attr_shortform_verify(ip); |
|---|
| 721 | + |
|---|
| 722 | + if (fa) { |
|---|
| 723 | + xfs_inode_verifier_error(ip, -EFSCORRUPTED, "attr fork", |
|---|
| 724 | + ifp ? ifp->if_u1.if_data : NULL, |
|---|
| 725 | + ifp ? ifp->if_bytes : 0, fa); |
|---|
| 726 | + return -EFSCORRUPTED; |
|---|
| 727 | + } |
|---|
| 728 | + |
|---|
| 729 | + return 0; |
|---|
| 734 | 730 | } |
|---|