aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/gfs2/bmap.c205
-rw-r--r--fs/gfs2/bmap.h6
-rw-r--r--fs/gfs2/file.c6
-rw-r--r--fs/gfs2/inode.c4
4 files changed, 126 insertions, 95 deletions
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 5226c3bfbcf7..a7b586e02693 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -572,22 +572,6 @@ static int gfs2_hole_size(struct inode *inode, sector_t lblock, u64 len,
572 return ret; 572 return ret;
573} 573}
574 574
575static inline void bmap_lock(struct gfs2_inode *ip, int create)
576{
577 if (create)
578 down_write(&ip->i_rw_mutex);
579 else
580 down_read(&ip->i_rw_mutex);
581}
582
583static inline void bmap_unlock(struct gfs2_inode *ip, int create)
584{
585 if (create)
586 up_write(&ip->i_rw_mutex);
587 else
588 up_read(&ip->i_rw_mutex);
589}
590
591static inline __be64 *gfs2_indirect_init(struct metapath *mp, 575static inline __be64 *gfs2_indirect_init(struct metapath *mp,
592 struct gfs2_glock *gl, unsigned int i, 576 struct gfs2_glock *gl, unsigned int i,
593 unsigned offset, u64 bn) 577 unsigned offset, u64 bn)
@@ -614,15 +598,11 @@ enum alloc_state {
614}; 598};
615 599
616/** 600/**
617 * gfs2_bmap_alloc - Build a metadata tree of the requested height 601 * gfs2_iomap_alloc - Build a metadata tree of the requested height
618 * @inode: The GFS2 inode 602 * @inode: The GFS2 inode
619 * @lblock: The logical starting block of the extent 603 * @iomap: The iomap structure
620 * @bh_map: This is used to return the mapping details 604 * @flags: iomap flags
621 * @zero_new: True if newly allocated blocks should be zeroed
622 * @mp: The metapath, with proper height information calculated 605 * @mp: The metapath, with proper height information calculated
623 * @maxlen: The max number of data blocks to alloc
624 * @dblock: Pointer to return the resulting new block
625 * @dblks: Pointer to return the number of blocks allocated
626 * 606 *
627 * In this routine we may have to alloc: 607 * In this routine we may have to alloc:
628 * i) Indirect blocks to grow the metadata tree height 608 * i) Indirect blocks to grow the metadata tree height
@@ -635,6 +615,13 @@ enum alloc_state {
635 * blocks are available, there will only be one request per bmap call) 615 * blocks are available, there will only be one request per bmap call)
636 * and uses the state machine to initialise the blocks in order. 616 * and uses the state machine to initialise the blocks in order.
637 * 617 *
618 * Right now, this function will allocate at most one indirect block
619 * worth of data -- with a default block size of 4K, that's slightly
620 * less than 2M. If this limitation is ever removed to allow huge
621 * allocations, we would probably still want to limit the iomap size we
622 * return to avoid stalling other tasks during huge writes; the next
623 * iomap iteration would then find the blocks already allocated.
624 *
638 * Returns: errno on error 625 * Returns: errno on error
639 */ 626 */
640 627
@@ -649,6 +636,7 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
649 unsigned dblks = 0; 636 unsigned dblks = 0;
650 unsigned ptrs_per_blk; 637 unsigned ptrs_per_blk;
651 const unsigned end_of_metadata = mp->mp_fheight - 1; 638 const unsigned end_of_metadata = mp->mp_fheight - 1;
639 int ret;
652 enum alloc_state state; 640 enum alloc_state state;
653 __be64 *ptr; 641 __be64 *ptr;
654 __be64 zero_bn = 0; 642 __be64 zero_bn = 0;
@@ -659,6 +647,8 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
659 647
660 gfs2_trans_add_meta(ip->i_gl, dibh); 648 gfs2_trans_add_meta(ip->i_gl, dibh);
661 649
650 down_write(&ip->i_rw_mutex);
651
662 if (mp->mp_fheight == mp->mp_aheight) { 652 if (mp->mp_fheight == mp->mp_aheight) {
663 struct buffer_head *bh; 653 struct buffer_head *bh;
664 int eob; 654 int eob;
@@ -694,11 +684,10 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
694 blks = dblks + iblks; 684 blks = dblks + iblks;
695 i = mp->mp_aheight; 685 i = mp->mp_aheight;
696 do { 686 do {
697 int error;
698 n = blks - alloced; 687 n = blks - alloced;
699 error = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL); 688 ret = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL);
700 if (error) 689 if (ret)
701 return error; 690 goto out;
702 alloced += n; 691 alloced += n;
703 if (state != ALLOC_DATA || gfs2_is_jdata(ip)) 692 if (state != ALLOC_DATA || gfs2_is_jdata(ip))
704 gfs2_trans_add_unrevoke(sdp, bn, n); 693 gfs2_trans_add_unrevoke(sdp, bn, n);
@@ -754,7 +743,7 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
754 dblks = n; 743 dblks = n;
755 ptr = metapointer(end_of_metadata, mp); 744 ptr = metapointer(end_of_metadata, mp);
756 iomap->addr = bn << inode->i_blkbits; 745 iomap->addr = bn << inode->i_blkbits;
757 iomap->flags |= IOMAP_F_NEW; 746 iomap->flags |= IOMAP_F_MERGED | IOMAP_F_NEW;
758 while (n-- > 0) 747 while (n-- > 0)
759 *ptr++ = cpu_to_be64(bn++); 748 *ptr++ = cpu_to_be64(bn++);
760 break; 749 break;
@@ -764,8 +753,10 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap,
764 iomap->length = (u64)dblks << inode->i_blkbits; 753 iomap->length = (u64)dblks << inode->i_blkbits;
765 ip->i_height = mp->mp_fheight; 754 ip->i_height = mp->mp_fheight;
766 gfs2_add_inode_blocks(&ip->i_inode, alloced); 755 gfs2_add_inode_blocks(&ip->i_inode, alloced);
767 gfs2_dinode_out(ip, mp->mp_bh[0]->b_data); 756 gfs2_dinode_out(ip, dibh->b_data);
768 return 0; 757out:
758 up_write(&ip->i_rw_mutex);
759 return ret;
769} 760}
770 761
771static void gfs2_stuffed_iomap(struct inode *inode, struct iomap *iomap) 762static void gfs2_stuffed_iomap(struct inode *inode, struct iomap *iomap)
@@ -781,110 +772,130 @@ static void gfs2_stuffed_iomap(struct inode *inode, struct iomap *iomap)
781} 772}
782 773
783/** 774/**
784 * gfs2_iomap_begin - Map blocks from an inode to disk blocks 775 * gfs2_iomap_get - Map blocks from an inode to disk blocks
785 * @inode: The inode 776 * @inode: The inode
786 * @pos: Starting position in bytes 777 * @pos: Starting position in bytes
787 * @length: Length to map, in bytes 778 * @length: Length to map, in bytes
788 * @flags: iomap flags 779 * @flags: iomap flags
789 * @iomap: The iomap structure 780 * @iomap: The iomap structure
781 * @mp: The metapath
790 * 782 *
791 * Returns: errno 783 * Returns: errno
792 */ 784 */
793int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length, 785static int gfs2_iomap_get(struct inode *inode, loff_t pos, loff_t length,
794 unsigned flags, struct iomap *iomap) 786 unsigned flags, struct iomap *iomap,
787 struct metapath *mp)
795{ 788{
796 struct gfs2_inode *ip = GFS2_I(inode); 789 struct gfs2_inode *ip = GFS2_I(inode);
797 struct gfs2_sbd *sdp = GFS2_SB(inode); 790 struct gfs2_sbd *sdp = GFS2_SB(inode);
798 struct metapath mp = { .mp_aheight = 1, };
799 __be64 *ptr; 791 __be64 *ptr;
800 sector_t lblock; 792 sector_t lblock;
801 sector_t lend; 793 sector_t lblock_stop;
802 int ret = 0; 794 int ret;
803 int eob; 795 int eob;
804 unsigned int len; 796 u64 len;
805 struct buffer_head *bh; 797 struct buffer_head *bh;
806 u8 height; 798 u8 height;
807 799
808 trace_gfs2_iomap_start(ip, pos, length, flags); 800 if (!length)
809 if (!length) { 801 return -EINVAL;
810 ret = -EINVAL;
811 goto out;
812 }
813 802
814 if (gfs2_is_stuffed(ip)) { 803 if (gfs2_is_stuffed(ip)) {
815 if (flags & IOMAP_REPORT) { 804 if (flags & IOMAP_REPORT) {
805 if (pos >= i_size_read(inode))
806 return -ENOENT;
816 gfs2_stuffed_iomap(inode, iomap); 807 gfs2_stuffed_iomap(inode, iomap);
817 if (pos >= iomap->length) 808 return 0;
818 ret = -ENOENT;
819 goto out;
820 } 809 }
821 BUG_ON(!(flags & IOMAP_WRITE)); 810 BUG_ON(!(flags & IOMAP_WRITE));
822 } 811 }
823
824 lblock = pos >> inode->i_blkbits; 812 lblock = pos >> inode->i_blkbits;
825 lend = (pos + length + sdp->sd_sb.sb_bsize - 1) >> inode->i_blkbits;
826 len = lend - lblock;
827
828 iomap->offset = lblock << inode->i_blkbits; 813 iomap->offset = lblock << inode->i_blkbits;
829 iomap->addr = IOMAP_NULL_ADDR; 814 lblock_stop = (pos + length - 1) >> inode->i_blkbits;
830 iomap->type = IOMAP_HOLE; 815 len = lblock_stop - lblock + 1;
831 iomap->length = (u64)(lend - lblock) << inode->i_blkbits; 816
832 iomap->flags = IOMAP_F_MERGED; 817 down_read(&ip->i_rw_mutex);
833 bmap_lock(ip, flags & IOMAP_WRITE);
834 818
835 ret = gfs2_meta_inode_buffer(ip, &mp.mp_bh[0]); 819 ret = gfs2_meta_inode_buffer(ip, &mp->mp_bh[0]);
836 if (ret) 820 if (ret)
837 goto out_release; 821 goto unlock;
838 822
839 height = ip->i_height; 823 height = ip->i_height;
840 while ((lblock + 1) * sdp->sd_sb.sb_bsize > sdp->sd_heightsize[height]) 824 while ((lblock + 1) * sdp->sd_sb.sb_bsize > sdp->sd_heightsize[height])
841 height++; 825 height++;
842 find_metapath(sdp, lblock, &mp, height); 826 find_metapath(sdp, lblock, mp, height);
843 if (height > ip->i_height || gfs2_is_stuffed(ip)) 827 if (height > ip->i_height || gfs2_is_stuffed(ip))
844 goto do_alloc; 828 goto do_alloc;
845 829
846 ret = lookup_metapath(ip, &mp); 830 ret = lookup_metapath(ip, mp);
847 if (ret) 831 if (ret)
848 goto out_release; 832 goto unlock;
849 833
850 if (mp.mp_aheight != ip->i_height) 834 if (mp->mp_aheight != ip->i_height)
851 goto do_alloc; 835 goto do_alloc;
852 836
853 ptr = metapointer(ip->i_height - 1, &mp); 837 ptr = metapointer(ip->i_height - 1, mp);
854 if (*ptr == 0) 838 if (*ptr == 0)
855 goto do_alloc; 839 goto do_alloc;
856 840
857 iomap->type = IOMAP_MAPPED; 841 bh = mp->mp_bh[ip->i_height - 1];
858 iomap->addr = be64_to_cpu(*ptr) << inode->i_blkbits; 842 len = gfs2_extent_length(bh->b_data, bh->b_size, ptr, len, &eob);
859 843
860 bh = mp.mp_bh[ip->i_height - 1]; 844 iomap->addr = be64_to_cpu(*ptr) << inode->i_blkbits;
861 len = gfs2_extent_length(bh->b_data, bh->b_size, ptr, lend - lblock, &eob); 845 iomap->length = len << inode->i_blkbits;
846 iomap->type = IOMAP_MAPPED;
847 iomap->flags = IOMAP_F_MERGED;
862 if (eob) 848 if (eob)
863 iomap->flags |= IOMAP_F_BOUNDARY; 849 iomap->flags |= IOMAP_F_BOUNDARY;
864 iomap->length = (u64)len << inode->i_blkbits;
865 850
866out_release:
867 release_metapath(&mp);
868 bmap_unlock(ip, flags & IOMAP_WRITE);
869out: 851out:
870 trace_gfs2_iomap_end(ip, iomap, ret); 852 iomap->bdev = inode->i_sb->s_bdev;
853unlock:
854 up_read(&ip->i_rw_mutex);
871 return ret; 855 return ret;
872 856
873do_alloc: 857do_alloc:
874 if (flags & IOMAP_WRITE) { 858 iomap->addr = IOMAP_NULL_ADDR;
875 ret = gfs2_iomap_alloc(inode, iomap, flags, &mp); 859 iomap->length = len << inode->i_blkbits;
876 } else if (flags & IOMAP_REPORT) { 860 iomap->type = IOMAP_HOLE;
861 iomap->flags = 0;
862 if (flags & IOMAP_REPORT) {
877 loff_t size = i_size_read(inode); 863 loff_t size = i_size_read(inode);
878 if (pos >= size) 864 if (pos >= size)
879 ret = -ENOENT; 865 ret = -ENOENT;
880 else if (height <= ip->i_height) 866 else if (height == ip->i_height)
881 ret = gfs2_hole_size(inode, lblock, len, &mp, iomap); 867 ret = gfs2_hole_size(inode, lblock, len, mp, iomap);
882 else 868 else
883 iomap->length = size - pos; 869 iomap->length = size - pos;
884 } 870 }
885 goto out_release; 871 goto out;
886} 872}
887 873
874static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length,
875 unsigned flags, struct iomap *iomap)
876{
877 struct gfs2_inode *ip = GFS2_I(inode);
878 struct metapath mp = { .mp_aheight = 1, };
879 int ret;
880
881 trace_gfs2_iomap_start(ip, pos, length, flags);
882 if (flags & IOMAP_WRITE) {
883 ret = gfs2_iomap_get(inode, pos, length, flags, iomap, &mp);
884 if (!ret && iomap->type == IOMAP_HOLE)
885 ret = gfs2_iomap_alloc(inode, iomap, flags, &mp);
886 release_metapath(&mp);
887 } else {
888 ret = gfs2_iomap_get(inode, pos, length, flags, iomap, &mp);
889 release_metapath(&mp);
890 }
891 trace_gfs2_iomap_end(ip, iomap, ret);
892 return ret;
893}
894
895const struct iomap_ops gfs2_iomap_ops = {
896 .iomap_begin = gfs2_iomap_begin,
897};
898
888/** 899/**
889 * gfs2_block_map - Map one or more blocks of an inode to a disk block 900 * gfs2_block_map - Map one or more blocks of an inode to a disk block
890 * @inode: The inode 901 * @inode: The inode
@@ -910,25 +921,34 @@ int gfs2_block_map(struct inode *inode, sector_t lblock,
910 struct buffer_head *bh_map, int create) 921 struct buffer_head *bh_map, int create)
911{ 922{
912 struct gfs2_inode *ip = GFS2_I(inode); 923 struct gfs2_inode *ip = GFS2_I(inode);
913 struct iomap iomap; 924 loff_t pos = (loff_t)lblock << inode->i_blkbits;
914 int ret, flags = 0; 925 loff_t length = bh_map->b_size;
926 struct metapath mp = { .mp_aheight = 1, };
927 struct iomap iomap = { };
928 int ret;
915 929
916 clear_buffer_mapped(bh_map); 930 clear_buffer_mapped(bh_map);
917 clear_buffer_new(bh_map); 931 clear_buffer_new(bh_map);
918 clear_buffer_boundary(bh_map); 932 clear_buffer_boundary(bh_map);
919 trace_gfs2_bmap(ip, bh_map, lblock, create, 1); 933 trace_gfs2_bmap(ip, bh_map, lblock, create, 1);
920 934
921 if (create) 935 if (create) {
922 flags |= IOMAP_WRITE; 936 ret = gfs2_iomap_get(inode, pos, length, IOMAP_WRITE, &iomap, &mp);
923 ret = gfs2_iomap_begin(inode, (loff_t)lblock << inode->i_blkbits, 937 if (!ret && iomap.type == IOMAP_HOLE)
924 bh_map->b_size, flags, &iomap); 938 ret = gfs2_iomap_alloc(inode, &iomap, IOMAP_WRITE, &mp);
925 if (ret) { 939 release_metapath(&mp);
926 if (!create && ret == -ENOENT) { 940 } else {
927 /* Return unmapped buffer beyond the end of file. */ 941 ret = gfs2_iomap_get(inode, pos, length, 0, &iomap, &mp);
942 release_metapath(&mp);
943
944 /* Return unmapped buffer beyond the end of file. */
945 if (ret == -ENOENT) {
928 ret = 0; 946 ret = 0;
947 goto out;
929 } 948 }
930 goto out;
931 } 949 }
950 if (ret)
951 goto out;
932 952
933 if (iomap.length > bh_map->b_size) { 953 if (iomap.length > bh_map->b_size) {
934 iomap.length = bh_map->b_size; 954 iomap.length = bh_map->b_size;
@@ -1143,6 +1163,19 @@ out:
1143 return error; 1163 return error;
1144} 1164}
1145 1165
1166int gfs2_iomap_get_alloc(struct inode *inode, loff_t pos, loff_t length,
1167 struct iomap *iomap)
1168{
1169 struct metapath mp = { .mp_aheight = 1, };
1170 int ret;
1171
1172 ret = gfs2_iomap_get(inode, pos, length, IOMAP_WRITE, iomap, &mp);
1173 if (!ret && iomap->type == IOMAP_HOLE)
1174 ret = gfs2_iomap_alloc(inode, iomap, IOMAP_WRITE, &mp);
1175 release_metapath(&mp);
1176 return ret;
1177}
1178
1146/** 1179/**
1147 * sweep_bh_for_rgrps - find an rgrp in a meta buffer and free blocks therein 1180 * sweep_bh_for_rgrps - find an rgrp in a meta buffer and free blocks therein
1148 * @ip: inode 1181 * @ip: inode
diff --git a/fs/gfs2/bmap.h b/fs/gfs2/bmap.h
index c3402fe00653..6b18fb323f0a 100644
--- a/fs/gfs2/bmap.h
+++ b/fs/gfs2/bmap.h
@@ -46,11 +46,13 @@ static inline void gfs2_write_calc_reserv(const struct gfs2_inode *ip,
46 } 46 }
47} 47}
48 48
49extern const struct iomap_ops gfs2_iomap_ops;
50
49extern int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page); 51extern int gfs2_unstuff_dinode(struct gfs2_inode *ip, struct page *page);
50extern int gfs2_block_map(struct inode *inode, sector_t lblock, 52extern int gfs2_block_map(struct inode *inode, sector_t lblock,
51 struct buffer_head *bh, int create); 53 struct buffer_head *bh, int create);
52extern int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length, 54extern int gfs2_iomap_get_alloc(struct inode *inode, loff_t pos, loff_t length,
53 unsigned flags, struct iomap *iomap); 55 struct iomap *iomap);
54extern int gfs2_extent_map(struct inode *inode, u64 lblock, int *new, 56extern int gfs2_extent_map(struct inode *inode, u64 lblock, int *new,
55 u64 *dblock, unsigned *extlen); 57 u64 *dblock, unsigned *extlen);
56extern int gfs2_setattr_size(struct inode *inode, u64 size); 58extern int gfs2_setattr_size(struct inode *inode, u64 size);
diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
index 4b71f021a9e2..7137db7b0119 100644
--- a/fs/gfs2/file.c
+++ b/fs/gfs2/file.c
@@ -733,7 +733,7 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
733 struct gfs2_inode *ip = GFS2_I(inode); 733 struct gfs2_inode *ip = GFS2_I(inode);
734 loff_t end = offset + len; 734 loff_t end = offset + len;
735 struct buffer_head *dibh; 735 struct buffer_head *dibh;
736 struct iomap iomap; 736 struct iomap iomap = { };
737 int error; 737 int error;
738 738
739 error = gfs2_meta_inode_buffer(ip, &dibh); 739 error = gfs2_meta_inode_buffer(ip, &dibh);
@@ -749,8 +749,8 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
749 } 749 }
750 750
751 while (offset < end) { 751 while (offset < end) {
752 error = gfs2_iomap_begin(inode, offset, end - offset, 752 error = gfs2_iomap_get_alloc(inode, offset, end - offset,
753 IOMAP_WRITE, &iomap); 753 &iomap);
754 if (error) 754 if (error)
755 goto out; 755 goto out;
756 offset = iomap.offset + iomap.length; 756 offset = iomap.offset + iomap.length;
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 8700eb815638..feda55f67050 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -2006,10 +2006,6 @@ static int gfs2_getattr(const struct path *path, struct kstat *stat,
2006 return 0; 2006 return 0;
2007} 2007}
2008 2008
2009const struct iomap_ops gfs2_iomap_ops = {
2010 .iomap_begin = gfs2_iomap_begin,
2011};
2012
2013static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, 2009static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
2014 u64 start, u64 len) 2010 u64 start, u64 len)
2015{ 2011{