This source file includes following definitions.
- xfs_reflink_find_shared
- xfs_reflink_trim_around_shared
- xfs_inode_need_cow
- xfs_reflink_convert_cow_locked
- xfs_reflink_convert_cow
- xfs_find_trim_cow_extent
- xfs_reflink_allocate_cow
- xfs_reflink_cancel_cow_blocks
- xfs_reflink_cancel_cow_range
- xfs_reflink_end_cow_extent
- xfs_reflink_end_cow
- xfs_reflink_recover_cow
- xfs_reflink_set_inode_flag
- xfs_reflink_update_dest
- xfs_reflink_ag_has_free_space
- xfs_reflink_remap_extent
- xfs_reflink_remap_blocks
- xfs_iolock_two_inodes_and_break_layout
- xfs_reflink_remap_unlock
- xfs_reflink_zero_posteof
- xfs_reflink_remap_prep
- xfs_reflink_dirty_extents
- xfs_reflink_inode_has_shared_extents
- xfs_reflink_clear_inode_flag
- xfs_reflink_try_clear_inode_flag
- xfs_reflink_unshare
1
2
3
4
5
6 #include "xfs.h"
7 #include "xfs_fs.h"
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_log_format.h"
11 #include "xfs_trans_resv.h"
12 #include "xfs_mount.h"
13 #include "xfs_defer.h"
14 #include "xfs_inode.h"
15 #include "xfs_trans.h"
16 #include "xfs_bmap.h"
17 #include "xfs_bmap_util.h"
18 #include "xfs_trace.h"
19 #include "xfs_icache.h"
20 #include "xfs_btree.h"
21 #include "xfs_refcount_btree.h"
22 #include "xfs_refcount.h"
23 #include "xfs_bmap_btree.h"
24 #include "xfs_trans_space.h"
25 #include "xfs_bit.h"
26 #include "xfs_alloc.h"
27 #include "xfs_quota.h"
28 #include "xfs_reflink.h"
29 #include "xfs_iomap.h"
30 #include "xfs_sb.h"
31 #include "xfs_ag_resv.h"
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128 int
129 xfs_reflink_find_shared(
130 struct xfs_mount *mp,
131 struct xfs_trans *tp,
132 xfs_agnumber_t agno,
133 xfs_agblock_t agbno,
134 xfs_extlen_t aglen,
135 xfs_agblock_t *fbno,
136 xfs_extlen_t *flen,
137 bool find_end_of_shared)
138 {
139 struct xfs_buf *agbp;
140 struct xfs_btree_cur *cur;
141 int error;
142
143 error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp);
144 if (error)
145 return error;
146 if (!agbp)
147 return -ENOMEM;
148
149 cur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno);
150
151 error = xfs_refcount_find_shared(cur, agbno, aglen, fbno, flen,
152 find_end_of_shared);
153
154 xfs_btree_del_cursor(cur, error);
155
156 xfs_trans_brelse(tp, agbp);
157 return error;
158 }
159
160
161
162
163
164
165
166
167
168
169
170 int
171 xfs_reflink_trim_around_shared(
172 struct xfs_inode *ip,
173 struct xfs_bmbt_irec *irec,
174 bool *shared)
175 {
176 xfs_agnumber_t agno;
177 xfs_agblock_t agbno;
178 xfs_extlen_t aglen;
179 xfs_agblock_t fbno;
180 xfs_extlen_t flen;
181 int error = 0;
182
183
184 if (!xfs_is_cow_inode(ip) || !xfs_bmap_is_real_extent(irec)) {
185 *shared = false;
186 return 0;
187 }
188
189 trace_xfs_reflink_trim_around_shared(ip, irec);
190
191 agno = XFS_FSB_TO_AGNO(ip->i_mount, irec->br_startblock);
192 agbno = XFS_FSB_TO_AGBNO(ip->i_mount, irec->br_startblock);
193 aglen = irec->br_blockcount;
194
195 error = xfs_reflink_find_shared(ip->i_mount, NULL, agno, agbno,
196 aglen, &fbno, &flen, true);
197 if (error)
198 return error;
199
200 *shared = false;
201 if (fbno == NULLAGBLOCK) {
202
203 return 0;
204 } else if (fbno == agbno) {
205
206
207
208
209
210
211 irec->br_blockcount = flen;
212 *shared = true;
213 return 0;
214 } else {
215
216
217
218
219
220
221 irec->br_blockcount = fbno - agbno;
222 return 0;
223 }
224 }
225
226 bool
227 xfs_inode_need_cow(
228 struct xfs_inode *ip,
229 struct xfs_bmbt_irec *imap,
230 bool *shared)
231 {
232
233 if (xfs_is_always_cow_inode(ip) &&
234 !isnullstartblock(imap->br_startblock)) {
235 *shared = true;
236 return 0;
237 }
238
239
240 return xfs_reflink_trim_around_shared(ip, imap, shared);
241 }
242
243 static int
244 xfs_reflink_convert_cow_locked(
245 struct xfs_inode *ip,
246 xfs_fileoff_t offset_fsb,
247 xfs_filblks_t count_fsb)
248 {
249 struct xfs_iext_cursor icur;
250 struct xfs_bmbt_irec got;
251 struct xfs_btree_cur *dummy_cur = NULL;
252 int dummy_logflags;
253 int error = 0;
254
255 if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &got))
256 return 0;
257
258 do {
259 if (got.br_startoff >= offset_fsb + count_fsb)
260 break;
261 if (got.br_state == XFS_EXT_NORM)
262 continue;
263 if (WARN_ON_ONCE(isnullstartblock(got.br_startblock)))
264 return -EIO;
265
266 xfs_trim_extent(&got, offset_fsb, count_fsb);
267 if (!got.br_blockcount)
268 continue;
269
270 got.br_state = XFS_EXT_NORM;
271 error = xfs_bmap_add_extent_unwritten_real(NULL, ip,
272 XFS_COW_FORK, &icur, &dummy_cur, &got,
273 &dummy_logflags);
274 if (error)
275 return error;
276 } while (xfs_iext_next_extent(ip->i_cowfp, &icur, &got));
277
278 return error;
279 }
280
281
282 int
283 xfs_reflink_convert_cow(
284 struct xfs_inode *ip,
285 xfs_off_t offset,
286 xfs_off_t count)
287 {
288 struct xfs_mount *mp = ip->i_mount;
289 xfs_fileoff_t offset_fsb = XFS_B_TO_FSBT(mp, offset);
290 xfs_fileoff_t end_fsb = XFS_B_TO_FSB(mp, offset + count);
291 xfs_filblks_t count_fsb = end_fsb - offset_fsb;
292 int error;
293
294 ASSERT(count != 0);
295
296 xfs_ilock(ip, XFS_ILOCK_EXCL);
297 error = xfs_reflink_convert_cow_locked(ip, offset_fsb, count_fsb);
298 xfs_iunlock(ip, XFS_ILOCK_EXCL);
299 return error;
300 }
301
302
303
304
305
306
307 static int
308 xfs_find_trim_cow_extent(
309 struct xfs_inode *ip,
310 struct xfs_bmbt_irec *imap,
311 bool *shared,
312 bool *found)
313 {
314 xfs_fileoff_t offset_fsb = imap->br_startoff;
315 xfs_filblks_t count_fsb = imap->br_blockcount;
316 struct xfs_iext_cursor icur;
317 struct xfs_bmbt_irec got;
318
319 *found = false;
320
321
322
323
324
325 if (!xfs_iext_lookup_extent(ip, ip->i_cowfp, offset_fsb, &icur, &got))
326 got.br_startoff = offset_fsb + count_fsb;
327 if (got.br_startoff > offset_fsb) {
328 xfs_trim_extent(imap, imap->br_startoff,
329 got.br_startoff - imap->br_startoff);
330 return xfs_inode_need_cow(ip, imap, shared);
331 }
332
333 *shared = true;
334 if (isnullstartblock(got.br_startblock)) {
335 xfs_trim_extent(imap, got.br_startoff, got.br_blockcount);
336 return 0;
337 }
338
339
340 xfs_trim_extent(&got, offset_fsb, count_fsb);
341 *imap = got;
342 *found = true;
343 return 0;
344 }
345
346
347 int
348 xfs_reflink_allocate_cow(
349 struct xfs_inode *ip,
350 struct xfs_bmbt_irec *imap,
351 bool *shared,
352 uint *lockmode,
353 bool convert_now)
354 {
355 struct xfs_mount *mp = ip->i_mount;
356 xfs_fileoff_t offset_fsb = imap->br_startoff;
357 xfs_filblks_t count_fsb = imap->br_blockcount;
358 struct xfs_trans *tp;
359 int nimaps, error = 0;
360 bool found;
361 xfs_filblks_t resaligned;
362 xfs_extlen_t resblks = 0;
363
364 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
365 if (!ip->i_cowfp) {
366 ASSERT(!xfs_is_reflink_inode(ip));
367 xfs_ifork_init_cow(ip);
368 }
369
370 error = xfs_find_trim_cow_extent(ip, imap, shared, &found);
371 if (error || !*shared)
372 return error;
373 if (found)
374 goto convert;
375
376 resaligned = xfs_aligned_fsb_count(imap->br_startoff,
377 imap->br_blockcount, xfs_get_cowextsz_hint(ip));
378 resblks = XFS_DIOSTRAT_SPACE_RES(mp, resaligned);
379
380 xfs_iunlock(ip, *lockmode);
381 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp);
382 *lockmode = XFS_ILOCK_EXCL;
383 xfs_ilock(ip, *lockmode);
384
385 if (error)
386 return error;
387
388 error = xfs_qm_dqattach_locked(ip, false);
389 if (error)
390 goto out_trans_cancel;
391
392
393
394
395 error = xfs_find_trim_cow_extent(ip, imap, shared, &found);
396 if (error || !*shared)
397 goto out_trans_cancel;
398 if (found) {
399 xfs_trans_cancel(tp);
400 goto convert;
401 }
402
403 error = xfs_trans_reserve_quota_nblks(tp, ip, resblks, 0,
404 XFS_QMOPT_RES_REGBLKS);
405 if (error)
406 goto out_trans_cancel;
407
408 xfs_trans_ijoin(tp, ip, 0);
409
410
411 nimaps = 1;
412 error = xfs_bmapi_write(tp, ip, imap->br_startoff, imap->br_blockcount,
413 XFS_BMAPI_COWFORK | XFS_BMAPI_PREALLOC,
414 resblks, imap, &nimaps);
415 if (error)
416 goto out_unreserve;
417
418 xfs_inode_set_cowblocks_tag(ip);
419 error = xfs_trans_commit(tp);
420 if (error)
421 return error;
422
423
424
425
426
427 if (nimaps == 0)
428 return -ENOSPC;
429 convert:
430 xfs_trim_extent(imap, offset_fsb, count_fsb);
431
432
433
434
435
436 if (!convert_now || imap->br_state == XFS_EXT_NORM)
437 return 0;
438 trace_xfs_reflink_convert_cow(ip, imap);
439 return xfs_reflink_convert_cow_locked(ip, offset_fsb, count_fsb);
440
441 out_unreserve:
442 xfs_trans_unreserve_quota_nblks(tp, ip, (long)resblks, 0,
443 XFS_QMOPT_RES_REGBLKS);
444 out_trans_cancel:
445 xfs_trans_cancel(tp);
446 return error;
447 }
448
449
450
451
452
453
454
455
456
457
458 int
459 xfs_reflink_cancel_cow_blocks(
460 struct xfs_inode *ip,
461 struct xfs_trans **tpp,
462 xfs_fileoff_t offset_fsb,
463 xfs_fileoff_t end_fsb,
464 bool cancel_real)
465 {
466 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
467 struct xfs_bmbt_irec got, del;
468 struct xfs_iext_cursor icur;
469 int error = 0;
470
471 if (!xfs_inode_has_cow_data(ip))
472 return 0;
473 if (!xfs_iext_lookup_extent_before(ip, ifp, &end_fsb, &icur, &got))
474 return 0;
475
476
477 while (got.br_startoff + got.br_blockcount > offset_fsb) {
478 del = got;
479 xfs_trim_extent(&del, offset_fsb, end_fsb - offset_fsb);
480
481
482 if (!del.br_blockcount) {
483 xfs_iext_prev(ifp, &icur);
484 goto next_extent;
485 }
486
487 trace_xfs_reflink_cancel_cow(ip, &del);
488
489 if (isnullstartblock(del.br_startblock)) {
490 error = xfs_bmap_del_extent_delay(ip, XFS_COW_FORK,
491 &icur, &got, &del);
492 if (error)
493 break;
494 } else if (del.br_state == XFS_EXT_UNWRITTEN || cancel_real) {
495 ASSERT((*tpp)->t_firstblock == NULLFSBLOCK);
496
497
498 xfs_refcount_free_cow_extent(*tpp, del.br_startblock,
499 del.br_blockcount);
500
501 xfs_bmap_add_free(*tpp, del.br_startblock,
502 del.br_blockcount, NULL);
503
504
505 error = xfs_defer_finish(tpp);
506 if (error)
507 break;
508
509
510 xfs_bmap_del_extent_cow(ip, &icur, &got, &del);
511
512
513 error = xfs_trans_reserve_quota_nblks(NULL, ip,
514 -(long)del.br_blockcount, 0,
515 XFS_QMOPT_RES_REGBLKS);
516 if (error)
517 break;
518 } else {
519
520 xfs_iext_prev(ifp, &icur);
521 }
522 next_extent:
523 if (!xfs_iext_get_extent(ifp, &icur, &got))
524 break;
525 }
526
527
528 if (!ifp->if_bytes)
529 xfs_inode_clear_cowblocks_tag(ip);
530 return error;
531 }
532
533
534
535
536
537
538
539 int
540 xfs_reflink_cancel_cow_range(
541 struct xfs_inode *ip,
542 xfs_off_t offset,
543 xfs_off_t count,
544 bool cancel_real)
545 {
546 struct xfs_trans *tp;
547 xfs_fileoff_t offset_fsb;
548 xfs_fileoff_t end_fsb;
549 int error;
550
551 trace_xfs_reflink_cancel_cow_range(ip, offset, count);
552 ASSERT(ip->i_cowfp);
553
554 offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset);
555 if (count == NULLFILEOFF)
556 end_fsb = NULLFILEOFF;
557 else
558 end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count);
559
560
561 error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_write,
562 0, 0, 0, &tp);
563 if (error)
564 goto out;
565
566 xfs_ilock(ip, XFS_ILOCK_EXCL);
567 xfs_trans_ijoin(tp, ip, 0);
568
569
570 error = xfs_reflink_cancel_cow_blocks(ip, &tp, offset_fsb, end_fsb,
571 cancel_real);
572 if (error)
573 goto out_cancel;
574
575 error = xfs_trans_commit(tp);
576
577 xfs_iunlock(ip, XFS_ILOCK_EXCL);
578 return error;
579
580 out_cancel:
581 xfs_trans_cancel(tp);
582 xfs_iunlock(ip, XFS_ILOCK_EXCL);
583 out:
584 trace_xfs_reflink_cancel_cow_range_error(ip, error, _RET_IP_);
585 return error;
586 }
587
588
589
590
591
592
593
594
595
596
597
598 STATIC int
599 xfs_reflink_end_cow_extent(
600 struct xfs_inode *ip,
601 xfs_fileoff_t offset_fsb,
602 xfs_fileoff_t *end_fsb)
603 {
604 struct xfs_bmbt_irec got, del;
605 struct xfs_iext_cursor icur;
606 struct xfs_mount *mp = ip->i_mount;
607 struct xfs_trans *tp;
608 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK);
609 xfs_filblks_t rlen;
610 unsigned int resblks;
611 int error;
612
613
614 if (ifp->if_bytes == 0) {
615 *end_fsb = offset_fsb;
616 return 0;
617 }
618
619 resblks = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK);
620 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0,
621 XFS_TRANS_RESERVE, &tp);
622 if (error)
623 return error;
624
625
626
627
628
629
630 xfs_ilock(ip, XFS_ILOCK_EXCL);
631 xfs_trans_ijoin(tp, ip, 0);
632
633
634
635
636
637
638 if (!xfs_iext_lookup_extent_before(ip, ifp, end_fsb, &icur, &got) ||
639 got.br_startoff + got.br_blockcount <= offset_fsb) {
640 *end_fsb = offset_fsb;
641 goto out_cancel;
642 }
643
644
645
646
647
648
649
650 del = got;
651 xfs_trim_extent(&del, offset_fsb, *end_fsb - offset_fsb);
652
653 ASSERT(del.br_blockcount > 0);
654
655
656
657
658
659
660 if (!xfs_bmap_is_real_extent(&got)) {
661 *end_fsb = del.br_startoff;
662 goto out_cancel;
663 }
664
665
666 rlen = del.br_blockcount;
667 error = __xfs_bunmapi(tp, ip, del.br_startoff, &rlen, 0, 1);
668 if (error)
669 goto out_cancel;
670
671
672 xfs_trim_extent(&del, del.br_startoff + rlen, del.br_blockcount - rlen);
673 trace_xfs_reflink_cow_remap(ip, &del);
674
675
676 xfs_refcount_free_cow_extent(tp, del.br_startblock, del.br_blockcount);
677
678
679 xfs_bmap_map_extent(tp, ip, &del);
680
681
682 xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_DELBCOUNT,
683 (long)del.br_blockcount);
684
685
686 xfs_bmap_del_extent_cow(ip, &icur, &got, &del);
687
688 error = xfs_trans_commit(tp);
689 xfs_iunlock(ip, XFS_ILOCK_EXCL);
690 if (error)
691 return error;
692
693
694 *end_fsb = del.br_startoff;
695 return 0;
696
697 out_cancel:
698 xfs_trans_cancel(tp);
699 xfs_iunlock(ip, XFS_ILOCK_EXCL);
700 return error;
701 }
702
703
704
705
706 int
707 xfs_reflink_end_cow(
708 struct xfs_inode *ip,
709 xfs_off_t offset,
710 xfs_off_t count)
711 {
712 xfs_fileoff_t offset_fsb;
713 xfs_fileoff_t end_fsb;
714 int error = 0;
715
716 trace_xfs_reflink_end_cow(ip, offset, count);
717
718 offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset);
719 end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count);
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753 while (end_fsb > offset_fsb && !error)
754 error = xfs_reflink_end_cow_extent(ip, offset_fsb, &end_fsb);
755
756 if (error)
757 trace_xfs_reflink_end_cow_error(ip, error, _RET_IP_);
758 return error;
759 }
760
761
762
763
764 int
765 xfs_reflink_recover_cow(
766 struct xfs_mount *mp)
767 {
768 xfs_agnumber_t agno;
769 int error = 0;
770
771 if (!xfs_sb_version_hasreflink(&mp->m_sb))
772 return 0;
773
774 for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
775 error = xfs_refcount_recover_cow_leftovers(mp, agno);
776 if (error)
777 break;
778 }
779
780 return error;
781 }
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862 STATIC int
863 xfs_reflink_set_inode_flag(
864 struct xfs_inode *src,
865 struct xfs_inode *dest)
866 {
867 struct xfs_mount *mp = src->i_mount;
868 int error;
869 struct xfs_trans *tp;
870
871 if (xfs_is_reflink_inode(src) && xfs_is_reflink_inode(dest))
872 return 0;
873
874 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp);
875 if (error)
876 goto out_error;
877
878
879 if (src->i_ino == dest->i_ino)
880 xfs_ilock(src, XFS_ILOCK_EXCL);
881 else
882 xfs_lock_two_inodes(src, XFS_ILOCK_EXCL, dest, XFS_ILOCK_EXCL);
883
884 if (!xfs_is_reflink_inode(src)) {
885 trace_xfs_reflink_set_inode_flag(src);
886 xfs_trans_ijoin(tp, src, XFS_ILOCK_EXCL);
887 src->i_d.di_flags2 |= XFS_DIFLAG2_REFLINK;
888 xfs_trans_log_inode(tp, src, XFS_ILOG_CORE);
889 xfs_ifork_init_cow(src);
890 } else
891 xfs_iunlock(src, XFS_ILOCK_EXCL);
892
893 if (src->i_ino == dest->i_ino)
894 goto commit_flags;
895
896 if (!xfs_is_reflink_inode(dest)) {
897 trace_xfs_reflink_set_inode_flag(dest);
898 xfs_trans_ijoin(tp, dest, XFS_ILOCK_EXCL);
899 dest->i_d.di_flags2 |= XFS_DIFLAG2_REFLINK;
900 xfs_trans_log_inode(tp, dest, XFS_ILOG_CORE);
901 xfs_ifork_init_cow(dest);
902 } else
903 xfs_iunlock(dest, XFS_ILOCK_EXCL);
904
905 commit_flags:
906 error = xfs_trans_commit(tp);
907 if (error)
908 goto out_error;
909 return error;
910
911 out_error:
912 trace_xfs_reflink_set_inode_flag_error(dest, error, _RET_IP_);
913 return error;
914 }
915
916
917
918
919 int
920 xfs_reflink_update_dest(
921 struct xfs_inode *dest,
922 xfs_off_t newlen,
923 xfs_extlen_t cowextsize,
924 unsigned int remap_flags)
925 {
926 struct xfs_mount *mp = dest->i_mount;
927 struct xfs_trans *tp;
928 int error;
929
930 if (newlen <= i_size_read(VFS_I(dest)) && cowextsize == 0)
931 return 0;
932
933 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp);
934 if (error)
935 goto out_error;
936
937 xfs_ilock(dest, XFS_ILOCK_EXCL);
938 xfs_trans_ijoin(tp, dest, XFS_ILOCK_EXCL);
939
940 if (newlen > i_size_read(VFS_I(dest))) {
941 trace_xfs_reflink_update_inode_size(dest, newlen);
942 i_size_write(VFS_I(dest), newlen);
943 dest->i_d.di_size = newlen;
944 }
945
946 if (cowextsize) {
947 dest->i_d.di_cowextsize = cowextsize;
948 dest->i_d.di_flags2 |= XFS_DIFLAG2_COWEXTSIZE;
949 }
950
951 xfs_trans_log_inode(tp, dest, XFS_ILOG_CORE);
952
953 error = xfs_trans_commit(tp);
954 if (error)
955 goto out_error;
956 return error;
957
958 out_error:
959 trace_xfs_reflink_update_inode_size_error(dest, error, _RET_IP_);
960 return error;
961 }
962
963
964
965
966
967
968
969 static int
970 xfs_reflink_ag_has_free_space(
971 struct xfs_mount *mp,
972 xfs_agnumber_t agno)
973 {
974 struct xfs_perag *pag;
975 int error = 0;
976
977 if (!xfs_sb_version_hasrmapbt(&mp->m_sb))
978 return 0;
979
980 pag = xfs_perag_get(mp, agno);
981 if (xfs_ag_resv_critical(pag, XFS_AG_RESV_RMAPBT) ||
982 xfs_ag_resv_critical(pag, XFS_AG_RESV_METADATA))
983 error = -ENOSPC;
984 xfs_perag_put(pag);
985 return error;
986 }
987
988
989
990
991
992
993 STATIC int
994 xfs_reflink_remap_extent(
995 struct xfs_inode *ip,
996 struct xfs_bmbt_irec *irec,
997 xfs_fileoff_t destoff,
998 xfs_off_t new_isize)
999 {
1000 struct xfs_mount *mp = ip->i_mount;
1001 bool real_extent = xfs_bmap_is_real_extent(irec);
1002 struct xfs_trans *tp;
1003 unsigned int resblks;
1004 struct xfs_bmbt_irec uirec;
1005 xfs_filblks_t rlen;
1006 xfs_filblks_t unmap_len;
1007 xfs_off_t newlen;
1008 int error;
1009
1010 unmap_len = irec->br_startoff + irec->br_blockcount - destoff;
1011 trace_xfs_reflink_punch_range(ip, destoff, unmap_len);
1012
1013
1014 if (real_extent) {
1015 error = xfs_reflink_ag_has_free_space(mp,
1016 XFS_FSB_TO_AGNO(mp, irec->br_startblock));
1017 if (error)
1018 goto out;
1019 }
1020
1021
1022 resblks = XFS_EXTENTADD_SPACE_RES(ip->i_mount, XFS_DATA_FORK);
1023 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp);
1024 if (error)
1025 goto out;
1026
1027 xfs_ilock(ip, XFS_ILOCK_EXCL);
1028 xfs_trans_ijoin(tp, ip, 0);
1029
1030
1031 if (real_extent) {
1032 error = xfs_trans_reserve_quota_nblks(tp, ip,
1033 irec->br_blockcount, 0, XFS_QMOPT_RES_REGBLKS);
1034 if (error)
1035 goto out_cancel;
1036 }
1037
1038 trace_xfs_reflink_remap(ip, irec->br_startoff,
1039 irec->br_blockcount, irec->br_startblock);
1040
1041
1042 rlen = unmap_len;
1043 while (rlen) {
1044 ASSERT(tp->t_firstblock == NULLFSBLOCK);
1045 error = __xfs_bunmapi(tp, ip, destoff, &rlen, 0, 1);
1046 if (error)
1047 goto out_cancel;
1048
1049
1050
1051
1052
1053 uirec.br_startblock = irec->br_startblock + rlen;
1054 uirec.br_startoff = irec->br_startoff + rlen;
1055 uirec.br_blockcount = unmap_len - rlen;
1056 uirec.br_state = irec->br_state;
1057 unmap_len = rlen;
1058
1059
1060 if (!real_extent || uirec.br_blockcount == 0)
1061 goto next_extent;
1062
1063 trace_xfs_reflink_remap(ip, uirec.br_startoff,
1064 uirec.br_blockcount, uirec.br_startblock);
1065
1066
1067 xfs_refcount_increase_extent(tp, &uirec);
1068
1069
1070 xfs_bmap_map_extent(tp, ip, &uirec);
1071
1072
1073 xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT,
1074 uirec.br_blockcount);
1075
1076
1077 newlen = XFS_FSB_TO_B(mp,
1078 uirec.br_startoff + uirec.br_blockcount);
1079 newlen = min_t(xfs_off_t, newlen, new_isize);
1080 if (newlen > i_size_read(VFS_I(ip))) {
1081 trace_xfs_reflink_update_inode_size(ip, newlen);
1082 i_size_write(VFS_I(ip), newlen);
1083 ip->i_d.di_size = newlen;
1084 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1085 }
1086
1087 next_extent:
1088
1089 error = xfs_defer_finish(&tp);
1090 if (error)
1091 goto out_cancel;
1092 }
1093
1094 error = xfs_trans_commit(tp);
1095 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1096 if (error)
1097 goto out;
1098 return 0;
1099
1100 out_cancel:
1101 xfs_trans_cancel(tp);
1102 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1103 out:
1104 trace_xfs_reflink_remap_extent_error(ip, error, _RET_IP_);
1105 return error;
1106 }
1107
1108
1109
1110
1111 int
1112 xfs_reflink_remap_blocks(
1113 struct xfs_inode *src,
1114 loff_t pos_in,
1115 struct xfs_inode *dest,
1116 loff_t pos_out,
1117 loff_t remap_len,
1118 loff_t *remapped)
1119 {
1120 struct xfs_bmbt_irec imap;
1121 xfs_fileoff_t srcoff;
1122 xfs_fileoff_t destoff;
1123 xfs_filblks_t len;
1124 xfs_filblks_t range_len;
1125 xfs_filblks_t remapped_len = 0;
1126 xfs_off_t new_isize = pos_out + remap_len;
1127 int nimaps;
1128 int error = 0;
1129
1130 destoff = XFS_B_TO_FSBT(src->i_mount, pos_out);
1131 srcoff = XFS_B_TO_FSBT(src->i_mount, pos_in);
1132 len = XFS_B_TO_FSB(src->i_mount, remap_len);
1133
1134
1135 while (len) {
1136 uint lock_mode;
1137
1138 trace_xfs_reflink_remap_blocks_loop(src, srcoff, len,
1139 dest, destoff);
1140
1141
1142 nimaps = 1;
1143 lock_mode = xfs_ilock_data_map_shared(src);
1144 error = xfs_bmapi_read(src, srcoff, len, &imap, &nimaps, 0);
1145 xfs_iunlock(src, lock_mode);
1146 if (error)
1147 break;
1148 ASSERT(nimaps == 1);
1149
1150 trace_xfs_reflink_remap_imap(src, srcoff, len, XFS_DATA_FORK,
1151 &imap);
1152
1153
1154 range_len = imap.br_startoff + imap.br_blockcount - srcoff;
1155 imap.br_startoff += destoff - srcoff;
1156
1157
1158 error = xfs_reflink_remap_extent(dest, &imap, destoff,
1159 new_isize);
1160 if (error)
1161 break;
1162
1163 if (fatal_signal_pending(current)) {
1164 error = -EINTR;
1165 break;
1166 }
1167
1168
1169 srcoff += range_len;
1170 destoff += range_len;
1171 len -= range_len;
1172 remapped_len += range_len;
1173 }
1174
1175 if (error)
1176 trace_xfs_reflink_remap_blocks_error(dest, error, _RET_IP_);
1177 *remapped = min_t(loff_t, remap_len,
1178 XFS_FSB_TO_B(src->i_mount, remapped_len));
1179 return error;
1180 }
1181
1182
1183
1184
1185
1186
1187
1188
1189 static int
1190 xfs_iolock_two_inodes_and_break_layout(
1191 struct inode *src,
1192 struct inode *dest)
1193 {
1194 int error;
1195
1196 if (src > dest)
1197 swap(src, dest);
1198
1199 retry:
1200
1201 error = break_layout(src, true);
1202 if (error)
1203 return error;
1204 if (src != dest) {
1205 error = break_layout(dest, true);
1206 if (error)
1207 return error;
1208 }
1209
1210
1211 inode_lock(src);
1212 error = break_layout(src, false);
1213 if (error) {
1214 inode_unlock(src);
1215 if (error == -EWOULDBLOCK)
1216 goto retry;
1217 return error;
1218 }
1219
1220 if (src == dest)
1221 return 0;
1222
1223
1224 inode_lock_nested(dest, I_MUTEX_NONDIR2);
1225 error = break_layout(dest, false);
1226 if (error) {
1227 inode_unlock(src);
1228 inode_unlock(dest);
1229 if (error == -EWOULDBLOCK)
1230 goto retry;
1231 return error;
1232 }
1233
1234 return 0;
1235 }
1236
1237
1238 void
1239 xfs_reflink_remap_unlock(
1240 struct file *file_in,
1241 struct file *file_out)
1242 {
1243 struct inode *inode_in = file_inode(file_in);
1244 struct xfs_inode *src = XFS_I(inode_in);
1245 struct inode *inode_out = file_inode(file_out);
1246 struct xfs_inode *dest = XFS_I(inode_out);
1247 bool same_inode = (inode_in == inode_out);
1248
1249 xfs_iunlock(dest, XFS_MMAPLOCK_EXCL);
1250 if (!same_inode)
1251 xfs_iunlock(src, XFS_MMAPLOCK_EXCL);
1252 inode_unlock(inode_out);
1253 if (!same_inode)
1254 inode_unlock(inode_in);
1255 }
1256
1257
1258
1259
1260
1261
1262 static int
1263 xfs_reflink_zero_posteof(
1264 struct xfs_inode *ip,
1265 loff_t pos)
1266 {
1267 loff_t isize = i_size_read(VFS_I(ip));
1268
1269 if (pos <= isize)
1270 return 0;
1271
1272 trace_xfs_zero_eof(ip, isize, pos - isize);
1273 return iomap_zero_range(VFS_I(ip), isize, pos - isize, NULL,
1274 &xfs_iomap_ops);
1275 }
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306 int
1307 xfs_reflink_remap_prep(
1308 struct file *file_in,
1309 loff_t pos_in,
1310 struct file *file_out,
1311 loff_t pos_out,
1312 loff_t *len,
1313 unsigned int remap_flags)
1314 {
1315 struct inode *inode_in = file_inode(file_in);
1316 struct xfs_inode *src = XFS_I(inode_in);
1317 struct inode *inode_out = file_inode(file_out);
1318 struct xfs_inode *dest = XFS_I(inode_out);
1319 bool same_inode = (inode_in == inode_out);
1320 ssize_t ret;
1321
1322
1323 ret = xfs_iolock_two_inodes_and_break_layout(inode_in, inode_out);
1324 if (ret)
1325 return ret;
1326 if (same_inode)
1327 xfs_ilock(src, XFS_MMAPLOCK_EXCL);
1328 else
1329 xfs_lock_two_inodes(src, XFS_MMAPLOCK_EXCL, dest,
1330 XFS_MMAPLOCK_EXCL);
1331
1332
1333 ret = -EINVAL;
1334
1335 if (XFS_IS_REALTIME_INODE(src) || XFS_IS_REALTIME_INODE(dest))
1336 goto out_unlock;
1337
1338
1339 if (IS_DAX(inode_in) || IS_DAX(inode_out))
1340 goto out_unlock;
1341
1342 ret = generic_remap_file_range_prep(file_in, pos_in, file_out, pos_out,
1343 len, remap_flags);
1344 if (ret < 0 || *len == 0)
1345 goto out_unlock;
1346
1347
1348 ret = xfs_qm_dqattach(dest);
1349 if (ret)
1350 goto out_unlock;
1351
1352
1353
1354
1355
1356 ret = xfs_reflink_zero_posteof(dest, pos_out);
1357 if (ret)
1358 goto out_unlock;
1359
1360
1361 ret = xfs_reflink_set_inode_flag(src, dest);
1362 if (ret)
1363 goto out_unlock;
1364
1365
1366
1367
1368
1369
1370 if (pos_out > XFS_ISIZE(dest)) {
1371 loff_t flen = *len + (pos_out - XFS_ISIZE(dest));
1372 ret = xfs_flush_unmap_range(dest, XFS_ISIZE(dest), flen);
1373 } else {
1374 ret = xfs_flush_unmap_range(dest, pos_out, *len);
1375 }
1376 if (ret)
1377 goto out_unlock;
1378
1379 return 1;
1380 out_unlock:
1381 xfs_reflink_remap_unlock(file_in, file_out);
1382 return ret;
1383 }
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393 STATIC int
1394 xfs_reflink_dirty_extents(
1395 struct xfs_inode *ip,
1396 xfs_fileoff_t fbno,
1397 xfs_filblks_t end,
1398 xfs_off_t isize)
1399 {
1400 struct xfs_mount *mp = ip->i_mount;
1401 xfs_agnumber_t agno;
1402 xfs_agblock_t agbno;
1403 xfs_extlen_t aglen;
1404 xfs_agblock_t rbno;
1405 xfs_extlen_t rlen;
1406 xfs_off_t fpos;
1407 xfs_off_t flen;
1408 struct xfs_bmbt_irec map[2];
1409 int nmaps;
1410 int error = 0;
1411
1412 while (end - fbno > 0) {
1413 nmaps = 1;
1414
1415
1416
1417
1418 error = xfs_bmapi_read(ip, fbno, end - fbno, map, &nmaps, 0);
1419 if (error)
1420 goto out;
1421 if (nmaps == 0)
1422 break;
1423 if (!xfs_bmap_is_real_extent(&map[0]))
1424 goto next;
1425
1426 map[1] = map[0];
1427 while (map[1].br_blockcount) {
1428 agno = XFS_FSB_TO_AGNO(mp, map[1].br_startblock);
1429 agbno = XFS_FSB_TO_AGBNO(mp, map[1].br_startblock);
1430 aglen = map[1].br_blockcount;
1431
1432 error = xfs_reflink_find_shared(mp, NULL, agno, agbno,
1433 aglen, &rbno, &rlen, true);
1434 if (error)
1435 goto out;
1436 if (rbno == NULLAGBLOCK)
1437 break;
1438
1439
1440 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1441 fpos = XFS_FSB_TO_B(mp, map[1].br_startoff +
1442 (rbno - agbno));
1443 flen = XFS_FSB_TO_B(mp, rlen);
1444 if (fpos + flen > isize)
1445 flen = isize - fpos;
1446 error = iomap_file_dirty(VFS_I(ip), fpos, flen,
1447 &xfs_iomap_ops);
1448 xfs_ilock(ip, XFS_ILOCK_EXCL);
1449 if (error)
1450 goto out;
1451
1452 map[1].br_blockcount -= (rbno - agbno + rlen);
1453 map[1].br_startoff += (rbno - agbno + rlen);
1454 map[1].br_startblock += (rbno - agbno + rlen);
1455 }
1456
1457 next:
1458 fbno = map[0].br_startoff + map[0].br_blockcount;
1459 }
1460 out:
1461 return error;
1462 }
1463
1464
1465 int
1466 xfs_reflink_inode_has_shared_extents(
1467 struct xfs_trans *tp,
1468 struct xfs_inode *ip,
1469 bool *has_shared)
1470 {
1471 struct xfs_bmbt_irec got;
1472 struct xfs_mount *mp = ip->i_mount;
1473 struct xfs_ifork *ifp;
1474 xfs_agnumber_t agno;
1475 xfs_agblock_t agbno;
1476 xfs_extlen_t aglen;
1477 xfs_agblock_t rbno;
1478 xfs_extlen_t rlen;
1479 struct xfs_iext_cursor icur;
1480 bool found;
1481 int error;
1482
1483 ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);
1484 if (!(ifp->if_flags & XFS_IFEXTENTS)) {
1485 error = xfs_iread_extents(tp, ip, XFS_DATA_FORK);
1486 if (error)
1487 return error;
1488 }
1489
1490 *has_shared = false;
1491 found = xfs_iext_lookup_extent(ip, ifp, 0, &icur, &got);
1492 while (found) {
1493 if (isnullstartblock(got.br_startblock) ||
1494 got.br_state != XFS_EXT_NORM)
1495 goto next;
1496 agno = XFS_FSB_TO_AGNO(mp, got.br_startblock);
1497 agbno = XFS_FSB_TO_AGBNO(mp, got.br_startblock);
1498 aglen = got.br_blockcount;
1499
1500 error = xfs_reflink_find_shared(mp, tp, agno, agbno, aglen,
1501 &rbno, &rlen, false);
1502 if (error)
1503 return error;
1504
1505 if (rbno != NULLAGBLOCK) {
1506 *has_shared = true;
1507 return 0;
1508 }
1509 next:
1510 found = xfs_iext_next_extent(ifp, &icur, &got);
1511 }
1512
1513 return 0;
1514 }
1515
1516
1517
1518
1519
1520
1521
1522 int
1523 xfs_reflink_clear_inode_flag(
1524 struct xfs_inode *ip,
1525 struct xfs_trans **tpp)
1526 {
1527 bool needs_flag;
1528 int error = 0;
1529
1530 ASSERT(xfs_is_reflink_inode(ip));
1531
1532 error = xfs_reflink_inode_has_shared_extents(*tpp, ip, &needs_flag);
1533 if (error || needs_flag)
1534 return error;
1535
1536
1537
1538
1539
1540 error = xfs_reflink_cancel_cow_blocks(ip, tpp, 0, NULLFILEOFF, true);
1541 if (error)
1542 return error;
1543
1544
1545 trace_xfs_reflink_unset_inode_flag(ip);
1546 ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK;
1547 xfs_inode_clear_cowblocks_tag(ip);
1548 xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE);
1549
1550 return error;
1551 }
1552
1553
1554
1555
1556
1557 STATIC int
1558 xfs_reflink_try_clear_inode_flag(
1559 struct xfs_inode *ip)
1560 {
1561 struct xfs_mount *mp = ip->i_mount;
1562 struct xfs_trans *tp;
1563 int error = 0;
1564
1565
1566 error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, 0, 0, 0, &tp);
1567 if (error)
1568 return error;
1569
1570 xfs_ilock(ip, XFS_ILOCK_EXCL);
1571 xfs_trans_ijoin(tp, ip, 0);
1572
1573 error = xfs_reflink_clear_inode_flag(ip, &tp);
1574 if (error)
1575 goto cancel;
1576
1577 error = xfs_trans_commit(tp);
1578 if (error)
1579 goto out;
1580
1581 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1582 return 0;
1583 cancel:
1584 xfs_trans_cancel(tp);
1585 out:
1586 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1587 return error;
1588 }
1589
1590
1591
1592
1593
1594 int
1595 xfs_reflink_unshare(
1596 struct xfs_inode *ip,
1597 xfs_off_t offset,
1598 xfs_off_t len)
1599 {
1600 struct xfs_mount *mp = ip->i_mount;
1601 xfs_fileoff_t fbno;
1602 xfs_filblks_t end;
1603 xfs_off_t isize;
1604 int error;
1605
1606 if (!xfs_is_reflink_inode(ip))
1607 return 0;
1608
1609 trace_xfs_reflink_unshare(ip, offset, len);
1610
1611 inode_dio_wait(VFS_I(ip));
1612
1613
1614 xfs_ilock(ip, XFS_ILOCK_EXCL);
1615 fbno = XFS_B_TO_FSBT(mp, offset);
1616 isize = i_size_read(VFS_I(ip));
1617 end = XFS_B_TO_FSB(mp, offset + len);
1618 error = xfs_reflink_dirty_extents(ip, fbno, end, isize);
1619 if (error)
1620 goto out_unlock;
1621 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1622
1623
1624 error = filemap_write_and_wait(VFS_I(ip)->i_mapping);
1625 if (error)
1626 goto out;
1627
1628
1629 error = xfs_reflink_try_clear_inode_flag(ip);
1630 if (error)
1631 goto out;
1632
1633 return 0;
1634
1635 out_unlock:
1636 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1637 out:
1638 trace_xfs_reflink_unshare_error(ip, error, _RET_IP_);
1639 return error;
1640 }