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>
This commit is contained in:
@@ -53,6 +53,7 @@
|
||||
#include "super.h"
|
||||
#include "uptodate.h"
|
||||
#include "quota.h"
|
||||
#include "refcounttree.h"
|
||||
|
||||
#include "buffer_head_io.h"
|
||||
|
||||
@@ -110,6 +111,11 @@ static void ocfs2_dentry_post_unlock(struct ocfs2_super *osb,
|
||||
|
||||
static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres);
|
||||
|
||||
static int ocfs2_check_refcount_downconvert(struct ocfs2_lock_res *lockres,
|
||||
int new_level);
|
||||
static int ocfs2_refcount_convert_worker(struct ocfs2_lock_res *lockres,
|
||||
int blocking);
|
||||
|
||||
#define mlog_meta_lvb(__level, __lockres) ocfs2_dump_meta_lvb_info(__level, __PRETTY_FUNCTION__, __LINE__, __lockres)
|
||||
|
||||
/* This aids in debugging situations where a bad LVB might be involved. */
|
||||
@@ -278,6 +284,12 @@ static struct ocfs2_lock_res_ops ocfs2_qinfo_lops = {
|
||||
.flags = LOCK_TYPE_REQUIRES_REFRESH | LOCK_TYPE_USES_LVB,
|
||||
};
|
||||
|
||||
static struct ocfs2_lock_res_ops ocfs2_refcount_block_lops = {
|
||||
.check_downconvert = ocfs2_check_refcount_downconvert,
|
||||
.downconvert_worker = ocfs2_refcount_convert_worker,
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres)
|
||||
{
|
||||
return lockres->l_type == OCFS2_LOCK_TYPE_META ||
|
||||
@@ -306,6 +318,12 @@ static inline struct ocfs2_mem_dqinfo *ocfs2_lock_res_qinfo(struct ocfs2_lock_re
|
||||
return (struct ocfs2_mem_dqinfo *)lockres->l_priv;
|
||||
}
|
||||
|
||||
static inline struct ocfs2_refcount_tree *
|
||||
ocfs2_lock_res_refcount_tree(struct ocfs2_lock_res *res)
|
||||
{
|
||||
return container_of(res, struct ocfs2_refcount_tree, rf_lockres);
|
||||
}
|
||||
|
||||
static inline struct ocfs2_super *ocfs2_get_lockres_osb(struct ocfs2_lock_res *lockres)
|
||||
{
|
||||
if (lockres->l_ops->get_osb)
|
||||
@@ -693,6 +711,17 @@ void ocfs2_qinfo_lock_res_init(struct ocfs2_lock_res *lockres,
|
||||
info);
|
||||
}
|
||||
|
||||
void ocfs2_refcount_lock_res_init(struct ocfs2_lock_res *lockres,
|
||||
struct ocfs2_super *osb, u64 ref_blkno,
|
||||
unsigned int generation)
|
||||
{
|
||||
ocfs2_lock_res_init_once(lockres);
|
||||
ocfs2_build_lock_name(OCFS2_LOCK_TYPE_REFCOUNT, ref_blkno,
|
||||
generation, lockres->l_name);
|
||||
ocfs2_lock_res_init_common(osb, lockres, OCFS2_LOCK_TYPE_REFCOUNT,
|
||||
&ocfs2_refcount_block_lops, osb);
|
||||
}
|
||||
|
||||
void ocfs2_lock_res_free(struct ocfs2_lock_res *res)
|
||||
{
|
||||
mlog_entry_void();
|
||||
@@ -3648,6 +3677,26 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres,
|
||||
return UNBLOCK_CONTINUE_POST;
|
||||
}
|
||||
|
||||
static int ocfs2_check_refcount_downconvert(struct ocfs2_lock_res *lockres,
|
||||
int new_level)
|
||||
{
|
||||
struct ocfs2_refcount_tree *tree =
|
||||
ocfs2_lock_res_refcount_tree(lockres);
|
||||
|
||||
return ocfs2_ci_checkpointed(&tree->rf_ci, lockres, new_level);
|
||||
}
|
||||
|
||||
static int ocfs2_refcount_convert_worker(struct ocfs2_lock_res *lockres,
|
||||
int blocking)
|
||||
{
|
||||
struct ocfs2_refcount_tree *tree =
|
||||
ocfs2_lock_res_refcount_tree(lockres);
|
||||
|
||||
ocfs2_metadata_cache_purge(&tree->rf_ci);
|
||||
|
||||
return UNBLOCK_CONTINUE;
|
||||
}
|
||||
|
||||
static void ocfs2_set_qinfo_lvb(struct ocfs2_lock_res *lockres)
|
||||
{
|
||||
struct ocfs2_qinfo_lvb *lvb;
|
||||
@@ -3760,6 +3809,37 @@ bail:
|
||||
return status;
|
||||
}
|
||||
|
||||
int ocfs2_refcount_lock(struct ocfs2_refcount_tree *ref_tree, int ex)
|
||||
{
|
||||
int status;
|
||||
int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
|
||||
struct ocfs2_lock_res *lockres = &ref_tree->rf_lockres;
|
||||
struct ocfs2_super *osb = lockres->l_priv;
|
||||
|
||||
|
||||
if (ocfs2_is_hard_readonly(osb))
|
||||
return -EROFS;
|
||||
|
||||
if (ocfs2_mount_local(osb))
|
||||
return 0;
|
||||
|
||||
status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
|
||||
if (status < 0)
|
||||
mlog_errno(status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void ocfs2_refcount_unlock(struct ocfs2_refcount_tree *ref_tree, int ex)
|
||||
{
|
||||
int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
|
||||
struct ocfs2_lock_res *lockres = &ref_tree->rf_lockres;
|
||||
struct ocfs2_super *osb = lockres->l_priv;
|
||||
|
||||
if (!ocfs2_mount_local(osb))
|
||||
ocfs2_cluster_unlock(osb, lockres, level);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the filesystem locking protocol. It provides the lock handling
|
||||
* hooks for the underlying DLM. It has a maximum version number.
|
||||
|
Reference in New Issue
Block a user