linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/2] cachefiles: use private mounts in cache->mnt
@ 2021-04-07  9:02 Christian Brauner
  2021-04-07  9:02 ` [PATCH v2 2/2] cachefiles: extend ro check to private mount Christian Brauner
  0 siblings, 1 reply; 4+ messages in thread
From: Christian Brauner @ 2021-04-07  9:02 UTC (permalink / raw)
  To: David Howells, linux-cachefs
  Cc: linux-fsdevel, Amir Goldstein, Christian Brauner

From: Christian Brauner <christian.brauner@ubuntu.com>

Since [1] we support creating private mounts from a given path's
vfsmount. This makes them very suitable for any filesystem or
filesystem functionality that piggybacks on paths of another filesystem.
Overlayfs and ecryptfs (which I'll port next) are just two such
examples.

Without trying to imply to many similarities cachefiles have one thing
in common with stacking filesystems namely that they also stack on top
of existing paths. These paths are then used as caches for a netfs.
Since private mounts aren't attached in the filesystem the aren't
affected by mount property changes after cachefiles makes use of them.
This seems a rather desirable property as the underlying path can't e.g.
suddenly go from read-write to read-only and in general it means that
cachefiles is always in full control of the underlying mount after the
user has allowed it to be used as a cache (apart from operations that
affect the superblock of course).

Besides that - and probably irrelevant from the perspective of a
cachefiles developer - it also makes things simpler for a variety of
other vfs features. One concrete example is fanotify. When the path->mnt
of the path that is used as a cache has been marked with FAN_MARK_MOUNT
the semantics get tricky as it isn't clear whether the watchers of
path->mnt should get notified about fsnotify events when files are
created by cachefilesd via path->mnt. Using a private mount let's us
elegantly handle this case too and aligns the behavior of stacks created
by overlayfs.

Reading through the codebase cachefiles currently takes path->mnt and
stashes it in cache->mnt. Everytime a cache object needs to be created,
looked-up, or in some other form interacted with cachefiles will create
a custom path comprised of cache->mnt and the relevant dentry it is
interested in:

struct path cachefiles_path = {
        .mnt = cache->mnt,
        .dentry = dentry,
};

So cachefiles already passes the cache->mnt through everywhere so
supporting private mounts with cachefiles is pretty simply. Instead of
recording path->mnt in cache->mnt we simply record a new private mount
we created as a copy of path->mnt via clone_private_mount() in
cache->mnt. The rest is cleanly handled by cachefiles already.

I have tested this patch with afs:

systemctl stop cachefilesd
sudo mount --bind /var/cache/fscache /var/cache/fscache
systemctl start cachefilesd

sudo apt install kafs-client
systemctl start afs.mount
ls -al /afs
ls -al /afs/grand.central.org/software/openafs/1.9.0
md5sum /afs/grand.central.org/software/openafs/1.9.0/openafs-1.9.0-doc.tar.bz2

cat /proc/fs/fscache/stats | grep [1-9]
  Cookies: idx=148 dat=34 spc=0
  Objects: alc=40 nal=0 avl=40 ded=1
  Pages  : mrk=934 unc=203
  Acquire: n=182 nul=0 noc=0 ok=182 nbf=0 oom=0
  Lookups: n=40 neg=40 pos=0 crt=40 tmo=0
  Retrvls: n=19 ok=0 wt=2 nod=19 nbf=0 int=0 oom=0
  Retrvls: ops=19 owt=2 abt=0
  Stores : n=934 ok=934 agn=0 nbf=0 oom=0
  Stores : ops=21 run=955 pgs=934 rxd=934 olm=0
  VmScan : nos=203 gon=0 bsy=0 can=0 wt=0
  Ops    : pend=2 run=40 enq=955 can=0 rej=0
  Ops    : ini=953 dfr=0 rel=953 gc=0

umount /afs/grand.central.org
md5sum /afs/grand.central.org/software/openafs/1.9.0/openafs-1.9.0-doc.tar.bz2

cat /proc/fs/fscache/stats | grep [1-9]
  Cookies: idx=153 dat=58 spc=0
  Objects: alc=68 nal=0 avl=68 ded=39
  ChkAux : non=0 ok=24 upd=0 obs=0
  Pages  : mrk=1868 unc=934
  Acquire: n=211 nul=0 noc=0 ok=211 nbf=0 oom=0
  Lookups: n=68 neg=40 pos=28 crt=40 tmo=0
  Relinqs: n=39 nul=0 wcr=0 rtr=0
  Retrvls: n=38 ok=19 wt=3 nod=19 nbf=0 int=0 oom=0
  Retrvls: ops=38 owt=2 abt=0
  Stores : n=934 ok=934 agn=0 nbf=0 oom=0
  Stores : ops=21 run=955 pgs=934 rxd=934 olm=0
  VmScan : nos=203 gon=0 bsy=0 can=0 wt=0
  Ops    : pend=2 run=59 enq=955 can=0 rej=0
  Ops    : ini=972 dfr=0 rel=972 gc=0

[1]: c771d683a62e ("vfs: introduce clone_private_mount()")
Cc: Amir Goldstein <amir73il@gmail.com>
Cc: David Howells <dhowells@redhat.com>
Cc: linux-cachefs@redhat.com
Cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
---
/* v2 */
Thank you to David for helping with testing!
- David Howells <dhowells@redhat.com>:
  - Don't copy all of path into cache_path. Simply set both path.dentry
    and path.mnt to the desired values.
  - Check for idmapped mount before calling clone_private_mount().
  - Add paragraphs into commit message to make it easier to parse.
---
 fs/cachefiles/bind.c | 30 ++++++++++++++++++++++--------
 1 file changed, 22 insertions(+), 8 deletions(-)

diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c
index 38bb7764b454..bbace3e51f52 100644
--- a/fs/cachefiles/bind.c
+++ b/fs/cachefiles/bind.c
@@ -81,7 +81,7 @@ int cachefiles_daemon_bind(struct cachefiles_cache *cache, char *args)
 static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
 {
 	struct cachefiles_object *fsdef;
-	struct path path;
+	struct path path, cache_path;
 	struct kstatfs stats;
 	struct dentry *graveyard, *cachedir, *root;
 	const struct cred *saved_cred;
@@ -115,16 +115,23 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
 	if (ret < 0)
 		goto error_open_root;
 
-	cache->mnt = path.mnt;
-	root = path.dentry;
-
-	ret = -EINVAL;
 	if (mnt_user_ns(path.mnt) != &init_user_ns) {
+		ret = -EINVAL;
+		cache->mnt = NULL;
 		pr_warn("File cache on idmapped mounts not supported");
 		goto error_unsupported;
 	}
 
+	cache->mnt = clone_private_mount(&path);
+	if (IS_ERR(cache->mnt)) {
+		ret = PTR_ERR(cache->mnt);
+		cache->mnt = NULL;
+		pr_warn("Failed to create private mount for file cache\n");
+		goto error_unsupported;
+	}
+
 	/* check parameters */
+	root = path.dentry;
 	ret = -EOPNOTSUPP;
 	if (d_is_negative(root) ||
 	    !d_backing_inode(root)->i_op->lookup ||
@@ -144,8 +151,10 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
 	if (ret < 0)
 		goto error_unsupported;
 
+	cache_path.dentry = path.dentry;
+	cache_path.mnt = cache->mnt;
 	/* get the cache size and blocksize */
-	ret = vfs_statfs(&path, &stats);
+	ret = vfs_statfs(&cache_path, &stats);
 	if (ret < 0)
 		goto error_unsupported;
 
@@ -229,7 +238,12 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
 
 	/* done */
 	set_bit(CACHEFILES_READY, &cache->flags);
-	dput(root);
+
+	/*
+	 * We've created a private mount and we've stashed our "cache" and
+	 * "graveyard" dentries so we don't need the path anymore.
+	 */
+	path_put(&path);
 
 	pr_info("File cache on %s registered\n", cache->cache.identifier);
 
@@ -242,11 +256,11 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
 	dput(cache->graveyard);
 	cache->graveyard = NULL;
 error_unsupported:
+	path_put(&path);
 	mntput(cache->mnt);
 	cache->mnt = NULL;
 	dput(fsdef->dentry);
 	fsdef->dentry = NULL;
-	dput(root);
 error_open_root:
 	kmem_cache_free(cachefiles_object_jar, fsdef);
 error_root_object:

base-commit: a5e13c6df0e41702d2b2c77c8ad41677ebb065b3
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v2 2/2] cachefiles: extend ro check to private mount
  2021-04-07  9:02 [PATCH v2 1/2] cachefiles: use private mounts in cache->mnt Christian Brauner
@ 2021-04-07  9:02 ` Christian Brauner
  2021-04-07 10:30   ` Amir Goldstein
  0 siblings, 1 reply; 4+ messages in thread
From: Christian Brauner @ 2021-04-07  9:02 UTC (permalink / raw)
  To: David Howells, linux-cachefs
  Cc: linux-fsdevel, Amir Goldstein, Christian Brauner

From: Christian Brauner <christian.brauner@ubuntu.com>

So far cachefiles only verified that the superblock wasn't read-only but
didn't check whether the mount was. This made sense when we did not use
a private mount because the read-only state could change at any point.

Now that we have a private mount and mount properties can't change
behind our back extend the read-only check to include the vfsmount.

The __mnt_is_readonly() helper will check both the mount and the
superblock.  Note that before we checked root->d_sb and now we check
mnt->mnt_sb but since we have a matching <vfsmount, dentry> pair here
this is only syntactical change, not a semantic one.

Here's how this works:

mount -o ro --bind /var/cache/fscache/ /var/cache/fscache/

systemctl start cachefilesd
  Job for cachefilesd.service failed because the control process exited with error code.
  See "systemctl status cachefilesd.service" and "journalctl -xe" for details.

dmesg | grep CacheFiles
  [    2.922514] CacheFiles: Loaded
  [  272.206907] CacheFiles: Failed to register: -30

errno 30
  EROFS 30 Read-only file system

Cc: David Howells <dhowells@redhat.com>
Cc: linux-cachefs@redhat.com
Cc: linux-fsdevel@vger.kernel.org
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
---
/* v2 */
patch introduced
---
 fs/cachefiles/bind.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c
index bbace3e51f52..cb8dd9ecc090 100644
--- a/fs/cachefiles/bind.c
+++ b/fs/cachefiles/bind.c
@@ -141,8 +141,13 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
 	    !root->d_sb->s_op->sync_fs)
 		goto error_unsupported;
 
+	/*
+	 * Verify our mount and superblock aren't read-only.
+	 * Note, while our private mount is guaranteed to not change anymore
+	 * the superblock may still go read-only later.
+	 */
 	ret = -EROFS;
-	if (sb_rdonly(root->d_sb))
+	if (__mnt_is_readonly(cache->mnt))
 		goto error_unsupported;
 
 	/* determine the security of the on-disk cache as this governs
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH v2 2/2] cachefiles: extend ro check to private mount
  2021-04-07  9:02 ` [PATCH v2 2/2] cachefiles: extend ro check to private mount Christian Brauner
