mirror of https://github.com/torvalds/linux.git
erofs: unify anonymous inodes for blob
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: Jingbo Xu <jefflexu@linux.alibaba.com> Reviewed-by: Jia Zhu <zhujia.zj@bytedance.com> Link: https://lore.kernel.org/r/20230209063913.46341-5-jefflexu@linux.alibaba.com Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
This commit is contained in:
parent
7032809a44
commit
61fef98945
|
|
@ -420,14 +420,14 @@ static int erofs_fscache_register_domain(struct super_block *sb)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static struct erofs_fscache *erofs_fscache_acquire_cookie(struct super_block *sb,
|
||||||
struct erofs_fscache *erofs_fscache_acquire_cookie(struct super_block *sb,
|
char *name, unsigned int flags)
|
||||||
char *name,
|
|
||||||
unsigned int flags)
|
|
||||||
{
|
{
|
||||||
struct fscache_volume *volume = EROFS_SB(sb)->volume;
|
struct fscache_volume *volume = EROFS_SB(sb)->volume;
|
||||||
struct erofs_fscache *ctx;
|
struct erofs_fscache *ctx;
|
||||||
struct fscache_cookie *cookie;
|
struct fscache_cookie *cookie;
|
||||||
|
struct super_block *isb;
|
||||||
|
struct inode *inode;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
||||||
|
|
@ -443,33 +443,32 @@ struct erofs_fscache *erofs_fscache_acquire_cookie(struct super_block *sb,
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
fscache_use_cookie(cookie, false);
|
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) {
|
if (!inode) {
|
||||||
erofs_err(sb, "failed to get anon inode for %s", name);
|
erofs_err(sb, "failed to get anon inode for %s", name);
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto err_cookie;
|
goto err_cookie;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_nlink(inode, 1);
|
|
||||||
inode->i_size = OFFSET_MAX;
|
inode->i_size = OFFSET_MAX;
|
||||||
inode->i_mapping->a_ops = &erofs_fscache_meta_aops;
|
inode->i_mapping->a_ops = &erofs_fscache_meta_aops;
|
||||||
mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
|
mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
|
||||||
inode->i_private = ctx;
|
inode->i_private = ctx;
|
||||||
|
|
||||||
|
ctx->cookie = cookie;
|
||||||
ctx->inode = inode;
|
ctx->inode = inode;
|
||||||
}
|
|
||||||
|
|
||||||
return ctx;
|
return ctx;
|
||||||
|
|
||||||
err_cookie:
|
err_cookie:
|
||||||
fscache_unuse_cookie(ctx->cookie, NULL, NULL);
|
fscache_unuse_cookie(cookie, NULL, NULL);
|
||||||
fscache_relinquish_cookie(ctx->cookie, false);
|
fscache_relinquish_cookie(cookie, false);
|
||||||
err:
|
err:
|
||||||
kfree(ctx);
|
kfree(ctx);
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
|
|
@ -480,18 +479,13 @@ static void erofs_fscache_relinquish_cookie(struct erofs_fscache *ctx)
|
||||||
fscache_unuse_cookie(ctx->cookie, NULL, NULL);
|
fscache_unuse_cookie(ctx->cookie, NULL, NULL);
|
||||||
fscache_relinquish_cookie(ctx->cookie, false);
|
fscache_relinquish_cookie(ctx->cookie, false);
|
||||||
iput(ctx->inode);
|
iput(ctx->inode);
|
||||||
iput(ctx->anon_inode);
|
|
||||||
kfree(ctx->name);
|
kfree(ctx->name);
|
||||||
kfree(ctx);
|
kfree(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static struct erofs_fscache *erofs_domain_init_cookie(struct super_block *sb,
|
||||||
struct erofs_fscache *erofs_fscache_domain_init_cookie(struct super_block *sb,
|
char *name, unsigned int flags)
|
||||||
char *name,
|
|
||||||
unsigned int flags)
|
|
||||||
{
|
{
|
||||||
int err;
|
|
||||||
struct inode *inode;
|
|
||||||
struct erofs_fscache *ctx;
|
struct erofs_fscache *ctx;
|
||||||
struct erofs_domain *domain = EROFS_SB(sb)->domain;
|
struct erofs_domain *domain = EROFS_SB(sb)->domain;
|
||||||
|
|
||||||
|
|
@ -501,35 +495,23 @@ struct erofs_fscache *erofs_fscache_domain_init_cookie(struct super_block *sb,
|
||||||
|
|
||||||
ctx->name = kstrdup(name, GFP_KERNEL);
|
ctx->name = kstrdup(name, GFP_KERNEL);
|
||||||
if (!ctx->name) {
|
if (!ctx->name) {
|
||||||
err = -ENOMEM;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
inode = new_inode(erofs_pseudo_mnt->mnt_sb);
|
|
||||||
if (!inode) {
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
erofs_fscache_relinquish_cookie(ctx);
|
||||||
return ERR_PTR(err);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
}
|
||||||
|
|
||||||
|
refcount_inc(&domain->ref);
|
||||||
|
ctx->domain = domain;
|
||||||
|
list_add(&ctx->node, &erofs_domain_cookies_list);
|
||||||
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static struct erofs_fscache *erofs_domain_register_cookie(struct super_block *sb,
|
||||||
struct erofs_fscache *erofs_domain_register_cookie(struct super_block *sb,
|
char *name, unsigned int flags)
|
||||||
char *name,
|
|
||||||
unsigned int flags)
|
|
||||||
{
|
{
|
||||||
struct erofs_fscache *ctx;
|
struct erofs_fscache *ctx;
|
||||||
struct erofs_domain *domain = EROFS_SB(sb)->domain;
|
struct erofs_domain *domain = EROFS_SB(sb)->domain;
|
||||||
|
|
||||||
|
flags |= EROFS_REG_COOKIE_SHARE;
|
||||||
mutex_lock(&erofs_domain_cookies_lock);
|
mutex_lock(&erofs_domain_cookies_lock);
|
||||||
list_for_each_entry(ctx, &erofs_domain_cookies_list, node) {
|
list_for_each_entry(ctx, &erofs_domain_cookies_list, node) {
|
||||||
if (ctx->domain != domain || strcmp(ctx->name, name))
|
if (ctx->domain != domain || strcmp(ctx->name, name))
|
||||||
|
|
@ -544,7 +526,7 @@ struct erofs_fscache *erofs_domain_register_cookie(struct super_block *sb,
|
||||||
mutex_unlock(&erofs_domain_cookies_lock);
|
mutex_unlock(&erofs_domain_cookies_lock);
|
||||||
return ctx;
|
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);
|
mutex_unlock(&erofs_domain_cookies_lock);
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
@ -583,7 +565,7 @@ int erofs_fscache_register_fs(struct super_block *sb)
|
||||||
int ret;
|
int ret;
|
||||||
struct erofs_sb_info *sbi = EROFS_SB(sb);
|
struct erofs_sb_info *sbi = EROFS_SB(sb);
|
||||||
struct erofs_fscache *fscache;
|
struct erofs_fscache *fscache;
|
||||||
unsigned int flags;
|
unsigned int flags = 0;
|
||||||
|
|
||||||
if (sbi->domain_id)
|
if (sbi->domain_id)
|
||||||
ret = erofs_fscache_register_domain(sb);
|
ret = erofs_fscache_register_domain(sb);
|
||||||
|
|
@ -602,7 +584,6 @@ int erofs_fscache_register_fs(struct super_block *sb)
|
||||||
*
|
*
|
||||||
* Acquired domain/volume will be relinquished in kill_sb() on error.
|
* Acquired domain/volume will be relinquished in kill_sb() on error.
|
||||||
*/
|
*/
|
||||||
flags = EROFS_REG_COOKIE_NEED_INODE;
|
|
||||||
if (sbi->domain_id)
|
if (sbi->domain_id)
|
||||||
flags |= EROFS_REG_COOKIE_NEED_NOEXIST;
|
flags |= EROFS_REG_COOKIE_NEED_NOEXIST;
|
||||||
fscache = erofs_fscache_register_cookie(sb, sbi->fsid, flags);
|
fscache = erofs_fscache_register_cookie(sb, sbi->fsid, flags);
|
||||||
|
|
|
||||||
|
|
@ -107,8 +107,7 @@ struct erofs_domain {
|
||||||
|
|
||||||
struct erofs_fscache {
|
struct erofs_fscache {
|
||||||
struct fscache_cookie *cookie;
|
struct fscache_cookie *cookie;
|
||||||
struct inode *inode;
|
struct inode *inode; /* anonymous inode for the blob */
|
||||||
struct inode *anon_inode;
|
|
||||||
|
|
||||||
/* used for share domain mode */
|
/* used for share domain mode */
|
||||||
struct erofs_domain *domain;
|
struct erofs_domain *domain;
|
||||||
|
|
@ -449,8 +448,8 @@ extern const struct file_operations erofs_dir_fops;
|
||||||
extern const struct iomap_ops z_erofs_iomap_report_ops;
|
extern const struct iomap_ops z_erofs_iomap_report_ops;
|
||||||
|
|
||||||
/* flags for erofs_fscache_register_cookie() */
|
/* flags for erofs_fscache_register_cookie() */
|
||||||
#define EROFS_REG_COOKIE_NEED_INODE 1
|
#define EROFS_REG_COOKIE_SHARE 0x0001
|
||||||
#define EROFS_REG_COOKIE_NEED_NOEXIST 2
|
#define EROFS_REG_COOKIE_NEED_NOEXIST 0x0002
|
||||||
|
|
||||||
void erofs_unmap_metabuf(struct erofs_buf *buf);
|
void erofs_unmap_metabuf(struct erofs_buf *buf);
|
||||||
void erofs_put_metabuf(struct erofs_buf *buf);
|
void erofs_put_metabuf(struct erofs_buf *buf);
|
||||||
|
|
|
||||||
|
|
@ -968,6 +968,8 @@ static void erofs_put_super(struct super_block *sb)
|
||||||
iput(sbi->packed_inode);
|
iput(sbi->packed_inode);
|
||||||
sbi->packed_inode = NULL;
|
sbi->packed_inode = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
erofs_free_dev_context(sbi->devs);
|
||||||
|
sbi->devs = NULL;
|
||||||
erofs_fscache_unregister_fs(sb);
|
erofs_fscache_unregister_fs(sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue