Skip to content

Commit

Permalink
netfs: Change netfs_inode_init to allocate memory to allow opt-in
Browse files Browse the repository at this point in the history
Reduce the memory footprint for non-netfs enabled mounts by changing
the netfs_inode structure to contain a "struct inode" and a pointer
to the rest of the netfs data, which is now inside a new structure
"netfs_info".

This keeps the memory footprint equal to the previous footprint
inside a network filesystems inode structure when fscache was
enabled (a struct inode, plus a pointer).

This saves memory for network filesystems inode that would build
in netfs support, but like to opt-in to netfs on some mounts while
opting-out of netfs on other mounts.

FIXME: call netfs_inode_free() as needed (afs, ceph, etc)
FIXME: Check setting of remote_i_size

Signed-off-by: Dave Wysochanski <dwysocha@redhat.com>
  • Loading branch information
DaveWysochanskiRH committed Nov 3, 2022
1 parent 86d0c26 commit bff09aa
Show file tree
Hide file tree
Showing 15 changed files with 92 additions and 58 deletions.
2 changes: 1 addition & 1 deletion fs/9p/cache.c
Expand Up @@ -62,7 +62,7 @@ void v9fs_cache_inode_get_cookie(struct inode *inode)
version = cpu_to_le32(v9inode->qid.version);
path = cpu_to_le64(v9inode->qid.path);
v9ses = v9fs_inode2v9ses(inode);
v9inode->netfs.cache =
v9inode->netfs.info->cache =
fscache_acquire_cookie(v9fs_session_cache(v9ses),
0,
&path, sizeof(path),
Expand Down
17 changes: 7 additions & 10 deletions fs/9p/vfs_inode.c
Expand Up @@ -227,10 +227,16 @@ v9fs_blank_wstat(struct p9_wstat *wstat)
struct inode *v9fs_alloc_inode(struct super_block *sb)
{
struct v9fs_inode *v9inode;
int ret;

v9inode = alloc_inode_sb(sb, v9fs_inode_cache, GFP_KERNEL);
if (!v9inode)
return NULL;
ret = netfs_inode_init(&v9inode->netfs, &v9fs_req_ops);
if (ret) {
kmem_cache_free(v9fs_inode_cache, v9inode);
return NULL;
}
v9inode->writeback_fid = NULL;
v9inode->cache_validity = 0;
mutex_init(&v9inode->v_mutex);
Expand All @@ -244,18 +250,10 @@ struct inode *v9fs_alloc_inode(struct super_block *sb)

void v9fs_free_inode(struct inode *inode)
{
netfs_inode_free(&V9FS_I(inode)->netfs);
kmem_cache_free(v9fs_inode_cache, V9FS_I(inode));
}

/*
* Set parameters for the netfs library
*/
static void v9fs_set_netfs_context(struct inode *inode)
{
struct v9fs_inode *v9inode = V9FS_I(inode);
netfs_inode_init(&v9inode->netfs, &v9fs_req_ops);
}

int v9fs_init_inode(struct v9fs_session_info *v9ses,
struct inode *inode, umode_t mode, dev_t rdev)
{
Expand Down Expand Up @@ -345,7 +343,6 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses,
goto error;
}

v9fs_set_netfs_context(inode);
error:
return err;

Expand Down
7 changes: 6 additions & 1 deletion fs/afs/dynroot.c
Expand Up @@ -48,6 +48,7 @@ struct inode *afs_iget_pseudo_dir(struct super_block *sb, bool root)
struct afs_vnode *vnode;
struct inode *inode;
struct afs_fid fid = {};
int ret;

_enter("");

Expand Down Expand Up @@ -76,7 +77,11 @@ struct inode *afs_iget_pseudo_dir(struct super_block *sb, bool root)
/* there shouldn't be an existing inode */
BUG_ON(!(inode->i_state & I_NEW));

netfs_inode_init(&vnode->netfs, NULL);
ret = netfs_inode_init(&vnode->netfs, NULL);
if (ret) {
_leave("= %d", ret);
return ERR_PTR(ret);
}
inode->i_size = 0;
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
if (root) {
Expand Down
14 changes: 2 additions & 12 deletions fs/afs/inode.c
Expand Up @@ -53,14 +53,6 @@ static noinline void dump_vnode(struct afs_vnode *vnode, struct afs_vnode *paren
dump_stack();
}

/*
* Set parameters for the netfs library
*/
static void afs_set_netfs_context(struct afs_vnode *vnode)
{
netfs_inode_init(&vnode->netfs, &afs_req_ops);
}

/*
* Initialise an inode from the vnode status.
*/
Expand Down Expand Up @@ -138,7 +130,6 @@ static int afs_inode_init_from_status(struct afs_operation *op,
}

afs_set_i_size(vnode, status->size);
afs_set_netfs_context(vnode);

vnode->invalid_before = status->data_version;
inode_set_iversion_raw(&vnode->netfs.inode, status->data_version);
Expand Down Expand Up @@ -248,7 +239,7 @@ static void afs_apply_status(struct afs_operation *op,
* idea of what the size should be that's not the same as
* what's on the server.
*/
vnode->netfs.remote_i_size = status->size;
vnode->netfs.info->remote_i_size = status->size;
if (change_size) {
afs_set_i_size(vnode, status->size);
inode->i_ctime = t;
Expand Down Expand Up @@ -432,7 +423,7 @@ static void afs_get_inode_cache(struct afs_vnode *vnode)
struct afs_vnode_cache_aux aux;

if (vnode->status.type != AFS_FTYPE_FILE) {
vnode->netfs.cache = NULL;
vnode->netfs.info->cache = NULL;
return;
}

Expand Down Expand Up @@ -542,7 +533,6 @@ struct inode *afs_root_iget(struct super_block *sb, struct key *key)

vnode = AFS_FS_I(inode);
vnode->cb_v_break = as->volume->cb_v_break,
afs_set_netfs_context(vnode);

op = afs_alloc_operation(key, as->volume);
if (IS_ERR(op)) {
Expand Down
2 changes: 1 addition & 1 deletion fs/afs/internal.h
Expand Up @@ -679,7 +679,7 @@ static inline void afs_vnode_set_cache(struct afs_vnode *vnode,
struct fscache_cookie *cookie)
{
#ifdef CONFIG_AFS_FSCACHE
vnode->netfs.cache = cookie;
vnode->netfs.info->cache = cookie;
#endif
}

Expand Down
7 changes: 7 additions & 0 deletions fs/afs/super.c
Expand Up @@ -678,11 +678,17 @@ static void afs_i_init_once(void *_vnode)
static struct inode *afs_alloc_inode(struct super_block *sb)
{
struct afs_vnode *vnode;
int ret;

vnode = alloc_inode_sb(sb, afs_inode_cachep, GFP_KERNEL);
if (!vnode)
return NULL;

ret = netfs_inode_init(&vnode->netfs, &afs_req_ops);
if (ret) {
afs_free_inode(AFS_VNODE_TO_I(vnode));
return NULL;
}
atomic_inc(&afs_count_active_inodes);

/* Reset anything that shouldn't leak from one inode to the next. */
Expand All @@ -706,6 +712,7 @@ static struct inode *afs_alloc_inode(struct super_block *sb)

static void afs_free_inode(struct inode *inode)
{
netfs_inode_free(&AFS_FS_I(inode)->netfs);
kmem_cache_free(afs_inode_cachep, AFS_FS_I(inode));
}

Expand Down
2 changes: 1 addition & 1 deletion fs/afs/write.c
Expand Up @@ -384,7 +384,7 @@ static int afs_store_data(struct afs_vnode *vnode, struct iov_iter *iter, loff_t
op->store.write_iter = iter;
op->store.pos = pos;
op->store.size = size;
op->store.i_size = max(pos + size, vnode->netfs.remote_i_size);
op->store.i_size = max(pos + size, vnode->netfs.info->remote_i_size);
op->store.laundering = laundering;
op->mtime = vnode->netfs.inode.i_mtime;
op->flags |= AFS_OPERATION_UNINTR;
Expand Down
6 changes: 5 additions & 1 deletion fs/ceph/inode.c
Expand Up @@ -452,6 +452,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
{
struct ceph_inode_info *ci;
int i;
int ret;

ci = alloc_inode_sb(sb, ceph_inode_cachep, GFP_NOFS);
if (!ci)
Expand All @@ -460,7 +461,9 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
dout("alloc_inode %p\n", &ci->netfs.inode);

/* Set parameters for the netfs library */
netfs_inode_init(&ci->netfs, &ceph_netfs_ops);
ret = netfs_inode_init(&ci->netfs, &ceph_netfs_ops);
if (ret)
return NULL;

spin_lock_init(&ci->i_ceph_lock);

Expand Down Expand Up @@ -554,6 +557,7 @@ void ceph_free_inode(struct inode *inode)
{
struct ceph_inode_info *ci = ceph_inode(inode);

netfs_inode_free(&ceph_inode(inode)->netfs);
kfree(ci->i_symlink);
kmem_cache_free(ceph_inode_cachep, ci);
}
Expand Down
16 changes: 8 additions & 8 deletions fs/netfs/buffered_read.c
Expand Up @@ -170,8 +170,8 @@ void netfs_readahead(struct readahead_control *ractl)
if (IS_ERR(rreq))
return;

if (ctx->ops->begin_cache_operation) {
ret = ctx->ops->begin_cache_operation(rreq);
if (ctx->info->ops->begin_cache_operation) {
ret = ctx->info->ops->begin_cache_operation(rreq);
if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS)
goto cleanup_free;
}
Expand Down Expand Up @@ -228,8 +228,8 @@ int netfs_read_folio(struct file *file, struct folio *folio)
goto alloc_error;
}

if (ctx->ops->begin_cache_operation) {
ret = ctx->ops->begin_cache_operation(rreq);
if (ctx->info->ops->begin_cache_operation) {
ret = ctx->info->ops->begin_cache_operation(rreq);
if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS)
goto discard;
}
Expand Down Expand Up @@ -347,9 +347,9 @@ int netfs_write_begin(struct netfs_inode *ctx,
if (!folio)
return -ENOMEM;

if (ctx->ops->check_write_begin) {
if (ctx->info->ops->check_write_begin) {
/* Allow the netfs (eg. ceph) to flush conflicts. */
ret = ctx->ops->check_write_begin(file, pos, len, &folio, _fsdata);
ret = ctx->info->ops->check_write_begin(file, pos, len, &folio, _fsdata);
if (ret < 0) {
trace_netfs_failure(NULL, NULL, ret, netfs_fail_check_write_begin);
goto error;
Expand Down Expand Up @@ -381,8 +381,8 @@ int netfs_write_begin(struct netfs_inode *ctx,
rreq->no_unlock_folio = folio_index(folio);
__set_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags);

if (ctx->ops->begin_cache_operation) {
ret = ctx->ops->begin_cache_operation(rreq);
if (ctx->info->ops->begin_cache_operation) {
ret = ctx->info->ops->begin_cache_operation(rreq);
if (ret == -ENOMEM || ret == -EINTR || ret == -ERESTARTSYS)
goto error_put;
}
Expand Down
2 changes: 1 addition & 1 deletion fs/netfs/internal.h
Expand Up @@ -94,7 +94,7 @@ static inline void netfs_stat_d(atomic_t *stat)
static inline bool netfs_is_cache_enabled(struct netfs_inode *ctx)
{
#if IS_ENABLED(CONFIG_FSCACHE)
struct fscache_cookie *cookie = ctx->cache;
struct fscache_cookie *cookie = ctx->info->cache;

return fscache_cookie_valid(cookie) && cookie->cache_priv &&
fscache_cookie_enabled(cookie);
Expand Down
2 changes: 1 addition & 1 deletion fs/netfs/objects.c
Expand Up @@ -29,7 +29,7 @@ struct netfs_io_request *netfs_alloc_request(struct address_space *mapping,
rreq->start = start;
rreq->len = len;
rreq->origin = origin;
rreq->netfs_ops = ctx->ops;
rreq->netfs_ops = ctx->info->ops;
rreq->mapping = mapping;
rreq->inode = inode;
rreq->i_size = i_size_read(inode);
Expand Down
12 changes: 6 additions & 6 deletions fs/nfs/fscache.c
Expand Up @@ -166,13 +166,13 @@ void nfs_fscache_init_inode(struct inode *inode)
struct nfs_server *nfss = NFS_SERVER(inode);
struct nfs_inode *nfsi = NFS_I(inode);

netfs_inode(inode)->cache = NULL;
netfs_inode(inode)->info->cache = NULL;
if (!(nfss->fscache && S_ISREG(inode->i_mode)))
return;

nfs_fscache_update_auxdata(&auxdata, inode);

netfs_inode(inode)->cache = fscache_acquire_cookie(
netfs_inode(inode)->info->cache = fscache_acquire_cookie(
nfss->fscache,
0,
nfsi->fh.data, /* index_key */
Expand All @@ -188,7 +188,7 @@ void nfs_fscache_init_inode(struct inode *inode)
void nfs_fscache_clear_inode(struct inode *inode)
{
fscache_relinquish_cookie(netfs_i_cookie(netfs_inode(inode)), false);
netfs_inode(inode)->cache = NULL;
netfs_inode(inode)->info->cache = NULL;
}

/*
Expand Down Expand Up @@ -240,7 +240,7 @@ void nfs_fscache_release_file(struct inode *inode, struct file *filp)

int nfs_netfs_read_folio(struct file *file, struct folio *folio)
{
if (!netfs_inode(folio_inode(folio))->cache)
if (!netfs_inode(folio_inode(folio))->info->cache)
return -ENOBUFS;

return netfs_read_folio(file, folio);
Expand All @@ -250,7 +250,7 @@ int nfs_netfs_readahead(struct readahead_control *ractl)
{
struct inode *inode = ractl->mapping->host;

if (!netfs_inode(inode)->cache)
if (!netfs_inode(inode)->info->cache)
return -ENOBUFS;

netfs_readahead(ractl);
Expand Down Expand Up @@ -354,7 +354,7 @@ void nfs_netfs_readpage_release(struct nfs_page *req)
/*
* If fscache is enabled, netfs will unlock pages.
*/
if (netfs_inode(inode)->cache)
if (netfs_inode(inode)->info->cache)
return;

unlock_page(req->wb_page);
Expand Down
11 changes: 8 additions & 3 deletions fs/nfs/fscache.h
Expand Up @@ -78,9 +78,13 @@ static inline void nfs_netfs_put(struct nfs_netfs_io_data *netfs)
netfs_subreq_terminated(netfs->sreq, netfs->error ?: final_len, false);
kfree(netfs);
}
static inline void nfs_netfs_inode_init(struct nfs_inode *nfsi)
static inline int nfs_netfs_inode_init(struct nfs_inode *nfsi)
{
netfs_inode_init(&nfsi->netfs, &nfs_netfs_ops);
return netfs_inode_init(&nfsi->netfs, &nfs_netfs_ops);
}
static inline void nfs_netfs_inode_free(struct nfs_inode *nfsi)
{
netfs_inode_free(&nfsi->netfs);
}
extern void nfs_netfs_initiate_read(struct nfs_pgio_header *hdr);
extern void nfs_netfs_read_completion(struct nfs_pgio_header *hdr);
Expand Down Expand Up @@ -160,7 +164,8 @@ static inline void nfs_netfs_reset_pageio_descriptor(struct nfs_pageio_descripto
desc->pg_netfs = NULL;
}
#else /* CONFIG_NFS_FSCACHE */
static inline void nfs_netfs_inode_init(struct nfs_inode *nfsi) {}
static inline int nfs_netfs_inode_init(struct nfs_inode *nfsi) { return 0; }
static inline void nfs_netfs_inode_free(struct nfs_inode *nfsi) { }
static inline void nfs_netfs_initiate_read(struct nfs_pgio_header *hdr) {}
static inline void nfs_netfs_read_completion(struct nfs_pgio_header *hdr) {}
static inline void nfs_netfs_readpage_release(struct nfs_page *req)
Expand Down
9 changes: 8 additions & 1 deletion fs/nfs/inode.c
Expand Up @@ -2234,6 +2234,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
struct inode *nfs_alloc_inode(struct super_block *sb)
{
struct nfs_inode *nfsi;
int ret;

nfsi = alloc_inode_sb(sb, nfs_inode_cachep, GFP_KERNEL);
if (!nfsi)
return NULL;
Expand All @@ -2245,14 +2247,19 @@ struct inode *nfs_alloc_inode(struct super_block *sb)
#ifdef CONFIG_NFS_V4_2
nfsi->xattr_cache = NULL;
#endif
nfs_netfs_inode_init(nfsi);
ret = nfs_netfs_inode_init(nfsi);
if (ret) {
kmem_cache_free(nfs_inode_cachep, nfsi);
return NULL;
}

return VFS_I(nfsi);
}
EXPORT_SYMBOL_GPL(nfs_alloc_inode);

void nfs_free_inode(struct inode *inode)
{
nfs_netfs_inode_free(NFS_I(inode));
kmem_cache_free(nfs_inode_cachep, NFS_I(inode));
}
EXPORT_SYMBOL_GPL(nfs_free_inode);
Expand Down

0 comments on commit bff09aa

Please sign in to comment.