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