Adds a new ioctl command to look up pathnames of an inode from its
inode number.

Signed-off-by: Ryusuke Konishi <[email protected]>
---
 fs/nilfs2/ioctl.c         |   76 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/nilfs2_fs.h |   13 ++++++++
 2 files changed, 89 insertions(+), 0 deletions(-)

diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index 79f3719..cc468ff 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -812,6 +812,80 @@ out:
        return ret;
 }
 
+/**
+ * nilfs_ioctl_ino_lookup - lookup pathname of inode
+ * @inode: inode on which this ioctl was issued
+ * @argp: pointer to nilfs_ino_lookup_args structure. Where the argv
+ *        member holds the following information
+ *
+ *   argv.v_nmembs: number of pathnames (used for both request and result)
+ *   argv.v_base: buffer in which pathnames will be stored
+ *   argv.v_size: size of pathnames buffer
+ *   argv.v_index: index number of pathnames
+ */
+static int nilfs_ioctl_ino_lookup(struct inode *inode, void __user *argp)
+{
+       struct nilfs_ino_lookup_args largs;
+       struct nilfs_root *root;
+       size_t namesz, bufsz;
+       void *kbuf;
+       void __user *base;
+       int ret;
+
+       ret = -EPERM;
+       if (!capable(CAP_SYS_ADMIN))
+               goto out;
+
+       ret = -EFAULT;
+       if (copy_from_user(&largs, argp, sizeof(largs)))
+               goto out;
+
+       ret = 0;
+       if (largs.argv.v_nmembs == 0)
+               goto out;
+
+       ret = -ERANGE;
+       if (largs.argv.v_size > 4096)
+               goto out;
+
+       bufsz = largs.argv.v_size;
+       base = (void __user *)(unsigned long)largs.argv.v_base;
+       kbuf = kmalloc(bufsz, GFP_NOFS);
+       if (!kbuf) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       down_read(&inode->i_sb->s_umount);
+
+       ret = nilfs_attach_checkpoint(inode->i_sb, largs.cno, false, &root);
+       if (ret < 0)
+               goto out_unlock;
+
+       ret = nilfs_search_path(inode->i_sb, root, largs.ino,
+                               largs.argv.v_index, kbuf, bufsz, &namesz);
+       if (ret >= 0) {
+               largs.argv.v_nmembs = ret;
+               largs.argv.v_size = namesz;
+               ret = 0;
+       }
+       nilfs_put_root(root);
+
+out_unlock:
+       up_read(&inode->i_sb->s_umount);
+
+       if (!ret && copy_to_user(base, kbuf + bufsz - namesz, namesz))
+               ret = -EFAULT;
+
+       kfree(kbuf);
+
+       if (!ret && copy_to_user(&((struct nilfs_ino_lookup_args *)argp)->argv,
+                                &largs.argv, sizeof(largs.argv)))
+               ret = -EFAULT;
+out:
+       return ret;
+}
+
 static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
                                unsigned int cmd, void __user *argp,
                                size_t membsz,
@@ -883,6 +957,8 @@ long nilfs_ioctl(struct file *filp, unsigned int cmd, 
unsigned long arg)
                return nilfs_ioctl_set_alloc_range(inode, argp);
        case NILFS_IOCTL_COMPARE_CHECKPOINTS:
                return nilfs_ioctl_compare_checkpoints(inode, argp);
+       case NILFS_IOCTL_INO_LOOKUP:
+               return nilfs_ioctl_ino_lookup(inode, argp);
        default:
                return -ENOTTY;
        }
diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h
index 599ccd1..9d2f425 100644
--- a/include/linux/nilfs2_fs.h
+++ b/include/linux/nilfs2_fs.h
@@ -863,6 +863,17 @@ struct nilfs_comp_args {
        struct nilfs_argv argv;
 };
 
+/**
+ * struct nilfs_ino_lookup_args - ioctl argument to lookup inode pathname
+ * @ino: inode number
+ * @cno: checkpoint number
+ * @argv: argument vector to exchange pathnames
+ */
+struct nilfs_ino_lookup_args {
+       __u64 ino;
+       __u64 cno;
+       struct nilfs_argv argv;
+};
 
 #define NILFS_IOCTL_IDENT              'n'
 
@@ -892,5 +903,7 @@ struct nilfs_comp_args {
        _IOW(NILFS_IOCTL_IDENT, 0x8C, __u64[2])
 #define NILFS_IOCTL_COMPARE_CHECKPOINTS  \
        _IOWR(NILFS_IOCTL_IDENT, 0x8D, struct nilfs_comp_args)
+#define NILFS_IOCTL_INO_LOOKUP  \
+       _IOWR(NILFS_IOCTL_IDENT, 0x8E, struct nilfs_ino_lookup_args)
 
 #endif /* _LINUX_NILFS_FS_H */
-- 
1.7.3.5

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

Reply via email to