|
@@ -92,6 +92,9 @@ struct ocfs2_unblock_ctl {
|
|
|
enum ocfs2_unblock_action unblock_action;
|
|
|
};
|
|
|
|
|
|
+/* Lockdep class keys */
|
|
|
+struct lock_class_key lockdep_keys[OCFS2_NUM_LOCK_TYPES];
|
|
|
+
|
|
|
static int ocfs2_check_meta_downconvert(struct ocfs2_lock_res *lockres,
|
|
|
int new_level);
|
|
|
static void ocfs2_set_meta_lvb(struct ocfs2_lock_res *lockres);
|
|
@@ -317,9 +320,16 @@ static int ocfs2_lock_create(struct ocfs2_super *osb,
|
|
|
u32 dlm_flags);
|
|
|
static inline int ocfs2_may_continue_on_blocked_lock(struct ocfs2_lock_res *lockres,
|
|
|
int wanted);
|
|
|
-static void ocfs2_cluster_unlock(struct ocfs2_super *osb,
|
|
|
- struct ocfs2_lock_res *lockres,
|
|
|
- int level);
|
|
|
+static void __ocfs2_cluster_unlock(struct ocfs2_super *osb,
|
|
|
+ struct ocfs2_lock_res *lockres,
|
|
|
+ int level, unsigned long caller_ip);
|
|
|
+static inline void ocfs2_cluster_unlock(struct ocfs2_super *osb,
|
|
|
+ struct ocfs2_lock_res *lockres,
|
|
|
+ int level)
|
|
|
+{
|
|
|
+ __ocfs2_cluster_unlock(osb, lockres, level, _RET_IP_);
|
|
|
+}
|
|
|
+
|
|
|
static inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res *lockres);
|
|
|
static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lockres);
|
|
|
static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *lockres);
|
|
@@ -489,6 +499,13 @@ static void ocfs2_lock_res_init_common(struct ocfs2_super *osb,
|
|
|
ocfs2_add_lockres_tracking(res, osb->osb_dlm_debug);
|
|
|
|
|
|
ocfs2_init_lock_stats(res);
|
|
|
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
|
|
+ if (type != OCFS2_LOCK_TYPE_OPEN)
|
|
|
+ lockdep_init_map(&res->l_lockdep_map, ocfs2_lock_type_strings[type],
|
|
|
+ &lockdep_keys[type], 0);
|
|
|
+ else
|
|
|
+ res->l_lockdep_map.key = NULL;
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res)
|
|
@@ -644,14 +661,10 @@ static void ocfs2_nfs_sync_lock_res_init(struct ocfs2_lock_res *res,
|
|
|
static void ocfs2_orphan_scan_lock_res_init(struct ocfs2_lock_res *res,
|
|
|
struct ocfs2_super *osb)
|
|
|
{
|
|
|
- struct ocfs2_orphan_scan_lvb *lvb;
|
|
|
-
|
|
|
ocfs2_lock_res_init_once(res);
|
|
|
ocfs2_build_lock_name(OCFS2_LOCK_TYPE_ORPHAN_SCAN, 0, 0, res->l_name);
|
|
|
ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_ORPHAN_SCAN,
|
|
|
&ocfs2_orphan_scan_lops, osb);
|
|
|
- lvb = ocfs2_dlm_lvb(&res->l_lksb);
|
|
|
- lvb->lvb_version = OCFS2_ORPHAN_LVB_VERSION;
|
|
|
}
|
|
|
|
|
|
void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres,
|
|
@@ -1256,11 +1269,13 @@ static int ocfs2_wait_for_mask_interruptible(struct ocfs2_mask_waiter *mw,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static int ocfs2_cluster_lock(struct ocfs2_super *osb,
|
|
|
- struct ocfs2_lock_res *lockres,
|
|
|
- int level,
|
|
|
- u32 lkm_flags,
|
|
|
- int arg_flags)
|
|
|
+static int __ocfs2_cluster_lock(struct ocfs2_super *osb,
|
|
|
+ struct ocfs2_lock_res *lockres,
|
|
|
+ int level,
|
|
|
+ u32 lkm_flags,
|
|
|
+ int arg_flags,
|
|
|
+ int l_subclass,
|
|
|
+ unsigned long caller_ip)
|
|
|
{
|
|
|
struct ocfs2_mask_waiter mw;
|
|
|
int wait, catch_signals = !(osb->s_mount_opt & OCFS2_MOUNT_NOINTR);
|
|
@@ -1403,13 +1418,37 @@ out:
|
|
|
}
|
|
|
ocfs2_update_lock_stats(lockres, level, &mw, ret);
|
|
|
|
|
|
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
|
|
+ if (!ret && lockres->l_lockdep_map.key != NULL) {
|
|
|
+ if (level == DLM_LOCK_PR)
|
|
|
+ rwsem_acquire_read(&lockres->l_lockdep_map, l_subclass,
|
|
|
+ !!(arg_flags & OCFS2_META_LOCK_NOQUEUE),
|
|
|
+ caller_ip);
|
|
|
+ else
|
|
|
+ rwsem_acquire(&lockres->l_lockdep_map, l_subclass,
|
|
|
+ !!(arg_flags & OCFS2_META_LOCK_NOQUEUE),
|
|
|
+ caller_ip);
|
|
|
+ }
|
|
|
+#endif
|
|
|
mlog_exit(ret);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-static void ocfs2_cluster_unlock(struct ocfs2_super *osb,
|
|
|
- struct ocfs2_lock_res *lockres,
|
|
|
- int level)
|
|
|
+static inline int ocfs2_cluster_lock(struct ocfs2_super *osb,
|
|
|
+ struct ocfs2_lock_res *lockres,
|
|
|
+ int level,
|
|
|
+ u32 lkm_flags,
|
|
|
+ int arg_flags)
|
|
|
+{
|
|
|
+ return __ocfs2_cluster_lock(osb, lockres, level, lkm_flags, arg_flags,
|
|
|
+ 0, _RET_IP_);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static void __ocfs2_cluster_unlock(struct ocfs2_super *osb,
|
|
|
+ struct ocfs2_lock_res *lockres,
|
|
|
+ int level,
|
|
|
+ unsigned long caller_ip)
|
|
|
{
|
|
|
unsigned long flags;
|
|
|
|
|
@@ -1418,6 +1457,10 @@ static void ocfs2_cluster_unlock(struct ocfs2_super *osb,
|
|
|
ocfs2_dec_holders(lockres, level);
|
|
|
ocfs2_downconvert_on_unlock(osb, lockres);
|
|
|
spin_unlock_irqrestore(&lockres->l_lock, flags);
|
|
|
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
|
|
+ if (lockres->l_lockdep_map.key != NULL)
|
|
|
+ rwsem_release(&lockres->l_lockdep_map, 1, caller_ip);
|
|
|
+#endif
|
|
|
mlog_exit_void();
|
|
|
}
|
|
|
|
|
@@ -1989,7 +2032,8 @@ static inline int ocfs2_meta_lvb_is_trustable(struct inode *inode,
|
|
|
{
|
|
|
struct ocfs2_meta_lvb *lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
|
|
|
|
|
|
- if (lvb->lvb_version == OCFS2_LVB_VERSION
|
|
|
+ if (ocfs2_dlm_lvb_valid(&lockres->l_lksb)
|
|
|
+ && lvb->lvb_version == OCFS2_LVB_VERSION
|
|
|
&& be32_to_cpu(lvb->lvb_igeneration) == inode->i_generation)
|
|
|
return 1;
|
|
|
return 0;
|
|
@@ -2162,10 +2206,11 @@ static int ocfs2_assign_bh(struct inode *inode,
|
|
|
* returns < 0 error if the callback will never be called, otherwise
|
|
|
* the result of the lock will be communicated via the callback.
|
|
|
*/
|
|
|
-int ocfs2_inode_lock_full(struct inode *inode,
|
|
|
- struct buffer_head **ret_bh,
|
|
|
- int ex,
|
|
|
- int arg_flags)
|
|
|
+int ocfs2_inode_lock_full_nested(struct inode *inode,
|
|
|
+ struct buffer_head **ret_bh,
|
|
|
+ int ex,
|
|
|
+ int arg_flags,
|
|
|
+ int subclass)
|
|
|
{
|
|
|
int status, level, acquired;
|
|
|
u32 dlm_flags;
|
|
@@ -2203,7 +2248,8 @@ int ocfs2_inode_lock_full(struct inode *inode,
|
|
|
if (arg_flags & OCFS2_META_LOCK_NOQUEUE)
|
|
|
dlm_flags |= DLM_LKF_NOQUEUE;
|
|
|
|
|
|
- status = ocfs2_cluster_lock(osb, lockres, level, dlm_flags, arg_flags);
|
|
|
+ status = __ocfs2_cluster_lock(osb, lockres, level, dlm_flags,
|
|
|
+ arg_flags, subclass, _RET_IP_);
|
|
|
if (status < 0) {
|
|
|
if (status != -EAGAIN && status != -EIOCBRETRY)
|
|
|
mlog_errno(status);
|
|
@@ -2369,35 +2415,45 @@ void ocfs2_inode_unlock(struct inode *inode,
|
|
|
mlog_exit_void();
|
|
|
}
|
|
|
|
|
|
-int ocfs2_orphan_scan_lock(struct ocfs2_super *osb, u32 *seqno, int ex)
|
|
|
+int ocfs2_orphan_scan_lock(struct ocfs2_super *osb, u32 *seqno)
|
|
|
{
|
|
|
struct ocfs2_lock_res *lockres;
|
|
|
struct ocfs2_orphan_scan_lvb *lvb;
|
|
|
- int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
|
|
|
int status = 0;
|
|
|
|
|
|
+ if (ocfs2_is_hard_readonly(osb))
|
|
|
+ return -EROFS;
|
|
|
+
|
|
|
+ if (ocfs2_mount_local(osb))
|
|
|
+ return 0;
|
|
|
+
|
|
|
lockres = &osb->osb_orphan_scan.os_lockres;
|
|
|
- status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
|
|
|
+ status = ocfs2_cluster_lock(osb, lockres, DLM_LOCK_EX, 0, 0);
|
|
|
if (status < 0)
|
|
|
return status;
|
|
|
|
|
|
lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
|
|
|
- if (lvb->lvb_version == OCFS2_ORPHAN_LVB_VERSION)
|
|
|
+ if (ocfs2_dlm_lvb_valid(&lockres->l_lksb) &&
|
|
|
+ lvb->lvb_version == OCFS2_ORPHAN_LVB_VERSION)
|
|
|
*seqno = be32_to_cpu(lvb->lvb_os_seqno);
|
|
|
+ else
|
|
|
+ *seqno = osb->osb_orphan_scan.os_seqno + 1;
|
|
|
+
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
-void ocfs2_orphan_scan_unlock(struct ocfs2_super *osb, u32 seqno, int ex)
|
|
|
+void ocfs2_orphan_scan_unlock(struct ocfs2_super *osb, u32 seqno)
|
|
|
{
|
|
|
struct ocfs2_lock_res *lockres;
|
|
|
struct ocfs2_orphan_scan_lvb *lvb;
|
|
|
- int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
|
|
|
|
|
|
- lockres = &osb->osb_orphan_scan.os_lockres;
|
|
|
- lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
|
|
|
- lvb->lvb_version = OCFS2_ORPHAN_LVB_VERSION;
|
|
|
- lvb->lvb_os_seqno = cpu_to_be32(seqno);
|
|
|
- ocfs2_cluster_unlock(osb, lockres, level);
|
|
|
+ if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb)) {
|
|
|
+ lockres = &osb->osb_orphan_scan.os_lockres;
|
|
|
+ lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
|
|
|
+ lvb->lvb_version = OCFS2_ORPHAN_LVB_VERSION;
|
|
|
+ lvb->lvb_os_seqno = cpu_to_be32(seqno);
|
|
|
+ ocfs2_cluster_unlock(osb, lockres, DLM_LOCK_EX);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
int ocfs2_super_lock(struct ocfs2_super *osb,
|
|
@@ -3627,7 +3683,8 @@ static int ocfs2_refresh_qinfo(struct ocfs2_mem_dqinfo *oinfo)
|
|
|
struct ocfs2_global_disk_dqinfo *gdinfo;
|
|
|
int status = 0;
|
|
|
|
|
|
- if (lvb->lvb_version == OCFS2_QINFO_LVB_VERSION) {
|
|
|
+ if (ocfs2_dlm_lvb_valid(&lockres->l_lksb) &&
|
|
|
+ lvb->lvb_version == OCFS2_QINFO_LVB_VERSION) {
|
|
|
info->dqi_bgrace = be32_to_cpu(lvb->lvb_bgrace);
|
|
|
info->dqi_igrace = be32_to_cpu(lvb->lvb_igrace);
|
|
|
oinfo->dqi_syncms = be32_to_cpu(lvb->lvb_syncms);
|