X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fosd-ldiskfs%2Fosd_scrub.c;h=d7e5d57ca6b3b52f3bb54628927dae9b0c11b9ba;hb=ad6dd123cc475e8babcc1b8698fc4d1963841832;hp=1804daa7fab0bc782a6b7897814b62c4fd2331b5;hpb=9bd7e40d2934cd0162eeff5388f054444a982ac9;p=fs%2Flustre-release.git diff --git a/lustre/osd-ldiskfs/osd_scrub.c b/lustre/osd-ldiskfs/osd_scrub.c index 1804daa..d7e5d57 100644 --- a/lustre/osd-ldiskfs/osd_scrub.c +++ b/lustre/osd-ldiskfs/osd_scrub.c @@ -35,7 +35,7 @@ * Author: Fan Yong */ -#define DEBUG_SUBSYSTEM S_MDS +#define DEBUG_SUBSYSTEM S_LFSCK #include #include @@ -80,6 +80,11 @@ static inline int osd_scrub_has_window(struct osd_scrub *scrub, return scrub->os_pos_current < ooc->ooc_pos_preload + SCRUB_WINDOW_SIZE; } +static inline const char *osd_scrub2name(struct osd_scrub *scrub) +{ + return LDISKFS_SB(osd_scrub2sb(scrub))->s_es->s_volume_name; +} + /** * update/insert/delete the specified OI mapping (@fid @id) according to the ops * @@ -94,30 +99,27 @@ static int osd_scrub_refresh_mapping(struct osd_thread_info *info, int ops, bool force, enum oi_check_flags flags) { - const struct lu_env *env = info->oti_env; - struct thandle *th; - struct osd_thandle *oh; - int rc; + handle_t *th; + int rc; ENTRY; if (dev->od_scrub.os_file.sf_param & SP_DRYRUN && !force) RETURN(0); - th = dt_trans_create(env, &dev->od_dt_dev); - if (IS_ERR(th)) - RETURN(PTR_ERR(th)); - - oh = container_of0(th, struct osd_thandle, ot_super); - LASSERT(oh->ot_handle == NULL); + /* DTO_INDEX_INSERT is enough for other two ops: + * delete/update, but save stack. */ + th = osd_journal_start_sb(osd_sb(dev), LDISKFS_HT_MISC, + osd_dto_credits_noquota[DTO_INDEX_INSERT]); + if (IS_ERR(th)) { + rc = PTR_ERR(th); + CDEBUG(D_LFSCK, "%s: fail to start trans for scrub op %d " + DFID" => %u/%u: rc = %d\n", osd_name(dev), ops, + PFID(fid), id->oii_ino, id->oii_gen, rc); + RETURN(rc); + } switch (ops) { case DTO_INDEX_UPDATE: - osd_trans_declare_op(env, oh, OSD_OT_UPDATE, - osd_dto_credits_noquota[DTO_INDEX_UPDATE]); - rc = dt_trans_start_local(env, &dev->od_dt_dev, th); - if (rc != 0) - GOTO(stop, rc); - rc = osd_oi_update(info, dev, fid, id, th, flags); if (unlikely(rc == -ENOENT)) { /* Some unlink thread may removed the OI mapping. */ @@ -125,12 +127,6 @@ static int osd_scrub_refresh_mapping(struct osd_thread_info *info, } break; case DTO_INDEX_INSERT: - osd_trans_declare_op(env, oh, OSD_OT_INSERT, - osd_dto_credits_noquota[DTO_INDEX_INSERT]); - rc = dt_trans_start_local(env, &dev->od_dt_dev, th); - if (rc != 0) - GOTO(stop, rc); - rc = osd_oi_insert(info, dev, fid, id, th, flags); if (unlikely(rc == -EEXIST)) { rc = 1; @@ -168,12 +164,6 @@ static int osd_scrub_refresh_mapping(struct osd_thread_info *info, } break; case DTO_INDEX_DELETE: - osd_trans_declare_op(env, oh, OSD_OT_DELETE, - osd_dto_credits_noquota[DTO_INDEX_DELETE]); - rc = dt_trans_start_local(env, &dev->od_dt_dev, th); - if (rc != 0) - GOTO(stop, rc); - rc = osd_oi_delete(info, dev, fid, th, flags); if (rc == -ENOENT) { /* It is normal that the unlink thread has removed the @@ -186,11 +176,13 @@ static int osd_scrub_refresh_mapping(struct osd_thread_info *info, break; } - GOTO(stop, rc); + ldiskfs_journal_stop(th); + if (rc < 0) + CDEBUG(D_LFSCK, "%s: fail to refresh OI map for scrub op %d " + DFID" => %u/%u: rc = %d\n", osd_name(dev), ops, + PFID(fid), id->oii_ino, id->oii_gen, rc); -stop: - dt_trans_stop(env, &dev->od_dt_dev, th); - return rc; + RETURN(rc); } /* OI_scrub file ops */ @@ -279,7 +271,8 @@ void osd_scrub_file_reset(struct osd_scrub *scrub, __u8 *uuid, __u64 flags) { struct scrub_file *sf = &scrub->os_file; - CDEBUG(D_LFSCK, "Reset OI scrub file, flags = "LPX64"\n", flags); + CDEBUG(D_LFSCK, "%.16s: reset OI scrub file, flags = "LPX64"\n", + osd_scrub2name(scrub), flags); memcpy(sf->sf_uuid, uuid, 16); sf->sf_status = SS_INIT; sf->sf_flags |= flags; @@ -300,7 +293,6 @@ void osd_scrub_file_reset(struct osd_scrub *scrub, __u8 *uuid, __u64 flags) static int osd_scrub_file_load(struct osd_scrub *scrub) { loff_t pos = 0; - char *name = LDISKFS_SB(osd_scrub2sb(scrub))->s_es->s_volume_name; int len = sizeof(scrub->os_file_disk); int rc; @@ -310,16 +302,18 @@ static int osd_scrub_file_load(struct osd_scrub *scrub) osd_scrub_file_to_cpu(sf, &scrub->os_file_disk); if (sf->sf_magic != SCRUB_MAGIC_V1) { - CWARN("%.16s: invalid scrub magic 0x%x != 0x%x\n,", - name, sf->sf_magic, SCRUB_MAGIC_V1); + CDEBUG(D_LFSCK, "%.16s: invalid scrub magic " + "0x%x != 0x%x\n", osd_scrub2name(scrub), + sf->sf_magic, SCRUB_MAGIC_V1); /* Process it as new scrub file. */ rc = -ENOENT; } else { rc = 0; } } else if (rc != 0) { - CERROR("%.16s: fail to load scrub file, expected = %d, " - "rc = %d\n", name, len, rc); + CDEBUG(D_LFSCK, "%.16s: fail to load scrub file, " + "expected = %d: rc = %d\n", + osd_scrub2name(scrub), len, rc); if (rc > 0) rc = -EFAULT; } else { @@ -345,8 +339,8 @@ int osd_scrub_file_store(struct osd_scrub *scrub) jh = osd_journal_start_sb(osd_sb(dev), LDISKFS_HT_MISC, credits); if (IS_ERR(jh)) { rc = PTR_ERR(jh); - CERROR("%.16s: fail to start trans for scrub store, rc = %d\n", - LDISKFS_SB(osd_scrub2sb(scrub))->s_es->s_volume_name,rc); + CDEBUG(D_LFSCK, "%.16s: fail to start trans for scrub store: " + "rc = %d\n", osd_scrub2name(scrub), rc); return rc; } @@ -355,10 +349,10 @@ int osd_scrub_file_store(struct osd_scrub *scrub) len, 0, &pos, jh); ldiskfs_journal_stop(jh); if (rc != 0) - CERROR("%.16s: fail to store scrub file, expected = %d, " - "rc = %d\n", - LDISKFS_SB(osd_scrub2sb(scrub))->s_es->s_volume_name, - len, rc); + CDEBUG(D_LFSCK, "%.16s: fail to store scrub file, " + "expected = %d: rc = %d\n", + osd_scrub2name(scrub), len, rc); + scrub->os_time_last_checkpoint = cfs_time_current(); scrub->os_time_next_checkpoint = scrub->os_time_last_checkpoint + cfs_time_seconds(SCRUB_CHECKPOINT_INTERVAL); @@ -395,9 +389,8 @@ osd_scrub_convert_ff(struct osd_thread_info *info, struct osd_device *dev, osd_dto_credits_noquota[DTO_XATTR_SET] * 3); if (IS_ERR(jh)) { rc = PTR_ERR(jh); - CERROR("%s: fail to start trans for convert ff: "DFID - ": rc = %d\n", - osd_name(dev), PFID(fid), rc); + CDEBUG(D_LFSCK, "%s: fail to start trans for convert ff " + DFID": rc = %d\n", osd_name(dev), PFID(fid), rc); RETURN(rc); } @@ -439,6 +432,9 @@ osd_scrub_convert_ff(struct osd_thread_info *info, struct osd_device *dev, stop: ldiskfs_journal_stop(jh); + if (rc < 0) + CDEBUG(D_LFSCK, "%s: fail to convert ff "DFID": rc = %d\n", + osd_name(dev), PFID(fid), rc); return rc; } @@ -465,8 +461,8 @@ osd_scrub_check_update(struct osd_thread_info *info, struct osd_device *dev, GOTO(out, rc = val); if (scrub->os_in_prior) - oii = cfs_list_entry(oic, struct osd_inconsistent_item, - oii_cache); + oii = list_entry(oic, struct osd_inconsistent_item, + oii_cache); if (lid->oii_ino < sf->sf_pos_latest_start && oii == NULL) GOTO(out, rc = 0); @@ -505,7 +501,7 @@ osd_scrub_check_update(struct osd_thread_info *info, struct osd_device *dev, (val == SCRUB_NEXT_OSTOBJ || val == SCRUB_NEXT_OSTOBJ_OLD) ? OI_KNOWN_ON_OST : 0); if (rc != 0) { - if (rc != -ENOENT) + if (rc != -ENOENT && rc != -ESTALE) GOTO(out, rc); iget: @@ -609,10 +605,10 @@ out: iput(inode); if (oii != NULL) { - LASSERT(!cfs_list_empty(&oii->oii_list)); + LASSERT(!list_empty(&oii->oii_list)); spin_lock(&scrub->os_lock); - cfs_list_del_init(&oii->oii_list); + list_del_init(&oii->oii_list); spin_unlock(&scrub->os_lock); OBD_FREE_PTR(oii); } @@ -754,10 +750,6 @@ static void osd_scrub_post(struct osd_scrub *scrub, int result) sf->sf_run_time += cfs_duration_sec(cfs_time_current() + HALF_SEC - scrub->os_time_last_checkpoint); result = osd_scrub_file_store(scrub); - if (result < 0) - CERROR("%.16s: fail to osd_scrub_post, rc = %d\n", - LDISKFS_SB(osd_scrub2sb(scrub))->s_es->s_volume_name, - result); up_write(&scrub->os_rwsem); EXIT; @@ -827,36 +819,31 @@ static int osd_scrub_get_fid(struct osd_thread_info *info, rc = osd_get_lma(info, inode, &info->oti_obj_dentry, lma); if (rc == 0) { has_lma = true; - if (lma->lma_compat & LMAC_NOT_IN_OI) { - ldiskfs_set_inode_state(inode, - LDISKFS_STATE_LUSTRE_NO_OI); + if (lma->lma_compat & LMAC_NOT_IN_OI || + lma->lma_incompat & LMAI_AGENT) return SCRUB_NEXT_CONTINUE; - } *fid = lma->lma_self_fid; - if (fid_is_internal(&lma->lma_self_fid)) { - if (!scrub) - rc = SCRUB_NEXT_CONTINUE; - return rc; - } - if (!scrub) return 0; - if (fid_is_namespace_visible(fid) && !fid_is_norm(fid)) - return 0; - if (lma->lma_compat & LMAC_FID_ON_OST) return SCRUB_NEXT_OSTOBJ; - if (fid_is_idif(fid) || fid_is_last_id(fid)) + if (fid_is_idif(fid)) return SCRUB_NEXT_OSTOBJ_OLD; - if (lma->lma_incompat & LMAI_AGENT) - return SCRUB_NEXT_CONTINUE; + /* For local object. */ + if (fid_is_internal(fid)) + return 0; + + /* For external visible MDT-object with non-normal FID. */ + if (fid_is_namespace_visible(fid) && !fid_is_norm(fid)) + return 0; - /* Here, it may be MDT-object, or may be 2.4 OST-object. - * Fall through. */ + /* For the object with normal FID, it may be MDT-object, + * or may be 2.4 OST-object, need further distinguish. + * Fall through to next section. */ } if (rc == -ENODATA || rc == 0) { @@ -916,6 +903,12 @@ static int osd_iit_iget(struct osd_thread_info *info, struct osd_device *dev, int rc; ENTRY; + /* Not handle the backend root object and agent parent object. + * They are neither visible to namespace nor have OI mappings. */ + if (unlikely(pos == osd_sb(dev)->s_root->d_inode->i_ino || + pos == osd_remote_parent_ino(dev))) + RETURN(SCRUB_NEXT_CONTINUE); + osd_id_gen(lid, pos, OSD_OII_NOGEN); inode = osd_iget(info, dev, lid); if (IS_ERR(inode)) { @@ -925,16 +918,12 @@ static int osd_iit_iget(struct osd_thread_info *info, struct osd_device *dev, if (rc == -ENOENT || rc == -ESTALE) RETURN(SCRUB_NEXT_CONTINUE); - CERROR("%.16s: fail to read inode, ino# = %u, rc = %d\n", - LDISKFS_SB(sb)->s_es->s_volume_name, pos, rc); + CDEBUG(D_LFSCK, "%.16s: fail to read inode, ino# = %u: " + "rc = %d\n", LDISKFS_SB(sb)->s_es->s_volume_name, + pos, rc); RETURN(rc); } - /* If the inode has no OI mapping, then it is special locally used, - * should be invisible to OI scrub or up layer LFSCK. */ - if (ldiskfs_test_inode_state(inode, LDISKFS_STATE_LUSTRE_NO_OI)) - GOTO(put, rc = SCRUB_NEXT_CONTINUE); - if (scrub && ldiskfs_test_inode_state(inode, LDISKFS_STATE_LUSTRE_NOSCRUB)) { /* Only skip it for the first OI scrub accessing. */ @@ -966,7 +955,7 @@ static int osd_scrub_next(struct osd_thread_info *info, struct osd_device *dev, lwi = LWI_TIMEOUT(cfs_time_seconds(cfs_fail_val), NULL, NULL); l_wait_event(thread->t_ctl_waitq, - !cfs_list_empty(&scrub->os_inconsistent_items) || + !list_empty(&scrub->os_inconsistent_items) || !thread_is_running(thread), &lwi); } @@ -984,11 +973,11 @@ static int osd_scrub_next(struct osd_thread_info *info, struct osd_device *dev, if (unlikely(!thread_is_running(thread))) return SCRUB_NEXT_EXIT; - if (!cfs_list_empty(&scrub->os_inconsistent_items)) { + if (!list_empty(&scrub->os_inconsistent_items)) { struct osd_inconsistent_item *oii; - oii = cfs_list_entry(scrub->os_inconsistent_items.next, - struct osd_inconsistent_item, oii_list); + oii = list_entry(scrub->os_inconsistent_items.next, + struct osd_inconsistent_item, oii_list); *oic = &oii->oii_cache; scrub->os_in_prior = 1; return 0; @@ -1043,7 +1032,7 @@ osd_scrub_wakeup(struct osd_scrub *scrub, struct osd_otable_it *it) { spin_lock(&scrub->os_lock); if (osd_scrub_has_window(scrub, &it->ooi_cache) || - !cfs_list_empty(&scrub->os_inconsistent_items) || + !list_empty(&scrub->os_inconsistent_items) || it->ooi_waiting || !thread_is_running(&scrub->os_thread)) scrub->os_waiting = 0; else @@ -1083,8 +1072,8 @@ static int osd_scrub_exec(struct osd_thread_info *info, struct osd_device *dev, rc = osd_scrub_checkpoint(scrub); if (rc != 0) { - CERROR("%.16s: fail to checkpoint, pos = %u, rc = %d\n", - LDISKFS_SB(param->sb)->s_es->s_volume_name, + CDEBUG(D_LFSCK, "%.16s: fail to checkpoint, pos = %u: " + "rc = %d\n", osd_scrub2name(scrub), scrub->os_pos_current, rc); /* Continue, as long as the scrub itself can go ahead. */ } @@ -1109,16 +1098,16 @@ wait: if (scrub->os_full_speed || rc == SCRUB_NEXT_CONTINUE) return 0; - if (osd_scrub_has_window(scrub, ooc)) { + if (ooc != NULL && osd_scrub_has_window(scrub, ooc)) { *noslot = 0; return 0; } - l_wait_event(thread->t_ctl_waitq, - osd_scrub_wakeup(scrub, it), - &lwi); + if (it != NULL) + l_wait_event(thread->t_ctl_waitq, osd_scrub_wakeup(scrub, it), + &lwi); - if (osd_scrub_has_window(scrub, ooc)) + if (ooc != NULL && osd_scrub_has_window(scrub, ooc)) *noslot = 0; else *noslot = 1; @@ -1181,7 +1170,7 @@ static int osd_inode_iteration(struct osd_thread_info *info, param.gbase = 1 + param.bg * LDISKFS_INODES_PER_GROUP(param.sb); param.bitmap = ldiskfs_read_inode_bitmap(param.sb, param.bg); if (param.bitmap == NULL) { - CERROR("%.16s: fail to read bitmap for %u, " + CDEBUG(D_LFSCK, "%.16s: fail to read bitmap for %u, " "scrub will stop, urgent mode\n", LDISKFS_SB(param.sb)->s_es->s_volume_name, (__u32)param.bg); @@ -1235,10 +1224,6 @@ static int osd_otable_it_preload(const struct lu_env *env, if (rc == SCRUB_IT_ALL) it->ooi_all_cached = 1; - CDEBUG(D_LFSCK, "OSD pre-loaded: max = %u, preload = %u, rc = %d\n", - le32_to_cpu(LDISKFS_SB(osd_sb(dev))->s_es->s_inodes_count), - ooc->ooc_pos_preload, rc); - if (scrub->os_waiting && osd_scrub_has_window(scrub, ooc)) { spin_lock(&scrub->os_lock); scrub->os_waiting = 0; @@ -1255,21 +1240,20 @@ static int osd_scrub_main(void *args) struct osd_device *dev = (struct osd_device *)args; struct osd_scrub *scrub = &dev->od_scrub; struct ptlrpc_thread *thread = &scrub->os_thread; - struct super_block *sb = osd_sb(dev); int rc; ENTRY; rc = lu_env_init(&env, LCT_LOCAL); if (rc != 0) { - CERROR("%.16s: OI scrub, fail to init env, rc = %d\n", - LDISKFS_SB(sb)->s_es->s_volume_name, rc); + CDEBUG(D_LFSCK, "%.16s: OI scrub fail to init env: rc = %d\n", + osd_scrub2name(scrub), rc); GOTO(noenv, rc); } rc = osd_scrub_prep(dev); if (rc != 0) { - CERROR("%.16s: OI scrub, fail to scrub prep, rc = %d\n", - LDISKFS_SB(sb)->s_es->s_volume_name, rc); + CDEBUG(D_LFSCK, "%.16s: OI scrub fail to scrub prep: rc = %d\n", + osd_scrub2name(scrub), rc); GOTO(out, rc); } @@ -1287,8 +1271,9 @@ static int osd_scrub_main(void *args) scrub->os_pos_current = ooc->ooc_pos_preload; } - CDEBUG(D_LFSCK, "OI scrub: flags = 0x%x, pos = %u\n", - scrub->os_start_flags, scrub->os_pos_current); + CDEBUG(D_LFSCK, "%.16s: OI scrub start, flags = 0x%x, pos = %u\n", + osd_scrub2name(scrub), scrub->os_start_flags, + scrub->os_pos_current); rc = osd_inode_iteration(osd_oti_get(&env), dev, ~0U, false); if (unlikely(rc == SCRUB_IT_CRASH)) @@ -1297,16 +1282,16 @@ static int osd_scrub_main(void *args) post: osd_scrub_post(scrub, rc); - CDEBUG(D_LFSCK, "OI scrub: stop, rc = %d, pos = %u\n", - rc, scrub->os_pos_current); + CDEBUG(D_LFSCK, "%.16s: OI scrub: stop, pos = %u: rc = %d\n", + osd_scrub2name(scrub), scrub->os_pos_current, rc); out: - while (!cfs_list_empty(&scrub->os_inconsistent_items)) { + while (!list_empty(&scrub->os_inconsistent_items)) { struct osd_inconsistent_item *oii; - oii = cfs_list_entry(scrub->os_inconsistent_items.next, + oii = list_entry(scrub->os_inconsistent_items.next, struct osd_inconsistent_item, oii_list); - cfs_list_del_init(&oii->oii_list); + list_del_init(&oii->oii_list); OBD_FREE_PTR(oii); } lu_env_fini(&env); @@ -1328,6 +1313,8 @@ static int osd_ios_varfid_fill(void *buf, const char *name, int namelen, loff_t offset, __u64 ino, unsigned d_type); static int osd_ios_lf_fill(void *buf, const char *name, int namelen, loff_t offset, __u64 ino, unsigned d_type); +static int osd_ios_dl_fill(void *buf, const char *name, int namelen, + loff_t offset, __u64 ino, unsigned d_type); static int osd_ios_general_scan(struct osd_thread_info *info, struct osd_device *dev, @@ -1438,21 +1425,42 @@ static const struct osd_lf_map osd_lf_maps[] = { { "LAST_GROUP", { FID_SEQ_LOCAL_FILE, OFD_LAST_GROUP_OID, 0 }, OLF_SHOW_NAME, NULL, NULL }, + /* SLAVE_LOG, llog for destroy slave stripes of striped dir */ + { "SLAVE_LOG", { FID_SEQ_LOCAL_FILE, SLAVE_LLOG_CATALOGS_OID, 0 }, + OLF_SHOW_NAME, NULL, NULL }, + /* lost+found */ - { "lost+found", { 0, 0, 0 }, OLF_SCAN_SUBITEMS | OLF_NO_OI, - osd_ios_general_scan, osd_ios_lf_fill }, + { "lost+found", { FID_SEQ_LOCAL_FILE, OSD_LPF_OID, 0 }, + OLF_SCAN_SUBITEMS, osd_ios_general_scan, osd_ios_lf_fill }, + + { NULL, { 0, 0, 0 }, 0, NULL, NULL } +}; + +/* Add the new introduced files under .lustre/ in the list in the future. */ +static const struct osd_lf_map osd_dl_maps[] = { + /* .lustre/fid */ + { "fid", { FID_SEQ_DOT_LUSTRE, FID_OID_DOT_LUSTRE_OBF, 0 }, 0, + NULL, NULL }, + + /* .lustre/lost+found */ + { "lost+found", { FID_SEQ_DOT_LUSTRE, FID_OID_DOT_LUSTRE_LPF, 0 }, 0, + NULL, NULL }, { NULL, { 0, 0, 0 }, 0, NULL, NULL } }; struct osd_ios_item { - cfs_list_t oii_list; + struct list_head oii_list; struct dentry *oii_dentry; scandir_t oii_scandir; filldir_t oii_filldir; }; struct osd_ios_filldir_buf { +#ifdef HAVE_DIR_CONTEXT + /* please keep it as first member */ + struct dir_context ctx; +#endif struct osd_thread_info *oifb_info; struct osd_device *oifb_dev; struct dentry *oifb_dentry; @@ -1463,9 +1471,6 @@ osd_ios_lookup_one_len(const char *name, struct dentry *parent, int namelen) { struct dentry *dentry; - CDEBUG(D_LFSCK, "init lookup one: parent = %.*s, name = %.*s\n", - parent->d_name.len, parent->d_name.name, namelen, name); - dentry = ll_lookup_one_len(name, parent, namelen); if (!IS_ERR(dentry) && dentry->d_inode == NULL) { dput(dentry); @@ -1486,11 +1491,11 @@ osd_ios_new_item(struct osd_device *dev, struct dentry *dentry, if (item == NULL) RETURN(-ENOMEM); - CFS_INIT_LIST_HEAD(&item->oii_list); + INIT_LIST_HEAD(&item->oii_list); item->oii_dentry = dget(dentry); item->oii_scandir = scandir; item->oii_filldir = filldir; - cfs_list_add_tail(&item->oii_list, &dev->od_ios_list); + list_add_tail(&item->oii_list, &dev->od_ios_list); RETURN(0); } @@ -1515,11 +1520,13 @@ osd_ios_scan_one(struct osd_thread_info *info, struct osd_device *dev, int rc; ENTRY; - CDEBUG(D_LFSCK, "init scan one: ino = %ld\n", inode->i_ino); - rc = osd_get_lma(info, inode, &info->oti_obj_dentry, lma); - if (rc != 0 && rc != -ENODATA) + if (rc != 0 && rc != -ENODATA) { + CDEBUG(D_LFSCK, "%s: fail to get lma for init OI scrub: " + "rc = %d\n", osd_name(dev), rc); + RETURN(rc); + } osd_id_gen(id, inode->i_ino, inode->i_generation); if (rc == -ENODATA) { @@ -1528,8 +1535,12 @@ osd_ios_scan_one(struct osd_thread_info *info, struct osd_device *dev, else tfid = *fid; rc = osd_ea_fid_set(info, inode, &tfid, 0, 0); - if (rc != 0) + if (rc != 0) { + CDEBUG(D_LFSCK, "%s: fail to set LMA for init OI " + "scrub: rc = %d\n", osd_name(dev), rc); + RETURN(rc); + } } else { if (lma->lma_compat & LMAC_NOT_IN_OI) RETURN(0); @@ -1596,7 +1607,7 @@ static int osd_ios_lf_fill(void *buf, const char *name, int namelen, scrub->os_lf_scanned++; child = osd_ios_lookup_one_len(name, parent, namelen); if (IS_ERR(child)) { - CWARN("%s: cannot lookup child '%.*s': rc = %d\n", + CDEBUG(D_LFSCK, "%s: cannot lookup child '%.*s': rc = %d\n", osd_name(dev), namelen, name, (int)PTR_ERR(child)); RETURN(0); } @@ -1606,8 +1617,8 @@ static int osd_ios_lf_fill(void *buf, const char *name, int namelen, rc = osd_ios_new_item(dev, child, osd_ios_general_scan, osd_ios_lf_fill); if (rc != 0) - CWARN("%s: cannot add child '%.*s': rc = %d\n", - osd_name(dev), namelen, name, rc); + CDEBUG(D_LFSCK, "%s: cannot add child '%.*s': " + "rc = %d\n", osd_name(dev), namelen, name, rc); GOTO(put, rc); } @@ -1622,8 +1633,9 @@ static int osd_ios_lf_fill(void *buf, const char *name, int namelen, "/lost+found.\n", namelen, name, PFID(fid)); scrub->os_lf_repaired++; } else { - CWARN("%s: cannot rename for '%.*s' "DFID": rc = %d\n", - osd_name(dev), namelen, name, PFID(fid), rc); + CDEBUG(D_LFSCK, "%s: cannot rename for '%.*s' " + DFID": rc = %d\n", + osd_name(dev), namelen, name, PFID(fid), rc); } } @@ -1668,6 +1680,42 @@ static int osd_ios_varfid_fill(void *buf, const char *name, int namelen, RETURN(rc); } +static int osd_ios_dl_fill(void *buf, const char *name, int namelen, + loff_t offset, __u64 ino, unsigned d_type) +{ + struct osd_ios_filldir_buf *fill_buf = buf; + struct osd_device *dev = fill_buf->oifb_dev; + const struct osd_lf_map *map; + struct dentry *child; + int rc = 0; + ENTRY; + + /* skip any '.' started names */ + if (name[0] == '.') + RETURN(0); + + for (map = osd_dl_maps; map->olm_name != NULL; map++) { + if (strlen(map->olm_name) != namelen) + continue; + + if (strncmp(map->olm_name, name, namelen) == 0) + break; + } + + if (map->olm_name == NULL) + RETURN(0); + + child = osd_ios_lookup_one_len(name, fill_buf->oifb_dentry, namelen); + if (IS_ERR(child)) + RETURN(PTR_ERR(child)); + + rc = osd_ios_scan_one(fill_buf->oifb_info, dev, child->d_inode, + &map->olm_fid, map->olm_flags); + dput(child); + + RETURN(rc); +} + static int osd_ios_root_fill(void *buf, const char *name, int namelen, loff_t offset, __u64 ino, unsigned d_type) { @@ -1712,7 +1760,13 @@ static int osd_ios_general_scan(struct osd_thread_info *info, struct osd_device *dev, struct dentry *dentry, filldir_t filldir) { - struct osd_ios_filldir_buf buf = { info, dev, dentry }; + struct osd_ios_filldir_buf buf = { +#ifdef HAVE_DIR_CONTEXT + .ctx.actor = filldir, +#endif + .oifb_info = info, + .oifb_dev = dev, + .oifb_dentry = dentry }; struct file *filp = &info->oti_it_ea.oie_file; struct inode *inode = dentry->d_inode; const struct file_operations *fops = inode->i_fop; @@ -1729,7 +1783,13 @@ osd_ios_general_scan(struct osd_thread_info *info, struct osd_device *dev, filp->private_data = NULL; set_file_inode(filp, inode); +#ifdef HAVE_DIR_CONTEXT + buf.ctx.pos = filp->f_pos; + rc = fops->iterate(filp, &buf.ctx); + filp->f_pos = buf.ctx.pos; +#else rc = fops->readdir(filp, &buf, filldir); +#endif fops->release(inode, filp); RETURN(rc); @@ -1801,6 +1861,9 @@ osd_ios_ROOT_scan(struct osd_thread_info *info, struct osd_device *dev, * to the solution 2). */ rc = osd_ios_scan_one(info, dev, child->d_inode, &LU_DOT_LUSTRE_FID, 0); + if (rc == 0) + rc = osd_ios_new_item(dev, child, osd_ios_general_scan, + osd_ios_dl_fill); dput(child); } @@ -1873,12 +1936,12 @@ static int osd_initial_OI_scrub(struct osd_thread_info *info, if (rc != 0) break; - if (cfs_list_empty(&dev->od_ios_list)) + if (list_empty(&dev->od_ios_list)) break; - item = cfs_list_entry(dev->od_ios_list.next, - struct osd_ios_item, oii_list); - cfs_list_del_init(&item->oii_list); + item = list_entry(dev->od_ios_list.next, + struct osd_ios_item, oii_list); + list_del_init(&item->oii_list); LASSERT(item->oii_scandir != NULL); scandir = item->oii_scandir; @@ -1886,10 +1949,10 @@ static int osd_initial_OI_scrub(struct osd_thread_info *info, dentry = item->oii_dentry; } - while (!cfs_list_empty(&dev->od_ios_list)) { - item = cfs_list_entry(dev->od_ios_list.next, - struct osd_ios_item, oii_list); - cfs_list_del_init(&item->oii_list); + while (!list_empty(&dev->od_ios_list)) { + item = list_entry(dev->od_ios_list.next, + struct osd_ios_item, oii_list); + list_del_init(&item->oii_list); dput(item->oii_dentry); OBD_FREE_PTR(item); } @@ -1949,6 +2012,7 @@ static int do_osd_scrub_start(struct osd_device *dev, __u32 flags) struct osd_scrub *scrub = &dev->od_scrub; struct ptlrpc_thread *thread = &scrub->os_thread; struct l_wait_info lwi = { 0 }; + struct task_struct *task; int rc; ENTRY; @@ -1967,15 +2031,23 @@ again: } spin_unlock(&scrub->os_lock); - if (scrub->os_file.sf_status == SS_COMPLETED) + if (scrub->os_file.sf_status == SS_COMPLETED) { + if (!(flags & SS_SET_FAILOUT)) + flags |= SS_CLEAR_FAILOUT; + + if (!(flags & SS_SET_DRYRUN)) + flags |= SS_CLEAR_DRYRUN; + flags |= SS_RESET; + } scrub->os_start_flags = flags; thread_set_flags(thread, 0); - rc = PTR_ERR(kthread_run(osd_scrub_main, dev, "OI_scrub")); - if (IS_ERR_VALUE(rc)) { - CERROR("%.16s: cannot start iteration thread, rc = %d\n", - LDISKFS_SB(osd_sb(dev))->s_es->s_volume_name, rc); + task = kthread_run(osd_scrub_main, dev, "OI_scrub"); + if (IS_ERR(task)) { + rc = PTR_ERR(task); + CERROR("%.16s: cannot start iteration thread: rc = %d\n", + osd_scrub2name(scrub), rc); RETURN(rc); } @@ -2058,30 +2130,29 @@ int osd_scrub_setup(const struct lu_env *env, struct osd_device *dev) init_waitqueue_head(&scrub->os_thread.t_ctl_waitq); init_rwsem(&scrub->os_rwsem); spin_lock_init(&scrub->os_lock); - CFS_INIT_LIST_HEAD(&scrub->os_inconsistent_items); + INIT_LIST_HEAD(&scrub->os_inconsistent_items); - push_ctxt(&saved, ctxt, NULL); + push_ctxt(&saved, ctxt); filp = filp_open(osd_scrub_name, O_RDWR | O_CREAT, 0644); if (IS_ERR(filp)) { - pop_ctxt(&saved, ctxt, NULL); + pop_ctxt(&saved, ctxt); RETURN(PTR_ERR(filp)); } inode = filp->f_dentry->d_inode; - ldiskfs_set_inode_state(inode, LDISKFS_STATE_LUSTRE_NO_OI); /* 'What the @fid is' is not imporatant, because the object * has no OI mapping, and only is visible inside the OSD.*/ lu_igif_build(fid, inode->i_ino, inode->i_generation); rc = osd_ea_fid_set(info, inode, fid, LMAC_NOT_IN_OI, 0); if (rc != 0) { filp_close(filp, 0); - pop_ctxt(&saved, ctxt, NULL); + pop_ctxt(&saved, ctxt); RETURN(rc); } scrub->os_inode = igrab(inode); filp_close(filp, 0); - pop_ctxt(&saved, ctxt, NULL); + pop_ctxt(&saved, ctxt); rc = osd_scrub_file_load(scrub); if (rc == -ENOENT) { @@ -2458,7 +2529,7 @@ int osd_oii_insert(struct osd_device *dev, struct osd_idmap_cache *oic, if (unlikely(oii == NULL)) RETURN(-ENOMEM); - CFS_INIT_LIST_HEAD(&oii->oii_list); + INIT_LIST_HEAD(&oii->oii_list); oii->oii_cache = *oic; oii->oii_insert = insert; @@ -2469,9 +2540,9 @@ int osd_oii_insert(struct osd_device *dev, struct osd_idmap_cache *oic, RETURN(-EAGAIN); } - if (cfs_list_empty(&scrub->os_inconsistent_items)) + if (list_empty(&scrub->os_inconsistent_items)) wakeup = 1; - cfs_list_add_tail(&oii->oii_list, &scrub->os_inconsistent_items); + list_add_tail(&oii->oii_list, &scrub->os_inconsistent_items); spin_unlock(&scrub->os_lock); if (wakeup != 0) @@ -2488,7 +2559,7 @@ int osd_oii_lookup(struct osd_device *dev, const struct lu_fid *fid, ENTRY; spin_lock(&scrub->os_lock); - cfs_list_for_each_entry(oii, &scrub->os_inconsistent_items, oii_list) { + list_for_each_entry(oii, &scrub->os_inconsistent_items, oii_list) { if (lu_fid_eq(fid, &oii->oii_cache.oic_fid)) { *id = oii->oii_cache.oic_lid; spin_unlock(&scrub->os_lock); @@ -2527,134 +2598,112 @@ static const char *scrub_param_names[] = { NULL }; -static int scrub_bits_dump(char **buf, int *len, int bits, const char *names[], +static int scrub_bits_dump(struct seq_file *m, int bits, const char *names[], const char *prefix) { - int save = *len; int flag; int rc; int i; - rc = snprintf(*buf, *len, "%s:%c", prefix, bits != 0 ? ' ' : '\n'); - if (rc <= 0) - return -ENOSPC; + rc = seq_printf(m, "%s:%c", prefix, bits != 0 ? ' ' : '\n'); + if (rc < 0) + return rc; - *buf += rc; - *len -= rc; for (i = 0, flag = 1; bits != 0; i++, flag = 1 << i) { if (flag & bits) { bits &= ~flag; - rc = snprintf(*buf, *len, "%s%c", names[i], - bits != 0 ? ',' : '\n'); - if (rc <= 0) - return -ENOSPC; - - *buf += rc; - *len -= rc; + rc = seq_printf(m, "%s%c", names[i], + bits != 0 ? ',' : '\n'); + if (rc < 0) + return rc; } } - return save - *len; + return 0; } -static int scrub_time_dump(char **buf, int *len, __u64 time, const char *prefix) +static int scrub_time_dump(struct seq_file *m, __u64 time, const char *prefix) { int rc; if (time != 0) - rc = snprintf(*buf, *len, "%s: "LPU64" seconds\n", prefix, + rc = seq_printf(m, "%s: "LPU64" seconds\n", prefix, cfs_time_current_sec() - time); else - rc = snprintf(*buf, *len, "%s: N/A\n", prefix); - if (rc <= 0) - return -ENOSPC; - - *buf += rc; - *len -= rc; + rc = seq_printf(m, "%s: N/A\n", prefix); return rc; } -static int scrub_pos_dump(char **buf, int *len, __u64 pos, const char *prefix) +static int scrub_pos_dump(struct seq_file *m, __u64 pos, const char *prefix) { int rc; if (pos != 0) - rc = snprintf(*buf, *len, "%s: "LPU64"\n", prefix, pos); + rc = seq_printf(m, "%s: "LPU64"\n", prefix, pos); else - rc = snprintf(*buf, *len, "%s: N/A\n", prefix); - if (rc <= 0) - return -ENOSPC; - - *buf += rc; - *len -= rc; + rc = seq_printf(m, "%s: N/A\n", prefix); return rc; } -int osd_scrub_dump(struct osd_device *dev, char *buf, int len) +int osd_scrub_dump(struct seq_file *m, struct osd_device *dev) { struct osd_scrub *scrub = &dev->od_scrub; struct scrub_file *sf = &scrub->os_file; __u64 checked; __u64 speed; - int save = len; - int ret = -ENOSPC; int rc; down_read(&scrub->os_rwsem); - rc = snprintf(buf, len, - "name: OI_scrub\n" - "magic: 0x%x\n" - "oi_files: %d\n" - "status: %s\n", - sf->sf_magic, (int)sf->sf_oi_count, - scrub_status_names[sf->sf_status]); - if (rc <= 0) + rc = seq_printf(m, "name: OI_scrub\n" + "magic: 0x%x\n" + "oi_files: %d\n" + "status: %s\n", + sf->sf_magic, (int)sf->sf_oi_count, + scrub_status_names[sf->sf_status]); + if (rc < 0) goto out; - buf += rc; - len -= rc; - rc = scrub_bits_dump(&buf, &len, sf->sf_flags, scrub_flags_names, + rc = scrub_bits_dump(m, sf->sf_flags, scrub_flags_names, "flags"); if (rc < 0) goto out; - rc = scrub_bits_dump(&buf, &len, sf->sf_param, scrub_param_names, + rc = scrub_bits_dump(m, sf->sf_param, scrub_param_names, "param"); if (rc < 0) goto out; - rc = scrub_time_dump(&buf, &len, sf->sf_time_last_complete, + rc = scrub_time_dump(m, sf->sf_time_last_complete, "time_since_last_completed"); if (rc < 0) goto out; - rc = scrub_time_dump(&buf, &len, sf->sf_time_latest_start, + rc = scrub_time_dump(m, sf->sf_time_latest_start, "time_since_latest_start"); if (rc < 0) goto out; - rc = scrub_time_dump(&buf, &len, sf->sf_time_last_checkpoint, + rc = scrub_time_dump(m, sf->sf_time_last_checkpoint, "time_since_last_checkpoint"); if (rc < 0) goto out; - rc = scrub_pos_dump(&buf, &len, sf->sf_pos_latest_start, + rc = scrub_pos_dump(m, sf->sf_pos_latest_start, "latest_start_position"); if (rc < 0) goto out; - rc = scrub_pos_dump(&buf, &len, sf->sf_pos_last_checkpoint, + rc = scrub_pos_dump(m, sf->sf_pos_last_checkpoint, "last_checkpoint_position"); if (rc < 0) goto out; - rc = scrub_pos_dump(&buf, &len, sf->sf_pos_first_inconsistent, + rc = scrub_pos_dump(m, sf->sf_pos_first_inconsistent, "first_failure_position"); if (rc < 0) goto out; checked = sf->sf_items_checked + scrub->os_new_checked; - rc = snprintf(buf, len, - "checked: "LPU64"\n" + rc = seq_printf(m, "checked: "LPU64"\n" "updated: "LPU64"\n" "failed: "LPU64"\n" "prior_updated: "LPU64"\n" @@ -2664,11 +2713,9 @@ int osd_scrub_dump(struct osd_device *dev, char *buf, int len) checked, sf->sf_items_updated, sf->sf_items_failed, sf->sf_items_updated_prior, sf->sf_items_noscrub, sf->sf_items_igif, sf->sf_success_count); - if (rc <= 0) + if (rc < 0) goto out; - buf += rc; - len -= rc; speed = checked; if (thread_is_running(&scrub->os_thread)) { cfs_duration_t duration = cfs_time_current() - @@ -2681,8 +2728,7 @@ int osd_scrub_dump(struct osd_device *dev, char *buf, int len) do_div(new_checked, duration); if (rtime != 0) do_div(speed, rtime); - rc = snprintf(buf, len, - "run_time: %u seconds\n" + rc = seq_printf(m, "run_time: %u seconds\n" "average_speed: "LPU64" objects/sec\n" "real-time_speed: "LPU64" objects/sec\n" "current_position: %u\n" @@ -2695,8 +2741,7 @@ int osd_scrub_dump(struct osd_device *dev, char *buf, int len) } else { if (sf->sf_run_time != 0) do_div(speed, sf->sf_run_time); - rc = snprintf(buf, len, - "run_time: %u seconds\n" + rc = seq_printf(m, "run_time: %u seconds\n" "average_speed: "LPU64" objects/sec\n" "real-time_speed: N/A\n" "current_position: N/A\n" @@ -2706,14 +2751,8 @@ int osd_scrub_dump(struct osd_device *dev, char *buf, int len) sf->sf_run_time, speed, scrub->os_lf_scanned, scrub->os_lf_repaired, scrub->os_lf_failed); } - if (rc <= 0) - goto out; - - buf += rc; - len -= rc; - ret = save - len; out: up_read(&scrub->os_rwsem); - return ret; + return (rc < 0 ? -ENOSPC : 0); }