/* The time for next checkpoint, seconds */
time64_t os_time_next_checkpoint;
+ /* How long to wait to start scrubbing */
+ time64_t os_auto_scrub_interval;
+
/* How many objects have been checked since last checkpoint. */
__u64 os_new_checked;
__u64 os_pos_current;
void scrub_file_reset(struct lustre_scrub *scrub, uuid_t uuid, u64 flags);
int scrub_file_load(const struct lu_env *env, struct lustre_scrub *scrub);
int scrub_file_store(const struct lu_env *env, struct lustre_scrub *scrub);
+bool scrub_needs_check(struct lustre_scrub *scrub, const struct lu_fid *fid,
+ u64 index);
int scrub_checkpoint(const struct lu_env *env, struct lustre_scrub *scrub);
int scrub_thread_prep(const struct lu_env *env, struct lustre_scrub *scrub,
uuid_t uuid, u64 start);
}
EXPORT_SYMBOL(scrub_file_store);
+bool scrub_needs_check(struct lustre_scrub *scrub, const struct lu_fid *fid,
+ u64 index)
+{
+ bool check = true;
+
+ if (!fid_is_norm(fid) && !fid_is_igif(fid))
+ check = false;
+ else if (scrub->os_running && scrub->os_pos_current > index)
+ check = false;
+ else if (scrub->os_auto_scrub_interval == AS_NEVER)
+ check = false;
+ else if (ktime_get_real_seconds() <
+ scrub->os_file.sf_time_last_complete +
+ scrub->os_auto_scrub_interval)
+ check = false;
+
+ return check;
+}
+EXPORT_SYMBOL(scrub_needs_check);
+
int scrub_checkpoint(const struct lu_env *env, struct lustre_scrub *scrub)
{
struct scrub_file *sf = &scrub->os_file;
goto found;
}
- if (dev->od_auto_scrub_interval == AS_NEVER) {
+ if (dev->od_scrub.os_scrub.os_auto_scrub_interval == AS_NEVER) {
if (!remote)
GOTO(out, result = -EREMCHG);
}
static int
-osd_consistency_check(struct osd_thread_info *oti, struct osd_device *dev,
- const struct lu_fid *fid, struct osd_inode_id *id)
+osd_ldiskfs_consistency_check(struct osd_thread_info *oti,
+ struct osd_device *dev,
+ const struct lu_fid *fid,
+ struct osd_inode_id *id)
{
struct lustre_scrub *scrub = &dev->od_scrub.os_scrub;
struct inode *inode = NULL;
int rc;
ENTRY;
-
- if (!fid_is_norm(fid) && !fid_is_igif(fid))
- RETURN(0);
-
- if (scrub->os_running && scrub->os_pos_current > id->oii_ino)
+ if (!scrub_needs_check(scrub, fid, id->oii_ino))
RETURN(0);
-
- if (dev->od_auto_scrub_interval == AS_NEVER ||
- ktime_get_real_seconds() <
- scrub->os_file.sf_time_last_complete + dev->od_auto_scrub_interval)
- RETURN(0);
-
again:
rc = osd_oi_lookup(oti, dev, fid, &oti->oti_id, 0);
if (rc == -ENOENT) {
GOTO(out, rc);
}
- if (dev->od_auto_scrub_interval != AS_NEVER && ++once == 1) {
+ if (dev->od_scrub.os_scrub.os_auto_scrub_interval != AS_NEVER &&
+ ++once == 1) {
rc = osd_scrub_start(oti->oti_env, dev, SS_AUTO_PARTIAL |
SS_CLEAR_DRYRUN | SS_CLEAR_FAILOUT);
CDEBUG_LIMIT(D_LFSCK | D_CONSOLE | D_WARNING,
if (rc != 0 || osd_remote_fid(env, dev, fid))
GOTO(out, rc);
- rc = osd_consistency_check(oti, dev, fid, id);
+ rc = osd_ldiskfs_consistency_check(oti, dev, fid, id);
if (rc != -ENOENT) {
/* Other error should not affect lookup result. */
rc = 0;
}
if (lmd_flags & LMD_FLG_NOSCRUB)
- o->od_auto_scrub_interval = AS_NEVER;
+ o->od_scrub.os_scrub.os_auto_scrub_interval = AS_NEVER;
if (blk_queue_nonrot(bdev_get_queue(osd_sb(o)->s_bdev))) {
/* do not use pagecache with flash-backed storage */
o->od_readcache_max_filesize = OSD_MAX_CACHE_SIZE;
o->od_readcache_max_iosize = OSD_READCACHE_MAX_IO_MB << 20;
o->od_writethrough_max_iosize = OSD_WRITECACHE_MAX_IO_MB << 20;
- o->od_auto_scrub_interval = AS_DEFAULT;
+ o->od_scrub.os_scrub.os_auto_scrub_interval = AS_DEFAULT;
/* default fallocate to unwritten extents: LU-14326/LU-14333 */
o->od_fallocate_zero_blocks = 0;
od_nonrotational:1;
- __s64 od_auto_scrub_interval;
__u32 od_dirent_journal;
int od_index;
struct proc_dir_entry *od_proc_entry;
if (unlikely(!dev->od_mnt))
return -EINPROGRESS;
- return sprintf(buf, "%lld\n", dev->od_auto_scrub_interval);
+ return scnprintf(buf, PAGE_SIZE, "%lld\n",
+ dev->od_scrub.os_scrub.os_auto_scrub_interval);
}
static ssize_t auto_scrub_store(struct kobject *kobj, struct attribute *attr,
if (rc)
return rc;
- dev->od_auto_scrub_interval = val;
+ dev->od_scrub.os_scrub.os_auto_scrub_interval = val;
return count;
}
LUSTRE_RW_ATTR(auto_scrub);
struct osd_thread_info *info = osd_oti_get(env);
struct lustre_scrub *scrub = &dev->od_scrub.os_scrub;
struct lvfs_run_ctxt *ctxt = &dev->od_scrub.os_ctxt;
+ time64_t interval = scrub->os_auto_scrub_interval;
struct scrub_file *sf = &scrub->os_file;
struct super_block *sb = osd_sb(dev);
struct lvfs_run_ctxt saved;
spin_lock_init(&scrub->os_lock);
INIT_LIST_HEAD(&scrub->os_inconsistent_items);
scrub->os_name = osd_name(dev);
+ scrub->os_auto_scrub_interval = interval;
push_ctxt(&saved, ctxt);
filp = filp_open(osd_scrub_name, O_RDWR |
dev->od_igif_inoi = 1;
if (!dev->od_dt_dev.dd_rdonly &&
- dev->od_auto_scrub_interval != AS_NEVER &&
+ dev->od_scrub.os_scrub.os_auto_scrub_interval != AS_NEVER &&
((sf->sf_status == SS_PAUSED) ||
(sf->sf_status == SS_CRASHED &&
sf->sf_flags & (SF_RECREATED | SF_INCONSISTENT |
char *mntdev = lustre_cfg_string(cfg, 1);
char *str = lustre_cfg_string(cfg, 2);
char *svname = lustre_cfg_string(cfg, 4);
+ time64_t interval = AS_DEFAULT;
dnode_t *rootdn;
const char *opts;
bool resetoi = false;
}
if (flags & LMD_FLG_NOSCRUB)
- o->od_auto_scrub_interval = AS_NEVER;
+ interval = AS_NEVER;
}
if (server_name_is_ost(o->od_svname))
resetoi = true;
o->od_in_init = 1;
- rc = osd_scrub_setup(env, o, resetoi);
+ rc = osd_scrub_setup(env, o, interval, resetoi);
o->od_in_init = 0;
if (rc)
GOTO(err, rc);
o->od_dt_dev.dd_ops = &osd_dt_ops;
sema_init(&o->od_otable_sem, 1);
INIT_LIST_HEAD(&o->od_ios_list);
- o->od_auto_scrub_interval = AS_DEFAULT;
o->od_sync_on_lseek = B_TRUE;
/* ZFS does not support reporting nonrotional status yet, so this flag
return rc;
}
-static int
-osd_consistency_check(const struct lu_env *env, struct osd_device *osd,
- struct osd_object *obj, const struct lu_fid *fid,
- uint64_t oid, bool is_dir)
+static void
+osd_zfs_consistency_check(const struct lu_env *env, struct osd_device *osd,
+ struct osd_object *obj, const struct lu_fid *fid,
+ u64 oid, bool is_dir)
{
struct lustre_scrub *scrub = &osd->od_scrub;
dnode_t *dn = NULL;
int once = 0;
bool insert;
int rc;
- ENTRY;
-
- if (!fid_is_norm(fid) && !fid_is_igif(fid))
- RETURN(0);
+ ENTRY;
/* oid == ZFS_NO_OBJECT must be for lookup ".." case */
if (oid == ZFS_NO_OBJECT) {
rc = osd_sa_handle_get(obj);
if (rc)
- RETURN(rc);
+ return;
rc = -sa_lookup(obj->oo_sa_hdl, SA_ZPL_PARENT(osd), &oid, 8);
if (rc)
- RETURN(rc);
- }
-
- if (scrub->os_running) {
- if (scrub->os_pos_current > oid)
- RETURN(0);
- } else if (osd->od_auto_scrub_interval == AS_NEVER) {
- RETURN(0);
- } else {
- if (ktime_get_real_seconds() <
- scrub->os_file.sf_time_last_complete +
- osd->od_auto_scrub_interval)
- RETURN(0);
+ return;
}
+ if (!scrub_needs_check(&osd->od_scrub, fid, oid))
+ return;
again:
rc = osd_fid_lookup(env, osd, fid, &oid2);
if (rc == -ENOENT) {
rc = __osd_obj2dnode(osd->od_os, oid, &dn);
/* The object has been removed (by race maybe). */
if (rc)
- RETURN(rc = (rc == -EEXIST ? -ENOENT : rc));
+ return;
goto trigger;
} else if (rc || oid == oid2) {
rc = __osd_obj2dnode(osd->od_os, oid, &dn);
/* The object has been removed (by race maybe). */
if (rc)
- RETURN(rc = (rc == -EEXIST ? -ENOENT : rc));
+ return;
}
rc = osd_oii_insert(env, osd, fid, oid, insert);
GOTO(out, rc);
}
- if (osd->od_auto_scrub_interval != AS_NEVER && ++once == 1) {
+ if (osd->od_scrub.os_auto_scrub_interval != AS_NEVER && ++once == 1) {
rc = osd_scrub_start(env, osd, SS_AUTO_FULL |
SS_CLEAR_DRYRUN | SS_CLEAR_FAILOUT);
CDEBUG_LIMIT(D_LFSCK | D_CONSOLE | D_WARNING,
out:
if (dn)
osd_dnode_rele(dn);
-
- return rc;
}
static int osd_dir_lookup(const struct lu_env *env, struct dt_object *dt,
up_read(&obj->oo_guard);
out:
if (!rc && !osd_remote_fid(env, osd, fid)) {
+ bool is_dir = S_ISDIR(DTTOIF(oti->oti_zde.lzd_reg.zde_type));
+
/*
* this should ask the scrubber to check OI given
* the mapping we just found in the dir entry.
* from the layers above, including LFSCK which
* is supposed to fix dangling entries.
*/
- osd_consistency_check(env, osd, obj, fid, oid,
- S_ISDIR(DTTOIF(oti->oti_zde.lzd_reg.zde_type)));
+ osd_zfs_consistency_check(env, osd, obj, fid, oid, is_dir);
}
return rc == 0 ? 1 : (rc == -ENOENT ? -ENODATA : rc);
int od_connects;
int od_index;
- __s64 od_auto_scrub_interval;
struct lu_site od_site;
dnode_t *od_groupused_dn;
/* osd_scrub.c */
int osd_scrub_setup(const struct lu_env *env, struct osd_device *dev,
- bool resetoi);
+ time64_t interval, 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);
if (!dev->od_os)
return -EINPROGRESS;
- return sprintf(buf, "%lld\n", dev->od_auto_scrub_interval);
+ return scnprintf(buf, PAGE_SIZE, "%lld\n",
+ dev->od_scrub.os_auto_scrub_interval);
}
static ssize_t auto_scrub_store(struct kobject *kobj, struct attribute *attr,
if (rc)
return rc;
- dev->od_auto_scrub_interval = val;
+ dev->od_scrub.os_auto_scrub_interval = val;
return count;
}
LUSTRE_RW_ATTR(auto_scrub);
}
/* The case NOT allow to trigger OI scrub automatically. */
- if (osd->od_auto_scrub_interval == AS_NEVER)
+ if (osd->od_scrub.os_auto_scrub_interval == AS_NEVER)
GOTO(out, rc);
/* It is me to trigger the OI scrub. */
static const char osd_scrub_name[] = "OI_scrub";
int osd_scrub_setup(const struct lu_env *env, struct osd_device *dev,
- bool resetoi)
+ time64_t interval, bool resetoi)
{
struct osd_thread_info *info = osd_oti_get(env);
struct lustre_scrub *scrub = &dev->od_scrub;
spin_lock_init(&scrub->os_lock);
INIT_LIST_HEAD(&scrub->os_inconsistent_items);
scrub->os_name = osd_name(dev);
+ scrub->os_auto_scrub_interval = interval;
/* 'What the @fid is' is not imporatant, because the object
* has no OI mapping, and only is visible inside the OSD.*/
osd_initial_OI_scrub(env, dev);
if (!dev->od_dt_dev.dd_rdonly &&
- dev->od_auto_scrub_interval != AS_NEVER &&
+ scrub->os_auto_scrub_interval != AS_NEVER &&
((sf->sf_status == SS_PAUSED) ||
(sf->sf_status == SS_CRASHED &&
sf->sf_flags & (SF_RECREATED | SF_INCONSISTENT |