diff options
-rw-r--r-- | fs/ocfs2/xattr.c | 673 |
1 files changed, 325 insertions, 348 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 4fd201a54c72..7a9089255a87 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -72,6 +72,7 @@ struct ocfs2_xattr_bucket { | |||
72 | }; | 72 | }; |
73 | 73 | ||
74 | struct ocfs2_xattr_set_ctxt { | 74 | struct ocfs2_xattr_set_ctxt { |
75 | handle_t *handle; | ||
75 | struct ocfs2_alloc_context *meta_ac; | 76 | struct ocfs2_alloc_context *meta_ac; |
76 | struct ocfs2_alloc_context *data_ac; | 77 | struct ocfs2_alloc_context *data_ac; |
77 | struct ocfs2_cached_dealloc_ctxt dealloc; | 78 | struct ocfs2_cached_dealloc_ctxt dealloc; |
@@ -346,9 +347,7 @@ static int ocfs2_xattr_extend_allocation(struct inode *inode, | |||
346 | struct ocfs2_xattr_set_ctxt *ctxt) | 347 | struct ocfs2_xattr_set_ctxt *ctxt) |
347 | { | 348 | { |
348 | int status = 0; | 349 | int status = 0; |
349 | int restart_func = 0; | 350 | handle_t *handle = ctxt->handle; |
350 | int credits = 0; | ||
351 | handle_t *handle = NULL; | ||
352 | enum ocfs2_alloc_restarted why; | 351 | enum ocfs2_alloc_restarted why; |
353 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 352 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
354 | u32 prev_clusters, logical_start = le32_to_cpu(xv->xr_clusters); | 353 | u32 prev_clusters, logical_start = le32_to_cpu(xv->xr_clusters); |
@@ -358,19 +357,6 @@ static int ocfs2_xattr_extend_allocation(struct inode *inode, | |||
358 | 357 | ||
359 | ocfs2_init_xattr_value_extent_tree(&et, inode, xattr_bh, xv); | 358 | ocfs2_init_xattr_value_extent_tree(&et, inode, xattr_bh, xv); |
360 | 359 | ||
361 | restart_all: | ||
362 | |||
363 | credits = ocfs2_calc_extend_credits(osb->sb, et.et_root_el, | ||
364 | clusters_to_add); | ||
365 | handle = ocfs2_start_trans(osb, credits); | ||
366 | if (IS_ERR(handle)) { | ||
367 | status = PTR_ERR(handle); | ||
368 | handle = NULL; | ||
369 | mlog_errno(status); | ||
370 | goto leave; | ||
371 | } | ||
372 | |||
373 | restarted_transaction: | ||
374 | status = ocfs2_journal_access(handle, inode, xattr_bh, | 360 | status = ocfs2_journal_access(handle, inode, xattr_bh, |
375 | OCFS2_JOURNAL_ACCESS_WRITE); | 361 | OCFS2_JOURNAL_ACCESS_WRITE); |
376 | if (status < 0) { | 362 | if (status < 0) { |
@@ -389,9 +375,8 @@ restarted_transaction: | |||
389 | ctxt->data_ac, | 375 | ctxt->data_ac, |
390 | ctxt->meta_ac, | 376 | ctxt->meta_ac, |
391 | &why); | 377 | &why); |
392 | if ((status < 0) && (status != -EAGAIN)) { | 378 | if (status < 0) { |
393 | if (status != -ENOSPC) | 379 | mlog_errno(status); |
394 | mlog_errno(status); | ||
395 | goto leave; | 380 | goto leave; |
396 | } | 381 | } |
397 | 382 | ||
@@ -403,39 +388,13 @@ restarted_transaction: | |||
403 | 388 | ||
404 | clusters_to_add -= le32_to_cpu(xv->xr_clusters) - prev_clusters; | 389 | clusters_to_add -= le32_to_cpu(xv->xr_clusters) - prev_clusters; |
405 | 390 | ||
406 | if (why != RESTART_NONE && clusters_to_add) { | 391 | /* |
407 | if (why == RESTART_META) { | 392 | * We should have already allocated enough space before the transaction, |
408 | mlog(0, "restarting function.\n"); | 393 | * so no need to restart. |
409 | restart_func = 1; | 394 | */ |
410 | } else { | 395 | BUG_ON(why != RESTART_NONE || clusters_to_add); |
411 | BUG_ON(why != RESTART_TRANS); | ||
412 | |||
413 | mlog(0, "restarting transaction.\n"); | ||
414 | /* TODO: This can be more intelligent. */ | ||
415 | credits = ocfs2_calc_extend_credits(osb->sb, | ||
416 | et.et_root_el, | ||
417 | clusters_to_add); | ||
418 | status = ocfs2_extend_trans(handle, credits); | ||
419 | if (status < 0) { | ||
420 | /* handle still has to be committed at | ||
421 | * this point. */ | ||
422 | status = -ENOMEM; | ||
423 | mlog_errno(status); | ||
424 | goto leave; | ||
425 | } | ||
426 | goto restarted_transaction; | ||
427 | } | ||
428 | } | ||
429 | 396 | ||
430 | leave: | 397 | leave: |
431 | if (handle) { | ||
432 | ocfs2_commit_trans(osb, handle); | ||
433 | handle = NULL; | ||
434 | } | ||
435 | if ((!status) && restart_func) { | ||
436 | restart_func = 0; | ||
437 | goto restart_all; | ||
438 | } | ||
439 | 398 | ||
440 | return status; | 399 | return status; |
441 | } | 400 | } |
@@ -448,31 +407,23 @@ static int __ocfs2_remove_xattr_range(struct inode *inode, | |||
448 | { | 407 | { |
449 | int ret; | 408 | int ret; |
450 | u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos); | 409 | u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos); |
451 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 410 | handle_t *handle = ctxt->handle; |
452 | handle_t *handle; | ||
453 | struct ocfs2_extent_tree et; | 411 | struct ocfs2_extent_tree et; |
454 | 412 | ||
455 | ocfs2_init_xattr_value_extent_tree(&et, inode, root_bh, xv); | 413 | ocfs2_init_xattr_value_extent_tree(&et, inode, root_bh, xv); |
456 | 414 | ||
457 | handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS); | ||
458 | if (IS_ERR(handle)) { | ||
459 | ret = PTR_ERR(handle); | ||
460 | mlog_errno(ret); | ||
461 | goto out; | ||
462 | } | ||
463 | |||
464 | ret = ocfs2_journal_access(handle, inode, root_bh, | 415 | ret = ocfs2_journal_access(handle, inode, root_bh, |
465 | OCFS2_JOURNAL_ACCESS_WRITE); | 416 | OCFS2_JOURNAL_ACCESS_WRITE); |
466 | if (ret) { | 417 | if (ret) { |
467 | mlog_errno(ret); | 418 | mlog_errno(ret); |
468 | goto out_commit; | 419 | goto out; |
469 | } | 420 | } |
470 | 421 | ||
471 | ret = ocfs2_remove_extent(inode, &et, cpos, len, handle, ctxt->meta_ac, | 422 | ret = ocfs2_remove_extent(inode, &et, cpos, len, handle, ctxt->meta_ac, |
472 | &ctxt->dealloc); | 423 | &ctxt->dealloc); |
473 | if (ret) { | 424 | if (ret) { |
474 | mlog_errno(ret); | 425 | mlog_errno(ret); |
475 | goto out_commit; | 426 | goto out; |
476 | } | 427 | } |
477 | 428 | ||
478 | le32_add_cpu(&xv->xr_clusters, -len); | 429 | le32_add_cpu(&xv->xr_clusters, -len); |
@@ -480,15 +431,13 @@ static int __ocfs2_remove_xattr_range(struct inode *inode, | |||
480 | ret = ocfs2_journal_dirty(handle, root_bh); | 431 | ret = ocfs2_journal_dirty(handle, root_bh); |
481 | if (ret) { | 432 | if (ret) { |
482 | mlog_errno(ret); | 433 | mlog_errno(ret); |
483 | goto out_commit; | 434 | goto out; |
484 | } | 435 | } |
485 | 436 | ||
486 | ret = ocfs2_cache_cluster_dealloc(&ctxt->dealloc, phys_blkno, len); | 437 | ret = ocfs2_cache_cluster_dealloc(&ctxt->dealloc, phys_blkno, len); |
487 | if (ret) | 438 | if (ret) |
488 | mlog_errno(ret); | 439 | mlog_errno(ret); |
489 | 440 | ||
490 | out_commit: | ||
491 | ocfs2_commit_trans(osb, handle); | ||
492 | out: | 441 | out: |
493 | return ret; | 442 | return ret; |
494 | } | 443 | } |
@@ -975,6 +924,7 @@ static int ocfs2_xattr_get(struct inode *inode, | |||
975 | } | 924 | } |
976 | 925 | ||
977 | static int __ocfs2_xattr_set_value_outside(struct inode *inode, | 926 | static int __ocfs2_xattr_set_value_outside(struct inode *inode, |
927 | handle_t *handle, | ||
978 | struct ocfs2_xattr_value_root *xv, | 928 | struct ocfs2_xattr_value_root *xv, |
979 | const void *value, | 929 | const void *value, |
980 | int value_len) | 930 | int value_len) |
@@ -986,14 +936,17 @@ static int __ocfs2_xattr_set_value_outside(struct inode *inode, | |||
986 | u32 clusters = ocfs2_clusters_for_bytes(inode->i_sb, value_len); | 936 | u32 clusters = ocfs2_clusters_for_bytes(inode->i_sb, value_len); |
987 | u64 blkno; | 937 | u64 blkno; |
988 | struct buffer_head *bh = NULL; | 938 | struct buffer_head *bh = NULL; |
989 | handle_t *handle; | ||
990 | 939 | ||
991 | BUG_ON(clusters > le32_to_cpu(xv->xr_clusters)); | 940 | BUG_ON(clusters > le32_to_cpu(xv->xr_clusters)); |
992 | 941 | ||
942 | /* | ||
943 | * In __ocfs2_xattr_set_value_outside has already been dirtied, | ||
944 | * so we don't need to worry about whether ocfs2_extend_trans | ||
945 | * will create a new transactio for us or not. | ||
946 | */ | ||
993 | credits = clusters * bpc; | 947 | credits = clusters * bpc; |
994 | handle = ocfs2_start_trans(OCFS2_SB(inode->i_sb), credits); | 948 | ret = ocfs2_extend_trans(handle, credits); |
995 | if (IS_ERR(handle)) { | 949 | if (ret) { |
996 | ret = PTR_ERR(handle); | ||
997 | mlog_errno(ret); | 950 | mlog_errno(ret); |
998 | goto out; | 951 | goto out; |
999 | } | 952 | } |
@@ -1003,7 +956,7 @@ static int __ocfs2_xattr_set_value_outside(struct inode *inode, | |||
1003 | &num_clusters, &xv->xr_list); | 956 | &num_clusters, &xv->xr_list); |
1004 | if (ret) { | 957 | if (ret) { |
1005 | mlog_errno(ret); | 958 | mlog_errno(ret); |
1006 | goto out_commit; | 959 | goto out; |
1007 | } | 960 | } |
1008 | 961 | ||
1009 | blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster); | 962 | blkno = ocfs2_clusters_to_blocks(inode->i_sb, p_cluster); |
@@ -1012,7 +965,7 @@ static int __ocfs2_xattr_set_value_outside(struct inode *inode, | |||
1012 | ret = ocfs2_read_block(inode, blkno, &bh); | 965 | ret = ocfs2_read_block(inode, blkno, &bh); |
1013 | if (ret) { | 966 | if (ret) { |
1014 | mlog_errno(ret); | 967 | mlog_errno(ret); |
1015 | goto out_commit; | 968 | goto out; |
1016 | } | 969 | } |
1017 | 970 | ||
1018 | ret = ocfs2_journal_access(handle, | 971 | ret = ocfs2_journal_access(handle, |
@@ -1021,7 +974,7 @@ static int __ocfs2_xattr_set_value_outside(struct inode *inode, | |||
1021 | OCFS2_JOURNAL_ACCESS_WRITE); | 974 | OCFS2_JOURNAL_ACCESS_WRITE); |
1022 | if (ret < 0) { | 975 | if (ret < 0) { |
1023 | mlog_errno(ret); | 976 | mlog_errno(ret); |
1024 | goto out_commit; | 977 | goto out; |
1025 | } | 978 | } |
1026 | 979 | ||
1027 | cp_len = value_len > blocksize ? blocksize : value_len; | 980 | cp_len = value_len > blocksize ? blocksize : value_len; |
@@ -1035,7 +988,7 @@ static int __ocfs2_xattr_set_value_outside(struct inode *inode, | |||
1035 | ret = ocfs2_journal_dirty(handle, bh); | 988 | ret = ocfs2_journal_dirty(handle, bh); |
1036 | if (ret < 0) { | 989 | if (ret < 0) { |
1037 | mlog_errno(ret); | 990 | mlog_errno(ret); |
1038 | goto out_commit; | 991 | goto out; |
1039 | } | 992 | } |
1040 | brelse(bh); | 993 | brelse(bh); |
1041 | bh = NULL; | 994 | bh = NULL; |
@@ -1049,8 +1002,6 @@ static int __ocfs2_xattr_set_value_outside(struct inode *inode, | |||
1049 | } | 1002 | } |
1050 | cpos += num_clusters; | 1003 | cpos += num_clusters; |
1051 | } | 1004 | } |
1052 | out_commit: | ||
1053 | ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); | ||
1054 | out: | 1005 | out: |
1055 | brelse(bh); | 1006 | brelse(bh); |
1056 | 1007 | ||
@@ -1058,28 +1009,21 @@ out: | |||
1058 | } | 1009 | } |
1059 | 1010 | ||
1060 | static int ocfs2_xattr_cleanup(struct inode *inode, | 1011 | static int ocfs2_xattr_cleanup(struct inode *inode, |
1012 | handle_t *handle, | ||
1061 | struct ocfs2_xattr_info *xi, | 1013 | struct ocfs2_xattr_info *xi, |
1062 | struct ocfs2_xattr_search *xs, | 1014 | struct ocfs2_xattr_search *xs, |
1063 | size_t offs) | 1015 | size_t offs) |
1064 | { | 1016 | { |
1065 | handle_t *handle = NULL; | ||
1066 | int ret = 0; | 1017 | int ret = 0; |
1067 | size_t name_len = strlen(xi->name); | 1018 | size_t name_len = strlen(xi->name); |
1068 | void *val = xs->base + offs; | 1019 | void *val = xs->base + offs; |
1069 | size_t size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE; | 1020 | size_t size = OCFS2_XATTR_SIZE(name_len) + OCFS2_XATTR_ROOT_SIZE; |
1070 | 1021 | ||
1071 | handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)), | ||
1072 | OCFS2_XATTR_BLOCK_UPDATE_CREDITS); | ||
1073 | if (IS_ERR(handle)) { | ||
1074 | ret = PTR_ERR(handle); | ||
1075 | mlog_errno(ret); | ||
1076 | goto out; | ||
1077 | } | ||
1078 | ret = ocfs2_journal_access(handle, inode, xs->xattr_bh, | 1022 | ret = ocfs2_journal_access(handle, inode, xs->xattr_bh, |
1079 | OCFS2_JOURNAL_ACCESS_WRITE); | 1023 | OCFS2_JOURNAL_ACCESS_WRITE); |
1080 | if (ret) { | 1024 | if (ret) { |
1081 | mlog_errno(ret); | 1025 | mlog_errno(ret); |
1082 | goto out_commit; | 1026 | goto out; |
1083 | } | 1027 | } |
1084 | /* Decrease xattr count */ | 1028 | /* Decrease xattr count */ |
1085 | le16_add_cpu(&xs->header->xh_count, -1); | 1029 | le16_add_cpu(&xs->header->xh_count, -1); |
@@ -1090,32 +1034,23 @@ static int ocfs2_xattr_cleanup(struct inode *inode, | |||
1090 | ret = ocfs2_journal_dirty(handle, xs->xattr_bh); | 1034 | ret = ocfs2_journal_dirty(handle, xs->xattr_bh); |
1091 | if (ret < 0) | 1035 | if (ret < 0) |
1092 | mlog_errno(ret); | 1036 | mlog_errno(ret); |
1093 | out_commit: | ||
1094 | ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); | ||
1095 | out: | 1037 | out: |
1096 | return ret; | 1038 | return ret; |
1097 | } | 1039 | } |
1098 | 1040 | ||
1099 | static int ocfs2_xattr_update_entry(struct inode *inode, | 1041 | static int ocfs2_xattr_update_entry(struct inode *inode, |
1042 | handle_t *handle, | ||
1100 | struct ocfs2_xattr_info *xi, | 1043 | struct ocfs2_xattr_info *xi, |
1101 | struct ocfs2_xattr_search *xs, | 1044 | struct ocfs2_xattr_search *xs, |
1102 | size_t offs) | 1045 | size_t offs) |
1103 | { | 1046 | { |
1104 | handle_t *handle = NULL; | 1047 | int ret; |
1105 | int ret = 0; | ||
1106 | 1048 | ||
1107 | handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)), | ||
1108 | OCFS2_XATTR_BLOCK_UPDATE_CREDITS); | ||
1109 | if (IS_ERR(handle)) { | ||
1110 | ret = PTR_ERR(handle); | ||
1111 | mlog_errno(ret); | ||
1112 | goto out; | ||
1113 | } | ||
1114 | ret = ocfs2_journal_access(handle, inode, xs->xattr_bh, | 1049 | ret = ocfs2_journal_access(handle, inode, xs->xattr_bh, |
1115 | OCFS2_JOURNAL_ACCESS_WRITE); | 1050 | OCFS2_JOURNAL_ACCESS_WRITE); |
1116 | if (ret) { | 1051 | if (ret) { |
1117 | mlog_errno(ret); | 1052 | mlog_errno(ret); |
1118 | goto out_commit; | 1053 | goto out; |
1119 | } | 1054 | } |
1120 | 1055 | ||
1121 | xs->here->xe_name_offset = cpu_to_le16(offs); | 1056 | xs->here->xe_name_offset = cpu_to_le16(offs); |
@@ -1129,8 +1064,6 @@ static int ocfs2_xattr_update_entry(struct inode *inode, | |||
1129 | ret = ocfs2_journal_dirty(handle, xs->xattr_bh); | 1064 | ret = ocfs2_journal_dirty(handle, xs->xattr_bh); |
1130 | if (ret < 0) | 1065 | if (ret < 0) |
1131 | mlog_errno(ret); | 1066 | mlog_errno(ret); |
1132 | out_commit: | ||
1133 | ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); | ||
1134 | out: | 1067 | out: |
1135 | return ret; | 1068 | return ret; |
1136 | } | 1069 | } |
@@ -1168,13 +1101,13 @@ static int ocfs2_xattr_set_value_outside(struct inode *inode, | |||
1168 | mlog_errno(ret); | 1101 | mlog_errno(ret); |
1169 | return ret; | 1102 | return ret; |
1170 | } | 1103 | } |
1171 | ret = __ocfs2_xattr_set_value_outside(inode, xv, xi->value, | 1104 | ret = ocfs2_xattr_update_entry(inode, ctxt->handle, xi, xs, offs); |
1172 | xi->value_len); | ||
1173 | if (ret < 0) { | 1105 | if (ret < 0) { |
1174 | mlog_errno(ret); | 1106 | mlog_errno(ret); |
1175 | return ret; | 1107 | return ret; |
1176 | } | 1108 | } |
1177 | ret = ocfs2_xattr_update_entry(inode, xi, xs, offs); | 1109 | ret = __ocfs2_xattr_set_value_outside(inode, ctxt->handle, xv, |
1110 | xi->value, xi->value_len); | ||
1178 | if (ret < 0) | 1111 | if (ret < 0) |
1179 | mlog_errno(ret); | 1112 | mlog_errno(ret); |
1180 | 1113 | ||
@@ -1302,7 +1235,7 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
1302 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; | 1235 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; |
1303 | size_t min_offs = xs->end - xs->base, name_len = strlen(xi->name); | 1236 | size_t min_offs = xs->end - xs->base, name_len = strlen(xi->name); |
1304 | size_t size_l = 0; | 1237 | size_t size_l = 0; |
1305 | handle_t *handle = NULL; | 1238 | handle_t *handle = ctxt->handle; |
1306 | int free, i, ret; | 1239 | int free, i, ret; |
1307 | struct ocfs2_xattr_info xi_l = { | 1240 | struct ocfs2_xattr_info xi_l = { |
1308 | .name_index = xi->name_index, | 1241 | .name_index = xi->name_index, |
@@ -1391,19 +1324,21 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
1391 | goto out; | 1324 | goto out; |
1392 | } | 1325 | } |
1393 | 1326 | ||
1394 | ret = __ocfs2_xattr_set_value_outside(inode, | 1327 | ret = ocfs2_xattr_update_entry(inode, |
1395 | xv, | 1328 | handle, |
1396 | xi->value, | 1329 | xi, |
1397 | xi->value_len); | 1330 | xs, |
1331 | offs); | ||
1398 | if (ret < 0) { | 1332 | if (ret < 0) { |
1399 | mlog_errno(ret); | 1333 | mlog_errno(ret); |
1400 | goto out; | 1334 | goto out; |
1401 | } | 1335 | } |
1402 | 1336 | ||
1403 | ret = ocfs2_xattr_update_entry(inode, | 1337 | ret = __ocfs2_xattr_set_value_outside(inode, |
1404 | xi, | 1338 | handle, |
1405 | xs, | 1339 | xv, |
1406 | offs); | 1340 | xi->value, |
1341 | xi->value_len); | ||
1407 | if (ret < 0) | 1342 | if (ret < 0) |
1408 | mlog_errno(ret); | 1343 | mlog_errno(ret); |
1409 | goto out; | 1344 | goto out; |
@@ -1413,45 +1348,29 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
1413 | * just trucate old value to zero. | 1348 | * just trucate old value to zero. |
1414 | */ | 1349 | */ |
1415 | ret = ocfs2_xattr_value_truncate(inode, | 1350 | ret = ocfs2_xattr_value_truncate(inode, |
1416 | xs->xattr_bh, | 1351 | xs->xattr_bh, |
1417 | xv, | 1352 | xv, |
1418 | 0, | 1353 | 0, |
1419 | ctxt); | 1354 | ctxt); |
1420 | if (ret < 0) | 1355 | if (ret < 0) |
1421 | mlog_errno(ret); | 1356 | mlog_errno(ret); |
1422 | } | 1357 | } |
1423 | } | 1358 | } |
1424 | } | 1359 | } |
1425 | 1360 | ||
1426 | handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)), | ||
1427 | OCFS2_INODE_UPDATE_CREDITS); | ||
1428 | if (IS_ERR(handle)) { | ||
1429 | ret = PTR_ERR(handle); | ||
1430 | mlog_errno(ret); | ||
1431 | goto out; | ||
1432 | } | ||
1433 | |||
1434 | ret = ocfs2_journal_access(handle, inode, xs->inode_bh, | 1361 | ret = ocfs2_journal_access(handle, inode, xs->inode_bh, |
1435 | OCFS2_JOURNAL_ACCESS_WRITE); | 1362 | OCFS2_JOURNAL_ACCESS_WRITE); |
1436 | if (ret) { | 1363 | if (ret) { |
1437 | mlog_errno(ret); | 1364 | mlog_errno(ret); |
1438 | goto out_commit; | 1365 | goto out; |
1439 | } | 1366 | } |
1440 | 1367 | ||
1441 | if (!(flag & OCFS2_INLINE_XATTR_FL)) { | 1368 | if (!(flag & OCFS2_INLINE_XATTR_FL)) { |
1442 | /* set extended attribute in external block. */ | ||
1443 | ret = ocfs2_extend_trans(handle, | ||
1444 | OCFS2_INODE_UPDATE_CREDITS + | ||
1445 | OCFS2_XATTR_BLOCK_UPDATE_CREDITS); | ||
1446 | if (ret) { | ||
1447 | mlog_errno(ret); | ||
1448 | goto out_commit; | ||
1449 | } | ||
1450 | ret = ocfs2_journal_access(handle, inode, xs->xattr_bh, | 1369 | ret = ocfs2_journal_access(handle, inode, xs->xattr_bh, |
1451 | OCFS2_JOURNAL_ACCESS_WRITE); | 1370 | OCFS2_JOURNAL_ACCESS_WRITE); |
1452 | if (ret) { | 1371 | if (ret) { |
1453 | mlog_errno(ret); | 1372 | mlog_errno(ret); |
1454 | goto out_commit; | 1373 | goto out; |
1455 | } | 1374 | } |
1456 | } | 1375 | } |
1457 | 1376 | ||
@@ -1465,7 +1384,7 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
1465 | ret = ocfs2_journal_dirty(handle, xs->xattr_bh); | 1384 | ret = ocfs2_journal_dirty(handle, xs->xattr_bh); |
1466 | if (ret < 0) { | 1385 | if (ret < 0) { |
1467 | mlog_errno(ret); | 1386 | mlog_errno(ret); |
1468 | goto out_commit; | 1387 | goto out; |
1469 | } | 1388 | } |
1470 | } | 1389 | } |
1471 | 1390 | ||
@@ -1502,9 +1421,6 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
1502 | if (ret < 0) | 1421 | if (ret < 0) |
1503 | mlog_errno(ret); | 1422 | mlog_errno(ret); |
1504 | 1423 | ||
1505 | out_commit: | ||
1506 | ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); | ||
1507 | |||
1508 | if (!ret && xi->value_len > OCFS2_XATTR_INLINE_SIZE) { | 1424 | if (!ret && xi->value_len > OCFS2_XATTR_INLINE_SIZE) { |
1509 | /* | 1425 | /* |
1510 | * Set value outside in B tree. | 1426 | * Set value outside in B tree. |
@@ -1520,14 +1436,14 @@ out_commit: | |||
1520 | * If set value outside failed, we have to clean | 1436 | * If set value outside failed, we have to clean |
1521 | * the junk tree root we have already set in local. | 1437 | * the junk tree root we have already set in local. |
1522 | */ | 1438 | */ |
1523 | ret2 = ocfs2_xattr_cleanup(inode, xi, xs, offs); | 1439 | ret2 = ocfs2_xattr_cleanup(inode, ctxt->handle, |
1440 | xi, xs, offs); | ||
1524 | if (ret2 < 0) | 1441 | if (ret2 < 0) |
1525 | mlog_errno(ret2); | 1442 | mlog_errno(ret2); |
1526 | } | 1443 | } |
1527 | } | 1444 | } |
1528 | out: | 1445 | out: |
1529 | return ret; | 1446 | return ret; |
1530 | |||
1531 | } | 1447 | } |
1532 | 1448 | ||
1533 | static int ocfs2_remove_value_outside(struct inode*inode, | 1449 | static int ocfs2_remove_value_outside(struct inode*inode, |
@@ -1540,6 +1456,13 @@ static int ocfs2_remove_value_outside(struct inode*inode, | |||
1540 | 1456 | ||
1541 | ocfs2_init_dealloc_ctxt(&ctxt.dealloc); | 1457 | ocfs2_init_dealloc_ctxt(&ctxt.dealloc); |
1542 | 1458 | ||
1459 | ctxt.handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS); | ||
1460 | if (IS_ERR(ctxt.handle)) { | ||
1461 | ret = PTR_ERR(ctxt.handle); | ||
1462 | mlog_errno(ret); | ||
1463 | goto out; | ||
1464 | } | ||
1465 | |||
1543 | for (i = 0; i < le16_to_cpu(header->xh_count); i++) { | 1466 | for (i = 0; i < le16_to_cpu(header->xh_count); i++) { |
1544 | struct ocfs2_xattr_entry *entry = &header->xh_entries[i]; | 1467 | struct ocfs2_xattr_entry *entry = &header->xh_entries[i]; |
1545 | 1468 | ||
@@ -1560,8 +1483,10 @@ static int ocfs2_remove_value_outside(struct inode*inode, | |||
1560 | } | 1483 | } |
1561 | } | 1484 | } |
1562 | 1485 | ||
1486 | ocfs2_commit_trans(osb, ctxt.handle); | ||
1563 | ocfs2_schedule_truncate_log_flush(osb, 1); | 1487 | ocfs2_schedule_truncate_log_flush(osb, 1); |
1564 | ocfs2_run_deallocs(osb, &ctxt.dealloc); | 1488 | ocfs2_run_deallocs(osb, &ctxt.dealloc); |
1489 | out: | ||
1565 | return ret; | 1490 | return ret; |
1566 | } | 1491 | } |
1567 | 1492 | ||
@@ -1920,7 +1845,7 @@ static int ocfs2_xattr_block_set(struct inode *inode, | |||
1920 | struct buffer_head *new_bh = NULL; | 1845 | struct buffer_head *new_bh = NULL; |
1921 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 1846 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
1922 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; | 1847 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; |
1923 | handle_t *handle = NULL; | 1848 | handle_t *handle = ctxt->handle; |
1924 | struct ocfs2_xattr_block *xblk = NULL; | 1849 | struct ocfs2_xattr_block *xblk = NULL; |
1925 | u16 suballoc_bit_start; | 1850 | u16 suballoc_bit_start; |
1926 | u32 num_got; | 1851 | u32 num_got; |
@@ -1928,18 +1853,11 @@ static int ocfs2_xattr_block_set(struct inode *inode, | |||
1928 | int ret; | 1853 | int ret; |
1929 | 1854 | ||
1930 | if (!xs->xattr_bh) { | 1855 | if (!xs->xattr_bh) { |
1931 | handle = ocfs2_start_trans(osb, | ||
1932 | OCFS2_XATTR_BLOCK_CREATE_CREDITS); | ||
1933 | if (IS_ERR(handle)) { | ||
1934 | ret = PTR_ERR(handle); | ||
1935 | mlog_errno(ret); | ||
1936 | goto out; | ||
1937 | } | ||
1938 | ret = ocfs2_journal_access(handle, inode, xs->inode_bh, | 1856 | ret = ocfs2_journal_access(handle, inode, xs->inode_bh, |
1939 | OCFS2_JOURNAL_ACCESS_CREATE); | 1857 | OCFS2_JOURNAL_ACCESS_CREATE); |
1940 | if (ret < 0) { | 1858 | if (ret < 0) { |
1941 | mlog_errno(ret); | 1859 | mlog_errno(ret); |
1942 | goto out_commit; | 1860 | goto end; |
1943 | } | 1861 | } |
1944 | 1862 | ||
1945 | ret = ocfs2_claim_metadata(osb, handle, ctxt->meta_ac, 1, | 1863 | ret = ocfs2_claim_metadata(osb, handle, ctxt->meta_ac, 1, |
@@ -1947,7 +1865,7 @@ static int ocfs2_xattr_block_set(struct inode *inode, | |||
1947 | &first_blkno); | 1865 | &first_blkno); |
1948 | if (ret < 0) { | 1866 | if (ret < 0) { |
1949 | mlog_errno(ret); | 1867 | mlog_errno(ret); |
1950 | goto out_commit; | 1868 | goto end; |
1951 | } | 1869 | } |
1952 | 1870 | ||
1953 | new_bh = sb_getblk(inode->i_sb, first_blkno); | 1871 | new_bh = sb_getblk(inode->i_sb, first_blkno); |
@@ -1957,7 +1875,7 @@ static int ocfs2_xattr_block_set(struct inode *inode, | |||
1957 | OCFS2_JOURNAL_ACCESS_CREATE); | 1875 | OCFS2_JOURNAL_ACCESS_CREATE); |
1958 | if (ret < 0) { | 1876 | if (ret < 0) { |
1959 | mlog_errno(ret); | 1877 | mlog_errno(ret); |
1960 | goto out_commit; | 1878 | goto end; |
1961 | } | 1879 | } |
1962 | 1880 | ||
1963 | /* Initialize ocfs2_xattr_block */ | 1881 | /* Initialize ocfs2_xattr_block */ |
@@ -1978,17 +1896,10 @@ static int ocfs2_xattr_block_set(struct inode *inode, | |||
1978 | ret = ocfs2_journal_dirty(handle, new_bh); | 1896 | ret = ocfs2_journal_dirty(handle, new_bh); |
1979 | if (ret < 0) { | 1897 | if (ret < 0) { |
1980 | mlog_errno(ret); | 1898 | mlog_errno(ret); |
1981 | goto out_commit; | 1899 | goto end; |
1982 | } | 1900 | } |
1983 | di->i_xattr_loc = cpu_to_le64(first_blkno); | 1901 | di->i_xattr_loc = cpu_to_le64(first_blkno); |
1984 | ret = ocfs2_journal_dirty(handle, xs->inode_bh); | 1902 | ocfs2_journal_dirty(handle, xs->inode_bh); |
1985 | if (ret < 0) | ||
1986 | mlog_errno(ret); | ||
1987 | out_commit: | ||
1988 | ocfs2_commit_trans(osb, handle); | ||
1989 | out: | ||
1990 | if (ret < 0) | ||
1991 | return ret; | ||
1992 | } else | 1903 | } else |
1993 | xblk = (struct ocfs2_xattr_block *)xs->xattr_bh->b_data; | 1904 | xblk = (struct ocfs2_xattr_block *)xs->xattr_bh->b_data; |
1994 | 1905 | ||
@@ -2057,10 +1968,11 @@ static int ocfs2_calc_xattr_set_need(struct inode *inode, | |||
2057 | struct ocfs2_xattr_search *xis, | 1968 | struct ocfs2_xattr_search *xis, |
2058 | struct ocfs2_xattr_search *xbs, | 1969 | struct ocfs2_xattr_search *xbs, |
2059 | int *clusters_need, | 1970 | int *clusters_need, |
2060 | int *meta_need) | 1971 | int *meta_need, |
1972 | int *credits_need) | ||
2061 | { | 1973 | { |
2062 | int ret = 0, old_in_xb = 0; | 1974 | int ret = 0, old_in_xb = 0; |
2063 | int clusters_add = 0, meta_add = 0; | 1975 | int clusters_add = 0, meta_add = 0, credits = 0; |
2064 | struct buffer_head *bh = NULL; | 1976 | struct buffer_head *bh = NULL; |
2065 | struct ocfs2_xattr_block *xb = NULL; | 1977 | struct ocfs2_xattr_block *xb = NULL; |
2066 | struct ocfs2_xattr_entry *xe = NULL; | 1978 | struct ocfs2_xattr_entry *xe = NULL; |
@@ -2071,16 +1983,15 @@ static int ocfs2_calc_xattr_set_need(struct inode *inode, | |||
2071 | xi->value_len); | 1983 | xi->value_len); |
2072 | u64 value_size; | 1984 | u64 value_size; |
2073 | 1985 | ||
2074 | /* | ||
2075 | * delete a xattr doesn't need metadata and cluster allocation. | ||
2076 | * so return. | ||
2077 | */ | ||
2078 | if (!xi->value) | ||
2079 | goto out; | ||
2080 | |||
2081 | if (xis->not_found && xbs->not_found) { | 1986 | if (xis->not_found && xbs->not_found) { |
2082 | if (xi->value_len > OCFS2_XATTR_INLINE_SIZE) | 1987 | credits += ocfs2_blocks_per_xattr_bucket(inode->i_sb); |
1988 | |||
1989 | if (xi->value_len > OCFS2_XATTR_INLINE_SIZE) { | ||
2083 | clusters_add += new_clusters; | 1990 | clusters_add += new_clusters; |
1991 | credits += ocfs2_calc_extend_credits(inode->i_sb, | ||
1992 | &def_xv.xv.xr_list, | ||
1993 | new_clusters); | ||
1994 | } | ||
2084 | 1995 | ||
2085 | goto meta_guess; | 1996 | goto meta_guess; |
2086 | } | 1997 | } |
@@ -2090,6 +2001,7 @@ static int ocfs2_calc_xattr_set_need(struct inode *inode, | |||
2090 | name_offset = le16_to_cpu(xe->xe_name_offset); | 2001 | name_offset = le16_to_cpu(xe->xe_name_offset); |
2091 | name_len = OCFS2_XATTR_SIZE(xe->xe_name_len); | 2002 | name_len = OCFS2_XATTR_SIZE(xe->xe_name_len); |
2092 | base = xis->base; | 2003 | base = xis->base; |
2004 | credits += OCFS2_INODE_UPDATE_CREDITS; | ||
2093 | } else { | 2005 | } else { |
2094 | int i, block_off; | 2006 | int i, block_off; |
2095 | xb = (struct ocfs2_xattr_block *)xbs->xattr_bh->b_data; | 2007 | xb = (struct ocfs2_xattr_block *)xbs->xattr_bh->b_data; |
@@ -2105,8 +2017,25 @@ static int ocfs2_calc_xattr_set_need(struct inode *inode, | |||
2105 | i, &block_off, | 2017 | i, &block_off, |
2106 | &name_offset); | 2018 | &name_offset); |
2107 | base = bucket_block(xbs->bucket, block_off); | 2019 | base = bucket_block(xbs->bucket, block_off); |
2108 | } else | 2020 | credits += ocfs2_blocks_per_xattr_bucket(inode->i_sb); |
2021 | } else { | ||
2109 | base = xbs->base; | 2022 | base = xbs->base; |
2023 | credits += OCFS2_XATTR_BLOCK_UPDATE_CREDITS; | ||
2024 | } | ||
2025 | } | ||
2026 | |||
2027 | /* | ||
2028 | * delete a xattr doesn't need metadata and cluster allocation. | ||
2029 | * so just calculate the credits and return. | ||
2030 | * | ||
2031 | * The credits for removing the value tree will be extended | ||
2032 | * by ocfs2_remove_extent itself. | ||
2033 | */ | ||
2034 | if (!xi->value) { | ||
2035 | if (!ocfs2_xattr_is_local(xe)) | ||
2036 | credits += OCFS2_REMOVE_EXTENT_CREDITS; | ||
2037 | |||
2038 | goto out; | ||
2110 | } | 2039 | } |
2111 | 2040 | ||
2112 | /* do cluster allocation guess first. */ | 2041 | /* do cluster allocation guess first. */ |
@@ -2121,6 +2050,13 @@ static int ocfs2_calc_xattr_set_need(struct inode *inode, | |||
2121 | */ | 2050 | */ |
2122 | if (ocfs2_xattr_can_be_in_inode(inode, xi, xis)) { | 2051 | if (ocfs2_xattr_can_be_in_inode(inode, xi, xis)) { |
2123 | clusters_add += new_clusters; | 2052 | clusters_add += new_clusters; |
2053 | credits += OCFS2_REMOVE_EXTENT_CREDITS + | ||
2054 | OCFS2_INODE_UPDATE_CREDITS; | ||
2055 | if (!ocfs2_xattr_is_local(xe)) | ||
2056 | credits += ocfs2_calc_extend_credits( | ||
2057 | inode->i_sb, | ||
2058 | &def_xv.xv.xr_list, | ||
2059 | new_clusters); | ||
2124 | goto out; | 2060 | goto out; |
2125 | } | 2061 | } |
2126 | } | 2062 | } |
@@ -2137,11 +2073,16 @@ static int ocfs2_calc_xattr_set_need(struct inode *inode, | |||
2137 | } else | 2073 | } else |
2138 | xv = &def_xv.xv; | 2074 | xv = &def_xv.xv; |
2139 | 2075 | ||
2140 | if (old_clusters >= new_clusters) | 2076 | if (old_clusters >= new_clusters) { |
2077 | credits += OCFS2_REMOVE_EXTENT_CREDITS; | ||
2141 | goto out; | 2078 | goto out; |
2142 | else { | 2079 | } else { |
2143 | meta_add += ocfs2_extend_meta_needed(&xv->xr_list); | 2080 | meta_add += ocfs2_extend_meta_needed(&xv->xr_list); |
2144 | clusters_add += new_clusters - old_clusters; | 2081 | clusters_add += new_clusters - old_clusters; |
2082 | credits += ocfs2_calc_extend_credits(inode->i_sb, | ||
2083 | &xv->xr_list, | ||
2084 | new_clusters - | ||
2085 | old_clusters); | ||
2145 | goto out; | 2086 | goto out; |
2146 | } | 2087 | } |
2147 | } else { | 2088 | } else { |
@@ -2177,6 +2118,8 @@ meta_guess: | |||
2177 | struct ocfs2_extent_list *el = | 2118 | struct ocfs2_extent_list *el = |
2178 | &xb->xb_attrs.xb_root.xt_list; | 2119 | &xb->xb_attrs.xb_root.xt_list; |
2179 | meta_add += ocfs2_extend_meta_needed(el); | 2120 | meta_add += ocfs2_extend_meta_needed(el); |
2121 | credits += ocfs2_calc_extend_credits(inode->i_sb, | ||
2122 | el, 1); | ||
2180 | } | 2123 | } |
2181 | 2124 | ||
2182 | /* | 2125 | /* |
@@ -2187,16 +2130,23 @@ meta_guess: | |||
2187 | * also. | 2130 | * also. |
2188 | */ | 2131 | */ |
2189 | clusters_add += 1; | 2132 | clusters_add += 1; |
2133 | credits += ocfs2_blocks_per_xattr_bucket(inode->i_sb); | ||
2190 | if (OCFS2_XATTR_BUCKET_SIZE == | 2134 | if (OCFS2_XATTR_BUCKET_SIZE == |
2191 | OCFS2_SB(inode->i_sb)->s_clustersize) | 2135 | OCFS2_SB(inode->i_sb)->s_clustersize) { |
2136 | credits += ocfs2_blocks_per_xattr_bucket(inode->i_sb); | ||
2192 | clusters_add += 1; | 2137 | clusters_add += 1; |
2193 | } else | 2138 | } |
2139 | } else { | ||
2194 | meta_add += 1; | 2140 | meta_add += 1; |
2141 | credits += OCFS2_XATTR_BLOCK_CREATE_CREDITS; | ||
2142 | } | ||
2195 | out: | 2143 | out: |
2196 | if (clusters_need) | 2144 | if (clusters_need) |
2197 | *clusters_need = clusters_add; | 2145 | *clusters_need = clusters_add; |
2198 | if (meta_need) | 2146 | if (meta_need) |
2199 | *meta_need = meta_add; | 2147 | *meta_need = meta_add; |
2148 | if (credits_need) | ||
2149 | *credits_need = credits; | ||
2200 | brelse(bh); | 2150 | brelse(bh); |
2201 | return ret; | 2151 | return ret; |
2202 | } | 2152 | } |
@@ -2206,7 +2156,8 @@ static int ocfs2_init_xattr_set_ctxt(struct inode *inode, | |||
2206 | struct ocfs2_xattr_info *xi, | 2156 | struct ocfs2_xattr_info *xi, |
2207 | struct ocfs2_xattr_search *xis, | 2157 | struct ocfs2_xattr_search *xis, |
2208 | struct ocfs2_xattr_search *xbs, | 2158 | struct ocfs2_xattr_search *xbs, |
2209 | struct ocfs2_xattr_set_ctxt *ctxt) | 2159 | struct ocfs2_xattr_set_ctxt *ctxt, |
2160 | int *credits) | ||
2210 | { | 2161 | { |
2211 | int clusters_add, meta_add, ret; | 2162 | int clusters_add, meta_add, ret; |
2212 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 2163 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
@@ -2216,14 +2167,14 @@ static int ocfs2_init_xattr_set_ctxt(struct inode *inode, | |||
2216 | ocfs2_init_dealloc_ctxt(&ctxt->dealloc); | 2167 | ocfs2_init_dealloc_ctxt(&ctxt->dealloc); |
2217 | 2168 | ||
2218 | ret = ocfs2_calc_xattr_set_need(inode, di, xi, xis, xbs, | 2169 | ret = ocfs2_calc_xattr_set_need(inode, di, xi, xis, xbs, |
2219 | &clusters_add, &meta_add); | 2170 | &clusters_add, &meta_add, credits); |
2220 | if (ret) { | 2171 | if (ret) { |
2221 | mlog_errno(ret); | 2172 | mlog_errno(ret); |
2222 | return ret; | 2173 | return ret; |
2223 | } | 2174 | } |
2224 | 2175 | ||
2225 | mlog(0, "Set xattr %s, reserve meta blocks = %d, clusters = %d\n", | 2176 | mlog(0, "Set xattr %s, reserve meta blocks = %d, clusters = %d, " |
2226 | xi->name, meta_add, clusters_add); | 2177 | "credits = %d\n", xi->name, meta_add, clusters_add, *credits); |
2227 | 2178 | ||
2228 | if (meta_add) { | 2179 | if (meta_add) { |
2229 | ret = ocfs2_reserve_new_metadata_blocks(osb, meta_add, | 2180 | ret = ocfs2_reserve_new_metadata_blocks(osb, meta_add, |
@@ -2254,6 +2205,126 @@ out: | |||
2254 | return ret; | 2205 | return ret; |
2255 | } | 2206 | } |
2256 | 2207 | ||
2208 | static int __ocfs2_xattr_set_handle(struct inode *inode, | ||
2209 | struct ocfs2_dinode *di, | ||
2210 | struct ocfs2_xattr_info *xi, | ||
2211 | struct ocfs2_xattr_search *xis, | ||
2212 | struct ocfs2_xattr_search *xbs, | ||
2213 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
2214 | { | ||
2215 | int ret = 0, credits; | ||
2216 | |||
2217 | if (!xi->value) { | ||
2218 | /* Remove existing extended attribute */ | ||
2219 | if (!xis->not_found) | ||
2220 | ret = ocfs2_xattr_ibody_set(inode, xi, xis, ctxt); | ||
2221 | else if (!xbs->not_found) | ||
2222 | ret = ocfs2_xattr_block_set(inode, xi, xbs, ctxt); | ||
2223 | } else { | ||
2224 | /* We always try to set extended attribute into inode first*/ | ||
2225 | ret = ocfs2_xattr_ibody_set(inode, xi, xis, ctxt); | ||
2226 | if (!ret && !xbs->not_found) { | ||
2227 | /* | ||
2228 | * If succeed and that extended attribute existing in | ||
2229 | * external block, then we will remove it. | ||
2230 | */ | ||
2231 | xi->value = NULL; | ||
2232 | xi->value_len = 0; | ||
2233 | |||
2234 | xis->not_found = -ENODATA; | ||
2235 | ret = ocfs2_calc_xattr_set_need(inode, | ||
2236 | di, | ||
2237 | xi, | ||
2238 | xis, | ||
2239 | xbs, | ||
2240 | NULL, | ||
2241 | NULL, | ||
2242 | &credits); | ||
2243 | if (ret) { | ||
2244 | mlog_errno(ret); | ||
2245 | goto out; | ||
2246 | } | ||
2247 | |||
2248 | ret = ocfs2_extend_trans(ctxt->handle, credits + | ||
2249 | ctxt->handle->h_buffer_credits); | ||
2250 | if (ret) { | ||
2251 | mlog_errno(ret); | ||
2252 | goto out; | ||
2253 | } | ||
2254 | ret = ocfs2_xattr_block_set(inode, xi, xbs, ctxt); | ||
2255 | } else if (ret == -ENOSPC) { | ||
2256 | if (di->i_xattr_loc && !xbs->xattr_bh) { | ||
2257 | ret = ocfs2_xattr_block_find(inode, | ||
2258 | xi->name_index, | ||
2259 | xi->name, xbs); | ||
2260 | if (ret) | ||
2261 | goto out; | ||
2262 | |||
2263 | xis->not_found = -ENODATA; | ||
2264 | ret = ocfs2_calc_xattr_set_need(inode, | ||
2265 | di, | ||
2266 | xi, | ||
2267 | xis, | ||
2268 | xbs, | ||
2269 | NULL, | ||
2270 | NULL, | ||
2271 | &credits); | ||
2272 | if (ret) { | ||
2273 | mlog_errno(ret); | ||
2274 | goto out; | ||
2275 | } | ||
2276 | |||
2277 | ret = ocfs2_extend_trans(ctxt->handle, credits + | ||
2278 | ctxt->handle->h_buffer_credits); | ||
2279 | if (ret) { | ||
2280 | mlog_errno(ret); | ||
2281 | goto out; | ||
2282 | } | ||
2283 | } | ||
2284 | /* | ||
2285 | * If no space in inode, we will set extended attribute | ||
2286 | * into external block. | ||
2287 | */ | ||
2288 | ret = ocfs2_xattr_block_set(inode, xi, xbs, ctxt); | ||
2289 | if (ret) | ||
2290 | goto out; | ||
2291 | if (!xis->not_found) { | ||
2292 | /* | ||
2293 | * If succeed and that extended attribute | ||
2294 | * existing in inode, we will remove it. | ||
2295 | */ | ||
2296 | xi->value = NULL; | ||
2297 | xi->value_len = 0; | ||
2298 | xbs->not_found = -ENODATA; | ||
2299 | ret = ocfs2_calc_xattr_set_need(inode, | ||
2300 | di, | ||
2301 | xi, | ||
2302 | xis, | ||
2303 | xbs, | ||
2304 | NULL, | ||
2305 | NULL, | ||
2306 | &credits); | ||
2307 | if (ret) { | ||
2308 | mlog_errno(ret); | ||
2309 | goto out; | ||
2310 | } | ||
2311 | |||
2312 | ret = ocfs2_extend_trans(ctxt->handle, credits + | ||
2313 | ctxt->handle->h_buffer_credits); | ||
2314 | if (ret) { | ||
2315 | mlog_errno(ret); | ||
2316 | goto out; | ||
2317 | } | ||
2318 | ret = ocfs2_xattr_ibody_set(inode, xi, | ||
2319 | xis, ctxt); | ||
2320 | } | ||
2321 | } | ||
2322 | } | ||
2323 | |||
2324 | out: | ||
2325 | return ret; | ||
2326 | } | ||
2327 | |||
2257 | /* | 2328 | /* |
2258 | * ocfs2_xattr_set() | 2329 | * ocfs2_xattr_set() |
2259 | * | 2330 | * |
@@ -2270,8 +2341,9 @@ int ocfs2_xattr_set(struct inode *inode, | |||
2270 | { | 2341 | { |
2271 | struct buffer_head *di_bh = NULL; | 2342 | struct buffer_head *di_bh = NULL; |
2272 | struct ocfs2_dinode *di; | 2343 | struct ocfs2_dinode *di; |
2273 | int ret; | 2344 | int ret, credits; |
2274 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 2345 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
2346 | struct inode *tl_inode = osb->osb_tl_inode; | ||
2275 | struct ocfs2_xattr_set_ctxt ctxt = { NULL, NULL, }; | 2347 | struct ocfs2_xattr_set_ctxt ctxt = { NULL, NULL, }; |
2276 | 2348 | ||
2277 | struct ocfs2_xattr_info xi = { | 2349 | struct ocfs2_xattr_info xi = { |
@@ -2337,56 +2409,37 @@ int ocfs2_xattr_set(struct inode *inode, | |||
2337 | goto cleanup; | 2409 | goto cleanup; |
2338 | } | 2410 | } |
2339 | 2411 | ||
2340 | ret = ocfs2_init_xattr_set_ctxt(inode, di, &xi, &xis, &xbs, &ctxt); | 2412 | |
2413 | mutex_lock(&tl_inode->i_mutex); | ||
2414 | |||
2415 | if (ocfs2_truncate_log_needs_flush(osb)) { | ||
2416 | ret = __ocfs2_flush_truncate_log(osb); | ||
2417 | if (ret < 0) { | ||
2418 | mutex_unlock(&tl_inode->i_mutex); | ||
2419 | mlog_errno(ret); | ||
2420 | goto cleanup; | ||
2421 | } | ||
2422 | } | ||
2423 | mutex_unlock(&tl_inode->i_mutex); | ||
2424 | |||
2425 | ret = ocfs2_init_xattr_set_ctxt(inode, di, &xi, &xis, | ||
2426 | &xbs, &ctxt, &credits); | ||
2341 | if (ret) { | 2427 | if (ret) { |
2342 | mlog_errno(ret); | 2428 | mlog_errno(ret); |
2343 | goto cleanup; | 2429 | goto cleanup; |
2344 | } | 2430 | } |
2345 | 2431 | ||
2346 | if (!value) { | 2432 | ctxt.handle = ocfs2_start_trans(osb, credits); |
2347 | /* Remove existing extended attribute */ | 2433 | if (IS_ERR(ctxt.handle)) { |
2348 | if (!xis.not_found) | 2434 | ret = PTR_ERR(ctxt.handle); |
2349 | ret = ocfs2_xattr_ibody_set(inode, &xi, &xis, &ctxt); | 2435 | mlog_errno(ret); |
2350 | else if (!xbs.not_found) | 2436 | goto cleanup; |
2351 | ret = ocfs2_xattr_block_set(inode, &xi, &xbs, &ctxt); | ||
2352 | } else { | ||
2353 | /* We always try to set extended attribute into inode first*/ | ||
2354 | ret = ocfs2_xattr_ibody_set(inode, &xi, &xis, &ctxt); | ||
2355 | if (!ret && !xbs.not_found) { | ||
2356 | /* | ||
2357 | * If succeed and that extended attribute existing in | ||
2358 | * external block, then we will remove it. | ||
2359 | */ | ||
2360 | xi.value = NULL; | ||
2361 | xi.value_len = 0; | ||
2362 | ret = ocfs2_xattr_block_set(inode, &xi, &xbs, &ctxt); | ||
2363 | } else if (ret == -ENOSPC) { | ||
2364 | if (di->i_xattr_loc && !xbs.xattr_bh) { | ||
2365 | ret = ocfs2_xattr_block_find(inode, name_index, | ||
2366 | name, &xbs); | ||
2367 | if (ret) | ||
2368 | goto cleanup; | ||
2369 | } | ||
2370 | /* | ||
2371 | * If no space in inode, we will set extended attribute | ||
2372 | * into external block. | ||
2373 | */ | ||
2374 | ret = ocfs2_xattr_block_set(inode, &xi, &xbs, &ctxt); | ||
2375 | if (ret) | ||
2376 | goto free; | ||
2377 | if (!xis.not_found) { | ||
2378 | /* | ||
2379 | * If succeed and that extended attribute | ||
2380 | * existing in inode, we will remove it. | ||
2381 | */ | ||
2382 | xi.value = NULL; | ||
2383 | xi.value_len = 0; | ||
2384 | ret = ocfs2_xattr_ibody_set(inode, &xi, | ||
2385 | &xis, &ctxt); | ||
2386 | } | ||
2387 | } | ||
2388 | } | 2437 | } |
2389 | free: | 2438 | |
2439 | ret = __ocfs2_xattr_set_handle(inode, di, &xi, &xis, &xbs, &ctxt); | ||
2440 | |||
2441 | ocfs2_commit_trans(osb, ctxt.handle); | ||
2442 | |||
2390 | if (ctxt.data_ac) | 2443 | if (ctxt.data_ac) |
2391 | ocfs2_free_alloc_context(ctxt.data_ac); | 2444 | ocfs2_free_alloc_context(ctxt.data_ac); |
2392 | if (ctxt.meta_ac) | 2445 | if (ctxt.meta_ac) |
@@ -2974,10 +3027,10 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, | |||
2974 | struct ocfs2_xattr_search *xs, | 3027 | struct ocfs2_xattr_search *xs, |
2975 | struct ocfs2_xattr_set_ctxt *ctxt) | 3028 | struct ocfs2_xattr_set_ctxt *ctxt) |
2976 | { | 3029 | { |
2977 | int ret, credits = OCFS2_SUBALLOC_ALLOC; | 3030 | int ret; |
2978 | u32 bit_off, len; | 3031 | u32 bit_off, len; |
2979 | u64 blkno; | 3032 | u64 blkno; |
2980 | handle_t *handle; | 3033 | handle_t *handle = ctxt->handle; |
2981 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 3034 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
2982 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | 3035 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
2983 | struct buffer_head *xb_bh = xs->xattr_bh; | 3036 | struct buffer_head *xb_bh = xs->xattr_bh; |
@@ -2999,30 +3052,18 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, | |||
2999 | */ | 3052 | */ |
3000 | down_write(&oi->ip_alloc_sem); | 3053 | down_write(&oi->ip_alloc_sem); |
3001 | 3054 | ||
3002 | /* | ||
3003 | * We need more credits. One for the xattr block update and one | ||
3004 | * for each block of the new xattr bucket. | ||
3005 | */ | ||
3006 | credits += 1 + ocfs2_blocks_per_xattr_bucket(inode->i_sb); | ||
3007 | handle = ocfs2_start_trans(osb, credits); | ||
3008 | if (IS_ERR(handle)) { | ||
3009 | ret = PTR_ERR(handle); | ||
3010 | mlog_errno(ret); | ||
3011 | goto out_sem; | ||
3012 | } | ||
3013 | |||
3014 | ret = ocfs2_journal_access(handle, inode, xb_bh, | 3055 | ret = ocfs2_journal_access(handle, inode, xb_bh, |
3015 | OCFS2_JOURNAL_ACCESS_WRITE); | 3056 | OCFS2_JOURNAL_ACCESS_WRITE); |
3016 | if (ret) { | 3057 | if (ret) { |
3017 | mlog_errno(ret); | 3058 | mlog_errno(ret); |
3018 | goto out_commit; | 3059 | goto out; |
3019 | } | 3060 | } |
3020 | 3061 | ||
3021 | ret = __ocfs2_claim_clusters(osb, handle, ctxt->data_ac, | 3062 | ret = __ocfs2_claim_clusters(osb, handle, ctxt->data_ac, |
3022 | 1, 1, &bit_off, &len); | 3063 | 1, 1, &bit_off, &len); |
3023 | if (ret) { | 3064 | if (ret) { |
3024 | mlog_errno(ret); | 3065 | mlog_errno(ret); |
3025 | goto out_commit; | 3066 | goto out; |
3026 | } | 3067 | } |
3027 | 3068 | ||
3028 | /* | 3069 | /* |
@@ -3038,14 +3079,14 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, | |||
3038 | ret = ocfs2_init_xattr_bucket(xs->bucket, blkno); | 3079 | ret = ocfs2_init_xattr_bucket(xs->bucket, blkno); |
3039 | if (ret) { | 3080 | if (ret) { |
3040 | mlog_errno(ret); | 3081 | mlog_errno(ret); |
3041 | goto out_commit; | 3082 | goto out; |
3042 | } | 3083 | } |
3043 | 3084 | ||
3044 | ret = ocfs2_xattr_bucket_journal_access(handle, xs->bucket, | 3085 | ret = ocfs2_xattr_bucket_journal_access(handle, xs->bucket, |
3045 | OCFS2_JOURNAL_ACCESS_CREATE); | 3086 | OCFS2_JOURNAL_ACCESS_CREATE); |
3046 | if (ret) { | 3087 | if (ret) { |
3047 | mlog_errno(ret); | 3088 | mlog_errno(ret); |
3048 | goto out_commit; | 3089 | goto out; |
3049 | } | 3090 | } |
3050 | 3091 | ||
3051 | ocfs2_cp_xattr_block_to_bucket(inode, xb_bh, xs->bucket); | 3092 | ocfs2_cp_xattr_block_to_bucket(inode, xb_bh, xs->bucket); |
@@ -3070,16 +3111,9 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, | |||
3070 | 3111 | ||
3071 | xb->xb_flags = cpu_to_le16(xb_flags | OCFS2_XATTR_INDEXED); | 3112 | xb->xb_flags = cpu_to_le16(xb_flags | OCFS2_XATTR_INDEXED); |
3072 | 3113 | ||
3073 | ret = ocfs2_journal_dirty(handle, xb_bh); | 3114 | ocfs2_journal_dirty(handle, xb_bh); |
3074 | if (ret) { | ||
3075 | mlog_errno(ret); | ||
3076 | goto out_commit; | ||
3077 | } | ||
3078 | 3115 | ||
3079 | out_commit: | 3116 | out: |
3080 | ocfs2_commit_trans(osb, handle); | ||
3081 | |||
3082 | out_sem: | ||
3083 | up_write(&oi->ip_alloc_sem); | 3117 | up_write(&oi->ip_alloc_sem); |
3084 | 3118 | ||
3085 | return ret; | 3119 | return ret; |
@@ -3105,6 +3139,7 @@ static int cmp_xe_offset(const void *a, const void *b) | |||
3105 | * so that we can spare some space for insertion. | 3139 | * so that we can spare some space for insertion. |
3106 | */ | 3140 | */ |
3107 | static int ocfs2_defrag_xattr_bucket(struct inode *inode, | 3141 | static int ocfs2_defrag_xattr_bucket(struct inode *inode, |
3142 | handle_t *handle, | ||
3108 | struct ocfs2_xattr_bucket *bucket) | 3143 | struct ocfs2_xattr_bucket *bucket) |
3109 | { | 3144 | { |
3110 | int ret, i; | 3145 | int ret, i; |
@@ -3114,7 +3149,6 @@ static int ocfs2_defrag_xattr_bucket(struct inode *inode, | |||
3114 | u64 blkno = bucket_blkno(bucket); | 3149 | u64 blkno = bucket_blkno(bucket); |
3115 | u16 xh_free_start; | 3150 | u16 xh_free_start; |
3116 | size_t blocksize = inode->i_sb->s_blocksize; | 3151 | size_t blocksize = inode->i_sb->s_blocksize; |
3117 | handle_t *handle; | ||
3118 | struct ocfs2_xattr_entry *xe; | 3152 | struct ocfs2_xattr_entry *xe; |
3119 | 3153 | ||
3120 | /* | 3154 | /* |
@@ -3133,19 +3167,11 @@ static int ocfs2_defrag_xattr_bucket(struct inode *inode, | |||
3133 | for (i = 0; i < bucket->bu_blocks; i++, buf += blocksize) | 3167 | for (i = 0; i < bucket->bu_blocks; i++, buf += blocksize) |
3134 | memcpy(buf, bucket_block(bucket, i), blocksize); | 3168 | memcpy(buf, bucket_block(bucket, i), blocksize); |
3135 | 3169 | ||
3136 | handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)), bucket->bu_blocks); | ||
3137 | if (IS_ERR(handle)) { | ||
3138 | ret = PTR_ERR(handle); | ||
3139 | handle = NULL; | ||
3140 | mlog_errno(ret); | ||
3141 | goto out; | ||
3142 | } | ||
3143 | |||
3144 | ret = ocfs2_xattr_bucket_journal_access(handle, bucket, | 3170 | ret = ocfs2_xattr_bucket_journal_access(handle, bucket, |
3145 | OCFS2_JOURNAL_ACCESS_WRITE); | 3171 | OCFS2_JOURNAL_ACCESS_WRITE); |
3146 | if (ret < 0) { | 3172 | if (ret < 0) { |
3147 | mlog_errno(ret); | 3173 | mlog_errno(ret); |
3148 | goto commit; | 3174 | goto out; |
3149 | } | 3175 | } |
3150 | 3176 | ||
3151 | xh = (struct ocfs2_xattr_header *)bucket_buf; | 3177 | xh = (struct ocfs2_xattr_header *)bucket_buf; |
@@ -3203,7 +3229,7 @@ static int ocfs2_defrag_xattr_bucket(struct inode *inode, | |||
3203 | "bucket %llu\n", (unsigned long long)blkno); | 3229 | "bucket %llu\n", (unsigned long long)blkno); |
3204 | 3230 | ||
3205 | if (xh_free_start == end) | 3231 | if (xh_free_start == end) |
3206 | goto commit; | 3232 | goto out; |
3207 | 3233 | ||
3208 | memset(bucket_buf + xh_free_start, 0, end - xh_free_start); | 3234 | memset(bucket_buf + xh_free_start, 0, end - xh_free_start); |
3209 | xh->xh_free_start = cpu_to_le16(end); | 3235 | xh->xh_free_start = cpu_to_le16(end); |
@@ -3218,8 +3244,6 @@ static int ocfs2_defrag_xattr_bucket(struct inode *inode, | |||
3218 | memcpy(bucket_block(bucket, i), buf, blocksize); | 3244 | memcpy(bucket_block(bucket, i), buf, blocksize); |
3219 | ocfs2_xattr_bucket_journal_dirty(handle, bucket); | 3245 | ocfs2_xattr_bucket_journal_dirty(handle, bucket); |
3220 | 3246 | ||
3221 | commit: | ||
3222 | ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); | ||
3223 | out: | 3247 | out: |
3224 | kfree(bucket_buf); | 3248 | kfree(bucket_buf); |
3225 | return ret; | 3249 | return ret; |
@@ -3270,7 +3294,7 @@ static int ocfs2_mv_xattr_bucket_cross_cluster(struct inode *inode, | |||
3270 | * 1 more for the update of the 1st bucket of the previous | 3294 | * 1 more for the update of the 1st bucket of the previous |
3271 | * extent record. | 3295 | * extent record. |
3272 | */ | 3296 | */ |
3273 | credits = bpc / 2 + 1; | 3297 | credits = bpc / 2 + 1 + handle->h_buffer_credits; |
3274 | ret = ocfs2_extend_trans(handle, credits); | 3298 | ret = ocfs2_extend_trans(handle, credits); |
3275 | if (ret) { | 3299 | if (ret) { |
3276 | mlog_errno(ret); | 3300 | mlog_errno(ret); |
@@ -3662,7 +3686,7 @@ static int ocfs2_cp_xattr_cluster(struct inode *inode, | |||
3662 | * We need to update the new cluster and 1 more for the update of | 3686 | * We need to update the new cluster and 1 more for the update of |
3663 | * the 1st bucket of the previous extent rec. | 3687 | * the 1st bucket of the previous extent rec. |
3664 | */ | 3688 | */ |
3665 | credits = bpc + 1; | 3689 | credits = bpc + 1 + handle->h_buffer_credits; |
3666 | ret = ocfs2_extend_trans(handle, credits); | 3690 | ret = ocfs2_extend_trans(handle, credits); |
3667 | if (ret) { | 3691 | if (ret) { |
3668 | mlog_errno(ret); | 3692 | mlog_errno(ret); |
@@ -3732,7 +3756,7 @@ static int ocfs2_divide_xattr_cluster(struct inode *inode, | |||
3732 | u32 *first_hash) | 3756 | u32 *first_hash) |
3733 | { | 3757 | { |
3734 | u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb); | 3758 | u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb); |
3735 | int ret, credits = 2 * blk_per_bucket; | 3759 | int ret, credits = 2 * blk_per_bucket + handle->h_buffer_credits; |
3736 | 3760 | ||
3737 | BUG_ON(OCFS2_XATTR_BUCKET_SIZE < OCFS2_SB(inode->i_sb)->s_clustersize); | 3761 | BUG_ON(OCFS2_XATTR_BUCKET_SIZE < OCFS2_SB(inode->i_sb)->s_clustersize); |
3738 | 3762 | ||
@@ -3845,12 +3869,12 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, | |||
3845 | int *extend, | 3869 | int *extend, |
3846 | struct ocfs2_xattr_set_ctxt *ctxt) | 3870 | struct ocfs2_xattr_set_ctxt *ctxt) |
3847 | { | 3871 | { |
3848 | int ret, credits; | 3872 | int ret; |
3849 | u16 bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1); | 3873 | u16 bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1); |
3850 | u32 prev_clusters = *num_clusters; | 3874 | u32 prev_clusters = *num_clusters; |
3851 | u32 clusters_to_add = 1, bit_off, num_bits, v_start = 0; | 3875 | u32 clusters_to_add = 1, bit_off, num_bits, v_start = 0; |
3852 | u64 block; | 3876 | u64 block; |
3853 | handle_t *handle = NULL; | 3877 | handle_t *handle = ctxt->handle; |
3854 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 3878 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
3855 | struct ocfs2_extent_tree et; | 3879 | struct ocfs2_extent_tree et; |
3856 | 3880 | ||
@@ -3861,16 +3885,6 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, | |||
3861 | 3885 | ||
3862 | ocfs2_init_xattr_tree_extent_tree(&et, inode, root_bh); | 3886 | ocfs2_init_xattr_tree_extent_tree(&et, inode, root_bh); |
3863 | 3887 | ||
3864 | credits = ocfs2_calc_extend_credits(osb->sb, et.et_root_el, | ||
3865 | clusters_to_add); | ||
3866 | handle = ocfs2_start_trans(osb, credits); | ||
3867 | if (IS_ERR(handle)) { | ||
3868 | ret = PTR_ERR(handle); | ||
3869 | handle = NULL; | ||
3870 | mlog_errno(ret); | ||
3871 | goto leave; | ||
3872 | } | ||
3873 | |||
3874 | ret = ocfs2_journal_access(handle, inode, root_bh, | 3888 | ret = ocfs2_journal_access(handle, inode, root_bh, |
3875 | OCFS2_JOURNAL_ACCESS_WRITE); | 3889 | OCFS2_JOURNAL_ACCESS_WRITE); |
3876 | if (ret < 0) { | 3890 | if (ret < 0) { |
@@ -3924,18 +3938,6 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, | |||
3924 | } | 3938 | } |
3925 | } | 3939 | } |
3926 | 3940 | ||
3927 | if (handle->h_buffer_credits < credits) { | ||
3928 | /* | ||
3929 | * The journal has been restarted before, and don't | ||
3930 | * have enough space for the insertion, so extend it | ||
3931 | * here. | ||
3932 | */ | ||
3933 | ret = ocfs2_extend_trans(handle, credits); | ||
3934 | if (ret) { | ||
3935 | mlog_errno(ret); | ||
3936 | goto leave; | ||
3937 | } | ||
3938 | } | ||
3939 | mlog(0, "Insert %u clusters at block %llu for xattr at %u\n", | 3941 | mlog(0, "Insert %u clusters at block %llu for xattr at %u\n", |
3940 | num_bits, (unsigned long long)block, v_start); | 3942 | num_bits, (unsigned long long)block, v_start); |
3941 | ret = ocfs2_insert_extent(osb, handle, inode, &et, v_start, block, | 3943 | ret = ocfs2_insert_extent(osb, handle, inode, &et, v_start, block, |
@@ -3946,15 +3948,10 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, | |||
3946 | } | 3948 | } |
3947 | 3949 | ||
3948 | ret = ocfs2_journal_dirty(handle, root_bh); | 3950 | ret = ocfs2_journal_dirty(handle, root_bh); |
3949 | if (ret < 0) { | 3951 | if (ret < 0) |
3950 | mlog_errno(ret); | 3952 | mlog_errno(ret); |
3951 | goto leave; | ||
3952 | } | ||
3953 | 3953 | ||
3954 | leave: | 3954 | leave: |
3955 | if (handle) | ||
3956 | ocfs2_commit_trans(osb, handle); | ||
3957 | |||
3958 | return ret; | 3955 | return ret; |
3959 | } | 3956 | } |
3960 | 3957 | ||
@@ -3963,6 +3960,7 @@ leave: | |||
3963 | * We meet with start_bh. Only move half of the xattrs to the bucket after it. | 3960 | * We meet with start_bh. Only move half of the xattrs to the bucket after it. |
3964 | */ | 3961 | */ |
3965 | static int ocfs2_extend_xattr_bucket(struct inode *inode, | 3962 | static int ocfs2_extend_xattr_bucket(struct inode *inode, |
3963 | handle_t *handle, | ||
3966 | struct buffer_head *first_bh, | 3964 | struct buffer_head *first_bh, |
3967 | struct buffer_head *start_bh, | 3965 | struct buffer_head *start_bh, |
3968 | u32 num_clusters) | 3966 | u32 num_clusters) |
@@ -3972,7 +3970,6 @@ static int ocfs2_extend_xattr_bucket(struct inode *inode, | |||
3972 | u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb); | 3970 | u16 blk_per_bucket = ocfs2_blocks_per_xattr_bucket(inode->i_sb); |
3973 | u64 start_blk = start_bh->b_blocknr, end_blk; | 3971 | u64 start_blk = start_bh->b_blocknr, end_blk; |
3974 | u32 num_buckets = num_clusters * ocfs2_xattr_buckets_per_cluster(osb); | 3972 | u32 num_buckets = num_clusters * ocfs2_xattr_buckets_per_cluster(osb); |
3975 | handle_t *handle; | ||
3976 | struct ocfs2_xattr_header *first_xh = | 3973 | struct ocfs2_xattr_header *first_xh = |
3977 | (struct ocfs2_xattr_header *)first_bh->b_data; | 3974 | (struct ocfs2_xattr_header *)first_bh->b_data; |
3978 | u16 bucket = le16_to_cpu(first_xh->xh_num_buckets); | 3975 | u16 bucket = le16_to_cpu(first_xh->xh_num_buckets); |
@@ -3989,11 +3986,10 @@ static int ocfs2_extend_xattr_bucket(struct inode *inode, | |||
3989 | * We will touch all the buckets after the start_bh(include it). | 3986 | * We will touch all the buckets after the start_bh(include it). |
3990 | * Then we add one more bucket. | 3987 | * Then we add one more bucket. |
3991 | */ | 3988 | */ |
3992 | credits = end_blk - start_blk + 3 * blk_per_bucket + 1; | 3989 | credits = end_blk - start_blk + 3 * blk_per_bucket + 1 + |
3993 | handle = ocfs2_start_trans(osb, credits); | 3990 | handle->h_buffer_credits; |
3994 | if (IS_ERR(handle)) { | 3991 | ret = ocfs2_extend_trans(handle, credits); |
3995 | ret = PTR_ERR(handle); | 3992 | if (ret) { |
3996 | handle = NULL; | ||
3997 | mlog_errno(ret); | 3993 | mlog_errno(ret); |
3998 | goto out; | 3994 | goto out; |
3999 | } | 3995 | } |
@@ -4002,14 +3998,14 @@ static int ocfs2_extend_xattr_bucket(struct inode *inode, | |||
4002 | OCFS2_JOURNAL_ACCESS_WRITE); | 3998 | OCFS2_JOURNAL_ACCESS_WRITE); |
4003 | if (ret) { | 3999 | if (ret) { |
4004 | mlog_errno(ret); | 4000 | mlog_errno(ret); |
4005 | goto commit; | 4001 | goto out; |
4006 | } | 4002 | } |
4007 | 4003 | ||
4008 | while (end_blk != start_blk) { | 4004 | while (end_blk != start_blk) { |
4009 | ret = ocfs2_cp_xattr_bucket(inode, handle, end_blk, | 4005 | ret = ocfs2_cp_xattr_bucket(inode, handle, end_blk, |
4010 | end_blk + blk_per_bucket, 0); | 4006 | end_blk + blk_per_bucket, 0); |
4011 | if (ret) | 4007 | if (ret) |
4012 | goto commit; | 4008 | goto out; |
4013 | end_blk -= blk_per_bucket; | 4009 | end_blk -= blk_per_bucket; |
4014 | } | 4010 | } |
4015 | 4011 | ||
@@ -4020,8 +4016,6 @@ static int ocfs2_extend_xattr_bucket(struct inode *inode, | |||
4020 | le16_add_cpu(&first_xh->xh_num_buckets, 1); | 4016 | le16_add_cpu(&first_xh->xh_num_buckets, 1); |
4021 | ocfs2_journal_dirty(handle, first_bh); | 4017 | ocfs2_journal_dirty(handle, first_bh); |
4022 | 4018 | ||
4023 | commit: | ||
4024 | ocfs2_commit_trans(osb, handle); | ||
4025 | out: | 4019 | out: |
4026 | return ret; | 4020 | return ret; |
4027 | } | 4021 | } |
@@ -4099,6 +4093,7 @@ static int ocfs2_add_new_xattr_bucket(struct inode *inode, | |||
4099 | 4093 | ||
4100 | if (extend) | 4094 | if (extend) |
4101 | ret = ocfs2_extend_xattr_bucket(inode, | 4095 | ret = ocfs2_extend_xattr_bucket(inode, |
4096 | ctxt->handle, | ||
4102 | first_bh, | 4097 | first_bh, |
4103 | header_bh, | 4098 | header_bh, |
4104 | num_clusters); | 4099 | num_clusters); |
@@ -4272,14 +4267,13 @@ set_new_name_value: | |||
4272 | * space for the xattr insertion. | 4267 | * space for the xattr insertion. |
4273 | */ | 4268 | */ |
4274 | static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode, | 4269 | static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode, |
4270 | handle_t *handle, | ||
4275 | struct ocfs2_xattr_info *xi, | 4271 | struct ocfs2_xattr_info *xi, |
4276 | struct ocfs2_xattr_search *xs, | 4272 | struct ocfs2_xattr_search *xs, |
4277 | u32 name_hash, | 4273 | u32 name_hash, |
4278 | int local) | 4274 | int local) |
4279 | { | 4275 | { |
4280 | int ret; | 4276 | int ret; |
4281 | handle_t *handle = NULL; | ||
4282 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
4283 | u64 blkno; | 4277 | u64 blkno; |
4284 | 4278 | ||
4285 | mlog(0, "Set xattr entry len = %lu index = %d in bucket %llu\n", | 4279 | mlog(0, "Set xattr entry len = %lu index = %d in bucket %llu\n", |
@@ -4296,14 +4290,6 @@ static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode, | |||
4296 | } | 4290 | } |
4297 | } | 4291 | } |
4298 | 4292 | ||
4299 | handle = ocfs2_start_trans(osb, xs->bucket->bu_blocks); | ||
4300 | if (IS_ERR(handle)) { | ||
4301 | ret = PTR_ERR(handle); | ||
4302 | handle = NULL; | ||
4303 | mlog_errno(ret); | ||
4304 | goto out; | ||
4305 | } | ||
4306 | |||
4307 | ret = ocfs2_xattr_bucket_journal_access(handle, xs->bucket, | 4293 | ret = ocfs2_xattr_bucket_journal_access(handle, xs->bucket, |
4308 | OCFS2_JOURNAL_ACCESS_WRITE); | 4294 | OCFS2_JOURNAL_ACCESS_WRITE); |
4309 | if (ret < 0) { | 4295 | if (ret < 0) { |
@@ -4315,32 +4301,22 @@ static int ocfs2_xattr_set_entry_in_bucket(struct inode *inode, | |||
4315 | ocfs2_xattr_bucket_journal_dirty(handle, xs->bucket); | 4301 | ocfs2_xattr_bucket_journal_dirty(handle, xs->bucket); |
4316 | 4302 | ||
4317 | out: | 4303 | out: |
4318 | ocfs2_commit_trans(osb, handle); | ||
4319 | |||
4320 | return ret; | 4304 | return ret; |
4321 | } | 4305 | } |
4322 | 4306 | ||
4323 | static int ocfs2_xattr_value_update_size(struct inode *inode, | 4307 | static int ocfs2_xattr_value_update_size(struct inode *inode, |
4308 | handle_t *handle, | ||
4324 | struct buffer_head *xe_bh, | 4309 | struct buffer_head *xe_bh, |
4325 | struct ocfs2_xattr_entry *xe, | 4310 | struct ocfs2_xattr_entry *xe, |
4326 | u64 new_size) | 4311 | u64 new_size) |
4327 | { | 4312 | { |
4328 | int ret; | 4313 | int ret; |
4329 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
4330 | handle_t *handle = NULL; | ||
4331 | |||
4332 | handle = ocfs2_start_trans(osb, 1); | ||
4333 | if (IS_ERR(handle)) { | ||
4334 | ret = -ENOMEM; | ||
4335 | mlog_errno(ret); | ||
4336 | goto out; | ||
4337 | } | ||
4338 | 4314 | ||
4339 | ret = ocfs2_journal_access(handle, inode, xe_bh, | 4315 | ret = ocfs2_journal_access(handle, inode, xe_bh, |
4340 | OCFS2_JOURNAL_ACCESS_WRITE); | 4316 | OCFS2_JOURNAL_ACCESS_WRITE); |
4341 | if (ret < 0) { | 4317 | if (ret < 0) { |
4342 | mlog_errno(ret); | 4318 | mlog_errno(ret); |
4343 | goto out_commit; | 4319 | goto out; |
4344 | } | 4320 | } |
4345 | 4321 | ||
4346 | xe->xe_value_size = cpu_to_le64(new_size); | 4322 | xe->xe_value_size = cpu_to_le64(new_size); |
@@ -4349,8 +4325,6 @@ static int ocfs2_xattr_value_update_size(struct inode *inode, | |||
4349 | if (ret < 0) | 4325 | if (ret < 0) |
4350 | mlog_errno(ret); | 4326 | mlog_errno(ret); |
4351 | 4327 | ||
4352 | out_commit: | ||
4353 | ocfs2_commit_trans(osb, handle); | ||
4354 | out: | 4328 | out: |
4355 | return ret; | 4329 | return ret; |
4356 | } | 4330 | } |
@@ -4407,7 +4381,8 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode, | |||
4407 | goto out; | 4381 | goto out; |
4408 | } | 4382 | } |
4409 | 4383 | ||
4410 | ret = ocfs2_xattr_value_update_size(inode, header_bh, xe, len); | 4384 | ret = ocfs2_xattr_value_update_size(inode, ctxt->handle, |
4385 | header_bh, xe, len); | ||
4411 | if (ret) { | 4386 | if (ret) { |
4412 | mlog_errno(ret); | 4387 | mlog_errno(ret); |
4413 | goto out; | 4388 | goto out; |
@@ -4439,6 +4414,7 @@ static int ocfs2_xattr_bucket_value_truncate_xs(struct inode *inode, | |||
4439 | } | 4414 | } |
4440 | 4415 | ||
4441 | static int ocfs2_xattr_bucket_set_value_outside(struct inode *inode, | 4416 | static int ocfs2_xattr_bucket_set_value_outside(struct inode *inode, |
4417 | handle_t *handle, | ||
4442 | struct ocfs2_xattr_search *xs, | 4418 | struct ocfs2_xattr_search *xs, |
4443 | char *val, | 4419 | char *val, |
4444 | int value_len) | 4420 | int value_len) |
@@ -4454,7 +4430,8 @@ static int ocfs2_xattr_bucket_set_value_outside(struct inode *inode, | |||
4454 | 4430 | ||
4455 | xv = (struct ocfs2_xattr_value_root *)(xs->base + offset); | 4431 | xv = (struct ocfs2_xattr_value_root *)(xs->base + offset); |
4456 | 4432 | ||
4457 | return __ocfs2_xattr_set_value_outside(inode, xv, val, value_len); | 4433 | return __ocfs2_xattr_set_value_outside(inode, handle, |
4434 | xv, val, value_len); | ||
4458 | } | 4435 | } |
4459 | 4436 | ||
4460 | static int ocfs2_rm_xattr_cluster(struct inode *inode, | 4437 | static int ocfs2_rm_xattr_cluster(struct inode *inode, |
@@ -4547,27 +4524,19 @@ out: | |||
4547 | } | 4524 | } |
4548 | 4525 | ||
4549 | static void ocfs2_xattr_bucket_remove_xs(struct inode *inode, | 4526 | static void ocfs2_xattr_bucket_remove_xs(struct inode *inode, |
4527 | handle_t *handle, | ||
4550 | struct ocfs2_xattr_search *xs) | 4528 | struct ocfs2_xattr_search *xs) |
4551 | { | 4529 | { |
4552 | handle_t *handle = NULL; | ||
4553 | struct ocfs2_xattr_header *xh = bucket_xh(xs->bucket); | 4530 | struct ocfs2_xattr_header *xh = bucket_xh(xs->bucket); |
4554 | struct ocfs2_xattr_entry *last = &xh->xh_entries[ | 4531 | struct ocfs2_xattr_entry *last = &xh->xh_entries[ |
4555 | le16_to_cpu(xh->xh_count) - 1]; | 4532 | le16_to_cpu(xh->xh_count) - 1]; |
4556 | int ret = 0; | 4533 | int ret = 0; |
4557 | 4534 | ||
4558 | handle = ocfs2_start_trans((OCFS2_SB(inode->i_sb)), | ||
4559 | ocfs2_blocks_per_xattr_bucket(inode->i_sb)); | ||
4560 | if (IS_ERR(handle)) { | ||
4561 | ret = PTR_ERR(handle); | ||
4562 | mlog_errno(ret); | ||
4563 | return; | ||
4564 | } | ||
4565 | |||
4566 | ret = ocfs2_xattr_bucket_journal_access(handle, xs->bucket, | 4535 | ret = ocfs2_xattr_bucket_journal_access(handle, xs->bucket, |
4567 | OCFS2_JOURNAL_ACCESS_WRITE); | 4536 | OCFS2_JOURNAL_ACCESS_WRITE); |
4568 | if (ret) { | 4537 | if (ret) { |
4569 | mlog_errno(ret); | 4538 | mlog_errno(ret); |
4570 | goto out_commit; | 4539 | return; |
4571 | } | 4540 | } |
4572 | 4541 | ||
4573 | /* Remove the old entry. */ | 4542 | /* Remove the old entry. */ |
@@ -4577,9 +4546,6 @@ static void ocfs2_xattr_bucket_remove_xs(struct inode *inode, | |||
4577 | le16_add_cpu(&xh->xh_count, -1); | 4546 | le16_add_cpu(&xh->xh_count, -1); |
4578 | 4547 | ||
4579 | ocfs2_xattr_bucket_journal_dirty(handle, xs->bucket); | 4548 | ocfs2_xattr_bucket_journal_dirty(handle, xs->bucket); |
4580 | |||
4581 | out_commit: | ||
4582 | ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); | ||
4583 | } | 4549 | } |
4584 | 4550 | ||
4585 | /* | 4551 | /* |
@@ -4645,7 +4611,8 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode, | |||
4645 | xi->value_len = OCFS2_XATTR_ROOT_SIZE; | 4611 | xi->value_len = OCFS2_XATTR_ROOT_SIZE; |
4646 | } | 4612 | } |
4647 | 4613 | ||
4648 | ret = ocfs2_xattr_set_entry_in_bucket(inode, xi, xs, name_hash, local); | 4614 | ret = ocfs2_xattr_set_entry_in_bucket(inode, ctxt->handle, xi, xs, |
4615 | name_hash, local); | ||
4649 | if (ret) { | 4616 | if (ret) { |
4650 | mlog_errno(ret); | 4617 | mlog_errno(ret); |
4651 | goto out; | 4618 | goto out; |
@@ -4666,13 +4633,14 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode, | |||
4666 | * storage and we have allocated xattr already, | 4633 | * storage and we have allocated xattr already, |
4667 | * so need to remove it. | 4634 | * so need to remove it. |
4668 | */ | 4635 | */ |
4669 | ocfs2_xattr_bucket_remove_xs(inode, xs); | 4636 | ocfs2_xattr_bucket_remove_xs(inode, ctxt->handle, xs); |
4670 | } | 4637 | } |
4671 | goto out; | 4638 | goto out; |
4672 | } | 4639 | } |
4673 | 4640 | ||
4674 | set_value_outside: | 4641 | set_value_outside: |
4675 | ret = ocfs2_xattr_bucket_set_value_outside(inode, xs, val, value_len); | 4642 | ret = ocfs2_xattr_bucket_set_value_outside(inode, ctxt->handle, |
4643 | xs, val, value_len); | ||
4676 | out: | 4644 | out: |
4677 | return ret; | 4645 | return ret; |
4678 | } | 4646 | } |
@@ -4785,7 +4753,8 @@ try_again: | |||
4785 | * name/value will be moved, the xe shouldn't be changed | 4753 | * name/value will be moved, the xe shouldn't be changed |
4786 | * in xs. | 4754 | * in xs. |
4787 | */ | 4755 | */ |
4788 | ret = ocfs2_defrag_xattr_bucket(inode, xs->bucket); | 4756 | ret = ocfs2_defrag_xattr_bucket(inode, ctxt->handle, |
4757 | xs->bucket); | ||
4789 | if (ret) { | 4758 | if (ret) { |
4790 | mlog_errno(ret); | 4759 | mlog_errno(ret); |
4791 | goto out; | 4760 | goto out; |
@@ -4865,6 +4834,13 @@ static int ocfs2_delete_xattr_in_bucket(struct inode *inode, | |||
4865 | 4834 | ||
4866 | ocfs2_init_dealloc_ctxt(&ctxt.dealloc); | 4835 | ocfs2_init_dealloc_ctxt(&ctxt.dealloc); |
4867 | 4836 | ||
4837 | ctxt.handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS); | ||
4838 | if (IS_ERR(ctxt.handle)) { | ||
4839 | ret = PTR_ERR(ctxt.handle); | ||
4840 | mlog_errno(ret); | ||
4841 | goto out; | ||
4842 | } | ||
4843 | |||
4868 | for (i = 0; i < le16_to_cpu(xh->xh_count); i++) { | 4844 | for (i = 0; i < le16_to_cpu(xh->xh_count); i++) { |
4869 | xe = &xh->xh_entries[i]; | 4845 | xe = &xh->xh_entries[i]; |
4870 | if (ocfs2_xattr_is_local(xe)) | 4846 | if (ocfs2_xattr_is_local(xe)) |
@@ -4879,9 +4855,10 @@ static int ocfs2_delete_xattr_in_bucket(struct inode *inode, | |||
4879 | } | 4855 | } |
4880 | } | 4856 | } |
4881 | 4857 | ||
4858 | ret = ocfs2_commit_trans(osb, ctxt.handle); | ||
4882 | ocfs2_schedule_truncate_log_flush(osb, 1); | 4859 | ocfs2_schedule_truncate_log_flush(osb, 1); |
4883 | ocfs2_run_deallocs(osb, &ctxt.dealloc); | 4860 | ocfs2_run_deallocs(osb, &ctxt.dealloc); |
4884 | 4861 | out: | |
4885 | return ret; | 4862 | return ret; |
4886 | } | 4863 | } |
4887 | 4864 | ||