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