]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/xfs_inode_fork.c
xfsprogs: Release v6.7.0
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_inode_fork.c
CommitLineData
37b3b4d6 1// SPDX-License-Identifier: GPL-2.0
5d90ab5a
DC
2/*
3 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
4 * All Rights Reserved.
5d90ab5a 5 */
2cf10e4c 6
9c799827 7#include "libxfs_priv.h"
b626fb59 8#include "xfs_fs.h"
27846843 9#include "xfs_shared.h"
b626fb59
DC
10#include "xfs_format.h"
11#include "xfs_log_format.h"
12#include "xfs_trans_resv.h"
13#include "xfs_mount.h"
14#include "xfs_inode.h"
15#include "xfs_trans.h"
81bf5e85 16#include "xfs_btree.h"
b626fb59
DC
17#include "xfs_bmap_btree.h"
18#include "xfs_bmap.h"
19#include "xfs_trace.h"
9a5fc886 20#include "xfs_da_format.h"
fc1d6454
DW
21#include "xfs_da_btree.h"
22#include "xfs_dir2_priv.h"
20e882d4 23#include "xfs_attr_leaf.h"
d629a2d9 24#include "xfs_types.h"
b88613bd 25#include "xfs_errortag.h"
5d90ab5a 26
2e1394fc 27struct kmem_cache *xfs_ifork_cache;
5d90ab5a 28
219eec76
CH
29void
30xfs_init_local_fork(
31 struct xfs_inode *ip,
32 int whichfork,
33 const void *data,
b6d2b93c 34 int64_t size)
219eec76 35{
722e81c1 36 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
227a3b63 37 int mem_size = size;
4cab415f
CH
38 bool zero_terminate;
39
40 /*
41 * If we are using the local fork to store a symlink body we need to
42 * zero-terminate it so that we can pass it back to the VFS directly.
43 * Overallocate the in-memory fork by one for that and add a zero
44 * to terminate it below.
45 */
46 zero_terminate = S_ISLNK(VFS_I(ip)->i_mode);
47 if (zero_terminate)
48 mem_size++;
219eec76 49
07fe4665 50 if (size) {
227a3b63 51 ifp->if_u1.if_data = kmem_alloc(mem_size, KM_NOFS);
219eec76 52 memcpy(ifp->if_u1.if_data, data, size);
4cab415f
CH
53 if (zero_terminate)
54 ifp->if_u1.if_data[size] = '\0';
07fe4665
CH
55 } else {
56 ifp->if_u1.if_data = NULL;
4cab415f 57 }
219eec76
CH
58
59 ifp->if_bytes = size;
219eec76
CH
60}
61
5d90ab5a
DC
62/*
63 * The file is in-lined in the on-disk inode.
5d90ab5a
DC
64 */
65STATIC int
66xfs_iformat_local(
7328ea6e
CH
67 struct xfs_inode *ip,
68 struct xfs_dinode *dip,
69 int whichfork,
70 int size)
5d90ab5a 71{
5d90ab5a
DC
72 /*
73 * If the size is unreasonable, then something
74 * is wrong and we just bail out rather than crash in
75 * kmem_alloc() or memcpy() below.
76 */
77 if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
78 xfs_warn(ip->i_mount,
be98db85 79 "corrupt inode %llu (bad size %d for local fork, size = %zd).",
5d90ab5a
DC
80 (unsigned long long) ip->i_ino, size,
81 XFS_DFORK_SIZE(dip, ip->i_mount, whichfork));
b02a2c9e
DW
82 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
83 "xfs_iformat_local", dip, sizeof(*dip),
84 __this_address);
12b53197 85 return -EFSCORRUPTED;
5d90ab5a 86 }
219eec76
CH
87
88 xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size);
5d90ab5a
DC
89 return 0;
90}
91
92/*
1f2a4478 93 * The file consists of a set of extents all of which fit into the on-disk
07fe4665 94 * inode.
5d90ab5a
DC
95 */
96STATIC int
97xfs_iformat_extents(
1f2a4478
CH
98 struct xfs_inode *ip,
99 struct xfs_dinode *dip,
100 int whichfork)
5d90ab5a 101{
1f2a4478 102 struct xfs_mount *mp = ip->i_mount;
722e81c1 103 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
322fd804 104 int state = xfs_bmap_fork_to_state(whichfork);
5f70c91b 105 xfs_extnum_t nex = xfs_dfork_nextents(dip, whichfork);
1f2a4478 106 int size = nex * sizeof(xfs_bmbt_rec_t);
9788e059 107 struct xfs_iext_cursor icur;
1f2a4478 108 struct xfs_bmbt_rec *dp;
b37d753d 109 struct xfs_bmbt_irec new;
1f2a4478 110 int i;
5d90ab5a
DC
111
112 /*
1f2a4478
CH
113 * If the number of extents is unreasonable, then something is wrong and
114 * we just bail out rather than crash in kmem_alloc() or memcpy() below.
5d90ab5a 115 */
1f2a4478 116 if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, mp, whichfork))) {
4b85994a
CB
117 xfs_warn(ip->i_mount, "corrupt inode %llu ((a)extents = %llu).",
118 ip->i_ino, nex);
b02a2c9e
DW
119 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
120 "xfs_iformat_extents(1)", dip, sizeof(*dip),
121 __this_address);
12b53197 122 return -EFSCORRUPTED;
5d90ab5a
DC
123 }
124
b37d753d
CH
125 ifp->if_bytes = 0;
126 ifp->if_u1.if_root = NULL;
127 ifp->if_height = 0;
5d90ab5a
DC
128 if (size) {
129 dp = (xfs_bmbt_rec_t *) XFS_DFORK_PTR(dip, whichfork);
9788e059
CH
130
131 xfs_iext_first(ifp, &icur);
5d90ab5a 132 for (i = 0; i < nex; i++, dp++) {
0cf6a3a9
DW
133 xfs_failaddr_t fa;
134
080f0c71 135 xfs_bmbt_disk_get_all(dp, &new);
0cf6a3a9
DW
136 fa = xfs_bmap_validate_extent(ip, whichfork, &new);
137 if (fa) {
138 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
139 "xfs_iformat_extents(2)",
140 dp, sizeof(*dp), fa);
830c99b1
DW
141 return xfs_bmap_complain_bad_rec(ip, whichfork,
142 fa, &new);
1f2a4478 143 }
9788e059 144
26a75f67 145 xfs_iext_insert(ip, &icur, &new, state);
9788e059
CH
146 trace_xfs_read_extent(ip, &icur, state, _THIS_IP_);
147 xfs_iext_next(ifp, &icur);
5d90ab5a 148 }
5d90ab5a 149 }
5d90ab5a
DC
150 return 0;
151}
152
153/*
154 * The file has too many extents to fit into
155 * the inode, so they are in B-tree format.
156 * Allocate a buffer for the root of the B-tree
157 * and copy the root into it. The i_extents
158 * field will remain NULL until all of the
159 * extents are read in (when they are needed).
160 */
161STATIC int
162xfs_iformat_btree(
7328ea6e
CH
163 struct xfs_inode *ip,
164 struct xfs_dinode *dip,
5d90ab5a
DC
165 int whichfork)
166{
167 struct xfs_mount *mp = ip->i_mount;
168 xfs_bmdr_block_t *dfp;
e07055b8 169 struct xfs_ifork *ifp;
5d90ab5a
DC
170 /* REFERENCED */
171 int nrecs;
172 int size;
81bf5e85 173 int level;
5d90ab5a 174
722e81c1 175 ifp = xfs_ifork_ptr(ip, whichfork);
5d90ab5a
DC
176 dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork);
177 size = XFS_BMAP_BROOT_SPACE(mp, dfp);
178 nrecs = be16_to_cpu(dfp->bb_numrecs);
81bf5e85 179 level = be16_to_cpu(dfp->bb_level);
5d90ab5a
DC
180
181 /*
182 * blow out if -- fork has less extents than can fit in
183 * fork (fork shouldn't be a btree format), root btree
184 * block has more records than can fit into the fork,
185 * or the number of extents is greater than the number of
186 * blocks.
187 */
87c472b7 188 if (unlikely(ifp->if_nextents <= XFS_IFORK_MAXEXT(ip, whichfork) ||
e4b963e9 189 nrecs == 0 ||
5d90ab5a
DC
190 XFS_BMDR_SPACE_CALC(nrecs) >
191 XFS_DFORK_SIZE(dip, mp, whichfork) ||
aa00f286 192 ifp->if_nextents > ip->i_nblocks) ||
55369096 193 level == 0 || level > XFS_BM_MAXLEVELS(mp, whichfork)) {
be98db85 194 xfs_warn(mp, "corrupt inode %llu (btree).",
5d90ab5a 195 (unsigned long long) ip->i_ino);
b02a2c9e
DW
196 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
197 "xfs_iformat_btree", dfp, size,
198 __this_address);
12b53197 199 return -EFSCORRUPTED;
5d90ab5a
DC
200 }
201
202 ifp->if_broot_bytes = size;
6cd1e6db 203 ifp->if_broot = kmem_alloc(size, KM_NOFS);
5d90ab5a
DC
204 ASSERT(ifp->if_broot != NULL);
205 /*
206 * Copy and convert from the on-disk structure
207 * to the in-memory structure.
208 */
209 xfs_bmdr_to_bmbt(ip, dfp, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork),
210 ifp->if_broot, size);
5d90ab5a 211
b37d753d
CH
212 ifp->if_bytes = 0;
213 ifp->if_u1.if_root = NULL;
214 ifp->if_height = 0;
5d90ab5a
DC
215 return 0;
216}
217
07973a77
CH
218int
219xfs_iformat_data_fork(
220 struct xfs_inode *ip,
221 struct xfs_dinode *dip)
222{
223 struct inode *inode = VFS_I(ip);
0815f7ab 224 int error;
07973a77 225
87c472b7
CH
226 /*
227 * Initialize the extent count early, as the per-format routines may
0bf7f8c3
DW
228 * depend on it. Use release semantics to set needextents /after/ we
229 * set the format. This ensures that we can use acquire semantics on
230 * needextents in xfs_need_iread_extents() and be guaranteed to see a
231 * valid format value after that load.
87c472b7 232 */
d967a68d 233 ip->i_df.if_format = dip->di_format;
5f70c91b 234 ip->i_df.if_nextents = xfs_dfork_data_extents(dip);
0bf7f8c3
DW
235 smp_store_release(&ip->i_df.if_needextents,
236 ip->i_df.if_format == XFS_DINODE_FMT_BTREE ? 1 : 0);
87c472b7 237
07973a77
CH
238 switch (inode->i_mode & S_IFMT) {
239 case S_IFIFO:
240 case S_IFCHR:
241 case S_IFBLK:
242 case S_IFSOCK:
509dcb4b 243 ip->i_disk_size = 0;
07973a77
CH
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:
d967a68d 249 switch (ip->i_df.if_format) {
07973a77 250 case XFS_DINODE_FMT_LOCAL:
0815f7ab 251 error = xfs_iformat_local(ip, dip, XFS_DATA_FORK,
07973a77 252 be64_to_cpu(dip->di_size));
0815f7ab
CH
253 if (!error)
254 error = xfs_ifork_verify_local_data(ip);
255 return error;
07973a77
CH
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
273static uint16_t
274xfs_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
7ff5f1ed
DW
283void
284xfs_ifork_init_attr(
285 struct xfs_inode *ip,
652a2133
DC
286 enum xfs_dinode_fmt format,
287 xfs_extnum_t nextents)
288{
0bf7f8c3
DW
289 /*
290 * Initialize the extent count early, as the per-format routines may
291 * depend on it. Use release semantics to set needextents /after/ we
292 * set the format. This ensures that we can use acquire semantics on
293 * needextents in xfs_need_iread_extents() and be guaranteed to see a
294 * valid format value after that load.
295 */
7ff5f1ed
DW
296 ip->i_af.if_format = format;
297 ip->i_af.if_nextents = nextents;
0bf7f8c3
DW
298 smp_store_release(&ip->i_af.if_needextents,
299 ip->i_af.if_format == XFS_DINODE_FMT_BTREE ? 1 : 0);
7ff5f1ed
DW
300}
301
302void
303xfs_ifork_zap_attr(
304 struct xfs_inode *ip)
305{
e373f06a 306 xfs_idestroy_fork(&ip->i_af);
7ff5f1ed
DW
307 memset(&ip->i_af, 0, sizeof(struct xfs_ifork));
308 ip->i_af.if_format = XFS_DINODE_FMT_EXTENTS;
652a2133
DC
309}
310
07973a77
CH
311int
312xfs_iformat_attr_fork(
313 struct xfs_inode *ip,
314 struct xfs_dinode *dip)
315{
5f70c91b 316 xfs_extnum_t naextents = xfs_dfork_attr_extents(dip);
07973a77
CH
317 int error = 0;
318
87c472b7
CH
319 /*
320 * Initialize the extent count early, as the per-format routines may
321 * depend on it.
322 */
7ff5f1ed 323 xfs_ifork_init_attr(ip, dip->di_aformat, naextents);
87c472b7 324
7ff5f1ed 325 switch (ip->i_af.if_format) {
07973a77
CH
326 case XFS_DINODE_FMT_LOCAL:
327 error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK,
328 xfs_dfork_attr_shortform_size(dip));
0815f7ab
CH
329 if (!error)
330 error = xfs_ifork_verify_local_attr(ip);
07973a77
CH
331 break;
332 case XFS_DINODE_FMT_EXTENTS:
333 error = xfs_iformat_extents(ip, dip, XFS_ATTR_FORK);
334 break;
335 case XFS_DINODE_FMT_BTREE:
336 error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK);
337 break;
338 default:
339 xfs_inode_verifier_error(ip, error, __func__, dip,
340 sizeof(*dip), __this_address);
341 error = -EFSCORRUPTED;
342 break;
343 }
344
7ff5f1ed
DW
345 if (error)
346 xfs_ifork_zap_attr(ip);
07973a77
CH
347 return error;
348}
349
5d90ab5a
DC
350/*
351 * Reallocate the space for if_broot based on the number of records
352 * being added or deleted as indicated in rec_diff. Move the records
353 * and pointers in if_broot to fit the new size. When shrinking this
354 * will eliminate holes between the records and pointers created by
355 * the caller. When growing this will create holes to be filled in
356 * by the caller.
357 *
358 * The caller must not request to add more records than would fit in
359 * the on-disk inode root. If the if_broot is currently NULL, then
e6d77a21 360 * if we are adding records, one will be allocated. The caller must also
5d90ab5a
DC
361 * not request that the number of records go below zero, although
362 * it can go to zero.
363 *
364 * ip -- the inode whose if_broot area is changing
365 * ext_diff -- the change in the number of records, positive or negative,
366 * requested for the if_broot array.
367 */
368void
369xfs_iroot_realloc(
370 xfs_inode_t *ip,
371 int rec_diff,
372 int whichfork)
373{
374 struct xfs_mount *mp = ip->i_mount;
375 int cur_max;
e07055b8 376 struct xfs_ifork *ifp;
5d90ab5a
DC
377 struct xfs_btree_block *new_broot;
378 int new_max;
379 size_t new_size;
380 char *np;
381 char *op;
382
383 /*
384 * Handle the degenerate case quietly.
385 */
386 if (rec_diff == 0) {
387 return;
388 }
389
722e81c1 390 ifp = xfs_ifork_ptr(ip, whichfork);
5d90ab5a
DC
391 if (rec_diff > 0) {
392 /*
393 * If there wasn't any memory allocated before, just
394 * allocate it now and get out.
395 */
396 if (ifp->if_broot_bytes == 0) {
397 new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, rec_diff);
6cd1e6db 398 ifp->if_broot = kmem_alloc(new_size, KM_NOFS);
5d90ab5a
DC
399 ifp->if_broot_bytes = (int)new_size;
400 return;
401 }
402
403 /*
404 * If there is already an existing if_broot, then we need
405 * to realloc() it and shift the pointers to their new
406 * location. The records don't change location because
407 * they are kept butted up against the btree block header.
408 */
409 cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0);
410 new_max = cur_max + rec_diff;
411 new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
8a21dbae
CM
412 ifp->if_broot = krealloc(ifp->if_broot, new_size,
413 GFP_NOFS | __GFP_NOFAIL);
5d90ab5a
DC
414 op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
415 ifp->if_broot_bytes);
416 np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
417 (int)new_size);
418 ifp->if_broot_bytes = (int)new_size;
419 ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
eae3e30d 420 xfs_inode_fork_size(ip, whichfork));
5a35bf2c 421 memmove(np, op, cur_max * (uint)sizeof(xfs_fsblock_t));
5d90ab5a
DC
422 return;
423 }
424
425 /*
426 * rec_diff is less than 0. In this case, we are shrinking the
427 * if_broot buffer. It must already exist. If we go to zero
428 * records, just get rid of the root and clear the status bit.
429 */
430 ASSERT((ifp->if_broot != NULL) && (ifp->if_broot_bytes > 0));
431 cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0);
432 new_max = cur_max + rec_diff;
433 ASSERT(new_max >= 0);
434 if (new_max > 0)
435 new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
436 else
437 new_size = 0;
438 if (new_size > 0) {
6cd1e6db 439 new_broot = kmem_alloc(new_size, KM_NOFS);
5d90ab5a
DC
440 /*
441 * First copy over the btree block header.
442 */
443 memcpy(new_broot, ifp->if_broot,
444 XFS_BMBT_BLOCK_LEN(ip->i_mount));
445 } else {
446 new_broot = NULL;
5d90ab5a
DC
447 }
448
449 /*
450 * Only copy the records and pointers if there are any.
451 */
452 if (new_max > 0) {
453 /*
454 * First copy the records.
455 */
456 op = (char *)XFS_BMBT_REC_ADDR(mp, ifp->if_broot, 1);
457 np = (char *)XFS_BMBT_REC_ADDR(mp, new_broot, 1);
458 memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_rec_t));
459
460 /*
461 * Then copy the pointers.
462 */
463 op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
464 ifp->if_broot_bytes);
465 np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, new_broot, 1,
466 (int)new_size);
5a35bf2c 467 memcpy(np, op, new_max * (uint)sizeof(xfs_fsblock_t));
5d90ab5a
DC
468 }
469 kmem_free(ifp->if_broot);
470 ifp->if_broot = new_broot;
471 ifp->if_broot_bytes = (int)new_size;
472 if (ifp->if_broot)
473 ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
eae3e30d 474 xfs_inode_fork_size(ip, whichfork));
5d90ab5a
DC
475 return;
476}
477
478
479/*
480 * This is called when the amount of space needed for if_data
481 * is increased or decreased. The change in size is indicated by
482 * the number of bytes that need to be added or deleted in the
483 * byte_diff parameter.
484 *
485 * If the amount of space needed has decreased below the size of the
486 * inline buffer, then switch to using the inline buffer. Otherwise,
487 * use kmem_realloc() or kmem_alloc() to adjust the size of the buffer
488 * to what is needed.
489 *
490 * ip -- the inode whose if_data area is changing
491 * byte_diff -- the change in the number of bytes, positive or negative,
492 * requested for the if_data array.
493 */
494void
495xfs_idata_realloc(
2282d1d1 496 struct xfs_inode *ip,
b6d2b93c 497 int64_t byte_diff,
2282d1d1 498 int whichfork)
5d90ab5a 499{
722e81c1 500 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
b6d2b93c 501 int64_t new_size = ifp->if_bytes + byte_diff;
5d90ab5a 502
5d90ab5a 503 ASSERT(new_size >= 0);
eae3e30d 504 ASSERT(new_size <= xfs_inode_fork_size(ip, whichfork));
2282d1d1
CH
505
506 if (byte_diff == 0)
507 return;
5d90ab5a
DC
508
509 if (new_size == 0) {
07fe4665 510 kmem_free(ifp->if_u1.if_data);
5d90ab5a 511 ifp->if_u1.if_data = NULL;
2282d1d1
CH
512 ifp->if_bytes = 0;
513 return;
5d90ab5a 514 }
2282d1d1 515
227a3b63
DC
516 ifp->if_u1.if_data = krealloc(ifp->if_u1.if_data, new_size,
517 GFP_NOFS | __GFP_NOFAIL);
5d90ab5a 518 ifp->if_bytes = new_size;
5d90ab5a
DC
519}
520
521void
522xfs_idestroy_fork(
a87a40a2 523 struct xfs_ifork *ifp)
5d90ab5a 524{
5d90ab5a
DC
525 if (ifp->if_broot != NULL) {
526 kmem_free(ifp->if_broot);
527 ifp->if_broot = NULL;
528 }
529
fca0a273
CH
530 switch (ifp->if_format) {
531 case XFS_DINODE_FMT_LOCAL:
a87a40a2
CH
532 kmem_free(ifp->if_u1.if_data);
533 ifp->if_u1.if_data = NULL;
fca0a273
CH
534 break;
535 case XFS_DINODE_FMT_EXTENTS:
536 case XFS_DINODE_FMT_BTREE:
a87a40a2
CH
537 if (ifp->if_height)
538 xfs_iext_destroy(ifp);
fca0a273 539 break;
5d90ab5a
DC
540 }
541}
542
543/*
ff105f75 544 * Convert in-core extents to on-disk form
5d90ab5a 545 *
ff105f75
DC
546 * In the case of the data fork, the in-core and on-disk fork sizes can be
547 * different due to delayed allocation extents. We only copy on-disk extents
548 * here, so callers must always use the physical fork size to determine the
549 * size of the buffer passed to this routine. We will return the size actually
550 * used.
5d90ab5a
DC
551 */
552int
553xfs_iextents_copy(
f11e7501
CH
554 struct xfs_inode *ip,
555 struct xfs_bmbt_rec *dp,
5d90ab5a
DC
556 int whichfork)
557{
322fd804 558 int state = xfs_bmap_fork_to_state(whichfork);
722e81c1 559 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
9788e059 560 struct xfs_iext_cursor icur;
f11e7501 561 struct xfs_bmbt_irec rec;
b6d2b93c 562 int64_t copied = 0;
5d90ab5a 563
f11e7501 564 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL | XFS_ILOCK_SHARED));
5d90ab5a
DC
565 ASSERT(ifp->if_bytes > 0);
566
9788e059 567 for_each_xfs_iext(ifp, &icur, &rec) {
f11e7501 568 if (isnullstartblock(rec.br_startblock))
5d90ab5a 569 continue;
0cf6a3a9 570 ASSERT(xfs_bmap_validate_extent(ip, whichfork, &rec) == NULL);
f11e7501 571 xfs_bmbt_disk_set_all(dp, &rec);
9788e059 572 trace_xfs_write_extent(ip, &icur, state, _RET_IP_);
f11e7501 573 copied += sizeof(struct xfs_bmbt_rec);
5d90ab5a 574 dp++;
5d90ab5a 575 }
5d90ab5a 576
f11e7501
CH
577 ASSERT(copied > 0);
578 ASSERT(copied <= ifp->if_bytes);
579 return copied;
5d90ab5a
DC
580}
581
582/*
583 * Each of the following cases stores data into the same region
584 * of the on-disk inode, so only one of them can be valid at
585 * any given time. While it is possible to have conflicting formats
586 * and log flags, e.g. having XFS_ILOG_?DATA set when the fork is
587 * in EXTENTS format, this can only happen when the fork has
588 * changed formats after being modified but before being flushed.
589 * In these cases, the format always takes precedence, because the
590 * format indicates the current state of the fork.
591 */
d15188a1 592void
5d90ab5a 593xfs_iflush_fork(
7328ea6e
CH
594 struct xfs_inode *ip,
595 struct xfs_dinode *dip,
ed8d09e1 596 struct xfs_inode_log_item *iip,
ff105f75 597 int whichfork)
5d90ab5a
DC
598{
599 char *cp;
e07055b8 600 struct xfs_ifork *ifp;
5d90ab5a
DC
601 xfs_mount_t *mp;
602 static const short brootflag[2] =
603 { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };
604 static const short dataflag[2] =
605 { XFS_ILOG_DDATA, XFS_ILOG_ADATA };
606 static const short extflag[2] =
607 { XFS_ILOG_DEXT, XFS_ILOG_AEXT };
608
609 if (!iip)
d15188a1 610 return;
722e81c1 611 ifp = xfs_ifork_ptr(ip, whichfork);
5d90ab5a
DC
612 /*
613 * This can happen if we gave up in iformat in an error path,
614 * for the attribute fork.
615 */
616 if (!ifp) {
617 ASSERT(whichfork == XFS_ATTR_FORK);
d15188a1 618 return;
5d90ab5a
DC
619 }
620 cp = XFS_DFORK_PTR(dip, whichfork);
621 mp = ip->i_mount;
d967a68d 622 switch (ifp->if_format) {
5d90ab5a
DC
623 case XFS_DINODE_FMT_LOCAL:
624 if ((iip->ili_fields & dataflag[whichfork]) &&
625 (ifp->if_bytes > 0)) {
626 ASSERT(ifp->if_u1.if_data != NULL);
eae3e30d 627 ASSERT(ifp->if_bytes <= xfs_inode_fork_size(ip, whichfork));
5d90ab5a
DC
628 memcpy(cp, ifp->if_u1.if_data, ifp->if_bytes);
629 }
630 break;
631
632 case XFS_DINODE_FMT_EXTENTS:
5d90ab5a
DC
633 if ((iip->ili_fields & extflag[whichfork]) &&
634 (ifp->if_bytes > 0)) {
87c472b7 635 ASSERT(ifp->if_nextents > 0);
5d90ab5a
DC
636 (void)xfs_iextents_copy(ip, (xfs_bmbt_rec_t *)cp,
637 whichfork);
638 }
639 break;
640
641 case XFS_DINODE_FMT_BTREE:
642 if ((iip->ili_fields & brootflag[whichfork]) &&
643 (ifp->if_broot_bytes > 0)) {
644 ASSERT(ifp->if_broot != NULL);
645 ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
eae3e30d 646 xfs_inode_fork_size(ip, whichfork));
5d90ab5a
DC
647 xfs_bmbt_to_bmdr(mp, ifp->if_broot, ifp->if_broot_bytes,
648 (xfs_bmdr_block_t *)cp,
649 XFS_DFORK_SIZE(dip, mp, whichfork));
650 }
651 break;
652
653 case XFS_DINODE_FMT_DEV:
654 if (iip->ili_fields & XFS_ILOG_DEV) {
655 ASSERT(whichfork == XFS_DATA_FORK);
dc9b1f58
CH
656 xfs_dinode_put_rdev(dip,
657 linux_to_xfs_dev_t(VFS_I(ip)->i_rdev));
5d90ab5a
DC
658 }
659 break;
660
5d90ab5a
DC
661 default:
662 ASSERT(0);
663 break;
664 }
665}
666
cb8a004a
DW
667/* Convert bmap state flags to an inode fork. */
668struct xfs_ifork *
669xfs_iext_state_to_fork(
670 struct xfs_inode *ip,
671 int state)
672{
673 if (state & BMAP_COWFORK)
674 return ip->i_cowfp;
675 else if (state & BMAP_ATTRFORK)
7ff5f1ed 676 return &ip->i_af;
cb8a004a
DW
677 return &ip->i_df;
678}
679
cb8a004a
DW
680/*
681 * Initialize an inode's copy-on-write fork.
682 */
683void
684xfs_ifork_init_cow(
685 struct xfs_inode *ip)
686{
687 if (ip->i_cowfp)
688 return;
689
2e1394fc 690 ip->i_cowfp = kmem_cache_zalloc(xfs_ifork_cache,
17e074de 691 GFP_NOFS | __GFP_NOFAIL);
d967a68d 692 ip->i_cowfp->if_format = XFS_DINODE_FMT_EXTENTS;
cb8a004a 693}
20e882d4 694
20e882d4 695/* Verify the inline contents of the data fork of an inode. */
318d12fd
CH
696int
697xfs_ifork_verify_local_data(
1fecabf9 698 struct xfs_inode *ip)
20e882d4 699{
318d12fd 700 xfs_failaddr_t fa = NULL;
20e882d4 701
20e882d4
DW
702 switch (VFS_I(ip)->i_mode & S_IFMT) {
703 case S_IFDIR:
318d12fd
CH
704 fa = xfs_dir2_sf_verify(ip);
705 break;
20e882d4 706 case S_IFLNK:
318d12fd
CH
707 fa = xfs_symlink_shortform_verify(ip);
708 break;
20e882d4 709 default:
318d12fd 710 break;
20e882d4 711 }
318d12fd
CH
712
713 if (fa) {
714 xfs_inode_verifier_error(ip, -EFSCORRUPTED, "data fork",
715 ip->i_df.if_u1.if_data, ip->i_df.if_bytes, fa);
716 return -EFSCORRUPTED;
717 }
718
719 return 0;
20e882d4
DW
720}
721
722/* Verify the inline contents of the attr fork of an inode. */
318d12fd
CH
723int
724xfs_ifork_verify_local_attr(
1fecabf9 725 struct xfs_inode *ip)
20e882d4 726{
7ff5f1ed 727 struct xfs_ifork *ifp = &ip->i_af;
318d12fd
CH
728 xfs_failaddr_t fa;
729
4f841585 730 if (!xfs_inode_has_attr_fork(ip))
318d12fd
CH
731 fa = __this_address;
732 else
733 fa = xfs_attr_shortform_verify(ip);
734
735 if (fa) {
736 xfs_inode_verifier_error(ip, -EFSCORRUPTED, "attr fork",
17df7eb7 737 ifp->if_u1.if_data, ifp->if_bytes, fa);
318d12fd
CH
738 return -EFSCORRUPTED;
739 }
740
741 return 0;
20e882d4 742}
d629a2d9
CB
743
744int
745xfs_iext_count_may_overflow(
746 struct xfs_inode *ip,
747 int whichfork,
748 int nr_to_add)
749{
722e81c1 750 struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
d629a2d9
CB
751 uint64_t max_exts;
752 uint64_t nr_exts;
753
754 if (whichfork == XFS_COW_FORK)
755 return 0;
756
5a8b4d6a
CB
757 max_exts = xfs_iext_max_nextents(xfs_inode_has_large_extent_counts(ip),
758 whichfork);
d629a2d9 759
b88613bd
CB
760 if (XFS_TEST_ERROR(false, ip->i_mount, XFS_ERRTAG_REDUCE_MAX_IEXTENTS))
761 max_exts = 10;
762
d629a2d9
CB
763 nr_exts = ifp->if_nextents + nr_to_add;
764 if (nr_exts < ifp->if_nextents || nr_exts > max_exts)
765 return -EFBIG;
766
767 return 0;
768}
fcba1629
CB
769
770/*
771 * Upgrade this inode's extent counter fields to be able to handle a potential
772 * increase in the extent count by nr_to_add. Normally this is the same
773 * quantity that caused xfs_iext_count_may_overflow() to return -EFBIG.
774 */
775int
776xfs_iext_count_upgrade(
777 struct xfs_trans *tp,
778 struct xfs_inode *ip,
779 uint nr_to_add)
780{
781 ASSERT(nr_to_add <= XFS_MAX_EXTCNT_UPGRADE_NR);
782
783 if (!xfs_has_large_extent_counts(ip->i_mount) ||
784 xfs_inode_has_large_extent_counts(ip) ||
785 XFS_TEST_ERROR(false, ip->i_mount, XFS_ERRTAG_REDUCE_MAX_IEXTENTS))
786 return -EFBIG;
787
788 ip->i_diflags2 |= XFS_DIFLAG2_NREXT64;
789 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
790
791 return 0;
792}