diff options
author | Tao Ma <tao.ma@oracle.com> | 2008-11-11 19:27:00 -0500 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2009-01-05 11:34:19 -0500 |
commit | 78f30c314a74b9dc5d7368d96fe4be883d9a3a04 (patch) | |
tree | 07904e23f2d2c1287869daecc9f27052b71d67a5 /fs/ocfs2/xattr.c | |
parent | c73f60f900ddf73ec4ea2a143829ab97242c4e8c (diff) |
ocfs2/xattr: Reserve meta/data at the beginning of ocfs2_xattr_set.
In ocfs2 xattr set, we reserve metadata and clusters in any place
they are needed. It is time-consuming and ineffective, so this
patch try to reserve metadata and clusters at the beginning of
ocfs2_xattr_set.
Signed-off-by: Tao Ma <tao.ma@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Diffstat (limited to 'fs/ocfs2/xattr.c')
-rw-r--r-- | fs/ocfs2/xattr.c | 483 |
1 files changed, 357 insertions, 126 deletions
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index f1da381a44f6..4fd201a54c72 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -71,6 +71,12 @@ struct ocfs2_xattr_bucket { | |||
71 | int bu_blocks; | 71 | int bu_blocks; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | struct ocfs2_xattr_set_ctxt { | ||
75 | struct ocfs2_alloc_context *meta_ac; | ||
76 | struct ocfs2_alloc_context *data_ac; | ||
77 | struct ocfs2_cached_dealloc_ctxt dealloc; | ||
78 | }; | ||
79 | |||
74 | #define OCFS2_XATTR_ROOT_SIZE (sizeof(struct ocfs2_xattr_def_value_root)) | 80 | #define OCFS2_XATTR_ROOT_SIZE (sizeof(struct ocfs2_xattr_def_value_root)) |
75 | #define OCFS2_XATTR_INLINE_SIZE 80 | 81 | #define OCFS2_XATTR_INLINE_SIZE 80 |
76 | 82 | ||
@@ -133,11 +139,13 @@ static int ocfs2_xattr_tree_list_index_block(struct inode *inode, | |||
133 | size_t buffer_size); | 139 | size_t buffer_size); |
134 | 140 | ||
135 | static int ocfs2_xattr_create_index_block(struct inode *inode, | 141 | static int ocfs2_xattr_create_index_block(struct inode *inode, |
136 | struct ocfs2_xattr_search *xs); | 142 | struct ocfs2_xattr_search *xs, |
143 | struct ocfs2_xattr_set_ctxt *ctxt); | ||
137 | 144 | ||
138 | static int ocfs2_xattr_set_entry_index_block(struct inode *inode, | 145 | static int ocfs2_xattr_set_entry_index_block(struct inode *inode, |
139 | struct ocfs2_xattr_info *xi, | 146 | struct ocfs2_xattr_info *xi, |
140 | struct ocfs2_xattr_search *xs); | 147 | struct ocfs2_xattr_search *xs, |
148 | struct ocfs2_xattr_set_ctxt *ctxt); | ||
141 | 149 | ||
142 | static int ocfs2_delete_xattr_index_block(struct inode *inode, | 150 | static int ocfs2_delete_xattr_index_block(struct inode *inode, |
143 | struct buffer_head *xb_bh); | 151 | struct buffer_head *xb_bh); |
@@ -334,14 +342,13 @@ static void ocfs2_xattr_hash_entry(struct inode *inode, | |||
334 | static int ocfs2_xattr_extend_allocation(struct inode *inode, | 342 | static int ocfs2_xattr_extend_allocation(struct inode *inode, |
335 | u32 clusters_to_add, | 343 | u32 clusters_to_add, |
336 | struct buffer_head *xattr_bh, | 344 | struct buffer_head *xattr_bh, |
337 | struct ocfs2_xattr_value_root *xv) | 345 | struct ocfs2_xattr_value_root *xv, |
346 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
338 | { | 347 | { |
339 | int status = 0; | 348 | int status = 0; |
340 | int restart_func = 0; | 349 | int restart_func = 0; |
341 | int credits = 0; | 350 | int credits = 0; |
342 | handle_t *handle = NULL; | 351 | handle_t *handle = NULL; |
343 | struct ocfs2_alloc_context *data_ac = NULL; | ||
344 | struct ocfs2_alloc_context *meta_ac = NULL; | ||
345 | enum ocfs2_alloc_restarted why; | 352 | enum ocfs2_alloc_restarted why; |
346 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 353 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
347 | u32 prev_clusters, logical_start = le32_to_cpu(xv->xr_clusters); | 354 | u32 prev_clusters, logical_start = le32_to_cpu(xv->xr_clusters); |
@@ -353,13 +360,6 @@ static int ocfs2_xattr_extend_allocation(struct inode *inode, | |||
353 | 360 | ||
354 | restart_all: | 361 | restart_all: |
355 | 362 | ||
356 | status = ocfs2_lock_allocators(inode, &et, clusters_to_add, 0, | ||
357 | &data_ac, &meta_ac); | ||
358 | if (status) { | ||
359 | mlog_errno(status); | ||
360 | goto leave; | ||
361 | } | ||
362 | |||
363 | credits = ocfs2_calc_extend_credits(osb->sb, et.et_root_el, | 363 | credits = ocfs2_calc_extend_credits(osb->sb, et.et_root_el, |
364 | clusters_to_add); | 364 | clusters_to_add); |
365 | handle = ocfs2_start_trans(osb, credits); | 365 | handle = ocfs2_start_trans(osb, credits); |
@@ -386,8 +386,8 @@ restarted_transaction: | |||
386 | 0, | 386 | 0, |
387 | &et, | 387 | &et, |
388 | handle, | 388 | handle, |
389 | data_ac, | 389 | ctxt->data_ac, |
390 | meta_ac, | 390 | ctxt->meta_ac, |
391 | &why); | 391 | &why); |
392 | if ((status < 0) && (status != -EAGAIN)) { | 392 | if ((status < 0) && (status != -EAGAIN)) { |
393 | if (status != -ENOSPC) | 393 | if (status != -ENOSPC) |
@@ -432,14 +432,6 @@ leave: | |||
432 | ocfs2_commit_trans(osb, handle); | 432 | ocfs2_commit_trans(osb, handle); |
433 | handle = NULL; | 433 | handle = NULL; |
434 | } | 434 | } |
435 | if (data_ac) { | ||
436 | ocfs2_free_alloc_context(data_ac); | ||
437 | data_ac = NULL; | ||
438 | } | ||
439 | if (meta_ac) { | ||
440 | ocfs2_free_alloc_context(meta_ac); | ||
441 | meta_ac = NULL; | ||
442 | } | ||
443 | if ((!status) && restart_func) { | 435 | if ((!status) && restart_func) { |
444 | restart_func = 0; | 436 | restart_func = 0; |
445 | goto restart_all; | 437 | goto restart_all; |
@@ -452,23 +444,16 @@ static int __ocfs2_remove_xattr_range(struct inode *inode, | |||
452 | struct buffer_head *root_bh, | 444 | struct buffer_head *root_bh, |
453 | struct ocfs2_xattr_value_root *xv, | 445 | struct ocfs2_xattr_value_root *xv, |
454 | u32 cpos, u32 phys_cpos, u32 len, | 446 | u32 cpos, u32 phys_cpos, u32 len, |
455 | struct ocfs2_cached_dealloc_ctxt *dealloc) | 447 | struct ocfs2_xattr_set_ctxt *ctxt) |
456 | { | 448 | { |
457 | int ret; | 449 | int ret; |
458 | u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos); | 450 | u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos); |
459 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 451 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
460 | handle_t *handle; | 452 | handle_t *handle; |
461 | struct ocfs2_alloc_context *meta_ac = NULL; | ||
462 | struct ocfs2_extent_tree et; | 453 | struct ocfs2_extent_tree et; |
463 | 454 | ||
464 | ocfs2_init_xattr_value_extent_tree(&et, inode, root_bh, xv); | 455 | ocfs2_init_xattr_value_extent_tree(&et, inode, root_bh, xv); |
465 | 456 | ||
466 | ret = ocfs2_lock_allocators(inode, &et, 0, 1, NULL, &meta_ac); | ||
467 | if (ret) { | ||
468 | mlog_errno(ret); | ||
469 | return ret; | ||
470 | } | ||
471 | |||
472 | handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS); | 457 | handle = ocfs2_start_trans(osb, OCFS2_REMOVE_EXTENT_CREDITS); |
473 | if (IS_ERR(handle)) { | 458 | if (IS_ERR(handle)) { |
474 | ret = PTR_ERR(handle); | 459 | ret = PTR_ERR(handle); |
@@ -483,8 +468,8 @@ static int __ocfs2_remove_xattr_range(struct inode *inode, | |||
483 | goto out_commit; | 468 | goto out_commit; |
484 | } | 469 | } |
485 | 470 | ||
486 | ret = ocfs2_remove_extent(inode, &et, cpos, len, handle, meta_ac, | 471 | ret = ocfs2_remove_extent(inode, &et, cpos, len, handle, ctxt->meta_ac, |
487 | dealloc); | 472 | &ctxt->dealloc); |
488 | if (ret) { | 473 | if (ret) { |
489 | mlog_errno(ret); | 474 | mlog_errno(ret); |
490 | goto out_commit; | 475 | goto out_commit; |
@@ -498,17 +483,13 @@ static int __ocfs2_remove_xattr_range(struct inode *inode, | |||
498 | goto out_commit; | 483 | goto out_commit; |
499 | } | 484 | } |
500 | 485 | ||
501 | ret = ocfs2_cache_cluster_dealloc(dealloc, phys_blkno, len); | 486 | ret = ocfs2_cache_cluster_dealloc(&ctxt->dealloc, phys_blkno, len); |
502 | if (ret) | 487 | if (ret) |
503 | mlog_errno(ret); | 488 | mlog_errno(ret); |
504 | 489 | ||
505 | out_commit: | 490 | out_commit: |
506 | ocfs2_commit_trans(osb, handle); | 491 | ocfs2_commit_trans(osb, handle); |
507 | out: | 492 | out: |
508 | |||
509 | if (meta_ac) | ||
510 | ocfs2_free_alloc_context(meta_ac); | ||
511 | |||
512 | return ret; | 493 | return ret; |
513 | } | 494 | } |
514 | 495 | ||
@@ -516,15 +497,12 @@ static int ocfs2_xattr_shrink_size(struct inode *inode, | |||
516 | u32 old_clusters, | 497 | u32 old_clusters, |
517 | u32 new_clusters, | 498 | u32 new_clusters, |
518 | struct buffer_head *root_bh, | 499 | struct buffer_head *root_bh, |
519 | struct ocfs2_xattr_value_root *xv) | 500 | struct ocfs2_xattr_value_root *xv, |
501 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
520 | { | 502 | { |
521 | int ret = 0; | 503 | int ret = 0; |
522 | u32 trunc_len, cpos, phys_cpos, alloc_size; | 504 | u32 trunc_len, cpos, phys_cpos, alloc_size; |
523 | u64 block; | 505 | u64 block; |
524 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
525 | struct ocfs2_cached_dealloc_ctxt dealloc; | ||
526 | |||
527 | ocfs2_init_dealloc_ctxt(&dealloc); | ||
528 | 506 | ||
529 | if (old_clusters <= new_clusters) | 507 | if (old_clusters <= new_clusters) |
530 | return 0; | 508 | return 0; |
@@ -544,7 +522,7 @@ static int ocfs2_xattr_shrink_size(struct inode *inode, | |||
544 | 522 | ||
545 | ret = __ocfs2_remove_xattr_range(inode, root_bh, xv, cpos, | 523 | ret = __ocfs2_remove_xattr_range(inode, root_bh, xv, cpos, |
546 | phys_cpos, alloc_size, | 524 | phys_cpos, alloc_size, |
547 | &dealloc); | 525 | ctxt); |
548 | if (ret) { | 526 | if (ret) { |
549 | mlog_errno(ret); | 527 | mlog_errno(ret); |
550 | goto out; | 528 | goto out; |
@@ -558,16 +536,14 @@ static int ocfs2_xattr_shrink_size(struct inode *inode, | |||
558 | } | 536 | } |
559 | 537 | ||
560 | out: | 538 | out: |
561 | ocfs2_schedule_truncate_log_flush(osb, 1); | ||
562 | ocfs2_run_deallocs(osb, &dealloc); | ||
563 | |||
564 | return ret; | 539 | return ret; |
565 | } | 540 | } |
566 | 541 | ||
567 | static int ocfs2_xattr_value_truncate(struct inode *inode, | 542 | static int ocfs2_xattr_value_truncate(struct inode *inode, |
568 | struct buffer_head *root_bh, | 543 | struct buffer_head *root_bh, |
569 | struct ocfs2_xattr_value_root *xv, | 544 | struct ocfs2_xattr_value_root *xv, |
570 | int len) | 545 | int len, |
546 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
571 | { | 547 | { |
572 | int ret; | 548 | int ret; |
573 | u32 new_clusters = ocfs2_clusters_for_bytes(inode->i_sb, len); | 549 | u32 new_clusters = ocfs2_clusters_for_bytes(inode->i_sb, len); |
@@ -579,11 +555,11 @@ static int ocfs2_xattr_value_truncate(struct inode *inode, | |||
579 | if (new_clusters > old_clusters) | 555 | if (new_clusters > old_clusters) |
580 | ret = ocfs2_xattr_extend_allocation(inode, | 556 | ret = ocfs2_xattr_extend_allocation(inode, |
581 | new_clusters - old_clusters, | 557 | new_clusters - old_clusters, |
582 | root_bh, xv); | 558 | root_bh, xv, ctxt); |
583 | else | 559 | else |
584 | ret = ocfs2_xattr_shrink_size(inode, | 560 | ret = ocfs2_xattr_shrink_size(inode, |
585 | old_clusters, new_clusters, | 561 | old_clusters, new_clusters, |
586 | root_bh, xv); | 562 | root_bh, xv, ctxt); |
587 | 563 | ||
588 | return ret; | 564 | return ret; |
589 | } | 565 | } |
@@ -1167,6 +1143,7 @@ out: | |||
1167 | static int ocfs2_xattr_set_value_outside(struct inode *inode, | 1143 | static int ocfs2_xattr_set_value_outside(struct inode *inode, |
1168 | struct ocfs2_xattr_info *xi, | 1144 | struct ocfs2_xattr_info *xi, |
1169 | struct ocfs2_xattr_search *xs, | 1145 | struct ocfs2_xattr_search *xs, |
1146 | struct ocfs2_xattr_set_ctxt *ctxt, | ||
1170 | size_t offs) | 1147 | size_t offs) |
1171 | { | 1148 | { |
1172 | size_t name_len = strlen(xi->name); | 1149 | size_t name_len = strlen(xi->name); |
@@ -1186,7 +1163,7 @@ static int ocfs2_xattr_set_value_outside(struct inode *inode, | |||
1186 | xv->xr_list.l_next_free_rec = 0; | 1163 | xv->xr_list.l_next_free_rec = 0; |
1187 | 1164 | ||
1188 | ret = ocfs2_xattr_value_truncate(inode, xs->xattr_bh, xv, | 1165 | ret = ocfs2_xattr_value_truncate(inode, xs->xattr_bh, xv, |
1189 | xi->value_len); | 1166 | xi->value_len, ctxt); |
1190 | if (ret < 0) { | 1167 | if (ret < 0) { |
1191 | mlog_errno(ret); | 1168 | mlog_errno(ret); |
1192 | return ret; | 1169 | return ret; |
@@ -1317,6 +1294,7 @@ static void ocfs2_xattr_set_entry_local(struct inode *inode, | |||
1317 | static int ocfs2_xattr_set_entry(struct inode *inode, | 1294 | static int ocfs2_xattr_set_entry(struct inode *inode, |
1318 | struct ocfs2_xattr_info *xi, | 1295 | struct ocfs2_xattr_info *xi, |
1319 | struct ocfs2_xattr_search *xs, | 1296 | struct ocfs2_xattr_search *xs, |
1297 | struct ocfs2_xattr_set_ctxt *ctxt, | ||
1320 | int flag) | 1298 | int flag) |
1321 | { | 1299 | { |
1322 | struct ocfs2_xattr_entry *last; | 1300 | struct ocfs2_xattr_entry *last; |
@@ -1387,7 +1365,7 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
1387 | if (ocfs2_xattr_is_local(xs->here) && size == size_l) { | 1365 | if (ocfs2_xattr_is_local(xs->here) && size == size_l) { |
1388 | /* Replace existing local xattr with tree root */ | 1366 | /* Replace existing local xattr with tree root */ |
1389 | ret = ocfs2_xattr_set_value_outside(inode, xi, xs, | 1367 | ret = ocfs2_xattr_set_value_outside(inode, xi, xs, |
1390 | offs); | 1368 | ctxt, offs); |
1391 | if (ret < 0) | 1369 | if (ret < 0) |
1392 | mlog_errno(ret); | 1370 | mlog_errno(ret); |
1393 | goto out; | 1371 | goto out; |
@@ -1406,7 +1384,8 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
1406 | ret = ocfs2_xattr_value_truncate(inode, | 1384 | ret = ocfs2_xattr_value_truncate(inode, |
1407 | xs->xattr_bh, | 1385 | xs->xattr_bh, |
1408 | xv, | 1386 | xv, |
1409 | xi->value_len); | 1387 | xi->value_len, |
1388 | ctxt); | ||
1410 | if (ret < 0) { | 1389 | if (ret < 0) { |
1411 | mlog_errno(ret); | 1390 | mlog_errno(ret); |
1412 | goto out; | 1391 | goto out; |
@@ -1436,7 +1415,8 @@ static int ocfs2_xattr_set_entry(struct inode *inode, | |||
1436 | ret = ocfs2_xattr_value_truncate(inode, | 1415 | ret = ocfs2_xattr_value_truncate(inode, |
1437 | xs->xattr_bh, | 1416 | xs->xattr_bh, |
1438 | xv, | 1417 | xv, |
1439 | 0); | 1418 | 0, |
1419 | ctxt); | ||
1440 | if (ret < 0) | 1420 | if (ret < 0) |
1441 | mlog_errno(ret); | 1421 | mlog_errno(ret); |
1442 | } | 1422 | } |
@@ -1531,7 +1511,7 @@ out_commit: | |||
1531 | * This is the second step for value size > INLINE_SIZE. | 1511 | * This is the second step for value size > INLINE_SIZE. |
1532 | */ | 1512 | */ |
1533 | size_t offs = le16_to_cpu(xs->here->xe_name_offset); | 1513 | size_t offs = le16_to_cpu(xs->here->xe_name_offset); |
1534 | ret = ocfs2_xattr_set_value_outside(inode, xi, xs, offs); | 1514 | ret = ocfs2_xattr_set_value_outside(inode, xi, xs, ctxt, offs); |
1535 | if (ret < 0) { | 1515 | if (ret < 0) { |
1536 | int ret2; | 1516 | int ret2; |
1537 | 1517 | ||
@@ -1555,6 +1535,10 @@ static int ocfs2_remove_value_outside(struct inode*inode, | |||
1555 | struct ocfs2_xattr_header *header) | 1535 | struct ocfs2_xattr_header *header) |
1556 | { | 1536 | { |
1557 | int ret = 0, i; | 1537 | int ret = 0, i; |
1538 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
1539 | struct ocfs2_xattr_set_ctxt ctxt = { NULL, NULL, }; | ||
1540 | |||
1541 | ocfs2_init_dealloc_ctxt(&ctxt.dealloc); | ||
1558 | 1542 | ||
1559 | for (i = 0; i < le16_to_cpu(header->xh_count); i++) { | 1543 | for (i = 0; i < le16_to_cpu(header->xh_count); i++) { |
1560 | struct ocfs2_xattr_entry *entry = &header->xh_entries[i]; | 1544 | struct ocfs2_xattr_entry *entry = &header->xh_entries[i]; |
@@ -1567,14 +1551,17 @@ static int ocfs2_remove_value_outside(struct inode*inode, | |||
1567 | le16_to_cpu(entry->xe_name_offset); | 1551 | le16_to_cpu(entry->xe_name_offset); |
1568 | xv = (struct ocfs2_xattr_value_root *) | 1552 | xv = (struct ocfs2_xattr_value_root *) |
1569 | (val + OCFS2_XATTR_SIZE(entry->xe_name_len)); | 1553 | (val + OCFS2_XATTR_SIZE(entry->xe_name_len)); |
1570 | ret = ocfs2_xattr_value_truncate(inode, bh, xv, 0); | 1554 | ret = ocfs2_xattr_value_truncate(inode, bh, xv, |
1555 | 0, &ctxt); | ||
1571 | if (ret < 0) { | 1556 | if (ret < 0) { |
1572 | mlog_errno(ret); | 1557 | mlog_errno(ret); |
1573 | return ret; | 1558 | break; |
1574 | } | 1559 | } |
1575 | } | 1560 | } |
1576 | } | 1561 | } |
1577 | 1562 | ||
1563 | ocfs2_schedule_truncate_log_flush(osb, 1); | ||
1564 | ocfs2_run_deallocs(osb, &ctxt.dealloc); | ||
1578 | return ret; | 1565 | return ret; |
1579 | } | 1566 | } |
1580 | 1567 | ||
@@ -1836,7 +1823,8 @@ static int ocfs2_xattr_ibody_find(struct inode *inode, | |||
1836 | */ | 1823 | */ |
1837 | static int ocfs2_xattr_ibody_set(struct inode *inode, | 1824 | static int ocfs2_xattr_ibody_set(struct inode *inode, |
1838 | struct ocfs2_xattr_info *xi, | 1825 | struct ocfs2_xattr_info *xi, |
1839 | struct ocfs2_xattr_search *xs) | 1826 | struct ocfs2_xattr_search *xs, |
1827 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
1840 | { | 1828 | { |
1841 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | 1829 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
1842 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; | 1830 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; |
@@ -1853,7 +1841,7 @@ static int ocfs2_xattr_ibody_set(struct inode *inode, | |||
1853 | } | 1841 | } |
1854 | } | 1842 | } |
1855 | 1843 | ||
1856 | ret = ocfs2_xattr_set_entry(inode, xi, xs, | 1844 | ret = ocfs2_xattr_set_entry(inode, xi, xs, ctxt, |
1857 | (OCFS2_INLINE_XATTR_FL | OCFS2_HAS_XATTR_FL)); | 1845 | (OCFS2_INLINE_XATTR_FL | OCFS2_HAS_XATTR_FL)); |
1858 | out: | 1846 | out: |
1859 | up_write(&oi->ip_alloc_sem); | 1847 | up_write(&oi->ip_alloc_sem); |
@@ -1926,12 +1914,12 @@ cleanup: | |||
1926 | */ | 1914 | */ |
1927 | static int ocfs2_xattr_block_set(struct inode *inode, | 1915 | static int ocfs2_xattr_block_set(struct inode *inode, |
1928 | struct ocfs2_xattr_info *xi, | 1916 | struct ocfs2_xattr_info *xi, |
1929 | struct ocfs2_xattr_search *xs) | 1917 | struct ocfs2_xattr_search *xs, |
1918 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
1930 | { | 1919 | { |
1931 | struct buffer_head *new_bh = NULL; | 1920 | struct buffer_head *new_bh = NULL; |
1932 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 1921 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
1933 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; | 1922 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)xs->inode_bh->b_data; |
1934 | struct ocfs2_alloc_context *meta_ac = NULL; | ||
1935 | handle_t *handle = NULL; | 1923 | handle_t *handle = NULL; |
1936 | struct ocfs2_xattr_block *xblk = NULL; | 1924 | struct ocfs2_xattr_block *xblk = NULL; |
1937 | u16 suballoc_bit_start; | 1925 | u16 suballoc_bit_start; |
@@ -1940,15 +1928,6 @@ static int ocfs2_xattr_block_set(struct inode *inode, | |||
1940 | int ret; | 1928 | int ret; |
1941 | 1929 | ||
1942 | if (!xs->xattr_bh) { | 1930 | if (!xs->xattr_bh) { |
1943 | /* | ||
1944 | * Alloc one external block for extended attribute | ||
1945 | * outside of inode. | ||
1946 | */ | ||
1947 | ret = ocfs2_reserve_new_metadata_blocks(osb, 1, &meta_ac); | ||
1948 | if (ret < 0) { | ||
1949 | mlog_errno(ret); | ||
1950 | goto out; | ||
1951 | } | ||
1952 | handle = ocfs2_start_trans(osb, | 1931 | handle = ocfs2_start_trans(osb, |
1953 | OCFS2_XATTR_BLOCK_CREATE_CREDITS); | 1932 | OCFS2_XATTR_BLOCK_CREATE_CREDITS); |
1954 | if (IS_ERR(handle)) { | 1933 | if (IS_ERR(handle)) { |
@@ -1963,7 +1942,7 @@ static int ocfs2_xattr_block_set(struct inode *inode, | |||
1963 | goto out_commit; | 1942 | goto out_commit; |
1964 | } | 1943 | } |
1965 | 1944 | ||
1966 | ret = ocfs2_claim_metadata(osb, handle, meta_ac, 1, | 1945 | ret = ocfs2_claim_metadata(osb, handle, ctxt->meta_ac, 1, |
1967 | &suballoc_bit_start, &num_got, | 1946 | &suballoc_bit_start, &num_got, |
1968 | &first_blkno); | 1947 | &first_blkno); |
1969 | if (ret < 0) { | 1948 | if (ret < 0) { |
@@ -1996,7 +1975,6 @@ static int ocfs2_xattr_block_set(struct inode *inode, | |||
1996 | xs->end = (void *)xblk + inode->i_sb->s_blocksize; | 1975 | xs->end = (void *)xblk + inode->i_sb->s_blocksize; |
1997 | xs->here = xs->header->xh_entries; | 1976 | xs->here = xs->header->xh_entries; |
1998 | 1977 | ||
1999 | |||
2000 | ret = ocfs2_journal_dirty(handle, new_bh); | 1978 | ret = ocfs2_journal_dirty(handle, new_bh); |
2001 | if (ret < 0) { | 1979 | if (ret < 0) { |
2002 | mlog_errno(ret); | 1980 | mlog_errno(ret); |
@@ -2009,8 +1987,6 @@ static int ocfs2_xattr_block_set(struct inode *inode, | |||
2009 | out_commit: | 1987 | out_commit: |
2010 | ocfs2_commit_trans(osb, handle); | 1988 | ocfs2_commit_trans(osb, handle); |
2011 | out: | 1989 | out: |
2012 | if (meta_ac) | ||
2013 | ocfs2_free_alloc_context(meta_ac); | ||
2014 | if (ret < 0) | 1990 | if (ret < 0) |
2015 | return ret; | 1991 | return ret; |
2016 | } else | 1992 | } else |
@@ -2018,22 +1994,266 @@ out: | |||
2018 | 1994 | ||
2019 | if (!(le16_to_cpu(xblk->xb_flags) & OCFS2_XATTR_INDEXED)) { | 1995 | if (!(le16_to_cpu(xblk->xb_flags) & OCFS2_XATTR_INDEXED)) { |
2020 | /* Set extended attribute into external block */ | 1996 | /* Set extended attribute into external block */ |
2021 | ret = ocfs2_xattr_set_entry(inode, xi, xs, OCFS2_HAS_XATTR_FL); | 1997 | ret = ocfs2_xattr_set_entry(inode, xi, xs, ctxt, |
1998 | OCFS2_HAS_XATTR_FL); | ||
2022 | if (!ret || ret != -ENOSPC) | 1999 | if (!ret || ret != -ENOSPC) |
2023 | goto end; | 2000 | goto end; |
2024 | 2001 | ||
2025 | ret = ocfs2_xattr_create_index_block(inode, xs); | 2002 | ret = ocfs2_xattr_create_index_block(inode, xs, ctxt); |
2026 | if (ret) | 2003 | if (ret) |
2027 | goto end; | 2004 | goto end; |
2028 | } | 2005 | } |
2029 | 2006 | ||
2030 | ret = ocfs2_xattr_set_entry_index_block(inode, xi, xs); | 2007 | ret = ocfs2_xattr_set_entry_index_block(inode, xi, xs, ctxt); |
2031 | 2008 | ||
2032 | end: | 2009 | end: |
2033 | 2010 | ||
2034 | return ret; | 2011 | return ret; |
2035 | } | 2012 | } |
2036 | 2013 | ||
2014 | /* Check whether the new xattr can be inserted into the inode. */ | ||
2015 | static int ocfs2_xattr_can_be_in_inode(struct inode *inode, | ||
2016 | struct ocfs2_xattr_info *xi, | ||
2017 | struct ocfs2_xattr_search *xs) | ||
2018 | { | ||
2019 | u64 value_size; | ||
2020 | struct ocfs2_xattr_entry *last; | ||
2021 | int free, i; | ||
2022 | size_t min_offs = xs->end - xs->base; | ||
2023 | |||
2024 | if (!xs->header) | ||
2025 | return 0; | ||
2026 | |||
2027 | last = xs->header->xh_entries; | ||
2028 | |||
2029 | for (i = 0; i < le16_to_cpu(xs->header->xh_count); i++) { | ||
2030 | size_t offs = le16_to_cpu(last->xe_name_offset); | ||
2031 | if (offs < min_offs) | ||
2032 | min_offs = offs; | ||
2033 | last += 1; | ||
2034 | } | ||
2035 | |||
2036 | free = min_offs - ((void *)last - xs->base) - sizeof(__u32); | ||
2037 | if (free < 0) | ||
2038 | return 0; | ||
2039 | |||
2040 | BUG_ON(!xs->not_found); | ||
2041 | |||
2042 | if (xi->value_len > OCFS2_XATTR_INLINE_SIZE) | ||
2043 | value_size = OCFS2_XATTR_ROOT_SIZE; | ||
2044 | else | ||
2045 | value_size = OCFS2_XATTR_SIZE(xi->value_len); | ||
2046 | |||
2047 | if (free >= sizeof(struct ocfs2_xattr_entry) + | ||
2048 | OCFS2_XATTR_SIZE(strlen(xi->name)) + value_size) | ||
2049 | return 1; | ||
2050 | |||
2051 | return 0; | ||
2052 | } | ||
2053 | |||
2054 | static int ocfs2_calc_xattr_set_need(struct inode *inode, | ||
2055 | struct ocfs2_dinode *di, | ||
2056 | struct ocfs2_xattr_info *xi, | ||
2057 | struct ocfs2_xattr_search *xis, | ||
2058 | struct ocfs2_xattr_search *xbs, | ||
2059 | int *clusters_need, | ||
2060 | int *meta_need) | ||
2061 | { | ||
2062 | int ret = 0, old_in_xb = 0; | ||
2063 | int clusters_add = 0, meta_add = 0; | ||
2064 | struct buffer_head *bh = NULL; | ||
2065 | struct ocfs2_xattr_block *xb = NULL; | ||
2066 | struct ocfs2_xattr_entry *xe = NULL; | ||
2067 | struct ocfs2_xattr_value_root *xv = NULL; | ||
2068 | char *base = NULL; | ||
2069 | int name_offset, name_len = 0; | ||
2070 | u32 new_clusters = ocfs2_clusters_for_bytes(inode->i_sb, | ||
2071 | xi->value_len); | ||
2072 | u64 value_size; | ||
2073 | |||
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) { | ||
2082 | if (xi->value_len > OCFS2_XATTR_INLINE_SIZE) | ||
2083 | clusters_add += new_clusters; | ||
2084 | |||
2085 | goto meta_guess; | ||
2086 | } | ||
2087 | |||
2088 | if (!xis->not_found) { | ||
2089 | xe = xis->here; | ||
2090 | name_offset = le16_to_cpu(xe->xe_name_offset); | ||
2091 | name_len = OCFS2_XATTR_SIZE(xe->xe_name_len); | ||
2092 | base = xis->base; | ||
2093 | } else { | ||
2094 | int i, block_off; | ||
2095 | xb = (struct ocfs2_xattr_block *)xbs->xattr_bh->b_data; | ||
2096 | xe = xbs->here; | ||
2097 | name_offset = le16_to_cpu(xe->xe_name_offset); | ||
2098 | name_len = OCFS2_XATTR_SIZE(xe->xe_name_len); | ||
2099 | i = xbs->here - xbs->header->xh_entries; | ||
2100 | old_in_xb = 1; | ||
2101 | |||
2102 | if (le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED) { | ||
2103 | ret = ocfs2_xattr_bucket_get_name_value(inode, | ||
2104 | bucket_xh(xbs->bucket), | ||
2105 | i, &block_off, | ||
2106 | &name_offset); | ||
2107 | base = bucket_block(xbs->bucket, block_off); | ||
2108 | } else | ||
2109 | base = xbs->base; | ||
2110 | } | ||
2111 | |||
2112 | /* do cluster allocation guess first. */ | ||
2113 | value_size = le64_to_cpu(xe->xe_value_size); | ||
2114 | |||
2115 | if (old_in_xb) { | ||
2116 | /* | ||
2117 | * In xattr set, we always try to set the xe in inode first, | ||
2118 | * so if it can be inserted into inode successfully, the old | ||
2119 | * one will be removed from the xattr block, and this xattr | ||
2120 | * will be inserted into inode as a new xattr in inode. | ||
2121 | */ | ||
2122 | if (ocfs2_xattr_can_be_in_inode(inode, xi, xis)) { | ||
2123 | clusters_add += new_clusters; | ||
2124 | goto out; | ||
2125 | } | ||
2126 | } | ||
2127 | |||
2128 | if (xi->value_len > OCFS2_XATTR_INLINE_SIZE) { | ||
2129 | /* the new values will be stored outside. */ | ||
2130 | u32 old_clusters = 0; | ||
2131 | |||
2132 | if (!ocfs2_xattr_is_local(xe)) { | ||
2133 | old_clusters = ocfs2_clusters_for_bytes(inode->i_sb, | ||
2134 | value_size); | ||
2135 | xv = (struct ocfs2_xattr_value_root *) | ||
2136 | (base + name_offset + name_len); | ||
2137 | } else | ||
2138 | xv = &def_xv.xv; | ||
2139 | |||
2140 | if (old_clusters >= new_clusters) | ||
2141 | goto out; | ||
2142 | else { | ||
2143 | meta_add += ocfs2_extend_meta_needed(&xv->xr_list); | ||
2144 | clusters_add += new_clusters - old_clusters; | ||
2145 | goto out; | ||
2146 | } | ||
2147 | } else { | ||
2148 | /* | ||
2149 | * Now the new value will be stored inside. So if the new | ||
2150 | * value is smaller than the size of value root or the old | ||
2151 | * value, we don't need any allocation, otherwise we have | ||
2152 | * to guess metadata allocation. | ||
2153 | */ | ||
2154 | if ((ocfs2_xattr_is_local(xe) && value_size >= xi->value_len) || | ||
2155 | (!ocfs2_xattr_is_local(xe) && | ||
2156 | OCFS2_XATTR_ROOT_SIZE >= xi->value_len)) | ||
2157 | goto out; | ||
2158 | } | ||
2159 | |||
2160 | meta_guess: | ||
2161 | /* calculate metadata allocation. */ | ||
2162 | if (di->i_xattr_loc) { | ||
2163 | if (!xbs->xattr_bh) { | ||
2164 | ret = ocfs2_read_block(inode, | ||
2165 | le64_to_cpu(di->i_xattr_loc), | ||
2166 | &bh); | ||
2167 | if (ret) { | ||
2168 | mlog_errno(ret); | ||
2169 | goto out; | ||
2170 | } | ||
2171 | |||
2172 | xb = (struct ocfs2_xattr_block *)bh->b_data; | ||
2173 | } else | ||
2174 | xb = (struct ocfs2_xattr_block *)xbs->xattr_bh->b_data; | ||
2175 | |||
2176 | if (le16_to_cpu(xb->xb_flags) & OCFS2_XATTR_INDEXED) { | ||
2177 | struct ocfs2_extent_list *el = | ||
2178 | &xb->xb_attrs.xb_root.xt_list; | ||
2179 | meta_add += ocfs2_extend_meta_needed(el); | ||
2180 | } | ||
2181 | |||
2182 | /* | ||
2183 | * This cluster will be used either for new bucket or for | ||
2184 | * new xattr block. | ||
2185 | * If the cluster size is the same as the bucket size, one | ||
2186 | * more is needed since we may need to extend the bucket | ||
2187 | * also. | ||
2188 | */ | ||
2189 | clusters_add += 1; | ||
2190 | if (OCFS2_XATTR_BUCKET_SIZE == | ||
2191 | OCFS2_SB(inode->i_sb)->s_clustersize) | ||
2192 | clusters_add += 1; | ||
2193 | } else | ||
2194 | meta_add += 1; | ||
2195 | out: | ||
2196 | if (clusters_need) | ||
2197 | *clusters_need = clusters_add; | ||
2198 | if (meta_need) | ||
2199 | *meta_need = meta_add; | ||
2200 | brelse(bh); | ||
2201 | return ret; | ||
2202 | } | ||
2203 | |||
2204 | static int ocfs2_init_xattr_set_ctxt(struct inode *inode, | ||
2205 | struct ocfs2_dinode *di, | ||
2206 | struct ocfs2_xattr_info *xi, | ||
2207 | struct ocfs2_xattr_search *xis, | ||
2208 | struct ocfs2_xattr_search *xbs, | ||
2209 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
2210 | { | ||
2211 | int clusters_add, meta_add, ret; | ||
2212 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
2213 | |||
2214 | memset(ctxt, 0, sizeof(struct ocfs2_xattr_set_ctxt)); | ||
2215 | |||
2216 | ocfs2_init_dealloc_ctxt(&ctxt->dealloc); | ||
2217 | |||
2218 | ret = ocfs2_calc_xattr_set_need(inode, di, xi, xis, xbs, | ||
2219 | &clusters_add, &meta_add); | ||
2220 | if (ret) { | ||
2221 | mlog_errno(ret); | ||
2222 | return ret; | ||
2223 | } | ||
2224 | |||
2225 | mlog(0, "Set xattr %s, reserve meta blocks = %d, clusters = %d\n", | ||
2226 | xi->name, meta_add, clusters_add); | ||
2227 | |||
2228 | if (meta_add) { | ||
2229 | ret = ocfs2_reserve_new_metadata_blocks(osb, meta_add, | ||
2230 | &ctxt->meta_ac); | ||
2231 | if (ret) { | ||
2232 | mlog_errno(ret); | ||
2233 | goto out; | ||
2234 | } | ||
2235 | } | ||
2236 | |||
2237 | if (clusters_add) { | ||
2238 | ret = ocfs2_reserve_clusters(osb, clusters_add, &ctxt->data_ac); | ||
2239 | if (ret) | ||
2240 | mlog_errno(ret); | ||
2241 | } | ||
2242 | out: | ||
2243 | if (ret) { | ||
2244 | if (ctxt->meta_ac) { | ||
2245 | ocfs2_free_alloc_context(ctxt->meta_ac); | ||
2246 | ctxt->meta_ac = NULL; | ||
2247 | } | ||
2248 | |||
2249 | /* | ||
2250 | * We cannot have an error and a non null ctxt->data_ac. | ||
2251 | */ | ||
2252 | } | ||
2253 | |||
2254 | return ret; | ||
2255 | } | ||
2256 | |||
2037 | /* | 2257 | /* |
2038 | * ocfs2_xattr_set() | 2258 | * ocfs2_xattr_set() |
2039 | * | 2259 | * |
@@ -2051,6 +2271,8 @@ int ocfs2_xattr_set(struct inode *inode, | |||
2051 | struct buffer_head *di_bh = NULL; | 2271 | struct buffer_head *di_bh = NULL; |
2052 | struct ocfs2_dinode *di; | 2272 | struct ocfs2_dinode *di; |
2053 | int ret; | 2273 | int ret; |
2274 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
2275 | struct ocfs2_xattr_set_ctxt ctxt = { NULL, NULL, }; | ||
2054 | 2276 | ||
2055 | struct ocfs2_xattr_info xi = { | 2277 | struct ocfs2_xattr_info xi = { |
2056 | .name_index = name_index, | 2278 | .name_index = name_index, |
@@ -2115,15 +2337,21 @@ int ocfs2_xattr_set(struct inode *inode, | |||
2115 | goto cleanup; | 2337 | goto cleanup; |
2116 | } | 2338 | } |
2117 | 2339 | ||
2340 | ret = ocfs2_init_xattr_set_ctxt(inode, di, &xi, &xis, &xbs, &ctxt); | ||
2341 | if (ret) { | ||
2342 | mlog_errno(ret); | ||
2343 | goto cleanup; | ||
2344 | } | ||
2345 | |||
2118 | if (!value) { | 2346 | if (!value) { |
2119 | /* Remove existing extended attribute */ | 2347 | /* Remove existing extended attribute */ |
2120 | if (!xis.not_found) | 2348 | if (!xis.not_found) |
2121 | ret = ocfs2_xattr_ibody_set(inode, &xi, &xis); | 2349 | ret = ocfs2_xattr_ibody_set(inode, &xi, &xis, &ctxt); |
2122 | else if (!xbs.not_found) | 2350 | else if (!xbs.not_found) |
2123 | ret = ocfs2_xattr_block_set(inode, &xi, &xbs); | 2351 | ret = ocfs2_xattr_block_set(inode, &xi, &xbs, &ctxt); |
2124 | } else { | 2352 | } else { |
2125 | /* We always try to set extended attribute into inode first*/ | 2353 | /* We always try to set extended attribute into inode first*/ |
2126 | ret = ocfs2_xattr_ibody_set(inode, &xi, &xis); | 2354 | ret = ocfs2_xattr_ibody_set(inode, &xi, &xis, &ctxt); |
2127 | if (!ret && !xbs.not_found) { | 2355 | if (!ret && !xbs.not_found) { |
2128 | /* | 2356 | /* |
2129 | * If succeed and that extended attribute existing in | 2357 | * If succeed and that extended attribute existing in |
@@ -2131,7 +2359,7 @@ int ocfs2_xattr_set(struct inode *inode, | |||
2131 | */ | 2359 | */ |
2132 | xi.value = NULL; | 2360 | xi.value = NULL; |
2133 | xi.value_len = 0; | 2361 | xi.value_len = 0; |
2134 | ret = ocfs2_xattr_block_set(inode, &xi, &xbs); | 2362 | ret = ocfs2_xattr_block_set(inode, &xi, &xbs, &ctxt); |
2135 | } else if (ret == -ENOSPC) { | 2363 | } else if (ret == -ENOSPC) { |
2136 | if (di->i_xattr_loc && !xbs.xattr_bh) { | 2364 | if (di->i_xattr_loc && !xbs.xattr_bh) { |
2137 | ret = ocfs2_xattr_block_find(inode, name_index, | 2365 | ret = ocfs2_xattr_block_find(inode, name_index, |
@@ -2143,9 +2371,9 @@ int ocfs2_xattr_set(struct inode *inode, | |||
2143 | * If no space in inode, we will set extended attribute | 2371 | * If no space in inode, we will set extended attribute |
2144 | * into external block. | 2372 | * into external block. |
2145 | */ | 2373 | */ |
2146 | ret = ocfs2_xattr_block_set(inode, &xi, &xbs); | 2374 | ret = ocfs2_xattr_block_set(inode, &xi, &xbs, &ctxt); |
2147 | if (ret) | 2375 | if (ret) |
2148 | goto cleanup; | 2376 | goto free; |
2149 | if (!xis.not_found) { | 2377 | if (!xis.not_found) { |
2150 | /* | 2378 | /* |
2151 | * If succeed and that extended attribute | 2379 | * If succeed and that extended attribute |
@@ -2153,10 +2381,19 @@ int ocfs2_xattr_set(struct inode *inode, | |||
2153 | */ | 2381 | */ |
2154 | xi.value = NULL; | 2382 | xi.value = NULL; |
2155 | xi.value_len = 0; | 2383 | xi.value_len = 0; |
2156 | ret = ocfs2_xattr_ibody_set(inode, &xi, &xis); | 2384 | ret = ocfs2_xattr_ibody_set(inode, &xi, |
2385 | &xis, &ctxt); | ||
2157 | } | 2386 | } |
2158 | } | 2387 | } |
2159 | } | 2388 | } |
2389 | free: | ||
2390 | if (ctxt.data_ac) | ||
2391 | ocfs2_free_alloc_context(ctxt.data_ac); | ||
2392 | if (ctxt.meta_ac) | ||
2393 | ocfs2_free_alloc_context(ctxt.meta_ac); | ||
2394 | if (ocfs2_dealloc_has_cluster(&ctxt.dealloc)) | ||
2395 | ocfs2_schedule_truncate_log_flush(osb, 1); | ||
2396 | ocfs2_run_deallocs(osb, &ctxt.dealloc); | ||
2160 | cleanup: | 2397 | cleanup: |
2161 | up_write(&OCFS2_I(inode)->ip_xattr_sem); | 2398 | up_write(&OCFS2_I(inode)->ip_xattr_sem); |
2162 | ocfs2_inode_unlock(inode, 1); | 2399 | ocfs2_inode_unlock(inode, 1); |
@@ -2734,7 +2971,8 @@ static void ocfs2_xattr_update_xattr_search(struct inode *inode, | |||
2734 | } | 2971 | } |
2735 | 2972 | ||
2736 | static int ocfs2_xattr_create_index_block(struct inode *inode, | 2973 | static int ocfs2_xattr_create_index_block(struct inode *inode, |
2737 | struct ocfs2_xattr_search *xs) | 2974 | struct ocfs2_xattr_search *xs, |
2975 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
2738 | { | 2976 | { |
2739 | int ret, credits = OCFS2_SUBALLOC_ALLOC; | 2977 | int ret, credits = OCFS2_SUBALLOC_ALLOC; |
2740 | u32 bit_off, len; | 2978 | u32 bit_off, len; |
@@ -2742,7 +2980,6 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, | |||
2742 | handle_t *handle; | 2980 | handle_t *handle; |
2743 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 2981 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
2744 | struct ocfs2_inode_info *oi = OCFS2_I(inode); | 2982 | struct ocfs2_inode_info *oi = OCFS2_I(inode); |
2745 | struct ocfs2_alloc_context *data_ac; | ||
2746 | struct buffer_head *xb_bh = xs->xattr_bh; | 2983 | struct buffer_head *xb_bh = xs->xattr_bh; |
2747 | struct ocfs2_xattr_block *xb = | 2984 | struct ocfs2_xattr_block *xb = |
2748 | (struct ocfs2_xattr_block *)xb_bh->b_data; | 2985 | (struct ocfs2_xattr_block *)xb_bh->b_data; |
@@ -2755,12 +2992,6 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, | |||
2755 | BUG_ON(xb_flags & OCFS2_XATTR_INDEXED); | 2992 | BUG_ON(xb_flags & OCFS2_XATTR_INDEXED); |
2756 | BUG_ON(!xs->bucket); | 2993 | BUG_ON(!xs->bucket); |
2757 | 2994 | ||
2758 | ret = ocfs2_reserve_clusters(osb, 1, &data_ac); | ||
2759 | if (ret) { | ||
2760 | mlog_errno(ret); | ||
2761 | goto out; | ||
2762 | } | ||
2763 | |||
2764 | /* | 2995 | /* |
2765 | * XXX: | 2996 | * XXX: |
2766 | * We can use this lock for now, and maybe move to a dedicated mutex | 2997 | * We can use this lock for now, and maybe move to a dedicated mutex |
@@ -2787,7 +3018,8 @@ static int ocfs2_xattr_create_index_block(struct inode *inode, | |||
2787 | goto out_commit; | 3018 | goto out_commit; |
2788 | } | 3019 | } |
2789 | 3020 | ||
2790 | ret = ocfs2_claim_clusters(osb, handle, data_ac, 1, &bit_off, &len); | 3021 | ret = __ocfs2_claim_clusters(osb, handle, ctxt->data_ac, |
3022 | 1, 1, &bit_off, &len); | ||
2791 | if (ret) { | 3023 | if (ret) { |
2792 | mlog_errno(ret); | 3024 | mlog_errno(ret); |
2793 | goto out_commit; | 3025 | goto out_commit; |
@@ -2850,10 +3082,6 @@ out_commit: | |||
2850 | out_sem: | 3082 | out_sem: |
2851 | up_write(&oi->ip_alloc_sem); | 3083 | up_write(&oi->ip_alloc_sem); |
2852 | 3084 | ||
2853 | out: | ||
2854 | if (data_ac) | ||
2855 | ocfs2_free_alloc_context(data_ac); | ||
2856 | |||
2857 | return ret; | 3085 | return ret; |
2858 | } | 3086 | } |
2859 | 3087 | ||
@@ -3614,7 +3842,8 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, | |||
3614 | u32 *num_clusters, | 3842 | u32 *num_clusters, |
3615 | u32 prev_cpos, | 3843 | u32 prev_cpos, |
3616 | u64 prev_blkno, | 3844 | u64 prev_blkno, |
3617 | int *extend) | 3845 | int *extend, |
3846 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
3618 | { | 3847 | { |
3619 | int ret, credits; | 3848 | int ret, credits; |
3620 | u16 bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1); | 3849 | u16 bpc = ocfs2_clusters_to_blocks(inode->i_sb, 1); |
@@ -3622,8 +3851,6 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, | |||
3622 | u32 clusters_to_add = 1, bit_off, num_bits, v_start = 0; | 3851 | u32 clusters_to_add = 1, bit_off, num_bits, v_start = 0; |
3623 | u64 block; | 3852 | u64 block; |
3624 | handle_t *handle = NULL; | 3853 | handle_t *handle = NULL; |
3625 | struct ocfs2_alloc_context *data_ac = NULL; | ||
3626 | struct ocfs2_alloc_context *meta_ac = NULL; | ||
3627 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 3854 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
3628 | struct ocfs2_extent_tree et; | 3855 | struct ocfs2_extent_tree et; |
3629 | 3856 | ||
@@ -3634,13 +3861,6 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, | |||
3634 | 3861 | ||
3635 | ocfs2_init_xattr_tree_extent_tree(&et, inode, root_bh); | 3862 | ocfs2_init_xattr_tree_extent_tree(&et, inode, root_bh); |
3636 | 3863 | ||
3637 | ret = ocfs2_lock_allocators(inode, &et, clusters_to_add, 0, | ||
3638 | &data_ac, &meta_ac); | ||
3639 | if (ret) { | ||
3640 | mlog_errno(ret); | ||
3641 | goto leave; | ||
3642 | } | ||
3643 | |||
3644 | credits = ocfs2_calc_extend_credits(osb->sb, et.et_root_el, | 3864 | credits = ocfs2_calc_extend_credits(osb->sb, et.et_root_el, |
3645 | clusters_to_add); | 3865 | clusters_to_add); |
3646 | handle = ocfs2_start_trans(osb, credits); | 3866 | handle = ocfs2_start_trans(osb, credits); |
@@ -3658,7 +3878,7 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, | |||
3658 | goto leave; | 3878 | goto leave; |
3659 | } | 3879 | } |
3660 | 3880 | ||
3661 | ret = __ocfs2_claim_clusters(osb, handle, data_ac, 1, | 3881 | ret = __ocfs2_claim_clusters(osb, handle, ctxt->data_ac, 1, |
3662 | clusters_to_add, &bit_off, &num_bits); | 3882 | clusters_to_add, &bit_off, &num_bits); |
3663 | if (ret < 0) { | 3883 | if (ret < 0) { |
3664 | if (ret != -ENOSPC) | 3884 | if (ret != -ENOSPC) |
@@ -3719,7 +3939,7 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, | |||
3719 | mlog(0, "Insert %u clusters at block %llu for xattr at %u\n", | 3939 | mlog(0, "Insert %u clusters at block %llu for xattr at %u\n", |
3720 | num_bits, (unsigned long long)block, v_start); | 3940 | num_bits, (unsigned long long)block, v_start); |
3721 | ret = ocfs2_insert_extent(osb, handle, inode, &et, v_start, block, | 3941 | ret = ocfs2_insert_extent(osb, handle, inode, &et, v_start, block, |
3722 | num_bits, 0, meta_ac); | 3942 | num_bits, 0, ctxt->meta_ac); |
3723 | if (ret < 0) { | 3943 | if (ret < 0) { |
3724 | mlog_errno(ret); | 3944 | mlog_errno(ret); |
3725 | goto leave; | 3945 | goto leave; |
@@ -3734,10 +3954,6 @@ static int ocfs2_add_new_xattr_cluster(struct inode *inode, | |||
3734 | leave: | 3954 | leave: |
3735 | if (handle) | 3955 | if (handle) |
3736 | ocfs2_commit_trans(osb, handle); | 3956 | ocfs2_commit_trans(osb, handle); |
3737 | if (data_ac) | ||
3738 | ocfs2_free_alloc_context(data_ac); | ||
3739 | if (meta_ac) | ||
3740 | ocfs2_free_alloc_context(meta_ac); | ||
3741 | 3957 | ||
3742 | return ret; | 3958 | return ret; |
3743 | } | 3959 | } |
@@ -3821,7 +4037,8 @@ out: | |||
3821 | */ | 4037 | */ |
3822 | static int ocfs2_add_new_xattr_bucket(struct inode *inode, | 4038 | static int ocfs2_add_new_xattr_bucket(struct inode *inode, |
3823 | struct buffer_head *xb_bh, | 4039 | struct buffer_head *xb_bh, |
3824 | struct buffer_head *header_bh) | 4040 | struct buffer_head *header_bh, |
4041 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
3825 | { | 4042 | { |
3826 | struct ocfs2_xattr_header *first_xh = NULL; | 4043 | struct ocfs2_xattr_header *first_xh = NULL; |
3827 | struct buffer_head *first_bh = NULL; | 4044 | struct buffer_head *first_bh = NULL; |
@@ -3872,7 +4089,8 @@ static int ocfs2_add_new_xattr_bucket(struct inode *inode, | |||
3872 | &num_clusters, | 4089 | &num_clusters, |
3873 | e_cpos, | 4090 | e_cpos, |
3874 | p_blkno, | 4091 | p_blkno, |
3875 | &extend); | 4092 | &extend, |
4093 | ctxt); | ||
3876 | if (ret) { | 4094 | if (ret) { |
3877 | mlog_errno(ret); | 4095 | mlog_errno(ret); |
3878 | goto out; | 4096 | goto out; |
@@ -4147,7 +4365,8 @@ out: | |||
4147 | static int ocfs2_xattr_bucket_value_truncate(struct inode *inode, | 4365 | static int ocfs2_xattr_bucket_value_truncate(struct inode *inode, |
4148 | struct buffer_head *header_bh, | 4366 | struct buffer_head *header_bh, |
4149 | int xe_off, | 4367 | int xe_off, |
4150 | int len) | 4368 | int len, |
4369 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
4151 | { | 4370 | { |
4152 | int ret, offset; | 4371 | int ret, offset; |
4153 | u64 value_blk; | 4372 | u64 value_blk; |
@@ -4182,7 +4401,7 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode, | |||
4182 | 4401 | ||
4183 | mlog(0, "truncate %u in xattr bucket %llu to %d bytes.\n", | 4402 | mlog(0, "truncate %u in xattr bucket %llu to %d bytes.\n", |
4184 | xe_off, (unsigned long long)header_bh->b_blocknr, len); | 4403 | xe_off, (unsigned long long)header_bh->b_blocknr, len); |
4185 | ret = ocfs2_xattr_value_truncate(inode, value_bh, xv, len); | 4404 | ret = ocfs2_xattr_value_truncate(inode, value_bh, xv, len, ctxt); |
4186 | if (ret) { | 4405 | if (ret) { |
4187 | mlog_errno(ret); | 4406 | mlog_errno(ret); |
4188 | goto out; | 4407 | goto out; |
@@ -4200,8 +4419,9 @@ out: | |||
4200 | } | 4419 | } |
4201 | 4420 | ||
4202 | static int ocfs2_xattr_bucket_value_truncate_xs(struct inode *inode, | 4421 | static int ocfs2_xattr_bucket_value_truncate_xs(struct inode *inode, |
4203 | struct ocfs2_xattr_search *xs, | 4422 | struct ocfs2_xattr_search *xs, |
4204 | int len) | 4423 | int len, |
4424 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
4205 | { | 4425 | { |
4206 | int ret, offset; | 4426 | int ret, offset; |
4207 | struct ocfs2_xattr_entry *xe = xs->here; | 4427 | struct ocfs2_xattr_entry *xe = xs->here; |
@@ -4211,7 +4431,7 @@ static int ocfs2_xattr_bucket_value_truncate_xs(struct inode *inode, | |||
4211 | 4431 | ||
4212 | offset = xe - xh->xh_entries; | 4432 | offset = xe - xh->xh_entries; |
4213 | ret = ocfs2_xattr_bucket_value_truncate(inode, xs->bucket->bu_bhs[0], | 4433 | ret = ocfs2_xattr_bucket_value_truncate(inode, xs->bucket->bu_bhs[0], |
4214 | offset, len); | 4434 | offset, len, ctxt); |
4215 | if (ret) | 4435 | if (ret) |
4216 | mlog_errno(ret); | 4436 | mlog_errno(ret); |
4217 | 4437 | ||
@@ -4375,7 +4595,8 @@ out_commit: | |||
4375 | */ | 4595 | */ |
4376 | static int ocfs2_xattr_set_in_bucket(struct inode *inode, | 4596 | static int ocfs2_xattr_set_in_bucket(struct inode *inode, |
4377 | struct ocfs2_xattr_info *xi, | 4597 | struct ocfs2_xattr_info *xi, |
4378 | struct ocfs2_xattr_search *xs) | 4598 | struct ocfs2_xattr_search *xs, |
4599 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
4379 | { | 4600 | { |
4380 | int ret, local = 1; | 4601 | int ret, local = 1; |
4381 | size_t value_len; | 4602 | size_t value_len; |
@@ -4403,7 +4624,8 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode, | |||
4403 | value_len = 0; | 4624 | value_len = 0; |
4404 | 4625 | ||
4405 | ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs, | 4626 | ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs, |
4406 | value_len); | 4627 | value_len, |
4628 | ctxt); | ||
4407 | if (ret) | 4629 | if (ret) |
4408 | goto out; | 4630 | goto out; |
4409 | 4631 | ||
@@ -4434,7 +4656,7 @@ static int ocfs2_xattr_set_in_bucket(struct inode *inode, | |||
4434 | 4656 | ||
4435 | /* allocate the space now for the outside block storage. */ | 4657 | /* allocate the space now for the outside block storage. */ |
4436 | ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs, | 4658 | ret = ocfs2_xattr_bucket_value_truncate_xs(inode, xs, |
4437 | value_len); | 4659 | value_len, ctxt); |
4438 | if (ret) { | 4660 | if (ret) { |
4439 | mlog_errno(ret); | 4661 | mlog_errno(ret); |
4440 | 4662 | ||
@@ -4485,7 +4707,8 @@ static int ocfs2_check_xattr_bucket_collision(struct inode *inode, | |||
4485 | 4707 | ||
4486 | static int ocfs2_xattr_set_entry_index_block(struct inode *inode, | 4708 | static int ocfs2_xattr_set_entry_index_block(struct inode *inode, |
4487 | struct ocfs2_xattr_info *xi, | 4709 | struct ocfs2_xattr_info *xi, |
4488 | struct ocfs2_xattr_search *xs) | 4710 | struct ocfs2_xattr_search *xs, |
4711 | struct ocfs2_xattr_set_ctxt *ctxt) | ||
4489 | { | 4712 | { |
4490 | struct ocfs2_xattr_header *xh; | 4713 | struct ocfs2_xattr_header *xh; |
4491 | struct ocfs2_xattr_entry *xe; | 4714 | struct ocfs2_xattr_entry *xe; |
@@ -4603,7 +4826,8 @@ try_again: | |||
4603 | 4826 | ||
4604 | ret = ocfs2_add_new_xattr_bucket(inode, | 4827 | ret = ocfs2_add_new_xattr_bucket(inode, |
4605 | xs->xattr_bh, | 4828 | xs->xattr_bh, |
4606 | xs->bucket->bu_bhs[0]); | 4829 | xs->bucket->bu_bhs[0], |
4830 | ctxt); | ||
4607 | if (ret) { | 4831 | if (ret) { |
4608 | mlog_errno(ret); | 4832 | mlog_errno(ret); |
4609 | goto out; | 4833 | goto out; |
@@ -4622,7 +4846,7 @@ try_again: | |||
4622 | } | 4846 | } |
4623 | 4847 | ||
4624 | xattr_set: | 4848 | xattr_set: |
4625 | ret = ocfs2_xattr_set_in_bucket(inode, xi, xs); | 4849 | ret = ocfs2_xattr_set_in_bucket(inode, xi, xs, ctxt); |
4626 | out: | 4850 | out: |
4627 | mlog_exit(ret); | 4851 | mlog_exit(ret); |
4628 | return ret; | 4852 | return ret; |
@@ -4636,6 +4860,10 @@ static int ocfs2_delete_xattr_in_bucket(struct inode *inode, | |||
4636 | struct ocfs2_xattr_header *xh = bucket_xh(bucket); | 4860 | struct ocfs2_xattr_header *xh = bucket_xh(bucket); |
4637 | u16 i; | 4861 | u16 i; |
4638 | struct ocfs2_xattr_entry *xe; | 4862 | struct ocfs2_xattr_entry *xe; |
4863 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | ||
4864 | struct ocfs2_xattr_set_ctxt ctxt = {NULL, NULL,}; | ||
4865 | |||
4866 | ocfs2_init_dealloc_ctxt(&ctxt.dealloc); | ||
4639 | 4867 | ||
4640 | for (i = 0; i < le16_to_cpu(xh->xh_count); i++) { | 4868 | for (i = 0; i < le16_to_cpu(xh->xh_count); i++) { |
4641 | xe = &xh->xh_entries[i]; | 4869 | xe = &xh->xh_entries[i]; |
@@ -4644,13 +4872,16 @@ static int ocfs2_delete_xattr_in_bucket(struct inode *inode, | |||
4644 | 4872 | ||
4645 | ret = ocfs2_xattr_bucket_value_truncate(inode, | 4873 | ret = ocfs2_xattr_bucket_value_truncate(inode, |
4646 | bucket->bu_bhs[0], | 4874 | bucket->bu_bhs[0], |
4647 | i, 0); | 4875 | i, 0, &ctxt); |
4648 | if (ret) { | 4876 | if (ret) { |
4649 | mlog_errno(ret); | 4877 | mlog_errno(ret); |
4650 | break; | 4878 | break; |
4651 | } | 4879 | } |
4652 | } | 4880 | } |
4653 | 4881 | ||
4882 | ocfs2_schedule_truncate_log_flush(osb, 1); | ||
4883 | ocfs2_run_deallocs(osb, &ctxt.dealloc); | ||
4884 | |||
4654 | return ret; | 4885 | return ret; |
4655 | } | 4886 | } |
4656 | 4887 | ||