+static void osd_scrub_join(struct osd_device *dev, __u32 flags,
+ bool inconsistent)
+{
+ struct osd_scrub *scrub = &dev->od_scrub;
+ struct ptlrpc_thread *thread = &scrub->os_thread;
+ struct scrub_file *sf = &scrub->os_file;
+ int rc;
+ ENTRY;
+
+ LASSERT(!(flags & SS_AUTO_PARTIAL));
+
+ down_write(&scrub->os_rwsem);
+ scrub->os_in_join = 1;
+ if (flags & SS_SET_FAILOUT)
+ sf->sf_param |= SP_FAILOUT;
+ else if (flags & SS_CLEAR_FAILOUT)
+ sf->sf_param &= ~SP_FAILOUT;
+
+ if (flags & SS_SET_DRYRUN)
+ sf->sf_param |= SP_DRYRUN;
+ else if (flags & SS_CLEAR_DRYRUN)
+ sf->sf_param &= ~SP_DRYRUN;
+
+ if (flags & SS_RESET) {
+ osd_scrub_file_reset(scrub,
+ LDISKFS_SB(osd_sb(dev))->s_es->s_uuid,
+ inconsistent ? SF_INCONSISTENT : 0);
+ sf->sf_status = SS_SCANNING;
+ }
+
+ if (flags & SS_AUTO_FULL) {
+ sf->sf_flags |= SF_AUTO;
+ scrub->os_full_speed = 1;
+ }
+
+ if (sf->sf_flags & (SF_RECREATED | SF_INCONSISTENT | SF_UPGRADE))
+ scrub->os_full_speed = 1;
+ else
+ scrub->os_full_speed = 0;
+
+ scrub->os_new_checked = 0;
+ 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_time_latest_start = cfs_time_current_sec();
+ sf->sf_time_last_checkpoint = sf->sf_time_latest_start;
+ sf->sf_pos_last_checkpoint = sf->sf_pos_latest_start - 1;
+ rc = osd_scrub_file_store(scrub);
+ if (rc != 0)
+ CDEBUG(D_LFSCK, "%.16s: fail to store scrub file when join "
+ "the OI scrub: rc = %d\n", osd_scrub2name(scrub), rc);
+
+ spin_lock(&scrub->os_lock);
+ scrub->os_waiting = 0;
+ scrub->os_paused = 0;
+ scrub->os_partial_scan = 0;
+ scrub->os_in_join = 0;
+ scrub->os_full_scrub = 0;
+ spin_unlock(&scrub->os_lock);
+ wake_up_all(&thread->t_ctl_waitq);
+ up_write(&scrub->os_rwsem);
+
+ EXIT;
+}
+