diff options
| -rw-r--r-- | fs/configfs/dir.c | 59 | ||||
| -rw-r--r-- | fs/ocfs2/alloc.c | 3 | ||||
| -rw-r--r-- | fs/ocfs2/dcache.c | 42 | ||||
| -rw-r--r-- | fs/ocfs2/dcache.h | 9 | ||||
| -rw-r--r-- | fs/ocfs2/dlmglue.c | 4 | ||||
| -rw-r--r-- | fs/ocfs2/ocfs2.h | 6 | ||||
| -rw-r--r-- | fs/ocfs2/quota_global.c | 4 | ||||
| -rw-r--r-- | fs/ocfs2/super.c | 3 | ||||
| -rw-r--r-- | fs/ocfs2/xattr.c | 17 |
9 files changed, 133 insertions, 14 deletions
diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 8e93341f3e8..9c235839114 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c | |||
| @@ -553,12 +553,24 @@ static void detach_groups(struct config_group *group) | |||
| 553 | 553 | ||
| 554 | child = sd->s_dentry; | 554 | child = sd->s_dentry; |
| 555 | 555 | ||
| 556 | /* | ||
| 557 | * Note: we hide this from lockdep since we have no way | ||
| 558 | * to teach lockdep about recursive | ||
| 559 | * I_MUTEX_PARENT -> I_MUTEX_CHILD patterns along a path | ||
| 560 | * in an inode tree, which are valid as soon as | ||
| 561 | * I_MUTEX_PARENT -> I_MUTEX_CHILD is valid from a | ||
| 562 | * parent inode to one of its children. | ||
| 563 | */ | ||
| 564 | lockdep_off(); | ||
| 556 | mutex_lock(&child->d_inode->i_mutex); | 565 | mutex_lock(&child->d_inode->i_mutex); |
| 566 | lockdep_on(); | ||
| 557 | 567 | ||
| 558 | configfs_detach_group(sd->s_element); | 568 | configfs_detach_group(sd->s_element); |
| 559 | child->d_inode->i_flags |= S_DEAD; | 569 | child->d_inode->i_flags |= S_DEAD; |
| 560 | 570 | ||
| 571 | lockdep_off(); | ||
| 561 | mutex_unlock(&child->d_inode->i_mutex); | 572 | mutex_unlock(&child->d_inode->i_mutex); |
| 573 | lockdep_on(); | ||
| 562 | 574 | ||
| 563 | d_delete(child); | 575 | d_delete(child); |
| 564 | dput(child); | 576 | dput(child); |
| @@ -748,11 +760,22 @@ static int configfs_attach_item(struct config_item *parent_item, | |||
| 748 | * We are going to remove an inode and its dentry but | 760 | * We are going to remove an inode and its dentry but |
| 749 | * the VFS may already have hit and used them. Thus, | 761 | * the VFS may already have hit and used them. Thus, |
| 750 | * we must lock them as rmdir() would. | 762 | * we must lock them as rmdir() would. |
| 763 | * | ||
| 764 | * Note: we hide this from lockdep since we have no way | ||
| 765 | * to teach lockdep about recursive | ||
| 766 | * I_MUTEX_PARENT -> I_MUTEX_CHILD patterns along a path | ||
| 767 | * in an inode tree, which are valid as soon as | ||
| 768 | * I_MUTEX_PARENT -> I_MUTEX_CHILD is valid from a | ||
| 769 | * parent inode to one of its children. | ||
| 751 | */ | 770 | */ |
| 771 | lockdep_off(); | ||
| 752 | mutex_lock(&dentry->d_inode->i_mutex); | 772 | mutex_lock(&dentry->d_inode->i_mutex); |
| 773 | lockdep_on(); | ||
| 753 | configfs_remove_dir(item); | 774 | configfs_remove_dir(item); |
| 754 | dentry->d_inode->i_flags |= S_DEAD; | 775 | dentry->d_inode->i_flags |= S_DEAD; |
| 776 | lockdep_off(); | ||
| 755 | mutex_unlock(&dentry->d_inode->i_mutex); | 777 | mutex_unlock(&dentry->d_inode->i_mutex); |
| 778 | lockdep_on(); | ||
| 756 | d_delete(dentry); | 779 | d_delete(dentry); |
| 757 | } | 780 | } |
| 758 | } | 781 | } |
| @@ -787,14 +810,25 @@ static int configfs_attach_group(struct config_item *parent_item, | |||
| 787 | * | 810 | * |
| 788 | * We must also lock the inode to remove it safely in case of | 811 | * We must also lock the inode to remove it safely in case of |
| 789 | * error, as rmdir() would. | 812 | * error, as rmdir() would. |
| 813 | * | ||
| 814 | * Note: we hide this from lockdep since we have no way | ||
| 815 | * to teach lockdep about recursive | ||
| 816 | * I_MUTEX_PARENT -> I_MUTEX_CHILD patterns along a path | ||
| 817 | * in an inode tree, which are valid as soon as | ||
| 818 | * I_MUTEX_PARENT -> I_MUTEX_CHILD is valid from a | ||
| 819 | * parent inode to one of its children. | ||
| 790 | */ | 820 | */ |
| 821 | lockdep_off(); | ||
| 791 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD); | 822 | mutex_lock_nested(&dentry->d_inode->i_mutex, I_MUTEX_CHILD); |
| 823 | lockdep_on(); | ||
| 792 | ret = populate_groups(to_config_group(item)); | 824 | ret = populate_groups(to_config_group(item)); |
| 793 | if (ret) { | 825 | if (ret) { |
| 794 | configfs_detach_item(item); | 826 | configfs_detach_item(item); |
| 795 | dentry->d_inode->i_flags |= S_DEAD; | 827 | dentry->d_inode->i_flags |= S_DEAD; |
| 796 | } | 828 | } |
| 829 | lockdep_off(); | ||
| 797 | mutex_unlock(&dentry->d_inode->i_mutex); | 830 | mutex_unlock(&dentry->d_inode->i_mutex); |
| 831 | lockdep_on(); | ||
| 798 | if (ret) | 832 | if (ret) |
| 799 | d_delete(dentry); | 833 | d_delete(dentry); |
| 800 | } | 834 | } |
| @@ -956,7 +990,17 @@ static int configfs_depend_prep(struct dentry *origin, | |||
| 956 | BUG_ON(!origin || !sd); | 990 | BUG_ON(!origin || !sd); |
| 957 | 991 | ||
| 958 | /* Lock this guy on the way down */ | 992 | /* Lock this guy on the way down */ |
| 993 | /* | ||
| 994 | * Note: we hide this from lockdep since we have no way | ||
| 995 | * to teach lockdep about recursive | ||
| 996 | * I_MUTEX_PARENT -> I_MUTEX_CHILD patterns along a path | ||
| 997 | * in an inode tree, which are valid as soon as | ||
| 998 | * I_MUTEX_PARENT -> I_MUTEX_CHILD is valid from a | ||
| 999 | * parent inode to one of its children. | ||
| 1000 | */ | ||
| 1001 | lockdep_off(); | ||
| 959 | mutex_lock(&sd->s_dentry->d_inode->i_mutex); | 1002 | mutex_lock(&sd->s_dentry->d_inode->i_mutex); |
| 1003 | lockdep_on(); | ||
| 960 | if (sd->s_element == target) /* Boo-yah */ | 1004 | if (sd->s_element == target) /* Boo-yah */ |
| 961 | goto out; | 1005 | goto out; |
| 962 | 1006 | ||
| @@ -970,7 +1014,9 @@ static int configfs_depend_prep(struct dentry *origin, | |||
| 970 | } | 1014 | } |
| 971 | 1015 | ||
| 972 | /* We looped all our children and didn't find target */ | 1016 | /* We looped all our children and didn't find target */ |
| 1017 | lockdep_off(); | ||
| 973 | mutex_unlock(&sd->s_dentry->d_inode->i_mutex); | 1018 | mutex_unlock(&sd->s_dentry->d_inode->i_mutex); |
| 1019 | lockdep_on(); | ||
| 974 | ret = -ENOENT; | 1020 | ret = -ENOENT; |
| 975 | 1021 | ||
| 976 | out: | 1022 | out: |
| @@ -990,11 +1036,16 @@ static void configfs_depend_rollback(struct dentry *origin, | |||
| 990 | struct dentry *dentry = item->ci_dentry; | 1036 | struct dentry *dentry = item->ci_dentry; |
| 991 | 1037 | ||
| 992 | while (dentry != origin) { | 1038 | while (dentry != origin) { |
| 1039 | /* See comments in configfs_depend_prep() */ | ||
| 1040 | lockdep_off(); | ||
| 993 | mutex_unlock(&dentry->d_inode->i_mutex); | 1041 | mutex_unlock(&dentry->d_inode->i_mutex); |
| 1042 | lockdep_on(); | ||
| 994 | dentry = dentry->d_parent; | 1043 | dentry = dentry->d_parent; |
| 995 | } | 1044 | } |
| 996 | 1045 | ||
| 1046 | lockdep_off(); | ||
| 997 | mutex_unlock(&origin->d_inode->i_mutex); | 1047 | mutex_unlock(&origin->d_inode->i_mutex); |
| 1048 | lockdep_on(); | ||
| 998 | } | 1049 | } |
| 999 | 1050 | ||
| 1000 | int configfs_depend_item(struct configfs_subsystem *subsys, | 1051 | int configfs_depend_item(struct configfs_subsystem *subsys, |
| @@ -1329,8 +1380,16 @@ static int configfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 1329 | } | 1380 | } |
| 1330 | 1381 | ||
| 1331 | /* Wait until the racing operation terminates */ | 1382 | /* Wait until the racing operation terminates */ |
| 1383 | /* | ||
| 1384 | * Note: we hide this from lockdep since we are locked | ||
| 1385 | * with subclass I_MUTEX_NORMAL from vfs_rmdir() (why | ||
| 1386 | * not I_MUTEX_CHILD?), and I_MUTEX_XATTR or | ||
| 1387 | * I_MUTEX_QUOTA are not relevant for the locked inode. | ||
| 1388 | */ | ||
| 1389 | lockdep_off(); | ||
| 1332 | mutex_lock(wait_mutex); | 1390 | mutex_lock(wait_mutex); |
| 1333 | mutex_unlock(wait_mutex); | 1391 | mutex_unlock(wait_mutex); |
| 1392 | lockdep_on(); | ||
| 1334 | } | 1393 | } |
| 1335 | } while (ret == -EAGAIN); | 1394 | } while (ret == -EAGAIN); |
| 1336 | 1395 | ||
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index d861096c9d8..60fe74035db 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
| @@ -5390,6 +5390,9 @@ int ocfs2_remove_btree_range(struct inode *inode, | |||
| 5390 | goto out; | 5390 | goto out; |
| 5391 | } | 5391 | } |
| 5392 | 5392 | ||
| 5393 | vfs_dq_free_space_nodirty(inode, | ||
| 5394 | ocfs2_clusters_to_bytes(inode->i_sb, len)); | ||
| 5395 | |||
| 5393 | ret = ocfs2_remove_extent(inode, et, cpos, len, handle, meta_ac, | 5396 | ret = ocfs2_remove_extent(inode, et, cpos, len, handle, meta_ac, |
| 5394 | dealloc); | 5397 | dealloc); |
| 5395 | if (ret) { | 5398 | if (ret) { |
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index b1cc7c381e8..e9d7c2038c0 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include "dlmglue.h" | 38 | #include "dlmglue.h" |
| 39 | #include "file.h" | 39 | #include "file.h" |
| 40 | #include "inode.h" | 40 | #include "inode.h" |
| 41 | #include "super.h" | ||
| 41 | 42 | ||
| 42 | 43 | ||
| 43 | static int ocfs2_dentry_revalidate(struct dentry *dentry, | 44 | static int ocfs2_dentry_revalidate(struct dentry *dentry, |
| @@ -294,6 +295,34 @@ out_attach: | |||
| 294 | return ret; | 295 | return ret; |
| 295 | } | 296 | } |
| 296 | 297 | ||
| 298 | static DEFINE_SPINLOCK(dentry_list_lock); | ||
| 299 | |||
| 300 | /* We limit the number of dentry locks to drop in one go. We have | ||
| 301 | * this limit so that we don't starve other users of ocfs2_wq. */ | ||
| 302 | #define DL_INODE_DROP_COUNT 64 | ||
| 303 | |||
| 304 | /* Drop inode references from dentry locks */ | ||
| 305 | void ocfs2_drop_dl_inodes(struct work_struct *work) | ||
| 306 | { | ||
| 307 | struct ocfs2_super *osb = container_of(work, struct ocfs2_super, | ||
| 308 | dentry_lock_work); | ||
| 309 | struct ocfs2_dentry_lock *dl; | ||
| 310 | int drop_count = DL_INODE_DROP_COUNT; | ||
| 311 | |||
| 312 | spin_lock(&dentry_list_lock); | ||
| 313 | while (osb->dentry_lock_list && drop_count--) { | ||
| 314 | dl = osb->dentry_lock_list; | ||
| 315 | osb->dentry_lock_list = dl->dl_next; | ||
| 316 | spin_unlock(&dentry_list_lock); | ||
| 317 | iput(dl->dl_inode); | ||
| 318 | kfree(dl); | ||
| 319 | spin_lock(&dentry_list_lock); | ||
| 320 | } | ||
| 321 | if (osb->dentry_lock_list) | ||
| 322 | queue_work(ocfs2_wq, &osb->dentry_lock_work); | ||
| 323 | spin_unlock(&dentry_list_lock); | ||
| 324 | } | ||
| 325 | |||
| 297 | /* | 326 | /* |
| 298 | * ocfs2_dentry_iput() and friends. | 327 | * ocfs2_dentry_iput() and friends. |
| 299 | * | 328 | * |
| @@ -318,16 +347,23 @@ out_attach: | |||
| 318 | static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb, | 347 | static void ocfs2_drop_dentry_lock(struct ocfs2_super *osb, |
| 319 | struct ocfs2_dentry_lock *dl) | 348 | struct ocfs2_dentry_lock *dl) |
| 320 | { | 349 | { |
| 321 | iput(dl->dl_inode); | ||
| 322 | ocfs2_simple_drop_lockres(osb, &dl->dl_lockres); | 350 | ocfs2_simple_drop_lockres(osb, &dl->dl_lockres); |
| 323 | ocfs2_lock_res_free(&dl->dl_lockres); | 351 | ocfs2_lock_res_free(&dl->dl_lockres); |
| 324 | kfree(dl); | 352 | |
| 353 | /* We leave dropping of inode reference to ocfs2_wq as that can | ||
| 354 | * possibly lead to inode deletion which gets tricky */ | ||
| 355 | spin_lock(&dentry_list_lock); | ||
| 356 | if (!osb->dentry_lock_list) | ||
| 357 | queue_work(ocfs2_wq, &osb->dentry_lock_work); | ||
| 358 | dl->dl_next = osb->dentry_lock_list; | ||
| 359 | osb->dentry_lock_list = dl; | ||
| 360 | spin_unlock(&dentry_list_lock); | ||
| 325 | } | 361 | } |
| 326 | 362 | ||
| 327 | void ocfs2_dentry_lock_put(struct ocfs2_super *osb, | 363 | void ocfs2_dentry_lock_put(struct ocfs2_super *osb, |
| 328 | struct ocfs2_dentry_lock *dl) | 364 | struct ocfs2_dentry_lock *dl) |
| 329 | { | 365 | { |
| 330 | int unlock = 0; | 366 | int unlock; |
| 331 | 367 | ||
| 332 | BUG_ON(dl->dl_count == 0); | 368 | BUG_ON(dl->dl_count == 0); |
| 333 | 369 | ||
diff --git a/fs/ocfs2/dcache.h b/fs/ocfs2/dcache.h index c091c34d988..d06e16c0664 100644 --- a/fs/ocfs2/dcache.h +++ b/fs/ocfs2/dcache.h | |||
| @@ -29,8 +29,13 @@ | |||
| 29 | extern struct dentry_operations ocfs2_dentry_ops; | 29 | extern struct dentry_operations ocfs2_dentry_ops; |
| 30 | 30 | ||
| 31 | struct ocfs2_dentry_lock { | 31 | struct ocfs2_dentry_lock { |
| 32 | /* Use count of dentry lock */ | ||
| 32 | unsigned int dl_count; | 33 | unsigned int dl_count; |
| 33 | u64 dl_parent_blkno; | 34 | union { |
| 35 | /* Linked list of dentry locks to release */ | ||
| 36 | struct ocfs2_dentry_lock *dl_next; | ||
| 37 | u64 dl_parent_blkno; | ||
| 38 | }; | ||
| 34 | 39 | ||
| 35 | /* | 40 | /* |
| 36 | * The ocfs2_dentry_lock keeps an inode reference until | 41 | * The ocfs2_dentry_lock keeps an inode reference until |
| @@ -47,6 +52,8 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, struct inode *inode, | |||
| 47 | void ocfs2_dentry_lock_put(struct ocfs2_super *osb, | 52 | void ocfs2_dentry_lock_put(struct ocfs2_super *osb, |
| 48 | struct ocfs2_dentry_lock *dl); | 53 | struct ocfs2_dentry_lock *dl); |
| 49 | 54 | ||
| 55 | void ocfs2_drop_dl_inodes(struct work_struct *work); | ||
| 56 | |||
| 50 | struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno, | 57 | struct dentry *ocfs2_find_local_alias(struct inode *inode, u64 parent_blkno, |
| 51 | int skip_unhashed); | 58 | int skip_unhashed); |
| 52 | 59 | ||
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index b0c4cadd4c4..206a2370876 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
| @@ -2860,6 +2860,10 @@ static void ocfs2_unlock_ast(void *opaque, int error) | |||
| 2860 | case OCFS2_UNLOCK_CANCEL_CONVERT: | 2860 | case OCFS2_UNLOCK_CANCEL_CONVERT: |
| 2861 | mlog(0, "Cancel convert success for %s\n", lockres->l_name); | 2861 | mlog(0, "Cancel convert success for %s\n", lockres->l_name); |
| 2862 | lockres->l_action = OCFS2_AST_INVALID; | 2862 | lockres->l_action = OCFS2_AST_INVALID; |
| 2863 | /* Downconvert thread may have requeued this lock, we | ||
| 2864 | * need to wake it. */ | ||
| 2865 | if (lockres->l_flags & OCFS2_LOCK_BLOCKED) | ||
| 2866 | ocfs2_wake_downconvert_thread(ocfs2_get_lockres_osb(lockres)); | ||
| 2863 | break; | 2867 | break; |
| 2864 | case OCFS2_UNLOCK_DROP_LOCK: | 2868 | case OCFS2_UNLOCK_DROP_LOCK: |
| 2865 | lockres->l_level = DLM_LOCK_IV; | 2869 | lockres->l_level = DLM_LOCK_IV; |
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index ad5c24a29ed..077384135f4 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
| @@ -210,6 +210,7 @@ struct ocfs2_journal; | |||
| 210 | struct ocfs2_slot_info; | 210 | struct ocfs2_slot_info; |
| 211 | struct ocfs2_recovery_map; | 211 | struct ocfs2_recovery_map; |
| 212 | struct ocfs2_quota_recovery; | 212 | struct ocfs2_quota_recovery; |
| 213 | struct ocfs2_dentry_lock; | ||
| 213 | struct ocfs2_super | 214 | struct ocfs2_super |
| 214 | { | 215 | { |
| 215 | struct task_struct *commit_task; | 216 | struct task_struct *commit_task; |
| @@ -325,6 +326,11 @@ struct ocfs2_super | |||
| 325 | struct list_head blocked_lock_list; | 326 | struct list_head blocked_lock_list; |
| 326 | unsigned long blocked_lock_count; | 327 | unsigned long blocked_lock_count; |
| 327 | 328 | ||
| 329 | /* List of dentry locks to release. Anyone can add locks to | ||
| 330 | * the list, ocfs2_wq processes the list */ | ||
| 331 | struct ocfs2_dentry_lock *dentry_lock_list; | ||
| 332 | struct work_struct dentry_lock_work; | ||
| 333 | |||
| 328 | wait_queue_head_t osb_mount_event; | 334 | wait_queue_head_t osb_mount_event; |
| 329 | 335 | ||
| 330 | /* Truncate log info */ | 336 | /* Truncate log info */ |
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c index f4efa89baee..1ed0f7c8686 100644 --- a/fs/ocfs2/quota_global.c +++ b/fs/ocfs2/quota_global.c | |||
| @@ -754,7 +754,9 @@ static int ocfs2_mark_dquot_dirty(struct dquot *dquot) | |||
| 754 | if (dquot->dq_flags & mask) | 754 | if (dquot->dq_flags & mask) |
| 755 | sync = 1; | 755 | sync = 1; |
| 756 | spin_unlock(&dq_data_lock); | 756 | spin_unlock(&dq_data_lock); |
| 757 | if (!sync) { | 757 | /* This is a slight hack but we can't afford getting global quota |
| 758 | * lock if we already have a transaction started. */ | ||
| 759 | if (!sync || journal_current_handle()) { | ||
| 758 | status = ocfs2_write_dquot(dquot); | 760 | status = ocfs2_write_dquot(dquot); |
| 759 | goto out; | 761 | goto out; |
| 760 | } | 762 | } |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 43ed11345b5..b1cb38fbe80 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
| @@ -1887,6 +1887,9 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
| 1887 | INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery); | 1887 | INIT_WORK(&journal->j_recovery_work, ocfs2_complete_recovery); |
| 1888 | journal->j_state = OCFS2_JOURNAL_FREE; | 1888 | journal->j_state = OCFS2_JOURNAL_FREE; |
| 1889 | 1889 | ||
| 1890 | INIT_WORK(&osb->dentry_lock_work, ocfs2_drop_dl_inodes); | ||
| 1891 | osb->dentry_lock_list = NULL; | ||
| 1892 | |||
| 1890 | /* get some pseudo constants for clustersize bits */ | 1893 | /* get some pseudo constants for clustersize bits */ |
| 1891 | osb->s_clustersize_bits = | 1894 | osb->s_clustersize_bits = |
| 1892 | le32_to_cpu(di->id2.i_super.s_clustersize_bits); | 1895 | le32_to_cpu(di->id2.i_super.s_clustersize_bits); |
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index e1d638af6ac..915039fffe6 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
| @@ -4729,13 +4729,6 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode, | |||
| 4729 | vb.vb_xv = (struct ocfs2_xattr_value_root *) | 4729 | vb.vb_xv = (struct ocfs2_xattr_value_root *) |
| 4730 | (vb.vb_bh->b_data + offset % blocksize); | 4730 | (vb.vb_bh->b_data + offset % blocksize); |
| 4731 | 4731 | ||
| 4732 | ret = ocfs2_xattr_bucket_journal_access(ctxt->handle, bucket, | ||
| 4733 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 4734 | if (ret) { | ||
| 4735 | mlog_errno(ret); | ||
| 4736 | goto out; | ||
| 4737 | } | ||
| 4738 | |||
| 4739 | /* | 4732 | /* |
| 4740 | * From here on out we have to dirty the bucket. The generic | 4733 | * From here on out we have to dirty the bucket. The generic |
| 4741 | * value calls only modify one of the bucket's bhs, but we need | 4734 | * value calls only modify one of the bucket's bhs, but we need |
| @@ -4748,12 +4741,18 @@ static int ocfs2_xattr_bucket_value_truncate(struct inode *inode, | |||
| 4748 | ret = ocfs2_xattr_value_truncate(inode, &vb, len, ctxt); | 4741 | ret = ocfs2_xattr_value_truncate(inode, &vb, len, ctxt); |
| 4749 | if (ret) { | 4742 | if (ret) { |
| 4750 | mlog_errno(ret); | 4743 | mlog_errno(ret); |
| 4751 | goto out_dirty; | 4744 | goto out; |
| 4745 | } | ||
| 4746 | |||
| 4747 | ret = ocfs2_xattr_bucket_journal_access(ctxt->handle, bucket, | ||
| 4748 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 4749 | if (ret) { | ||
| 4750 | mlog_errno(ret); | ||
| 4751 | goto out; | ||
| 4752 | } | 4752 | } |
| 4753 | 4753 | ||
| 4754 | xe->xe_value_size = cpu_to_le64(len); | 4754 | xe->xe_value_size = cpu_to_le64(len); |
| 4755 | 4755 | ||
| 4756 | out_dirty: | ||
| 4757 | ocfs2_xattr_bucket_journal_dirty(ctxt->handle, bucket); | 4756 | ocfs2_xattr_bucket_journal_dirty(ctxt->handle, bucket); |
| 4758 | 4757 | ||
| 4759 | out: | 4758 | out: |
