diff options
author | Dave Chinner <dchinner@redhat.com> | 2012-11-12 06:54:13 -0500 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2012-11-15 22:34:43 -0500 |
commit | 2025207ca6738a1217126ef14af9d104433f9824 (patch) | |
tree | 522cac64d22f59063e16e7e2aec5a1688fa77a6b /fs | |
parent | 82025d7f79148fe66a1594a0ebe4ab38152cf9e6 (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.c | 3 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_node.c | 218 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_priv.h | 2 |
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, | |||
55 | static int xfs_dir2_node_addname_int(xfs_da_args_t *args, | 55 | static 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 | ||
58 | static void | ||
59 | xfs_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 | |||
77 | static 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 | |||
89 | int | ||
90 | xfs_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 | |||
99 | static int | ||
100 | xfs_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 | ||
877 | static int | ||
878 | xfs_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); | |||
117 | extern int xfs_dir2_node_replace(struct xfs_da_args *args); | 117 | extern int xfs_dir2_node_replace(struct xfs_da_args *args); |
118 | extern int xfs_dir2_node_trim_free(struct xfs_da_args *args, xfs_fileoff_t fo, | 118 | extern int xfs_dir2_node_trim_free(struct xfs_da_args *args, xfs_fileoff_t fo, |
119 | int *rvalp); | 119 | int *rvalp); |
120 | extern 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 */ |
122 | extern xfs_ino_t xfs_dir2_sf_get_parent_ino(struct xfs_dir2_sf_hdr *sfp); | 124 | extern xfs_ino_t xfs_dir2_sf_get_parent_ino(struct xfs_dir2_sf_hdr *sfp); |