Skip to content

Commit

Permalink
netfs: Fix gcc-12 warning by embedding vfs inode in netfs_i_context
Browse files Browse the repository at this point in the history
While randstruct was satisfied with using an open-coded "void *" offset
cast for the netfs_i_context <-> inode casting, __builtin_object_size() as
used by FORTIFY_SOURCE was not as easily fooled.  This was causing the
following complaint[1] from gcc v12:

  In file included from include/linux/string.h:253,
                   from include/linux/ceph/ceph_debug.h:7,
                   from fs/ceph/inode.c:2:
  In function 'fortify_memset_chk',
      inlined from 'netfs_i_context_init' at include/linux/netfs.h:326:2,
      inlined from 'ceph_alloc_inode' at fs/ceph/inode.c:463:2:
  include/linux/fortify-string.h:242:25: warning: call to '__write_overflow_field' declared with attribute warning: detected write beyond size of field (1st parameter); maybe use struct_group()? [-Wattribute-warning]
    242 |                         __write_overflow_field(p_size_field, size);
        |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Fix this by embedding a struct inode into struct netfs_i_context (which
should perhaps be renamed to struct netfs_inode).  The struct inode
vfs_inode fields are then removed from the 9p, afs, ceph and cifs inode
structs and vfs_inode is then simply changed to "netfs.inode" in those
filesystems.

Further, rename netfs_i_context to netfs_inode, get rid of the
netfs_inode() function that converted a netfs_i_context pointer to an
inode pointer (that can now be done with &ctx->inode) and rename the
netfs_i_context() function to netfs_inode() (which is now a wrapper
around container_of()).

Most of the changes were done with:

  perl -p -i -e 's/vfs_inode/netfs.inode/'g \
        `git grep -l 'vfs_inode' -- fs/{9p,afs,ceph,cifs}/*.[ch]`

Kees suggested doing it with a pair structure[2] and a special
declarator to insert that into the network filesystem's inode
wrapper[3], but I think it's cleaner to embed it - and then it doesn't
matter if struct randomisation reorders things.

Dave Chinner suggested using a filesystem-specific VFS_I() function in
each filesystem to convert that filesystem's own inode wrapper struct
into the VFS inode struct[4].

Version #2:
 - Fix a couple of missed name changes due to a disabled cifs option.
 - Rename nfs_i_context to nfs_inode
 - Use "netfs" instead of "nic" as the member name in per-fs inode wrapper
   structs.

