]>
Commit | Line | Data |
---|---|---|
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" |
178287f4 | 26 | #include "xfs_health.h" |
ce160fd9 | 27 | #include "xfs_symlink_remote.h" |
b8d1b5ca | 28 | #include "xfs_rtrmap_btree.h" |
b81e004c | 29 | #include "xfs_rtrefcount_btree.h" |
5d90ab5a | 30 | |
2e1394fc | 31 | struct kmem_cache *xfs_ifork_cache; |
5d90ab5a | 32 | |
219eec76 CH |
33 | void |
34 | xfs_init_local_fork( | |
35 | struct xfs_inode *ip, | |
36 | int whichfork, | |
37 | const void *data, | |
b6d2b93c | 38 | int64_t size) |
219eec76 | 39 | { |
722e81c1 | 40 | struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); |
227a3b63 | 41 | int mem_size = size; |
4cab415f CH |
42 | bool zero_terminate; |
43 | ||
44 | /* | |
45 | * If we are using the local fork to store a symlink body we need to | |
46 | * zero-terminate it so that we can pass it back to the VFS directly. | |
47 | * Overallocate the in-memory fork by one for that and add a zero | |
48 | * to terminate it below. | |
49 | */ | |
50 | zero_terminate = S_ISLNK(VFS_I(ip)->i_mode); | |
51 | if (zero_terminate) | |
52 | mem_size++; | |
219eec76 | 53 | |
07fe4665 | 54 | if (size) { |
c3bf5a1f DC |
55 | char *new_data = kmalloc(mem_size, |
56 | GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOFAIL); | |
f8146197 CH |
57 | |
58 | memcpy(new_data, data, size); | |
4cab415f | 59 | if (zero_terminate) |
f8146197 CH |
60 | new_data[size] = '\0'; |
61 | ||
62 | ifp->if_data = new_data; | |
07fe4665 | 63 | } else { |
f8146197 | 64 | ifp->if_data = NULL; |
4cab415f | 65 | } |
219eec76 CH |
66 | |
67 | ifp->if_bytes = size; | |
219eec76 CH |
68 | } |
69 | ||
5d90ab5a DC |
70 | /* |
71 | * The file is in-lined in the on-disk inode. | |
5d90ab5a DC |
72 | */ |
73 | STATIC int | |
74 | xfs_iformat_local( | |
7328ea6e CH |
75 | struct xfs_inode *ip, |
76 | struct xfs_dinode *dip, | |
77 | int whichfork, | |
78 | int size) | |
5d90ab5a | 79 | { |
5d90ab5a DC |
80 | /* |
81 | * If the size is unreasonable, then something | |
82 | * is wrong and we just bail out rather than crash in | |
52233984 | 83 | * kmalloc() or memcpy() below. |
5d90ab5a DC |
84 | */ |
85 | if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) { | |
86 | xfs_warn(ip->i_mount, | |
be98db85 | 87 | "corrupt inode %llu (bad size %d for local fork, size = %zd).", |
5d90ab5a DC |
88 | (unsigned long long) ip->i_ino, size, |
89 | XFS_DFORK_SIZE(dip, ip->i_mount, whichfork)); | |
b02a2c9e DW |
90 | xfs_inode_verifier_error(ip, -EFSCORRUPTED, |
91 | "xfs_iformat_local", dip, sizeof(*dip), | |
92 | __this_address); | |
178287f4 | 93 | xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE); |
12b53197 | 94 | return -EFSCORRUPTED; |
5d90ab5a | 95 | } |
219eec76 CH |
96 | |
97 | xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size); | |
5d90ab5a DC |
98 | return 0; |
99 | } | |
100 | ||
101 | /* | |
1f2a4478 | 102 | * The file consists of a set of extents all of which fit into the on-disk |
07fe4665 | 103 | * inode. |
5d90ab5a DC |
104 | */ |
105 | STATIC int | |
106 | xfs_iformat_extents( | |
1f2a4478 CH |
107 | struct xfs_inode *ip, |
108 | struct xfs_dinode *dip, | |
109 | int whichfork) | |
5d90ab5a | 110 | { |
1f2a4478 | 111 | struct xfs_mount *mp = ip->i_mount; |
722e81c1 | 112 | struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); |
322fd804 | 113 | int state = xfs_bmap_fork_to_state(whichfork); |
5f70c91b | 114 | xfs_extnum_t nex = xfs_dfork_nextents(dip, whichfork); |
1f2a4478 | 115 | int size = nex * sizeof(xfs_bmbt_rec_t); |
9788e059 | 116 | struct xfs_iext_cursor icur; |
1f2a4478 | 117 | struct xfs_bmbt_rec *dp; |
b37d753d | 118 | struct xfs_bmbt_irec new; |
1f2a4478 | 119 | int i; |
5d90ab5a DC |
120 | |
121 | /* | |
1f2a4478 | 122 | * If the number of extents is unreasonable, then something is wrong and |
52233984 | 123 | * we just bail out rather than crash in kmalloc() or memcpy() below. |
5d90ab5a | 124 | */ |
1f2a4478 | 125 | if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, mp, whichfork))) { |
4b85994a CB |
126 | xfs_warn(ip->i_mount, "corrupt inode %llu ((a)extents = %llu).", |
127 | ip->i_ino, nex); | |
b02a2c9e DW |
128 | xfs_inode_verifier_error(ip, -EFSCORRUPTED, |
129 | "xfs_iformat_extents(1)", dip, sizeof(*dip), | |
130 | __this_address); | |
178287f4 | 131 | xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE); |
12b53197 | 132 | return -EFSCORRUPTED; |
5d90ab5a DC |
133 | } |
134 | ||
b37d753d | 135 | ifp->if_bytes = 0; |
f8146197 | 136 | ifp->if_data = NULL; |
b37d753d | 137 | ifp->if_height = 0; |
5d90ab5a DC |
138 | if (size) { |
139 | dp = (xfs_bmbt_rec_t *) XFS_DFORK_PTR(dip, whichfork); | |
9788e059 CH |
140 | |
141 | xfs_iext_first(ifp, &icur); | |
5d90ab5a | 142 | for (i = 0; i < nex; i++, dp++) { |
0cf6a3a9 DW |
143 | xfs_failaddr_t fa; |
144 | ||
080f0c71 | 145 | xfs_bmbt_disk_get_all(dp, &new); |
0cf6a3a9 DW |
146 | fa = xfs_bmap_validate_extent(ip, whichfork, &new); |
147 | if (fa) { | |
148 | xfs_inode_verifier_error(ip, -EFSCORRUPTED, | |
149 | "xfs_iformat_extents(2)", | |
150 | dp, sizeof(*dp), fa); | |
178287f4 | 151 | xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE); |
830c99b1 DW |
152 | return xfs_bmap_complain_bad_rec(ip, whichfork, |
153 | fa, &new); | |
1f2a4478 | 154 | } |
9788e059 | 155 | |
26a75f67 | 156 | xfs_iext_insert(ip, &icur, &new, state); |
9788e059 CH |
157 | trace_xfs_read_extent(ip, &icur, state, _THIS_IP_); |
158 | xfs_iext_next(ifp, &icur); | |
5d90ab5a | 159 | } |
5d90ab5a | 160 | } |
5d90ab5a DC |
161 | return 0; |
162 | } | |
163 | ||
164 | /* | |
165 | * The file has too many extents to fit into | |
166 | * the inode, so they are in B-tree format. | |
167 | * Allocate a buffer for the root of the B-tree | |
168 | * and copy the root into it. The i_extents | |
169 | * field will remain NULL until all of the | |
170 | * extents are read in (when they are needed). | |
171 | */ | |
172 | STATIC int | |
173 | xfs_iformat_btree( | |
7328ea6e CH |
174 | struct xfs_inode *ip, |
175 | struct xfs_dinode *dip, | |
5d90ab5a DC |
176 | int whichfork) |
177 | { | |
178 | struct xfs_mount *mp = ip->i_mount; | |
179 | xfs_bmdr_block_t *dfp; | |
e07055b8 | 180 | struct xfs_ifork *ifp; |
5b8ba053 | 181 | struct xfs_btree_block *broot; |
5d90ab5a DC |
182 | int nrecs; |
183 | int size; | |
81bf5e85 | 184 | int level; |
5d90ab5a | 185 | |
722e81c1 | 186 | ifp = xfs_ifork_ptr(ip, whichfork); |
5d90ab5a | 187 | dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); |
2f8e9b0a | 188 | size = xfs_bmap_broot_space(mp, dfp); |
5d90ab5a | 189 | nrecs = be16_to_cpu(dfp->bb_numrecs); |
81bf5e85 | 190 | level = be16_to_cpu(dfp->bb_level); |
5d90ab5a DC |
191 | |
192 | /* | |
193 | * blow out if -- fork has less extents than can fit in | |
194 | * fork (fork shouldn't be a btree format), root btree | |
195 | * block has more records than can fit into the fork, | |
196 | * or the number of extents is greater than the number of | |
197 | * blocks. | |
198 | */ | |
87c472b7 | 199 | if (unlikely(ifp->if_nextents <= XFS_IFORK_MAXEXT(ip, whichfork) || |
e4b963e9 | 200 | nrecs == 0 || |
2f8e9b0a | 201 | xfs_bmdr_space_calc(nrecs) > |
5d90ab5a | 202 | XFS_DFORK_SIZE(dip, mp, whichfork) || |
aa00f286 | 203 | ifp->if_nextents > ip->i_nblocks) || |
55369096 | 204 | level == 0 || level > XFS_BM_MAXLEVELS(mp, whichfork)) { |
be98db85 | 205 | xfs_warn(mp, "corrupt inode %llu (btree).", |
5d90ab5a | 206 | (unsigned long long) ip->i_ino); |
b02a2c9e DW |
207 | xfs_inode_verifier_error(ip, -EFSCORRUPTED, |
208 | "xfs_iformat_btree", dfp, size, | |
209 | __this_address); | |
178287f4 | 210 | xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE); |
12b53197 | 211 | return -EFSCORRUPTED; |
5d90ab5a DC |
212 | } |
213 | ||
5b8ba053 | 214 | broot = xfs_broot_alloc(ifp, size); |
5d90ab5a DC |
215 | /* |
216 | * Copy and convert from the on-disk structure | |
217 | * to the in-memory structure. | |
218 | */ | |
219 | xfs_bmdr_to_bmbt(ip, dfp, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork), | |
5b8ba053 | 220 | broot, size); |
5d90ab5a | 221 | |
b37d753d | 222 | ifp->if_bytes = 0; |
f8146197 | 223 | ifp->if_data = NULL; |
b37d753d | 224 | ifp->if_height = 0; |
5d90ab5a DC |
225 | return 0; |
226 | } | |
227 | ||
07973a77 CH |
228 | int |
229 | xfs_iformat_data_fork( | |
230 | struct xfs_inode *ip, | |
231 | struct xfs_dinode *dip) | |
232 | { | |
233 | struct inode *inode = VFS_I(ip); | |
0815f7ab | 234 | int error; |
07973a77 | 235 | |
87c472b7 CH |
236 | /* |
237 | * Initialize the extent count early, as the per-format routines may | |
0bf7f8c3 DW |
238 | * depend on it. Use release semantics to set needextents /after/ we |
239 | * set the format. This ensures that we can use acquire semantics on | |
240 | * needextents in xfs_need_iread_extents() and be guaranteed to see a | |
241 | * valid format value after that load. | |
87c472b7 | 242 | */ |
d967a68d | 243 | ip->i_df.if_format = dip->di_format; |
5f70c91b | 244 | ip->i_df.if_nextents = xfs_dfork_data_extents(dip); |
0bf7f8c3 DW |
245 | smp_store_release(&ip->i_df.if_needextents, |
246 | ip->i_df.if_format == XFS_DINODE_FMT_BTREE ? 1 : 0); | |
87c472b7 | 247 | |
07973a77 CH |
248 | switch (inode->i_mode & S_IFMT) { |
249 | case S_IFIFO: | |
250 | case S_IFCHR: | |
251 | case S_IFBLK: | |
252 | case S_IFSOCK: | |
509dcb4b | 253 | ip->i_disk_size = 0; |
07973a77 CH |
254 | inode->i_rdev = xfs_to_linux_dev_t(xfs_dinode_get_rdev(dip)); |
255 | return 0; | |
256 | case S_IFREG: | |
257 | case S_IFLNK: | |
258 | case S_IFDIR: | |
d967a68d | 259 | switch (ip->i_df.if_format) { |
07973a77 | 260 | case XFS_DINODE_FMT_LOCAL: |
0815f7ab | 261 | error = xfs_iformat_local(ip, dip, XFS_DATA_FORK, |
07973a77 | 262 | be64_to_cpu(dip->di_size)); |
0815f7ab CH |
263 | if (!error) |
264 | error = xfs_ifork_verify_local_data(ip); | |
265 | return error; | |
07973a77 CH |
266 | case XFS_DINODE_FMT_EXTENTS: |
267 | return xfs_iformat_extents(ip, dip, XFS_DATA_FORK); | |
268 | case XFS_DINODE_FMT_BTREE: | |
269 | return xfs_iformat_btree(ip, dip, XFS_DATA_FORK); | |
64c60f52 DW |
270 | case XFS_DINODE_FMT_META_BTREE: |
271 | switch (ip->i_metatype) { | |
5a9a1f89 | 272 | case XFS_METAFILE_RTRMAP: |
b8d1b5ca | 273 | return xfs_iformat_rtrmap(ip, dip); |
0f2ef731 | 274 | case XFS_METAFILE_RTREFCOUNT: |
b81e004c | 275 | return xfs_iformat_rtrefcount(ip, dip); |
64c60f52 DW |
276 | default: |
277 | break; | |
278 | } | |
279 | fallthrough; | |
07973a77 CH |
280 | default: |
281 | xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, | |
282 | dip, sizeof(*dip), __this_address); | |
178287f4 | 283 | xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE); |
07973a77 CH |
284 | return -EFSCORRUPTED; |
285 | } | |
286 | break; | |
287 | default: | |
288 | xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip, | |
289 | sizeof(*dip), __this_address); | |
178287f4 | 290 | xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE); |
07973a77 CH |
291 | return -EFSCORRUPTED; |
292 | } | |
293 | } | |
294 | ||
295 | static uint16_t | |
296 | xfs_dfork_attr_shortform_size( | |
297 | struct xfs_dinode *dip) | |
298 | { | |
5e2372c4 | 299 | struct xfs_attr_sf_hdr *sf = XFS_DFORK_APTR(dip); |
07973a77 | 300 | |
5e2372c4 | 301 | return be16_to_cpu(sf->totsize); |
07973a77 CH |
302 | } |
303 | ||
7ff5f1ed DW |
304 | void |
305 | xfs_ifork_init_attr( | |
306 | struct xfs_inode *ip, | |
652a2133 DC |
307 | enum xfs_dinode_fmt format, |
308 | xfs_extnum_t nextents) | |
309 | { | |
0bf7f8c3 DW |
310 | /* |
311 | * Initialize the extent count early, as the per-format routines may | |
312 | * depend on it. Use release semantics to set needextents /after/ we | |
313 | * set the format. This ensures that we can use acquire semantics on | |
314 | * needextents in xfs_need_iread_extents() and be guaranteed to see a | |
315 | * valid format value after that load. | |
316 | */ | |
7ff5f1ed DW |
317 | ip->i_af.if_format = format; |
318 | ip->i_af.if_nextents = nextents; | |
0bf7f8c3 DW |
319 | smp_store_release(&ip->i_af.if_needextents, |
320 | ip->i_af.if_format == XFS_DINODE_FMT_BTREE ? 1 : 0); | |
7ff5f1ed DW |
321 | } |
322 | ||
323 | void | |
324 | xfs_ifork_zap_attr( | |
325 | struct xfs_inode *ip) | |
326 | { | |
e373f06a | 327 | xfs_idestroy_fork(&ip->i_af); |
7ff5f1ed DW |
328 | memset(&ip->i_af, 0, sizeof(struct xfs_ifork)); |
329 | ip->i_af.if_format = XFS_DINODE_FMT_EXTENTS; | |
652a2133 DC |
330 | } |
331 | ||
07973a77 CH |
332 | int |
333 | xfs_iformat_attr_fork( | |
334 | struct xfs_inode *ip, | |
335 | struct xfs_dinode *dip) | |
336 | { | |
5f70c91b | 337 | xfs_extnum_t naextents = xfs_dfork_attr_extents(dip); |
07973a77 CH |
338 | int error = 0; |
339 | ||
87c472b7 CH |
340 | /* |
341 | * Initialize the extent count early, as the per-format routines may | |
342 | * depend on it. | |
343 | */ | |
7ff5f1ed | 344 | xfs_ifork_init_attr(ip, dip->di_aformat, naextents); |
87c472b7 | 345 | |
7ff5f1ed | 346 | switch (ip->i_af.if_format) { |
07973a77 CH |
347 | case XFS_DINODE_FMT_LOCAL: |
348 | error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK, | |
349 | xfs_dfork_attr_shortform_size(dip)); | |
0815f7ab CH |
350 | if (!error) |
351 | error = xfs_ifork_verify_local_attr(ip); | |
07973a77 CH |
352 | break; |
353 | case XFS_DINODE_FMT_EXTENTS: | |
354 | error = xfs_iformat_extents(ip, dip, XFS_ATTR_FORK); | |
355 | break; | |
356 | case XFS_DINODE_FMT_BTREE: | |
357 | error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK); | |
358 | break; | |
359 | default: | |
360 | xfs_inode_verifier_error(ip, error, __func__, dip, | |
361 | sizeof(*dip), __this_address); | |
178287f4 | 362 | xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE); |
07973a77 CH |
363 | error = -EFSCORRUPTED; |
364 | break; | |
365 | } | |
366 | ||
7ff5f1ed DW |
367 | if (error) |
368 | xfs_ifork_zap_attr(ip); | |
07973a77 CH |
369 | return error; |
370 | } | |
371 | ||
5b8ba053 DW |
372 | /* |
373 | * Allocate the if_broot component of an inode fork so that it is @new_size | |
374 | * bytes in size, using __GFP_NOLOCKDEP like all the other code that | |
375 | * initializes a broot during inode load. Returns if_broot. | |
376 | */ | |
377 | struct xfs_btree_block * | |
378 | xfs_broot_alloc( | |
379 | struct xfs_ifork *ifp, | |
380 | size_t new_size) | |
381 | { | |
382 | ASSERT(ifp->if_broot == NULL); | |
383 | ||
384 | ifp->if_broot = kmalloc(new_size, | |
385 | GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOFAIL); | |
386 | ifp->if_broot_bytes = new_size; | |
387 | return ifp->if_broot; | |
388 | } | |
389 | ||
390 | /* | |
391 | * Reallocate the if_broot component of an inode fork so that it is @new_size | |
392 | * bytes in size. Returns if_broot. | |
393 | */ | |
394 | struct xfs_btree_block * | |
395 | xfs_broot_realloc( | |
396 | struct xfs_ifork *ifp, | |
397 | size_t new_size) | |
398 | { | |
399 | /* No size change? No action needed. */ | |
400 | if (new_size == ifp->if_broot_bytes) | |
401 | return ifp->if_broot; | |
402 | ||
403 | /* New size is zero, free it. */ | |
404 | if (new_size == 0) { | |
405 | ifp->if_broot_bytes = 0; | |
406 | kfree(ifp->if_broot); | |
407 | ifp->if_broot = NULL; | |
408 | return NULL; | |
409 | } | |
410 | ||
411 | /* | |
412 | * Shrinking the iroot means we allocate a new smaller object and copy | |
413 | * it. We don't trust krealloc not to nop on realloc-down. | |
414 | */ | |
415 | if (ifp->if_broot_bytes > 0 && ifp->if_broot_bytes > new_size) { | |
416 | struct xfs_btree_block *old_broot = ifp->if_broot; | |
417 | ||
418 | ifp->if_broot = kmalloc(new_size, GFP_KERNEL | __GFP_NOFAIL); | |
419 | ifp->if_broot_bytes = new_size; | |
420 | memcpy(ifp->if_broot, old_broot, new_size); | |
421 | kfree(old_broot); | |
422 | return ifp->if_broot; | |
423 | } | |
424 | ||
425 | /* | |
426 | * Growing the iroot means we can krealloc. This may get us the same | |
427 | * object. | |
428 | */ | |
429 | ifp->if_broot = krealloc(ifp->if_broot, new_size, | |
430 | GFP_KERNEL | __GFP_NOFAIL); | |
431 | ifp->if_broot_bytes = new_size; | |
432 | return ifp->if_broot; | |
433 | } | |
434 | ||
5d90ab5a DC |
435 | /* |
436 | * This is called when the amount of space needed for if_data | |
437 | * is increased or decreased. The change in size is indicated by | |
438 | * the number of bytes that need to be added or deleted in the | |
439 | * byte_diff parameter. | |
440 | * | |
441 | * If the amount of space needed has decreased below the size of the | |
442 | * inline buffer, then switch to using the inline buffer. Otherwise, | |
52233984 | 443 | * use krealloc() or kmalloc() to adjust the size of the buffer |
5d90ab5a DC |
444 | * to what is needed. |
445 | * | |
446 | * ip -- the inode whose if_data area is changing | |
447 | * byte_diff -- the change in the number of bytes, positive or negative, | |
448 | * requested for the if_data array. | |
449 | */ | |
4ff35b84 | 450 | void * |
5d90ab5a | 451 | xfs_idata_realloc( |
2282d1d1 | 452 | struct xfs_inode *ip, |
b6d2b93c | 453 | int64_t byte_diff, |
2282d1d1 | 454 | int whichfork) |
5d90ab5a | 455 | { |
722e81c1 | 456 | struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); |
b6d2b93c | 457 | int64_t new_size = ifp->if_bytes + byte_diff; |
5d90ab5a | 458 | |
5d90ab5a | 459 | ASSERT(new_size >= 0); |
eae3e30d | 460 | ASSERT(new_size <= xfs_inode_fork_size(ip, whichfork)); |
2282d1d1 | 461 | |
4ff35b84 CH |
462 | if (byte_diff) { |
463 | ifp->if_data = krealloc(ifp->if_data, new_size, | |
a6cb3f66 | 464 | GFP_KERNEL | __GFP_NOFAIL); |
4ff35b84 CH |
465 | if (new_size == 0) |
466 | ifp->if_data = NULL; | |
467 | ifp->if_bytes = new_size; | |
5d90ab5a | 468 | } |
2282d1d1 | 469 | |
4ff35b84 | 470 | return ifp->if_data; |
5d90ab5a DC |
471 | } |
472 | ||
7310dea5 | 473 | /* Free all memory and reset a fork back to its initial state. */ |
5d90ab5a DC |
474 | void |
475 | xfs_idestroy_fork( | |
a87a40a2 | 476 | struct xfs_ifork *ifp) |
5d90ab5a | 477 | { |
5d90ab5a | 478 | if (ifp->if_broot != NULL) { |
336b689a | 479 | kfree(ifp->if_broot); |
5d90ab5a DC |
480 | ifp->if_broot = NULL; |
481 | } | |
482 | ||
fca0a273 CH |
483 | switch (ifp->if_format) { |
484 | case XFS_DINODE_FMT_LOCAL: | |
336b689a | 485 | kfree(ifp->if_data); |
f8146197 | 486 | ifp->if_data = NULL; |
fca0a273 CH |
487 | break; |
488 | case XFS_DINODE_FMT_EXTENTS: | |
489 | case XFS_DINODE_FMT_BTREE: | |
a87a40a2 CH |
490 | if (ifp->if_height) |
491 | xfs_iext_destroy(ifp); | |
fca0a273 | 492 | break; |
5d90ab5a DC |
493 | } |
494 | } | |
495 | ||
496 | /* | |
ff105f75 | 497 | * Convert in-core extents to on-disk form |
5d90ab5a | 498 | * |
ff105f75 DC |
499 | * In the case of the data fork, the in-core and on-disk fork sizes can be |
500 | * different due to delayed allocation extents. We only copy on-disk extents | |
501 | * here, so callers must always use the physical fork size to determine the | |
502 | * size of the buffer passed to this routine. We will return the size actually | |
503 | * used. | |
5d90ab5a DC |
504 | */ |
505 | int | |
506 | xfs_iextents_copy( | |
f11e7501 CH |
507 | struct xfs_inode *ip, |
508 | struct xfs_bmbt_rec *dp, | |
5d90ab5a DC |
509 | int whichfork) |
510 | { | |
322fd804 | 511 | int state = xfs_bmap_fork_to_state(whichfork); |
722e81c1 | 512 | struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); |
9788e059 | 513 | struct xfs_iext_cursor icur; |
f11e7501 | 514 | struct xfs_bmbt_irec rec; |
b6d2b93c | 515 | int64_t copied = 0; |
5d90ab5a | 516 | |
d3d1a2cb | 517 | xfs_assert_ilocked(ip, XFS_ILOCK_EXCL | XFS_ILOCK_SHARED); |
5d90ab5a DC |
518 | ASSERT(ifp->if_bytes > 0); |
519 | ||
9788e059 | 520 | for_each_xfs_iext(ifp, &icur, &rec) { |
f11e7501 | 521 | if (isnullstartblock(rec.br_startblock)) |
5d90ab5a | 522 | continue; |
0cf6a3a9 | 523 | ASSERT(xfs_bmap_validate_extent(ip, whichfork, &rec) == NULL); |
f11e7501 | 524 | xfs_bmbt_disk_set_all(dp, &rec); |
9788e059 | 525 | trace_xfs_write_extent(ip, &icur, state, _RET_IP_); |
f11e7501 | 526 | copied += sizeof(struct xfs_bmbt_rec); |
5d90ab5a | 527 | dp++; |
5d90ab5a | 528 | } |
5d90ab5a | 529 | |
f11e7501 CH |
530 | ASSERT(copied > 0); |
531 | ASSERT(copied <= ifp->if_bytes); | |
532 | return copied; | |
5d90ab5a DC |
533 | } |
534 | ||
535 | /* | |
536 | * Each of the following cases stores data into the same region | |
537 | * of the on-disk inode, so only one of them can be valid at | |
538 | * any given time. While it is possible to have conflicting formats | |
539 | * and log flags, e.g. having XFS_ILOG_?DATA set when the fork is | |
540 | * in EXTENTS format, this can only happen when the fork has | |
541 | * changed formats after being modified but before being flushed. | |
542 | * In these cases, the format always takes precedence, because the | |
543 | * format indicates the current state of the fork. | |
544 | */ | |
d15188a1 | 545 | void |
5d90ab5a | 546 | xfs_iflush_fork( |
7328ea6e CH |
547 | struct xfs_inode *ip, |
548 | struct xfs_dinode *dip, | |
ed8d09e1 | 549 | struct xfs_inode_log_item *iip, |
ff105f75 | 550 | int whichfork) |
5d90ab5a DC |
551 | { |
552 | char *cp; | |
e07055b8 | 553 | struct xfs_ifork *ifp; |
5d90ab5a DC |
554 | xfs_mount_t *mp; |
555 | static const short brootflag[2] = | |
556 | { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT }; | |
557 | static const short dataflag[2] = | |
558 | { XFS_ILOG_DDATA, XFS_ILOG_ADATA }; | |
559 | static const short extflag[2] = | |
560 | { XFS_ILOG_DEXT, XFS_ILOG_AEXT }; | |
561 | ||
562 | if (!iip) | |
d15188a1 | 563 | return; |
722e81c1 | 564 | ifp = xfs_ifork_ptr(ip, whichfork); |
5d90ab5a DC |
565 | /* |
566 | * This can happen if we gave up in iformat in an error path, | |
567 | * for the attribute fork. | |
568 | */ | |
569 | if (!ifp) { | |
570 | ASSERT(whichfork == XFS_ATTR_FORK); | |
d15188a1 | 571 | return; |
5d90ab5a DC |
572 | } |
573 | cp = XFS_DFORK_PTR(dip, whichfork); | |
574 | mp = ip->i_mount; | |
d967a68d | 575 | switch (ifp->if_format) { |
5d90ab5a DC |
576 | case XFS_DINODE_FMT_LOCAL: |
577 | if ((iip->ili_fields & dataflag[whichfork]) && | |
578 | (ifp->if_bytes > 0)) { | |
f8146197 | 579 | ASSERT(ifp->if_data != NULL); |
eae3e30d | 580 | ASSERT(ifp->if_bytes <= xfs_inode_fork_size(ip, whichfork)); |
f8146197 | 581 | memcpy(cp, ifp->if_data, ifp->if_bytes); |
5d90ab5a DC |
582 | } |
583 | break; | |
584 | ||
585 | case XFS_DINODE_FMT_EXTENTS: | |
5d90ab5a DC |
586 | if ((iip->ili_fields & extflag[whichfork]) && |
587 | (ifp->if_bytes > 0)) { | |
87c472b7 | 588 | ASSERT(ifp->if_nextents > 0); |
5d90ab5a DC |
589 | (void)xfs_iextents_copy(ip, (xfs_bmbt_rec_t *)cp, |
590 | whichfork); | |
591 | } | |
592 | break; | |
593 | ||
594 | case XFS_DINODE_FMT_BTREE: | |
595 | if ((iip->ili_fields & brootflag[whichfork]) && | |
596 | (ifp->if_broot_bytes > 0)) { | |
597 | ASSERT(ifp->if_broot != NULL); | |
2f8e9b0a | 598 | ASSERT(xfs_bmap_bmdr_space(ifp->if_broot) <= |
eae3e30d | 599 | xfs_inode_fork_size(ip, whichfork)); |
5d90ab5a DC |
600 | xfs_bmbt_to_bmdr(mp, ifp->if_broot, ifp->if_broot_bytes, |
601 | (xfs_bmdr_block_t *)cp, | |
602 | XFS_DFORK_SIZE(dip, mp, whichfork)); | |
603 | } | |
604 | break; | |
605 | ||
606 | case XFS_DINODE_FMT_DEV: | |
607 | if (iip->ili_fields & XFS_ILOG_DEV) { | |
608 | ASSERT(whichfork == XFS_DATA_FORK); | |
dc9b1f58 CH |
609 | xfs_dinode_put_rdev(dip, |
610 | linux_to_xfs_dev_t(VFS_I(ip)->i_rdev)); | |
5d90ab5a DC |
611 | } |
612 | break; | |
613 | ||
64c60f52 DW |
614 | case XFS_DINODE_FMT_META_BTREE: |
615 | ASSERT(whichfork == XFS_DATA_FORK); | |
616 | ||
617 | if (!(iip->ili_fields & brootflag[whichfork])) | |
618 | break; | |
619 | ||
620 | switch (ip->i_metatype) { | |
5a9a1f89 | 621 | case XFS_METAFILE_RTRMAP: |
b8d1b5ca | 622 | xfs_iflush_rtrmap(ip, dip); |
5a9a1f89 | 623 | break; |
0f2ef731 | 624 | case XFS_METAFILE_RTREFCOUNT: |
b81e004c | 625 | xfs_iflush_rtrefcount(ip, dip); |
0f2ef731 | 626 | break; |
64c60f52 DW |
627 | default: |
628 | ASSERT(0); | |
629 | break; | |
630 | } | |
631 | break; | |
632 | ||
5d90ab5a DC |
633 | default: |
634 | ASSERT(0); | |
635 | break; | |
636 | } | |
637 | } | |
638 | ||
cb8a004a DW |
639 | /* Convert bmap state flags to an inode fork. */ |
640 | struct xfs_ifork * | |
641 | xfs_iext_state_to_fork( | |
642 | struct xfs_inode *ip, | |
643 | int state) | |
644 | { | |
645 | if (state & BMAP_COWFORK) | |
646 | return ip->i_cowfp; | |
647 | else if (state & BMAP_ATTRFORK) | |
7ff5f1ed | 648 | return &ip->i_af; |
cb8a004a DW |
649 | return &ip->i_df; |
650 | } | |
651 | ||
cb8a004a DW |
652 | /* |
653 | * Initialize an inode's copy-on-write fork. | |
654 | */ | |
655 | void | |
656 | xfs_ifork_init_cow( | |
657 | struct xfs_inode *ip) | |
658 | { | |
659 | if (ip->i_cowfp) | |
660 | return; | |
661 | ||
2e1394fc | 662 | ip->i_cowfp = kmem_cache_zalloc(xfs_ifork_cache, |
c3bf5a1f | 663 | GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOFAIL); |
d967a68d | 664 | ip->i_cowfp->if_format = XFS_DINODE_FMT_EXTENTS; |
cb8a004a | 665 | } |
20e882d4 | 666 | |
20e882d4 | 667 | /* Verify the inline contents of the data fork of an inode. */ |
318d12fd CH |
668 | int |
669 | xfs_ifork_verify_local_data( | |
1fecabf9 | 670 | struct xfs_inode *ip) |
20e882d4 | 671 | { |
318d12fd | 672 | xfs_failaddr_t fa = NULL; |
20e882d4 | 673 | |
20e882d4 | 674 | switch (VFS_I(ip)->i_mode & S_IFMT) { |
7c5d4f92 DW |
675 | case S_IFDIR: { |
676 | struct xfs_mount *mp = ip->i_mount; | |
677 | struct xfs_ifork *ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK); | |
f8146197 | 678 | struct xfs_dir2_sf_hdr *sfp = ifp->if_data; |
7c5d4f92 | 679 | |
7c5d4f92 | 680 | fa = xfs_dir2_sf_verify(mp, sfp, ifp->if_bytes); |
318d12fd | 681 | break; |
7c5d4f92 DW |
682 | } |
683 | case S_IFLNK: { | |
684 | struct xfs_ifork *ifp = xfs_ifork_ptr(ip, XFS_DATA_FORK); | |
685 | ||
f8146197 | 686 | fa = xfs_symlink_shortform_verify(ifp->if_data, ifp->if_bytes); |
318d12fd | 687 | break; |
7c5d4f92 | 688 | } |
20e882d4 | 689 | default: |
318d12fd | 690 | break; |
20e882d4 | 691 | } |
318d12fd CH |
692 | |
693 | if (fa) { | |
694 | xfs_inode_verifier_error(ip, -EFSCORRUPTED, "data fork", | |
f8146197 | 695 | ip->i_df.if_data, ip->i_df.if_bytes, fa); |
318d12fd CH |
696 | return -EFSCORRUPTED; |
697 | } | |
698 | ||
699 | return 0; | |
20e882d4 DW |
700 | } |
701 | ||
702 | /* Verify the inline contents of the attr fork of an inode. */ | |
318d12fd CH |
703 | int |
704 | xfs_ifork_verify_local_attr( | |
1fecabf9 | 705 | struct xfs_inode *ip) |
20e882d4 | 706 | { |
7ff5f1ed | 707 | struct xfs_ifork *ifp = &ip->i_af; |
318d12fd CH |
708 | xfs_failaddr_t fa; |
709 | ||
7c5d4f92 | 710 | if (!xfs_inode_has_attr_fork(ip)) { |
318d12fd | 711 | fa = __this_address; |
7c5d4f92 | 712 | } else { |
f8146197 | 713 | struct xfs_ifork *ifp = &ip->i_af; |
7c5d4f92 | 714 | |
f8146197 CH |
715 | ASSERT(ifp->if_format == XFS_DINODE_FMT_LOCAL); |
716 | fa = xfs_attr_shortform_verify(ifp->if_data, ifp->if_bytes); | |
7c5d4f92 | 717 | } |
318d12fd CH |
718 | if (fa) { |
719 | xfs_inode_verifier_error(ip, -EFSCORRUPTED, "attr fork", | |
f8146197 | 720 | ifp->if_data, ifp->if_bytes, fa); |
318d12fd CH |
721 | return -EFSCORRUPTED; |
722 | } | |
723 | ||
724 | return 0; | |
20e882d4 | 725 | } |
d629a2d9 | 726 | |
7163cfcd CH |
727 | /* |
728 | * Check if the inode fork supports adding nr_to_add more extents. | |
729 | * | |
730 | * If it doesn't but we can upgrade it to large extent counters, do the upgrade. | |
731 | * If we can't upgrade or are already using big counters but still can't fit the | |
732 | * additional extents, return -EFBIG. | |
733 | */ | |
d629a2d9 | 734 | int |
7163cfcd CH |
735 | xfs_iext_count_extend( |
736 | struct xfs_trans *tp, | |
d629a2d9 CB |
737 | struct xfs_inode *ip, |
738 | int whichfork, | |
7163cfcd | 739 | uint nr_to_add) |
d629a2d9 | 740 | { |
7163cfcd CH |
741 | struct xfs_mount *mp = ip->i_mount; |
742 | bool has_large = | |
743 | xfs_inode_has_large_extent_counts(ip); | |
722e81c1 | 744 | struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); |
d629a2d9 CB |
745 | uint64_t nr_exts; |
746 | ||
7163cfcd CH |
747 | ASSERT(nr_to_add <= XFS_MAX_EXTCNT_UPGRADE_NR); |
748 | ||
d629a2d9 CB |
749 | if (whichfork == XFS_COW_FORK) |
750 | return 0; | |
751 | ||
7163cfcd | 752 | /* no point in upgrading if if_nextents overflows */ |
d629a2d9 | 753 | nr_exts = ifp->if_nextents + nr_to_add; |
7163cfcd | 754 | if (nr_exts < ifp->if_nextents) |
d629a2d9 CB |
755 | return -EFBIG; |
756 | ||
7163cfcd CH |
757 | if (XFS_TEST_ERROR(false, mp, XFS_ERRTAG_REDUCE_MAX_IEXTENTS) && |
758 | nr_exts > 10) | |
fcba1629 CB |
759 | return -EFBIG; |
760 | ||
7163cfcd CH |
761 | if (nr_exts > xfs_iext_max_nextents(has_large, whichfork)) { |
762 | if (has_large || !xfs_has_large_extent_counts(mp)) | |
763 | return -EFBIG; | |
764 | ip->i_diflags2 |= XFS_DIFLAG2_NREXT64; | |
765 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | |
766 | } | |
fcba1629 CB |
767 | return 0; |
768 | } | |
36a93334 DW |
769 | |
770 | /* Decide if a file mapping is on the realtime device or not. */ | |
771 | bool | |
772 | xfs_ifork_is_realtime( | |
773 | struct xfs_inode *ip, | |
774 | int whichfork) | |
775 | { | |
776 | return XFS_IS_REALTIME_INODE(ip) && whichfork != XFS_ATTR_FORK; | |
777 | } |