Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ocfs2: Add new refcount tree lock resource in dlmglue.

refcount tree lock resource is used to protect refcount
tree read/write among multiple nodes.

Signed-off-by: Tao Ma <tao.ma@oracle.com>

authored by

Tao Ma and committed by
Joel Becker
8dec98ed a4338481

+127
+80
fs/ocfs2/dlmglue.c
··· 53 53 #include "super.h" 54 54 #include "uptodate.h" 55 55 #include "quota.h" 56 + #include "refcounttree.h" 56 57 57 58 #include "buffer_head_io.h" 58 59 ··· 110 109 struct ocfs2_lock_res *lockres); 111 110 112 111 static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres); 112 + 113 + static int ocfs2_check_refcount_downconvert(struct ocfs2_lock_res *lockres, 114 + int new_level); 115 + static int ocfs2_refcount_convert_worker(struct ocfs2_lock_res *lockres, 116 + int blocking); 113 117 114 118 #define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres) 115 119 ··· 284 278 .flags = LOCK_TYPE_REQUIRES_REFRESH | LOCK_TYPE_USES_LVB, 285 279 }; 286 280 281 + static struct ocfs2_lock_res_ops ocfs2_refcount_block_lops = { 282 + .check_downconvert = ocfs2_check_refcount_downconvert, 283 + .downconvert_worker = ocfs2_refcount_convert_worker, 284 + .flags = 0, 285 + }; 286 + 287 287 static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres) 288 288 { 289 289 return lockres->l_type == OCFS2_LOCK_TYPE_META || ··· 316 304 BUG_ON(lockres->l_type != OCFS2_LOCK_TYPE_QINFO); 317 305 318 306 return (struct ocfs2_mem_dqinfo *)lockres->l_priv; 307 + } 308 + 309 + static inline struct ocfs2_refcount_tree * 310 + ocfs2_lock_res_refcount_tree(struct ocfs2_lock_res *res) 311 + { 312 + return container_of(res, struct ocfs2_refcount_tree, rf_lockres); 319 313 } 320 314 321 315 static inline struct ocfs2_super *ocfs2_get_lockres_osb(struct ocfs2_lock_res *lockres) ··· 709 691 ocfs2_lock_res_init_common(OCFS2_SB(info->dqi_gi.dqi_sb), lockres, 710 692 OCFS2_LOCK_TYPE_QINFO, &ocfs2_qinfo_lops, 711 693 info); 694 + } 695 + 696 + void ocfs2_refcount_lock_res_init(struct ocfs2_lock_res *lockres, 697 + struct ocfs2_super *osb, u64 ref_blkno, 698 + unsigned int generation) 699 + { 700 + ocfs2_lock_res_init_once(lockres); 701 + ocfs2_build_lock_name(OCFS2_LOCK_TYPE_REFCOUNT, ref_blkno, 702 + generation, lockres->l_name); 703 + ocfs2_lock_res_init_common(osb, lockres, OCFS2_LOCK_TYPE_REFCOUNT, 704 + &ocfs2_refcount_block_lops, osb); 712 705 } 713 706 714 707 void ocfs2_lock_res_free(struct ocfs2_lock_res *res) ··· 3677 3648 return UNBLOCK_CONTINUE_POST; 3678 3649 } 3679 3650 3651 + static int ocfs2_check_refcount_downconvert(struct ocfs2_lock_res *lockres, 3652 + int new_level) 3653 + { 3654 + struct ocfs2_refcount_tree *tree = 3655 + ocfs2_lock_res_refcount_tree(lockres); 3656 + 3657 + return ocfs2_ci_checkpointed(&tree->rf_ci, lockres, new_level); 3658 + } 3659 + 3660 + static int ocfs2_refcount_convert_worker(struct ocfs2_lock_res *lockres, 3661 + int blocking) 3662 + { 3663 + struct ocfs2_refcount_tree *tree = 3664 + ocfs2_lock_res_refcount_tree(lockres); 3665 + 3666 + ocfs2_metadata_cache_purge(&tree->rf_ci); 3667 + 3668 + return UNBLOCK_CONTINUE; 3669 + } 3670 + 3680 3671 static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres) 3681 3672 { 3682 3673 struct ocfs2_qinfo_lvb *lvb; ··· 3807 3758 bail: 3808 3759 mlog_exit(status); 3809 3760 return status; 3761 + } 3762 + 3763 + int ocfs2_refcount_lock(struct ocfs2_refcount_tree *ref_tree, int ex) 3764 + { 3765 + int status; 3766 + int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR; 3767 + struct ocfs2_lock_res *lockres = &ref_tree->rf_lockres; 3768 + struct ocfs2_super *osb = lockres->l_priv; 3769 + 3770 + 3771 + if (ocfs2_is_hard_readonly(osb)) 3772 + return -EROFS; 3773 + 3774 + if (ocfs2_mount_local(osb)) 3775 + return 0; 3776 + 3777 + status = ocfs2_cluster_lock(osb, lockres, level, 0, 0); 3778 + if (status < 0) 3779 + mlog_errno(status); 3780 + 3781 + return status; 3782 + } 3783 + 3784 + void ocfs2_refcount_unlock(struct ocfs2_refcount_tree *ref_tree, int ex) 3785 + { 3786 + int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR; 3787 + struct ocfs2_lock_res *lockres = &ref_tree->rf_lockres; 3788 + struct ocfs2_super *osb = lockres->l_priv; 3789 + 3790 + if (!ocfs2_mount_local(osb)) 3791 + ocfs2_cluster_unlock(osb, lockres, level); 3810 3792 } 3811 3793 3812 3794 /*
+6
fs/ocfs2/dlmglue.h
··· 101 101 struct ocfs2_mem_dqinfo; 102 102 void ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres, 103 103 struct ocfs2_mem_dqinfo *info); 104 + void ocfs2_refcount_lock_res_init(struct ocfs2_lock_res *lockres, 105 + struct ocfs2_super *osb, u64 ref_blkno, 106 + unsigned int generation); 104 107 void ocfs2_lock_res_free(struct ocfs2_lock_res *res); 105 108 int ocfs2_create_new_inode_locks(struct inode *inode); 106 109 int ocfs2_drop_inode_locks(struct inode *inode); ··· 151 148 void ocfs2_file_unlock(struct file *file); 152 149 int ocfs2_qinfo_lock(struct ocfs2_mem_dqinfo *oinfo, int ex); 153 150 void ocfs2_qinfo_unlock(struct ocfs2_mem_dqinfo *oinfo, int ex); 151 + struct ocfs2_refcount_tree; 152 + int ocfs2_refcount_lock(struct ocfs2_refcount_tree *ref_tree, int ex); 153 + void ocfs2_refcount_unlock(struct ocfs2_refcount_tree *ref_tree, int ex); 154 154 155 155 156 156 void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres);
+5
fs/ocfs2/ocfs2_lockid.h
··· 49 49 OCFS2_LOCK_TYPE_QINFO, 50 50 OCFS2_LOCK_TYPE_NFS_SYNC, 51 51 OCFS2_LOCK_TYPE_ORPHAN_SCAN, 52 + OCFS2_LOCK_TYPE_REFCOUNT, 52 53 OCFS2_NUM_LOCK_TYPES 53 54 }; 54 55 ··· 90 89 case OCFS2_LOCK_TYPE_ORPHAN_SCAN: 91 90 c = 'P'; 92 91 break; 92 + case OCFS2_LOCK_TYPE_REFCOUNT: 93 + c = 'T'; 94 + break; 93 95 default: 94 96 c = '\0'; 95 97 } ··· 114 110 [OCFS2_LOCK_TYPE_QINFO] = "Quota", 115 111 [OCFS2_LOCK_TYPE_NFS_SYNC] = "NFSSync", 116 112 [OCFS2_LOCK_TYPE_ORPHAN_SCAN] = "OrphanScan", 113 + [OCFS2_LOCK_TYPE_REFCOUNT] = "Refcount", 117 114 }; 118 115 119 116 static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type)
+36
fs/ocfs2/refcounttree.h
··· 1 + /* -*- mode: c; c-basic-offset: 8; -*- 2 + * vim: noexpandtab sw=8 ts=8 sts=0: 3 + * 4 + * refcounttree.h 5 + * 6 + * Copyright (C) 2009 Oracle. All rights reserved. 7 + * 8 + * This program is free software; you can redistribute it and/or 9 + * modify it under the terms of the GNU General Public 10 + * License version 2 as published by the Free Software Foundation. 11 + * 12 + * This program is distributed in the hope that it will be useful, 13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 + * General Public License for more details. 16 + */ 17 + #ifndef OCFS2_REFCOUNTTREE_H 18 + #define OCFS2_REFCOUNTTREE_H 19 + 20 + struct ocfs2_refcount_tree { 21 + struct rb_node rf_node; 22 + u64 rf_blkno; 23 + u32 rf_generation; 24 + struct rw_semaphore rf_sem; 25 + struct ocfs2_lock_res rf_lockres; 26 + struct kref rf_getcnt; 27 + int rf_removed; 28 + 29 + /* the following 4 fields are used by caching_info. */ 30 + struct ocfs2_caching_info rf_ci; 31 + spinlock_t rf_lock; 32 + struct mutex rf_io_mutex; 33 + struct super_block *rf_sb; 34 + }; 35 + 36 + #endif /* OCFS2_REFCOUNTTREE_H */