Commit 45ee5410 authored by Jingbo Xu's avatar Jingbo Xu Committed by Baokun Li
Browse files

erofs: unify anonymous inodes for blob

mainline inclusion
from mainline-v6.3-rc1
commit 61fef989
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IB5UKT



--------------------------------

Currently there're two anonymous inodes (inode and anon_inode in struct
erofs_fscache) for each blob.  The former was introduced as the
address_space of page cache for bootstrap.

The latter was initially introduced as both the address_space of page
cache and also a sentinel in the shared domain.  Since now the management
of cookies in share domain has been decoupled with the anonymous inode,
there's no need to maintain an extra anonymous inode.  Let's unify these
two anonymous inodes.

Besides, in non-share-domain mode only bootstrap will allocate anonymous
inode.  To simplify the implementation, always allocate anonymous inode
for both bootstrap and data blobs.  Similarly release anonymous inodes
for data blobs when .put_super() is called, or we'll get "VFS: Busy
inodes after unmount." warning.

Also remove the redundant set_nlink() when initializing the anonymous
inode, since i_nlink has already been initialized to 1 when the inode
gets allocated.

Signed-off-by: default avatarJingbo Xu <jefflexu@linux.alibaba.com>
Reviewed-by: default avatarJia Zhu <zhujia.zj@bytedance.com>
Link: https://lore.kernel.org/r/20230209063913.46341-5-jefflexu@linux.alibaba.com


Signed-off-by: default avatarGao Xiang <hsiangkao@linux.alibaba.com>

Conflicts:
	fs/erofs/fscache.c
	fs/erofs/internal.h
	fs/erofs/super.c
[ Because it hasn't switched to folio yet and doesn't have the volume
introduced by the cachefile rewrite patch. ]
Signed-off-by: default avatarBaokun Li <libaokun1@huawei.com>
parent 84ca9df8
Loading
Loading
Loading
Loading
+33 −51
Original line number Diff line number Diff line
@@ -375,13 +375,13 @@ static int erofs_fscache_register_domain(struct super_block *sb)
	return err;
}

static
struct erofs_fscache *erofs_fscache_acquire_cookie(struct super_block *sb,
						   char *name,
						   unsigned int flags)
static struct erofs_fscache *erofs_fscache_acquire_cookie(struct super_block *sb,
						char *name, unsigned int flags)
{
	struct erofs_fscache *ctx;
	struct fscache_cookie *cookie;
	struct super_block *isb;
	struct inode *inode;
	int ret;

	ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
@@ -401,31 +401,31 @@ struct erofs_fscache *erofs_fscache_acquire_cookie(struct super_block *sb,
	}

	//fscache_use_cookie(cookie, false);
	ctx->cookie = cookie;

	if (flags & EROFS_REG_COOKIE_NEED_INODE) {
		struct inode *const inode = new_inode(sb);

	/*
	 * Allocate anonymous inode in global pseudo mount for shareable blobs,
	 * so that they are accessible among erofs fs instances.
	 */
	isb = flags & EROFS_REG_COOKIE_SHARE ? erofs_pseudo_mnt->mnt_sb : sb;
	inode = new_inode(isb);
	if (!inode) {
		erofs_err(sb, "failed to get anon inode for %s", name);
		ret = -ENOMEM;
		goto err_cookie;
	}

		set_nlink(inode, 1);
	inode->i_size = OFFSET_MAX;
	inode->i_mapping->a_ops = &erofs_fscache_meta_aops;
	mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
	inode->i_private = ctx;

	ctx->cookie = cookie;
	ctx->inode = inode;
	}

	return ctx;

err_cookie:
//	fscache_unuse_cookie(ctx->cookie, NULL, NULL);
	fscache_relinquish_cookie(ctx->cookie, NULL, false);
//	fscache_unuse_cookie(cookie, NULL, NULL);
	fscache_relinquish_cookie(cookie, NULL, false);
err:
	kfree(ctx);
	return ERR_PTR(ret);
@@ -436,18 +436,13 @@ static void erofs_fscache_relinquish_cookie(struct erofs_fscache *ctx)
	//fscache_unuse_cookie(ctx->cookie, NULL, NULL);
	fscache_relinquish_cookie(ctx->cookie, NULL, false);
	iput(ctx->inode);
	iput(ctx->anon_inode);
	kfree(ctx->name);
	kfree(ctx);
}

static
struct erofs_fscache *erofs_fscache_domain_init_cookie(struct super_block *sb,
						       char *name,
						       unsigned int flags)
