All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
To: miklos@szeredi.hu
Cc: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>,
	Amir Goldstein <amir73il@gmail.com>,
	Andrei Vagin <avagin@gmail.com>,
	Pavel Tikhomirov <ptikhomirov@virtuozzo.com>,
	David Howells <dhowells@redhat.com>,
	linux-unionfs@vger.kernel.org, linux-fsdevel@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [RFC PATCH 1/1] overlayfs: add ioctls that allows to get fhandle for layers dentries
Date: Sun,  4 Oct 2020 22:24:01 +0300	[thread overview]
Message-ID: <20201004192401.9738-2-alexander.mikhalitsyn@virtuozzo.com> (raw)
In-Reply-To: <20201004192401.9738-1-alexander.mikhalitsyn@virtuozzo.com>

Add several ioctls to ovl_dir_operations that allows to get file handles
for upperdir, workdir, lowerdir dentries. Special {s_dev; fhandle}
format used. (Ideally should be {mnt_id; fhandle} but this impossible
because overlayfs not keeps mounts refcnt for layers.)

Added ioctls list:
OVL_IOC_GETLWRFHNDLSNUM - get lowerdirs count
OVL_IOC_GETLWRFHNDL - get i-th lowerdir fhandle
OVL_IOC_GETUPPRFHNDL - get upperdir fhandle
OVL_IOC_GETWRKFHNDL - get workdir fhandle

Cc: Amir Goldstein <amir73il@gmail.com>
Cc: Andrei Vagin <avagin@gmail.com>
Cc: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Cc: Miklos Szeredi <miklos@szeredi.hu>
Cc: David Howells <dhowells@redhat.com>
Cc: linux-unionfs@vger.kernel.org
Cc: linux-fsdevel@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
---
 fs/overlayfs/readdir.c | 160 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 160 insertions(+)

diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
index 596002054ac6..12ee043d2b3a 100644
--- a/fs/overlayfs/readdir.c
+++ b/fs/overlayfs/readdir.c
@@ -13,6 +13,7 @@
 #include <linux/security.h>
 #include <linux/cred.h>
 #include <linux/ratelimit.h>
