When osd_consistency_check(), the target file may has just been
removed by other, so the osd_oi_lookup() will return -ENOENT to
the caller. Under such case, the osd_consistency_check() should
not trigger OI scrub.
On the other hand, if someone unlinked the file during OI scrub
adding the missed OI mapping to the OI file, the OI scrub needs
to remove the new added OI mapping.
Test-Parameters: alwaysuploadlogs \
envdefinitions=SLOW=yes,ENABLE_QUOTA=yes \
mdtfilesystemtype=ldiskfs mdsfilesystemtype=ldiskfs \
ostfilesystemtype=ldiskfs clientdistro=el7 ossdistro=el7 \
mdsdistro=el7 mdtcount=1 \
testlist=sanity-scrub,sanity-scrub,sanity-scrub,sanity-scrub
Signed-off-by: Fan Yong <fan.yong@intel.com>
Change-Id: I4703fc7f99d7b0a0f769127b5cdba5a2b992250d
Reviewed-on: http://review.whamcloud.com/16439
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Alex Zhuravlev <alexey.zhuravlev@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
rc = osd_get_lma(info, inode, dentry, lma);
if (rc == -ENODATA) {
rc = osd_get_idif(info, inode, dentry, oi_fid);
rc = osd_get_lma(info, inode, dentry, lma);
if (rc == -ENODATA) {
rc = osd_get_idif(info, inode, dentry, oi_fid);
+ if (rc > 0 || rc == -ENODATA) {
oi_fid = NULL;
rc = 0;
}
}
iput(inode);
oi_fid = NULL;
rc = 0;
}
}
iput(inode);
- /* If the OST-object has neither FID-in-LMA nor FID-in-ff, it is
- * either a crashed object or a uninitialized one. Replace it. */
- if (rc == -ENODATA || oi_fid == NULL)
- goto update;
-
if (rc != 0)
GOTO(out, rc);
if (rc != 0)
GOTO(out, rc);
- if (lu_fid_eq(fid, oi_fid)) {
+ /* If the OST-object has neither FID-in-LMA nor FID-in-ff, it is
+ * either a crashed object or a uninitialized one. Replace it. */
+ if (oi_fid != NULL && lu_fid_eq(fid, oi_fid)) {
CERROR("%s: the FID "DFID" is used by two objects: "
"%u/%u %u/%u\n", osd_name(osd), PFID(fid),
oi_id->oii_ino, oi_id->oii_gen,
CERROR("%s: the FID "DFID" is used by two objects: "
"%u/%u %u/%u\n", osd_name(osd), PFID(fid),
oi_id->oii_ino, oi_id->oii_gen,
iput(inode);
inode = ERR_PTR(-ENOENT);
} else {
iput(inode);
inode = ERR_PTR(-ENOENT);
} else {
+ ldiskfs_clear_inode_state(inode, LDISKFS_STATE_LUSTRE_DESTROY);
if (id->oii_gen == OSD_OII_NOGEN)
osd_id_gen(id, inode->i_ino, inode->i_generation);
if (id->oii_gen == OSD_OII_NOGEN)
osd_id_gen(id, inode->i_ino, inode->i_generation);
+ ldiskfs_clear_inode_state(inode, LDISKFS_STATE_LUSTRE_DESTROY);
+
check_oi:
if (rc != 0) {
LASSERTF(rc == -ESTALE || rc == -ENOENT, "rc = %d\n", rc);
check_oi:
if (rc != 0) {
LASSERTF(rc == -ESTALE || rc == -ENOENT, "rc = %d\n", rc);
osd_trans_exec_op(env, th, OSD_OT_DESTROY);
osd_trans_exec_op(env, th, OSD_OT_DESTROY);
+ ldiskfs_set_inode_state(inode, LDISKFS_STATE_LUSTRE_DESTROY);
result = osd_oi_delete(osd_oti_get(env), osd, fid, oh->ot_handle,
OI_CHECK_FLD);
result = osd_oi_delete(osd_oti_get(env), osd, fid, oh->ot_handle,
OI_CHECK_FLD);
osd_consistency_check(struct osd_thread_info *oti, struct osd_device *dev,
struct osd_idmap_cache *oic)
{
osd_consistency_check(struct osd_thread_info *oti, struct osd_device *dev,
struct osd_idmap_cache *oic)
{
ENTRY;
if (!fid_is_norm(fid) && !fid_is_igif(fid))
ENTRY;
if (!fid_is_norm(fid) && !fid_is_igif(fid))
if (scrub->os_pos_current > id->oii_ino)
if (scrub->os_pos_current > id->oii_ino)
- rc = osd_oi_lookup(oti, dev, fid, id, OI_CHECK_FLD);
- if (rc != 0 && rc != -ENOENT)
- RETURN_EXIT;
+ rc = osd_oi_lookup(oti, dev, fid, id, 0);
+ if (rc == -ENOENT) {
+ struct inode *inode;
+
+ *id = oic->oic_lid;
+ inode = osd_iget(oti, dev, &oic->oic_lid);
+
+ /* The inode has been removed (by race maybe). */
+ if (IS_ERR(inode)) {
+ rc = PTR_ERR(inode);
- if (rc == 0 && osd_id_eq(id, &oic->oic_lid))
- RETURN_EXIT;
+ RETURN(rc == -ESTALE ? -ENOENT : rc);
+ }
+
+ iput(inode);
+ /* The OI mapping is lost. */
+ if (id->oii_gen != OSD_OII_NOGEN)
+ goto trigger;
+ /* The inode may has been reused by others, we do not know,
+ * leave it to be handled by subsequent osd_fid_lookup(). */
+ RETURN(0);
+ } else if (rc != 0 || osd_id_eq(id, &oic->oic_lid)) {
+ RETURN(rc);
+ }
+
+trigger:
if (thread_is_running(&scrub->os_thread)) {
rc = osd_oii_insert(dev, oic, rc == -ENOENT);
/* There is race condition between osd_oi_lookup and OI scrub.
if (thread_is_running(&scrub->os_thread)) {
rc = osd_oii_insert(dev, oic, rc == -ENOENT);
/* There is race condition between osd_oi_lookup and OI scrub.
if (unlikely(rc == -EAGAIN))
goto again;
if (unlikely(rc == -EAGAIN))
goto again;
}
if (!dev->od_noscrub && ++once == 1) {
}
if (!dev->od_noscrub && ++once == 1) {
}
static int osd_fail_fid_lookup(struct osd_thread_info *oti,
}
static int osd_fail_fid_lookup(struct osd_thread_info *oti,
osd_id_gen(id, ino, OSD_OII_NOGEN);
}
osd_id_gen(id, ino, OSD_OII_NOGEN);
}
+ if (rc != 0 || osd_remote_fid(env, dev, fid)) {
- if (osd_remote_fid(env, dev, fid))
- GOTO(out, rc = 0);
-
osd_add_oi_cache(osd_oti_get(env), osd_obj2dev(obj), id, fid);
osd_add_oi_cache(osd_oti_get(env), osd_obj2dev(obj), id, fid);
- osd_consistency_check(oti, dev, oic);
+ rc = osd_consistency_check(oti, dev, oic);
+ if (rc != 0)
+ fid_zero(&oic->oic_fid);
/* OI scrub should skip this inode. */
#define LDISKFS_STATE_LUSTRE_NOSCRUB 31
/* OI scrub should skip this inode. */
#define LDISKFS_STATE_LUSTRE_NOSCRUB 31
+#define LDISKFS_STATE_LUSTRE_DESTROY 30
/** Enable thandle usage statistics */
#define OSD_THANDLE_STATS (0)
/** Enable thandle usage statistics */
#define OSD_THANDLE_STATS (0)
return rc;
if (unlikely(osd_id_eq(id, oi_id)))
return rc;
if (unlikely(osd_id_eq(id, oi_id)))
/* Check whether the mapping for oi_id is valid or not. */
inode = osd_iget(info, osd, oi_id);
/* Check whether the mapping for oi_id is valid or not. */
inode = osd_iget(info, osd, oi_id);
/* There may be conflict unlink during the OI scrub,
* if happend, then remove the new added OI mapping. */
if (ops == DTO_INDEX_INSERT && inode != NULL && !IS_ERR(inode) &&
/* There may be conflict unlink during the OI scrub,
* if happend, then remove the new added OI mapping. */
if (ops == DTO_INDEX_INSERT && inode != NULL && !IS_ERR(inode) &&
- unlikely(inode->i_nlink == 0))
+ unlikely(ldiskfs_test_inode_state(inode,
+ LDISKFS_STATE_LUSTRE_DESTROY)))
osd_scrub_refresh_mapping(info, dev, fid, lid,
DTO_INDEX_DELETE, false,
(val == SCRUB_NEXT_OSTOBJ ||
osd_scrub_refresh_mapping(info, dev, fid, lid,
DTO_INDEX_DELETE, false,
(val == SCRUB_NEXT_OSTOBJ ||
iput(inode);
if (oii != NULL) {
iput(inode);
if (oii != NULL) {
- LASSERT(!list_empty(&oii->oii_list));
+ LASSERT(list_empty(&oii->oii_list));
- spin_lock(&scrub->os_lock);
- list_del_init(&oii->oii_list);
- spin_unlock(&scrub->os_lock);
RETURN(sf->sf_param & SP_FAILOUT ? rc : 0);
}
RETURN(sf->sf_param & SP_FAILOUT ? rc : 0);
}
return SCRUB_NEXT_EXIT;
if (!list_empty(&scrub->os_inconsistent_items)) {
return SCRUB_NEXT_EXIT;
if (!list_empty(&scrub->os_inconsistent_items)) {
- struct osd_inconsistent_item *oii;
+ spin_lock(&scrub->os_lock);
+ if (likely(!list_empty(&scrub->os_inconsistent_items))) {
+ struct osd_inconsistent_item *oii;
- 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;
+ oii = list_entry(scrub->os_inconsistent_items.next,
+ struct osd_inconsistent_item, oii_list);
+ list_del_init(&oii->oii_list);
+ spin_unlock(&scrub->os_lock);
+
+ *oic = &oii->oii_cache;
+ scrub->os_in_prior = 1;
+
+ return 0;
+ }
+ spin_unlock(&scrub->os_lock);
}
rc = osd_scrub_check_update(info, dev, oic, rc);
}
rc = osd_scrub_check_update(info, dev, oic, rc);
+ if (rc != 0) {
+ scrub->os_in_prior = 0;
rc = osd_scrub_checkpoint(scrub);
if (rc != 0) {
rc = osd_scrub_checkpoint(scrub);
if (rc != 0) {