static struct erofs_fscache *erofs_domain_init_cookie(struct super_block *sb,
						char *name, unsigned int flags)
{
	int err;
	struct inode *inode;
	struct erofs_fscache *ctx;
	struct erofs_domain *domain = EROFS_SB(sb)->domain;

@@ -457,35 +452,23 @@ struct erofs_fscache *erofs_fscache_domain_init_cookie(struct super_block *sb,

	ctx->name = kstrdup(name, GFP_KERNEL);
	if (!ctx->name) {
		err = -ENOMEM;
		goto out;
	}

	inode = new_inode(erofs_pseudo_mnt->mnt_sb);
	if (!inode) {
		err = -ENOMEM;
		goto out;
		erofs_fscache_relinquish_cookie(ctx);
		return ERR_PTR(-ENOMEM);
	}

	refcount_inc(&domain->ref);
	ctx->domain = domain;
	ctx->anon_inode = inode;
	list_add(&ctx->node, &erofs_domain_cookies_list);
	inode->i_private = ctx;
	refcount_inc(&domain->ref);
	return ctx;
out:
	erofs_fscache_relinquish_cookie(ctx);
	return ERR_PTR(err);
}

static
struct erofs_fscache *erofs_domain_register_cookie(struct super_block *sb,
						   char *name,
						   unsigned int flags)
static struct erofs_fscache *erofs_domain_register_cookie(struct super_block *sb,
						char *name, unsigned int flags)
{
	struct erofs_fscache *ctx;
	struct erofs_domain *domain = EROFS_SB(sb)->domain;

	flags |= EROFS_REG_COOKIE_SHARE;
	mutex_lock(&erofs_domain_cookies_lock);
	list_for_each_entry(ctx, &erofs_domain_cookies_list, node) {
		if (ctx->domain != domain || strcmp(ctx->name, name))
@@ -500,7 +483,7 @@ struct erofs_fscache *erofs_domain_register_cookie(struct super_block *sb,
		mutex_unlock(&erofs_domain_cookies_lock);
		return ctx;
	}
	ctx = erofs_fscache_domain_init_cookie(sb, name, flags);
	ctx = erofs_domain_init_cookie(sb, name, flags);
	mutex_unlock(&erofs_domain_cookies_lock);
	return ctx;
}
@@ -539,7 +522,7 @@ int erofs_fscache_register_fs(struct super_block *sb)
	int ret;
	struct erofs_sb_info *sbi = EROFS_SB(sb);
	struct erofs_fscache *fscache;
	unsigned int flags;
	unsigned int flags = 0;

	if (sbi->domain_id)
		ret = erofs_fscache_register_domain(sb);
@@ -558,7 +541,6 @@ int erofs_fscache_register_fs(struct super_block *sb)
	 *
	 * Acquired domain/volume will be relinquished in kill_sb() on error.
	 */
	flags = EROFS_REG_COOKIE_NEED_INODE;
	if (sbi->domain_id)
		flags |= EROFS_REG_COOKIE_NEED_NOEXIST;
	fscache = erofs_fscache_register_cookie(sb, sbi->fsid, flags);
+3 −4
Original line number Diff line number Diff line
@@ -91,8 +91,7 @@ struct erofs_domain {

struct erofs_fscache {
	struct fscache_cookie *cookie;
	struct inode *inode;
	struct inode *anon_inode;
	struct inode *inode;	/* anonymous inode for the blob */

	/* used for share domain mode */
	struct erofs_domain *domain;
@@ -496,8 +495,8 @@ static inline void z_erofs_exit_zip_subsystem(void) {}
#endif	/* !CONFIG_EROFS_FS_ZIP */

/* flags for erofs_fscache_register_cookie() */
#define EROFS_REG_COOKIE_NEED_INODE   1
#define EROFS_REG_COOKIE_NEED_NOEXIST 2
#define EROFS_REG_COOKIE_SHARE         0x0001
#define EROFS_REG_COOKIE_NEED_NOEXIST  0x0002

/* fscache.c */
#ifdef CONFIG_EROFS_FS_ONDEMAND
+2 −0
Original line number Diff line number Diff line
@@ -717,6 +717,8 @@ static void erofs_put_super(struct super_block *sb)
	iput(sbi->managed_cache);
	sbi->managed_cache = NULL;
#endif
	erofs_free_dev_context(sbi->devs);
	sbi->devs = NULL;
	erofs_fscache_unregister_cookie(sbi->s_fscache);
	sbi->s_fscache = NULL;
}