+/* OI scrub APIs */
+
+static int osd_scrub_prep(struct osd_device *dev)
+{
+ struct osd_scrub *scrub = &dev->od_scrub;
+ struct ptlrpc_thread *thread = &scrub->os_thread;
+ struct scrub_file *sf = &scrub->os_file;
+ __u32 flags = scrub->os_start_flags;
+ int rc;
+ bool drop_dryrun = false;
+ ENTRY;
+
+ down_write(&scrub->os_rwsem);
+ if (flags & SS_SET_FAILOUT)
+ sf->sf_param |= SP_FAILOUT;
+
+ if (flags & SS_CLEAR_FAILOUT)
+ sf->sf_param &= ~SP_FAILOUT;
+
+ if (flags & SS_SET_DRYRUN)
+ sf->sf_param |= SP_DRYRUN;
+
+ if (flags & SS_CLEAR_DRYRUN && sf->sf_param & SP_DRYRUN) {
+ sf->sf_param &= ~SP_DRYRUN;
+ drop_dryrun = true;
+ }
+
+ if (flags & SS_RESET)
+ osd_scrub_file_reset(scrub,
+ LDISKFS_SB(osd_sb(dev))->s_es->s_uuid, 0);
+
+ if (flags & SS_AUTO) {
+ scrub->os_full_speed = 1;
+ sf->sf_flags |= SF_AUTO;
+ /* For the case of OI scrub auto triggered, NOT dryrun. */
+ sf->sf_param &= ~SP_FAILOUT;
+ } else {
+ scrub->os_full_speed = 0;
+ }
+
+ if (sf->sf_flags & (SF_RECREATED | SF_INCONSISTENT | SF_UPGRADE))
+ scrub->os_full_speed = 1;
+
+ scrub->os_in_prior = 0;
+ spin_lock(&scrub->os_lock);
+ scrub->os_waiting = 0;
+ scrub->os_paused = 0;
+ spin_unlock(&scrub->os_lock);
+ scrub->os_new_checked = 0;
+ if (drop_dryrun && sf->sf_pos_first_inconsistent != 0)
+ sf->sf_pos_latest_start = sf->sf_pos_first_inconsistent;
+ else if (sf->sf_pos_last_checkpoint != 0)
+ sf->sf_pos_latest_start = sf->sf_pos_last_checkpoint + 1;
+ else
+ sf->sf_pos_latest_start = LDISKFS_FIRST_INO(osd_sb(dev)) + 1;
+
+ scrub->os_pos_current = sf->sf_pos_latest_start;
+ sf->sf_status = SS_SCANNING;
+ sf->sf_time_latest_start = cfs_time_current_sec();
+ sf->sf_time_last_checkpoint = sf->sf_time_latest_start;
+ rc = osd_scrub_file_store(scrub);
+ if (rc == 0) {
+ spin_lock(&scrub->os_lock);
+ thread_set_flags(thread, SVC_RUNNING);
+ spin_unlock(&scrub->os_lock);
+ wake_up_all(&thread->t_ctl_waitq);
+ }
+ up_write(&scrub->os_rwsem);
+
+ RETURN(rc);
+}
+