rc = osd_get_lma(info, inode, dentry, lma);
if (rc == -ENODATA) {
rc = osd_get_idif(info, inode, dentry, oi_fid);
- if (rc > 0) {
+ if (rc > 0 || rc == -ENODATA) {
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 (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,
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);
goto check_oi;
}
+ ldiskfs_clear_inode_state(inode, LDISKFS_STATE_LUSTRE_DESTROY);
+
check_oi:
if (rc != 0) {
LASSERTF(rc == -ESTALE || rc == -ENOENT, "rc = %d\n", rc);
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);
return rc;
}
-static void
+static int
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))
- RETURN_EXIT;
+ RETURN(0);
if (scrub->os_pos_current > id->oii_ino)
- RETURN_EXIT;
+ RETURN(0);
again:
- 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 (unlikely(rc == -EAGAIN))
goto again;
- RETURN_EXIT;
+ RETURN(0);
}
if (!dev->od_noscrub && ++once == 1) {
goto again;
}
- EXIT;
+ RETURN(0);
}
static int osd_fail_fid_lookup(struct osd_thread_info *oti,
osd_id_gen(id, ino, OSD_OII_NOGEN);
}
- if (rc != 0) {
+ if (rc != 0 || osd_remote_fid(env, dev, fid)) {
fid_zero(&oic->oic_fid);
+
GOTO(out, rc);
}
- 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_consistency_check(oti, dev, oic);
+ rc = osd_consistency_check(oti, dev, oic);
+ if (rc != 0)
+ fid_zero(&oic->oic_fid);
} else {
rc = -ENOENT;
}
/* 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)
return rc;
if (unlikely(osd_id_eq(id, oi_id)))
- return 0;
+ return 1;
/* 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) &&
- 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 ||
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);
OBD_FREE_PTR(oii);
}
+
RETURN(sf->sf_param & SP_FAILOUT ? rc : 0);
}
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);
}
if (noslot)
}
rc = osd_scrub_check_update(info, dev, oic, rc);
- if (rc != 0)
+ if (rc != 0) {
+ scrub->os_in_prior = 0;
return rc;
+ }
rc = osd_scrub_checkpoint(scrub);
if (rc != 0) {