+#include <linux/exportfs.h>
 #include "overlayfs.h"
 
 struct ovl_cache_entry {
@@ -58,6 +59,20 @@ struct ovl_dir_file {
 	struct file *upperfile;
 };
 
+struct ovl_mnt_opt_fh {
+	__u32 s_dev;
+	struct file_handle fh;
+	/* use f_handle field from struct file_handle */
+	__u8 __fhdata[MAX_HANDLE_SZ];
+};
+
+struct ovl_mnt_opt_fh_req {
+	union {
+		unsigned int lowernum;
+		struct ovl_mnt_opt_fh result;
+	};
+} __packed;
+
 static struct ovl_cache_entry *ovl_cache_entry_from_node(struct rb_node *n)
 {
 	return rb_entry(n, struct ovl_cache_entry, node);
@@ -942,6 +957,150 @@ static int ovl_dir_open(struct inode *inode, struct file *file)
 	return 0;
 }
 
+static long ovl_ioctl_get_lowers_num(struct super_block *sb)
+{
+	struct ovl_entry *oe = sb->s_root->d_fsdata;
+	return oe->numlower;
+}
+
+static struct ovl_mnt_opt_fh *__ovl_encode_mnt_opt_fh(struct dentry *dentry)
+{
+	struct ovl_mnt_opt_fh *opt_fh;
+	int fh_type, dwords;
+	int buflen = MAX_HANDLE_SZ;
+	int err;
+
+	opt_fh = kzalloc(sizeof(struct ovl_mnt_opt_fh), GFP_KERNEL);
+	if (!opt_fh)
+		return ERR_PTR(-ENOMEM);
+
+	/* we ask for a non connected handle */
+	dwords = buflen >> 2;
+	fh_type = exportfs_encode_fh(dentry, (void *)opt_fh->fh.f_handle, &dwords, 0);
+	buflen = (dwords << 2);
+
+	err = -EIO;
+	if (WARN_ON(fh_type < 0) ||
+	    WARN_ON(buflen > MAX_HANDLE_SZ) ||
+	    WARN_ON(fh_type == FILEID_INVALID))
+		goto out_err;
+
+	opt_fh->fh.handle_type = fh_type;
+	opt_fh->fh.handle_bytes = buflen;
+
+	/*
+	 * Ideally, we want to have mnt_id+fhandle, but overlayfs not
+	 * keep refcnts on layers mounts and we couldn't determine
+	 * mnt_ids for layers. So, let's give s_dev to CRIU.
+	 * It's better than nothing.
+	 */
+	opt_fh->s_dev = dentry->d_sb->s_dev;
+
+	return opt_fh;
+
+out_err:
+	kfree(opt_fh);
+	return ERR_PTR(err);
+}
+
+static long __ovl_ioctl_get_fhandle(struct dentry *origin,
+				    unsigned long arg)
+{
+	struct ovl_mnt_opt_fh *fh;
+	int ret = 0;
+
+	fh = __ovl_encode_mnt_opt_fh(origin);
+	if (IS_ERR(fh))
+		return PTR_ERR(fh);
+
+	if (copy_to_user((struct ovl_mnt_opt_fh __user *)arg,
+			 fh, sizeof(*fh)))
+		ret = -EFAULT;
+
+	kfree(fh);
+	return ret;
+}
+
+static long ovl_ioctl_get_lower_fhandle(struct super_block *sb,
+					unsigned long arg)
+{
+	struct ovl_entry *oe = sb->s_root->d_fsdata;
+	struct dentry *origin;
+	struct ovl_mnt_opt_fh_req input;
+
+	BUILD_BUG_ON(sizeof(struct ovl_mnt_opt_fh_req) != sizeof(struct ovl_mnt_opt_fh));
+
+	if (copy_from_user(&input, (struct ovl_mnt_opt_fh_req __user *)arg,
+			   sizeof(input)))
+		return -EFAULT;
+
+	if (input.lowernum >= oe->numlower)
+		return -EINVAL;
+
+	origin = oe->lowerstack[input.lowernum].dentry;
+
+	return __ovl_ioctl_get_fhandle(origin, arg);
+}
+
+static long ovl_ioctl_get_upper_fhandle(struct super_block *sb,
+					unsigned long arg)
+{
+	struct ovl_fs *ofs = sb->s_fs_info;
+	struct dentry *origin;
+
+	if (!ofs->config.upperdir)
+		return -EINVAL;
+
+	origin = OVL_I(d_inode(sb->s_root))->__upperdentry;
+
+	return __ovl_ioctl_get_fhandle(origin, arg);
+}
+
+static long ovl_ioctl_get_work_fhandle(struct super_block *sb,
+				       unsigned long arg)
+{
+	struct ovl_fs *ofs = sb->s_fs_info;
+
+	if (!ofs->config.upperdir)
+		return -EINVAL;
+
+	return __ovl_ioctl_get_fhandle(ofs->workbasedir, arg);
+}
+
+#define	OVL_IOC_GETLWRFHNDLSNUM			_IO('o', 1)
+// DISCUSS: what if MAX_HANDLE_SZ will change?
+#define	OVL_IOC_GETLWRFHNDL			_IOR('o', 2, struct ovl_mnt_opt_fh)
+#define	OVL_IOC_GETUPPRFHNDL			_IOR('o', 3, struct ovl_mnt_opt_fh)
+#define	OVL_IOC_GETWRKFHNDL			_IOR('o', 4, struct ovl_mnt_opt_fh)
+
+static long ovl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	long ret;
+
+	switch (cmd) {
+	case OVL_IOC_GETLWRFHNDLSNUM:
+		ret = ovl_ioctl_get_lowers_num(file_inode(file)->i_sb);
+		break;
+
+	case OVL_IOC_GETLWRFHNDL:
+		ret = ovl_ioctl_get_lower_fhandle(file_inode(file)->i_sb, arg);
+		break;
+
+	case OVL_IOC_GETUPPRFHNDL:
+		ret = ovl_ioctl_get_upper_fhandle(file_inode(file)->i_sb, arg);
+		break;
+
+	case OVL_IOC_GETWRKFHNDL:
+		ret = ovl_ioctl_get_work_fhandle(file_inode(file)->i_sb, arg);
+		break;
+
+	default:
+		ret = -ENOTTY;
+	}
+
+	return ret;
+}
+
 const struct file_operations ovl_dir_operations = {
 	.read		= generic_read_dir,
 	.open		= ovl_dir_open,
@@ -949,6 +1108,7 @@ const struct file_operations ovl_dir_operations = {
 	.llseek		= ovl_dir_llseek,
 	.fsync		= ovl_dir_fsync,
 	.release	= ovl_dir_release,
+	.unlocked_ioctl	= ovl_ioctl,
 };
 
 int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list)
-- 
2.25.1


  reply	other threads:[~2020-10-04 19:45 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-04 19:24 [RFC PATCH 0/1] overlayfs: C/R enhancments (RFC) Alexander Mikhalitsyn
2020-10-04 19:24 ` Alexander Mikhalitsyn [this message]
2020-10-04 19:48   ` [RFC PATCH 1/1] overlayfs: add ioctls that allows to get fhandle for layers dentries Randy Dunlap
2020-10-05  7:56 ` [RFC PATCH 0/1] overlayfs: C/R enhancments (RFC) Amir Goldstein
2020-10-05 19:46   ` Alexander Mikhalitsyn
2020-10-06  6:53     ` Amir Goldstein
2020-10-05 17:02 ` [RFC PATCH] overlayfs: add OVL_IOC_GETINFOFD ioctl that opens ovlinfofd Alexander Mikhalitsyn
2020-10-05 17:08   ` Randy Dunlap
2020-10-05 17:12     ` Alexander Mikhalitsyn
2020-10-05 17:22       ` Amir Goldstein
2020-10-05 19:39         ` Alexander Mikhalitsyn
2020-10-06  9:54           ` Miklos Szeredi
2020-10-14 14:14 ` [RFC PATCH] overlayfs: add fsinfo(FSINFO_ATTR_OVL_SOURCES) support Alexander Mikhalitsyn
2020-10-04 23:45 [RFC PATCH 1/1] overlayfs: add ioctls that allows to get fhandle for layers dentries kernel test robot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201004192401.9738-2-alexander.mikhalitsyn@virtuozzo.com \
    --to=alexander.mikhalitsyn@virtuozzo.com \
    --cc=amir73il@gmail.com \
    --cc=avagin@gmail.com \
    --cc=dhowells@redhat.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-unionfs@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=ptikhomirov@virtuozzo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.