-static struct inode *osd_iget_check(struct osd_thread_info *info,
- struct osd_device *dev,
- const struct lu_fid *fid,
- struct osd_inode_id *id,
- bool in_oi)
-{
- struct inode *inode;
- int rc = 0;
- ENTRY;
-
- inode = ldiskfs_iget(osd_sb(dev), id->oii_ino);
- if (IS_ERR(inode)) {
- rc = PTR_ERR(inode);
- if (!in_oi || (rc != -ENOENT && rc != -ESTALE)) {
- CDEBUG(D_INODE, "no inode: ino = %u, rc = %d\n",
- id->oii_ino, rc);
-
- GOTO(put, rc);
- }
-
- goto check_oi;
- }
-
- if (is_bad_inode(inode)) {
- rc = -ENOENT;
- if (!in_oi) {
- CDEBUG(D_INODE, "bad inode: ino = %u\n", id->oii_ino);
-
- GOTO(put, rc);
- }
-
- goto check_oi;
- }
-
- if (id->oii_gen != OSD_OII_NOGEN &&
- inode->i_generation != id->oii_gen) {
- rc = -ESTALE;
- if (!in_oi) {
- CDEBUG(D_INODE, "unmatched inode: ino = %u, "
- "oii_gen = %u, i_generation = %u\n",
- id->oii_ino, id->oii_gen, inode->i_generation);
-
- GOTO(put, rc);
- }
-
- goto check_oi;
- }
-
- if (inode->i_nlink == 0) {
- rc = -ENOENT;
- if (!in_oi) {
- CDEBUG(D_INODE, "stale inode: ino = %u\n", id->oii_ino);
-
- GOTO(put, rc);
- }
-
- goto check_oi;
- }
-
-check_oi:
- if (rc != 0) {
- struct osd_inode_id saved_id = *id;
-
- LASSERTF(rc == -ESTALE || rc == -ENOENT, "rc = %d\n", rc);
-
- rc = osd_oi_lookup(info, dev, fid, id, OI_CHECK_FLD);
- /* XXX: There are some possible cases:
- * 1. rc = 0.
- * Backup/restore caused the OI invalid.
- * 2. rc = 0.
- * Someone unlinked the object but NOT removed
- * the OI mapping, such as mount target device
- * as ldiskfs, and modify something directly.
- * 3. rc = -ENOENT.
- * Someone just removed the object between the
- * former oi_lookup and the iget. It is normal.
- * 4. Other failure cases.
- *
- * Generally, when the device is mounted, it will
- * auto check whether the system is restored from
- * file-level backup or not. We trust such detect
- * to distinguish the 1st case from the 2nd case. */
- if (rc == 0) {
- if (!IS_ERR(inode) && inode->i_generation != 0 &&
- inode->i_generation == id->oii_gen) {
- rc = -ENOENT;
- } else {
- __u32 level = D_LFSCK;
-
- rc = -EREMCHG;
- if (!thread_is_running(&dev->od_scrub.os_thread))
- level |= D_CONSOLE;
-
- CDEBUG(level, "%s: the OI mapping for the FID "
- DFID" become inconsistent, the given ID "
- "%u/%u, the ID in OI mapping %u/%u\n",
- osd_name(dev), PFID(fid),
- saved_id.oii_ino, saved_id.oii_gen,
- id->oii_ino, id->oii_ino);
- }
- }
- } else {
- if (id->oii_gen == OSD_OII_NOGEN)
- osd_id_gen(id, inode->i_ino, inode->i_generation);
-
- /* Do not update file c/mtime in ldiskfs.
- * NB: we don't have any lock to protect this because we don't
- * have reference on osd_object now, but contention with
- * another lookup + attr_set can't happen in the tiny window
- * between if (...) and set S_NOCMTIME. */
- if (!(inode->i_flags & S_NOCMTIME))
- inode->i_flags |= S_NOCMTIME;
- }
-
- GOTO(put, rc);
-
-put:
- if (rc != 0) {
- if (!IS_ERR(inode))
- iput(inode);
-
- inode = ERR_PTR(rc);
- }
-
- return inode;
-}
-