[PATCH 8/9] nilfs2: add pathname lookup routine from inode number

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This adds pathname lookup routine nilfs_search_path(), which makes up
a full pathname of a given inode number tracking namespace upward from
the inode to the root directory with the parent inode number added to
each inode.

Signed-off-by: Ryusuke Konishi <konishi.ryusuke@xxxxxxxxxxxxx>
---
 fs/nilfs2/namei.c |   92 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/nilfs2/nilfs.h |    5 +++
 2 files changed, 97 insertions(+), 0 deletions(-)

diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index 16bfa37..320e5d3 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -455,6 +455,98 @@ out:
 	return err;
 }
 
+/**
+ * nilfs_search_path - lookup path of inode in a past checkpoint tree
+ * @sb: super block instance
+ * @root: root object
+ * @ino: inode number
+ * @parent_index: parent index number
+ * @buf: buffer in which a pathname to be stored
+ * @bufsz: size of @buf
+ * @namesz: buffer to store size of the acquired pathname
+ */
+ssize_t nilfs_search_path(struct super_block *sb, struct nilfs_root *root,
+			  ino_t ino, int parent_index,
+			  char *buf, size_t bufsz, size_t *namesz)
+{
+	struct inode *inode, *parent;
+	struct nilfs_dir_entry *de;
+	struct page *page;
+	ssize_t ret;
+	size_t namelen;
+	char *cp;
+
+	inode = nilfs_iget(sb, root, ino);
+	if (IS_ERR(inode)) {
+		ret = PTR_ERR(inode);
+		if (ret == -EINVAL)
+			ret = -ENOENT;
+		goto out;
+	}
+
+	cp = buf + bufsz - 1;
+	if (cp - 1 < buf) {
+		/* at least the root directory needs one more character */
+		ret = -ENAMETOOLONG;
+		goto out_iput;
+	}
+	*cp = '\0'; /* end of a pathname */
+	ret = 1;
+
+	if (inode->i_ino == NILFS_ROOT_INO) {
+		*--cp = '/';
+		goto out_iput;
+	}
+
+	do {
+		if (!NILFS_I(inode)->i_parent_ino) {
+			ret = -ENOENT;
+			break;
+		}
+
+		parent = nilfs_iget(sb, root,
+				    NILFS_I(inode)->i_parent_ino);
+		if (IS_ERR(parent)) {
+			ret = PTR_ERR(parent);
+			if (ret == -EINVAL)
+				ret = -ENOENT;
+			break;
+		}
+
+		de = nilfs_find_entry_by_ino(parent, inode->i_ino, &page);
+		if (!de) {
+			iput(parent);
+			ret = -ENOENT;
+			break;
+		}
+
+		namelen = de->name_len;
+		if (cp - (namelen + 1) < buf) {
+			kunmap(page);
+			page_cache_release(page);
+			iput(parent);
+			ret = -ENAMETOOLONG;
+			break;
+		}
+		cp -= namelen;
+		memcpy(cp, de->name, namelen);
+		*--cp = '/';
+		kunmap(page);
+		page_cache_release(page);
+
+		iput(inode);
+		inode = parent;
+
+	} while (inode->i_ino != NILFS_ROOT_INO);
+
+out_iput:
+	iput(inode);
+	if (ret >= 0)
+		*namesz = buf + bufsz - cp;
+out:
+	return ret;
+}
+
 /*
  * Export operations
  */
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index 1e47669..e8e97c2 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -237,6 +237,11 @@ extern struct nilfs_dir_entry *nilfs_dotdot(struct inode *, struct page **);
 extern void nilfs_set_link(struct inode *, struct nilfs_dir_entry *,
 			   struct page *, struct inode *);
 
+/* namei.c */
+ssize_t nilfs_search_path(struct super_block *sb, struct nilfs_root *root,
+			  ino_t ino, int parent_index,
+			  char *buf, size_t bufsz, size_t *namesz);
+
 /* file.c */
 extern int nilfs_sync_file(struct file *, int);
 
-- 
1.7.3.5

--
To unsubscribe from this list: send the line "unsubscribe linux-nilfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Filesystem Development]     [Linux BTRFS]     [Linux CIFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux