mdd->mdd_txn_cb.dtc_txn_stop = mdd_txn_stop_cb;
mdd->mdd_txn_cb.dtc_txn_commit = mdd_txn_commit_cb;
mdd->mdd_txn_cb.dtc_cookie = mdd;
+ mdd->mdd_txn_cb.dtc_tag = LCT_MD_THREAD;
CFS_INIT_LIST_HEAD(&mdd->mdd_txn_cb.dtc_linkage);
mdd->mdd_atime_diff = MAX_ATIME_DIFF;
ENTRY;
mdd_changelog_fini(env, m);
dt_txn_callback_del(m->mdd_child, &m->mdd_txn_cb);
- mdd_object_put(env, m->mdd_dot_lustre_objs.mdd_obf);
- mdd_object_put(env, m->mdd_dot_lustre);
+ if (m->mdd_dot_lustre_objs.mdd_obf)
+ mdd_object_put(env, m->mdd_dot_lustre_objs.mdd_obf);
+ if (m->mdd_dot_lustre)
+ mdd_object_put(env, m->mdd_dot_lustre);
if (m->mdd_obd_dev)
mdd_fini_obd(env, m, cfg);
orph_index_fini(env, m);
CERROR("changelog init failed: %d\n", rc);
return rc;
}
- CDEBUG(D_INODE, "changelog starting index="LPU64"\n",
+ CDEBUG(D_IOCTL, "changelog starting index="LPU64"\n",
mdd->mdd_cl.mc_index);
/* Find last changelog user id */
CERROR("changelog user init failed: %d\n", rc);
return rc;
}
- return 0;
+
+ /* If we have registered users, assume we want changelogs on */
+ if (mdd->mdd_cl.mc_lastuser > 0)
+ rc = mdd_changelog_on(mdd, 1);
+
+ return rc;
}
static int mdd_changelog_init(const struct lu_env *env, struct mdd_device *mdd)
mdd->mdd_cl.mc_flags = 0;
}
+/* Start / stop recording */
+int mdd_changelog_on(struct mdd_device *mdd, int on)
+{
+ int rc = 0;
+
+ if ((on == 1) && ((mdd->mdd_cl.mc_flags & CLM_ON) == 0)) {
+ LCONSOLE_INFO("%s: changelog on\n", mdd2obd_dev(mdd)->obd_name);
+ if (mdd->mdd_cl.mc_flags & CLM_ERR) {
+ CERROR("Changelogs cannot be enabled due to error "
+ "condition (see %s log).\n",
+ mdd2obd_dev(mdd)->obd_name);
+ rc = -ESRCH;
+ } else {
+ spin_lock(&mdd->mdd_cl.mc_lock);
+ mdd->mdd_cl.mc_flags |= CLM_ON;
+ spin_unlock(&mdd->mdd_cl.mc_lock);
+ rc = mdd_changelog_write_header(mdd, CLM_START);
+ }
+ } else if ((on == 0) && ((mdd->mdd_cl.mc_flags & CLM_ON) == CLM_ON)) {
+ LCONSOLE_INFO("%s: changelog off\n",mdd2obd_dev(mdd)->obd_name);
+ rc = mdd_changelog_write_header(mdd, CLM_FINI);
+ spin_lock(&mdd->mdd_cl.mc_lock);
+ mdd->mdd_cl.mc_flags &= ~CLM_ON;
+ spin_unlock(&mdd->mdd_cl.mc_lock);
+ }
+ return rc;
+}
+
/** Add a changelog entry \a rec to the changelog llog
* \param mdd
* \param rec
memcpy(fid, &LU_DOT_LUSTRE_FID, sizeof(struct lu_fid));
mdo = llo_store_create_index(env, &m->mdd_md_dev, m->mdd_child,
- mdd_root_dir_name, mdd_dot_lustre_name,
+ mdd_root_dir_name, dot_lustre_name,
fid, &dt_directory_features);
/* .lustre dir may be already present */
if (IS_ERR(mdo) && PTR_ERR(mdo) != -EEXIST) {
rc = PTR_ERR(mdo);
CERROR("creating obj [%s] fid = "DFID" rc = %d\n",
- mdd_dot_lustre_name, PFID(fid), rc);
+ dot_lustre_name, PFID(fid), rc);
RETURN(rc);
}
return 0;
}
+static int dot_lustre_xattr_list(const struct lu_env *env,
+ struct md_object *obj, struct lu_buf *buf)
+{
+ return -EPERM;
+}
+
static int dot_lustre_mdd_open(const struct lu_env *env, struct md_object *obj,
int flags)
{
return 0;
}
+static dt_obj_version_t dot_lustre_version_get(const struct lu_env *env,
+ struct md_object *obj)
+{
+ return 0;
+}
+
+static void dot_lustre_version_set(const struct lu_env *env,
+ struct md_object *obj,
+ dt_obj_version_t version)
+{
+ return;
+}
+
+
static struct md_object_operations mdd_dot_lustre_obj_ops = {
.moo_attr_get = dot_lustre_attr_get,
.moo_attr_set = dot_lustre_attr_set,
.moo_xattr_get = dot_lustre_xattr_get,
+ .moo_xattr_list = dot_lustre_xattr_list,
.moo_open = dot_lustre_mdd_open,
.moo_close = dot_lustre_close,
.moo_readpage = mdd_readpage,
+ .moo_version_get = dot_lustre_version_get,
+ .moo_version_set = dot_lustre_version_set,
.moo_path = dot_lustre_path
};
while (*name == '[')
name++;
- sscanf(name, SFID, &(f->f_seq), &(f->f_oid),
- &(f->f_ver));
+ sscanf(name, SFID, RFID(f));
if (!fid_is_sane(f)) {
CWARN("bad FID format [%s], should be "DFID"\n", lname->ln_name,
(__u64)1, 2, 0);
return rc;
dt_dot_lustre = dt_store_open(env, m->mdd_child, mdd_root_dir_name,
- mdd_dot_lustre_name, fid);
+ dot_lustre_name, fid);
if (IS_ERR(dt_dot_lustre)) {
rc = PTR_ERR(dt_dot_lustre);
GOTO(out, rc);
struct md_device *m,
struct lustre_capa_key *key)
{
+ struct mds_capa_info info = { .uuid = NULL, .capa = key };
struct mdd_device *mdd = lu2mdd_dev(&m->md_lu_dev);
struct obd_export *lov_exp = mdd2obd_dev(mdd)->u.mds.mds_osc_exp;
int rc;
ENTRY;
rc = obd_set_info_async(lov_exp, sizeof(KEY_CAPA_KEY), KEY_CAPA_KEY,
- sizeof(*key), key, NULL);
+ sizeof(info), &info, NULL);
RETURN(rc);
}
RETURN(-ENOMEM);
}
+ /* Assume we want it on since somebody registered */
+ rc = mdd_changelog_on(mdd, 1);
+ if (rc)
+ GOTO(out, rc);
+
rec->cur_hdr.lrh_len = sizeof(*rec);
rec->cur_hdr.lrh_type = CHANGELOG_USER_REC;
- rec->cur_endrec = 0ULL;
spin_lock(&mdd->mdd_cl.mc_user_lock);
if (mdd->mdd_cl.mc_lastuser == (unsigned int)(-1)) {
spin_unlock(&mdd->mdd_cl.mc_user_lock);
GOTO(out, rc = -EOVERFLOW);
}
*id = rec->cur_id = ++mdd->mdd_cl.mc_lastuser;
+ rec->cur_endrec = mdd->mdd_cl.mc_index;
spin_unlock(&mdd->mdd_cl.mc_user_lock);
+
rc = llog_add(ctxt, &rec->cur_hdr, NULL, NULL, 0);
- CDEBUG(D_INODE, "Registered changelog user %d\n", *id);
+ CDEBUG(D_IOCTL, "Registered changelog user %d\n", *id);
out:
OBD_FREE_PTR(rec);
llog_ctxt_put(ctxt);
__u64 mcud_minrec; /**< lowest changelog recno still referenced */
__u32 mcud_id;
__u32 mcud_minid; /**< user id with lowest rec reference */
+ __u32 mcud_usercount;
int mcud_found:1;
};
+#define MCUD_UNREGISTER -1LL
/** Two things:
* 1. Find the smallest record everyone is willing to purge
rec = (struct llog_changelog_user_rec *)hdr;
- /* If we have a new endrec for this id, use it for the min check */
+ mcud->mcud_usercount++;
+
+ /* If we have a new endrec for this id, use it for the following
+ min check instead of its old value */
if (rec->cur_id == mcud->mcud_id)
rec->cur_endrec = max(rec->cur_endrec, mcud->mcud_endrec);
/* Update this user's record */
mcud->mcud_found = 1;
- /* Special case: unregister this user if endrec == -1 */
- if (mcud->mcud_endrec == -1) {
+ /* Special case: unregister this user */
+ if (mcud->mcud_endrec == MCUD_UNREGISTER) {
struct llog_cookie cookie;
cookie.lgc_lgl = llh->lgh_id;
cookie.lgc_index = hdr->lrh_index;
rc = llog_cat_cancel_records(llh->u.phd.phd_cat_handle,
1, &cookie);
+ if (rc == 0)
+ mcud->mcud_usercount--;
RETURN(rc);
}
CDEBUG(D_IOCTL, "Purge request: id=%d, endrec="LPD64"\n", id, endrec);
+ data.mcud_id = id;
+ data.mcud_minid = 0;
+ data.mcud_minrec = 0;
+ data.mcud_usercount = 0;
+ data.mcud_endrec = endrec;
+ spin_lock(&mdd->mdd_cl.mc_lock);
+ endrec = mdd->mdd_cl.mc_index;
+ spin_unlock(&mdd->mdd_cl.mc_lock);
+ if ((data.mcud_endrec == 0) ||
+ ((data.mcud_endrec > endrec) &&
+ (data.mcud_endrec != MCUD_UNREGISTER)))
+ data.mcud_endrec = endrec;
+
ctxt = llog_get_context(mdd2obd_dev(mdd),LLOG_CHANGELOG_USER_ORIG_CTXT);
if (ctxt == NULL)
return -ENXIO;
LASSERT(ctxt->loc_handle->lgh_hdr->llh_flags & LLOG_F_IS_CAT);
- data.mcud_id = id;
- data.mcud_endrec = endrec;
- data.mcud_minid = 0;
- data.mcud_minrec = 0;
rc = llog_cat_process(ctxt->loc_handle, mdd_changelog_user_purge_cb,
(void *)&data, 0, 0);
if ((rc >= 0) && (data.mcud_minrec > 0)) {
- CDEBUG(D_INODE, "Purging CL entries up to "LPD64
+ CDEBUG(D_IOCTL, "Purging changelog entries up to "LPD64
", referenced by "CHANGELOG_USER_PREFIX"%d\n",
data.mcud_minrec, data.mcud_minid);
rc = mdd_changelog_llog_cancel(mdd, data.mcud_minrec);
rc);
}
+ llog_ctxt_put(ctxt);
+
if (!data.mcud_found) {
CWARN("No entry for user %d. Last changelog reference is "
LPD64" by changelog user %d\n", data.mcud_id,
rc = -ENOENT;
}
- llog_ctxt_put(ctxt);
+ if (!rc && data.mcud_usercount == 0)
+ /* No more users; turn changelogs off */
+ rc = mdd_changelog_on(mdd, 0);
+
RETURN (rc);
}
/** mdd_iocontrol
* May be called remotely from mdt_iocontrol_handle or locally from
- * mdt_iocontrol. Data may be freeform - remote handling doesn't enforce or
- * swab an obd_ioctl_data format (but local ioctl handler does).
+ * mdt_iocontrol. Data may be freeform - remote handling doesn't enforce
+ * an obd_ioctl_data format (but local ioctl handler does).
* \param cmd - ioc
* \param len - data len
* \param karg - ioctl data, in kernel space
/* Doesn't use obd_ioctl_data */
if (cmd == OBD_IOC_CHANGELOG_CLEAR) {
struct changelog_setinfo *cs = karg;
- if (len != sizeof(*cs)) {
- CERROR("Bad changelog_clear ioctl size %d\n", len);
- RETURN(-EINVAL);
- }
rc = mdd_changelog_user_purge(mdd, cs->cs_id, cs->cs_recno);
RETURN(rc);
}
rc = mdd_changelog_user_register(mdd, &data->ioc_u32_1);
break;
case OBD_IOC_CHANGELOG_DEREG:
- rc = mdd_changelog_user_purge(mdd, data->ioc_u32_1, -1);
+ rc = mdd_changelog_user_purge(mdd, data->ioc_u32_1,
+ MCUD_UNREGISTER);
break;
default:
rc = -EOPNOTSUPP;