Hash lock protects only during .hs_put_locked.
Switch to atomic blocking_refs.
Whole policy structure was zeroed twice.
Once during enqueue and second time during resend or replay.
Policy structure should be initialized with default values
only in ldlm_lock_new().
Change-Id: Ib916f64cd03cfe812c86463b4354bf5a9bbcdd56
Seagate-bug-id: MRP-2536, MRP-2909
Signed-off-by: Andriy Skulysh <andriy.skulysh@seagate.com>
Reviewed-by: Alexander Boyko <alexander.boyko@seagate.com>
Reviewed-by: Vitaly Fertman <vitaly.fertman@seagate.com>
Signed-off-by: Ben Evans <bevans@cray.com>
Reviewed-on: http://review.whamcloud.com/21061
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Mike Pershin <mike.pershin@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
__u64 owner;
__u64 blocking_owner;
struct obd_export *blocking_export;
- /* Protected by the hash lock */
- __u32 blocking_refs;
+ atomic_t blocking_refs;
__u32 pid;
};
void ldlm_extent_policy_wire_to_local(const union ldlm_wire_policy_data *wpolicy,
union ldlm_policy_data *lpolicy)
{
- memset(lpolicy, 0, sizeof(*lpolicy));
lpolicy->l_extent.start = wpolicy->l_extent.start;
lpolicy->l_extent.end = wpolicy->l_extent.end;
lpolicy->l_extent.gid = wpolicy->l_extent.gid;
lock->l_policy_data.l_flock.owner;
req->l_policy_data.l_flock.blocking_export =
lock->l_export;
- req->l_policy_data.l_flock.blocking_refs = 0;
+ atomic_set(&req->l_policy_data.l_flock.blocking_refs, 0);
cfs_hash_add(req->l_export->exp_flock_hash,
&req->l_policy_data.l_flock.owner,
void ldlm_flock_policy_wire_to_local(const union ldlm_wire_policy_data *wpolicy,
union ldlm_policy_data *lpolicy)
{
- memset(lpolicy, 0, sizeof(*lpolicy));
lpolicy->l_flock.start = wpolicy->l_flock.lfw_start;
lpolicy->l_flock.end = wpolicy->l_flock.lfw_end;
lpolicy->l_flock.pid = wpolicy->l_flock.lfw_pid;
flock = &lock->l_policy_data.l_flock;
LASSERT(flock->blocking_export != NULL);
class_export_get(flock->blocking_export);
- flock->blocking_refs++;
+ atomic_inc(&flock->blocking_refs);
}
static void
struct ldlm_flock *flock;
lock = hlist_entry(hnode, struct ldlm_lock, l_exp_flock_hash);
- LDLM_LOCK_RELEASE(lock);
flock = &lock->l_policy_data.l_flock;
LASSERT(flock->blocking_export != NULL);
class_export_put(flock->blocking_export);
- if (--flock->blocking_refs == 0) {
+ if (atomic_dec_and_test(&flock->blocking_refs)) {
flock->blocking_owner = 0;
flock->blocking_export = NULL;
}
+ LDLM_LOCK_RELEASE(lock);
}
static struct cfs_hash_ops ldlm_export_flock_ops = {
void ldlm_ibits_policy_wire_to_local(const union ldlm_wire_policy_data *wpolicy,
union ldlm_policy_data *lpolicy)
{
- memset(lpolicy, 0, sizeof(*lpolicy));
lpolicy->l_inodebits.bits = wpolicy->l_inodebits.bits;
}
* without them. */
lock->l_flags |= ldlm_flags_from_wire(dlm_req->lock_flags &
LDLM_FL_INHERIT_MASK);
+
+ ldlm_convert_policy_to_local(req->rq_export,
+ dlm_req->lock_desc.l_resource.lr_type,
+ &dlm_req->lock_desc.l_policy_data,
+ &lock->l_policy_data);
+ if (dlm_req->lock_desc.l_resource.lr_type == LDLM_EXTENT)
+ lock->l_req_extent = lock->l_policy_data.l_extent;
+
existing_lock:
if (flags & LDLM_FL_HAS_INTENT) {
GOTO(out, rc);
}
- if (dlm_req->lock_desc.l_resource.lr_type != LDLM_PLAIN)
- ldlm_convert_policy_to_local(req->rq_export,
- dlm_req->lock_desc.l_resource.lr_type,
- &dlm_req->lock_desc.l_policy_data,
- &lock->l_policy_data);
- if (dlm_req->lock_desc.l_resource.lr_type == LDLM_EXTENT)
- lock->l_req_extent = lock->l_policy_data.l_extent;
-
err = ldlm_lock_enqueue(ns, &lock, cookie, &flags);
if (err) {
if ((int)err < 0)
#include <sys/vfs.h>
#include <sys/ioctl.h>
#include <sys/xattr.h>
+#include <sys/file.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
exit(save_errno);
}
break;
+ case 'j':
+ if (flock(fd, LOCK_EX) == -1)
+ errx(-1, "flock()");
+ break;
case 'K':
oldpath = POP_ARG();
if (oldpath == NULL)
}
run_test 131 "IO vs evict results to IO under staled lock"
+test_133() {
+ local list=$(comma_list $(mdts_nodes))
+
+ local t=$((TIMEOUT * 2))
+ touch $DIR/$tfile
+
+ flock $DIR/$tfile -c "echo bl lock;sleep $t;echo bl flock unlocked" &
+ sleep 1
+ multiop_bg_pause $DIR/$tfile O_jc || return 1
+ PID=$!
+
+ #define OBD_FAIL_LDLM_REPLY 0x30c
+ do_nodes $list $LCTL set_param fail_loc=0x8000030c
+ kill -USR1 $PID
+ echo "waiting for multiop $PID"
+ wait $PID || return 2
+
+ rm -f $DIR/$tfile
+
+ return 0
+}
+run_test 133 "don't fail on flock resend"
+
complete $SECONDS
check_and_cleanup_lustre
exit_status