"force_over_256tb",
"force_over_512tb",
"force_over_1024tb",
+ "resetoi",
NULL
};
strncat(options, opts, PAGE_SIZE);
{
struct lu_device *l = osd2lu_dev(o);
struct osd_thread_info *info;
- int rc;
int cplen = 0;
+ char *opts = NULL;
+ bool restored = false;
+ int rc;
/* if the module was re-loaded, env can loose its keys */
rc = lu_env_refill((struct lu_env *)env);
if (rc != 0)
GOTO(out_site, rc);
+ opts = lustre_cfg_string(cfg, 3);
+ if (opts && strstr(opts, "resetoi"))
+ restored = true;
+
INIT_LIST_HEAD(&o->od_ios_list);
/* setup scrub, including OI files initialization */
o->od_in_init = 1;
- rc = osd_scrub_setup(env, o);
+ rc = osd_scrub_setup(env, o, restored);
o->od_in_init = 0;
if (rc < 0)
GOTO(out_site, rc);
int osd_scrub_start(const struct lu_env *env, struct osd_device *dev,
__u32 flags);
void osd_scrub_stop(struct osd_device *dev);
-int osd_scrub_setup(const struct lu_env *env, struct osd_device *dev);
+int osd_scrub_setup(const struct lu_env *env, struct osd_device *dev,
+ bool restored);
void osd_scrub_cleanup(const struct lu_env *env, struct osd_device *dev);
int osd_oii_insert(struct osd_device *dev, const struct lu_fid *fid,
struct osd_inode_id *id, int insert);
}
if (restored) {
+ LCONSOLE_WARN("%s: reset Object Index mappings\n",
+ osd_dev2name(osd));
rc = osd_remove_ois(info, osd);
if (rc)
RETURN(rc);
static const char osd_scrub_name[] = "OI_scrub";
-int osd_scrub_setup(const struct lu_env *env, struct osd_device *dev)
+int osd_scrub_setup(const struct lu_env *env, struct osd_device *dev,
+ bool restored)
{
struct osd_thread_info *info = osd_oti_get(env);
struct lustre_scrub *scrub = &dev->od_scrub.os_scrub;
struct osd_inode_id *id = &info->oti_id;
struct dt_object *obj;
bool dirty = false;
- bool restored = false;
int rc = 0;
ENTRY;
static int osd_mount(const struct lu_env *env,
struct osd_device *o, struct lustre_cfg *cfg)
{
- char *mntdev = lustre_cfg_string(cfg, 1);
- char *str = lustre_cfg_string(cfg, 2);
- char *svname = lustre_cfg_string(cfg, 4);
+ char *mntdev = lustre_cfg_string(cfg, 1);
+ char *str = lustre_cfg_string(cfg, 2);
+ char *svname = lustre_cfg_string(cfg, 4);
dnode_t *rootdn;
- const char *opts;
- int rc;
+ const char *opts;
+ bool resetoi = false;
+ int rc;
+
ENTRY;
if (o->od_os != NULL)
if (rc >= sizeof(o->od_svname))
RETURN(-E2BIG);
+ opts = lustre_cfg_string(cfg, 3);
+
o->od_index_backup_stop = 0;
o->od_index = -1; /* -1 means index is invalid */
rc = server_name2index(o->od_svname, &o->od_index, NULL);
if (rc)
GOTO(err, rc);
+ if (opts && strstr(opts, "resetoi"))
+ resetoi = true;
+
o->od_in_init = 1;
- rc = osd_scrub_setup(env, o);
+ rc = osd_scrub_setup(env, o, resetoi);
o->od_in_init = 0;
if (rc)
GOTO(err, rc);
#endif
/* parse mount option "noacl", and enable ACL by default */
- opts = lustre_cfg_string(cfg, 3);
if (opts == NULL || strstr(opts, "noacl") == NULL)
o->od_posix_acl = 1;
uint64_t oid, dnode_t **dnp);
/* osd_oi.c */
-int osd_oi_init(const struct lu_env *env, struct osd_device *o);
+int osd_oi_init(const struct lu_env *env, struct osd_device *o, bool reset);
void osd_oi_fini(const struct lu_env *env, struct osd_device *o);
int osd_fid_lookup(const struct lu_env *env,
struct osd_device *, const struct lu_fid *, uint64_t *);
nvlist_t **sa);
/* osd_scrub.c */
-int osd_scrub_setup(const struct lu_env *env, struct osd_device *dev);
+int osd_scrub_setup(const struct lu_env *env, struct osd_device *dev,
+ bool resetoi);
void osd_scrub_cleanup(const struct lu_env *env, struct osd_device *dev);
int osd_scrub_start(const struct lu_env *env, struct osd_device *dev,
__u32 flags);
return rc;
}
+static int osd_oi_destroy(const struct lu_env *env, struct osd_device *o,
+ const char *name)
+{
+ struct osd_oi oi;
+ dmu_tx_t *tx;
+ dnode_t *rootdn;
+ uint64_t oid;
+ int rc;
+
+ ENTRY;
+
+ if (o->od_dt_dev.dd_rdonly)
+ RETURN(-EROFS);
+
+ rc = osd_oi_lookup(env, o, o->od_rootid, name, &oi);
+ if (rc == -ENOENT)
+ RETURN(0);
+ if (rc)
+ RETURN(rc);
+
+ oid = oi.oi_zapid;
+
+ rc = __osd_obj2dnode(o->od_os, o->od_rootid, &rootdn);
+ if (rc)
+ RETURN(rc);
+
+ tx = dmu_tx_create(o->od_os);
+ dmu_tx_mark_netfree(tx);
+ dmu_tx_hold_free(tx, oid, 0, DMU_OBJECT_END);
+ osd_tx_hold_zap(tx, oid, rootdn, FALSE, NULL);
+ rc = -dmu_tx_assign(tx, TXG_WAIT);
+ if (rc) {
+ dmu_tx_abort(tx);
+ GOTO(out, rc);
+ }
+
+ rc = -dmu_object_free(o->od_os, oid, tx);
+ if (rc) {
+ CERROR("%s: failed to free %s %llu: rc = %d\n",
+ o->od_svname, name, oid, rc);
+ GOTO(commit, rc);
+ }
+
+ rc = osd_zap_remove(o, o->od_rootid, rootdn, name, tx);
+ if (rc) {
+ CERROR("%s: zap_remove %s failed: rc = %d\n",
+ o->od_svname, name, rc);
+ GOTO(commit, rc);
+ }
+
+ EXIT;
+commit:
+ dmu_tx_commit(tx);
+out:
+ osd_dnode_rele(rootdn);
+
+ return rc;
+}
+
static int
osd_oi_find_or_create(const struct lu_env *env, struct osd_device *o,
uint64_t parent, const char *name, uint64_t *child)
/**
* Initialize the OIs by either opening or creating them as needed.
*/
-int osd_oi_init(const struct lu_env *env, struct osd_device *o)
+int osd_oi_init(const struct lu_env *env, struct osd_device *o, bool reset)
{
struct lustre_scrub *scrub = &o->od_scrub;
struct scrub_file *sf = &scrub->os_file;
GOTO(out, rc = count);
if (count > 0) {
- if (count == sf->sf_oi_count)
+ if (count == sf->sf_oi_count && !reset)
goto open;
if (sf->sf_oi_count == 0) {
if (rc)
GOTO(out, rc);
+ if (reset)
+ LCONSOLE_WARN("%s: reset Object Index mappings\n",
+ osd_name(o));
+
for (i = 0; i < count; i++) {
LASSERT(sizeof(osd_oti_get(env)->oti_buf) >= 32);
snprintf(key, sizeof(osd_oti_get(env)->oti_buf) - 1,
"%s.%d", DMU_OSD_OI_NAME_BASE, i);
+ if (reset) {
+ rc = osd_oi_destroy(env, o, key);
+ if (rc)
+ GOTO(out, rc);
+ }
rc = osd_oi_find_or_create(env, o, o->od_root, key, &sdb);
if (rc)
GOTO(out, rc);
static const char osd_scrub_name[] = "OI_scrub";
-int osd_scrub_setup(const struct lu_env *env, struct osd_device *dev)
+int osd_scrub_setup(const struct lu_env *env, struct osd_device *dev,
+ bool resetoi)
{
struct osd_thread_info *info = osd_oti_get(env);
struct lustre_scrub *scrub = &dev->od_scrub;
}
/* Initialize OI files. */
- rc = osd_oi_init(env, dev);
+ rc = osd_oi_init(env, dev, resetoi);
if (rc < 0)
GOTO(cleanup_obj, rc);
}
run_test 17b "ENOSPC on .. insertion shouldn't leak inodes"
+test_18() {
+ local n
+ local fids=()
+ local opts=$(csa_add "$MOUNT_OPTS_SCRUB" -o resetoi)
+
+ scrub_prep 10
+ scrub_start_mds 1 "$MOUNT_OPTS_SCRUB"
+ mount_client $MOUNT || error "(2) Fail to start client!"
+ for n in $(seq $MDSCOUNT); do
+ fids+=($($LFS path2fid $DIR/$tdir/mds$n/test-framework.sh))
+ done
+ cleanup_mount $MOUNT > /dev/null || error "(3) Fail to stop client!"
+ for n in $(seq $MDSCOUNT); do
+ stop mds$n > /dev/null || error "(4) Fail to stop MDS$n!"
+ done
+ scrub_start_mds 5 "$opts"
+ do_facet mds1 dmesg | grep "reset Object Index" ||
+ error "(6) reset log not found"
+ mount_client $MOUNT || error "(7) Fail to start client!"
+ scrub_check_data 7
+
+ local fid
+ local path
+ for n in $(seq $MDSCOUNT); do
+ path=$($LFS fid2path $DIR ${fids[$((n - 1))]})
+ [ "$path" == "$DIR/$tdir/mds$n/test-framework.sh" ] ||
+ error "path mismatch $path != $DIR/$tdir/mds$n/test-framework.sh"
+ fid=$($LFS path2fid $DIR/$tdir/mds$n/test-framework.sh)
+ [ "${fids[$((n - 1))]}" == "$fid" ] ||
+ error "$DIR/$tdir/mds$n/test-framework.sh FID mismatch ${fids[$((n - 1))]} != $fid"
+ done
+}
+run_test 18 "test mount -o resetoi to recreate OI files"
# restore MDS/OST size
MDSSIZE=${SAVED_MDSSIZE}