[ This also undoes commit 507160f ("netfs: gcc-12: temporarily
  disable '-Wattribute-warning' for now") that is no longer needed ]

Fixes: bc899ee ("netfs: Add a netfs inode context")
Reported-by: Jeff Layton <[email protected]>
Signed-off-by: David Howells <[email protected]>
Reviewed-by: Jeff Layton <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
Reviewed-by: Xiubo Li <[email protected]>
cc: Jonathan Corbet <[email protected]>
cc: Eric Van Hensbergen <[email protected]>
cc: Latchesar Ionkov <[email protected]>
cc: Dominique Martinet <[email protected]>
cc: Christian Schoenebeck <[email protected]>
cc: Marc Dionne <[email protected]>
cc: Ilya Dryomov <[email protected]>
cc: Steve French <[email protected]>
cc: William Kucharski <[email protected]>
cc: "Matthew Wilcox (Oracle)" <[email protected]>
cc: Dave Chinner <[email protected]>
cc: [email protected]
cc: [email protected]
cc: [email protected]
cc: [email protected]
cc: [email protected]
cc: [email protected]
cc: [email protected]
cc: [email protected]
Link: https://lore.kernel.org/r/[email protected]/ [1]
Link: https://lore.kernel.org/r/[email protected]/ [2]
Link: https://lore.kernel.org/r/[email protected]/ [3]
Link: https://lore.kernel.org/r/[email protected]/ [4]
Link: https://lore.kernel.org/r/165296786831.3591209.12111293034669289733.stgit@warthog.procyon.org.uk/ # v1
Link: https://lore.kernel.org/r/165305805651.4094995.7763502506786714216.stgit@warthog.procyon.org.uk # v2
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
dhowells authored and torvalds committed Jun 9, 2022
1 parent 3d9f55c commit 874c8ca
Show file tree
Hide file tree
Showing 40 changed files with 227 additions and 261 deletions.
37 changes: 18 additions & 19 deletions Documentation/filesystems/netfs_library.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,30 +37,31 @@ The network filesystem helper library needs a place to store a bit of state for
its use on each netfs inode it is helping to manage. To this end, a context
structure is defined::

struct netfs_i_context {
struct netfs_inode {
struct inode inode;
const struct netfs_request_ops *ops;
struct fscache_cookie *cache;
struct fscache_cookie *cache;
};

A network filesystem that wants to use netfs lib must place one of these
directly after the VFS ``struct inode`` it allocates, usually as part of its
own struct. This can be done in a way similar to the following::
A network filesystem that wants to use netfs lib must place one of these in its
inode wrapper struct instead of the VFS ``struct inode``. This can be done in
a way similar to the following::

struct my_inode {
struct {
/* These must be contiguous */
struct inode vfs_inode;
struct netfs_i_context netfs_ctx;
};
struct netfs_inode netfs; /* Netfslib context and vfs inode */
...
};

This allows netfslib to find its state by simple offset from the inode pointer,
thereby allowing the netfslib helper functions to be pointed to directly by the
VFS/VM operation tables.
This allows netfslib to find its state by using ``container_of()`` from the
inode pointer, thereby allowing the netfslib helper functions to be pointed to
directly by the VFS/VM operation tables.

The structure contains the following fields:

* ``inode``

The VFS inode structure.

* ``ops``

The set of operations provided by the network filesystem to netfslib.
Expand All @@ -78,14 +79,12 @@ To help deal with the per-inode context, a number helper functions are
provided. Firstly, a function to perform basic initialisation on a context and
set the operations table pointer::

void netfs_i_context_init(struct inode *inode,
const struct netfs_request_ops *ops);
void netfs_inode_init(struct inode *inode,
const struct netfs_request_ops *ops);

then two functions to cast between the VFS inode structure and the netfs
context::
then a function to cast from the VFS inode structure to the netfs context::

struct netfs_i_context *netfs_i_context(struct inode *inode);
struct inode *netfs_inode(struct netfs_i_context *ctx);
struct netfs_inode *netfs_node(struct inode *inode);

and finally, a function to get the cache cookie pointer from the context
attached to an inode (or NULL if fscache is disabled)::
Expand Down
4 changes: 2 additions & 2 deletions fs/9p/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,12 @@ 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_ctx.cache =
v9inode->netfs.cache =
fscache_acquire_cookie(v9fs_session_cache(v9ses),
0,
&path, sizeof(path),
&version, sizeof(version),
i_size_read(&v9inode->vfs_inode));
i_size_read(&v9inode->netfs.inode));

p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n",
inode, v9fs_inode_cookie(v9inode));
Expand Down
2 changes: 1 addition & 1 deletion fs/9p/v9fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ static void v9fs_inode_init_once(void *foo)
struct v9fs_inode *v9inode = (struct v9fs_inode *)foo;

memset(&v9inode->qid, 0, sizeof(v9inode->qid));
inode_init_once(&v9inode->vfs_inode);
inode_init_once(&v9inode->netfs.inode);
}

/**
Expand Down
10 changes: 3 additions & 7 deletions fs/9p/v9fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,7 @@ struct v9fs_session_info {
#define V9FS_INO_INVALID_ATTR 0x01

struct v9fs_inode {
struct {
/* These must be contiguous */
struct inode vfs_inode; /* the VFS's inode record */
struct netfs_i_context netfs_ctx; /* Netfslib context */
};
struct netfs_inode netfs; /* Netfslib context and vfs inode */
struct p9_qid qid;
unsigned int cache_validity;
struct p9_fid *writeback_fid;
Expand All @@ -122,13 +118,13 @@ struct v9fs_inode {

static inline struct v9fs_inode *V9FS_I(const struct inode *inode)
{
return container_of(inode, struct v9fs_inode, vfs_inode);
return container_of(inode, struct v9fs_inode, netfs.inode);
}

static inline struct fscache_cookie *v9fs_inode_cookie(struct v9fs_inode *v9inode)
{
#ifdef CONFIG_9P_FSCACHE
return netfs_i_cookie(&v9inode->vfs_inode);
return netfs_i_cookie(&v9inode->netfs.inode);
#else
return NULL;
#endif
Expand Down
2 changes: 1 addition & 1 deletion fs/9p/vfs_addr.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ static void v9fs_write_to_cache_done(void *priv, ssize_t transferred_or_error,
transferred_or_error != -ENOBUFS) {
version = cpu_to_le32(v9inode->qid.version);
fscache_invalidate(v9fs_inode_cookie(v9inode), &version,
i_size_read(&v9inode->vfs_inode), 0);
i_size_read(&v9inode->netfs.inode), 0);
}
}

