2022-04-25 12:21:33 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2022, Alibaba Cloud
|
|
|
|
*/
|
|
|
|
#include <linux/fscache.h>
|
|
|
|
#include "internal.h"
|
|
|
|
|
2022-04-25 12:21:35 +00:00
|
|
|
static const struct address_space_operations erofs_fscache_meta_aops = {
|
|
|
|
};
|
|
|
|
|
2022-04-25 12:21:34 +00:00
|
|
|
int erofs_fscache_register_cookie(struct super_block *sb,
|
2022-04-25 12:21:35 +00:00
|
|
|
struct erofs_fscache **fscache,
|
|
|
|
char *name, bool need_inode)
|
2022-04-25 12:21:34 +00:00
|
|
|
{
|
|
|
|
struct fscache_volume *volume = EROFS_SB(sb)->volume;
|
|
|
|
struct erofs_fscache *ctx;
|
|
|
|
struct fscache_cookie *cookie;
|
2022-04-25 12:21:35 +00:00
|
|
|
int ret;
|
2022-04-25 12:21:34 +00:00
|
|
|
|
|
|
|
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
|
|
|
|
if (!ctx)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
cookie = fscache_acquire_cookie(volume, FSCACHE_ADV_WANT_CACHE_SIZE,
|
|
|
|
name, strlen(name), NULL, 0, 0);
|
|
|
|
if (!cookie) {
|
|
|
|
erofs_err(sb, "failed to get cookie for %s", name);
|
2022-04-25 12:21:35 +00:00
|
|
|
ret = -EINVAL;
|
|
|
|
goto err;
|
2022-04-25 12:21:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fscache_use_cookie(cookie, false);
|
|
|
|
ctx->cookie = cookie;
|
|
|
|
|
2022-04-25 12:21:35 +00:00
|
|
|
if (need_inode) {
|
|
|
|
struct inode *const inode = new_inode(sb);
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
ctx->inode = inode;
|
|
|
|
}
|
|
|
|
|
2022-04-25 12:21:34 +00:00
|
|
|
*fscache = ctx;
|
|
|
|
return 0;
|
2022-04-25 12:21:35 +00:00
|
|
|
|
|
|
|
err_cookie:
|
|
|
|
fscache_unuse_cookie(ctx->cookie, NULL, NULL);
|
|
|
|
fscache_relinquish_cookie(ctx->cookie, false);
|
|
|
|
ctx->cookie = NULL;
|
|
|
|
err:
|
|
|
|
kfree(ctx);
|
|
|
|
return ret;
|
2022-04-25 12:21:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void erofs_fscache_unregister_cookie(struct erofs_fscache **fscache)
|
|
|
|
{
|
|
|
|
struct erofs_fscache *ctx = *fscache;
|
|
|
|
|
|
|
|
if (!ctx)
|
|
|
|
return;
|
|
|
|
|
|
|
|
fscache_unuse_cookie(ctx->cookie, NULL, NULL);
|
|
|
|
fscache_relinquish_cookie(ctx->cookie, false);
|
|
|
|
ctx->cookie = NULL;
|
|
|
|
|
2022-04-25 12:21:35 +00:00
|
|
|
iput(ctx->inode);
|
|
|
|
ctx->inode = NULL;
|
|
|
|
|
2022-04-25 12:21:34 +00:00
|
|
|
kfree(ctx);
|
|
|
|
*fscache = NULL;
|
|
|
|
}
|
|
|
|
|
2022-04-25 12:21:33 +00:00
|
|
|
int erofs_fscache_register_fs(struct super_block *sb)
|
|
|
|
{
|
|
|
|
struct erofs_sb_info *sbi = EROFS_SB(sb);
|
|
|
|
struct fscache_volume *volume;
|
|
|
|
char *name;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
name = kasprintf(GFP_KERNEL, "erofs,%s", sbi->opt.fsid);
|
|
|
|
if (!name)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
volume = fscache_acquire_volume(name, NULL, NULL, 0);
|
|
|
|
if (IS_ERR_OR_NULL(volume)) {
|
|
|
|
erofs_err(sb, "failed to register volume for %s", name);
|
|
|
|
ret = volume ? PTR_ERR(volume) : -EOPNOTSUPP;
|
|
|
|
volume = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
sbi->volume = volume;
|
|
|
|
kfree(name);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void erofs_fscache_unregister_fs(struct super_block *sb)
|
|
|
|
{
|
|
|
|
struct erofs_sb_info *sbi = EROFS_SB(sb);
|
|
|
|
|
|
|
|
fscache_relinquish_volume(sbi->volume, NULL, false);
|
|
|
|
sbi->volume = NULL;
|
|
|
|
}
|