@ 2021-04-07 10:30   ` Amir Goldstein
  2021-04-07 11:50     ` Christian Brauner
  0 siblings, 1 reply; 4+ messages in thread
From: Amir Goldstein @ 2021-04-07 10:30 UTC (permalink / raw)
  To: Christian Brauner
  Cc: David Howells, linux-cachefs, linux-fsdevel, Christian Brauner,
	Miklos Szeredi, Tyler Hicks

On Wed, Apr 7, 2021 at 12:02 PM Christian Brauner <brauner@kernel.org> wrote:
>
> From: Christian Brauner <christian.brauner@ubuntu.com>
>
> So far cachefiles only verified that the superblock wasn't read-only but
> didn't check whether the mount was. This made sense when we did not use
> a private mount because the read-only state could change at any point.
>
> Now that we have a private mount and mount properties can't change
> behind our back extend the read-only check to include the vfsmount.
>
> The __mnt_is_readonly() helper will check both the mount and the
> superblock.  Note that before we checked root->d_sb and now we check
> mnt->mnt_sb but since we have a matching <vfsmount, dentry> pair here
> this is only syntactical change, not a semantic one.
>
> Here's how this works:
>
> mount -o ro --bind /var/cache/fscache/ /var/cache/fscache/
>
> systemctl start cachefilesd
>   Job for cachefilesd.service failed because the control process exited with error code.
>   See "systemctl status cachefilesd.service" and "journalctl -xe" for details.
>
> dmesg | grep CacheFiles
>   [    2.922514] CacheFiles: Loaded
>   [  272.206907] CacheFiles: Failed to register: -30
>
> errno 30
>   EROFS 30 Read-only file system
>
> Cc: David Howells <dhowells@redhat.com>
> Cc: linux-cachefs@redhat.com
> Cc: linux-fsdevel@vger.kernel.org
> Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
> ---
> /* v2 */
> patch introduced
> ---
>  fs/cachefiles/bind.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c
> index bbace3e51f52..cb8dd9ecc090 100644
> --- a/fs/cachefiles/bind.c
> +++ b/fs/cachefiles/bind.c
> @@ -141,8 +141,13 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
>             !root->d_sb->s_op->sync_fs)
>                 goto error_unsupported;
>
> +       /*
> +        * Verify our mount and superblock aren't read-only.
> +        * Note, while our private mount is guaranteed to not change anymore
> +        * the superblock may still go read-only later.
> +        */
>         ret = -EROFS;
> -       if (sb_rdonly(root->d_sb))
> +       if (__mnt_is_readonly(cache->mnt))
>                 goto error_unsupported;
>

