aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_attr.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_attr.c')
-rw-r--r--fs/xfs/xfs_attr.c454
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);
74STATIC int xfs_attr_fillstate(xfs_da_state_t *state); 74STATIC int xfs_attr_fillstate(xfs_da_state_t *state);
75STATIC int xfs_attr_refillstate(xfs_da_state_t *state); 75STATIC int xfs_attr_refillstate(xfs_da_state_t *state);
76 76
77/*
78 * Routines to manipulate out-of-line attribute values.
79 */
80STATIC int xfs_attr_rmtval_set(xfs_da_args_t *args);
81STATIC int xfs_attr_rmtval_remove(xfs_da_args_t *args);
82
83#define ATTR_RMTVALUE_MAPSIZE 1 /* # of map entries at once */
84 77
85STATIC int 78STATIC int
86xfs_attr_name_to_xname( 79xfs_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 */
1927int
1928xfs_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 */
1982STATIC int
1983xfs_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 */
2116STATIC int
2117xfs_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}