* [PATCH 01/12] fs/ceph/super: remove unused field `i_cap_migration_resv`
2026-06-12 16:51 [PATCH 00/12] fs/ceph: optimize struct layouts Max Kellermann
@ 2026-06-12 16:51 ` Max Kellermann
2026-06-12 16:51 ` [PATCH 02/12] fs/ceph/super: make field `i_truncate_pagecache_size` optional Max Kellermann
` (10 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Max Kellermann @ 2026-06-12 16:51 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 afc89ce91804..6aec40955387 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -448,7 +448,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] 13+ messages in thread* [PATCH 02/12] fs/ceph/super: make field `i_truncate_pagecache_size` optional
2026-06-12 16:51 [PATCH 00/12] fs/ceph: optimize struct layouts Max Kellermann
2026-06-12 16:51 ` [PATCH 01/12] fs/ceph/super: remove unused field `i_cap_migration_resv` Max Kellermann
@ 2026-06-12 16:51 ` Max Kellermann
2026-06-12 16:51 ` [PATCH 03/12] include/ceph/ceph_fs.h: convert `pool_id` to u32 Max Kellermann
` (9 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Max Kellermann @ 2026-06-12 16:51 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 22c7da1ea61c..1504b889622c 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -680,7 +680,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;
@@ -865,6 +867,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);
@@ -872,6 +875,7 @@ int ceph_fill_file_size(struct inode *inode, int issued,
} else {
ci->i_truncate_pagecache_size = truncate_size;
}
+#endif
}
return queue_trunc;
}
@@ -2331,7 +2335,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);
@@ -2341,7 +2345,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 6aec40955387..f0f03aeb5b19 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -461,11 +461,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 */
@@ -660,6 +663,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_CEPH_FS_SNAPSHOTS
+ return ci->i_truncate_pagecache_size;
+#else
+ return ci->i_truncate_size;
+#endif
+}
/*
* Ceph inode.
--
2.47.3
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH 03/12] include/ceph/ceph_fs.h: convert `pool_id` to u32
2026-06-12 16:51 [PATCH 00/12] fs/ceph: optimize struct layouts Max Kellermann
2026-06-12 16:51 ` [PATCH 01/12] fs/ceph/super: remove unused field `i_cap_migration_resv` Max Kellermann
2026-06-12 16:51 ` [PATCH 02/12] fs/ceph/super: make field `i_truncate_pagecache_size` optional Max Kellermann
@ 2026-06-12 16:51 ` Max Kellermann
2026-06-12 16:51 ` [PATCH 04/12] fs/ceph/super.h: convert ceph_inode_xattr fields to `bool` Max Kellermann
` (8 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Max Kellermann @ 2026-06-12 16:51 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 0a86f672cc09..a11b5c633358 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, flags;
/* Only need to do this for regular files */
@@ -2587,11 +2587,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 d51454e995a8..cf9916608dc2 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -3638,7 +3638,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 1504b889622c..c26217ed2034 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -1175,7 +1175,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 4e6c87f8414c..7b848fdd6f70 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -396,7 +396,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 e773be07f767..9808eb10625d 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] 13+ messages in thread* [PATCH 04/12] fs/ceph/super.h: convert ceph_inode_xattr fields to `bool`
2026-06-12 16:51 [PATCH 00/12] fs/ceph: optimize struct layouts Max Kellermann
` (2 preceding siblings ...)
2026-06-12 16:51 ` [PATCH 03/12] include/ceph/ceph_fs.h: convert `pool_id` to u32 Max Kellermann
@ 2026-06-12 16:51 ` Max Kellermann
2026-06-12 16:51 ` [PATCH 05/12] fs/ceph/super.h: convert ceph_cap_snap.writing " Max Kellermann
` (7 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Max Kellermann @ 2026-06-12 16:51 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 f0f03aeb5b19..18960a9e735a 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -318,10 +318,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] 13+ messages in thread* [PATCH 05/12] fs/ceph/super.h: convert ceph_cap_snap.writing fields to `bool`
2026-06-12 16:51 [PATCH 00/12] fs/ceph: optimize struct layouts Max Kellermann
` (3 preceding siblings ...)
2026-06-12 16:51 ` [PATCH 04/12] fs/ceph/super.h: convert ceph_inode_xattr fields to `bool` Max Kellermann
@ 2026-06-12 16:51 ` Max Kellermann
2026-06-12 16:51 ` [PATCH 06/12] fs/ceph: consistently use `u32` for `time_warp_seq` Max Kellermann
` (6 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Max Kellermann @ 2026-06-12 16:51 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 cf9916608dc2..e50bcb393c8f 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -3288,7 +3288,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 52b4c2684f92..6dbc7859ff49 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 18960a9e735a..505a1552f355 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -269,7 +269,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] 13+ messages in thread* [PATCH 06/12] fs/ceph: consistently use `u32` for `time_warp_seq`
2026-06-12 16:51 [PATCH 00/12] fs/ceph: optimize struct layouts Max Kellermann
` (4 preceding siblings ...)
2026-06-12 16:51 ` [PATCH 05/12] fs/ceph/super.h: convert ceph_cap_snap.writing " Max Kellermann
@ 2026-06-12 16:51 ` Max Kellermann
2026-06-12 16:51 ` [PATCH 07/12] fs/ceph/super: reorder fields to eliminate padding holes Max Kellermann
` (5 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Max Kellermann @ 2026-06-12 16:51 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 c26217ed2034..17df694fe978 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -915,7 +915,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);
@@ -939,7 +939,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);
@@ -971,7 +971,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 505a1552f355..9b5119b1d0a9 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -266,7 +266,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 */
@@ -1091,7 +1091,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] 13+ messages in thread* [PATCH 07/12] fs/ceph/super: reorder fields to eliminate padding holes
2026-06-12 16:51 [PATCH 00/12] fs/ceph: optimize struct layouts Max Kellermann
` (5 preceding siblings ...)
2026-06-12 16:51 ` [PATCH 06/12] fs/ceph: consistently use `u32` for `time_warp_seq` Max Kellermann
@ 2026-06-12 16:51 ` Max Kellermann
2026-06-12 16:52 ` [PATCH 08/12] fs/ceph: remove i_truncate_mutex, use i_fragtree_mutex for both Max Kellermann
` (4 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Max Kellermann @ 2026-06-12 16:51 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 9b5119b1d0a9..646ebc03d263 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -248,6 +248,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;
@@ -256,7 +259,6 @@ struct ceph_cap_snap {
int issued, dirty;
struct ceph_snap_context *context;
- umode_t mode;
kuid_t uid;
kgid_t gid;
@@ -266,11 +268,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;
};
@@ -315,8 +318,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;
@@ -377,9 +380,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;
@@ -410,8 +413,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;
@@ -451,15 +454,14 @@ 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 */
unsigned long i_last_rd;
unsigned long i_last_wr;
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
@@ -488,6 +490,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] 13+ messages in thread* [PATCH 08/12] fs/ceph: remove i_truncate_mutex, use i_fragtree_mutex for both
2026-06-12 16:51 [PATCH 00/12] fs/ceph: optimize struct layouts Max Kellermann
` (6 preceding siblings ...)
2026-06-12 16:51 ` [PATCH 07/12] fs/ceph/super: reorder fields to eliminate padding holes Max Kellermann
@ 2026-06-12 16:52 ` Max Kellermann
2026-06-12 16:52 ` [PATCH 09/12] fs/ceph/super.h: add `const` to helpers Max Kellermann
` (3 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Max Kellermann @ 2026-06-12 16:52 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 17df694fe978..c0d88cf1f6e3 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -676,7 +676,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 646ebc03d263..19f26724b285 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -459,7 +459,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] 13+ messages in thread* [PATCH 09/12] fs/ceph/super.h: add `const` to helpers
2026-06-12 16:51 [PATCH 00/12] fs/ceph: optimize struct layouts Max Kellermann
` (7 preceding siblings ...)
2026-06-12 16:52 ` [PATCH 08/12] fs/ceph: remove i_truncate_mutex, use i_fragtree_mutex for both Max Kellermann
@ 2026-06-12 16:52 ` Max Kellermann
2026-06-12 16:52 ` [PATCH 10/12] fs/ceph/super.h: add helper ceph_in_snap() Max Kellermann
` (2 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Max Kellermann @ 2026-06-12 16:52 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 19f26724b285..b1d38fa6647f 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -581,7 +581,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);
@@ -591,12 +591,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;
}
@@ -810,7 +810,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);
}
@@ -1068,7 +1068,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,
@@ -1165,7 +1165,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);
@@ -1349,7 +1349,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 */
@@ -1424,7 +1424,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;
@@ -1457,7 +1457,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] 13+ messages in thread* [PATCH 10/12] fs/ceph/super.h: add helper ceph_in_snap()
2026-06-12 16:51 [PATCH 00/12] fs/ceph: optimize struct layouts Max Kellermann
` (8 preceding siblings ...)
2026-06-12 16:52 ` [PATCH 09/12] fs/ceph/super.h: add `const` to helpers Max Kellermann
@ 2026-06-12 16:52 ` Max Kellermann
2026-06-12 16:52 ` [PATCH 11/12] fs/ceph: use ceph_vino() etc. instead of accessing i_vino directly Max Kellermann
2026-06-12 16:52 ` [PATCH 12/12] fs/ceph: remove redundant inode number from ceph_inode_info Max Kellermann
11 siblings, 0 replies; 13+ messages in thread
From: Max Kellermann @ 2026-06-12 16:52 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 a11b5c633358..b114ef483937 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -2567,7 +2567,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 d54d71669176..00e62991a416 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);
@@ -1534,7 +1534,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",
@@ -1770,7 +1770,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,
@@ -2405,7 +2405,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();
@@ -2757,7 +2757,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;
}
@@ -3046,7 +3046,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 c0d88cf1f6e3..dcdbc24d1e21 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -765,7 +765,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);
@@ -1065,7 +1065,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;
@@ -1087,7 +1087,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);
@@ -1332,7 +1332,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,
@@ -1432,7 +1432,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)
@@ -2929,7 +2929,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))
@@ -3184,7 +3184,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 ed17e0023705..1534a91342a7 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1308,7 +1308,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;
}
@@ -1382,7 +1382,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);
@@ -2782,7 +2782,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;
@@ -2891,7 +2891,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);
@@ -2917,7 +2917,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 b1d38fa6647f..abdbffbdf0e6 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -601,6 +601,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 9808eb10625d..c5e9ef656b5f 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] 13+ messages in thread* [PATCH 11/12] fs/ceph: use ceph_vino() etc. instead of accessing i_vino directly
2026-06-12 16:51 [PATCH 00/12] fs/ceph: optimize struct layouts Max Kellermann
` (9 preceding siblings ...)
2026-06-12 16:52 ` [PATCH 10/12] fs/ceph/super.h: add helper ceph_in_snap() Max Kellermann
@ 2026-06-12 16:52 ` Max Kellermann
2026-06-12 16:52 ` [PATCH 12/12] fs/ceph: remove redundant inode number from ceph_inode_info Max Kellermann
11 siblings, 0 replies; 13+ messages in thread
From: Max Kellermann @ 2026-06-12 16:52 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 b114ef483937..d9a32897f4f0 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 e50bcb393c8f..151baed53721 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 00e62991a416..2cc5d8db40ac 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -1113,7 +1113,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,
@@ -1819,7 +1819,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 ");
/*
@@ -1852,7 +1852,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,
@@ -2050,7 +2050,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,
@@ -2975,12 +2975,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 1534a91342a7..ebe2b79eafca 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1986,7 +1986,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 6dbc7859ff49..44200eca9af4 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 abdbffbdf0e6..5e4addbfc0f2 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -589,7 +589,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)
{
@@ -634,9 +634,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 c5e9ef656b5f..cffb9236d4e0 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] 13+ messages in thread* [PATCH 12/12] fs/ceph: remove redundant inode number from ceph_inode_info
2026-06-12 16:51 [PATCH 00/12] fs/ceph: optimize struct layouts Max Kellermann
` (10 preceding siblings ...)
2026-06-12 16:52 ` [PATCH 11/12] fs/ceph: use ceph_vino() etc. instead of accessing i_vino directly Max Kellermann
@ 2026-06-12 16:52 ` Max Kellermann
11 siblings, 0 replies; 13+ messages in thread
From: Max Kellermann @ 2026-06-12 16:52 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 dcdbc24d1e21..c8ee7d735861 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 5e4addbfc0f2..5cb535b126eb 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -376,7 +376,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;
@@ -563,7 +571,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)
@@ -593,12 +608,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] 13+ messages in thread