I suppose ovl_get_upper() and ecryptfs_mount() could use a similar fix?
I can post the ovl fix myself.

Thanks,
Amir.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH v2 2/2] cachefiles: extend ro check to private mount
  2021-04-07 10:30   ` Amir Goldstein
@ 2021-04-07 11:50     ` Christian Brauner
  0 siblings, 0 replies; 4+ messages in thread
From: Christian Brauner @ 2021-04-07 11:50 UTC (permalink / raw)
  To: Amir Goldstein
  Cc: Christian Brauner, David Howells, linux-cachefs, linux-fsdevel,
	Miklos Szeredi, Tyler Hicks

On Wed, Apr 07, 2021 at 01:30:19PM +0300, Amir Goldstein wrote:
> On Wed, Apr 7, 2021 at 12:02 PM Christian Brauner <brauner@kernel.org> wrote:
> >
> > From: Christian Brauner <christian.brauner@ubuntu.com>
> >
> > So far cachefiles only verified that the superblock wasn't read-only but
> > didn't check whether the mount was. This made sense when we did not use
> > a private mount because the read-only state could change at any point.
> >
> > Now that we have a private mount and mount properties can't change
> > behind our back extend the read-only check to include the vfsmount.
> >
> > The __mnt_is_readonly() helper will check both the mount and the
> > superblock.  Note that before we checked root->d_sb and now we check
> > mnt->mnt_sb but since we have a matching <vfsmount, dentry> pair here
> > this is only syntactical change, not a semantic one.
> >
> > Here's how this works:
> >
> > mount -o ro --bind /var/cache/fscache/ /var/cache/fscache/
> >
> > systemctl start cachefilesd
> >   Job for cachefilesd.service failed because the control process exited with error code.
> >   See "systemctl status cachefilesd.service" and "journalctl -xe" for details.
> >
> > dmesg | grep CacheFiles
> >   [    2.922514] CacheFiles: Loaded
> >   [  272.206907] CacheFiles: Failed to register: -30
> >
> > errno 30
> >   EROFS 30 Read-only file system
> >
> > Cc: David Howells <dhowells@redhat.com>
> > Cc: linux-cachefs@redhat.com
> > Cc: linux-fsdevel@vger.kernel.org
> > Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
> > ---
> > /* v2 */
> > patch introduced
> > ---
> >  fs/cachefiles/bind.c | 7 ++++++-
> >  1 file changed, 6 insertions(+), 1 deletion(-)
> >
> > diff --git a/fs/cachefiles/bind.c b/fs/cachefiles/bind.c
> > index bbace3e51f52..cb8dd9ecc090 100644
> > --- a/fs/cachefiles/bind.c
> > +++ b/fs/cachefiles/bind.c
> > @@ -141,8 +141,13 @@ static int cachefiles_daemon_add_cache(struct cachefiles_cache *cache)
> >             !root->d_sb->s_op->sync_fs)
> >                 goto error_unsupported;
> >
> > +       /*
> > +        * Verify our mount and superblock aren't read-only.
> > +        * Note, while our private mount is guaranteed to not change anymore
> > +        * the superblock may still go read-only later.
> > +        */
> >         ret = -EROFS;
> > -       if (sb_rdonly(root->d_sb))
> > +       if (__mnt_is_readonly(cache->mnt))
> >                 goto error_unsupported;
> >
> 
> I suppose ovl_get_upper() and ecryptfs_mount() could use a similar fix?
> I can post the ovl fix myself.

Likely. Note that I still need to port ecryptfs. I hope to get a port
ready for review soon!

Thanks!
Christian

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-04-07 11:50 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-07  9:02 [PATCH v2 1/2] cachefiles: use private mounts in cache->mnt Christian Brauner
2021-04-07  9:02 ` [PATCH v2 2/2] cachefiles: extend ro check to private mount Christian Brauner
2021-04-07 10:30   ` Amir Goldstein
2021-04-07 11:50     ` Christian Brauner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).