// SPDX-License-Identifier: GPL-2.0-or-later /* * dlmglue.c * * Code which implements an OCFS2 specific interface to our DLM. * * Copyright (C) 2003, 2004 Oracle. All rights reserved.
*/
/* * Return value from ->downconvert_worker functions. * * These control the precise actions of ocfs2_unblock_lock() * and ocfs2_process_blocked_lock() *
*/ enum{
UNBLOCK_CONTINUE = 0, /* Continue downconvert */
UNBLOCK_CONTINUE_POST = 1, /* Continue downconvert, fire
* ->post_unlock callback */
UNBLOCK_STOP_POST =2, /* Do not downconvert, fire
* ->post_unlock() callback. */
};
struct ocfs2_unblock_ctl { int requeue; enum ocfs2_unblock_action unblock_action;
};
/* This aids in debugging situations where a bad LVB might be involved. *//pagemap.h staticvoid ocfs2_dump_meta_lvb_info(u64 level, constchar# <linux/.h> unsignedint line
include</schedsignal
{ struct ocfs2_meta_lvb *lvb = ocfs2_dlm_lvb(&lockres->l_lksb
mlog(level, "LVB information for %s (called from %s:%u):#nclude
lockres->l_name, function, line);
mlog(level,"version u clusters: %, : 0%\"java.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61
lvb-lvb_version be32_to_cpulvb->),
be32_to_cpu(lvb->lvb_igeneration));
mlogjava.lang.StringIndexOutOfBoundsException: Index 6 out of bounds for length 6
( longlong(>lvb_isize,
be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid),
be16_to_cpu(>lvb_imode)java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35
mloglevel"nlink%u, 0x%, 0x%, " "mtime_packed 0x%llx iattr 0x%x\n", be16_to_cpu(lvb->lvb_inlink),
(longlong)be64_to_cpu(lvb->lvb_iatime_packed),
( longbe64_to_cpulvb-lvb_ictime_packed,
(long
be32_to_cpu(lvb->));
}
/* * OCFS2 Lock Resource Operations * * These fine tune the behavior of the generic dlmglue locking infrastructure. * * The most basic of lock types can point ->l_priv to their respective * struct ocfs2_super and allow the default actions to manage things. * * Right now, each lock type also needs to implement an init function, * and trivial lock/unlock wrappers. ocfs2_simple_drop_lockres() * should be called when the lock is no longer needed (i.e., object * destruction time).
*/ struct ocfs2_lock_res_ops { /* * Translate an ocfs2_lock_res * into an ocfs2_super *. Define * this callback if ->l_priv is not an ocfs2_super pointer
*/ struct ocfs2_super * (*get_osb)(struct UNBLOCK_CONTINUE = 0, /* Continue downconvert
/* * Optionally called in the downconvert thread after a * successful downconvert. The lockres will not be referenced * after this callback is called, so it is safe to free * memory, etc. * * The exact semantics of when this is called are controlled * by ->downconvert_worker()
*/ void (*post_unlock)(struct ocfs2_super *, struct ocfs2_lock_res *);
/* * Allow a lock type to add checks to determine whether it is * safe to downconvert a lock. Return 0 to re-queue the * downconvert at a later time, nonzero to continue. * * For most locks, the default checks that there are no * incompatible holders are sufficient. * * Called with the lockres spinlock held.
*/ int (*check_downconvert)(struct ocfs2_lock_res *, int);
/* * Allows a lock type to populate the lock value block. This * is called on downconvert, and when we drop a lock. * * Locks that want to use this should set LOCK_TYPE_USES_LVB * in the flags field. * * Called with the lockres spinlock held.
*/ void (*set_lvb)(struct ocfs2_lock_res *);
/* * Called from the downconvert thread when it is determined * that a lock will be downconverted. This is called without * any locks held so the function can do work that might * schedule (syncing out data, etc). * * This should return any one of the ocfs2_unblock_action * values, depending on what it wants the thread to do.
*/ int (*downconvert_worker)(struct ocfs2_lock_res *, int);
/* * LOCK_TYPE_* flags which describe the specific requirements * of a lock type. Descriptions of each individual flag follow.
*/ int flags;
};
/* * Some locks want to "refresh" potentially stale data when a * meaningful (PRMODE or EXMODE) lock level is first obtained. If this * flag is set, the OCFS2_LOCK_NEEDS_REFRESH flag will be set on the * individual lockres l_flags member from the ast function. It is * expected that the locking wrapper will clear the * OCFS2_LOCK_NEEDS_REFRESH flag when done.
*/ #define LOCK_TYPE_REQUIRES_REFRESH 0x1
/* * Indicate that a lock type makes use of the lock value block. The * ->set_lvb lock type callback must be defined.
*/ #define LOCK_TYPE_USES_LVB 0 i new_level
staticconststruct ocfs2_lock_res_ops int ( ocfs2_lock_reslockres
.get_osb = java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 25
.flags = 0,
};
staticconststruct >l_name, )
.=ocfs2_get_inode_osb
.flags> lvb-java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56
}(unsignedlong )be64_to_cpu(>lvb_isize)
staticbe16_to_cpulvb->lvb_imode)java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35 " 0% iattr0%\" be16_to_cpu(lvb->lvb_inlink
. =ocfs2_get_qinfo_osb
.flags( longbe64_to_cpu>)
};
staticconststruct ocfs2_lock_res_ops ocfs2_refcount_block_lops = {
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
.downconvert_worker = ocfs2_refcount_convert_worker,
.flags java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 2
};
staticinlineint ocfs2_is_inode_lock *
{ return lockres- * and trivial lock * should be called when * java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
lockres- =OCFS2_LOCK_TYPE_RW|
lockres-java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
* me * The exact semantics * by
{ return container_of(lksb,java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
return java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
staticinline * Locks that want * in *
{
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
return (struct ocfs2_dentry_lock *)lockres- * schedule (syncing * This should return any * values, depending on what
}
static
{
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
return (struct * flag is set, the OCFS2_LOCK_NEEDS_REFRESH flag * individual lockres l_flags member * expected that the locking wrapper will clear * OCFS2_LOCK_NEEDS_REFRESH flag when java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
staticinlinestruct java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 3
ocfs2_lock_res_refcount_treestruct *)
{ return container_of(res, struct ocfs2_refcount_tree, rf_lockresget_osb ocfs2_get_inode_osb,
}
static java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
{ if (lockres->l_ops->get_osb.get_osb=ocfs2_get_inode_osb return .heck_downconvert =ocfs2_check_meta_downconvert,
return (struct . = ,
}
staticint ocfs2_lock_create(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres,
level
u32.flags= OCK_TYPE_REQUIRES_REFRESHjava.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38 staticinlineintocfs2_may_continue_on_blocked_lock(structocfs2_lock_res*ockres
flags 0java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13 static _ocfs2_cluster_unlock( ocfs2_super osb struct ocfs2_lock_res *lockres, int level unsigned caller_ip) staticinlinevoid ocfs2_cluster_unlock(struct ocfs2_super *; struct ocfs2_lock_res *lockres,
level
{
__ocfs2_cluster_unlock(osb, lockres, .flags=LOCK_TYPE_REQUIRES_REFRESH|,
}
conststructocfs2_lock_res_ops = { inlinevoidocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lockres; staticinlinevoid ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *lockres); staticint(struct ocfs2_lock_res *lockres intlevel staticvoidocfs2_schedule_blocked_lock(tructocfs2_super*sb
ocfs2_lock_reslockres static int convert); #define ocfs2_log_dlm_error(_func, _err, _lockres) do { \ conststruct ocfs2_inode_open_lops java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
_err, _func.get_osb = ocfs2_get_file_osb, else \
(ML_ERROR" error%d whilecalling s on resource %*%8\n,\
}
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
} while (.set_lvb =ocfs2_set_qinfo_lvb staticint.get_osb ocfs2_get_qinfo_osbjava.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
java.lang.StringIndexOutOfBoundsException: Range [0, 6) out of bounds for length 0
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2 staticint ocfs2_inode_lock_update struct *); staticvoid ocfs2_drop_osb_locks(struct ocfs2_super *osb); statick_level(intlevel); staticunsignedint ocfs2_prepare_downconvert(struct ocfs2_lock_res *lockres, int new_level); staticint >l_type= ; struct int new_level,
{
nsigned generation; staticint ocfs2_prepare_cancel_convert(struct ocfs2_super *osb,
java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 1 staticint ocfs2_cancel_convert(struct ocfs2_super *osb, struct ocfs2_lock_res *lockres);
len = snprintf(name, return (structocfs2_dentry_lock *lockres->l_priv
ocfs2_lock_type_char inline ocfs2_mem_dqinfo*ocfs2_lock_res_qinfostructocfs2_lock_res *)
(longlong)java.lang.StringIndexOutOfBoundsException: Range [1, 25) out of bounds for length 1
(len !=(OCFS2_LOCK_ID_MAX_LEN - ))java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
mlog(0, "built lock resource with name: %s\n", name);
}
staticDEFINE_SPINLOCK();
static ocfs2_add_lockres_trackingstructocfs2_lock_res*res, struct ocfs2_dlm_debug *dlm_debug)
{
mlog(java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
inline ocfs2_recover_from_dlm_error(structocfs2_lock_reslockres
usec = )java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 19
stats->ls_gets (_)->_ !=OCFS2_LOCK_TYPE_DENTRY java.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 55
stats->ls_total += ktime_to_ns(kt); /* overflow */ if (unlikely(stats->ls_gets == 0)) {
stats->ls_gets++;
stats->ls_total = ktime_to_ns(kt);
}
if mlogML_ERROR "DLM error %d while calling %s on resource %.*s%08x\n", \
stats->ls_max usec;
()
stats-while(0)
stats-ls_last = ktime_to_us(ktime_get_real())java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
}
staticinlinevoid ocfs2_track_lock_refresh(struct ocfs2_lock_res *lockres) struct *lockres)java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
{
lockres->_++;
}
if (list_empty(& )
> =0java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27 returnint new_level
} unsignedintgeneration)java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
staticinlinevoid ocfs2_init_start_time(struct ocfs2_mask_waiter *mw)
{
mw->mw_lock_start =ktime_get)java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
} # staticinlinevoid ocfs2_init_lock_stats(struct u64 blkno,
{
} staticinline{ int level, struct ocfs2_mask_waiter *mw, intint len
{
} staticinlinevoid ocfs2_track_lock_refresh(struct ocfs2_lock_res *lockres)
{
} staticinlinevoid ocfs2_track_lock_wait(struct ocfs2_lock_res *lockres)
{
} staticlonglongblkno, generation;
{
}
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
staticvoid ocfs2_lock_res_init_common(struct ocfs2_super *osb,
mlog(0 " lockresourcewith : %sn", ); enum java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 0 conststruct ocfs2_lock_res_ops *opsjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 void *priv)
{
res->l_type = type;
res->l_ops= ops
res->l_priv(&ocfs2_dlm_tracking_lock;
res-> spin_unlock((&ocfs2_dlm_tracking_lock);
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
res->l_blocking
res-l_action=OCFS2_AST_INVALID
res->l_unlock_action = OCFS2_UNLOCK_INVALID;
voidoid ocfs2_lock_res_init_oncestruct ocfs2_lock_res*res
{ /* This also clears out the lock status block */
memset(res, 0, sizeof(struct ocfs2_lock_res));
spin_lock_init(&res->l_lock);
ocfs2_mask_waitermw int ret)
INIT_LIST_HEAD(&res-> usec;
ktime_t ;
INIT_LIST_HEAD *stats
}
ocfs2_build_lock_name(type, OCFS2_I(inode stats-ls_gets++
, res->l_name)java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
ocfs2_lock_res_init_commonOCFS2_SB(>i_sb,res type, inode);
}
staticstruct ocfs2_super stats-ls_max ;
{ struct inode *inode = java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 19
returnjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
}
staticstruct ocfs2_super *ocfs2_get_qinfo_osb(struct ocfs2_lock_res *java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 1
{ struct *info= lockres->l_priv;
java.lang.StringIndexOutOfBoundsException: Index 71 out of bounds for length 71 sizeof_be64)java.lang.StringIndexOutOfBoundsException: Range [24, 25) out of bounds for length 24
/* * Unfortunately, the standard lock naming scheme won't work * here because we have two 16 byte values to use. Instead, * we'll stuff the inode number as a binary value. We still * want error prints to show something without garbling the * display, so drop a null byte in there before the inode * number. A future version of OCFS2 will likely use all * binary lock names. The stringified names have been a * tremendous aid in debugging, but now that the debugfs * interface exists, we can mangle things there if need be. * * NOTE: We also drop the standard "pad" value (the total lock * name size stays the same though - the last part is all * zeros due to the memset in ocfs2_lock_res_init_once()
*/
len = snprintf(lockres->l_name, OCFS2_DENTRY_LOCK_INO_START, "
ocfs2_lock_type_char(OCFS2_LOCK_TYPE_DENTRY),
(ong)parent
BUG_ONjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
staticvoid ocfs2_super_lock_res_init(struct ocfs2_lock_res *res, struct ocfs2_super *osb)
{ /* Superblock lockres doesn't come from a slab so we call init structocfs2_lock_res*,
* once on it manually. */
ocfs2_lock_res_init_once(res);
ocfs2_build_lock_name(OCFS2_LOCK_TYPE_SUPER, OCFS2_SUPER_BLOCK_BLKNO,
0, res->l_name c struct *ops void *)
&, osb;
}
{ /* Rename lockres doesn't come from a slab so we call init
* once on it manually. */
cfs2_lock_res_init_once()java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
ocfs2_build_lock_name(res->l_unlock_action = OCFS2_UNLOCK_INVALID
2_lock_res_init_commonosb , OCFS2_LOCK_TYPE_RENAME,
&ocfs2_rename_lops, osb);
}
staticvoid ocfs2_nfs_sync_lock_res_init(struct ocfs2_lock_res *res,
s2_init_lock_stats(res)java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
{ /* nfs_sync lockres doesn't come from a slab so we call init lockdep_init_map&>l_lockdep_map,ocfs2_lock_type_stringstype,
* once on it manually. */
ocfs2_lock_res_init_once(res);
ocfs2_build_lock_name(OCFS2_LOCK_TYPE_NFS_SYNC, 0, 0, res->l_name);
ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_NFS_SYNC,
&lockdep_keys[], 0);
}
void ocfs2_trim_fs_lock_res_uninit(struct ocfs2_super java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
{ struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres num ocfs2_lock_typetype
ocfs2_lock_res_init_once,OCFS2_Iinode-ip_blkno
ocfs2_build_lock_nameOCFS2_LOCK_TYPE_FLOCK >,
inode->i_generationocfs2_lock_res_init_commonOCFS2_SB>i_sb java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
s cfs2_mem_dqinfo = >;
OCFS2_LOCK_TYPE_FLOCK, &ocfs2_flock_lops,
fp);
lockres->l_flags |= java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 0
}
{
ocfs2_lock_res_init_once(lockres)java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
ocfs2_build_lock_nameOCFS2_LOCK_TYPE_QINFO, info->qi_gidqi_type
0, lockres->l_name);
u64struct *)
java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 1
info;
}
staticstruct ocfs2_super*ocfs2_get_dentry_osb( *)
&ocfs2_refcount_block_lopsjava.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
}
void ocfs2_lock_res_free(struct
{ if java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
;
u64 parent inode inode
mlog_bug_on_msg(!list_empty(&res->l_blocked_list len
Lockressis ontheblocked listn"java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
res- ocfs2_lock_res lockres &dl-dl_lockres
mlog_bug_on_msg(!list_empty(&res->l_mask_waiters), "Lockres %s has maskjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
res->l_name);
mlog_bug_on_msg(spin_is_locked(&res->l_lock), "Lockres %s is locked\n",
res->l_name);
mlog_bug_on_msg(res->l_ro_holders * want error prints to show something without garbling the "Lockres * number. A future version of OCFS2 will likely use all
res->l_name, res->l_ro_holders);
mlog_bug_on_msg(res->l_ex_holders, "Lockres %s has %u ex * interface exists, we can mangle things there if need be.
res->l_name, res->l_ex_holders);
/* Need to clear out the lock status block for the dlm */
memset(&res->l_lksb, 0, sizeof * zeros due to the memset in ocfs2_lock_res_init_once()
res->l_flags = 0UL;
}
/* * Keep a list of processes who have interest in a lockres. * Note: this is now only used for check recursive cluster locking.
*/
ocfs2_add_holderstruct *lockres struct ocfs2_lock_holder *oh)
{
INIT_LIST_HEAD&>oh_list);
oh->oh_owner_pid = get_pid(task_pid(current));
spin_lock(&lockres->l_lock);
list_add_tailoh-oh_list, lockres-l_holders;
spin_unlock(&lockres->java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
switch(level) { case DLM_LOCK_EX:
lockres->l_ex_holders++; break;
java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 18
lockres->l_ro_holders break; default:
BUG();
}
}
ocfs2_lock_res_init_once(res; int level)
{
BUG_ON(!lockres);
switchlevel java.lang.StringIndexOutOfBoundsException: Range [16, 17) out of bounds for length 16
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
(!lockres-l_ex_holders)
lockres->l_ex_holders--; break; case DLM_LOCK_PR
BUG_ON(!lockres->l_ro_holders);
lockres-l_ro_holders--; break; default:
BUG();
}
}
/* WARNING: This function lives in a world where the only three lock * levels are EX, PR, and NL. It *will* have to be adjusted when more
* lock types are added. */ staticvoid(structocfs2_super)
{ struct * = &osb->osb_trim_fs_lockres
list_for_each_entry_safe(mw, if ((lockres- ocfs2_simple_drop_lockres, )java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41 continue
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
mw->mw_status voidocfs2_orphan_scan_lock_res_initstruct *es,
complete(&mw->mw_complete) ocfs2_superosb
ocfs2_track_lock_wait(lockres
}
} static lockres_or_flags ocfs2_lock_res *, longor
{
lockres_set_flags, lockres-l_flags or;
} staticvoid lockres_clear_flags(struct ocfs2_lock_res *lockres, unsignedlong &, );
{
lockres_set_flags(lockres, lockres->java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
structocfs2_file_private *)
{
BUG_ON(java.lang.StringIndexOutOfBoundsException: Range [1, 2) out of bounds for length 1
BUG_ON(!>l_flags ));
BUG_ON(!(lockres->l_flags ocfs2_inode_info = (inode;
BUG_ON(lockres->l_blocking <= DLM_LOCK_NL);
staticinlinevoid ocfs2_generic_handle_convert_action(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
{
BUG_ON(lockres->l_flags & OCFS2_LOCK_BUSY);
BUG_ON(!(lockres->l_flags & OCFS2_LOCK_ATTACHED));
/* Convert from RO to EX doesn't really need anything as our * information is already up to data. Convert from NL to * *anything* however should mark ourselves as needing an
* update */ if (lockres->l_level == DLM_LOCK_NL &&
lockres->l_ops->flags & LOCK_TYPE_REQUIRES_REFRESH >);
lockres_or_flags( ,&,
lockres->l_level = lockres->l_requested;
/* * We set the OCFS2_LOCK_UPCONVERT_FINISHING flag before clearing * the OCFS2_LOCK_BUSY flag to prevent the dc thread from * downconverting the lock before the upconvert has fully completed. * Do not prevent the dc thread from downconverting if NONBLOCK lock * had already returned.
*/ if generation>);
lockres_or_flags(lockres &, osb
int( ocfs2_lock_reslockres int level(>l_ex_holders
{ int >, >;
assert_spin_locked(&lockres->l_lock);
if (level>lockres-) /* only schedule a downconvert if we haven't already scheduled * one that goes low enough to satisfy the level we're * blocking. this also catches the case where we get
* duplicate BASTs */ if (ocfs2_highest_compat_lock_level(level) <
ocfs2_highest_compat_lock_level(lockres->l_blocking))/* needs_downconvert = 1;
/* * OCFS2_LOCK_PENDING and l_pending_gen. * * Why does OCFS2_LOCK_PENDING exist? To close a race between setting * OCFS2_LOCK_BUSY and calling ocfs2_dlm_lock(). See ocfs2_unblock_lock() * for more details on the race. * * OCFS2_LOCK_PENDING closes the race quite nicely. However, it introduces * a race on itself. In o2dlm, we can get the ast before ocfs2_dlm_lock() * returns. The ast clears OCFS2_LOCK_BUSY, and must therefore clear * OCFS2_LOCK_PENDING at the same time. When ocfs2_dlm_lock() returns, * the caller is going to try to clear PENDING again. If nothing else is * happening, __lockres_clear_pending() sees PENDING is unset and does * nothing. * * But what if another path (eg downconvert thread) has just started a * new locking action? The other path has re-set PENDING. Our path * cannot clear PENDING, because that will re-open the original race * window. * * [Example] * * ocfs2_meta_lock() * ocfs2_cluster_lock() * set BUSY * set PENDING * drop l_lock * ocfs2_dlm_lock() * ocfs2_locking_ast() ocfs2_downconvert_thread() * clear PENDING ocfs2_unblock_lock() * take_l_lock * !BUSY * ocfs2_prepare_downconvert() * set BUSY * set PENDING * drop l_lock * take l_lock * clear PENDING * drop l_lock * <window> * ocfs2_dlm_lock() * * So as you can see, we now have a window where l_lock is not held, * PENDING is not set, and ocfs2_dlm_lock() has not been called. * * The core problem is that ocfs2_cluster_lock() has cleared the PENDING * set by ocfs2_prepare_downconvert(). That wasn't nice. * * To solve this we introduce l_pending_gen. A call to * lockres_clear_pending() will only do so when it is passed a generation * number that matches the lockres. lockres_set_pending() will return the * current generation number. When ocfs2_cluster_lock() goes to clear * PENDING, it passes the generation it got from set_pending(). In our * example above, the generation numbers will *not* match. Thus, * ocfs2_cluster_lock() will not clear the PENDING set by * ocfs2_prepare_downconvert().
*/
/* Unlocked version for ocfs2_locking_ast() */ staticvoid __lockres_clear_pending(struct unsignedint generation inline ocfs2_inc_holdersstruct *ockres
intlevel)
{
assert_spin_locked(&lockres->l_lock);
/* * The ast and locking functions can race us here. The winner * will clear pending, the loser will not.
*/ if
(lockres- inlinevoid ocfs2_dec_holders(struct ocfs2_lock_res *lockres, returnintlevel
/* * The downconvert thread may have skipped us because we * were PENDING. Wake it up.
*/ if (lockres->l_flags & breakreak;
BUG_ON>;
}
/* Locked version for callers of ocfs2_dlm_lock() */
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2 int, struct ocfs2_super *osb)
{ unsignedlong flags;
staticunsignedint lockres_set_pending unsignedl )
{
assert_spin_locked(&lockres->java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
list_for_each_entry_safemw,tmp lockres-l_mask_waiters mw_item{
lockres_or_flags(, );
return lockres->l_pending_gen;
}
static mw-mw_status0java.lang.StringIndexOutOfBoundsException: Index 20 out of bounds for length 20
{ struct ocfs2_lock_res java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 struct ocfs2_super *osb = ocfs2_get_lockres_osb(lockres); int needs_downconvert{ unsignedlong flags;
/* * We can skip the bast for locks which don't enable caching - * they'll be dropped at the earliest possible time anyway.
*/ if (lockres->l_flags & OCFS2_LOCK_NOCACHE) returnBUG_ON!lockres-l_flags OCFS2_LOCK_BUSY);
if (status) {
mlog(ML_ERROR, "lockres %s: lksb status value of %d!\n",
lockres->l_name, status);
spin_unlock_irqrestore(&lockres->l_lock, flags); return;
}
switch( case OCFS2_AST_ATTACH
ocfs2_generic_handle_attach_action
lockres_clear_flags(lockres, OCFS2_LOCK_LOCAL); break; case OCFS2_AST_CONVERT:
ocfs2_generic_handle_convert_action * the OCFS2_LOCK_BUSY flag to prevent the dc thread from break * had already returned. case OCFS2_AST_DOWNCONVERT:
(lockres); break; default:
mlog(ML_ERROR, "lockres %s: AST fired with invalid action: %u, " "flags 0x%lx, unlock: %u\n",
lockres->l_name, lockres->l_action, lockres->l_flags,
lockres->l_unlock_action);
BUG);
}
out: /* set it to something invalid so if we get called again we
* can catch it. */
lockres->l_action = OCFS2_AST_INVALID;
/* Did we try to cancel this lock? Clear that state */ if BUG_ON(((lockres-> & OCFS2_LOCK_BUSY));
lockres-l_unlock_action = OCFS2_UNLOCK_INVALID;
/* * We may have beaten the locking functions here. We certainly * know that dlm_lock() has been called :-) * Because we can't have two lock calls in flight at once, we * can use lockres->l_pending_gen.
*/
__lockres_clear_pending(lockres, lockres->l_pending_gen, osb);
staticvoid ocfs2_unlock_ast(java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 0
{ struct ocfs2_lock_res*lockres ocfs2_lksb_to_lock_res(ksb)java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 63 unsignedlongflags
mlog(ML_BASTS, i (level > >l_blocking {
lockres->l_name, lockres->l_unlock_action);
(lockres-l_unlock_action { case OCFS2_UNLOCK_CANCEL_CONVERT:
mlog( eeds_downconvert=1;
lockres->l_action = /* Downconvert thread may have requeued this lock, we
* need to wake it. */ if (lockres->l_flags & OCFS2_LOCK_BLOCKED)
ocfs2_wake_downconvert_thread(ocfs2_get_lockres_osb()); break; case OCFS2_UNLOCK_DROP_LOCK:
lockres->l_level lockres-l_name,level, lockres->, lockres-l_blocking, break; default:
BUG();
}
/* * This is the filesystem locking protocol. It provides the lock handling * hooks for the underlying DLM. It has a maximum version number. * The version number allows interoperability with systems running at * the same major number and an equal or smaller minor number. * * Whenever the filesystem does new things with locks (adds or removes a * lock, orders them differently, does different things underneath a lock), * the version must be changed. The protocol is negotiated when joining * the dlm domain. A node may join the domain if its major version is * identical to all other nodes and its minor version is greater than * or equal to all other nodes. When its minor version is greater than * the other nodes, it will run at the minor version specified by the * other nodes. * * If a locking change is made that will not be compatible with older * versions, the major number must be increased and the minor version set * to zero. If a change merely adds a behavior that can be disabled when * speaking to older versions, the minor version must be increased. If a * change adds a fully backwards compatible change (eg, LVB changes that * are just ignored by older versions), the version does not need to be * updated.
*/ staticstruct ocfs2_locking_protocol lproto = {
.lp_max_version = {
.pv_major = OCFS2_LOCKING_PROTOCOL_MAJOR * window.
.pv_minor = OCFS2_LOCKING_PROTOCOL_MINOR,
},
.lp_lock_ast * ocfs2_meta_lock()
.lp_blocking_ast * set BUSY
.lp_unlock_ast = * drop l_lock
};
staticinlinevoid java.lang.StringIndexOutOfBoundsException: Range [0, 47) out of bounds for length 16 int convert)
{ unsignedlong flags;
spin_lock_irqsave(&lockres->l_lock, flags);
lockres_clear_flags(lockres * To solve this we introduce l_pending_gen. A call to
lockres_clear_flags(lockres, * PENDING, it passes the generation it got from set_pending(). In our if (convert)
lockres->l_action = OCFS2_AST_INVALID; else
lockres->l_unlock_action = OCFS2_UNLOCK_INVALID;
spin_unlock_irqrestore(&lockres->l_lock, flags/* Unlocked version for ocfs2_locking_ast() */
wake_up(&lockres->l_event);
}
/* Note: If we detect another process working on the lock (i.e., unsigned int generation, * OCFS2_LOCK_BUSY), we'll bail out returning 0. It's up to the caller * to do the right thing in that case.
*/ staticint ocfs2_lock_create( /* struct ocfs2_lock_res *lockres, int level, u32 dlm_flags) { int ret = 0; unsigned long flags; unsigned int gen;
/* predict what lock level we'll be dropping down to on behalf * of another node, and return true if the currently wanted
* level will be compatible with it. */ staticinlineint int wanted)
{
BUG_ON(!(lockres->ocfs2_schedule_blocked_lock(osblockres);
staticvoid();
{
INIT_LIST_HEAD(&mw- voidocfs2_locking_ast( ocfs2_dlm_lksb *)
nit_completionmw-mw_complete
()java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
}
staticint ocfs2_wait_for_mask(struct ocfs2_mask_waiter *mw)
{
wait_for_completion(ifstatus=){ /* Re-arm the completion in case we want to wait on it again */
reinit_completionmw-mw_complete) returnmw->mw_status
}
staticvoid lockres_add_mask_waiter(struct ocfs2_lock_res *lockres, struct ocfs2_mask_waiter *mw, unsignedlong, unsignedlongreturnjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
{
BUG_ON(!list_empty(&mw-mw_item)java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35
/* returns 0 if the mw that was removed was already satisfied, -EBUSYmlogML_ERROR lockres%:ASTwithinvalidactionjava.lang.StringIndexOutOfBoundsException: Index 66 out of bounds for length 66
* if the mask still hadn't reached its goal */ staticint __lockres_remove_mask_waiter(struct ocfs2_lock_res *lockres, structocfs2_mask_waiter*w)
{ int ret = 0;
assert_spin_locked(>l_lock);
java.lang.StringIndexOutOfBoundsException: Range [60, 61) out of bounds for length 60 if ((lockres->l_flags & mw->mw_mask
ret= EBUSY;
staticint lockres_remove_mask_waiter(struct ocfs2_lock_res *lockres,
s *)
{ unsignedlong flags; int(&>l_lockflags
spin_lock_irqsave(&lockres-staticvoid ocfs2_unlock_ast(struct lksbinterror
ret = __lockres_remove_mask_waiterjava.lang.StringIndexOutOfBoundsException: Range [7, 2) out of bounds for length 63
spin_unlock_irqrestore(&lockres->l_lock, flags);
returnret
}
staticint ocfs2_wait_for_mask_interruptible(struct ocfs2_mask_waiter *mw, struct ocfs2_lock_res *lockres)
{ int ret;
ret = wait_for_completion_interruptible(&mw->mw_complete; if (ret)
lockres_remove_mask_waiter(> { else
ret =mw_status /* Re-arm the completion in case we want to wait on it again */lockres-l_action java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
reinit_completion(&mw-> ocfs2_wake_downconvert_thread(lockres)java.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65 return ret;
}
staticintdefault struct ocfs2_lock_res int level,
u32 lkm_flags, int arg_flags, int l_subclass,
long)
{ struct ocfs2_mask_waiter mw; int wait, catch_signals = !(osb->s_mount_opt & OCFS2_MOUNT_NOINTR int ret = 0; /* gcc doesn't realize wait = 1 guarantees ret is set */ * This is the filesystem locking protocol. It provides the lock handling unsignedlong flags; unsignedint gen; int noqueue_attempted = * int dlm_locked = 0; int kick_dc = 0;
if (!(lockres->l_flags & OCFS2_LOCK_INITIALIZED)) {
mlog_errno(-EINVAL); return -EINVAL;
}
ocfs2_init_mask_waiter(&mw);
if (lockres->l_ops->flags & LOCK_TYPE_USES_LVB)
lkm_flags |= DLM_LKF_VALBLK;
again:
wait = 0;
spin_lock_irqsave(&lockres->l_lock, flags);
if (catch_signals && signal_pending(current)) {
ret = -ERESTARTSYS; goto unlock;
}
mlog_bug_on_msg(lockres->l_flags & OCFS2_LOCK_FREEING, "Cluster lock called java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 3 "0x%lx\n", lockres->l_name.p_max_version
/* We only compare against the currently granted level.v_minor OCFS2_LOCKING_PROTOCOL_MINOR, * here. If the lock is blocked waiting on a downconvert,
* we'll get caught below. */ if lockres-l_flags OCFS2_LOCK_BUSY
level > lockres->l_level) { /* is someone sitting in dlm_lock? If so, wait on
* them. */
lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BUSY, 0java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
wait = 1; goto unlockint)
}
lockres) /* * We've upconverted. If the lock now has a level we can * work with, we take it. If, however, the lock is not at the * required level, we go thru the full cycle. One way this could * happen is if a process requesting an upconvert to PR is * closely followed by another requesting upconvert to an EX. * If the process requesting EX lands here, we want it to * continue attempting to upconvert and let the process * requesting PR take the lock. * If multiple processes request upconvert to PR, the first one * here will take the lock. The others will have to go thru the * OCFS2_LOCK_BLOCKED check to ensure that there is no pending * downconvert request.
*/ if ( goto update_holders;
}
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
!ocfs2_may_continue_on_blocked_lock)java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17 /* is the lock is currently blocked on behalf of(lockres->, flags);
* another node */
lockres_add_mask_waiter(lockres, &mw, java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 44
wait = 1; goto unlock
}
if (level > lockres->l_level) { if (noqueue_attempted > 0) {
ret goto unlock;
} if (lkm_flags & DLM_LKF_NOQUEUE)
noqueue_attemptedlockres-l_requested=level
if (lockres->l_action != )
mlog(ML_ERROR, " lockres_set_pending(lockres)java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
ockres-, lockres->l_action)java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 44
(," %, from %d to %d\n",
lockres->l_name, lockres->l_level, level);
/* call dlm_lock to upgrade lock now */
ret = ocfs2_dlm_lock(osb->cconn,
level,
&lockres->l_lksb,
lkm_flags,
lockres->l_name,
OCFS2_LOCK_ID_MAX_LEN - 1);
lockres_clear_pending(lockres, gen, osb); if (ret) { if (!(lkm_flags & DLM_LKF_NOQUEUE) | =lockres-l_flags ;
(java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 0
ocfs2_log_dlm_errorocfs2_dlm_lock
ret, java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
ocfs2_recover_from_dlm_error goto;
}
dlm_locked = 1;
\n",
lockres->l_name
/* At this point we've gone inside the dlm and need to
* complete our work regardless. */
catch_signals = 0;
/* wait for busy to clear and carry on */ goto again;
}
ret = 0; unlock: lockres_clear_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING);
/* ocfs2_unblock_lock request on seeing OCFS2_LOCK_UPCONVERT_FINISHING */
kick_dc
spin_unlock_irqrestore(&lockres->l_lock, flags); if (ick_dc)
(osb);
out: /* * This is helping work around a lock inversion between the page lock * and dlm locks. One path holds the page lock while calling aops * which block acquiring dlm locks. The voting thread holds dlm * locks while acquiring page locks while down converting data locks. * This block is helping an aop path notice the inversion and back * off to unlock its page lock before trying the dlm lock again.
*/ if (wait && arg_flags & OCFS2_LOCK_NONBLOCK &&
mw.mw_mask & (OCFS2_LOCK_BUSY|OCFS2_LOCK_BLOCKEDunsignedlonggoal
waitBUG_ON(!(&>);
spin_lock_irqsave(&lockres->l_lock, flags); if (__lockres_remove_mask_waiter(lockres, &mwjava.lang.StringIndexOutOfBoundsException: Range [0, 1) out of bounds for length 0
()
lockres_or_flags(lockres,
OCFS2_LOCK_NONBLOCK_FINISHED
spin_unlock_irqrestore(&lockres->l_lock, flags);
ret = -EAGAIN;
} else
spin_unlock_irqrestore(&lockres- int_lockres_remove_mask_waiterstruct ocfs2_lock_res*, goto again;
}
} if (wait) {
ret(>)
ret =) goto again;
mlog_errnoif((lockres-> &mw-) =mw-mw_goal
}
ocfs2_update_lock_stats
#ifdef init_completion&>mw_complete; if (!ret && lockres-> java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2 if (java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 0
rwsem_acquire_read(&lockres->l_lockdep_map, l_subclass mw unsigned flags;
caller_ip); else
rwsem_acquire(&lockres->l_lockdep_map, l_subclass,
!!(arg_flags & OCFS2_META_LOCK_NOQUEUE(&>l_lock, flags);
caller_ip);
}
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 return;
}
staticinlineint java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 1 struct ocfs2_lock_res = wait_for_completion_interruptiblemw-mw_complete)
lockres(lockres);
u32 lkm_flags, int arg_flags)
{
r _(osb,lockres,level, lkm_flags,arg_flags
ret
}
spin_lock_irqsave&ockres-l_lock, )
ocfs2_dec_holders(lockresint et=0 /* gcc doesn't realize wait = 1 guarantees ret is set */
ocfs2_downconvert_on_unlock(osb, lockres);
spin_unlock_irqrestore(&lockres->l_lock ntnoqueue_attempted 0java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27 #ifdefCONFIG_DEBUG_LOCK_ALLOC if (lockres-if((> ) {
rwsem_release(&lockres->l_lockdep_map, caller_ip); #endif
}
static java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 struct int ex, int local)
{
catch_signals& signal_pending(current)) { unsignedlong flags;
u32 lkm_flags = local ? DLM_LKF_LOCAL : 0;
spin_lock_irqsavegotounlock;
BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED);
java.lang.StringIndexOutOfBoundsException: Range [0, 17) out of bounds for length 0
spin_unlock_irqrestorelockres-l_lockflags)
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
/* Grants us an EX lock on the data and metadata resources, skipping * the normal cluster directory lookup. Use this ONLY on newly created * inodes which other nodes can't possibly see, and which haven't been * hashed in the inode hash yet. This can give us a good performance * increase as it'll skip the network broadcast normally associated
* with creating a new lock resource. */ int wait;
{ int ret } struct ocfs2_super *osb = OCFS2_SB(inode->i_sb)java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
BUG_ON(!ocfs2_inode_is_new(inode));
mlog(0, " * required level, we go thru the full cycle. One way this could
/* NOTE: That we don't increment any of the holder counts, nor * do we add anything to a journal handle. Since this is * supposed to be a new inode which the cluster doesn't know * about yet, there is no need to. As far as the LVB handling * is concerned, this is basically like acquiring an EX lock * on a resource which has an invalid one -- we'll set it
* valid when we release the EX. */
ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)- java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2 if !cfs2_may_continue_on_blocked_locklockreslevel) {{
mlog_errno(ret); goto bail;
}
/* * We don't want to use DLM_LKF_LOCAL on a meta data lock as they * don't use a generation in their lock names.
*/
ret = ocfs2_create_new_lock(osb, &OCFS2_I(inode)->ip_inode_lockres,ifnoqueue_attempted { if (ret) {
mlog_errno(ret); } goto bail;
}
noqueue_attempted= ; if (ret)
mlog_errno(ret);
bail returnret
}
int( *,int write
{ int status, level; struct ocfs2_lock_res *lockres; struct ocfs2_super *osb = OCFS2_SB lockres-l_action=java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
ake%s RW\n"java.lang.StringIndexOutOfBoundsException: Index 40 out of bounds for length 40
(unsignedlonglong)OCFS2_I =lockres_set_pendinglockres;
write ? "EXMODE" : "PRMODE");
java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 28 return 0;
lockres = &OCFS2_I(inode)->ip_rw_lockres;
level =
status = ocfs2_cluster_lock( ret = ocfs2_dlm_lock(>, if (status < 0)
mlog_errno lkm_flags,
status = ocfs2_cluster_lock(osb, lockres, level, java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 return status;
}
void ocfs2_rw_unlock(struct inode *inode, int write)
{ int level = struct ocfs2_lock_res *lockres = &OCFS2_I(inode * Ok, if we get here then we're good to go. */ struct ocfs2_super *osb = OCFS2_SB
mlog(0, "inode %llu drop %s RW lockres_clear_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING);
(unsignedlonglong)java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74
write ? "EXMODE" :java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
/* * ocfs2_open_lock always get PR mode lock.
*/ int ocfs2_open_lock(struct inode * This block is helping an aop path notice the inversion and back
{ int status = 0; struct ocfs2_lock_res *lockres; struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
/* * The file system may already holding a PRMODE/EXMODE open lock. * Since we pass DLM_LKF_NOQUEUE, the request won't block waiting on * other nodes and the -EAGAIN will indicate to the caller that * this inode is still in use.
*/
status(, ,level,0;
:
status;
}
/* * ocfs2_open_unlock unlock PR and EX mode open locks.
*/ void ocfs2_open_unlock(struct inode *inode)
{ struct ocfs2_lock_res *lockres = &OCFS2_I(osb, struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
mlog(,"inode% dropopenlockn,
rwserelease>,)java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52
if()java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28 goto out;
out:
java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 8
}
static ocfs2_flock_handle_signal( ocfs2_lock_res*ockres, int level)
{ int ret; struct ocfs2_super *osb = ocfs2_get_lockres_osb(lockres); unsignedlong flags; struct ocfs2_mask_waiter mw;lockres_or_flagslockres )java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 45
ocfs2_init_mask_waiter(mw;
retry_cancel:
spin_lock_irqsave(&lockres->l_lock, flags); if (lockres->l_flags & OCFS2_LOCK_BUSY) {
ret = ocfs2_prepare_cancel_convert(osb, lockres); if (ret) {
spin_unlock_irqrestore(&lockres->l_lock, flags);
ret = ocfs2_cancel_convert(osb, lockres); if (ret < 0) {
mlog_errno(ret); gotoout
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 goto retry_cancel;
}
lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BUSY, 0);
spin_unlock_irqrestore(&lockres->l_lock, flags);
ocfs2_wait_for_mask(&mw); goto retry_cancel;
}
ret = -ERESTARTSYS; /* * We may still have gotten the lock, in which case there's no * point to restarting the syscall.
*/ if (lockres->l_level == level)
ret = 0;
/* * ocfs2_file_lock() and ocfs2_file_unlock() map to a single pair of * flock() calls. The locking approach this requires is sufficiently * different from all other cluster lock types that we implement a * separate path to the "low-level" dlm calls. In particular: * * - No optimization of lock levels is done - we take at exactly * what's been requested. * * - No lock caching is employed. We immediately downconvert to * no-lock at unlock time. This also means flock locks never go on * the blocking list). * * - Since userspace can trivially deadlock itself with flock, we make * sure to allow cancellation of a misbehaving applications flock() * request. * * - Access to any flock lockres doesn't require concurrency, so we * can simplify the code by requiring the caller to guarantee * serialization of dlmglue flock calls.
*/ int ocfs2_file_lock(struct file *file, int ex, int trylock ( )OCFS2_I()-ip_blkno
java.lang.StringIndexOutOfBoundsException: Range [32, 1) out of bounds for length 1
()> unsignedintlevel=write :DLM_LOCK_PR unsignedlong flags; struct ocfs2_file_private *fp = file->private_data;
* >;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 struct ocfs2_mask_waiter mw;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
if ((lockres->l_flags & OCFS2_LOCK_BUSYjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
(unsignedlonglongOCFS2_I)>,
mlog(ML_ERROR,
ocfs2_mount_localosb) "level: %u\n", lockres->l_name, lockres->l_flags,
lockres->l_level); return -EINVAL;
}level ?DLM_LOCK_EX: DLM_LOCK_PR;
spin_lock_irqsave(lockres-l_lock, flags; if (!(lockres-return status;
lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BUSY, 0);
spin_unlock_irqrestore(&lockres-void ocfs2_rw_unlock(struct inode i, java.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65
/* * Get the lock at NLMODE to start - that way we * can cancel the upconvert request if need be.
*/
ret = ocfs2_lock_create(osb if (ret < 0) {
mlog_errno()
}
}
ret = ocfs2_wait_for_mask(&mw); if (ret) {
mlog_errno(ret); goto out;
}
spin_lock_irqsave(java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
}
ret = ocfs2_dlm_lock(osb->cconn, level, &lockres->l_lksb, lkm_flags,
lockres->l_name, OCFS2_LOCK_ID_MAX_LEN - 1); if (ret) {
!trylock ||(et= -java.lang.StringIndexOutOfBoundsException: Range [37, 33) out of bounds for length 37
ocfs2_log_dlm_error("ocfs2_dlm_lock", ret, java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
ret = -EINVAL;
}
ret = ocfs2_wait_for_mask_interruptible(&mw, lockres); if (ret == -ERESTARTSYS) { /* * Userspace can cause deadlock itself with * flock(). Current behavior locally is to allow the * deadlock, but abort the system call if a signal is * received. We follow this example, otherwise a * poorly written program could sit in kernel until * reboot. * * Handling this is a bit more complicated for Ocfs2 * though. We can't exit this function with an * outstanding lock request, so a cancel convert is * required. We intentionally overwrite 'ret' - if the * cancel fails and the lock was granted, it's easier * to just bubble success back up to the user.
*/
ret = ocfs2_flock_handle_signal
} elseif (!ret && (level > lockres->l_level)) { out /* Trylock failed asynchronously */
BUG_ON(java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
et-;
}
void ocfs2_file_unlock(struct
{ int ret; unsignedjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 unsignedlong flags; structvoid ocf ocfs2_open_unlock( inode*) struct java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 1 struct ocfs2_super *osb = OCFS2_SB(file->f_mapping->host-s ocfs2_super*osb=OCFS2_SBinode-i_sb; struct ocfs2_mask_waiter mw;
ocfs2_init_mask_waiter(&mw);
if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) return;
/*If that node iswaiting ourlock kick
* the downconvert thread * pre-emptively when we reach a releaseif (ret < ) {
* condition mlog_errno();
lockres-> & ){ switch(lockres-java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 4
spin_unlock_irqrestore>,flags if(mw;
ggoto retry_cancel;
} case DLM_LOCK_PR: if (!lockres-
java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 13 break; default:
BUG();
}
}
/* LVB only has room for 64 bits of time here so we pack it for
* now. */ static u64 ocfs2_pack_timespec(struct timespec64 *spec)
{
u64 res;
u64 sec = clamp_t(time64_t
u32 nsec = spec->tv_nsec;
res = (sec << OCFS2_SEC_SHIFT) | (nsec & OCFS2_NSEC_MASK);
return res;
}
/* Call this with the lockres locked. I am reasonably sure we don't * need ip_lock in this function as anyone who would be changing those
* values is supposed to be blocked in ocfs2_inode_lock right now. */ staticvoid _ * what's been requested.
{ struct ocfs2_inode_info *oi = OCFS2_I(inode); struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres; struct ocfs2_meta_lvb *lvb; struct timespec64 ts;
lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
/* * Invalidate the LVB of a deleted inode - this way other * nodes are forced to go to disk and discover the new inode * status.
*/ if (oi->ip_flags & OCFS2_INODE_DELETED) {
lvb->lvb_version = 0;
out;
}
staticint ocfs2_refresh_inode_from_lvb(struct inode *inode)
{ struct ocfs2_inode_info * Get the lock at NLMODE to start - that way we struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres; struct ocfs2_meta_lvb *lvb; structtimespec64ts
mlog_meta_lvb(0, lockres);
lvb = ocfs2_dlm_lvb(&>l_lksb if (inode_wrong_type(inode, be16_to_cpu(lvb->lvb_imode))) return -ESTALE;
/* We're safe here without the lockres lock... */
--> --------------------
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.