Expand Down
4 changes: 2 additions & 2 deletions fs/9p/vfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ struct inode *v9fs_alloc_inode(struct super_block *sb)
v9inode->writeback_fid = NULL;
v9inode->cache_validity = 0;
mutex_init(&v9inode->v_mutex);
return &v9inode->vfs_inode;
return &v9inode->netfs.inode;
}

/**
Expand All @@ -252,7 +252,7 @@ void v9fs_free_inode(struct inode *inode)
*/
static void v9fs_set_netfs_context(struct inode *inode)
{
netfs_i_context_init(inode, &v9fs_req_ops);
netfs_inode_init(inode, &v9fs_req_ops);
}

int v9fs_init_inode(struct v9fs_session_info *v9ses,
Expand Down
2 changes: 1 addition & 1 deletion fs/afs/callback.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ void afs_invalidate_mmap_work(struct work_struct *work)
{
struct afs_vnode *vnode = container_of(work, struct afs_vnode, cb_work);

unmap_mapping_pages(vnode->vfs_inode.i_mapping, 0, 0, false);
unmap_mapping_pages(vnode->netfs.inode.i_mapping, 0, 0, false);
}

void afs_server_init_callback_work(struct work_struct *work)
Expand Down
32 changes: 16 additions & 16 deletions fs/afs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ struct afs_lookup_cookie {
*/
static void afs_dir_read_cleanup(struct afs_read *req)
{
struct address_space *mapping = req->vnode->vfs_inode.i_mapping;
struct address_space *mapping = req->vnode->netfs.inode.i_mapping;
struct folio *folio;
pgoff_t last = req->nr_pages - 1;

Expand Down Expand Up @@ -153,7 +153,7 @@ static bool afs_dir_check_folio(struct afs_vnode *dvnode, struct folio *folio,
block = kmap_local_folio(folio, offset);
if (block->hdr.magic != AFS_DIR_MAGIC) {
printk("kAFS: %s(%lx): [%llx] bad magic %zx/%zx is %04hx\n",
__func__, dvnode->vfs_inode.i_ino,
__func__, dvnode->netfs.inode.i_ino,
pos, offset, size, ntohs(block->hdr.magic));
trace_afs_dir_check_failed(dvnode, pos + offset, i_size);
kunmap_local(block);
Expand Down Expand Up @@ -183,7 +183,7 @@ static bool afs_dir_check_folio(struct afs_vnode *dvnode, struct folio *folio,
static void afs_dir_dump(struct afs_vnode *dvnode, struct afs_read *req)
{
union afs_xdr_dir_block *block;
struct address_space *mapping = dvnode->vfs_inode.i_mapping;
struct address_space *mapping = dvnode->netfs.inode.i_mapping;
struct folio *folio;
pgoff_t last = req->nr_pages - 1;
size_t offset, size;
Expand Down Expand Up @@ -217,7 +217,7 @@ static void afs_dir_dump(struct afs_vnode *dvnode, struct afs_read *req)
*/
static int afs_dir_check(struct afs_vnode *dvnode, struct afs_read *req)
{
struct address_space *mapping = dvnode->vfs_inode.i_mapping;
struct address_space *mapping = dvnode->netfs.inode.i_mapping;
struct folio *folio;
pgoff_t last = req->nr_pages - 1;
int ret = 0;
Expand Down Expand Up @@ -269,7 +269,7 @@ static int afs_dir_open(struct inode *inode, struct file *file)
static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
__acquires(&dvnode->validate_lock)
{
struct address_space *mapping = dvnode->vfs_inode.i_mapping;
struct address_space *mapping = dvnode->netfs.inode.i_mapping;
struct afs_read *req;
loff_t i_size;
int nr_pages, i;
Expand All @@ -287,7 +287,7 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
req->cleanup = afs_dir_read_cleanup;

expand:
i_size = i_size_read(&dvnode->vfs_inode);
i_size = i_size_read(&dvnode->netfs.inode);
if (i_size < 2048) {
ret = afs_bad(dvnode, afs_file_error_dir_small);
goto error;
Expand All @@ -305,7 +305,7 @@ static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
req->actual_len = i_size; /* May change */
req->len = nr_pages * PAGE_SIZE; /* We can ask for more than there is */
req->data_version = dvnode->status.data_version; /* May change */
iov_iter_xarray(&req->def_iter, READ, &dvnode->vfs_inode.i_mapping->i_pages,
iov_iter_xarray(&req->def_iter, READ, &dvnode->netfs.inode.i_mapping->i_pages,
0, i_size);
req->iter = &req->def_iter;

Expand Down Expand Up @@ -897,7 +897,7 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,

out_op:
if (op->error == 0) {
inode = &op->file[1].vnode->vfs_inode;
inode = &op->file[1].vnode->netfs.inode;
op->file[1].vnode = NULL;
}

Expand Down Expand Up @@ -1139,7 +1139,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
afs_stat_v(dir, n_reval);

/* search the directory for this vnode */
ret = afs_do_lookup_one(&dir->vfs_inode, dentry, &fid, key, &dir_version);
ret = afs_do_lookup_one(&dir->netfs.inode, dentry, &fid, key, &dir_version);
switch (ret) {
case 0:
/* the filename maps to something */
Expand Down Expand Up @@ -1170,7 +1170,7 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
_debug("%pd: file deleted (uq %u -> %u I:%u)",
dentry, fid.unique,
vnode->fid.unique,
vnode->vfs_inode.i_generation);
vnode->netfs.inode.i_generation);
goto not_found;
}
goto out_valid;
Expand Down Expand Up @@ -1368,7 +1368,7 @@ static void afs_dir_remove_subdir(struct dentry *dentry)
if (d_really_is_positive(dentry)) {
struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));

clear_nlink(&vnode->vfs_inode);
clear_nlink(&vnode->netfs.inode);
set_bit(AFS_VNODE_DELETED, &vnode->flags);
clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
Expand Down Expand Up @@ -1487,8 +1487,8 @@ static void afs_dir_remove_link(struct afs_operation *op)
/* Already done */
} else if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
write_seqlock(&vnode->cb_lock);
drop_nlink(&vnode->vfs_inode);
if (vnode->vfs_inode.i_nlink == 0) {
drop_nlink(&vnode->netfs.inode);
if (vnode->netfs.inode.i_nlink == 0) {
set_bit(AFS_VNODE_DELETED, &vnode->flags);
__afs_break_callback(vnode, afs_cb_break_for_unlink);
}
Expand All @@ -1504,7 +1504,7 @@ static void afs_dir_remove_link(struct afs_operation *op)
op->error = ret;
}

_debug("nlink %d [val %d]", vnode->vfs_inode.i_nlink, op->error);
_debug("nlink %d [val %d]", vnode->netfs.inode.i_nlink, op->error);
}

static void afs_unlink_success(struct afs_operation *op)
Expand Down Expand Up @@ -1680,8 +1680,8 @@ static void afs_link_success(struct afs_operation *op)
afs_update_dentry_version(op, dvp, op->dentry);
if (op->dentry_2->d_parent == op->dentry->d_parent)
afs_update_dentry_version(op, dvp, op->dentry_2);
ihold(&vp->vnode->vfs_inode);
d_instantiate(op->dentry, &vp->vnode->vfs_inode);
ihold(&vp->vnode->netfs.inode);
d_instantiate(op->dentry, &vp->vnode->netfs.inode);
}

static void afs_link_put(struct afs_operation *op)
Expand Down
10 changes: 5 additions & 5 deletions fs/afs/dir_edit.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ static void afs_clear_contig_bits(union afs_xdr_dir_block *block,
*/
static struct folio *afs_dir_get_folio(struct afs_vnode *vnode, pgoff_t index)
{
struct address_space *mapping = vnode->vfs_inode.i_mapping;
struct address_space *mapping = vnode->netfs.inode.i_mapping;
struct folio *folio;

folio = __filemap_get_folio(mapping, index,
Expand Down Expand Up @@ -216,7 +216,7 @@ void afs_edit_dir_add(struct afs_vnode *vnode,

_enter(",,{%d,%s},", name->len, name->name);

i_size = i_size_read(&vnode->vfs_inode);
i_size = i_size_read(&vnode->netfs.inode);
if (i_size > AFS_DIR_BLOCK_SIZE * AFS_DIR_MAX_BLOCKS ||
(i_size & (AFS_DIR_BLOCK_SIZE - 1))) {
clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
Expand Down Expand Up @@ -336,7 +336,7 @@ void afs_edit_dir_add(struct afs_vnode *vnode,
if (b < AFS_DIR_BLOCKS_WITH_CTR)
meta->meta.alloc_ctrs[b] -= need_slots;

inode_inc_iversion_raw(&vnode->vfs_inode);
inode_inc_iversion_raw(&vnode->netfs.inode);
afs_stat_v(vnode, n_dir_cr);
_debug("Insert %s in %u[%u]", name->name, b, slot);

Expand Down Expand Up @@ -383,7 +383,7 @@ void afs_edit_dir_remove(struct afs_vnode *vnode,

_enter(",,{%d,%s},", name->len, name->name);

i_size = i_size_read(&vnode->vfs_inode);
i_size = i_size_read(&vnode->netfs.inode);
if (i_size < AFS_DIR_BLOCK_SIZE ||
i_size > AFS_DIR_BLOCK_SIZE * AFS_DIR_MAX_BLOCKS ||
(i_size & (AFS_DIR_BLOCK_SIZE - 1))) {
Expand Down Expand Up @@ -463,7 +463,7 @@ void afs_edit_dir_remove(struct afs_vnode *vnode,
if (b < AFS_DIR_BLOCKS_WITH_CTR)
meta->meta.alloc_ctrs[b] += need_slots;

inode_set_iversion_raw(&vnode->vfs_inode, vnode->status.data_version);
inode_set_iversion_raw(&vnode->netfs.inode, vnode->status.data_version);
afs_stat_v(vnode, n_dir_rm);
_debug("Remove %s from %u[%u]", name->name, b, slot);

Expand Down
4 changes: 2 additions & 2 deletions fs/afs/dir_silly.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ int afs_sillyrename(struct afs_vnode *dvnode, struct afs_vnode *vnode,
goto out;
} while (!d_is_negative(sdentry));

ihold(&vnode->vfs_inode);
ihold(&vnode->netfs.inode);

ret = afs_do_silly_rename(dvnode, vnode, dentry, sdentry, key);
switch (ret) {
Expand All @@ -148,7 +148,7 @@ int afs_sillyrename(struct afs_vnode *dvnode, struct afs_vnode *vnode,
d_drop(sdentry);
}

iput(&vnode->vfs_inode);
iput(&vnode->netfs.inode);
dput(sdentry);
out:
_leave(" = %d", ret);
Expand Down
2 changes: 1 addition & 1 deletion fs/afs/dynroot.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ 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_i_context_init(inode, NULL);
netfs_inode_init(inode, NULL);
inode->i_size = 0;
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
if (root) {
Expand Down
4 changes: 2 additions & 2 deletions fs/afs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ int afs_release(struct inode *inode, struct file *file)
afs_put_wb_key(af->wb);

if ((file->f_mode & FMODE_WRITE)) {
i_size = i_size_read(&vnode->vfs_inode);
i_size = i_size_read(&vnode->netfs.inode);
afs_set_cache_aux(vnode, &aux);
fscache_unuse_cookie(afs_vnode_cache(vnode), &aux, &i_size);
} else {
Expand Down Expand Up @@ -325,7 +325,7 @@ static void afs_issue_read(struct netfs_io_subrequest *subreq)
fsreq->iter = &fsreq->def_iter;

iov_iter_xarray(&fsreq->def_iter, READ,
&fsreq->vnode->vfs_inode.i_mapping->i_pages,
&fsreq->vnode->netfs.inode.i_mapping->i_pages,
fsreq->pos, fsreq->len);

afs_fetch_data(fsreq->vnode, fsreq);
Expand Down
6 changes: 3 additions & 3 deletions fs/afs/fs_operation.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,14 +232,14 @@ int afs_put_operation(struct afs_operation *op)
if (op->file[1].modification && op->file[1].vnode != op->file[0].vnode)
clear_bit(AFS_VNODE_MODIFYING, &op->file[1].vnode->flags);
if (op->file[0].put_vnode)
iput(&op->file[0].vnode->vfs_inode);
iput(&op->file[0].vnode->netfs.inode);
if (op->file[1].put_vnode)
iput(&op->file[1].vnode->vfs_inode);
iput(&op->file[1].vnode->netfs.inode);

if (op->more_files) {
for (i = 0; i < op->nr_files - 2; i++)
if (op->more_files[i].put_vnode)
iput(&op->more_files[i].vnode->vfs_inode);
iput(&op->more_files[i].vnode->netfs.inode);
kfree(op->more_files);
}

Expand Down
Loading

0 comments on commit 874c8ca

Please sign in to comment.