Whamcloud - gitweb
LU-3706 scrub: fix mutex leak in osd_obj_map_recover()
[fs/lustre-release.git] / lustre / osd-ldiskfs / osd_compat.c
index 2f22f5a..2dbd4e4 100644 (file)
@@ -112,7 +112,7 @@ static struct dentry *simple_mkdir(struct dentry *dir, struct vfsmount *mnt,
                GOTO(out_up, dchild);
        }
 
-       err = ll_vfs_mkdir(dir->d_inode, dchild, mnt, mode);
+       err = vfs_mkdir(dir->d_inode, dchild, mode);
        if (err)
                GOTO(out_err, err);
 
@@ -396,9 +396,21 @@ static int osd_ost_init(const struct lu_env *env, struct osd_device *dev)
         LASSERT(dev->od_fsops);
         osd_push_ctxt(dev, &new, &save);
 
-        d = simple_mkdir(rootd, dev->od_mnt, "O", 0755, 1);
+       d = ll_lookup_one_len("O", rootd, strlen("O"));
        if (IS_ERR(d))
                GOTO(cleanup, rc = PTR_ERR(d));
+       if (d->d_inode == NULL) {
+               dput(d);
+               /* The lookup() may be called again inside simple_mkdir().
+                * Since the repeated lookup() only be called for "/O" at
+                * mount time, it will not affect the whole performance. */
+               d = simple_mkdir(rootd, dev->od_mnt, "O", 0755, 1);
+               if (IS_ERR(d))
+                       GOTO(cleanup, rc = PTR_ERR(d));
+
+               /* It is quite probably that the device is new formatted. */
+               dev->od_maybe_new = 1;
+       }
 
        inode = d->d_inode;
        ldiskfs_set_inode_state(inode, LDISKFS_STATE_LUSTRE_NO_OI);
@@ -1109,11 +1121,16 @@ int osd_obj_map_recover(struct osd_thread_info *info,
                 *      So keep it there before we have suitable solution. */
                brelse(bh);
 
+               mutex_unlock(&dir->i_mutex);
+               mutex_unlock(&src_parent->i_mutex);
+
+               rc = -EEXIST;
                /* If the src object has never been modified, then remove it. */
                if (inode->i_size == 0 && inode->i_mode & S_ISUID &&
                    inode->i_mode & S_ISGID)
-                       ll_vfs_unlink(src_parent, src_child, osd->od_mnt);
-               GOTO(unlock_src, rc = 0);
+                       rc = vfs_unlink(src_parent, src_child);
+               ldiskfs_journal_stop(jh);
+               RETURN(rc);
        }
 
        bh = osd_ldiskfs_find_entry(src_parent, src_child, &de, NULL);
@@ -1131,8 +1148,6 @@ int osd_obj_map_recover(struct osd_thread_info *info,
 
 unlock:
        mutex_unlock(&dir->i_mutex);
-
-unlock_src:
        mutex_unlock(&src_parent->i_mutex);
        ldiskfs_journal_stop(jh);
        return rc;