diff options
Diffstat (limited to 'fs/xfs/xfs_attr.c')
-rw-r--r-- | fs/xfs/xfs_attr.c | 454 |
1 files changed, 85 insertions, 369 deletions
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index 888683844d98..20fe3fe9d341 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c | |||
@@ -15,7 +15,6 @@ | |||
15 | * along with this program; if not, write the Free Software Foundation, | 15 | * along with this program; if not, write the Free Software Foundation, |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | |||
19 | #include "xfs.h" | 18 | #include "xfs.h" |
20 | #include "xfs_fs.h" | 19 | #include "xfs_fs.h" |
21 | #include "xfs_types.h" | 20 | #include "xfs_types.h" |
@@ -35,6 +34,7 @@ | |||
35 | #include "xfs_bmap.h" | 34 | #include "xfs_bmap.h" |
36 | #include "xfs_attr.h" | 35 | #include "xfs_attr.h" |
37 | #include "xfs_attr_leaf.h" | 36 | #include "xfs_attr_leaf.h" |
37 | #include "xfs_attr_remote.h" | ||
38 | #include "xfs_error.h" | 38 | #include "xfs_error.h" |
39 | #include "xfs_quota.h" | 39 | #include "xfs_quota.h" |
40 | #include "xfs_trans_space.h" | 40 | #include "xfs_trans_space.h" |
@@ -74,13 +74,6 @@ STATIC int xfs_attr_node_list(xfs_attr_list_context_t *context); | |||
74 | STATIC int xfs_attr_fillstate(xfs_da_state_t *state); | 74 | STATIC int xfs_attr_fillstate(xfs_da_state_t *state); |
75 | STATIC int xfs_attr_refillstate(xfs_da_state_t *state); | 75 | STATIC int xfs_attr_refillstate(xfs_da_state_t *state); |
76 | 76 | ||
77 | /* | ||
78 | * Routines to manipulate out-of-line attribute values. | ||
79 | */ | ||
80 | STATIC int xfs_attr_rmtval_set(xfs_da_args_t *args); | ||
81 | STATIC int xfs_attr_rmtval_remove(xfs_da_args_t *args); | ||
82 | |||
83 | #define ATTR_RMTVALUE_MAPSIZE 1 /* # of map entries at once */ | ||
84 | 77 | ||
85 | STATIC int | 78 | STATIC int |
86 | xfs_attr_name_to_xname( | 79 | xfs_attr_name_to_xname( |
@@ -820,7 +813,7 @@ xfs_attr_inactive(xfs_inode_t *dp) | |||
820 | error = 0; | 813 | error = 0; |
821 | goto out; | 814 | goto out; |
822 | } | 815 | } |
823 | error = xfs_attr_root_inactive(&trans, dp); | 816 | error = xfs_attr3_root_inactive(&trans, dp); |
824 | if (error) | 817 | if (error) |
825 | goto out; | 818 | goto out; |
826 | 819 | ||
@@ -906,7 +899,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) | |||
906 | */ | 899 | */ |
907 | dp = args->dp; | 900 | dp = args->dp; |
908 | args->blkno = 0; | 901 | args->blkno = 0; |
909 | error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno, -1, &bp); | 902 | error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp); |
910 | if (error) | 903 | if (error) |
911 | return error; | 904 | return error; |
912 | 905 | ||
@@ -914,14 +907,14 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) | |||
914 | * Look up the given attribute in the leaf block. Figure out if | 907 | * Look up the given attribute in the leaf block. Figure out if |
915 | * the given flags produce an error or call for an atomic rename. | 908 | * the given flags produce an error or call for an atomic rename. |
916 | */ | 909 | */ |
917 | retval = xfs_attr_leaf_lookup_int(bp, args); | 910 | retval = xfs_attr3_leaf_lookup_int(bp, args); |
918 | if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) { | 911 | if ((args->flags & ATTR_REPLACE) && (retval == ENOATTR)) { |
919 | xfs_trans_brelse(args->trans, bp); | 912 | xfs_trans_brelse(args->trans, bp); |
920 | return(retval); | 913 | return retval; |
921 | } else if (retval == EEXIST) { | 914 | } else if (retval == EEXIST) { |
922 | if (args->flags & ATTR_CREATE) { /* pure create op */ | 915 | if (args->flags & ATTR_CREATE) { /* pure create op */ |
923 | xfs_trans_brelse(args->trans, bp); | 916 | xfs_trans_brelse(args->trans, bp); |
924 | return(retval); | 917 | return retval; |
925 | } | 918 | } |
926 | 919 | ||
927 | trace_xfs_attr_leaf_replace(args); | 920 | trace_xfs_attr_leaf_replace(args); |
@@ -937,7 +930,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) | |||
937 | * Add the attribute to the leaf block, transitioning to a Btree | 930 | * Add the attribute to the leaf block, transitioning to a Btree |
938 | * if required. | 931 | * if required. |
939 | */ | 932 | */ |
940 | retval = xfs_attr_leaf_add(bp, args); | 933 | retval = xfs_attr3_leaf_add(bp, args); |
941 | if (retval == ENOSPC) { | 934 | if (retval == ENOSPC) { |
942 | /* | 935 | /* |
943 | * Promote the attribute list to the Btree format, then | 936 | * Promote the attribute list to the Btree format, then |
@@ -945,7 +938,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) | |||
945 | * can manage its own transactions. | 938 | * can manage its own transactions. |
946 | */ | 939 | */ |
947 | xfs_bmap_init(args->flist, args->firstblock); | 940 | xfs_bmap_init(args->flist, args->firstblock); |
948 | error = xfs_attr_leaf_to_node(args); | 941 | error = xfs_attr3_leaf_to_node(args); |
949 | if (!error) { | 942 | if (!error) { |
950 | error = xfs_bmap_finish(&args->trans, args->flist, | 943 | error = xfs_bmap_finish(&args->trans, args->flist, |
951 | &committed); | 944 | &committed); |
@@ -1010,7 +1003,7 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) | |||
1010 | * In a separate transaction, set the incomplete flag on the | 1003 | * In a separate transaction, set the incomplete flag on the |
1011 | * "old" attr and clear the incomplete flag on the "new" attr. | 1004 | * "old" attr and clear the incomplete flag on the "new" attr. |
1012 | */ | 1005 | */ |
1013 | error = xfs_attr_leaf_flipflags(args); | 1006 | error = xfs_attr3_leaf_flipflags(args); |
1014 | if (error) | 1007 | if (error) |
1015 | return(error); | 1008 | return(error); |
1016 | 1009 | ||
@@ -1032,19 +1025,19 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) | |||
1032 | * Read in the block containing the "old" attr, then | 1025 | * Read in the block containing the "old" attr, then |
1033 | * remove the "old" attr from that block (neat, huh!) | 1026 | * remove the "old" attr from that block (neat, huh!) |
1034 | */ | 1027 | */ |
1035 | error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno, | 1028 | error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, |
1036 | -1, &bp); | 1029 | -1, &bp); |
1037 | if (error) | 1030 | if (error) |
1038 | return error; | 1031 | return error; |
1039 | 1032 | ||
1040 | xfs_attr_leaf_remove(bp, args); | 1033 | xfs_attr3_leaf_remove(bp, args); |
1041 | 1034 | ||
1042 | /* | 1035 | /* |
1043 | * If the result is small enough, shrink it all into the inode. | 1036 | * If the result is small enough, shrink it all into the inode. |
1044 | */ | 1037 | */ |
1045 | if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { | 1038 | if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { |
1046 | xfs_bmap_init(args->flist, args->firstblock); | 1039 | xfs_bmap_init(args->flist, args->firstblock); |
1047 | error = xfs_attr_leaf_to_shortform(bp, args, forkoff); | 1040 | error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); |
1048 | /* bp is gone due to xfs_da_shrink_inode */ | 1041 | /* bp is gone due to xfs_da_shrink_inode */ |
1049 | if (!error) { | 1042 | if (!error) { |
1050 | error = xfs_bmap_finish(&args->trans, | 1043 | error = xfs_bmap_finish(&args->trans, |
@@ -1076,9 +1069,9 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) | |||
1076 | /* | 1069 | /* |
1077 | * Added a "remote" value, just clear the incomplete flag. | 1070 | * Added a "remote" value, just clear the incomplete flag. |
1078 | */ | 1071 | */ |
1079 | error = xfs_attr_leaf_clearflag(args); | 1072 | error = xfs_attr3_leaf_clearflag(args); |
1080 | } | 1073 | } |
1081 | return(error); | 1074 | return error; |
1082 | } | 1075 | } |
1083 | 1076 | ||
1084 | /* | 1077 | /* |
@@ -1101,24 +1094,24 @@ xfs_attr_leaf_removename(xfs_da_args_t *args) | |||
1101 | */ | 1094 | */ |
1102 | dp = args->dp; | 1095 | dp = args->dp; |
1103 | args->blkno = 0; | 1096 | args->blkno = 0; |
1104 | error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno, -1, &bp); | 1097 | error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp); |
1105 | if (error) | 1098 | if (error) |
1106 | return error; | 1099 | return error; |
1107 | 1100 | ||
1108 | error = xfs_attr_leaf_lookup_int(bp, args); | 1101 | error = xfs_attr3_leaf_lookup_int(bp, args); |
1109 | if (error == ENOATTR) { | 1102 | if (error == ENOATTR) { |
1110 | xfs_trans_brelse(args->trans, bp); | 1103 | xfs_trans_brelse(args->trans, bp); |
1111 | return(error); | 1104 | return error; |
1112 | } | 1105 | } |
1113 | 1106 | ||
1114 | xfs_attr_leaf_remove(bp, args); | 1107 | xfs_attr3_leaf_remove(bp, args); |
1115 | 1108 | ||
1116 | /* | 1109 | /* |
1117 | * If the result is small enough, shrink it all into the inode. | 1110 | * If the result is small enough, shrink it all into the inode. |
1118 | */ | 1111 | */ |
1119 | if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { | 1112 | if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { |
1120 | xfs_bmap_init(args->flist, args->firstblock); | 1113 | xfs_bmap_init(args->flist, args->firstblock); |
1121 | error = xfs_attr_leaf_to_shortform(bp, args, forkoff); | 1114 | error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); |
1122 | /* bp is gone due to xfs_da_shrink_inode */ | 1115 | /* bp is gone due to xfs_da_shrink_inode */ |
1123 | if (!error) { | 1116 | if (!error) { |
1124 | error = xfs_bmap_finish(&args->trans, args->flist, | 1117 | error = xfs_bmap_finish(&args->trans, args->flist, |
@@ -1128,7 +1121,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args) | |||
1128 | ASSERT(committed); | 1121 | ASSERT(committed); |
1129 | args->trans = NULL; | 1122 | args->trans = NULL; |
1130 | xfs_bmap_cancel(args->flist); | 1123 | xfs_bmap_cancel(args->flist); |
1131 | return(error); | 1124 | return error; |
1132 | } | 1125 | } |
1133 | 1126 | ||
1134 | /* | 1127 | /* |
@@ -1138,7 +1131,7 @@ xfs_attr_leaf_removename(xfs_da_args_t *args) | |||
1138 | if (committed) | 1131 | if (committed) |
1139 | xfs_trans_ijoin(args->trans, dp, 0); | 1132 | xfs_trans_ijoin(args->trans, dp, 0); |
1140 | } | 1133 | } |
1141 | return(0); | 1134 | return 0; |
1142 | } | 1135 | } |
1143 | 1136 | ||
1144 | /* | 1137 | /* |
@@ -1156,21 +1149,21 @@ xfs_attr_leaf_get(xfs_da_args_t *args) | |||
1156 | trace_xfs_attr_leaf_get(args); | 1149 | trace_xfs_attr_leaf_get(args); |
1157 | 1150 | ||
1158 | args->blkno = 0; | 1151 | args->blkno = 0; |
1159 | error = xfs_attr_leaf_read(args->trans, args->dp, args->blkno, -1, &bp); | 1152 | error = xfs_attr3_leaf_read(args->trans, args->dp, args->blkno, -1, &bp); |
1160 | if (error) | 1153 | if (error) |
1161 | return error; | 1154 | return error; |
1162 | 1155 | ||
1163 | error = xfs_attr_leaf_lookup_int(bp, args); | 1156 | error = xfs_attr3_leaf_lookup_int(bp, args); |
1164 | if (error != EEXIST) { | 1157 | if (error != EEXIST) { |
1165 | xfs_trans_brelse(args->trans, bp); | 1158 | xfs_trans_brelse(args->trans, bp); |
1166 | return(error); | 1159 | return error; |
1167 | } | 1160 | } |
1168 | error = xfs_attr_leaf_getvalue(bp, args); | 1161 | error = xfs_attr3_leaf_getvalue(bp, args); |
1169 | xfs_trans_brelse(args->trans, bp); | 1162 | xfs_trans_brelse(args->trans, bp); |
1170 | if (!error && (args->rmtblkno > 0) && !(args->flags & ATTR_KERNOVAL)) { | 1163 | if (!error && (args->rmtblkno > 0) && !(args->flags & ATTR_KERNOVAL)) { |
1171 | error = xfs_attr_rmtval_get(args); | 1164 | error = xfs_attr_rmtval_get(args); |
1172 | } | 1165 | } |
1173 | return(error); | 1166 | return error; |
1174 | } | 1167 | } |
1175 | 1168 | ||
1176 | /* | 1169 | /* |
@@ -1185,11 +1178,11 @@ xfs_attr_leaf_list(xfs_attr_list_context_t *context) | |||
1185 | trace_xfs_attr_leaf_list(context); | 1178 | trace_xfs_attr_leaf_list(context); |
1186 | 1179 | ||
1187 | context->cursor->blkno = 0; | 1180 | context->cursor->blkno = 0; |
1188 | error = xfs_attr_leaf_read(NULL, context->dp, 0, -1, &bp); | 1181 | error = xfs_attr3_leaf_read(NULL, context->dp, 0, -1, &bp); |
1189 | if (error) | 1182 | if (error) |
1190 | return XFS_ERROR(error); | 1183 | return XFS_ERROR(error); |
1191 | 1184 | ||
1192 | error = xfs_attr_leaf_list_int(bp, context); | 1185 | error = xfs_attr3_leaf_list_int(bp, context); |
1193 | xfs_trans_brelse(NULL, bp); | 1186 | xfs_trans_brelse(NULL, bp); |
1194 | return XFS_ERROR(error); | 1187 | return XFS_ERROR(error); |
1195 | } | 1188 | } |
@@ -1236,7 +1229,7 @@ restart: | |||
1236 | * Search to see if name already exists, and get back a pointer | 1229 | * Search to see if name already exists, and get back a pointer |
1237 | * to where it should go. | 1230 | * to where it should go. |
1238 | */ | 1231 | */ |
1239 | error = xfs_da_node_lookup_int(state, &retval); | 1232 | error = xfs_da3_node_lookup_int(state, &retval); |
1240 | if (error) | 1233 | if (error) |
1241 | goto out; | 1234 | goto out; |
1242 | blk = &state->path.blk[ state->path.active-1 ]; | 1235 | blk = &state->path.blk[ state->path.active-1 ]; |
@@ -1258,7 +1251,7 @@ restart: | |||
1258 | args->rmtblkcnt = 0; | 1251 | args->rmtblkcnt = 0; |
1259 | } | 1252 | } |
1260 | 1253 | ||
1261 | retval = xfs_attr_leaf_add(blk->bp, state->args); | 1254 | retval = xfs_attr3_leaf_add(blk->bp, state->args); |
1262 | if (retval == ENOSPC) { | 1255 | if (retval == ENOSPC) { |
1263 | if (state->path.active == 1) { | 1256 | if (state->path.active == 1) { |
1264 | /* | 1257 | /* |
@@ -1268,7 +1261,7 @@ restart: | |||
1268 | */ | 1261 | */ |
1269 | xfs_da_state_free(state); | 1262 | xfs_da_state_free(state); |
1270 | xfs_bmap_init(args->flist, args->firstblock); | 1263 | xfs_bmap_init(args->flist, args->firstblock); |
1271 | error = xfs_attr_leaf_to_node(args); | 1264 | error = xfs_attr3_leaf_to_node(args); |
1272 | if (!error) { | 1265 | if (!error) { |
1273 | error = xfs_bmap_finish(&args->trans, | 1266 | error = xfs_bmap_finish(&args->trans, |
1274 | args->flist, | 1267 | args->flist, |
@@ -1307,7 +1300,7 @@ restart: | |||
1307 | * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields. | 1300 | * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields. |
1308 | */ | 1301 | */ |
1309 | xfs_bmap_init(args->flist, args->firstblock); | 1302 | xfs_bmap_init(args->flist, args->firstblock); |
1310 | error = xfs_da_split(state); | 1303 | error = xfs_da3_split(state); |
1311 | if (!error) { | 1304 | if (!error) { |
1312 | error = xfs_bmap_finish(&args->trans, args->flist, | 1305 | error = xfs_bmap_finish(&args->trans, args->flist, |
1313 | &committed); | 1306 | &committed); |
@@ -1329,7 +1322,7 @@ restart: | |||
1329 | /* | 1322 | /* |
1330 | * Addition succeeded, update Btree hashvals. | 1323 | * Addition succeeded, update Btree hashvals. |
1331 | */ | 1324 | */ |
1332 | xfs_da_fixhashpath(state, &state->path); | 1325 | xfs_da3_fixhashpath(state, &state->path); |
1333 | } | 1326 | } |
1334 | 1327 | ||
1335 | /* | 1328 | /* |
@@ -1370,7 +1363,7 @@ restart: | |||
1370 | * In a separate transaction, set the incomplete flag on the | 1363 | * In a separate transaction, set the incomplete flag on the |
1371 | * "old" attr and clear the incomplete flag on the "new" attr. | 1364 | * "old" attr and clear the incomplete flag on the "new" attr. |
1372 | */ | 1365 | */ |
1373 | error = xfs_attr_leaf_flipflags(args); | 1366 | error = xfs_attr3_leaf_flipflags(args); |
1374 | if (error) | 1367 | if (error) |
1375 | goto out; | 1368 | goto out; |
1376 | 1369 | ||
@@ -1400,7 +1393,7 @@ restart: | |||
1400 | state->blocksize = state->mp->m_sb.sb_blocksize; | 1393 | state->blocksize = state->mp->m_sb.sb_blocksize; |
1401 | state->node_ents = state->mp->m_attr_node_ents; | 1394 | state->node_ents = state->mp->m_attr_node_ents; |
1402 | state->inleaf = 0; | 1395 | state->inleaf = 0; |
1403 | error = xfs_da_node_lookup_int(state, &retval); | 1396 | error = xfs_da3_node_lookup_int(state, &retval); |
1404 | if (error) | 1397 | if (error) |
1405 | goto out; | 1398 | goto out; |
1406 | 1399 | ||
@@ -1409,15 +1402,15 @@ restart: | |||
1409 | */ | 1402 | */ |
1410 | blk = &state->path.blk[ state->path.active-1 ]; | 1403 | blk = &state->path.blk[ state->path.active-1 ]; |
1411 | ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC); | 1404 | ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC); |
1412 | error = xfs_attr_leaf_remove(blk->bp, args); | 1405 | error = xfs_attr3_leaf_remove(blk->bp, args); |
1413 | xfs_da_fixhashpath(state, &state->path); | 1406 | xfs_da3_fixhashpath(state, &state->path); |
1414 | 1407 | ||
1415 | /* | 1408 | /* |
1416 | * Check to see if the tree needs to be collapsed. | 1409 | * Check to see if the tree needs to be collapsed. |
1417 | */ | 1410 | */ |
1418 | if (retval && (state->path.active > 1)) { | 1411 | if (retval && (state->path.active > 1)) { |
1419 | xfs_bmap_init(args->flist, args->firstblock); | 1412 | xfs_bmap_init(args->flist, args->firstblock); |
1420 | error = xfs_da_join(state); | 1413 | error = xfs_da3_join(state); |
1421 | if (!error) { | 1414 | if (!error) { |
1422 | error = xfs_bmap_finish(&args->trans, | 1415 | error = xfs_bmap_finish(&args->trans, |
1423 | args->flist, | 1416 | args->flist, |
@@ -1450,7 +1443,7 @@ restart: | |||
1450 | /* | 1443 | /* |
1451 | * Added a "remote" value, just clear the incomplete flag. | 1444 | * Added a "remote" value, just clear the incomplete flag. |
1452 | */ | 1445 | */ |
1453 | error = xfs_attr_leaf_clearflag(args); | 1446 | error = xfs_attr3_leaf_clearflag(args); |
1454 | if (error) | 1447 | if (error) |
1455 | goto out; | 1448 | goto out; |
1456 | } | 1449 | } |
@@ -1495,7 +1488,7 @@ xfs_attr_node_removename(xfs_da_args_t *args) | |||
1495 | /* | 1488 | /* |
1496 | * Search to see if name exists, and get back a pointer to it. | 1489 | * Search to see if name exists, and get back a pointer to it. |
1497 | */ | 1490 | */ |
1498 | error = xfs_da_node_lookup_int(state, &retval); | 1491 | error = xfs_da3_node_lookup_int(state, &retval); |
1499 | if (error || (retval != EEXIST)) { | 1492 | if (error || (retval != EEXIST)) { |
1500 | if (error == 0) | 1493 | if (error == 0) |
1501 | error = retval; | 1494 | error = retval; |
@@ -1524,7 +1517,7 @@ xfs_attr_node_removename(xfs_da_args_t *args) | |||
1524 | * Mark the attribute as INCOMPLETE, then bunmapi() the | 1517 | * Mark the attribute as INCOMPLETE, then bunmapi() the |
1525 | * remote value. | 1518 | * remote value. |
1526 | */ | 1519 | */ |
1527 | error = xfs_attr_leaf_setflag(args); | 1520 | error = xfs_attr3_leaf_setflag(args); |
1528 | if (error) | 1521 | if (error) |
1529 | goto out; | 1522 | goto out; |
1530 | error = xfs_attr_rmtval_remove(args); | 1523 | error = xfs_attr_rmtval_remove(args); |
@@ -1545,15 +1538,15 @@ xfs_attr_node_removename(xfs_da_args_t *args) | |||
1545 | */ | 1538 | */ |
1546 | blk = &state->path.blk[ state->path.active-1 ]; | 1539 | blk = &state->path.blk[ state->path.active-1 ]; |
1547 | ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC); | 1540 | ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC); |
1548 | retval = xfs_attr_leaf_remove(blk->bp, args); | 1541 | retval = xfs_attr3_leaf_remove(blk->bp, args); |
1549 | xfs_da_fixhashpath(state, &state->path); | 1542 | xfs_da3_fixhashpath(state, &state->path); |
1550 | 1543 | ||
1551 | /* | 1544 | /* |
1552 | * Check to see if the tree needs to be collapsed. | 1545 | * Check to see if the tree needs to be collapsed. |
1553 | */ | 1546 | */ |
1554 | if (retval && (state->path.active > 1)) { | 1547 | if (retval && (state->path.active > 1)) { |
1555 | xfs_bmap_init(args->flist, args->firstblock); | 1548 | xfs_bmap_init(args->flist, args->firstblock); |
1556 | error = xfs_da_join(state); | 1549 | error = xfs_da3_join(state); |
1557 | if (!error) { | 1550 | if (!error) { |
1558 | error = xfs_bmap_finish(&args->trans, args->flist, | 1551 | error = xfs_bmap_finish(&args->trans, args->flist, |
1559 | &committed); | 1552 | &committed); |
@@ -1591,13 +1584,13 @@ xfs_attr_node_removename(xfs_da_args_t *args) | |||
1591 | ASSERT(state->path.blk[0].bp); | 1584 | ASSERT(state->path.blk[0].bp); |
1592 | state->path.blk[0].bp = NULL; | 1585 | state->path.blk[0].bp = NULL; |
1593 | 1586 | ||
1594 | error = xfs_attr_leaf_read(args->trans, args->dp, 0, -1, &bp); | 1587 | error = xfs_attr3_leaf_read(args->trans, args->dp, 0, -1, &bp); |
1595 | if (error) | 1588 | if (error) |
1596 | goto out; | 1589 | goto out; |
1597 | 1590 | ||
1598 | if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { | 1591 | if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { |
1599 | xfs_bmap_init(args->flist, args->firstblock); | 1592 | xfs_bmap_init(args->flist, args->firstblock); |
1600 | error = xfs_attr_leaf_to_shortform(bp, args, forkoff); | 1593 | error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); |
1601 | /* bp is gone due to xfs_da_shrink_inode */ | 1594 | /* bp is gone due to xfs_da_shrink_inode */ |
1602 | if (!error) { | 1595 | if (!error) { |
1603 | error = xfs_bmap_finish(&args->trans, | 1596 | error = xfs_bmap_finish(&args->trans, |
@@ -1699,7 +1692,7 @@ xfs_attr_refillstate(xfs_da_state_t *state) | |||
1699 | ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); | 1692 | ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); |
1700 | for (blk = path->blk, level = 0; level < path->active; blk++, level++) { | 1693 | for (blk = path->blk, level = 0; level < path->active; blk++, level++) { |
1701 | if (blk->disk_blkno) { | 1694 | if (blk->disk_blkno) { |
1702 | error = xfs_da_node_read(state->args->trans, | 1695 | error = xfs_da3_node_read(state->args->trans, |
1703 | state->args->dp, | 1696 | state->args->dp, |
1704 | blk->blkno, blk->disk_blkno, | 1697 | blk->blkno, blk->disk_blkno, |
1705 | &blk->bp, XFS_ATTR_FORK); | 1698 | &blk->bp, XFS_ATTR_FORK); |
@@ -1718,7 +1711,7 @@ xfs_attr_refillstate(xfs_da_state_t *state) | |||
1718 | ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); | 1711 | ASSERT((path->active >= 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); |
1719 | for (blk = path->blk, level = 0; level < path->active; blk++, level++) { | 1712 | for (blk = path->blk, level = 0; level < path->active; blk++, level++) { |
1720 | if (blk->disk_blkno) { | 1713 | if (blk->disk_blkno) { |
1721 | error = xfs_da_node_read(state->args->trans, | 1714 | error = xfs_da3_node_read(state->args->trans, |
1722 | state->args->dp, | 1715 | state->args->dp, |
1723 | blk->blkno, blk->disk_blkno, | 1716 | blk->blkno, blk->disk_blkno, |
1724 | &blk->bp, XFS_ATTR_FORK); | 1717 | &blk->bp, XFS_ATTR_FORK); |
@@ -1758,7 +1751,7 @@ xfs_attr_node_get(xfs_da_args_t *args) | |||
1758 | /* | 1751 | /* |
1759 | * Search to see if name exists, and get back a pointer to it. | 1752 | * Search to see if name exists, and get back a pointer to it. |
1760 | */ | 1753 | */ |
1761 | error = xfs_da_node_lookup_int(state, &retval); | 1754 | error = xfs_da3_node_lookup_int(state, &retval); |
1762 | if (error) { | 1755 | if (error) { |
1763 | retval = error; | 1756 | retval = error; |
1764 | } else if (retval == EEXIST) { | 1757 | } else if (retval == EEXIST) { |
@@ -1769,7 +1762,7 @@ xfs_attr_node_get(xfs_da_args_t *args) | |||
1769 | /* | 1762 | /* |
1770 | * Get the value, local or "remote" | 1763 | * Get the value, local or "remote" |
1771 | */ | 1764 | */ |
1772 | retval = xfs_attr_leaf_getvalue(blk->bp, args); | 1765 | retval = xfs_attr3_leaf_getvalue(blk->bp, args); |
1773 | if (!retval && (args->rmtblkno > 0) | 1766 | if (!retval && (args->rmtblkno > 0) |
1774 | && !(args->flags & ATTR_KERNOVAL)) { | 1767 | && !(args->flags & ATTR_KERNOVAL)) { |
1775 | retval = xfs_attr_rmtval_get(args); | 1768 | retval = xfs_attr_rmtval_get(args); |
@@ -1794,7 +1787,9 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) | |||
1794 | attrlist_cursor_kern_t *cursor; | 1787 | attrlist_cursor_kern_t *cursor; |
1795 | xfs_attr_leafblock_t *leaf; | 1788 | xfs_attr_leafblock_t *leaf; |
1796 | xfs_da_intnode_t *node; | 1789 | xfs_da_intnode_t *node; |
1797 | xfs_da_node_entry_t *btree; | 1790 | struct xfs_attr3_icleaf_hdr leafhdr; |
1791 | struct xfs_da3_icnode_hdr nodehdr; | ||
1792 | struct xfs_da_node_entry *btree; | ||
1798 | int error, i; | 1793 | int error, i; |
1799 | struct xfs_buf *bp; | 1794 | struct xfs_buf *bp; |
1800 | 1795 | ||
@@ -1810,27 +1805,33 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) | |||
1810 | */ | 1805 | */ |
1811 | bp = NULL; | 1806 | bp = NULL; |
1812 | if (cursor->blkno > 0) { | 1807 | if (cursor->blkno > 0) { |
1813 | error = xfs_da_node_read(NULL, context->dp, cursor->blkno, -1, | 1808 | error = xfs_da3_node_read(NULL, context->dp, cursor->blkno, -1, |
1814 | &bp, XFS_ATTR_FORK); | 1809 | &bp, XFS_ATTR_FORK); |
1815 | if ((error != 0) && (error != EFSCORRUPTED)) | 1810 | if ((error != 0) && (error != EFSCORRUPTED)) |
1816 | return(error); | 1811 | return(error); |
1817 | if (bp) { | 1812 | if (bp) { |
1813 | struct xfs_attr_leaf_entry *entries; | ||
1814 | |||
1818 | node = bp->b_addr; | 1815 | node = bp->b_addr; |
1819 | switch (be16_to_cpu(node->hdr.info.magic)) { | 1816 | switch (be16_to_cpu(node->hdr.info.magic)) { |
1820 | case XFS_DA_NODE_MAGIC: | 1817 | case XFS_DA_NODE_MAGIC: |
1818 | case XFS_DA3_NODE_MAGIC: | ||
1821 | trace_xfs_attr_list_wrong_blk(context); | 1819 | trace_xfs_attr_list_wrong_blk(context); |
1822 | xfs_trans_brelse(NULL, bp); | 1820 | xfs_trans_brelse(NULL, bp); |
1823 | bp = NULL; | 1821 | bp = NULL; |
1824 | break; | 1822 | break; |
1825 | case XFS_ATTR_LEAF_MAGIC: | 1823 | case XFS_ATTR_LEAF_MAGIC: |
1824 | case XFS_ATTR3_LEAF_MAGIC: | ||
1826 | leaf = bp->b_addr; | 1825 | leaf = bp->b_addr; |
1827 | if (cursor->hashval > be32_to_cpu(leaf->entries[ | 1826 | xfs_attr3_leaf_hdr_from_disk(&leafhdr, leaf); |
1828 | be16_to_cpu(leaf->hdr.count)-1].hashval)) { | 1827 | entries = xfs_attr3_leaf_entryp(leaf); |
1828 | if (cursor->hashval > be32_to_cpu( | ||
1829 | entries[leafhdr.count - 1].hashval)) { | ||
1829 | trace_xfs_attr_list_wrong_blk(context); | 1830 | trace_xfs_attr_list_wrong_blk(context); |
1830 | xfs_trans_brelse(NULL, bp); | 1831 | xfs_trans_brelse(NULL, bp); |
1831 | bp = NULL; | 1832 | bp = NULL; |
1832 | } else if (cursor->hashval <= | 1833 | } else if (cursor->hashval <= be32_to_cpu( |
1833 | be32_to_cpu(leaf->entries[0].hashval)) { | 1834 | entries[0].hashval)) { |
1834 | trace_xfs_attr_list_wrong_blk(context); | 1835 | trace_xfs_attr_list_wrong_blk(context); |
1835 | xfs_trans_brelse(NULL, bp); | 1836 | xfs_trans_brelse(NULL, bp); |
1836 | bp = NULL; | 1837 | bp = NULL; |
@@ -1852,27 +1853,31 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) | |||
1852 | if (bp == NULL) { | 1853 | if (bp == NULL) { |
1853 | cursor->blkno = 0; | 1854 | cursor->blkno = 0; |
1854 | for (;;) { | 1855 | for (;;) { |
1855 | error = xfs_da_node_read(NULL, context->dp, | 1856 | __uint16_t magic; |
1857 | |||
1858 | error = xfs_da3_node_read(NULL, context->dp, | ||
1856 | cursor->blkno, -1, &bp, | 1859 | cursor->blkno, -1, &bp, |
1857 | XFS_ATTR_FORK); | 1860 | XFS_ATTR_FORK); |
1858 | if (error) | 1861 | if (error) |
1859 | return(error); | 1862 | return(error); |
1860 | node = bp->b_addr; | 1863 | node = bp->b_addr; |
1861 | if (node->hdr.info.magic == | 1864 | magic = be16_to_cpu(node->hdr.info.magic); |
1862 | cpu_to_be16(XFS_ATTR_LEAF_MAGIC)) | 1865 | if (magic == XFS_ATTR_LEAF_MAGIC || |
1866 | magic == XFS_ATTR3_LEAF_MAGIC) | ||
1863 | break; | 1867 | break; |
1864 | if (unlikely(node->hdr.info.magic != | 1868 | if (magic != XFS_DA_NODE_MAGIC && |
1865 | cpu_to_be16(XFS_DA_NODE_MAGIC))) { | 1869 | magic != XFS_DA3_NODE_MAGIC) { |
1866 | XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)", | 1870 | XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)", |
1867 | XFS_ERRLEVEL_LOW, | 1871 | XFS_ERRLEVEL_LOW, |
1868 | context->dp->i_mount, | 1872 | context->dp->i_mount, |
1869 | node); | 1873 | node); |
1870 | xfs_trans_brelse(NULL, bp); | 1874 | xfs_trans_brelse(NULL, bp); |
1871 | return(XFS_ERROR(EFSCORRUPTED)); | 1875 | return XFS_ERROR(EFSCORRUPTED); |
1872 | } | 1876 | } |
1873 | btree = node->btree; | 1877 | |
1874 | for (i = 0; i < be16_to_cpu(node->hdr.count); | 1878 | xfs_da3_node_hdr_from_disk(&nodehdr, node); |
1875 | btree++, i++) { | 1879 | btree = xfs_da3_node_tree_p(node); |
1880 | for (i = 0; i < nodehdr.count; btree++, i++) { | ||
1876 | if (cursor->hashval | 1881 | if (cursor->hashval |
1877 | <= be32_to_cpu(btree->hashval)) { | 1882 | <= be32_to_cpu(btree->hashval)) { |
1878 | cursor->blkno = be32_to_cpu(btree->before); | 1883 | cursor->blkno = be32_to_cpu(btree->before); |
@@ -1881,9 +1886,9 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) | |||
1881 | break; | 1886 | break; |
1882 | } | 1887 | } |
1883 | } | 1888 | } |
1884 | if (i == be16_to_cpu(node->hdr.count)) { | 1889 | if (i == nodehdr.count) { |
1885 | xfs_trans_brelse(NULL, bp); | 1890 | xfs_trans_brelse(NULL, bp); |
1886 | return(0); | 1891 | return 0; |
1887 | } | 1892 | } |
1888 | xfs_trans_brelse(NULL, bp); | 1893 | xfs_trans_brelse(NULL, bp); |
1889 | } | 1894 | } |
@@ -1897,310 +1902,21 @@ xfs_attr_node_list(xfs_attr_list_context_t *context) | |||
1897 | */ | 1902 | */ |
1898 | for (;;) { | 1903 | for (;;) { |
1899 | leaf = bp->b_addr; | 1904 | leaf = bp->b_addr; |
1900 | error = xfs_attr_leaf_list_int(bp, context); | 1905 | error = xfs_attr3_leaf_list_int(bp, context); |
1901 | if (error) { | 1906 | if (error) { |
1902 | xfs_trans_brelse(NULL, bp); | 1907 | xfs_trans_brelse(NULL, bp); |
1903 | return error; | 1908 | return error; |
1904 | } | 1909 | } |
1905 | if (context->seen_enough || leaf->hdr.info.forw == 0) | 1910 | xfs_attr3_leaf_hdr_from_disk(&leafhdr, leaf); |
1911 | if (context->seen_enough || leafhdr.forw == 0) | ||
1906 | break; | 1912 | break; |
1907 | cursor->blkno = be32_to_cpu(leaf->hdr.info.forw); | 1913 | cursor->blkno = leafhdr.forw; |
1908 | xfs_trans_brelse(NULL, bp); | 1914 | xfs_trans_brelse(NULL, bp); |
1909 | error = xfs_attr_leaf_read(NULL, context->dp, cursor->blkno, -1, | 1915 | error = xfs_attr3_leaf_read(NULL, context->dp, cursor->blkno, -1, |
1910 | &bp); | 1916 | &bp); |
1911 | if (error) | 1917 | if (error) |
1912 | return error; | 1918 | return error; |
1913 | } | 1919 | } |
1914 | xfs_trans_brelse(NULL, bp); | 1920 | xfs_trans_brelse(NULL, bp); |
1915 | return(0); | 1921 | return 0; |
1916 | } | ||
1917 | |||
1918 | |||
1919 | /*======================================================================== | ||
1920 | * External routines for manipulating out-of-line attribute values. | ||
1921 | *========================================================================*/ | ||
1922 | |||
1923 | /* | ||
1924 | * Read the value associated with an attribute from the out-of-line buffer | ||
1925 | * that we stored it in. | ||
1926 | */ | ||
1927 | int | ||
1928 | xfs_attr_rmtval_get(xfs_da_args_t *args) | ||
1929 | { | ||
1930 | xfs_bmbt_irec_t map[ATTR_RMTVALUE_MAPSIZE]; | ||
1931 | xfs_mount_t *mp; | ||
1932 | xfs_daddr_t dblkno; | ||
1933 | void *dst; | ||
1934 | xfs_buf_t *bp; | ||
1935 | int nmap, error, tmp, valuelen, blkcnt, i; | ||
1936 | xfs_dablk_t lblkno; | ||
1937 | |||
1938 | trace_xfs_attr_rmtval_get(args); | ||
1939 | |||
1940 | ASSERT(!(args->flags & ATTR_KERNOVAL)); | ||
1941 | |||
1942 | mp = args->dp->i_mount; | ||
1943 | dst = args->value; | ||
1944 | valuelen = args->valuelen; | ||
1945 | lblkno = args->rmtblkno; | ||
1946 | while (valuelen > 0) { | ||
1947 | nmap = ATTR_RMTVALUE_MAPSIZE; | ||
1948 | error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno, | ||
1949 | args->rmtblkcnt, map, &nmap, | ||
1950 | XFS_BMAPI_ATTRFORK); | ||
1951 | if (error) | ||
1952 | return(error); | ||
1953 | ASSERT(nmap >= 1); | ||
1954 | |||
1955 | for (i = 0; (i < nmap) && (valuelen > 0); i++) { | ||
1956 | ASSERT((map[i].br_startblock != DELAYSTARTBLOCK) && | ||
1957 | (map[i].br_startblock != HOLESTARTBLOCK)); | ||
1958 | dblkno = XFS_FSB_TO_DADDR(mp, map[i].br_startblock); | ||
1959 | blkcnt = XFS_FSB_TO_BB(mp, map[i].br_blockcount); | ||
1960 | error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, | ||
1961 | dblkno, blkcnt, 0, &bp, NULL); | ||
1962 | if (error) | ||
1963 | return(error); | ||
1964 | |||
1965 | tmp = min_t(int, valuelen, BBTOB(bp->b_length)); | ||
1966 | xfs_buf_iomove(bp, 0, tmp, dst, XBRW_READ); | ||
1967 | xfs_buf_relse(bp); | ||
1968 | dst += tmp; | ||
1969 | valuelen -= tmp; | ||
1970 | |||
1971 | lblkno += map[i].br_blockcount; | ||
1972 | } | ||
1973 | } | ||
1974 | ASSERT(valuelen == 0); | ||
1975 | return(0); | ||
1976 | } | ||
1977 | |||
1978 | /* | ||
1979 | * Write the value associated with an attribute into the out-of-line buffer | ||
1980 | * that we have defined for it. | ||
1981 | */ | ||
1982 | STATIC int | ||
1983 | xfs_attr_rmtval_set(xfs_da_args_t *args) | ||
1984 | { | ||
1985 | xfs_mount_t *mp; | ||
1986 | xfs_fileoff_t lfileoff; | ||
1987 | xfs_inode_t *dp; | ||
1988 | xfs_bmbt_irec_t map; | ||
1989 | xfs_daddr_t dblkno; | ||
1990 | void *src; | ||
1991 | xfs_buf_t *bp; | ||
1992 | xfs_dablk_t lblkno; | ||
1993 | int blkcnt, valuelen, nmap, error, tmp, committed; | ||
1994 | |||
1995 | trace_xfs_attr_rmtval_set(args); | ||
1996 | |||
1997 | dp = args->dp; | ||
1998 | mp = dp->i_mount; | ||
1999 | src = args->value; | ||
2000 | |||
2001 | /* | ||
2002 | * Find a "hole" in the attribute address space large enough for | ||
2003 | * us to drop the new attribute's value into. | ||
2004 | */ | ||
2005 | blkcnt = XFS_B_TO_FSB(mp, args->valuelen); | ||
2006 | lfileoff = 0; | ||
2007 | error = xfs_bmap_first_unused(args->trans, args->dp, blkcnt, &lfileoff, | ||
2008 | XFS_ATTR_FORK); | ||
2009 | if (error) { | ||
2010 | return(error); | ||
2011 | } | ||
2012 | args->rmtblkno = lblkno = (xfs_dablk_t)lfileoff; | ||
2013 | args->rmtblkcnt = blkcnt; | ||
2014 | |||
2015 | /* | ||
2016 | * Roll through the "value", allocating blocks on disk as required. | ||
2017 | */ | ||
2018 | while (blkcnt > 0) { | ||
2019 | /* | ||
2020 | * Allocate a single extent, up to the size of the value. | ||
2021 | */ | ||
2022 | xfs_bmap_init(args->flist, args->firstblock); | ||
2023 | nmap = 1; | ||
2024 | error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno, | ||
2025 | blkcnt, | ||
2026 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | ||
2027 | args->firstblock, args->total, &map, &nmap, | ||
2028 | args->flist); | ||
2029 | if (!error) { | ||
2030 | error = xfs_bmap_finish(&args->trans, args->flist, | ||
2031 | &committed); | ||
2032 | } | ||
2033 | if (error) { | ||
2034 | ASSERT(committed); | ||
2035 | args->trans = NULL; | ||
2036 | xfs_bmap_cancel(args->flist); | ||
2037 | return(error); | ||
2038 | } | ||
2039 | |||
2040 | /* | ||
2041 | * bmap_finish() may have committed the last trans and started | ||
2042 | * a new one. We need the inode to be in all transactions. | ||
2043 | */ | ||
2044 | if (committed) | ||
2045 | xfs_trans_ijoin(args->trans, dp, 0); | ||
2046 | |||
2047 | ASSERT(nmap == 1); | ||
2048 | ASSERT((map.br_startblock != DELAYSTARTBLOCK) && | ||
2049 | (map.br_startblock != HOLESTARTBLOCK)); | ||
2050 | lblkno += map.br_blockcount; | ||
2051 | blkcnt -= map.br_blockcount; | ||
2052 | |||
2053 | /* | ||
2054 | * Start the next trans in the chain. | ||
2055 | */ | ||
2056 | error = xfs_trans_roll(&args->trans, dp); | ||
2057 | if (error) | ||
2058 | return (error); | ||
2059 | } | ||
2060 | |||
2061 | /* | ||
2062 | * Roll through the "value", copying the attribute value to the | ||
2063 | * already-allocated blocks. Blocks are written synchronously | ||
2064 | * so that we can know they are all on disk before we turn off | ||
2065 | * the INCOMPLETE flag. | ||
2066 | */ | ||
2067 | lblkno = args->rmtblkno; | ||
2068 | valuelen = args->valuelen; | ||
2069 | while (valuelen > 0) { | ||
2070 | int buflen; | ||
2071 | |||
2072 | /* | ||
2073 | * Try to remember where we decided to put the value. | ||
2074 | */ | ||
2075 | xfs_bmap_init(args->flist, args->firstblock); | ||
2076 | nmap = 1; | ||
2077 | error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno, | ||
2078 | args->rmtblkcnt, &map, &nmap, | ||
2079 | XFS_BMAPI_ATTRFORK); | ||
2080 | if (error) | ||
2081 | return(error); | ||
2082 | ASSERT(nmap == 1); | ||
2083 | ASSERT((map.br_startblock != DELAYSTARTBLOCK) && | ||
2084 | (map.br_startblock != HOLESTARTBLOCK)); | ||
2085 | |||
2086 | dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock), | ||
2087 | blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount); | ||
2088 | |||
2089 | bp = xfs_buf_get(mp->m_ddev_targp, dblkno, blkcnt, 0); | ||
2090 | if (!bp) | ||
2091 | return ENOMEM; | ||
2092 | |||
2093 | buflen = BBTOB(bp->b_length); | ||
2094 | tmp = min_t(int, valuelen, buflen); | ||
2095 | xfs_buf_iomove(bp, 0, tmp, src, XBRW_WRITE); | ||
2096 | if (tmp < buflen) | ||
2097 | xfs_buf_zero(bp, tmp, buflen - tmp); | ||
2098 | |||
2099 | error = xfs_bwrite(bp); /* GROT: NOTE: synchronous write */ | ||
2100 | xfs_buf_relse(bp); | ||
2101 | if (error) | ||
2102 | return error; | ||
2103 | src += tmp; | ||
2104 | valuelen -= tmp; | ||
2105 | |||
2106 | lblkno += map.br_blockcount; | ||
2107 | } | ||
2108 | ASSERT(valuelen == 0); | ||
2109 | return(0); | ||
2110 | } | ||
2111 | |||
2112 | /* | ||
2113 | * Remove the value associated with an attribute by deleting the | ||
2114 | * out-of-line buffer that it is stored on. | ||
2115 | */ | ||
2116 | STATIC int | ||
2117 | xfs_attr_rmtval_remove(xfs_da_args_t *args) | ||
2118 | { | ||
2119 | xfs_mount_t *mp; | ||
2120 | xfs_bmbt_irec_t map; | ||
2121 | xfs_buf_t *bp; | ||
2122 | xfs_daddr_t dblkno; | ||
2123 | xfs_dablk_t lblkno; | ||
2124 | int valuelen, blkcnt, nmap, error, done, committed; | ||
2125 | |||
2126 | trace_xfs_attr_rmtval_remove(args); | ||
2127 | |||
2128 | mp = args->dp->i_mount; | ||
2129 | |||
2130 | /* | ||
2131 | * Roll through the "value", invalidating the attribute value's | ||
2132 | * blocks. | ||
2133 | */ | ||
2134 | lblkno = args->rmtblkno; | ||
2135 | valuelen = args->rmtblkcnt; | ||
2136 | while (valuelen > 0) { | ||
2137 | /* | ||
2138 | * Try to remember where we decided to put the value. | ||
2139 | */ | ||
2140 | nmap = 1; | ||
2141 | error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno, | ||
2142 | args->rmtblkcnt, &map, &nmap, | ||
2143 | XFS_BMAPI_ATTRFORK); | ||
2144 | if (error) | ||
2145 | return(error); | ||
2146 | ASSERT(nmap == 1); | ||
2147 | ASSERT((map.br_startblock != DELAYSTARTBLOCK) && | ||
2148 | (map.br_startblock != HOLESTARTBLOCK)); | ||
2149 | |||
2150 | dblkno = XFS_FSB_TO_DADDR(mp, map.br_startblock), | ||
2151 | blkcnt = XFS_FSB_TO_BB(mp, map.br_blockcount); | ||
2152 | |||
2153 | /* | ||
2154 | * If the "remote" value is in the cache, remove it. | ||
2155 | */ | ||
2156 | bp = xfs_incore(mp->m_ddev_targp, dblkno, blkcnt, XBF_TRYLOCK); | ||
2157 | if (bp) { | ||
2158 | xfs_buf_stale(bp); | ||
2159 | xfs_buf_relse(bp); | ||
2160 | bp = NULL; | ||
2161 | } | ||
2162 | |||
2163 | valuelen -= map.br_blockcount; | ||
2164 | |||
2165 | lblkno += map.br_blockcount; | ||
2166 | } | ||
2167 | |||
2168 | /* | ||
2169 | * Keep de-allocating extents until the remote-value region is gone. | ||
2170 | */ | ||
2171 | lblkno = args->rmtblkno; | ||
2172 | blkcnt = args->rmtblkcnt; | ||
2173 | done = 0; | ||
2174 | while (!done) { | ||
2175 | xfs_bmap_init(args->flist, args->firstblock); | ||
2176 | error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, | ||
2177 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | ||
2178 | 1, args->firstblock, args->flist, | ||
2179 | &done); | ||
2180 | if (!error) { | ||
2181 | error = xfs_bmap_finish(&args->trans, args->flist, | ||
2182 | &committed); | ||
2183 | } | ||
2184 | if (error) { | ||
2185 | ASSERT(committed); | ||
2186 | args->trans = NULL; | ||
2187 | xfs_bmap_cancel(args->flist); | ||
2188 | return(error); | ||
2189 | } | ||
2190 | |||
2191 | /* | ||
2192 | * bmap_finish() may have committed the last trans and started | ||
2193 | * a new one. We need the inode to be in all transactions. | ||
2194 | */ | ||
2195 | if (committed) | ||
2196 | xfs_trans_ijoin(args->trans, args->dp, 0); | ||
2197 | |||
2198 | /* | ||
2199 | * Close out trans and start the next one in the chain. | ||
2200 | */ | ||
2201 | error = xfs_trans_roll(&args->trans, args->dp); | ||
2202 | if (error) | ||
2203 | return (error); | ||
2204 | } | ||
2205 | return(0); | ||
2206 | } | 1922 | } |