* [PATCH v2 00/18] fs/ceph: optimize struct layouts
@ 2026-07-06 7:24 Max Kellermann
2026-07-06 7:24 ` [PATCH v2 01/18] fs/ceph/super: remove unused field `i_cap_migration_resv` Max Kellermann
` (17 more replies)
0 siblings, 18 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
This patch set aims to reduce the memory usage of the Ceph filesystems
by optimizing the layout of structs, most importantly struct
ceph_inode_info:
- use `bool` instead of `int` for booelans
- use `u32` instead of `u64` where possible
- reorder fields to eliminate padding holes
- eliminate redundant fields
Without this patch set, ceph_inode_info looks like this with pahole:
/* size: 1456, cachelines: 23, members: 79 */
/* sum members: 1424, holes: 8, sum holes: 32 */
/* member types with holes: 3, total: 3 */
With this patch set, struct ceph_inode_info got smaller by 96 bytes:
/* size: 1360, cachelines: 22, members: 76 */
/* member types with holes: 1, total: 1 */
struct ceph_cap shrinks by 24 bytes:
/* size: 120, cachelines: 2, members: 12 */
/* size: 96, cachelines: 2, members: 10 */
struct ceph_snap_realm shrinks by 24 bytes, too:
/* size: 232, cachelines: 4, members: 21 */
/* sum members: 216, holes: 3, sum holes: 12 */
/* size: 208, cachelines: 4, members: 20 */
---
v1->v2:
- fix CONFIG_FS_ENCRYPTION check in "i_truncate_pagecache_size" patch
- add patches to shrink ceph_cap and ceph_snap_realm
Max Kellermann (18):
fs/ceph/super: remove unused field `i_cap_migration_resv`
fs/ceph/super: make field `i_truncate_pagecache_size` optional
include/ceph/ceph_fs.h: convert `pool_id` to u32
fs/ceph/super.h: convert ceph_inode_xattr fields to `bool`
fs/ceph/super.h: convert ceph_cap_snap.writing fields to `bool`
fs/ceph: consistently use `u32` for `time_warp_seq`
fs/ceph/super: reorder fields to eliminate padding holes
fs/ceph: remove i_truncate_mutex, use i_fragtree_mutex for both
fs/ceph/super.h: add `const` to helpers
fs/ceph/super.h: add helper ceph_in_snap()
fs/ceph: use ceph_vino() etc. instead of accessing i_vino directly
fs/ceph: remove redundant inode number from ceph_inode_info
fs/ceph: remove unused field `ceph_cap.last_used`
fs/ceph: convert ceph_cap.queue_release to bool
fs/ceph/super: move `ceph_cap.caps_item` into the union
fs/ceph/snap: add a kmem_cache for struct ceph_snap_realm
fs/ceph/super: reorder struct ceph_snap_realm fields
fs/ceph/super: remove redundant field `ceph_snap_realm.parent_ino`
fs/ceph/acl.c | 2 +-
fs/ceph/addr.c | 23 ++++---
fs/ceph/cache.c | 4 +-
fs/ceph/caps.c | 14 ++--
fs/ceph/dir.c | 20 +++---
fs/ceph/export.c | 8 +--
fs/ceph/file.c | 28 ++++----
fs/ceph/inode.c | 38 +++++++----
fs/ceph/mds_client.c | 16 ++---
fs/ceph/mds_client.h | 2 +-
fs/ceph/quota.c | 6 +-
fs/ceph/snap.c | 17 +++--
fs/ceph/super.c | 9 +++
fs/ceph/super.h | 123 +++++++++++++++++++++++++----------
fs/ceph/util.c | 8 +--
fs/ceph/xattr.c | 18 ++---
include/linux/ceph/ceph_fs.h | 2 +-
include/linux/ceph/libceph.h | 1 +
18 files changed, 204 insertions(+), 135 deletions(-)
--
2.47.3
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v2 01/18] fs/ceph/super: remove unused field `i_cap_migration_resv`
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
@ 2026-07-06 7:24 ` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 02/18] fs/ceph/super: make field `i_truncate_pagecache_size` optional Max Kellermann
` (16 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
This field was added 17 years ago by commit de57606c23afd ("ceph:
client types") but it was never used.
This reduces the size of `struct ceph_inode_info` by 8 bytes.
Fixes: de57606c23afd ("ceph: client types")
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
fs/ceph/super.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 1d6aab060780..3cbd320b49a8 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -450,7 +450,6 @@ struct ceph_inode_info {
wait_queue_head_t i_cap_wq; /* threads waiting on a capability */
unsigned long i_hold_caps_max; /* jiffies */
struct list_head i_cap_delay_list; /* for delayed cap release to mds */
- struct ceph_cap_reservation i_cap_migration_resv;
struct list_head i_cap_snaps; /* snapped state pending flush to mds */
struct ceph_snap_context *i_head_snapc; /* set if wr_buffer_head > 0 or
dirty|flushing caps */
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 02/18] fs/ceph/super: make field `i_truncate_pagecache_size` optional
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
2026-07-06 7:24 ` [PATCH v2 01/18] fs/ceph/super: remove unused field `i_cap_migration_resv` Max Kellermann
@ 2026-07-06 7:24 ` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 03/18] include/ceph/ceph_fs.h: convert `pool_id` to u32 Max Kellermann
` (15 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
This field is only used with CONFIG_FS_ENCRYPTION; without it, it
always equals `i_truncate_size`.
This reduces the size of `struct ceph_inode_info` by 8 bytes on
kernels that have filesystem encryption disabled.
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
fs/ceph/inode.c | 8 ++++++--
fs/ceph/super.h | 11 +++++++++++
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 61d7c0b8161f..bdb82f123033 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -681,7 +681,9 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
ci->i_truncate_seq = 0;
ci->i_truncate_size = 0;
ci->i_truncate_pending = 0;
+#ifdef CONFIG_FS_ENCRYPTION
ci->i_truncate_pagecache_size = 0;
+#endif
ci->i_max_size = 0;
ci->i_reported_size = 0;
@@ -866,6 +868,7 @@ int ceph_fill_file_size(struct inode *inode, int issued,
ci->i_truncate_size = truncate_size;
+#ifdef CONFIG_FS_ENCRYPTION
if (IS_ENCRYPTED(inode)) {
doutc(cl, "truncate_pagecache_size %lld -> %llu\n",
ci->i_truncate_pagecache_size, size);
@@ -873,6 +876,7 @@ int ceph_fill_file_size(struct inode *inode, int issued,
} else {
ci->i_truncate_pagecache_size = truncate_size;
}
+#endif
}
return queue_trunc;
}
@@ -2332,7 +2336,7 @@ void __ceph_do_pending_vmtruncate(struct inode *inode)
/* there should be no reader or writer */
WARN_ON_ONCE(ci->i_rd_ref || ci->i_wr_ref);
- to = ci->i_truncate_pagecache_size;
+ to = ceph_get_truncate_pagecache_size(ci);
wrbuffer_refs = ci->i_wrbuffer_ref;
doutc(cl, "%p %llx.%llx (%d) to %lld\n", inode, ceph_vinop(inode),
ci->i_truncate_pending, to);
@@ -2342,7 +2346,7 @@ void __ceph_do_pending_vmtruncate(struct inode *inode)
truncate_pagecache(inode, to);
spin_lock(&ci->i_ceph_lock);
- if (to == ci->i_truncate_pagecache_size) {
+ if (to == ceph_get_truncate_pagecache_size(ci)) {
ci->i_truncate_pending = 0;
finish = 1;
}
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 3cbd320b49a8..7023af704e14 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -468,11 +468,14 @@ struct ceph_inode_info {
u32 i_truncate_seq; /* last truncate to smaller size */
u64 i_truncate_size; /* and the size we last truncated down to */
int i_truncate_pending; /* still need to call vmtruncate */
+
+#ifdef CONFIG_FS_ENCRYPTION
/*
* For none fscrypt case it equals to i_truncate_size or it will
* equals to fscrypt_file_size
*/
u64 i_truncate_pagecache_size;
+#endif
u64 i_max_size; /* max file size authorized by mds */
u64 i_reported_size; /* (max_)size reported to or requested of mds */
@@ -667,6 +670,14 @@ static inline struct inode *ceph_find_inode(struct super_block *sb,
return ilookup5(sb, (unsigned long)vino.ino, ceph_ino_compare, &vino);
}
+static inline u64 ceph_get_truncate_pagecache_size(const struct ceph_inode_info *ci)
+{
+#ifdef CONFIG_FS_ENCRYPTION
+ return ci->i_truncate_pagecache_size;
+#else
+ return ci->i_truncate_size;
+#endif
+}
/*
* Ceph inode.
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 03/18] include/ceph/ceph_fs.h: convert `pool_id` to u32
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
2026-07-06 7:24 ` [PATCH v2 01/18] fs/ceph/super: remove unused field `i_cap_migration_resv` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 02/18] fs/ceph/super: make field `i_truncate_pagecache_size` optional Max Kellermann
@ 2026-07-06 7:24 ` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 04/18] fs/ceph/super.h: convert ceph_inode_xattr fields to `bool` Max Kellermann
` (14 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
While the Ceph OSD protocol transmits OSD pool ids as 64 bit integers,
the MDS protocol is limited to 32 bits. This is a protocol limitation
we cannot fix, but it gives us the chance to reduce the struct sizes
by only using the integer size we really need.
There is one caveat: previously, -1 was used to indicate "invalid pool
id". This patch changes this magic value to 0 (i.e. removes the
special-case code from ceph_file_layout_{from,to}_legacy()). This is
fine because on the wire, this magic value is 0, too.
This reduces the size of `struct ceph_inode_info` by 16 bytes (because
it contains `struct ceph_file_layout` twice, and that struct shrinks
by 8 bytes; the small pool_id now fits in the existing padding hole).
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
fs/ceph/addr.c | 16 ++++++++--------
fs/ceph/caps.c | 2 +-
fs/ceph/inode.c | 2 +-
fs/ceph/mds_client.h | 2 +-
fs/ceph/util.c | 8 +-------
fs/ceph/xattr.c | 10 +++++-----
include/linux/ceph/ceph_fs.h | 2 +-
7 files changed, 18 insertions(+), 24 deletions(-)
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 61bd6d92ff25..481654872e9f 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -2381,7 +2381,7 @@ enum {
};
static int __ceph_pool_perm_get(struct ceph_inode_info *ci,
- s64 pool, struct ceph_string *pool_ns)
+ u32 pool, struct ceph_string *pool_ns)
{
struct ceph_fs_client *fsc = ceph_inode_to_fs_client(&ci->netfs.inode);
struct ceph_mds_client *mdsc = fsc->mdsc;
@@ -2420,10 +2420,10 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci,
goto out;
if (pool_ns)
- doutc(cl, "pool %lld ns %.*s no perm cached\n", pool,
+ doutc(cl, "pool %u ns %.*s no perm cached\n", pool,
(int)pool_ns->len, pool_ns->str);
else
- doutc(cl, "pool %lld no perm cached\n", pool);
+ doutc(cl, "pool %u no perm cached\n", pool);
down_write(&mdsc->pool_perm_rwsem);
p = &mdsc->pool_perm_tree.rb_node;
@@ -2548,10 +2548,10 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci,
if (!err)
err = have;
if (pool_ns)
- doutc(cl, "pool %lld ns %.*s result = %d\n", pool,
+ doutc(cl, "pool %u ns %.*s result = %d\n", pool,
(int)pool_ns->len, pool_ns->str, err);
else
- doutc(cl, "pool %lld result = %d\n", pool, err);
+ doutc(cl, "pool %u result = %d\n", pool, err);
return err;
}
@@ -2560,7 +2560,7 @@ int ceph_pool_perm_check(struct inode *inode, int need)
struct ceph_client *cl = ceph_inode_to_client(inode);
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_string *pool_ns;
- s64 pool;
+ u32 pool;
int ret;
unsigned long flags;
@@ -2588,11 +2588,11 @@ int ceph_pool_perm_check(struct inode *inode, int need)
check:
if (flags & CEPH_I_POOL_PERM) {
if ((need & CEPH_CAP_FILE_RD) && !(flags & CEPH_I_POOL_RD)) {
- doutc(cl, "pool %lld no read perm\n", pool);
+ doutc(cl, "pool %u no read perm\n", pool);
return -EPERM;
}
if ((need & CEPH_CAP_FILE_WR) && !(flags & CEPH_I_POOL_WR)) {
- doutc(cl, "pool %lld no write perm\n", pool);
+ doutc(cl, "pool %u no write perm\n", pool);
return -EPERM;
}
return 0;
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 4b37d9ffdf7f..39dad1a528b5 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -3641,7 +3641,7 @@ static void handle_cap_grant(struct inode *inode,
if (newcaps & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR)) {
/* file layout may have changed */
- s64 old_pool = ci->i_layout.pool_id;
+ u32 old_pool = ci->i_layout.pool_id;
struct ceph_string *old_ns;
ceph_file_layout_from_legacy(&ci->i_layout, &grant->layout);
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index bdb82f123033..cd1e09c32eba 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -1176,7 +1176,7 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
if (new_version ||
(new_issued & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR))) {
u64 size = le64_to_cpu(info->size);
- s64 old_pool = ci->i_layout.pool_id;
+ u32 old_pool = ci->i_layout.pool_id;
struct ceph_string *old_ns;
ceph_file_layout_from_legacy(&ci->i_layout, &info->layout);
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index 731d6ad04956..d59bc904f0ce 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -440,7 +440,7 @@ struct ceph_mds_request {
struct ceph_pool_perm {
struct rb_node node;
int perm;
- s64 pool;
+ u32 pool;
size_t pool_ns_len;
char pool_ns[];
};
diff --git a/fs/ceph/util.c b/fs/ceph/util.c
index 2c34875675bf..5bb40af08b1c 100644
--- a/fs/ceph/util.c
+++ b/fs/ceph/util.c
@@ -35,9 +35,6 @@ void ceph_file_layout_from_legacy(struct ceph_file_layout *fl,
fl->stripe_count = le32_to_cpu(legacy->fl_stripe_count);
fl->object_size = le32_to_cpu(legacy->fl_object_size);
fl->pool_id = le32_to_cpu(legacy->fl_pg_pool);
- if (fl->pool_id == 0 && fl->stripe_unit == 0 &&
- fl->stripe_count == 0 && fl->object_size == 0)
- fl->pool_id = -1;
}
void ceph_file_layout_to_legacy(struct ceph_file_layout *fl,
@@ -46,10 +43,7 @@ void ceph_file_layout_to_legacy(struct ceph_file_layout *fl,
legacy->fl_stripe_unit = cpu_to_le32(fl->stripe_unit);
legacy->fl_stripe_count = cpu_to_le32(fl->stripe_count);
legacy->fl_object_size = cpu_to_le32(fl->object_size);
- if (fl->pool_id >= 0)
- legacy->fl_pg_pool = cpu_to_le32(fl->pool_id);
- else
- legacy->fl_pg_pool = 0;
+ legacy->fl_pg_pool = cpu_to_le32(fl->pool_id);
}
int ceph_flags_to_mode(int flags)
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 860fc8e1867d..124dde705e79 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -50,7 +50,7 @@ static bool ceph_vxattrcb_layout_exists(struct ceph_inode_info *ci)
{
struct ceph_file_layout *fl = &ci->i_layout;
return (fl->stripe_unit > 0 || fl->stripe_count > 0 ||
- fl->object_size > 0 || fl->pool_id >= 0 ||
+ fl->object_size > 0 || fl->pool_id > 0 ||
rcu_dereference_raw(fl->pool_ns) != NULL);
}
@@ -61,7 +61,7 @@ static ssize_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val,
struct ceph_client *cl = fsc->client;
struct ceph_osd_client *osdc = &fsc->client->osdc;
struct ceph_string *pool_ns;
- s64 pool = ci->i_layout.pool_id;
+ u32 pool = ci->i_layout.pool_id;
const char *pool_name;
const char *ns_field = " pool_namespace=";
char buf[128];
@@ -81,7 +81,7 @@ static ssize_t ceph_vxattrcb_layout(struct ceph_inode_info *ci, char *val,
total_len = len + strlen(pool_name);
} else {
len = snprintf(buf, sizeof(buf),
- "stripe_unit=%u stripe_count=%u object_size=%u pool=%lld",
+ "stripe_unit=%u stripe_count=%u object_size=%u pool=%u",
ci->i_layout.stripe_unit, ci->i_layout.stripe_count,
ci->i_layout.object_size, pool);
total_len = len;
@@ -164,7 +164,7 @@ static ssize_t ceph_vxattrcb_layout_pool(struct ceph_inode_info *ci,
ssize_t ret;
struct ceph_fs_client *fsc = ceph_sb_to_fs_client(ci->netfs.inode.i_sb);
struct ceph_osd_client *osdc = &fsc->client->osdc;
- s64 pool = ci->i_layout.pool_id;
+ u32 pool = ci->i_layout.pool_id;
const char *pool_name;
down_read(&osdc->lock);
@@ -174,7 +174,7 @@ static ssize_t ceph_vxattrcb_layout_pool(struct ceph_inode_info *ci,
if (ret <= size)
memcpy(val, pool_name, ret);
} else {
- ret = ceph_fmt_xattr(val, size, "%lld", pool);
+ ret = ceph_fmt_xattr(val, size, "%u", pool);
}
up_read(&osdc->lock);
return ret;
diff --git a/include/linux/ceph/ceph_fs.h b/include/linux/ceph/ceph_fs.h
index 69ac3e55a3fe..7faa18493a07 100644
--- a/include/linux/ceph/ceph_fs.h
+++ b/include/linux/ceph/ceph_fs.h
@@ -69,7 +69,7 @@ struct ceph_file_layout {
u32 stripe_unit; /* stripe unit, in bytes */
u32 stripe_count; /* over this many objects */
u32 object_size; /* until objects are this big */
- s64 pool_id; /* rados pool id */
+ u32 pool_id; /* rados pool id */
struct ceph_string __rcu *pool_ns; /* rados pool namespace */
};
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 04/18] fs/ceph/super.h: convert ceph_inode_xattr fields to `bool`
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
` (2 preceding siblings ...)
2026-07-06 7:24 ` [PATCH v2 03/18] include/ceph/ceph_fs.h: convert `pool_id` to u32 Max Kellermann
@ 2026-07-06 7:24 ` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 05/18] fs/ceph/super.h: convert ceph_cap_snap.writing " Max Kellermann
` (13 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
This reduces the size of `struct ceph_inode_xattr` by 8 bytes.
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
fs/ceph/super.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 7023af704e14..a3dae2c0bbee 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -320,10 +320,10 @@ struct ceph_inode_xattr {
int name_len;
const char *val;
int val_len;
- int dirty;
+ bool dirty;
- int should_free_name;
- int should_free_val;
+ bool should_free_name;
+ bool should_free_val;
};
/*
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 05/18] fs/ceph/super.h: convert ceph_cap_snap.writing fields to `bool`
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
` (3 preceding siblings ...)
2026-07-06 7:24 ` [PATCH v2 04/18] fs/ceph/super.h: convert ceph_inode_xattr fields to `bool` Max Kellermann
@ 2026-07-06 7:24 ` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 06/18] fs/ceph: consistently use `u32` for `time_warp_seq` Max Kellermann
` (12 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
This will allow better struct packing.
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
fs/ceph/caps.c | 2 +-
fs/ceph/snap.c | 4 ++--
fs/ceph/super.h | 2 +-
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 39dad1a528b5..372b239f6a36 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -3291,7 +3291,7 @@ static void __ceph_put_cap_refs(struct ceph_inode_info *ci, int had,
struct ceph_cap_snap,
ci_item);
- capsnap->writing = 0;
+ capsnap->writing = false;
if (ceph_try_drop_cap_snap(ci, capsnap))
/* put the ref held by ceph_queue_cap_snap() */
put++;
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index 9b79a5eaca93..94964e0952bd 100644
--- a/fs/ceph/snap.c
+++ b/fs/ceph/snap.c
@@ -521,7 +521,7 @@ static bool has_new_snaps(struct ceph_snap_context *o,
* However, if a (sync) write is currently in-progress when we apply
* the snapshot, we have to wait until the write succeeds or fails
* (and a final size/mtime is known). In this case the
- * cap_snap->writing = 1, and is said to be "pending." When the write
+ * cap_snap->writing = true, and is said to be "pending." When the write
* finishes, we __ceph_finish_cap_snap().
*
* Caller must hold snap_rwsem for read (i.e., the realm topology won't
@@ -627,7 +627,7 @@ static void ceph_queue_cap_snap(struct ceph_inode_info *ci,
doutc(cl, "%p %llx.%llx cap_snap %p snapc %p seq %llu used WR,"
" now pending\n", inode, ceph_vinop(inode), capsnap,
old_snapc, old_snapc->seq);
- capsnap->writing = 1;
+ capsnap->writing = true;
} else {
/* note mtime, size NOW. */
__ceph_finish_cap_snap(ci, capsnap);
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index a3dae2c0bbee..0d3363b0a33b 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -271,7 +271,7 @@ struct ceph_cap_snap {
u64 time_warp_seq;
u64 truncate_size;
u32 truncate_seq;
- int writing; /* a sync write is still in progress */
+ bool writing; /* a sync write is still in progress */
int dirty_pages; /* dirty pages awaiting writeback */
bool inline_data;
bool need_flush;
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 06/18] fs/ceph: consistently use `u32` for `time_warp_seq`
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
` (4 preceding siblings ...)
2026-07-06 7:24 ` [PATCH v2 05/18] fs/ceph/super.h: convert ceph_cap_snap.writing " Max Kellermann
@ 2026-07-06 7:24 ` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 07/18] fs/ceph/super: reorder fields to eliminate padding holes Max Kellermann
` (11 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
Previously, both `u32` and `u64` was used with implicit casts. All
this does is add useless overhead.
This will allow better struct packing in `struct ceph_cap_snap`.
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
fs/ceph/inode.c | 6 +++---
fs/ceph/super.h | 4 ++--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index cd1e09c32eba..e79ba09f2cdf 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -916,7 +916,7 @@ void ceph_inode_set_subvolume(struct inode *inode, u64 subvolume_id)
}
void ceph_fill_file_time(struct inode *inode, int issued,
- u64 time_warp_seq, struct timespec64 *ctime,
+ u32 time_warp_seq, struct timespec64 *ctime,
struct timespec64 *mtime, struct timespec64 *atime)
{
struct ceph_client *cl = ceph_inode_to_client(inode);
@@ -940,7 +940,7 @@ void ceph_fill_file_time(struct inode *inode, int issued,
ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) > 0) {
/* the MDS did a utimes() */
doutc(cl, "mtime %ptSp -> %ptSp tw %d -> %d\n", &imtime, mtime,
- ci->i_time_warp_seq, (int)time_warp_seq);
+ ci->i_time_warp_seq, time_warp_seq);
inode_set_mtime_to_ts(inode, *mtime);
inode_set_atime_to_ts(inode, *atime);
@@ -972,7 +972,7 @@ void ceph_fill_file_time(struct inode *inode, int issued,
}
}
if (warn) /* time_warp_seq shouldn't go backwards */
- doutc(cl, "%p mds time_warp_seq %llu < %u\n", inode,
+ doutc(cl, "%p mds time_warp_seq %u < %u\n", inode,
time_warp_seq, ci->i_time_warp_seq);
}
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 0d3363b0a33b..67411a5d8b91 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -268,7 +268,7 @@ struct ceph_cap_snap {
u64 size;
u64 change_attr;
struct timespec64 mtime, atime, ctime, btime;
- u64 time_warp_seq;
+ u32 time_warp_seq;
u64 truncate_size;
u32 truncate_seq;
bool writing; /* a sync write is still in progress */
@@ -1099,7 +1099,7 @@ extern int ceph_fill_file_size(struct inode *inode, int issued,
u32 truncate_seq, u64 truncate_size, u64 size);
extern void ceph_inode_set_subvolume(struct inode *inode, u64 subvolume_id);
extern void ceph_fill_file_time(struct inode *inode, int issued,
- u64 time_warp_seq, struct timespec64 *ctime,
+ u32 time_warp_seq, struct timespec64 *ctime,
struct timespec64 *mtime,
struct timespec64 *atime);
extern int ceph_fill_inode(struct inode *inode, struct page *locked_page,
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 07/18] fs/ceph/super: reorder fields to eliminate padding holes
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
` (5 preceding siblings ...)
2026-07-06 7:24 ` [PATCH v2 06/18] fs/ceph: consistently use `u32` for `time_warp_seq` Max Kellermann
@ 2026-07-06 7:24 ` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 08/18] fs/ceph: remove i_truncate_mutex, use i_fragtree_mutex for both Max Kellermann
` (10 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
This reduces the size of `struct ceph_inode_info` by 32 bytes.
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
fs/ceph/super.h | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 67411a5d8b91..05452bc7eac1 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -250,6 +250,9 @@ struct ceph_cap_flush {
*/
struct ceph_cap_snap {
refcount_t nref;
+
+ umode_t mode;
+
struct list_head ci_item;
struct ceph_cap_flush cap_flush;
@@ -258,7 +261,6 @@ struct ceph_cap_snap {
int issued, dirty;
struct ceph_snap_context *context;
- umode_t mode;
kuid_t uid;
kgid_t gid;
@@ -268,11 +270,12 @@ struct ceph_cap_snap {
u64 size;
u64 change_attr;
struct timespec64 mtime, atime, ctime, btime;
- u32 time_warp_seq;
u64 truncate_size;
u32 truncate_seq;
- bool writing; /* a sync write is still in progress */
+ u32 time_warp_seq;
int dirty_pages; /* dirty pages awaiting writeback */
+
+ bool writing; /* a sync write is still in progress */
bool inline_data;
bool need_flush;
};
@@ -317,8 +320,8 @@ struct ceph_inode_xattr {
struct rb_node node;
const char *name;
- int name_len;
const char *val;
+ int name_len;
int val_len;
bool dirty;
@@ -379,9 +382,9 @@ struct ceph_inode_info {
spinlock_t i_ceph_lock;
+ u32 i_time_warp_seq;
u64 i_version;
u64 i_inline_version;
- u32 i_time_warp_seq;
unsigned long i_ceph_flags;
atomic64_t i_release_count;
@@ -412,8 +415,8 @@ struct ceph_inode_info {
s32 i_dir_pin;
- struct rb_root i_fragtree;
int i_fragtree_nsplits;
+ struct rb_root i_fragtree;
struct mutex i_fragtree_mutex;
struct ceph_inode_xattrs_info i_xattrs;
@@ -453,7 +456,6 @@ struct ceph_inode_info {
struct list_head i_cap_snaps; /* snapped state pending flush to mds */
struct ceph_snap_context *i_head_snapc; /* set if wr_buffer_head > 0 or
dirty|flushing caps */
- unsigned i_snap_caps; /* cap bits for snapped files */
/*
* Written under i_ceph_lock, read via READ_ONCE()
* from diagnostic paths.
@@ -465,8 +467,8 @@ struct ceph_inode_info {
int i_nr_by_mode[CEPH_FILE_MODE_BITS]; /* open file counts */
struct mutex i_truncate_mutex;
- u32 i_truncate_seq; /* last truncate to smaller size */
u64 i_truncate_size; /* and the size we last truncated down to */
+ u32 i_truncate_seq; /* last truncate to smaller size */
int i_truncate_pending; /* still need to call vmtruncate */
#ifdef CONFIG_FS_ENCRYPTION
@@ -495,6 +497,8 @@ struct ceph_inode_info {
struct list_head i_unsafe_iops; /* uncommitted mds inode ops */
spinlock_t i_unsafe_lock;
+ unsigned int i_snap_caps; /* cap bits for snapped files */
+
union {
struct ceph_snap_realm *i_snap_realm; /* snap realm (if caps) */
struct ceph_snapid_map *i_snapid_map; /* snapid -> dev_t */
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 08/18] fs/ceph: remove i_truncate_mutex, use i_fragtree_mutex for both
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
` (6 preceding siblings ...)
2026-07-06 7:24 ` [PATCH v2 07/18] fs/ceph/super: reorder fields to eliminate padding holes Max Kellermann
@ 2026-07-06 7:24 ` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 09/18] fs/ceph/super.h: add `const` to helpers Max Kellermann
` (9 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
`i_fragtree_mutex` is only used for directories and `i_truncate_mutex`
is only used for regular files. Since these two fields will never be
both be used on any given object, let's merge them into one.
(This is a minimal diff that defines a preprocessor macro, to avoid
refactoring all code lines using these two mutexes.)
This reduces the size of `struct ceph_inode_info` by 8 bytes.
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
fs/ceph/inode.c | 1 -
fs/ceph/super.h | 6 +++++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index e79ba09f2cdf..1f65aa387008 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -677,7 +677,6 @@ struct inode *ceph_alloc_inode(struct super_block *sb)
for (i = 0; i < CEPH_FILE_MODE_BITS; i++)
ci->i_nr_by_mode[i] = 0;
- mutex_init(&ci->i_truncate_mutex);
ci->i_truncate_seq = 0;
ci->i_truncate_size = 0;
ci->i_truncate_pending = 0;
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 05452bc7eac1..35399689f0c1 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -466,7 +466,11 @@ struct ceph_inode_info {
unsigned long i_last_wr;
int i_nr_by_mode[CEPH_FILE_MODE_BITS]; /* open file counts */
- struct mutex i_truncate_mutex;
+/* since i_fragtree_mutex is only used for directories and
+ i_truncate_mutex is only used for regular files, we use the same
+ field for both */
+#define i_truncate_mutex i_fragtree_mutex
+
u64 i_truncate_size; /* and the size we last truncated down to */
u32 i_truncate_seq; /* last truncate to smaller size */
int i_truncate_pending; /* still need to call vmtruncate */
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 09/18] fs/ceph/super.h: add `const` to helpers
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
` (7 preceding siblings ...)
2026-07-06 7:24 ` [PATCH v2 08/18] fs/ceph: remove i_truncate_mutex, use i_fragtree_mutex for both Max Kellermann
@ 2026-07-06 7:24 ` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 10/18] fs/ceph/super.h: add helper ceph_in_snap() Max Kellermann
` (8 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
This documents that these functions do not modify the parameters.
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
fs/ceph/super.h | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 35399689f0c1..ab6fa8319c79 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -588,7 +588,7 @@ static inline u32 ceph_ino_to_ino32(u64 vino)
* we do want to set it to something, so that generic vfs code has an
* appropriate value for tracepoints and the like.
*/
-static inline ino_t ceph_vino_to_ino_t(struct ceph_vino vino)
+static inline ino_t ceph_vino_to_ino_t(const struct ceph_vino vino)
{
if (sizeof(ino_t) == sizeof(u32))
return ceph_ino_to_ino32(vino.ino);
@@ -598,12 +598,12 @@ static inline ino_t ceph_vino_to_ino_t(struct ceph_vino vino)
/* for printf-style formatting */
#define ceph_vinop(i) ceph_inode(i)->i_vino.ino, ceph_inode(i)->i_vino.snap
-static inline u64 ceph_ino(struct inode *inode)
+static inline u64 ceph_ino(const struct inode *inode)
{
return ceph_inode(inode)->i_vino.ino;
}
-static inline u64 ceph_snap(struct inode *inode)
+static inline u64 ceph_snap(const struct inode *inode)
{
return ceph_inode(inode)->i_vino.snap;
}
@@ -818,7 +818,7 @@ static inline struct ceph_dentry_info *ceph_dentry(const struct dentry *dentry)
/*
* caps helpers
*/
-static inline bool __ceph_is_any_real_caps(struct ceph_inode_info *ci)
+static inline bool __ceph_is_any_real_caps(const struct ceph_inode_info *ci)
{
return !RB_EMPTY_ROOT(&ci->i_caps);
}
@@ -1076,7 +1076,7 @@ void ceph_umount_begin(struct super_block *sb);
* a cap_snap is "pending" if it is still awaiting an in-progress
* sync write (that may/may not still update size, mtime, etc.).
*/
-static inline bool __ceph_have_pending_cap_snap(struct ceph_inode_info *ci)
+static inline bool __ceph_have_pending_cap_snap(const struct ceph_inode_info *ci)
{
return !list_empty(&ci->i_cap_snaps) &&
list_last_entry(&ci->i_cap_snaps, struct ceph_cap_snap,
@@ -1173,7 +1173,7 @@ extern int ceph_getattr(struct mnt_idmap *idmap,
u32 request_mask, unsigned int flags);
void ceph_inode_shutdown(struct inode *inode);
-static inline bool ceph_inode_is_shutdown(struct inode *inode)
+static inline bool ceph_inode_is_shutdown(const struct inode *inode)
{
unsigned long flags = READ_ONCE(ceph_inode(inode)->i_ceph_flags);
struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
@@ -1357,7 +1357,7 @@ extern int ceph_pool_perm_check(struct inode *inode, int need);
extern void ceph_pool_perm_destroy(struct ceph_mds_client* mdsc);
int ceph_purge_inode_cap(struct inode *inode, struct ceph_cap *cap, bool *invalidate);
-static inline bool ceph_has_inline_data(struct ceph_inode_info *ci)
+static inline bool ceph_has_inline_data(const struct ceph_inode_info *ci)
{
if (ci->i_inline_version == CEPH_INLINE_NONE ||
ci->i_inline_version == 1) /* initial version, no data */
@@ -1432,7 +1432,7 @@ enum quota_get_realm {
QUOTA_GET_ANY
};
-static inline bool __ceph_has_quota(struct ceph_inode_info *ci,
+static inline bool __ceph_has_quota(const struct ceph_inode_info *ci,
enum quota_get_realm which)
{
bool has_quota = false;
@@ -1465,7 +1465,7 @@ static inline void __ceph_update_quota(struct ceph_inode_info *ci,
ceph_adjust_quota_realms_count(&ci->netfs.inode, has_quota);
}
-static inline int __ceph_sparse_read_ext_count(struct inode *inode, u64 len)
+static inline int __ceph_sparse_read_ext_count(const struct inode *inode, u64 len)
{
int cnt = 0;
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 10/18] fs/ceph/super.h: add helper ceph_in_snap()
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
` (8 preceding siblings ...)
2026-07-06 7:24 ` [PATCH v2 09/18] fs/ceph/super.h: add `const` to helpers Max Kellermann
@ 2026-07-06 7:24 ` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 11/18] fs/ceph: use ceph_vino() etc. instead of accessing i_vino directly Max Kellermann
` (7 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
Some code simplification.
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
fs/ceph/acl.c | 2 +-
fs/ceph/addr.c | 2 +-
fs/ceph/dir.c | 20 ++++++++++----------
fs/ceph/export.c | 8 ++++----
fs/ceph/file.c | 14 +++++++-------
fs/ceph/inode.c | 14 +++++++-------
fs/ceph/mds_client.c | 10 +++++-----
fs/ceph/quota.c | 4 ++--
fs/ceph/super.h | 8 ++++++++
fs/ceph/xattr.c | 4 ++--
10 files changed, 47 insertions(+), 39 deletions(-)
diff --git a/fs/ceph/acl.c b/fs/ceph/acl.c
index 85d3dd48b167..dbc64ab60308 100644
--- a/fs/ceph/acl.c
+++ b/fs/ceph/acl.c
@@ -99,7 +99,7 @@ int ceph_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
struct timespec64 old_ctime = inode_get_ctime(inode);
umode_t new_mode = inode->i_mode, old_mode = inode->i_mode;
- if (ceph_snap(inode) != CEPH_NOSNAP) {
+ if (ceph_in_snap(inode)) {
ret = -EROFS;
goto out;
}
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 481654872e9f..d03639525eb8 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -2568,7 +2568,7 @@ int ceph_pool_perm_check(struct inode *inode, int need)
if (!S_ISREG(inode->i_mode))
return 0;
- if (ci->i_vino.snap != CEPH_NOSNAP) {
+ if (ceph_in_snap(inode)) {
/*
* Pool permission check needs to write to the first object.
* But for snapshot, head of the first object may have already
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 27ce9e55e947..c297cc57f88c 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -727,7 +727,7 @@ struct dentry *ceph_handle_snapdir(struct ceph_mds_request *req,
struct ceph_client *cl = ceph_inode_to_client(parent);
/* .snap dir? */
- if (ceph_snap(parent) == CEPH_NOSNAP &&
+ if (!ceph_in_snap(parent) &&
strcmp(dentry->d_name.name, fsc->mount_options->snapdir_name) == 0) {
struct dentry *res;
struct inode *inode = ceph_get_snapdir(parent);
@@ -919,7 +919,7 @@ static int ceph_mknod(struct mnt_idmap *idmap, struct inode *dir,
struct ceph_acl_sec_ctx as_ctx = {};
int err;
- if (ceph_snap(dir) != CEPH_NOSNAP)
+ if (ceph_in_snap(dir))
return -EROFS;
err = ceph_wait_on_conflict_unlink(dentry);
@@ -1031,7 +1031,7 @@ static int ceph_symlink(struct mnt_idmap *idmap, struct inode *dir,
umode_t mode = S_IFLNK | 0777;
int err;
- if (ceph_snap(dir) != CEPH_NOSNAP)
+ if (ceph_in_snap(dir))
return -EROFS;
err = ceph_wait_on_conflict_unlink(dentry);
@@ -1115,7 +1115,7 @@ static struct dentry *ceph_mkdir(struct mnt_idmap *idmap, struct inode *dir,
op = CEPH_MDS_OP_MKSNAP;
doutc(cl, "mksnap %llx.%llx/'%pd' dentry %p\n",
ceph_vinop(dir), dentry, dentry);
- } else if (ceph_snap(dir) == CEPH_NOSNAP) {
+ } else if (!ceph_in_snap(dir)) {
doutc(cl, "mkdir %llx.%llx/'%pd' dentry %p mode 0%ho\n",
ceph_vinop(dir), dentry, dentry, mode);
op = CEPH_MDS_OP_MKDIR;
@@ -1202,7 +1202,7 @@ static int ceph_link(struct dentry *old_dentry, struct inode *dir,
if (err)
return err;
- if (ceph_snap(dir) != CEPH_NOSNAP)
+ if (ceph_in_snap(dir))
return -EROFS;
err = fscrypt_prepare_link(old_dentry, dir, dentry);
@@ -1354,7 +1354,7 @@ static int ceph_unlink(struct inode *dir, struct dentry *dentry)
doutc(cl, "rmsnap %llx.%llx/'%pd' dn\n", ceph_vinop(dir),
dentry);
op = CEPH_MDS_OP_RMSNAP;
- } else if (ceph_snap(dir) == CEPH_NOSNAP) {
+ } else if (!ceph_in_snap(dir)) {
doutc(cl, "unlink/rmdir %llx.%llx/'%pd' inode %llx.%llx\n",
ceph_vinop(dir), dentry, ceph_vinop(inode));
op = d_is_dir(dentry) ?
@@ -1483,7 +1483,7 @@ static int ceph_rename(struct mnt_idmap *idmap, struct inode *old_dir,
if (ceph_snap(old_dir) != ceph_snap(new_dir))
return -EXDEV;
- if (ceph_snap(old_dir) != CEPH_NOSNAP) {
+ if (ceph_in_snap(old_dir)) {
if (old_dir == new_dir && ceph_snap(old_dir) == CEPH_SNAPDIR)
op = CEPH_MDS_OP_RENAMESNAP;
else
@@ -1981,7 +1981,7 @@ static int ceph_d_revalidate(struct inode *dir, const struct qstr *name,
mdsc = ceph_sb_to_fs_client(dir->i_sb)->mdsc;
/* always trust cached snapped dentries, snapdir dentry */
- if (ceph_snap(dir) != CEPH_NOSNAP) {
+ if (ceph_in_snap(dir)) {
doutc(cl, "%p '%pd' inode %p is SNAPPED\n", dentry,
dentry, inode);
valid = 1;
@@ -2065,7 +2065,7 @@ static int ceph_d_delete(const struct dentry *dentry)
/* won't release caps */
if (d_really_is_negative(dentry))
return 0;
- if (ceph_snap(d_inode(dentry)) != CEPH_NOSNAP)
+ if (ceph_in_snap(d_inode(dentry)))
return 0;
/* valid lease? */
di = ceph_dentry(dentry);
@@ -2120,7 +2120,7 @@ static void ceph_d_prune(struct dentry *dentry)
/* we hold d_lock, so d_parent is stable */
dir_ci = ceph_inode(d_inode(dentry->d_parent));
- if (dir_ci->i_vino.snap == CEPH_SNAPDIR)
+ if (ceph_in_snap(&dir_ci->netfs.inode))
return;
/* who calls d_delete() should also disable dcache readdir */
diff --git a/fs/ceph/export.c b/fs/ceph/export.c
index b2f2af104679..d132db40ba00 100644
--- a/fs/ceph/export.c
+++ b/fs/ceph/export.c
@@ -99,7 +99,7 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,
static const int connected_handle_length = CEPH_FH_WITH_PARENT_SIZE;
int type;
- if (ceph_snap(inode) != CEPH_NOSNAP)
+ if (ceph_in_snap(inode))
return ceph_encode_snapfh(inode, rawfh, max_len, parent_inode);
if (parent_inode && (*max_len < connected_handle_length)) {
@@ -372,7 +372,7 @@ static struct dentry *ceph_get_parent(struct dentry *child)
struct ceph_client *cl = ceph_inode_to_client(inode);
struct dentry *dn;
- if (ceph_snap(inode) != CEPH_NOSNAP) {
+ if (ceph_in_snap(inode)) {
struct inode* dir;
bool unlinked = false;
/* do not support non-directory */
@@ -456,7 +456,7 @@ static int __get_snap_name(struct dentry *parent, char *name,
if (ceph_ino(inode) != ceph_ino(dir))
goto out;
if (ceph_snap(inode) == CEPH_SNAPDIR) {
- if (ceph_snap(dir) == CEPH_NOSNAP) {
+ if (!ceph_in_snap(dir)) {
/*
* .get_name() from struct export_operations
* assumes that its 'name' parameter is pointing
@@ -555,7 +555,7 @@ static int ceph_get_name(struct dentry *parent, char *name,
struct ceph_mds_reply_info_parsed *rinfo;
int err;
- if (ceph_snap(inode) != CEPH_NOSNAP)
+ if (ceph_in_snap(inode))
return __get_snap_name(parent, name, child);
mdsc = ceph_inode_to_fs_client(inode)->mdsc;
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 71161f2b2151..d8859e4bed8b 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -437,7 +437,7 @@ int ceph_open(struct inode *inode, struct file *file)
}
/* snapped files are read-only */
- if (ceph_snap(inode) != CEPH_NOSNAP && (file->f_mode & FMODE_WRITE))
+ if (ceph_in_snap(inode) && (file->f_mode & FMODE_WRITE))
return -EROFS;
/* trivially open snapdir */
@@ -469,7 +469,7 @@ int ceph_open(struct inode *inode, struct file *file)
ceph_check_caps(ci, 0);
return ceph_init_file(inode, file, fmode);
- } else if (!do_sync && ceph_snap(inode) != CEPH_NOSNAP &&
+ } else if (!do_sync && ceph_in_snap(inode) &&
(ci->i_snap_caps & wanted) == wanted) {
__ceph_touch_fmode(ci, mdsc, fmode);
spin_unlock(&ci->i_ceph_lock);
@@ -1539,7 +1539,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
bool should_dirty = !write && user_backed_iter(iter);
bool sparse = ceph_test_mount_opt(fsc, SPARSEREAD);
- if (write && ceph_snap(file_inode(file)) != CEPH_NOSNAP)
+ if (write && ceph_in_snap(file_inode(file)))
return -EROFS;
doutc(cl, "sync_direct_%s on file %p %lld~%u snapc %p seq %lld\n",
@@ -1775,7 +1775,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
struct timespec64 mtime = current_time(inode);
size_t count = iov_iter_count(from);
- if (ceph_snap(file_inode(file)) != CEPH_NOSNAP)
+ if (ceph_in_snap(file_inode(file)))
return -EROFS;
doutc(cl, "on file %p %lld~%u snapc %p seq %lld\n", file, pos,
@@ -2410,7 +2410,7 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
if (ceph_inode_is_shutdown(inode))
return -ESTALE;
- if (ceph_snap(inode) != CEPH_NOSNAP)
+ if (ceph_in_snap(inode))
return -EROFS;
prealloc_cf = ceph_alloc_cap_flush();
@@ -2762,7 +2762,7 @@ static long ceph_fallocate(struct file *file, int mode,
inode_lock(inode);
- if (ceph_snap(inode) != CEPH_NOSNAP) {
+ if (ceph_in_snap(inode)) {
ret = -EROFS;
goto unlock;
}
@@ -3051,7 +3051,7 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off,
return -EXDEV;
}
}
- if (ceph_snap(dst_inode) != CEPH_NOSNAP)
+ if (ceph_in_snap(dst_inode))
return -EROFS;
/*
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 1f65aa387008..aba98975a8a3 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -766,7 +766,7 @@ void ceph_evict_inode(struct inode *inode)
* caps in i_snap_caps.
*/
if (ci->i_snap_realm) {
- if (ceph_snap(inode) == CEPH_NOSNAP) {
+ if (!ceph_in_snap(inode)) {
doutc(cl, " dropping residual ref to snap realm %p\n",
ci->i_snap_realm);
ceph_change_snap_realm(inode, NULL);
@@ -1066,7 +1066,7 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
info_caps = le32_to_cpu(info->cap.caps);
/* prealloc new cap struct */
- if (info_caps && ceph_snap(inode) == CEPH_NOSNAP) {
+ if (info_caps && !ceph_in_snap(inode)) {
new_cap = ceph_get_cap(mdsc, caps_reservation);
if (!new_cap)
return -ENOMEM;
@@ -1088,7 +1088,7 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
pool_ns = ceph_find_or_create_string(iinfo->pool_ns_data,
iinfo->pool_ns_len);
- if (ceph_snap(inode) != CEPH_NOSNAP && !ci->i_snapid_map)
+ if (ceph_in_snap(inode) && !ci->i_snapid_map)
ci->i_snapid_map = ceph_get_snapid_map(mdsc, ceph_snap(inode));
spin_lock(&ci->i_ceph_lock);
@@ -1333,7 +1333,7 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page,
/* were we issued a capability? */
if (info_caps) {
- if (ceph_snap(inode) == CEPH_NOSNAP) {
+ if (!ceph_in_snap(inode)) {
ceph_add_cap(inode, session,
le64_to_cpu(info->cap.cap_id),
info_caps,
@@ -1433,7 +1433,7 @@ static void __update_dentry_lease(struct inode *dir, struct dentry *dentry,
doutc(cl, "%p duration %lu ms ttl %lu\n", dentry, duration, ttl);
/* only track leases on regular dentries */
- if (ceph_snap(dir) != CEPH_NOSNAP)
+ if (ceph_in_snap(dir))
return;
if (mask & CEPH_LEASE_PRIMARY_LINK)
@@ -2930,7 +2930,7 @@ int ceph_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
int err;
- if (ceph_snap(inode) != CEPH_NOSNAP)
+ if (ceph_in_snap(inode))
return -EROFS;
if (ceph_inode_is_shutdown(inode))
@@ -3185,7 +3185,7 @@ int ceph_getattr(struct mnt_idmap *idmap, const struct path *path,
valid_mask |= STATX_CHANGE_COOKIE;
}
- if (ceph_snap(inode) == CEPH_NOSNAP)
+ if (!ceph_in_snap(inode))
stat->dev = sb->s_dev;
else
stat->dev = ci->i_snapid_map ? ci->i_snapid_map->dev : 0;
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 853bf698b356..540e1ad9ea77 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1310,7 +1310,7 @@ static struct inode *get_nonsnap_parent(struct dentry *dentry)
while (dentry && !IS_ROOT(dentry)) {
inode = d_inode_rcu(dentry);
- if (!inode || ceph_snap(inode) == CEPH_NOSNAP)
+ if (!inode || !ceph_in_snap(inode))
break;
dentry = dentry->d_parent;
}
@@ -1384,7 +1384,7 @@ static int __choose_mds(struct ceph_mds_client *mdsc,
inode = d_inode(req->r_dentry);
if (inode)
ihold(inode);
- } else if (ceph_snap(dir) != CEPH_NOSNAP) {
+ } else if (ceph_in_snap(dir)) {
/* direct snapped/virtual snapdir requests
* based on parent dir inode */
inode = get_nonsnap_parent(parent);
@@ -2877,7 +2877,7 @@ char *ceph_mdsc_build_path(struct ceph_mds_client *mdsc, struct dentry *dentry,
spin_unlock(&cur->d_lock);
parent = dget_parent(cur);
} else if (for_wire && inode && dentry != cur &&
- ceph_snap(inode) == CEPH_NOSNAP) {
+ !ceph_in_snap(inode)) {
spin_unlock(&cur->d_lock);
pos++; /* get rid of any prepended '/' */
break;
@@ -2986,7 +2986,7 @@ static int build_dentry_path(struct ceph_mds_client *mdsc, struct dentry *dentry
rcu_read_lock();
if (!dir)
dir = d_inode_rcu(dentry->d_parent);
- if (dir && parent_locked && ceph_snap(dir) == CEPH_NOSNAP &&
+ if (dir && parent_locked && !ceph_in_snap(dir) &&
!IS_ENCRYPTED(dir)) {
path_info->vino.ino = ceph_ino(dir);
path_info->vino.snap = ceph_snap(dir);
@@ -3012,7 +3012,7 @@ static int build_inode_path(struct inode *inode, struct ceph_path_info *path_inf
struct dentry *dentry;
char *path;
- if (ceph_snap(inode) == CEPH_NOSNAP) {
+ if (!ceph_in_snap(inode)) {
path_info->vino.ino = ceph_ino(inode);
path_info->vino.snap = ceph_snap(inode);
path_info->pathlen = 0;
diff --git a/fs/ceph/quota.c b/fs/ceph/quota.c
index 053d5bf0c9f0..08641d578a0b 100644
--- a/fs/ceph/quota.c
+++ b/fs/ceph/quota.c
@@ -223,7 +223,7 @@ static int get_quota_realm(struct ceph_mds_client *mdsc, struct inode *inode,
if (realmp)
*realmp = NULL;
- if (ceph_snap(inode) != CEPH_NOSNAP)
+ if (ceph_in_snap(inode))
return 0;
restart:
@@ -341,7 +341,7 @@ static bool check_quota_exceeded(struct inode *inode, enum quota_check_op op,
u64 max, rvalue;
bool exceeded = false;
- if (ceph_snap(inode) != CEPH_NOSNAP)
+ if (ceph_in_snap(inode))
return false;
down_read(&mdsc->snap_rwsem);
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index ab6fa8319c79..b0b8d04b594f 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -608,6 +608,14 @@ static inline u64 ceph_snap(const struct inode *inode)
return ceph_inode(inode)->i_vino.snap;
}
+/**
+ * Is this inode in a ".snap" directory?
+ */
+static inline bool ceph_in_snap(const struct inode *inode)
+{
+ return ceph_snap(inode) != CEPH_NOSNAP;
+}
+
/**
* ceph_present_ino - format an inode number for presentation to userland
* @sb: superblock where the inode lives
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 124dde705e79..af54480d9254 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -270,7 +270,7 @@ static bool ceph_vxattrcb_quota_exists(struct ceph_inode_info *ci)
bool ret = false;
spin_lock(&ci->i_ceph_lock);
if ((ci->i_max_files || ci->i_max_bytes) &&
- ci->i_vino.snap == CEPH_NOSNAP &&
+ !ceph_in_snap(&ci->netfs.inode) &&
ci->i_snap_realm &&
ci->i_snap_realm->ino == ci->i_vino.ino)
ret = true;
@@ -1193,7 +1193,7 @@ int __ceph_setxattr(struct inode *inode, const char *name,
bool check_realm = false;
bool lock_snap_rwsem = false;
- if (ceph_snap(inode) != CEPH_NOSNAP)
+ if (ceph_in_snap(inode))
return -EROFS;
vxattr = ceph_match_vxattr(inode, name);
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 11/18] fs/ceph: use ceph_vino() etc. instead of accessing i_vino directly
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
` (9 preceding siblings ...)
2026-07-06 7:24 ` [PATCH v2 10/18] fs/ceph/super.h: add helper ceph_in_snap() Max Kellermann
@ 2026-07-06 7:24 ` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 12/18] fs/ceph: remove redundant inode number from ceph_inode_info Max Kellermann
` (6 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
Prepare to remove (optimize) `i_vino`.
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
fs/ceph/addr.c | 5 ++---
fs/ceph/caps.c | 4 ++--
fs/ceph/file.c | 14 +++++++-------
fs/ceph/mds_client.c | 2 +-
fs/ceph/quota.c | 2 +-
fs/ceph/snap.c | 4 ++--
fs/ceph/super.h | 7 +++----
fs/ceph/xattr.c | 4 ++--
8 files changed, 20 insertions(+), 22 deletions(-)
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index d03639525eb8..f627f2e28b9b 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -282,7 +282,6 @@ static bool ceph_netfs_issue_op_inline(struct netfs_io_subrequest *subreq)
struct ceph_mds_reply_info_in *iinfo;
struct ceph_mds_request *req;
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
- struct ceph_inode_info *ci = ceph_inode(inode);
ssize_t err = 0;
size_t len;
int mode;
@@ -302,7 +301,7 @@ static bool ceph_netfs_issue_op_inline(struct netfs_io_subrequest *subreq)
err = PTR_ERR(req);
goto out;
}
- req->r_ino1 = ci->i_vino;
+ req->r_ino1 = ceph_vino(inode);
req->r_args.getattr.mask = cpu_to_le32(CEPH_STAT_CAP_INLINE_DATA);
req->r_num_caps = 2;
@@ -2466,7 +2465,7 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci,
rd_req->r_base_oloc.pool = pool;
if (pool_ns)
rd_req->r_base_oloc.pool_ns = ceph_get_string(pool_ns);
- ceph_oid_printf(&rd_req->r_base_oid, "%llx.00000000", ci->i_vino.ino);
+ ceph_oid_printf(&rd_req->r_base_oid, "%llx.00000000", ceph_ino(&ci->netfs.inode));
err = ceph_osdc_alloc_messages(rd_req, GFP_NOFS);
if (err)
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 372b239f6a36..00ef37312a79 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -730,7 +730,7 @@ void ceph_add_cap(struct inode *inode,
ceph_change_snap_realm(inode, realm);
else
WARN(1, "%s: couldn't find snap realm 0x%llx (ino 0x%llx oldrealm 0x%llx)\n",
- __func__, realmino, ci->i_vino.ino,
+ __func__, realmino, ceph_ino(inode),
ci->i_snap_realm ? ci->i_snap_realm->ino : 0);
}
@@ -1176,7 +1176,7 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
} else {
cap->queue_release = 0;
}
- cap->cap_ino = ci->i_vino.ino;
+ cap->cap_ino = ceph_ino(inode);
spin_unlock(&session->s_cap_lock);
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index d8859e4bed8b..7a6bff86b750 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -1118,7 +1118,7 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
read_off, read_len);
req = ceph_osdc_new_request(osdc, &ci->i_layout,
- ci->i_vino, read_off, &read_len, 0, 1,
+ ceph_vino(inode), read_off, &read_len, 0, 1,
sparse ? CEPH_OSD_OP_SPARSE_READ :
CEPH_OSD_OP_READ,
CEPH_OSD_FLAG_READ,
@@ -1824,7 +1824,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
rmw = first || last;
doutc(cl, "ino %llx %lld~%llu adjusted %lld~%llu -- %srmw\n",
- ci->i_vino.ino, pos, len, write_pos, write_len,
+ ceph_ino(inode), pos, len, write_pos, write_len,
rmw ? "" : "no ");
/*
@@ -1857,7 +1857,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
* depending on how the request was aligned.
*/
req = ceph_osdc_new_request(osdc, &ci->i_layout,
- ci->i_vino, first ? first_pos : last_pos,
+ ceph_vino(inode), first ? first_pos : last_pos,
&read_len, 0, (first && last) ? 2 : 1,
CEPH_OSD_OP_SPARSE_READ, CEPH_OSD_FLAG_READ,
NULL, ci->i_truncate_seq,
@@ -2055,7 +2055,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
}
req = ceph_osdc_new_request(osdc, &ci->i_layout,
- ci->i_vino, write_pos, &write_len,
+ ceph_vino(inode), write_pos, &write_len,
rmw ? 1 : 0, rmw ? 2 : 1,
CEPH_OSD_OP_WRITE,
CEPH_OSD_FLAG_WRITE,
@@ -2980,12 +2980,12 @@ static ssize_t ceph_do_objects_copy(struct ceph_inode_info *src_ci, u64 *src_off
&dst_objoff, &dst_objlen);
ceph_oid_init(&src_oid);
ceph_oid_printf(&src_oid, "%llx.%08llx",
- src_ci->i_vino.ino, src_objnum);
+ ceph_ino(&src_ci->netfs.inode), src_objnum);
ceph_oid_init(&dst_oid);
ceph_oid_printf(&dst_oid, "%llx.%08llx",
- dst_ci->i_vino.ino, dst_objnum);
+ ceph_ino(&dst_ci->netfs.inode), dst_objnum);
/* Do an object remote copy */
- req = ceph_alloc_copyfrom_request(osdc, src_ci->i_vino.snap,
+ req = ceph_alloc_copyfrom_request(osdc, ceph_snap(&src_ci->netfs.inode),
&src_oid, &src_oloc,
&dst_oid, &dst_oloc,
dst_ci->i_truncate_seq,
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 540e1ad9ea77..b4a1c126cbc9 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1988,7 +1988,7 @@ static void remove_session_caps(struct ceph_mds_session *session)
if (cap == prev)
break;
prev = cap;
- vino = cap->ci->i_vino;
+ vino = ceph_vino(&cap->ci->netfs.inode);
spin_unlock(&session->s_cap_lock);
inode = ceph_find_inode(sb, vino);
diff --git a/fs/ceph/quota.c b/fs/ceph/quota.c
index 08641d578a0b..02d7a3062f2d 100644
--- a/fs/ceph/quota.c
+++ b/fs/ceph/quota.c
@@ -31,7 +31,7 @@ static inline bool ceph_has_realms_with_quotas(struct inode *inode)
if (root && ceph_ino(root) == CEPH_INO_ROOT)
return false;
/* MDS stray dirs have no quota realms */
- if (ceph_vino_is_reserved(ceph_inode(inode)->i_vino))
+ if (ceph_vino_is_reserved(ceph_vino(inode)))
return false;
/* otherwise, we can't know for sure */
return true;
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index 94964e0952bd..f064b5ad3bf4 100644
--- a/fs/ceph/snap.c
+++ b/fs/ceph/snap.c
@@ -985,7 +985,7 @@ void ceph_change_snap_realm(struct inode *inode, struct ceph_snap_realm *realm)
if (oldrealm) {
spin_lock(&oldrealm->inodes_with_caps_lock);
list_del_init(&ci->i_snap_realm_item);
- if (oldrealm->ino == ci->i_vino.ino)
+ if (oldrealm->ino == ceph_ino(inode))
oldrealm->inode = NULL;
spin_unlock(&oldrealm->inodes_with_caps_lock);
ceph_put_snap_realm(mdsc, oldrealm);
@@ -996,7 +996,7 @@ void ceph_change_snap_realm(struct inode *inode, struct ceph_snap_realm *realm)
if (realm) {
spin_lock(&realm->inodes_with_caps_lock);
list_add(&ci->i_snap_realm_item, &realm->inodes_with_caps);
- if (realm->ino == ci->i_vino.ino)
+ if (realm->ino == ceph_ino(inode))
realm->inode = inode;
spin_unlock(&realm->inodes_with_caps_lock);
}
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index b0b8d04b594f..660125d94f8e 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -596,7 +596,7 @@ static inline ino_t ceph_vino_to_ino_t(const struct ceph_vino vino)
}
/* for printf-style formatting */
-#define ceph_vinop(i) ceph_inode(i)->i_vino.ino, ceph_inode(i)->i_vino.snap
+#define ceph_vinop(i) ceph_ino(i), ceph_snap(i)
static inline u64 ceph_ino(const struct inode *inode)
{
@@ -641,9 +641,8 @@ static inline u64 ceph_present_inode(struct inode *inode)
static inline int ceph_ino_compare(struct inode *inode, void *data)
{
struct ceph_vino *pvino = (struct ceph_vino *)data;
- struct ceph_inode_info *ci = ceph_inode(inode);
- return ci->i_vino.ino == pvino->ino &&
- ci->i_vino.snap == pvino->snap;
+ return ceph_ino(inode) == pvino->ino &&
+ ceph_snap(inode) == pvino->snap;
}
/*
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index af54480d9254..b8416afd4901 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -272,7 +272,7 @@ static bool ceph_vxattrcb_quota_exists(struct ceph_inode_info *ci)
if ((ci->i_max_files || ci->i_max_bytes) &&
!ceph_in_snap(&ci->netfs.inode) &&
ci->i_snap_realm &&
- ci->i_snap_realm->ino == ci->i_vino.ino)
+ ci->i_snap_realm->ino == ceph_ino(&ci->netfs.inode))
ret = true;
spin_unlock(&ci->i_ceph_lock);
return ret;
@@ -1328,7 +1328,7 @@ int __ceph_setxattr(struct inode *inode, const char *name,
spin_lock(&ci->i_ceph_lock);
if ((ci->i_max_files || ci->i_max_bytes) &&
!(ci->i_snap_realm &&
- ci->i_snap_realm->ino == ci->i_vino.ino))
+ ci->i_snap_realm->ino == ceph_ino(&ci->netfs.inode)))
err = -EOPNOTSUPP;
spin_unlock(&ci->i_ceph_lock);
}
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 12/18] fs/ceph: remove redundant inode number from ceph_inode_info
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
` (10 preceding siblings ...)
2026-07-06 7:24 ` [PATCH v2 11/18] fs/ceph: use ceph_vino() etc. instead of accessing i_vino directly Max Kellermann
@ 2026-07-06 7:24 ` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 13/18] fs/ceph: remove unused field `ceph_cap.last_used` Max Kellermann
` (5 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
On 64 bit systems, ceph_vino_to_ino_t() is a no-op, and inode.i_ino is
the same as ceph_vino.ino.
This reduces the size of `struct ceph_inode_info` by 8 bytes.
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
fs/ceph/cache.c | 4 +++-
fs/ceph/inode.c | 7 +++++++
fs/ceph/super.h | 23 +++++++++++++++++++++++
3 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/fs/ceph/cache.c b/fs/ceph/cache.c
index f678bab189d8..289615e58196 100644
--- a/fs/ceph/cache.c
+++ b/fs/ceph/cache.c
@@ -16,6 +16,7 @@ void ceph_fscache_register_inode_cookie(struct inode *inode)
{
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode);
+ struct ceph_vino vino;
/* No caching for filesystem? */
if (!fsc->fscache)
@@ -31,9 +32,10 @@ void ceph_fscache_register_inode_cookie(struct inode *inode)
WARN_ON_ONCE(ci->netfs.cache);
+ vino = ceph_vino(inode);
ci->netfs.cache =
fscache_acquire_cookie(fsc->fscache, 0,
- &ci->i_vino, sizeof(ci->i_vino),
+ &vino, sizeof(vino),
&ci->i_version, sizeof(ci->i_version),
i_size_read(inode));
if (ci->netfs.cache)
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index aba98975a8a3..e82877782601 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -44,11 +44,18 @@ static void ceph_inode_work(struct work_struct *work);
*/
static int ceph_set_ino_cb(struct inode *inode, void *data)
{
+ const struct ceph_vino *vino = data;
struct ceph_inode_info *ci = ceph_inode(inode);
struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb);
+#if BITS_PER_LONG >= 64
+ inode->i_ino = vino->ino;
+ ci->i_snap = vino->snap;
+#else
ci->i_vino = *(struct ceph_vino *)data;
inode->i_ino = ceph_vino_to_ino_t(ci->i_vino);
+#endif
+
inode_set_iversion_raw(inode, 0);
percpu_counter_inc(&mdsc->metric.total_inodes);
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 660125d94f8e..e5ab1b83a84d 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -378,7 +378,15 @@ struct ceph_inode_xattrs_info {
*/
struct ceph_inode_info {
struct netfs_inode netfs; /* Netfslib context and vfs inode */
+
+#if BITS_PER_LONG >= 64
+ /* on 64 bit systems, the full Ceph inode number is stored in
+ * netfs.inode.i_ino
+ */
+ u64 i_snap;
+#else
struct ceph_vino i_vino; /* ceph ino + snap */
+#endif
spinlock_t i_ceph_lock;
@@ -570,7 +578,14 @@ ceph_inode_to_client(const struct inode *inode)
static inline struct ceph_vino
ceph_vino(const struct inode *inode)
{
+#if BITS_PER_LONG >= 64
+ return (struct ceph_vino){
+ .ino = inode->i_ino,
+ .snap = ceph_inode(inode)->i_snap,
+ };
+#else
return ceph_inode(inode)->i_vino;
+#endif
}
static inline u32 ceph_ino_to_ino32(u64 vino)
@@ -600,12 +615,20 @@ static inline ino_t ceph_vino_to_ino_t(const struct ceph_vino vino)
static inline u64 ceph_ino(const struct inode *inode)
{
+#if BITS_PER_LONG >= 64
+ return inode->i_ino;
+#else
return ceph_inode(inode)->i_vino.ino;
+#endif
}
static inline u64 ceph_snap(const struct inode *inode)
{
+#if BITS_PER_LONG >= 64
+ return ceph_inode(inode)->i_snap;
+#else
return ceph_inode(inode)->i_vino.snap;
+#endif
}
/**
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 13/18] fs/ceph: remove unused field `ceph_cap.last_used`
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
` (11 preceding siblings ...)
2026-07-06 7:24 ` [PATCH v2 12/18] fs/ceph: remove redundant inode number from ceph_inode_info Max Kellermann
@ 2026-07-06 7:24 ` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 14/18] fs/ceph: convert ceph_cap.queue_release to bool Max Kellermann
` (4 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
This reduces the size of `struct ceph_cap` by 8 bytes.
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
fs/ceph/super.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index e5ab1b83a84d..4916faf54915 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -224,7 +224,6 @@ struct ceph_cap {
};
u32 seq, issue_seq, mseq;
u32 cap_gen; /* active/stale cycle */
- unsigned long last_used;
struct list_head caps_item;
};
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 14/18] fs/ceph: convert ceph_cap.queue_release to bool
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
` (12 preceding siblings ...)
2026-07-06 7:24 ` [PATCH v2 13/18] fs/ceph: remove unused field `ceph_cap.last_used` Max Kellermann
@ 2026-07-06 7:24 ` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 15/18] fs/ceph/super: move `ceph_cap.caps_item` into the union Max Kellermann
` (3 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
fs/ceph/caps.c | 6 +++---
fs/ceph/super.h | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 00ef37312a79..7b0125d6df0b 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -1168,13 +1168,13 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
if (queue_release &&
(!session->s_cap_reconnect ||
cap->cap_gen == atomic_read(&session->s_cap_gen))) {
- cap->queue_release = 1;
+ cap->queue_release = true;
if (removed) {
__ceph_queue_cap_release(session, cap);
removed = 0;
}
} else {
- cap->queue_release = 0;
+ cap->queue_release = false;
}
cap->cap_ino = ceph_ino(inode);
@@ -4593,7 +4593,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
if (do_cap_release) {
cap = ceph_get_cap(mdsc, NULL);
cap->cap_ino = vino.ino;
- cap->queue_release = 1;
+ cap->queue_release = true;
cap->cap_id = le64_to_cpu(h->cap_id);
cap->mseq = mseq;
cap->seq = seq;
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 4916faf54915..abe403eff0bb 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -219,7 +219,7 @@ struct ceph_cap {
/* caps to release */
struct {
u64 cap_ino;
- int queue_release;
+ bool queue_release;
};
};
u32 seq, issue_seq, mseq;
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 15/18] fs/ceph/super: move `ceph_cap.caps_item` into the union
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
` (13 preceding siblings ...)
2026-07-06 7:24 ` [PATCH v2 14/18] fs/ceph: convert ceph_cap.queue_release to bool Max Kellermann
@ 2026-07-06 7:24 ` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 16/18] fs/ceph/snap: add a kmem_cache for struct ceph_snap_realm Max Kellermann
` (2 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
The `caps_item` field is only used if the `ceph_cap` object is
"reserved", i.e. when it is in the `ceph_mds_client.caps_list` list
(but is otherwise uninitialized).
This reduces the size of the struct by 16 bytes.
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
fs/ceph/super.h | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index abe403eff0bb..afe681a47f71 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -208,6 +208,14 @@ struct ceph_cap {
struct list_head session_caps; /* per-session caplist */
u64 cap_id; /* unique cap id (mds provided) */
union {
+ /* reserved caps */
+ struct {
+ /**
+ * For the `ceph_mds_client.caps_list` list.
+ * Protected by `caps_list_lock`.
+ */
+ struct list_head caps_item;
+ };
/* in-use caps */
struct {
int issued; /* latest, from the mds */
@@ -224,7 +232,6 @@ struct ceph_cap {
};
u32 seq, issue_seq, mseq;
u32 cap_gen; /* active/stale cycle */
- struct list_head caps_item;
};
#define CHECK_CAPS_AUTHONLY 1 /* only check auth cap */
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 16/18] fs/ceph/snap: add a kmem_cache for struct ceph_snap_realm
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
` (14 preceding siblings ...)
2026-07-06 7:24 ` [PATCH v2 15/18] fs/ceph/super: move `ceph_cap.caps_item` into the union Max Kellermann
@ 2026-07-06 7:24 ` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 17/18] fs/ceph/super: reorder struct ceph_snap_realm fields Max Kellermann
2026-07-06 7:24 ` [PATCH v2 18/18] fs/ceph/super: remove redundant field `ceph_snap_realm.parent_ino` Max Kellermann
17 siblings, 0 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
There will be lots of ceph_snap_realm instances, and having a separate
kmem_cache seems worthwile.
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
fs/ceph/snap.c | 4 ++--
fs/ceph/super.c | 9 +++++++++
include/linux/ceph/libceph.h | 1 +
3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index f064b5ad3bf4..12f80df4b651 100644
--- a/fs/ceph/snap.c
+++ b/fs/ceph/snap.c
@@ -118,7 +118,7 @@ static struct ceph_snap_realm *ceph_create_snap_realm(
lockdep_assert_held_write(&mdsc->snap_rwsem);
- realm = kzalloc_obj(*realm, GFP_NOFS);
+ realm = kmem_cache_zalloc(ceph_snap_realm_cachep, GFP_NOFS);
if (!realm)
return ERR_PTR(-ENOMEM);
@@ -205,7 +205,7 @@ static void __destroy_snap_realm(struct ceph_mds_client *mdsc,
kfree(realm->prior_parent_snaps);
kfree(realm->snaps);
ceph_put_snap_context(realm->cached_context);
- kfree(realm);
+ kmem_cache_free(ceph_snap_realm_cachep, realm);
}
/*
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index c05fbd4237f8..73c316c23315 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -910,6 +910,7 @@ struct kmem_cache *ceph_inode_cachep;
struct kmem_cache *ceph_cap_cachep;
struct kmem_cache *ceph_cap_snap_cachep;
struct kmem_cache *ceph_cap_flush_cachep;
+struct kmem_cache *ceph_snap_realm_cachep;
struct kmem_cache *ceph_dentry_cachep;
struct kmem_cache *ceph_file_cachep;
struct kmem_cache *ceph_dir_file_cachep;
@@ -945,6 +946,11 @@ static int __init init_caches(void)
if (!ceph_cap_flush_cachep)
goto bad_cap_flush;
+ ceph_snap_realm_cachep = KMEM_CACHE(ceph_snap_realm,
+ SLAB_RECLAIM_ACCOUNT);
+ if (!ceph_snap_realm_cachep)
+ goto bad_snap_realm;
+
ceph_dentry_cachep = KMEM_CACHE(ceph_dentry_info,
SLAB_RECLAIM_ACCOUNT);
if (!ceph_dentry_cachep)
@@ -984,6 +990,8 @@ static int __init init_caches(void)
bad_file:
kmem_cache_destroy(ceph_dentry_cachep);
bad_dentry:
+ kmem_cache_destroy(ceph_snap_realm_cachep);
+bad_snap_realm:
kmem_cache_destroy(ceph_cap_flush_cachep);
bad_cap_flush:
kmem_cache_destroy(ceph_cap_snap_cachep);
@@ -1006,6 +1014,7 @@ static void destroy_caches(void)
kmem_cache_destroy(ceph_cap_cachep);
kmem_cache_destroy(ceph_cap_snap_cachep);
kmem_cache_destroy(ceph_cap_flush_cachep);
+ kmem_cache_destroy(ceph_snap_realm_cachep);
kmem_cache_destroy(ceph_dentry_cachep);
kmem_cache_destroy(ceph_file_cachep);
kmem_cache_destroy(ceph_dir_file_cachep);
diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
index 63e0e2aa1ce9..379629cafbce 100644
--- a/include/linux/ceph/libceph.h
+++ b/include/linux/ceph/libceph.h
@@ -276,6 +276,7 @@ extern struct kmem_cache *ceph_inode_cachep;
extern struct kmem_cache *ceph_cap_cachep;
extern struct kmem_cache *ceph_cap_snap_cachep;
extern struct kmem_cache *ceph_cap_flush_cachep;
+extern struct kmem_cache *ceph_snap_realm_cachep;
extern struct kmem_cache *ceph_dentry_cachep;
extern struct kmem_cache *ceph_file_cachep;
extern struct kmem_cache *ceph_dir_file_cachep;
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 17/18] fs/ceph/super: reorder struct ceph_snap_realm fields
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
` (15 preceding siblings ...)
2026-07-06 7:24 ` [PATCH v2 16/18] fs/ceph/snap: add a kmem_cache for struct ceph_snap_realm Max Kellermann
@ 2026-07-06 7:24 ` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 18/18] fs/ceph/super: remove redundant field `ceph_snap_realm.parent_ino` Max Kellermann
17 siblings, 0 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
This eliminates two padding hole and reduces the size of the struct by
16 bytes.
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
fs/ceph/super.h | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index afe681a47f71..ca4db56ef2d0 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -1020,16 +1020,16 @@ struct ceph_readdir_cache_control {
struct ceph_snap_realm {
u64 ino;
struct inode *inode;
- atomic_t nref;
struct rb_node node;
u64 created, seq;
u64 parent_ino;
u64 parent_since; /* snapid when our current parent became so */
- u64 *prior_parent_snaps; /* snaps inherited from any parents we */
- u32 num_prior_parent_snaps; /* had prior to parent_since */
+ u64 *prior_parent_snaps; /* snaps inherited from any parents we had prior to parent_since */
u64 *snaps; /* snaps specific to this realm */
+
+ u32 num_prior_parent_snaps;
u32 num_snaps;
struct ceph_snap_realm *parent;
@@ -1047,6 +1047,8 @@ struct ceph_snap_realm {
struct list_head inodes_with_caps;
spinlock_t inodes_with_caps_lock;
+
+ atomic_t nref;
};
static inline int default_congestion_kb(void)
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 18/18] fs/ceph/super: remove redundant field `ceph_snap_realm.parent_ino`
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
` (16 preceding siblings ...)
2026-07-06 7:24 ` [PATCH v2 17/18] fs/ceph/super: reorder struct ceph_snap_realm fields Max Kellermann
@ 2026-07-06 7:24 ` Max Kellermann
17 siblings, 0 replies; 19+ messages in thread
From: Max Kellermann @ 2026-07-06 7:24 UTC (permalink / raw)
To: idryomov, amarkuze, ceph-devel, linux-kernel; +Cc: Max Kellermann
This reduces the size of the struct by another 8 bytes.
Signed-off-by: Max Kellermann <max.kellermann@ionos.com>
---
fs/ceph/mds_client.c | 4 ++--
fs/ceph/snap.c | 5 ++---
fs/ceph/super.h | 1 -
3 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index b4a1c126cbc9..f0b9d653ffd1 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -5044,10 +5044,10 @@ static int encode_snap_realms(struct ceph_mds_client *mdsc,
}
doutc(cl, " adding snap realm %llx seq %lld parent %llx\n",
- realm->ino, realm->seq, realm->parent_ino);
+ realm->ino, realm->seq, realm->parent ? realm->parent->ino : 0);
sr_rec.ino = cpu_to_le64(realm->ino);
sr_rec.seq = cpu_to_le64(realm->seq);
- sr_rec.parent = cpu_to_le64(realm->parent_ino);
+ sr_rec.parent = cpu_to_le64(realm->parent ? realm->parent->ino : 0);
err = ceph_pagelist_append(pagelist, &sr_rec, sizeof(sr_rec));
if (err)
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index 12f80df4b651..a5f8f3f95f3b 100644
--- a/fs/ceph/snap.c
+++ b/fs/ceph/snap.c
@@ -297,7 +297,7 @@ static int adjust_snap_realm_parent(struct ceph_mds_client *mdsc,
lockdep_assert_held_write(&mdsc->snap_rwsem);
- if (realm->parent_ino == parentino)
+ if (realm->parent && realm->parent->ino == parentino)
return 0;
parent = ceph_lookup_snap_realm(mdsc, parentino);
@@ -307,12 +307,11 @@ static int adjust_snap_realm_parent(struct ceph_mds_client *mdsc,
return PTR_ERR(parent);
}
doutc(cl, "%llx %p: %llx %p -> %llx %p\n", realm->ino, realm,
- realm->parent_ino, realm->parent, parentino, parent);
+ realm->parent ? realm->parent->ino : 0, realm->parent, parentino, parent);
if (realm->parent) {
list_del_init(&realm->child_item);
ceph_put_snap_realm(mdsc, realm->parent);
}
- realm->parent_ino = parentino;
realm->parent = parent;
list_add(&realm->child_item, &parent->children);
return 1;
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index ca4db56ef2d0..86a5929ee5d2 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -1023,7 +1023,6 @@ struct ceph_snap_realm {
struct rb_node node;
u64 created, seq;
- u64 parent_ino;
u64 parent_since; /* snapid when our current parent became so */
u64 *prior_parent_snaps; /* snaps inherited from any parents we had prior to parent_since */
--
2.47.3
^ permalink raw reply related [flat|nested] 19+ messages in thread
end of thread, other threads:[~2026-07-06 7:25 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-06 7:24 [PATCH v2 00/18] fs/ceph: optimize struct layouts Max Kellermann
2026-07-06 7:24 ` [PATCH v2 01/18] fs/ceph/super: remove unused field `i_cap_migration_resv` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 02/18] fs/ceph/super: make field `i_truncate_pagecache_size` optional Max Kellermann
2026-07-06 7:24 ` [PATCH v2 03/18] include/ceph/ceph_fs.h: convert `pool_id` to u32 Max Kellermann
2026-07-06 7:24 ` [PATCH v2 04/18] fs/ceph/super.h: convert ceph_inode_xattr fields to `bool` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 05/18] fs/ceph/super.h: convert ceph_cap_snap.writing " Max Kellermann
2026-07-06 7:24 ` [PATCH v2 06/18] fs/ceph: consistently use `u32` for `time_warp_seq` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 07/18] fs/ceph/super: reorder fields to eliminate padding holes Max Kellermann
2026-07-06 7:24 ` [PATCH v2 08/18] fs/ceph: remove i_truncate_mutex, use i_fragtree_mutex for both Max Kellermann
2026-07-06 7:24 ` [PATCH v2 09/18] fs/ceph/super.h: add `const` to helpers Max Kellermann
2026-07-06 7:24 ` [PATCH v2 10/18] fs/ceph/super.h: add helper ceph_in_snap() Max Kellermann
2026-07-06 7:24 ` [PATCH v2 11/18] fs/ceph: use ceph_vino() etc. instead of accessing i_vino directly Max Kellermann
2026-07-06 7:24 ` [PATCH v2 12/18] fs/ceph: remove redundant inode number from ceph_inode_info Max Kellermann
2026-07-06 7:24 ` [PATCH v2 13/18] fs/ceph: remove unused field `ceph_cap.last_used` Max Kellermann
2026-07-06 7:24 ` [PATCH v2 14/18] fs/ceph: convert ceph_cap.queue_release to bool Max Kellermann
2026-07-06 7:24 ` [PATCH v2 15/18] fs/ceph/super: move `ceph_cap.caps_item` into the union Max Kellermann
2026-07-06 7:24 ` [PATCH v2 16/18] fs/ceph/snap: add a kmem_cache for struct ceph_snap_realm Max Kellermann
2026-07-06 7:24 ` [PATCH v2 17/18] fs/ceph/super: reorder struct ceph_snap_realm fields Max Kellermann
2026-07-06 7:24 ` [PATCH v2 18/18] fs/ceph/super: remove redundant field `ceph_snap_realm.parent_ino` Max Kellermann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox