add CLOSE event into changelog, but not into the default mask.
do not create close changelog record sometimes, if a dup mfd handler appeared:
- open replay (1st mfd appears)
- re-connect
- open replay (2nd mfd appears)
Reviewed-by: Nathan Rutman <Nathan_Rutman@xyratex.com>
Reviewed-by: Alexey Lyashkov <alexey_lyashkov@xyratex.com>
Change-Id: I8e5ff99905b84ee58416406ca7b690c86db60c62
Signed-off-by: Vitaly Fertman <vitaly_fertman@xyratex.com>
Reviewed-on: http://review.whamcloud.com/1197
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Mikhail Pershin <tappro@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
}
static int cml_close(const struct lu_env *env, struct md_object *mo,
- struct md_attr *ma)
+ struct md_attr *ma, int mode)
{
int rc;
ENTRY;
- rc = mo_close(env, md_object_next(mo), ma);
+ rc = mo_close(env, md_object_next(mo), ma, mode);
RETURN(rc);
}
}
static int cmr_close(const struct lu_env *env, struct md_object *mo,
- struct md_attr *ma)
+ struct md_attr *ma, int mode)
{
return -EFAULT;
}
MDS_SOM = 1 << 4,
MDS_QUOTA_IGNORE = 1 << 5,
MDS_CLOSE_CLEANUP = 1 << 6,
- MDS_KEEP_ORPHAN = 1 << 7
+ MDS_KEEP_ORPHAN = 1 << 7,
+ MDS_RECOV_OPEN = 1 << 8,
};
/* instance of mdt_reint_rec */
/** bits covering all \a changelog_rec_type's */
#define CHANGELOG_ALLMASK 0XFFFFFFFF
/** default \a changelog_rec_type mask */
-#define CHANGELOG_DEFMASK CHANGELOG_ALLMASK & ~(1 << CL_ATIME)
+#define CHANGELOG_DEFMASK CHANGELOG_ALLMASK & ~(1 << CL_ATIME | 1 << CL_CLOSE)
/* changelog llog name, needed by client replicators */
#define CHANGELOG_CATALOG "changelog_catalog"
struct md_object *obj, int flag);
int (*moo_close)(const struct lu_env *env, struct md_object *obj,
- struct md_attr *ma);
+ struct md_attr *ma, int mode);
int (*moo_capa_get)(const struct lu_env *, struct md_object *,
struct lustre_capa *, int renewal);
static inline int mo_close(const struct lu_env *env,
struct md_object *m,
- struct md_attr *ma)
+ struct md_attr *ma,
+ int mode)
{
LASSERT(m->mo_ops->moo_close);
- return m->mo_ops->moo_close(env, m, ma);
+ return m->mo_ops->moo_close(env, m, ma, mode);
}
static inline int mo_readpage(const struct lu_env *env,
}
static int dot_lustre_mdd_close(const struct lu_env *env, struct md_object *obj,
- struct md_attr *ma)
+ struct md_attr *ma, int mode)
{
struct mdd_object *mdd_obj = md2mdd_obj(obj);
}
static int obf_mdd_close(const struct lu_env *env, struct md_object *obj,
- struct md_attr *ma)
+ struct md_attr *ma, int mode)
{
struct mdd_object *mdd_obj = md2mdd_obj(obj);
MDD_TXN_RENAME_TGT_OP,
MDD_TXN_CREATE_DATA_OP,
MDD_TXN_MKDIR_OP,
+ MDD_TXN_CLOSE_OP,
MDD_TXN_LAST_OP
};
{
const struct lu_fid *tfid = mdo2fid(mdd_obj);
struct llog_changelog_rec *rec;
+ struct thandle *th = NULL;
struct lu_buf *buf;
int reclen;
int rc;
if ((mdd->mdd_cl.mc_mask & (1 << type)) == 0)
RETURN(0);
- LASSERT(handle != NULL);
LASSERT(mdd_obj != NULL);
if ((type >= CL_MTIME) && (type <= CL_ATIME) &&
rec->cr.cr_namelen = 0;
mdd_obj->mod_cltime = cfs_time_current_64();
- rc = mdd_changelog_llog_write(mdd, rec, handle);
+ if (handle == NULL) {
+ /* Used for the close event only for now. */
+ LASSERT(type == CL_CLOSE);
+ LASSERT(mdd_env_info(env)->mti_param.tp_credits != 0);
+ th = mdd_trans_start(env, mdd);
+ if (IS_ERR(th))
+ GOTO(err, rc = PTR_ERR(th));
+ }
+
+ rc = mdd_changelog_llog_write(mdd, rec, handle ? : th);
+
+ if (th)
+ mdd_trans_stop(env, mdd, rc, th);
+err:
if (rc < 0) {
CERROR("changelog failed: rc=%d op%d t"DFID"\n",
rc, type, PFID(tfid));
* No permission check is needed.
*/
static int mdd_close(const struct lu_env *env, struct md_object *obj,
- struct md_attr *ma)
+ struct md_attr *ma, int mode)
{
struct mdd_object *mdd_obj = md2mdd_obj(obj);
struct mdd_device *mdd = mdo2mdd(obj);
if (mdd_obj->mod_count == 1 &&
(mdd_obj->mod_flags & (ORPHAN_OBJ | DEAD_OBJ)) != 0) {
again:
- rc = mdd_log_txn_param_build(env, obj, ma, MDD_TXN_UNLINK_OP, 0);
+ rc = mdd_log_txn_param_build(env, obj, ma,
+ MDD_TXN_UNLINK_OP, 1);
if (rc)
RETURN(rc);
handle = mdd_trans_start(env, mdo2mdd(obj));
ma->ma_valid &= ~(MA_LOV | MA_COOKIE);
mdd_write_unlock(env, mdd_obj);
+
+ if (rc == 0 &&
+ (mode & (FMODE_WRITE | MDS_OPEN_APPEND | MDS_OPEN_TRUNC)) &&
+ !(ma->ma_valid & MA_FLAGS && ma->ma_attr_flags & MDS_RECOV_OPEN)) {
+ if (handle == 0)
+ mdd_txn_param_build(env, mdd, MDD_TXN_CLOSE_OP, 1);
+ mdd_changelog_data_store(env, mdd, CL_CLOSE, mode,
+ mdd_obj, handle);
+ }
+
if (handle != NULL)
- mdd_trans_stop(env, mdo2mdd(obj), rc, handle);
+ mdd_trans_stop(env, mdd, rc, handle);
#ifdef HAVE_QUOTA_SUPPORT
if (quota_opc)
/* Trigger dqrel on the owner of child. If failed,
*c = 2 * dt[DTO_INDEX_INSERT] +
dt[DTO_OBJECT_CREATE];
break;
+ case MDD_TXN_CLOSE_OP:
+ *c = 0;
+ break;
default:
CERROR("Invalid op %d init its credit\n", op);
LBUG();
cfs_spin_unlock(&med->med_open_lock);
/* no attr update for that close */
la->la_valid = 0;
+ ma->ma_valid |= MA_FLAGS;
+ ma->ma_attr_flags |= MDS_RECOV_OPEN;
mdt_mfd_close(info, old_mfd);
+ ma->ma_attr_flags &= ~MDS_RECOV_OPEN;
+ ma->ma_valid &= ~MA_FLAGS;
}
CDEBUG(D_HA, "Store old cookie "LPX64" in new mfd\n",
info->mti_rr.rr_handle->cookie);
ma->ma_valid &= ~MA_INODE;
if (!MFD_CLOSED(mode))
- rc = mo_close(info->mti_env, next, ma);
+ rc = mo_close(info->mti_env, next, ma, mode);
if (ret == MDT_IOEPOCH_GETATTR || ret == MDT_IOEPOCH_OPENED) {
struct mdt_export_data *med;
error $*
fi
}
+
+changelog_chmask()
+{
+ MASK=$(do_facet $SINGLEMDS $LCTL get_param mdd.$MDT0.changelog_mask |\
+ grep -c $1)
+
+ if [ $MASK -eq 1 ]; then
+ do_facet $SINGLEMDS $LCTL set_param mdd.$MDT0.changelog_mask="-$1"
+ else
+ do_facet $SINGLEMDS $LCTL set_param mdd.$MDT0.changelog_mask="+$1"
+ fi
+}
+
test_160() {
remote_mds_nodsh && skip "remote MDS with nodsh" && return
- USER=$(do_facet $SINGLEMDS lctl --device $MDT0 changelog_register -n)
+ USER=$(do_facet $SINGLEMDS $LCTL --device $MDT0 changelog_register -n)
echo "Registered as changelog user $USER"
- do_facet $SINGLEMDS lctl get_param -n mdd.$MDT0.changelog_users | \
+ do_facet $SINGLEMDS $LCTL get_param -n mdd.$MDT0.changelog_users | \
grep -q $USER || error "User $USER not found in changelog_users"
# change something
$LFS changelog $MDT0 | tail -5
echo "verifying changelog mask"
- do_facet $SINGLEMDS lctl set_param mdd.$MDT0.changelog_mask="-mkdir"
- mkdir -p $DIR/$tdir/pics/2009/sofia
- do_facet $SINGLEMDS lctl set_param mdd.$MDT0.changelog_mask="+mkdir"
- mkdir $DIR/$tdir/pics/2009/zachary
- DIRS=$($LFS changelog $MDT0 | tail -5 | grep -c MKDIR)
- [ $DIRS -eq 1 ] || err17935 "changelog mask count $DIRS != 1"
+ changelog_chmask "MKDIR"
+ changelog_chmask "CLOSE"
+
+ mkdir -p $DIR/$tdir/pics/zach/sofia
+ echo "zzzzzz" > $DIR/$tdir/pics/zach/file
+
+ changelog_chmask "MKDIR"
+ changelog_chmask "CLOSE"
+
+ mkdir -p $DIR/$tdir/pics/2008/sofia
+ echo "zzzzzz" > $DIR/$tdir/pics/zach/file
+
+ $LFS changelog $MDT0
+ MKDIRS=$($LFS changelog $MDT0 | tail -5 | grep -c "MKDIR")
+ CLOSES=$($LFS changelog $MDT0 | tail -5 | grep -c "CLOSE")
+ [ $MKDIRS -eq 1 ] || err17935 "MKDIR changelog mask count $DIRS != 1"
+ [ $CLOSES -eq 1 ] || err17935 "CLOSE changelog mask count $DIRS != 1"
# verify contents
echo "verifying target fid"
[ "$fidc" == "p=$fidf" ] || \
err17935 "pfid in changelog $fidc != dir fid $fidf"
- USER_REC1=$(do_facet $SINGLEMDS lctl get_param -n \
+ USER_REC1=$(do_facet $SINGLEMDS $LCTL get_param -n \
mdd.$MDT0.changelog_users | grep $USER | awk '{print $2}')
$LFS changelog_clear $MDT0 $USER $(($USER_REC1 + 5))
- USER_REC2=$(do_facet $SINGLEMDS lctl get_param -n \
+ USER_REC2=$(do_facet $SINGLEMDS $LCTL get_param -n \
mdd.$MDT0.changelog_users | grep $USER | awk '{print $2}')
echo "verifying user clear: $(( $USER_REC1 + 5 )) == $USER_REC2"
[ $USER_REC2 == $(($USER_REC1 + 5)) ] || \
err17935 "user index should be $(($USER_REC1 + 5)); is $USER_REC2"
- MIN_REC=$(do_facet $SINGLEMDS lctl get_param mdd.$MDT0.changelog_users | \
+ MIN_REC=$(do_facet $SINGLEMDS $LCTL get_param mdd.$MDT0.changelog_users | \
awk 'min == "" || $2 < min {min = $2}; END {print min}')
FIRST_REC=$($LFS changelog $MDT0 | head -1 | awk '{print $1}')
echo "verifying min purge: $(( $MIN_REC + 1 )) == $FIRST_REC"
err17935 "first index should be $(($MIN_REC + 1)); is $FIRST_REC"
echo "verifying user deregister"
- do_facet $SINGLEMDS lctl --device $MDT0 changelog_deregister $USER
- do_facet $SINGLEMDS lctl get_param -n mdd.$MDT0.changelog_users | \
+ do_facet $SINGLEMDS $LCTL --device $MDT0 changelog_deregister $USER
+ do_facet $SINGLEMDS $LCTL get_param -n mdd.$MDT0.changelog_users | \
grep -q $USER && error "User $USER still found in changelog_users"
- USERS=$(( $(do_facet $SINGLEMDS lctl get_param -n \
+ USERS=$(( $(do_facet $SINGLEMDS $LCTL get_param -n \
mdd.$MDT0.changelog_users | wc -l) - 2 ))
if [ $USERS -eq 0 ]; then
- LAST_REC1=$(do_facet $SINGLEMDS lctl get_param -n \
+ LAST_REC1=$(do_facet $SINGLEMDS $LCTL get_param -n \
mdd.$MDT0.changelog_users | head -1 | awk '{print $3}')
touch $DIR/$tdir/chloe
- LAST_REC2=$(do_facet $SINGLEMDS lctl get_param -n \
+ LAST_REC2=$(do_facet $SINGLEMDS $LCTL get_param -n \
mdd.$MDT0.changelog_users | head -1 | awk '{print $3}')
echo "verify changelogs are off if we were the only user: $LAST_REC1 == $LAST_REC2"
[ $LAST_REC1 == $LAST_REC2 ] || error "changelogs not off"