if (unlikely(fid_is_acct(fid)))
RETURN(-EPERM);
- /* Parallel control for OI scrub. For most of cases, there is no
- * lock contention. So it will not affect unlink performance. */
- mutex_lock(&inode->i_mutex);
if (S_ISDIR(inode->i_mode)) {
LASSERT(osd_inode_unlinked(inode) || inode->i_nlink == 1);
/* it will check/delete the inode from remote parent,
osd_trans_exec_op(env, th, OSD_OT_DESTROY);
result = osd_oi_delete(osd_oti_get(env), osd, fid, th);
- mutex_unlock(&inode->i_mutex);
/* XXX: add to ext3 orphan list */
/* rc = ext3_orphan_add(handle_t *handle, struct inode *inode) */
return scrub->os_pos_current < ooc->ooc_pos_preload + SCRUB_WINDOW_SIZE;
}
+/**
+ * update/insert/delete the specified OI mapping (@fid @id) according to the ops
+ *
+ * \retval 1, changed nothing
+ * \retval 0, changed successfully
+ * \retval -ve, on error
+ */
static int osd_scrub_refresh_mapping(struct osd_thread_info *info,
struct osd_device *dev,
const struct lu_fid *fid,
RETURN(-ENOMEM);
}
- if (ops == DTO_INDEX_UPDATE) {
+ switch (ops) {
+ case DTO_INDEX_UPDATE:
rc = iam_update(jh, bag, (const struct iam_key *)oi_fid,
(struct iam_rec *)oi_id, ipd);
- } else {
+ if (unlikely(rc == -ENOENT)) {
+ /* Some unlink thread mat removed the OI mapping. */
+ rc = 1;
+ }
+ break;
+ case DTO_INDEX_INSERT:
rc = iam_insert(jh, bag, (const struct iam_key *)oi_fid,
(struct iam_rec *)oi_id, ipd);
- if (rc == -EEXIST) {
+ if (unlikely(rc == -EEXIST)) {
rc = 1;
/* XXX: There are trouble things when adding OI
* mapping for IGIF object, which may cause
*
* Anyway, it is rare, only exists in theory. */
}
+ break;
+ case DTO_INDEX_DELETE:
+ rc = iam_delete(jh, bag, (const struct iam_key *)oi_fid, ipd);
+ if (rc == -ENOENT) {
+ /* It is normal that the unlink thread has removed the
+ * OI mapping already. */
+ rc = 1;
+ }
+ break;
+ default:
+ LASSERTF(0, "Unexpected ops %d\n", ops);
+ break;
}
osd_ipd_put(info->oti_env, bag, ipd);
ldiskfs_journal_stop(jh);
GOTO(out, rc);
}
- /* Prevent the inode to be unlinked during OI scrub. */
- mutex_lock(&inode->i_mutex);
+ /* Check whether the inode to be unlinked during OI scrub. */
if (unlikely(inode->i_nlink == 0)) {
- mutex_unlock(&inode->i_mutex);
iput(inode);
GOTO(out, rc = 0);
}
}
if (ops == DTO_INDEX_INSERT) {
- mutex_unlock(&inode->i_mutex);
+ /* There may be conflict unlink during the OI scrub,
+ * if happend, then remove the new added OI mapping. */
+ if (unlikely(inode->i_nlink == 0))
+ osd_scrub_refresh_mapping(info, dev, fid, lid,
+ DTO_INDEX_DELETE);
iput(inode);
}
up_write(&scrub->os_rwsem);