This source file includes following definitions.
- xfs_iformat_fork
- xfs_init_local_fork
- xfs_iformat_local
- xfs_iformat_extents
- xfs_iformat_btree
- xfs_iroot_realloc
- xfs_idata_realloc
- xfs_idestroy_fork
- xfs_iextents_copy
- xfs_iflush_fork
- xfs_iext_state_to_fork
- xfs_ifork_init_cow
- xfs_ifork_verify_data
- xfs_ifork_verify_attr
1
2
3
4
5
6
7 #include "xfs.h"
8 #include "xfs_fs.h"
9 #include "xfs_shared.h"
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"
16 #include "xfs_inode_item.h"
17 #include "xfs_btree.h"
18 #include "xfs_bmap_btree.h"
19 #include "xfs_bmap.h"
20 #include "xfs_error.h"
21 #include "xfs_trace.h"
22 #include "xfs_da_format.h"
23 #include "xfs_da_btree.h"
24 #include "xfs_dir2_priv.h"
25 #include "xfs_attr_leaf.h"
26
27 kmem_zone_t *xfs_ifork_zone;
28
29 STATIC int xfs_iformat_local(xfs_inode_t *, xfs_dinode_t *, int, int);
30 STATIC int xfs_iformat_extents(xfs_inode_t *, xfs_dinode_t *, int);
31 STATIC int xfs_iformat_btree(xfs_inode_t *, xfs_dinode_t *, int);
32
33
34
35
36
37
38
39
40
41
42 int
43 xfs_iformat_fork(
44 struct xfs_inode *ip,
45 struct xfs_dinode *dip)
46 {
47 struct inode *inode = VFS_I(ip);
48 struct xfs_attr_shortform *atp;
49 int size;
50 int error = 0;
51 xfs_fsize_t di_size;
52
53 switch (inode->i_mode & S_IFMT) {
54 case S_IFIFO:
55 case S_IFCHR:
56 case S_IFBLK:
57 case S_IFSOCK:
58 ip->i_d.di_size = 0;
59 inode->i_rdev = xfs_to_linux_dev_t(xfs_dinode_get_rdev(dip));
60 break;
61
62 case S_IFREG:
63 case S_IFLNK:
64 case S_IFDIR:
65 switch (dip->di_format) {
66 case XFS_DINODE_FMT_LOCAL:
67 di_size = be64_to_cpu(dip->di_size);
68 size = (int)di_size;
69 error = xfs_iformat_local(ip, dip, XFS_DATA_FORK, size);
70 break;
71 case XFS_DINODE_FMT_EXTENTS:
72 error = xfs_iformat_extents(ip, dip, XFS_DATA_FORK);
73 break;
74 case XFS_DINODE_FMT_BTREE:
75 error = xfs_iformat_btree(ip, dip, XFS_DATA_FORK);
76 break;
77 default:
78 return -EFSCORRUPTED;
79 }
80 break;
81
82 default:
83 return -EFSCORRUPTED;
84 }
85 if (error)
86 return error;
87
88 if (xfs_is_reflink_inode(ip)) {
89 ASSERT(ip->i_cowfp == NULL);
90 xfs_ifork_init_cow(ip);
91 }
92
93 if (!XFS_DFORK_Q(dip))
94 return 0;
95
96 ASSERT(ip->i_afp == NULL);
97 ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_NOFS);
98
99 switch (dip->di_aformat) {
100 case XFS_DINODE_FMT_LOCAL:
101 atp = (xfs_attr_shortform_t *)XFS_DFORK_APTR(dip);
102 size = be16_to_cpu(atp->hdr.totsize);
103
104 error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK, size);
105 break;
106 case XFS_DINODE_FMT_EXTENTS:
107 error = xfs_iformat_extents(ip, dip, XFS_ATTR_FORK);
108 break;
109 case XFS_DINODE_FMT_BTREE:
110 error = xfs_iformat_btree(ip, dip, XFS_ATTR_FORK);
111 break;
112 default:
113 error = -EFSCORRUPTED;
114 break;
115 }
116 if (error) {
117 kmem_zone_free(xfs_ifork_zone, ip->i_afp);
118 ip->i_afp = NULL;
119 if (ip->i_cowfp)
120 kmem_zone_free(xfs_ifork_zone, ip->i_cowfp);
121 ip->i_cowfp = NULL;
122 xfs_idestroy_fork(ip, XFS_DATA_FORK);
123 }
124 return error;
125 }
126
127 void
128 xfs_init_local_fork(
129 struct xfs_inode *ip,
130 int whichfork,
131 const void *data,
132 int size)
133 {
134 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
135 int mem_size = size, real_size = 0;
136 bool zero_terminate;
137
138
139
140
141
142
143
144 zero_terminate = S_ISLNK(VFS_I(ip)->i_mode);
145 if (zero_terminate)
146 mem_size++;
147
148 if (size) {
149 real_size = roundup(mem_size, 4);
150 ifp->if_u1.if_data = kmem_alloc(real_size, KM_NOFS);
151 memcpy(ifp->if_u1.if_data, data, size);
152 if (zero_terminate)
153 ifp->if_u1.if_data[size] = '\0';
154 } else {
155 ifp->if_u1.if_data = NULL;
156 }
157
158 ifp->if_bytes = size;
159 ifp->if_flags &= ~(XFS_IFEXTENTS | XFS_IFBROOT);
160 ifp->if_flags |= XFS_IFINLINE;
161 }
162
163
164
165
166 STATIC int
167 xfs_iformat_local(
168 xfs_inode_t *ip,
169 xfs_dinode_t *dip,
170 int whichfork,
171 int size)
172 {
173
174
175
176
177
178 if (unlikely(size > XFS_DFORK_SIZE(dip, ip->i_mount, whichfork))) {
179 xfs_warn(ip->i_mount,
180 "corrupt inode %Lu (bad size %d for local fork, size = %d).",
181 (unsigned long long) ip->i_ino, size,
182 XFS_DFORK_SIZE(dip, ip->i_mount, whichfork));
183 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
184 "xfs_iformat_local", dip, sizeof(*dip),
185 __this_address);
186 return -EFSCORRUPTED;
187 }
188
189 xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size);
190 return 0;
191 }
192
193
194
195
196
197 STATIC int
198 xfs_iformat_extents(
199 struct xfs_inode *ip,
200 struct xfs_dinode *dip,
201 int whichfork)
202 {
203 struct xfs_mount *mp = ip->i_mount;
204 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
205 int state = xfs_bmap_fork_to_state(whichfork);
206 int nex = XFS_DFORK_NEXTENTS(dip, whichfork);
207 int size = nex * sizeof(xfs_bmbt_rec_t);
208 struct xfs_iext_cursor icur;
209 struct xfs_bmbt_rec *dp;
210 struct xfs_bmbt_irec new;
211 int i;
212
213
214
215
216
217 if (unlikely(size < 0 || size > XFS_DFORK_SIZE(dip, mp, whichfork))) {
218 xfs_warn(ip->i_mount, "corrupt inode %Lu ((a)extents = %d).",
219 (unsigned long long) ip->i_ino, nex);
220 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
221 "xfs_iformat_extents(1)", dip, sizeof(*dip),
222 __this_address);
223 return -EFSCORRUPTED;
224 }
225
226 ifp->if_bytes = 0;
227 ifp->if_u1.if_root = NULL;
228 ifp->if_height = 0;
229 if (size) {
230 dp = (xfs_bmbt_rec_t *) XFS_DFORK_PTR(dip, whichfork);
231
232 xfs_iext_first(ifp, &icur);
233 for (i = 0; i < nex; i++, dp++) {
234 xfs_failaddr_t fa;
235
236 xfs_bmbt_disk_get_all(dp, &new);
237 fa = xfs_bmap_validate_extent(ip, whichfork, &new);
238 if (fa) {
239 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
240 "xfs_iformat_extents(2)",
241 dp, sizeof(*dp), fa);
242 return -EFSCORRUPTED;
243 }
244
245 xfs_iext_insert(ip, &icur, &new, state);
246 trace_xfs_read_extent(ip, &icur, state, _THIS_IP_);
247 xfs_iext_next(ifp, &icur);
248 }
249 }
250 ifp->if_flags |= XFS_IFEXTENTS;
251 return 0;
252 }
253
254
255
256
257
258
259
260
261
262 STATIC int
263 xfs_iformat_btree(
264 xfs_inode_t *ip,
265 xfs_dinode_t *dip,
266 int whichfork)
267 {
268 struct xfs_mount *mp = ip->i_mount;
269 xfs_bmdr_block_t *dfp;
270 struct xfs_ifork *ifp;
271
272 int nrecs;
273 int size;
274 int level;
275
276 ifp = XFS_IFORK_PTR(ip, whichfork);
277 dfp = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork);
278 size = XFS_BMAP_BROOT_SPACE(mp, dfp);
279 nrecs = be16_to_cpu(dfp->bb_numrecs);
280 level = be16_to_cpu(dfp->bb_level);
281
282
283
284
285
286
287
288
289 if (unlikely(XFS_IFORK_NEXTENTS(ip, whichfork) <=
290 XFS_IFORK_MAXEXT(ip, whichfork) ||
291 nrecs == 0 ||
292 XFS_BMDR_SPACE_CALC(nrecs) >
293 XFS_DFORK_SIZE(dip, mp, whichfork) ||
294 XFS_IFORK_NEXTENTS(ip, whichfork) > ip->i_d.di_nblocks) ||
295 level == 0 || level > XFS_BTREE_MAXLEVELS) {
296 xfs_warn(mp, "corrupt inode %Lu (btree).",
297 (unsigned long long) ip->i_ino);
298 xfs_inode_verifier_error(ip, -EFSCORRUPTED,
299 "xfs_iformat_btree", dfp, size,
300 __this_address);
301 return -EFSCORRUPTED;
302 }
303
304 ifp->if_broot_bytes = size;
305 ifp->if_broot = kmem_alloc(size, KM_NOFS);
306 ASSERT(ifp->if_broot != NULL);
307
308
309
310
311 xfs_bmdr_to_bmbt(ip, dfp, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork),
312 ifp->if_broot, size);
313 ifp->if_flags &= ~XFS_IFEXTENTS;
314 ifp->if_flags |= XFS_IFBROOT;
315
316 ifp->if_bytes = 0;
317 ifp->if_u1.if_root = NULL;
318 ifp->if_height = 0;
319 return 0;
320 }
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340 void
341 xfs_iroot_realloc(
342 xfs_inode_t *ip,
343 int rec_diff,
344 int whichfork)
345 {
346 struct xfs_mount *mp = ip->i_mount;
347 int cur_max;
348 struct xfs_ifork *ifp;
349 struct xfs_btree_block *new_broot;
350 int new_max;
351 size_t new_size;
352 char *np;
353 char *op;
354
355
356
357
358 if (rec_diff == 0) {
359 return;
360 }
361
362 ifp = XFS_IFORK_PTR(ip, whichfork);
363 if (rec_diff > 0) {
364
365
366
367
368 if (ifp->if_broot_bytes == 0) {
369 new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, rec_diff);
370 ifp->if_broot = kmem_alloc(new_size, KM_NOFS);
371 ifp->if_broot_bytes = (int)new_size;
372 return;
373 }
374
375
376
377
378
379
380
381 cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0);
382 new_max = cur_max + rec_diff;
383 new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
384 ifp->if_broot = kmem_realloc(ifp->if_broot, new_size,
385 KM_NOFS);
386 op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
387 ifp->if_broot_bytes);
388 np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
389 (int)new_size);
390 ifp->if_broot_bytes = (int)new_size;
391 ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
392 XFS_IFORK_SIZE(ip, whichfork));
393 memmove(np, op, cur_max * (uint)sizeof(xfs_fsblock_t));
394 return;
395 }
396
397
398
399
400
401
402 ASSERT((ifp->if_broot != NULL) && (ifp->if_broot_bytes > 0));
403 cur_max = xfs_bmbt_maxrecs(mp, ifp->if_broot_bytes, 0);
404 new_max = cur_max + rec_diff;
405 ASSERT(new_max >= 0);
406 if (new_max > 0)
407 new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max);
408 else
409 new_size = 0;
410 if (new_size > 0) {
411 new_broot = kmem_alloc(new_size, KM_NOFS);
412
413
414
415 memcpy(new_broot, ifp->if_broot,
416 XFS_BMBT_BLOCK_LEN(ip->i_mount));
417 } else {
418 new_broot = NULL;
419 ifp->if_flags &= ~XFS_IFBROOT;
420 }
421
422
423
424
425 if (new_max > 0) {
426
427
428
429 op = (char *)XFS_BMBT_REC_ADDR(mp, ifp->if_broot, 1);
430 np = (char *)XFS_BMBT_REC_ADDR(mp, new_broot, 1);
431 memcpy(np, op, new_max * (uint)sizeof(xfs_bmbt_rec_t));
432
433
434
435
436 op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1,
437 ifp->if_broot_bytes);
438 np = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, new_broot, 1,
439 (int)new_size);
440 memcpy(np, op, new_max * (uint)sizeof(xfs_fsblock_t));
441 }
442 kmem_free(ifp->if_broot);
443 ifp->if_broot = new_broot;
444 ifp->if_broot_bytes = (int)new_size;
445 if (ifp->if_broot)
446 ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
447 XFS_IFORK_SIZE(ip, whichfork));
448 return;
449 }
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467 void
468 xfs_idata_realloc(
469 struct xfs_inode *ip,
470 int byte_diff,
471 int whichfork)
472 {
473 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
474 int new_size = (int)ifp->if_bytes + byte_diff;
475
476 ASSERT(new_size >= 0);
477 ASSERT(new_size <= XFS_IFORK_SIZE(ip, whichfork));
478
479 if (byte_diff == 0)
480 return;
481
482 if (new_size == 0) {
483 kmem_free(ifp->if_u1.if_data);
484 ifp->if_u1.if_data = NULL;
485 ifp->if_bytes = 0;
486 return;
487 }
488
489
490
491
492
493
494 ifp->if_u1.if_data = kmem_realloc(ifp->if_u1.if_data,
495 roundup(new_size, 4), KM_NOFS);
496 ifp->if_bytes = new_size;
497 }
498
499 void
500 xfs_idestroy_fork(
501 xfs_inode_t *ip,
502 int whichfork)
503 {
504 struct xfs_ifork *ifp;
505
506 ifp = XFS_IFORK_PTR(ip, whichfork);
507 if (ifp->if_broot != NULL) {
508 kmem_free(ifp->if_broot);
509 ifp->if_broot = NULL;
510 }
511
512
513
514
515
516
517
518 if (XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL) {
519 if (ifp->if_u1.if_data != NULL) {
520 kmem_free(ifp->if_u1.if_data);
521 ifp->if_u1.if_data = NULL;
522 }
523 } else if ((ifp->if_flags & XFS_IFEXTENTS) && ifp->if_height) {
524 xfs_iext_destroy(ifp);
525 }
526
527 if (whichfork == XFS_ATTR_FORK) {
528 kmem_zone_free(xfs_ifork_zone, ip->i_afp);
529 ip->i_afp = NULL;
530 } else if (whichfork == XFS_COW_FORK) {
531 kmem_zone_free(xfs_ifork_zone, ip->i_cowfp);
532 ip->i_cowfp = NULL;
533 }
534 }
535
536
537
538
539
540
541
542
543
544
545 int
546 xfs_iextents_copy(
547 struct xfs_inode *ip,
548 struct xfs_bmbt_rec *dp,
549 int whichfork)
550 {
551 int state = xfs_bmap_fork_to_state(whichfork);
552 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
553 struct xfs_iext_cursor icur;
554 struct xfs_bmbt_irec rec;
555 int copied = 0;
556
557 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL | XFS_ILOCK_SHARED));
558 ASSERT(ifp->if_bytes > 0);
559
560 for_each_xfs_iext(ifp, &icur, &rec) {
561 if (isnullstartblock(rec.br_startblock))
562 continue;
563 ASSERT(xfs_bmap_validate_extent(ip, whichfork, &rec) == NULL);
564 xfs_bmbt_disk_set_all(dp, &rec);
565 trace_xfs_write_extent(ip, &icur, state, _RET_IP_);
566 copied += sizeof(struct xfs_bmbt_rec);
567 dp++;
568 }
569
570 ASSERT(copied > 0);
571 ASSERT(copied <= ifp->if_bytes);
572 return copied;
573 }
574
575
576
577
578
579
580
581
582
583
584
585 void
586 xfs_iflush_fork(
587 xfs_inode_t *ip,
588 xfs_dinode_t *dip,
589 xfs_inode_log_item_t *iip,
590 int whichfork)
591 {
592 char *cp;
593 struct xfs_ifork *ifp;
594 xfs_mount_t *mp;
595 static const short brootflag[2] =
596 { XFS_ILOG_DBROOT, XFS_ILOG_ABROOT };
597 static const short dataflag[2] =
598 { XFS_ILOG_DDATA, XFS_ILOG_ADATA };
599 static const short extflag[2] =
600 { XFS_ILOG_DEXT, XFS_ILOG_AEXT };
601
602 if (!iip)
603 return;
604 ifp = XFS_IFORK_PTR(ip, whichfork);
605
606
607
608
609 if (!ifp) {
610 ASSERT(whichfork == XFS_ATTR_FORK);
611 return;
612 }
613 cp = XFS_DFORK_PTR(dip, whichfork);
614 mp = ip->i_mount;
615 switch (XFS_IFORK_FORMAT(ip, whichfork)) {
616 case XFS_DINODE_FMT_LOCAL:
617 if ((iip->ili_fields & dataflag[whichfork]) &&
618 (ifp->if_bytes > 0)) {
619 ASSERT(ifp->if_u1.if_data != NULL);
620 ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork));
621 memcpy(cp, ifp->if_u1.if_data, ifp->if_bytes);
622 }
623 break;
624
625 case XFS_DINODE_FMT_EXTENTS:
626 ASSERT((ifp->if_flags & XFS_IFEXTENTS) ||
627 !(iip->ili_fields & extflag[whichfork]));
628 if ((iip->ili_fields & extflag[whichfork]) &&
629 (ifp->if_bytes > 0)) {
630 ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) > 0);
631 (void)xfs_iextents_copy(ip, (xfs_bmbt_rec_t *)cp,
632 whichfork);
633 }
634 break;
635
636 case XFS_DINODE_FMT_BTREE:
637 if ((iip->ili_fields & brootflag[whichfork]) &&
638 (ifp->if_broot_bytes > 0)) {
639 ASSERT(ifp->if_broot != NULL);
640 ASSERT(XFS_BMAP_BMDR_SPACE(ifp->if_broot) <=
641 XFS_IFORK_SIZE(ip, whichfork));
642 xfs_bmbt_to_bmdr(mp, ifp->if_broot, ifp->if_broot_bytes,
643 (xfs_bmdr_block_t *)cp,
644 XFS_DFORK_SIZE(dip, mp, whichfork));
645 }
646 break;
647
648 case XFS_DINODE_FMT_DEV:
649 if (iip->ili_fields & XFS_ILOG_DEV) {
650 ASSERT(whichfork == XFS_DATA_FORK);
651 xfs_dinode_put_rdev(dip,
652 linux_to_xfs_dev_t(VFS_I(ip)->i_rdev));
653 }
654 break;
655
656 default:
657 ASSERT(0);
658 break;
659 }
660 }
661
662
663 struct xfs_ifork *
664 xfs_iext_state_to_fork(
665 struct xfs_inode *ip,
666 int state)
667 {
668 if (state & BMAP_COWFORK)
669 return ip->i_cowfp;
670 else if (state & BMAP_ATTRFORK)
671 return ip->i_afp;
672 return &ip->i_df;
673 }
674
675
676
677
678 void
679 xfs_ifork_init_cow(
680 struct xfs_inode *ip)
681 {
682 if (ip->i_cowfp)
683 return;
684
685 ip->i_cowfp = kmem_zone_zalloc(xfs_ifork_zone,
686 KM_NOFS);
687 ip->i_cowfp->if_flags = XFS_IFEXTENTS;
688 ip->i_cformat = XFS_DINODE_FMT_EXTENTS;
689 ip->i_cnextents = 0;
690 }
691
692
693 struct xfs_ifork_ops xfs_default_ifork_ops = {
694 .verify_attr = xfs_attr_shortform_verify,
695 .verify_dir = xfs_dir2_sf_verify,
696 .verify_symlink = xfs_symlink_shortform_verify,
697 };
698
699
700 xfs_failaddr_t
701 xfs_ifork_verify_data(
702 struct xfs_inode *ip,
703 struct xfs_ifork_ops *ops)
704 {
705
706 if (ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
707 return NULL;
708
709
710 switch (VFS_I(ip)->i_mode & S_IFMT) {
711 case S_IFDIR:
712 return ops->verify_dir(ip);
713 case S_IFLNK:
714 return ops->verify_symlink(ip);
715 default:
716 return NULL;
717 }
718 }
719
720
721 xfs_failaddr_t
722 xfs_ifork_verify_attr(
723 struct xfs_inode *ip,
724 struct xfs_ifork_ops *ops)
725 {
726
727 if (ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)
728 return NULL;
729 if (!XFS_IFORK_PTR(ip, XFS_ATTR_FORK))
730 return __this_address;
731 return ops->verify_attr(ip);
732 }