/*
* retrieve object from backend ext fs.
**/
-struct inode *osd_iget(struct osd_thread_info *info, struct osd_device *dev,
- struct osd_inode_id *id)
+static struct inode *osd_iget2(struct osd_thread_info *info,
+ struct osd_device *dev, struct osd_inode_id *id,
+ int *err)
{
- int rc;
+ int rc = 0;
struct inode *inode = NULL;
/*
CDEBUG(D_INODE, "unmatched inode: ino = %u, oii_gen = %u, "
"i_generation = %u\n",
id->oii_ino, id->oii_gen, inode->i_generation);
- iput(inode);
- inode = ERR_PTR(-ESTALE);
+ rc = -ESTALE;
} else if (inode->i_nlink == 0) {
/*
* due to parallel readdir and unlink,
* we can have dead inode here.
*/
CDEBUG(D_INODE, "stale inode: ino = %u\n", id->oii_ino);
- iput(inode);
- inode = ERR_PTR(-ESTALE);
+ rc = -ESTALE;
} else if (is_bad_inode(inode)) {
- rc = -ENOENT;
CWARN("%s: bad inode: ino = %u: rc = %d\n",
- osd_dev2name(dev), id->oii_ino, rc);
- iput(inode);
- inode = ERR_PTR(rc);
+ osd_dev2name(dev), id->oii_ino, -ENOENT);
+ rc = -ENOENT;
} else if ((rc = osd_attach_jinode(inode))) {
- iput(inode);
- inode = ERR_PTR(rc);
+ CDEBUG(D_INODE, "jbd: ino = %u rc = %d\n", id->oii_ino, rc);
} else {
ldiskfs_clear_inode_state(inode, LDISKFS_STATE_LUSTRE_DESTROY);
if (id->oii_gen == OSD_OII_NOGEN)
if (!(inode->i_flags & S_NOCMTIME))
inode->i_flags |= S_NOCMTIME;
}
+
+ *err = rc;
+
+ return inode;
+}
+
+struct inode *osd_iget(struct osd_thread_info *info, struct osd_device *dev,
+ struct osd_inode_id *id)
+{
+ struct inode *inode;
+ int rc = 0;
+
+ inode = osd_iget2(info, dev, id, &rc);
+
+ if (rc) {
+ iput(inode);
+ inode = ERR_PTR(rc);
+ }
+
return inode;
}
*/
again:
- inode = osd_ldiskfs_iget(osd_sb(dev), id->oii_ino);
- if (IS_ERR(inode)) {
- rc = PTR_ERR(inode);
+ inode = osd_iget2(info, dev, id, &rc);
+ if (rc) {
if (!trusted && (rc == -ENOENT || rc == -ESTALE))
goto check_oi;
GOTO(put, rc);
}
- if (is_bad_inode(inode)) {
- rc = -ENOENT;
- if (!trusted)
- goto check_oi;
-
- CDEBUG(D_INODE, "bad inode for FID: "DFID", ino = %u\n",
- PFID(fid), id->oii_ino);
- GOTO(put, rc);
- }
-
- if (id->oii_gen != OSD_OII_NOGEN &&
- inode->i_generation != id->oii_gen) {
- rc = -ESTALE;
- if (!trusted)
- goto check_oi;
-
- CDEBUG(D_INODE, "unmatched inode for FID: "DFID", ino = %u, "
- "oii_gen = %u, i_generation = %u\n", PFID(fid),
- id->oii_ino, id->oii_gen, inode->i_generation);
- GOTO(put, rc);
- }
-
- if (inode->i_nlink == 0) {
- rc = -ENOENT;
- if (!trusted)
- goto check_oi;
-
- CDEBUG(D_INODE, "stale inode for FID: "DFID", ino = %u\n",
- PFID(fid), id->oii_ino);
- GOTO(put, rc);
- }
-
- ldiskfs_clear_inode_state(inode, LDISKFS_STATE_LUSTRE_DESTROY);
-
check_oi:
if (rc != 0) {
__u32 saved_ino = id->oii_ino;
rc = -ENOENT;
else
rc = -EREMCHG;
- } else {
+ } else if (!IS_ERR(inode)) {
if (id->oii_gen == OSD_OII_NOGEN)
osd_id_gen(id, inode->i_ino, inode->i_generation);
}
run_test 20 "Don't trigger OI scrub for irreparable oi repeatedly"
+test_21() {
+ [ $MDSCOUNT -lt 2 ] && skip "needs >= 2 MDTs"
+ [ "$mds1_FSTYPE" != "ldiskfs" ] && skip_env "ldiskfs only test"
+
+ local timeout
+ local td=$TMP/$tdir
+ local device=$(mdsdevname 1)
+
+ echo $device
+
+ timeout=$(do_facet mds2 "$LCTL get_param -n \
+ mdt.$FSNAME-MDT0001.recovery_time_hard")
+ for idx in $(seq $MDSCOUNT); do
+ stop mds${idx}
+ done
+
+ #test reproduce simple situation, when OI record exist
+ #and inode was reused/wrong. Scrub should handle it.
+ do_facet mds1 "mkdir -p $td && mount -t ldiskfs $device $td &&
+ rm -rf $td/update_log_dir/*; umount $td; rm -rf $td"
+
+ for idx in $(seq $MDSCOUNT); do
+ start mds${idx} $(mdsdevname $idx) $MDS_MOUNT_OPTS ||
+ error "mount mds$idx failed"
+ done
+
+ wait_recovery_complete mds2 $((timeout + TIMEOUT))
+
+}
+run_test 21 "don't hang MDS recovery when failed to get update log"
+
+
# restore MDS/OST size
MDSSIZE=${SAVED_MDSSIZE}
OSTSIZE=${SAVED_OSTSIZE}