aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2012-11-12 06:54:13 -0500
committerBen Myers <bpm@sgi.com>2012-11-15 22:34:43 -0500
commit2025207ca6738a1217126ef14af9d104433f9824 (patch)
tree522cac64d22f59063e16e7e2aec5a1688fa77a6b /fs
parent82025d7f79148fe66a1594a0ebe4ab38152cf9e6 (diff)
xfs: factor dir2 free block reading
Also factor out the updating of the free block when removing entries from leaf blocks, and add a verifier callback for reads. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Phil White <pwhite@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_dir2_leaf.c3
-rw-r--r--fs/xfs/xfs_dir2_node.c218
-rw-r--r--fs/xfs/xfs_dir2_priv.h2
3 files changed, 143 insertions, 80 deletions
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c
index 86e3dc1de0e7..6c1359dc9898 100644
--- a/fs/xfs/xfs_dir2_leaf.c
+++ b/fs/xfs/xfs_dir2_leaf.c
@@ -1863,8 +1863,7 @@ xfs_dir2_node_to_leaf(
1863 /* 1863 /*
1864 * Read the freespace block. 1864 * Read the freespace block.
1865 */ 1865 */
1866 error = xfs_da_read_buf(tp, dp, mp->m_dirfreeblk, -1, &fbp, 1866 error = xfs_dir2_free_read(tp, dp, mp->m_dirfreeblk, &fbp);
1867 XFS_DATA_FORK, NULL);
1868 if (error) 1867 if (error)
1869 return error; 1868 return error;
1870 free = fbp->b_addr; 1869 free = fbp->b_addr;
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c
index 290c2b1016ab..d7f899dfbff5 100644
--- a/fs/xfs/xfs_dir2_node.c
+++ b/fs/xfs/xfs_dir2_node.c
@@ -55,6 +55,57 @@ static int xfs_dir2_leafn_remove(xfs_da_args_t *args, struct xfs_buf *bp,
55static int xfs_dir2_node_addname_int(xfs_da_args_t *args, 55static int xfs_dir2_node_addname_int(xfs_da_args_t *args,
56 xfs_da_state_blk_t *fblk); 56 xfs_da_state_blk_t *fblk);
57 57
58static void
59xfs_dir2_free_verify(
60 struct xfs_buf *bp)
61{
62 struct xfs_mount *mp = bp->b_target->bt_mount;
63 struct xfs_dir2_free_hdr *hdr = bp->b_addr;
64 int block_ok = 0;
65
66 block_ok = hdr->magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC);
67 if (!block_ok) {
68 XFS_CORRUPTION_ERROR("xfs_dir2_free_verify magic",
69 XFS_ERRLEVEL_LOW, mp, hdr);
70 xfs_buf_ioerror(bp, EFSCORRUPTED);
71 }
72
73 bp->b_iodone = NULL;
74 xfs_buf_ioend(bp, 0);
75}
76
77static int
78__xfs_dir2_free_read(
79 struct xfs_trans *tp,
80 struct xfs_inode *dp,
81 xfs_dablk_t fbno,
82 xfs_daddr_t mappedbno,
83 struct xfs_buf **bpp)
84{
85 return xfs_da_read_buf(tp, dp, fbno, mappedbno, bpp,
86 XFS_DATA_FORK, xfs_dir2_free_verify);
87}
88
89int
90xfs_dir2_free_read(
91 struct xfs_trans *tp,
92 struct xfs_inode *dp,
93 xfs_dablk_t fbno,
94 struct xfs_buf **bpp)
95{
96 return __xfs_dir2_free_read(tp, dp, fbno, -1, bpp);
97}
98
99static int
100xfs_dir2_free_try_read(
101 struct xfs_trans *tp,
102 struct xfs_inode *dp,
103 xfs_dablk_t fbno,
104 struct xfs_buf **bpp)
105{
106 return __xfs_dir2_free_read(tp, dp, fbno, -2, bpp);
107}
108
58/* 109/*
59 * Log entries from a freespace block. 110 * Log entries from a freespace block.
60 */ 111 */
@@ -394,12 +445,10 @@ xfs_dir2_leafn_lookup_for_addname(
394 */ 445 */
395 if (curbp) 446 if (curbp)
396 xfs_trans_brelse(tp, curbp); 447 xfs_trans_brelse(tp, curbp);
397 /* 448
398 * Read the free block. 449 error = xfs_dir2_free_read(tp, dp,
399 */
400 error = xfs_da_read_buf(tp, dp,
401 xfs_dir2_db_to_da(mp, newfdb), 450 xfs_dir2_db_to_da(mp, newfdb),
402 -1, &curbp, XFS_DATA_FORK, NULL); 451 &curbp);
403 if (error) 452 if (error)
404 return error; 453 return error;
405 free = curbp->b_addr; 454 free = curbp->b_addr;
@@ -825,6 +874,77 @@ xfs_dir2_leafn_rebalance(
825 } 874 }
826} 875}
827 876
877static int
878xfs_dir2_data_block_free(
879 xfs_da_args_t *args,
880 struct xfs_dir2_data_hdr *hdr,
881 struct xfs_dir2_free *free,
882 xfs_dir2_db_t fdb,
883 int findex,
884 struct xfs_buf *fbp,
885 int longest)
886{
887 struct xfs_trans *tp = args->trans;
888 int logfree = 0;
889
890 if (!hdr) {
891 /* One less used entry in the free table. */
892 be32_add_cpu(&free->hdr.nused, -1);
893 xfs_dir2_free_log_header(tp, fbp);
894
895 /*
896 * If this was the last entry in the table, we can trim the
897 * table size back. There might be other entries at the end
898 * referring to non-existent data blocks, get those too.
899 */
900 if (findex == be32_to_cpu(free->hdr.nvalid) - 1) {
901 int i; /* free entry index */
902
903 for (i = findex - 1; i >= 0; i--) {
904 if (free->bests[i] != cpu_to_be16(NULLDATAOFF))
905 break;
906 }
907 free->hdr.nvalid = cpu_to_be32(i + 1);
908 logfree = 0;
909 } else {
910 /* Not the last entry, just punch it out. */
911 free->bests[findex] = cpu_to_be16(NULLDATAOFF);
912 logfree = 1;
913 }
914 /*
915 * If there are no useful entries left in the block,
916 * get rid of the block if we can.
917 */
918 if (!free->hdr.nused) {
919 int error;
920
921 error = xfs_dir2_shrink_inode(args, fdb, fbp);
922 if (error == 0) {
923 fbp = NULL;
924 logfree = 0;
925 } else if (error != ENOSPC || args->total != 0)
926 return error;
927 /*
928 * It's possible to get ENOSPC if there is no
929 * space reservation. In this case some one
930 * else will eventually get rid of this block.
931 */
932 }
933 } else {
934 /*
935 * Data block is not empty, just set the free entry to the new
936 * value.
937 */
938 free->bests[findex] = cpu_to_be16(longest);
939 logfree = 1;
940 }
941
942 /* Log the free entry that changed, unless we got rid of it. */
943 if (logfree)
944 xfs_dir2_free_log_bests(tp, fbp, findex, findex);
945 return 0;
946}
947
828/* 948/*
829 * Remove an entry from a node directory. 949 * Remove an entry from a node directory.
830 * This removes the leaf entry and the data entry, 950 * This removes the leaf entry and the data entry,
@@ -908,15 +1028,14 @@ xfs_dir2_leafn_remove(
908 xfs_dir2_db_t fdb; /* freeblock block number */ 1028 xfs_dir2_db_t fdb; /* freeblock block number */
909 int findex; /* index in freeblock entries */ 1029 int findex; /* index in freeblock entries */
910 xfs_dir2_free_t *free; /* freeblock structure */ 1030 xfs_dir2_free_t *free; /* freeblock structure */
911 int logfree; /* need to log free entry */
912 1031
913 /* 1032 /*
914 * Convert the data block number to a free block, 1033 * Convert the data block number to a free block,
915 * read in the free block. 1034 * read in the free block.
916 */ 1035 */
917 fdb = xfs_dir2_db_to_fdb(mp, db); 1036 fdb = xfs_dir2_db_to_fdb(mp, db);
918 error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, fdb), 1037 error = xfs_dir2_free_read(tp, dp, xfs_dir2_db_to_da(mp, fdb),
919 -1, &fbp, XFS_DATA_FORK, NULL); 1038 &fbp);
920 if (error) 1039 if (error)
921 return error; 1040 return error;
922 free = fbp->b_addr; 1041 free = fbp->b_addr;
@@ -954,68 +1073,12 @@ xfs_dir2_leafn_remove(
954 * If we got rid of the data block, we can eliminate that entry 1073 * If we got rid of the data block, we can eliminate that entry
955 * in the free block. 1074 * in the free block.
956 */ 1075 */
957 if (hdr == NULL) { 1076 error = xfs_dir2_data_block_free(args, hdr, free,
958 /* 1077 fdb, findex, fbp, longest);
959 * One less used entry in the free table. 1078 if (error)
960 */ 1079 return error;
961 be32_add_cpu(&free->hdr.nused, -1);
962 xfs_dir2_free_log_header(tp, fbp);
963 /*
964 * If this was the last entry in the table, we can
965 * trim the table size back. There might be other
966 * entries at the end referring to non-existent
967 * data blocks, get those too.
968 */
969 if (findex == be32_to_cpu(free->hdr.nvalid) - 1) {
970 int i; /* free entry index */
971
972 for (i = findex - 1;
973 i >= 0 &&
974 free->bests[i] == cpu_to_be16(NULLDATAOFF);
975 i--)
976 continue;
977 free->hdr.nvalid = cpu_to_be32(i + 1);
978 logfree = 0;
979 }
980 /*
981 * Not the last entry, just punch it out.
982 */
983 else {
984 free->bests[findex] = cpu_to_be16(NULLDATAOFF);
985 logfree = 1;
986 }
987 /*
988 * If there are no useful entries left in the block,
989 * get rid of the block if we can.
990 */
991 if (!free->hdr.nused) {
992 error = xfs_dir2_shrink_inode(args, fdb, fbp);
993 if (error == 0) {
994 fbp = NULL;
995 logfree = 0;
996 } else if (error != ENOSPC || args->total != 0)
997 return error;
998 /*
999 * It's possible to get ENOSPC if there is no
1000 * space reservation. In this case some one
1001 * else will eventually get rid of this block.
1002 */
1003 }
1004 }
1005 /*
1006 * Data block is not empty, just set the free entry to
1007 * the new value.
1008 */
1009 else {
1010 free->bests[findex] = cpu_to_be16(longest);
1011 logfree = 1;
1012 }
1013 /*
1014 * Log the free entry that changed, unless we got rid of it.
1015 */
1016 if (logfree)
1017 xfs_dir2_free_log_bests(tp, fbp, findex, findex);
1018 } 1080 }
1081
1019 xfs_dir2_leafn_check(dp, bp); 1082 xfs_dir2_leafn_check(dp, bp);
1020 /* 1083 /*
1021 * Return indication of whether this leaf block is empty enough 1084 * Return indication of whether this leaf block is empty enough
@@ -1453,9 +1516,9 @@ xfs_dir2_node_addname_int(
1453 * This should be really rare, so there's no reason 1516 * This should be really rare, so there's no reason
1454 * to avoid it. 1517 * to avoid it.
1455 */ 1518 */
1456 error = xfs_da_read_buf(tp, dp, 1519 error = xfs_dir2_free_try_read(tp, dp,
1457 xfs_dir2_db_to_da(mp, fbno), -2, 1520 xfs_dir2_db_to_da(mp, fbno),
1458 &fbp, XFS_DATA_FORK, NULL); 1521 &fbp);
1459 if (error) 1522 if (error)
1460 return error; 1523 return error;
1461 if (!fbp) 1524 if (!fbp)
@@ -1518,8 +1581,9 @@ xfs_dir2_node_addname_int(
1518 * that was just allocated. 1581 * that was just allocated.
1519 */ 1582 */
1520 fbno = xfs_dir2_db_to_fdb(mp, dbno); 1583 fbno = xfs_dir2_db_to_fdb(mp, dbno);
1521 error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp, fbno), -2, 1584 error = xfs_dir2_free_try_read(tp, dp,
1522 &fbp, XFS_DATA_FORK, NULL); 1585 xfs_dir2_db_to_da(mp, fbno),
1586 &fbp);
1523 if (error) 1587 if (error)
1524 return error; 1588 return error;
1525 1589
@@ -1915,17 +1979,15 @@ xfs_dir2_node_trim_free(
1915 /* 1979 /*
1916 * Read the freespace block. 1980 * Read the freespace block.
1917 */ 1981 */
1918 error = xfs_da_read_buf(tp, dp, (xfs_dablk_t)fo, -2, &bp, 1982 error = xfs_dir2_free_try_read(tp, dp, fo, &bp);
1919 XFS_DATA_FORK, NULL);
1920 if (error) 1983 if (error)
1921 return error; 1984 return error;
1922 /* 1985 /*
1923 * There can be holes in freespace. If fo is a hole, there's 1986 * There can be holes in freespace. If fo is a hole, there's
1924 * nothing to do. 1987 * nothing to do.
1925 */ 1988 */
1926 if (bp == NULL) { 1989 if (!bp)
1927 return 0; 1990 return 0;
1928 }
1929 free = bp->b_addr; 1991 free = bp->b_addr;
1930 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC)); 1992 ASSERT(free->hdr.magic == cpu_to_be32(XFS_DIR2_FREE_MAGIC));
1931 /* 1993 /*
diff --git a/fs/xfs/xfs_dir2_priv.h b/fs/xfs/xfs_dir2_priv.h
index 93b8f66ae788..263a63287910 100644
--- a/fs/xfs/xfs_dir2_priv.h
+++ b/fs/xfs/xfs_dir2_priv.h
@@ -117,6 +117,8 @@ extern int xfs_dir2_node_removename(struct xfs_da_args *args);
117extern int xfs_dir2_node_replace(struct xfs_da_args *args); 117extern int xfs_dir2_node_replace(struct xfs_da_args *args);
118extern int xfs_dir2_node_trim_free(struct xfs_da_args *args, xfs_fileoff_t fo, 118extern int xfs_dir2_node_trim_free(struct xfs_da_args *args, xfs_fileoff_t fo,
119 int *rvalp); 119 int *rvalp);
120extern int xfs_dir2_free_read(struct xfs_trans *tp, struct xfs_inode *dp,
121 xfs_dablk_t fbno, struct xfs_buf **bpp);
120 122
121/* xfs_dir2_sf.c */ 123/* xfs_dir2_sf.c */
122extern xfs_ino_t xfs_dir2_sf_get_parent_ino(struct xfs_dir2_sf_hdr *sfp); 124extern xfs_ino_t xfs_dir2_sf_get_parent_ino(struct xfs_dir2_sf_hdr *sfp);