Whamcloud - gitweb
LU-12137 osd-ldiskfs: create locked and unlocked versions of osd lookup code
[fs/lustre-release.git] / lustre / osd-ldiskfs / osd_compat.c
index 680d236..15c395f 100644 (file)
@@ -59,13 +59,87 @@ static void osd_push_ctxt(const struct osd_device *dev,
        OBD_SET_CTXT_MAGIC(newctxt);
        newctxt->pwdmnt = dev->od_mnt;
        newctxt->pwd = dev->od_mnt->mnt_root;
-       newctxt->fs = get_ds();
+       newctxt->fs = KERNEL_DS;
        newctxt->umask = current_umask();
        newctxt->dt = NULL;
 
        push_ctxt(save, newctxt);
 }
 
+struct dentry *osd_lookup_one_len_common(struct osd_device *dev,
+                                        const char *name,
+                                        struct dentry *base, int len,
+                                        enum oi_check_flags flags)
+{
+       struct dentry *dchild;
+
+       /*
+        * We can't use inode_is_locked() directly since we can't know
+        * if the current thread context took the lock earlier or if
+        * another thread context took the lock. OI_LOCKED tells us
+        * if the current thread context has already taken the lock.
+        */
+       if (!(flags & OI_LOCKED)) {
+               /* If another thread took this lock already we will
+                * just have to wait until the other thread is done.
+                */
+               inode_lock(base->d_inode);
+               dchild = lookup_one_len(name, base, len);
+               inode_unlock(base->d_inode);
+       } else {
+               /* This thread context already has taken the lock.
+                * Other threads will have to wait until we are done.
+                */
+               dchild = lookup_one_len(name, base, len);
+       }
+       if (IS_ERR(dchild))
+               return dchild;
+
+       if (dchild->d_inode && unlikely(is_bad_inode(dchild->d_inode))) {
+               CERROR("%s: bad inode returned %lu/%u: rc = -ENOENT\n",
+                      osd_name(dev), dchild->d_inode->i_ino,
+                      dchild->d_inode->i_generation);
+               dput(dchild);
+               dchild = ERR_PTR(-ENOENT);
+       }
+
+       return dchild;
+}
+
+/**
+ * osd_lookup_one_len_unlocked
+ *
+ * @dev:       obd device we are searching
+ * @name:      pathname component to lookup
+ * @base:      base directory to lookup from
+ * @len:       maximum length @len should be interpreted to
+ *
+ * Unlike osd_lookup_one_len, this should be called without the parent
+ * i_mutex held, and will take the i_mutex itself.
+ */
+struct dentry *osd_lookup_one_len_unlocked(struct osd_device *dev,
+                                          const char *name,
+                                          struct dentry *base, int len)
+{
+       return osd_lookup_one_len_common(dev, name, base, len, ~OI_LOCKED);
+}
+
+/**
+ * osd_lookup_one_len - lookup single pathname component
+ *
+ * @dev:       obd device we are searching
+ * @name:      pathname component to lookup
+ * @base:      base directory to lookup from
+ * @len:       maximum length @len should be interpreted to
+ *
+ * The caller must hold inode lock
+ */
+struct dentry *osd_lookup_one_len(struct osd_device *dev, const char *name,
+                                 struct dentry *base, int len)
+{
+       return osd_lookup_one_len_common(dev, name, base, len, OI_LOCKED);
+}
+
 /* utility to make a directory */
 static struct dentry *
 simple_mkdir(const struct lu_env *env, struct osd_device *osd,
@@ -82,7 +156,7 @@ simple_mkdir(const struct lu_env *env, struct osd_device *osd,
 
        // ASSERT_KERNEL_CTXT("kernel doing mkdir outside kernel context\n");
        CDEBUG(D_INODE, "creating directory %.*s\n", (int)strlen(name), name);
-       dchild = ll_lookup_one_len(name, dir, strlen(name));
+       dchild = osd_lookup_one_len_unlocked(osd, name, dir, strlen(name));
        if (IS_ERR(dchild))
                RETURN(dchild);
 
@@ -162,8 +236,8 @@ static int osd_last_rcvd_subdir_count(struct osd_device *osd)
 
        ENTRY;
 
-       dlast = ll_lookup_one_len(LAST_RCVD, osd_sb(osd)->s_root,
-                                 strlen(LAST_RCVD));
+       dlast = osd_lookup_one_len_unlocked(osd, LAST_RCVD, osd_sb(osd)->s_root,
+                                           strlen(LAST_RCVD));
        if (IS_ERR(dlast))
                return PTR_ERR(dlast);
        else if (dlast->d_inode == NULL)
@@ -638,7 +712,7 @@ static int osd_obj_update_entry(struct osd_thread_info *info,
        child->d_name.name = name;
        child->d_name.len = strlen(name);
 
-       ll_vfs_dq_init(parent);
+       dquot_initialize(parent);
        inode_lock(parent);
        bh = osd_ldiskfs_find_entry(parent, &child->d_name, &de, NULL, NULL);
        if (IS_ERR(bh))
@@ -779,7 +853,7 @@ static int osd_obj_del_entry(struct osd_thread_info *info,
        child->d_parent = dird;
        child->d_inode = NULL;
 
-       ll_vfs_dq_init(dir);
+       dquot_initialize(dir);
        inode_lock(dir);
        bh = osd_ldiskfs_find_entry(dir, &child->d_name, &de, NULL, NULL);
        if (IS_ERR(bh)) {
@@ -835,7 +909,7 @@ static int osd_obj_add_entry(struct osd_thread_info *info,
        if (OBD_FAIL_CHECK(OBD_FAIL_OSD_COMPAT_INVALID_ENTRY))
                inode->i_ino++;
 
-       ll_vfs_dq_init(dir->d_inode);
+       dquot_initialize(dir->d_inode);
        inode_lock(dir->d_inode);
        rc = osd_ldiskfs_add_entry(info, osd, th, child, inode, NULL);
        inode_unlock(dir->d_inode);
@@ -1221,8 +1295,8 @@ int osd_obj_map_recover(struct osd_thread_info *info,
        if (IS_ERR(jh))
                RETURN(PTR_ERR(jh));
 
-       ll_vfs_dq_init(src_parent);
-       ll_vfs_dq_init(dir);
+       dquot_initialize(src_parent);
+       dquot_initialize(dir);
 
        inode_lock(src_parent);
        inode_lock(dir);
@@ -1260,7 +1334,8 @@ int osd_obj_map_recover(struct osd_thread_info *info,
                        if (unlikely(rc == -ENOENT))
                                rc = 0;
                }
-               RETURN(rc);
+               if (rc)
+                       RETURN(rc);
        }
 
        bh = osd_ldiskfs_find_entry(src_parent, &src_child->d_name, &de,
@@ -1381,7 +1456,7 @@ int osd_obj_spec_lookup(struct osd_thread_info *info, struct osd_device *osd,
                        RETURN(-ENOENT);
        }
 
-       dentry = ll_lookup_one_len(name, root, strlen(name));
+       dentry = osd_lookup_one_len_unlocked(osd, name, root, strlen(name));
        if (!IS_ERR(dentry)) {
                inode = dentry->d_inode;
                if (inode) {