[RFC v2 53/83] Namei: lookup.

2018-03-10 Thread Andiry Xu
From: Andiry Xu 

NOVA lookup the inode number by searching the radix tree with
the filename hash value and locating the corresponding dentry on the log.

Signed-off-by: Andiry Xu 
---
 fs/nova/Makefile |  3 +-
 fs/nova/inode.c  |  2 ++
 fs/nova/namei.c  | 97 
 fs/nova/nova.h   |  4 +++
 4 files changed, 105 insertions(+), 1 deletion(-)
 create mode 100644 fs/nova/namei.c

diff --git a/fs/nova/Makefile b/fs/nova/Makefile
index 3a3243c..eb97e46 100644
--- a/fs/nova/Makefile
+++ b/fs/nova/Makefile
@@ -4,4 +4,5 @@
 
 obj-$(CONFIG_NOVA_FS) += nova.o
 
-nova-y := balloc.o bbuild.o dir.o inode.o journal.o log.o rebuild.o stats.o 
super.o
+nova-y := balloc.o bbuild.o dir.o inode.o journal.o log.o namei.o\
+ rebuild.o stats.o super.o
diff --git a/fs/nova/inode.c b/fs/nova/inode.c
index 17addd3..2d3f7a3 100644
--- a/fs/nova/inode.c
+++ b/fs/nova/inode.c
@@ -181,6 +181,7 @@ static int nova_read_inode(struct super_block *sb, struct 
inode *inode,
case S_IFREG:
break;
case S_IFDIR:
+   inode->i_op = _dir_inode_operations;
inode->i_fop = _dir_operations;
break;
case S_IFLNK:
@@ -881,6 +882,7 @@ struct inode *nova_new_vfs_inode(enum nova_new_inode_type 
type,
inode->i_mapping->a_ops = _aops_dax;
break;
case TYPE_MKDIR:
+   inode->i_op = _dir_inode_operations;
inode->i_fop = _dir_operations;
inode->i_mapping->a_ops = _aops_dax;
set_nlink(inode, 2);
diff --git a/fs/nova/namei.c b/fs/nova/namei.c
new file mode 100644
index 000..8076f5b
--- /dev/null
+++ b/fs/nova/namei.c
@@ -0,0 +1,97 @@
+/*
+ * BRIEF DESCRIPTION
+ *
+ * Inode operations for directories.
+ *
+ * Copyright 2015-2016 Regents of the University of California,
+ * UCSD Non-Volatile Systems Lab, Andiry Xu 
+ * Copyright 2012-2013 Intel Corporation
+ * Copyright 2009-2011 Marco Stornelli 
+ * Copyright 2003 Sony Corporation
+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include 
+#include 
+#include "nova.h"
+#include "journal.h"
+#include "inode.h"
+
+static ino_t nova_inode_by_name(struct inode *dir, struct qstr *entry,
+struct nova_dentry **res_entry)
+{
+   struct super_block *sb = dir->i_sb;
+   struct nova_dentry *direntry;
+
+   direntry = nova_find_dentry(sb, NULL, dir,
+   entry->name, entry->len);
+   if (direntry == NULL)
+   return 0;
+
+   *res_entry = direntry;
+   return direntry->ino;
+}
+
+static struct dentry *nova_lookup(struct inode *dir, struct dentry *dentry,
+  unsigned int flags)
+{
+   struct inode *inode = NULL;
+   struct nova_dentry *de;
+   ino_t ino;
+   timing_t lookup_time;
+
+   NOVA_START_TIMING(lookup_t, lookup_time);
+   if (dentry->d_name.len > NOVA_NAME_LEN) {
+   nova_dbg("%s: namelen %u exceeds limit\n",
+   __func__, dentry->d_name.len);
+   return ERR_PTR(-ENAMETOOLONG);
+   }
+
+   nova_dbg_verbose("%s: %s\n", __func__, dentry->d_name.name);
+   ino = nova_inode_by_name(dir, >d_name, );
+   nova_dbg_verbose("%s: ino %lu\n", __func__, ino);
+   if (ino) {
+   inode = nova_iget(dir->i_sb, ino);
+   if (inode == ERR_PTR(-ESTALE) || inode == ERR_PTR(-ENOMEM)
+   || inode == ERR_PTR(-EACCES)) {
+   nova_err(dir->i_sb,
+ "%s: get inode failed: %lu\n",
+ __func__, (unsigned long)ino);
+   return ERR_PTR(-EIO);
+   }
+   }
+
+   NOVA_END_TIMING(lookup_t, lookup_time);
+   return d_splice_alias(inode, dentry);
+}
+
+struct dentry *nova_get_parent(struct dentry *child)
+{
+   struct inode *inode;
+   struct qstr dotdot = QSTR_INIT("..", 2);
+   struct nova_dentry *de = NULL;
+   ino_t ino;
+
+   nova_inode_by_name(child->d_inode, , );
+   if (!de)
+   return ERR_PTR(-ENOENT);
+
+   /* FIXME: can de->ino be avoided by using the return value of
+* nova_inode_by_name()?
+*/
+   ino = le64_to_cpu(de->ino);
+
+   if (ino)
+   inode = nova_iget(child->d_inode->i_sb, ino);
+   else
+   return ERR_PTR(-ENOENT);
+
+   return d_obtain_alias(inode);
+}
+
+const struct inode_operations nova_dir_inode_operations = {
+   .lookup = 

[RFC v2 53/83] Namei: lookup.

2018-03-10 Thread Andiry Xu
From: Andiry Xu 

NOVA lookup the inode number by searching the radix tree with
the filename hash value and locating the corresponding dentry on the log.

Signed-off-by: Andiry Xu 
---
 fs/nova/Makefile |  3 +-
 fs/nova/inode.c  |  2 ++
 fs/nova/namei.c  | 97 
 fs/nova/nova.h   |  4 +++
 4 files changed, 105 insertions(+), 1 deletion(-)
 create mode 100644 fs/nova/namei.c

diff --git a/fs/nova/Makefile b/fs/nova/Makefile
index 3a3243c..eb97e46 100644
--- a/fs/nova/Makefile
+++ b/fs/nova/Makefile
@@ -4,4 +4,5 @@
 
 obj-$(CONFIG_NOVA_FS) += nova.o
 
-nova-y := balloc.o bbuild.o dir.o inode.o journal.o log.o rebuild.o stats.o 
super.o
+nova-y := balloc.o bbuild.o dir.o inode.o journal.o log.o namei.o\
+ rebuild.o stats.o super.o
diff --git a/fs/nova/inode.c b/fs/nova/inode.c
index 17addd3..2d3f7a3 100644
--- a/fs/nova/inode.c
+++ b/fs/nova/inode.c
@@ -181,6 +181,7 @@ static int nova_read_inode(struct super_block *sb, struct 
inode *inode,
case S_IFREG:
break;
case S_IFDIR:
+   inode->i_op = _dir_inode_operations;
inode->i_fop = _dir_operations;
break;
case S_IFLNK:
@@ -881,6 +882,7 @@ struct inode *nova_new_vfs_inode(enum nova_new_inode_type 
type,
inode->i_mapping->a_ops = _aops_dax;
break;
case TYPE_MKDIR:
+   inode->i_op = _dir_inode_operations;
inode->i_fop = _dir_operations;
inode->i_mapping->a_ops = _aops_dax;
set_nlink(inode, 2);
diff --git a/fs/nova/namei.c b/fs/nova/namei.c
new file mode 100644
index 000..8076f5b
--- /dev/null
+++ b/fs/nova/namei.c
@@ -0,0 +1,97 @@
+/*
+ * BRIEF DESCRIPTION
+ *
+ * Inode operations for directories.
+ *
+ * Copyright 2015-2016 Regents of the University of California,
+ * UCSD Non-Volatile Systems Lab, Andiry Xu 
+ * Copyright 2012-2013 Intel Corporation
+ * Copyright 2009-2011 Marco Stornelli 
+ * Copyright 2003 Sony Corporation
+ * Copyright 2003 Matsushita Electric Industrial Co., Ltd.
+ * 2003-2004 (c) MontaVista Software, Inc. , Steve Longerbeam
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include 
+#include 
+#include "nova.h"
+#include "journal.h"
+#include "inode.h"
+
+static ino_t nova_inode_by_name(struct inode *dir, struct qstr *entry,
+struct nova_dentry **res_entry)
+{
+   struct super_block *sb = dir->i_sb;
+   struct nova_dentry *direntry;
+
+   direntry = nova_find_dentry(sb, NULL, dir,
+   entry->name, entry->len);
+   if (direntry == NULL)
+   return 0;
+
+   *res_entry = direntry;
+   return direntry->ino;
+}
+
+static struct dentry *nova_lookup(struct inode *dir, struct dentry *dentry,
+  unsigned int flags)
+{
+   struct inode *inode = NULL;
+   struct nova_dentry *de;
+   ino_t ino;
+   timing_t lookup_time;
+
+   NOVA_START_TIMING(lookup_t, lookup_time);
+   if (dentry->d_name.len > NOVA_NAME_LEN) {
+   nova_dbg("%s: namelen %u exceeds limit\n",
+   __func__, dentry->d_name.len);
+   return ERR_PTR(-ENAMETOOLONG);
+   }
+
+   nova_dbg_verbose("%s: %s\n", __func__, dentry->d_name.name);
+   ino = nova_inode_by_name(dir, >d_name, );
+   nova_dbg_verbose("%s: ino %lu\n", __func__, ino);
+   if (ino) {
+   inode = nova_iget(dir->i_sb, ino);
+   if (inode == ERR_PTR(-ESTALE) || inode == ERR_PTR(-ENOMEM)
+   || inode == ERR_PTR(-EACCES)) {
+   nova_err(dir->i_sb,
+ "%s: get inode failed: %lu\n",
+ __func__, (unsigned long)ino);
+   return ERR_PTR(-EIO);
+   }
+   }
+
+   NOVA_END_TIMING(lookup_t, lookup_time);
+   return d_splice_alias(inode, dentry);
+}
+
+struct dentry *nova_get_parent(struct dentry *child)
+{
+   struct inode *inode;
+   struct qstr dotdot = QSTR_INIT("..", 2);
+   struct nova_dentry *de = NULL;
+   ino_t ino;
+
+   nova_inode_by_name(child->d_inode, , );
+   if (!de)
+   return ERR_PTR(-ENOENT);
+
+   /* FIXME: can de->ino be avoided by using the return value of
+* nova_inode_by_name()?
+*/
+   ino = le64_to_cpu(de->ino);
+
+   if (ino)
+   inode = nova_iget(child->d_inode->i_sb, ino);
+   else
+   return ERR_PTR(-ENOENT);
+
+   return d_obtain_alias(inode);
+}
+
+const struct inode_operations nova_dir_inode_operations = {
+   .lookup = nova_lookup,
+};
diff --git a/fs/nova/nova.h b/fs/nova/nova.h
index 983c6b2..03ea0bd 100644
---