enum changelog_rec_type type,
enum changelog_rec_flags clf_flags,
const struct lu_fid *fid,
+ const struct lu_fid *pfid,
const char *xattr_name,
struct thandle *handle);
rc2 = mdd_changelog_data_store_by_fid(env, mdd, CL_GETXATTR, 0,
mdd_object_fid(mdd_obj),
- name, handle);
+ NULL, name, handle);
stop:
rc2 = mdd_trans_stop(env, mdd, rc2, handle);
enum changelog_rec_type type,
enum changelog_rec_flags clf_flags,
const struct lu_fid *fid,
+ const struct lu_fid *pfid,
const char *xattr_name,
struct thandle *handle)
{
rec->cr.cr_flags = clf_flags;
rec->cr.cr_type = (__u32)type;
rec->cr.cr_tfid = *fid;
+ if (pfid)
+ rec->cr.cr_pfid = *pfid;
rec->cr.cr_namelen = 0;
if (clf_flags & CLF_JOBID)
* want the change to commit without the log entry.
* \param mdd_obj - mdd_object of change
* \param handle - transaction handle
+ * \param pfid - parent FID for CL_MTIME changelogs
*/
int mdd_changelog_data_store(const struct lu_env *env, struct mdd_device *mdd,
enum changelog_rec_type type,
enum changelog_rec_flags clf_flags,
- struct mdd_object *mdd_obj, struct thandle *handle)
+ struct mdd_object *mdd_obj, struct thandle *handle,
+ const struct lu_fid *pfid)
{
int rc;
}
rc = mdd_changelog_data_store_by_fid(env, mdd, type, clf_flags,
- mdd_object_fid(mdd_obj),
+ mdd_object_fid(mdd_obj), pfid,
NULL, handle);
if (rc == 0)
mdd_obj->mod_cltime = ktime_get();
}
rc = mdd_changelog_data_store_by_fid(env, mdd, type, clf_flags,
- mdd_object_fid(mdd_obj),
+ mdd_object_fid(mdd_obj), NULL,
xattr_name, handle);
if (rc == 0)
mdd_obj->mod_cltime = ktime_get();
GOTO(stop, rc);
rc = mdd_changelog_data_store_by_fid(env, mdd, type, clf_flags,
- fid, NULL, handle);
+ fid, NULL, NULL, handle);
stop:
rc = mdd_trans_stop(env, mdd, rc, handle);
* atime and ctime are independent.) */
static int mdd_attr_set_changelog(const struct lu_env *env,
struct md_object *obj, struct thandle *handle,
- __u64 valid)
+ const struct lu_fid *pfid, __u64 valid)
{
struct mdd_device *mdd = mdo2mdd(obj);
int bits, type = 0;
type = __ffs(bits);
/* XXX: we only store the low CLF_FLAGMASK bits of la_valid */
- return mdd_changelog_data_store(env, mdd, type, valid,
- md2mdd_obj(obj), handle);
+ return mdd_changelog_data_store(env, mdd, type, valid, md2mdd_obj(obj),
+ handle, pfid);
}
static int mdd_declare_attr_set(const struct lu_env *env,
out:
if (rc == 0)
- rc = mdd_attr_set_changelog(env, obj, handle,
+ rc = mdd_attr_set_changelog(env, obj, handle, &ma->ma_pfid,
la_copy->la_valid);
if (handle != NULL)
if (rc) /* wtf? */
GOTO(out_restore, rc);
- (void)mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, obj, handle);
- (void)mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, vic, handle);
+ (void)mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, obj, handle,
+ NULL);
+ (void)mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, vic, handle,
+ NULL);
EXIT;
out_restore:
if (rc)
GOTO(out_restore, rc);
- rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, obj, handle);
+ rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, obj, handle,
+ NULL);
if (rc)
GOTO(out, rc);
- rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, vic, handle);
+ rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, vic, handle,
+ NULL);
if (rc)
GOTO(out, rc);
EXIT;
/* Add a changelog record for release. */
hsm_set_cl_event(&clf_flags, HE_RELEASE);
rc = mdd_changelog_data_store(env, mdo2mdd(&o->mod_obj), CL_HSM,
- clf_flags, o, handle);
+ clf_flags, o, handle, NULL);
RETURN(rc);
}
GOTO(out_restore, rc);
/* Issue one changelog record per file */
- rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, fst_o, handle);
+ rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, fst_o, handle,
+ NULL);
if (rc)
GOTO(stop, rc);
- rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, snd_o, handle);
+ rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, snd_o, handle,
+ NULL);
if (rc)
GOTO(stop, rc);
EXIT;
if (rc)
RETURN(rc);
- rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, obj, handle);
+ rc = mdd_changelog_data_store(env, mdd, CL_LAYOUT, 0, obj, handle,
+ NULL);
RETURN(rc);
}
if (rc)
GOTO(out, rc);
- rc = mdd_changelog_data_store(env, mdd, CL_FLRW, 0, obj, handle);
+ rc = mdd_changelog_data_store(env, mdd, CL_FLRW, 0, obj, handle, NULL);
if (rc)
GOTO(out, rc);
GOTO(out, rc);
}
- rc = mdd_changelog_data_store(env, mdd, CL_RESYNC, 0, obj, handle);
+ rc = mdd_changelog_data_store(env, mdd, CL_RESYNC, 0, obj, handle,
+ NULL);
if (rc)
GOTO(out, rc);
EXIT;
/* FYI, only the bottom 32 bits of open_flags are recorded */
mdd_changelog_data_store(env, mdd, CL_CLOSE, open_flags,
- mdd_obj, handle);
+ mdd_obj, handle, NULL);
}
stop:
}
run_test 160k "Verify that changelog records are not lost"
+# Verifies that a file passed as a parameter has recently had an operation
+# performed on it that has generated an MTIME changelog which contains the
+# correct parent FID. As files might reside on a different MDT from the
+# parent directory in DNE configurations, the FIDs are translated to paths
+# before being compared, which should be identical
+compare_mtime_changelog() {
+ local file="${1}"
+ local mdtidx
+ local mtime
+ local cl_fid
+ local pdir
+ local dir
+
+ mdtidx=$($LFS getstripe --mdt-index $file)
+ mdtidx=$(printf "%04x" $mdtidx)
+
+ # Obtain the parent FID from the MTIME changelog
+ mtime=$($LFS changelog $FSNAME-MDT$mdtidx | tail -n 1 | grep MTIME)
+ [ -z "$mtime" ] && error "MTIME changelog not recorded"
+
+ cl_fid=$(sed -e 's/.* p=//' -e 's/ .*//' <<<$mtime)
+ [ -z "$cl_fid" ] && error "parent FID not present"
+
+ # Verify that the path for the parent FID is the same as the path for
+ # the test directory
+ pdir=$($LFS fid2path $MOUNT "$cl_fid")
+
+ dir=$(dirname $1)
+
+ [[ "${pdir%/}" == "$dir" ]] ||
+ error "MTIME changelog parent FID is wrong, expected $dir, got $pdir"
+}
+
+test_160l() {
+ [ $PARALLEL == "yes" ] && skip "skip parallel run"
+
+ remote_mds_nodsh && skip "remote MDS with nodsh"
+ [[ $MDS1_VERSION -ge $(version_code 2.13.55) ]] ||
+ skip "Need MDS version at least 2.13.55"
+
+ local cl_user
+
+ changelog_register || error "changelog_register failed"
+ cl_user="${CL_USERS[$SINGLEMDS]%% *}"
+
+ changelog_users $SINGLEMDS | grep -q $cl_user ||
+ error "User '$cl_user' not found in changelog_users"
+
+ # Clear some types so that MTIME changelogs are generated
+ changelog_chmask "-CREAT"
+ changelog_chmask "-CLOSE"
+
+ test_mkdir $DIR/$tdir || error "failed to mkdir $DIR/$tdir"
+
+ # Test CL_MTIME during setattr
+ touch $DIR/$tdir/$tfile
+ compare_mtime_changelog $DIR/$tdir/$tfile
+
+ # Test CL_MTIME during close
+ dd if=/dev/urandom of=$DIR/$tdir/${tfile}_2 bs=1M count=64 ||
+ error "cannot create file $DIR/$tdir/${tfile}_2"
+ compare_mtime_changelog $DIR/$tdir/${tfile}_2
+}
+run_test 160l "Verify that MTIME changelog records contain the parent FID"
+
test_161a() {
[ $PARALLEL == "yes" ] && skip "skip parallel run"