FAILED: patch "[PATCH] ceph: fix hanging __ceph_get_caps() with stale mds_wanted" failed to apply to 5.15-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 50958bb928bad3bdba9e5d1b7ff4bbadcf6951e6
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026072911-tipoff-trilogy-a6d0@gregkh' --subject-prefix 'PATCH 5.15.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 50958bb928bad3bdba9e5d1b7ff4bbadcf6951e6 Mon Sep 17 00:00:00 2001
From: Max Kellermann <[email protected]>
Date: Mon, 6 Jul 2026 17:06:59 +0200
Subject: [PATCH] ceph: fix hanging __ceph_get_caps() with stale mds_wanted
A reader can hang forever in __ceph_get_caps() when the client no longer holds FILE_RD, but local cap state still says that the capability is already wanted (via mds_wanted).
One way to trigger this is through MDS cap revocation. If another client performs a conflicting operation, the MDS can revoke FILE_RD from the reader; the next read then has to reacquire FILE_RD. If the cap update that should request FILE_RD never reaches the MDS after cap->mds_wanted was raised, the reader is left holding only non-file caps while local mds_wanted still includes the file read caps.
In that state, try_get_cap_refs() sees need <= mds_wanted and returns 0, so __ceph_get_caps() just waits on i_cap_wq. If the cap update that was supposed to request FILE_RD never reaches the MDS after cap->mds_wanted was` raised, no further request is sent and the waiter can sleep indefinitely until unrelated cap traffic happens to wake it up.
The ordering issue is that cap->mds_wanted is updated in __prep_cap() before the CEPH_MSG_CLIENT_CAPS message is actually queued for send. That makes one field serve two different meanings at
once: what this client wants, and what the client believes the MDS already knows it wants.
A proper fix would be to split those states and track whether a cap update is actually in flight or has been observed by the MDS. However, simply moving the cap->mds_wanted assignment later would not be sufficient: queueing the message in the messenger does not guarantee that the MDS processed that specific wanted set, and reconnect or message loss can still invalidate that assumption. Fixing that properly would require a larger rework of the cap state machine.
To allow simpler backports to stable kernels, this patch implements a simpler workaround:
- stop waiting forever in __ceph_get_caps(); after a bounded wait, fall back to the renew path
- make ceph_renew_caps() issue a synchronous OPEN request whenever the inode still does not actually hold the wanted caps, instead of only calling ceph_check_caps()
The extra issued-vs-wanted check in ceph_renew_caps() is necessary because the previous test only checked whether the inode still had any real caps at all. That is not enough after revocation: the client can still hold something like pLs and yet be missing FILE_RD completely. In that case, falling back to ceph_check_caps() is not sufficient, because it still trusts cap->mds_wanted and may resend nothing. By requiring (issued & wanted) == wanted before taking the asynchronous path, the code only uses ceph_check_caps() when the wanted caps are already actually issued. Otherwise, it sends the synchronous OPEN renew.
This preserves the existing asynchronous fast path when the wanted caps are already issued, avoids changing cap-state semantics, and fixes the hang by guaranteeing that a stalled waiter eventually retries through a path that does not rely on the stale mds_wanted state.
[ idryomov: move CEPH_GET_CAPS_WAIT_TIMEOUT from libceph.h to
mds_client.h, formatting ]
fs/ceph/caps.c +15 -2
@@ -3094,7 +3094,19 @@ int __ceph_get_caps(struct inode *inode, struct ceph_file_info *fi, int need, ret = -ERESTARTSYS ;break ; } -wait_woken (&wait,TASK_INTERRUPTIBLE ,MAX_SCHEDULE_TIMEOUT ); + +/* +* If a cap update is lost after +* mds_wanted was raised, waiting +* forever will never make progress. +* Retry the renew path periodically +* so we can resend synchronously. +*/ +if (!wait_woken (&wait,TASK_INTERRUPTIBLE , +CEPH_GET_CAPS_WAIT_TIMEOUT )) { + ret = -EUCLEAN ; +break ; + } }remove_wait_queue (&ci->i_cap_wq, &wait);
@@ -3128,7 +3140,8 @@ int __ceph_get_caps(struct inode *inode, struct ceph_file_info *fi, int need,continue ; }if (ret == -EUCLEAN ) { -/* session was killed, try renew caps */ +/* session was killed or a waited cap +* request needs a retry */ ret =ceph_renew_caps (inode, flags);if (ret ==0 )continue ;
fs/ceph/file.c +5 -4
@@ -314,7 +314,7 @@ static int ceph_init_file(struct inode *inode, struct file *file, int fmode) }/* -* try renew caps after session gets killed. +* Retry cap acquisition after a stale session or a lost cap update. */ int ceph_renew_caps (struct inode *inode,int fmode) {
@@ -322,14 +322,15 @@ int ceph_renew_caps(struct inode *inode, int fmode)struct ceph_client *cl = mdsc->fsc->client;struct ceph_inode_info *ci =ceph_inode (inode);struct ceph_mds_request *req; -int err, flags, wanted; +int err, flags, wanted, issued;spin_lock (&ci->i_ceph_lock);__ceph_touch_fmode (ci, mdsc, fmode); wanted =__ceph_caps_file_wanted (ci); + issued =__ceph_caps_issued (ci,NULL );if (__ceph_is_any_real_caps (ci) && - (!(wanted &CEPH_CAP_ANY_WR ) || ci->i_auth_cap)) { -int issued =__ceph_caps_issued (ci,NULL ); + (!(wanted &CEPH_CAP_ANY_WR ) || ci->i_auth_cap) && + (issued & wanted) == wanted) {spin_unlock (&ci->i_ceph_lock); doutc(cl, "%p %llx.%llx want %s issued %s updating mds_wanted\n", inode, ceph_vinop(inode), ceph_cap_string(wanted),
fs/ceph/mds_client.h +1 -0
@@ -77,6 +77,7 @@ struct ceph_fs_client;struct ceph_cap ;#define MDS_AUTH_UID_ANY -1 +#define CEPH_GET_CAPS_WAIT_TIMEOUT (5 * HZ)#define CEPH_CAP_FLUSH_WAIT_TIMEOUT_SEC 60#define CEPH_CAP_FLUSH_MAX_DUMP_ENTRIES 5#define CEPH_CAP_FLUSH_MAX_DUMP_ITERS 5
Sasha Levin
maintainerPATCH 1/4 libceph: add doutc and *_client debug macros support
From: Xiubo Li <[email protected]>
[ Upstream commit 5c5f0d2b5f92c47baf82b9b211e27edd7d195158 ]
This will help print the fsid and client's global_id in debug logs, and also print the function names.
[ idryomov: %lld -> %llu, leading space for doutc(), don't include
__func__ in pr_*() variants ]
Stable-dep-of: 50958bb928ba ("ceph: fix hanging __ceph_get_caps() with stale mds_wanted")
--- include/linux/ceph/ceph_debug.h | 38 +++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+)
include/linux/ceph/ceph_debug.h +38 -0
@@ -19,12 +19,25 @@pr_debug ("%.*s %12.12s:%-4d : " fmt, \8 - (int )sizeof (KBUILD_MODNAME )," " , \ kbasename(__FILE__), __LINE__, ##__VA_ARGS__) +# define doutc (client, fmt, ...) \ + pr_debug("%.*s %12.12s:%-4d : [%pU %llu] " fmt, \ + 8 - (int)sizeof(KBUILD_MODNAME), " ", \ + kbasename(__FILE__), __LINE__, \ + &client->fsid, client->monc.auth->global_id, \ + ##__VA_ARGS__)# else /* faux printk call just to see any compiler warnings. */ # define dout (fmt, ...) do { \ if (0) \ printk(KERN_DEBUG fmt, ##__VA_ARGS__); \ } while (0) +# define doutc (client, fmt, ...) do { \ + if (0) \ + printk(KERN_DEBUG "[%pU %llu] " fmt, \ + &client->fsid, \ + client->monc.auth->global_id, \ + ##__VA_ARGS__); \ + } while (0)# endif #else
@@ -33,7 +46,32 @@* or, just wrap pr_debug */ # define dout (fmt, ...) pr_debug(" " fmt, ##__VA_ARGS__) +# define doutc (client, fmt, ...) \ + pr_debug(" [%pU %llu] %s: " fmt, &client->fsid, \ + client->monc.auth->global_id, __func__, ##__VA_ARGS__)#endif +#define pr_notice_client (client, fmt, ...) \ + pr_notice("[%pU %llu]: " fmt, &client->fsid, \ + client->monc.auth->global_id, ##__VA_ARGS__) +#define pr_info_client (client, fmt, ...) \ + pr_info("[%pU %llu]: " fmt, &client->fsid, \ + client->monc.auth->global_id, ##__VA_ARGS__) +#define pr_warn_client (client, fmt, ...) \ + pr_warn("[%pU %llu]: " fmt, &client->fsid, \ + client->monc.auth->global_id, ##__VA_ARGS__) +#define pr_warn_once_client (client, fmt, ...) \ + pr_warn_once("[%pU %llu]: " fmt, &client->fsid, \ + client->monc.auth->global_id, ##__VA_ARGS__) +#define pr_err_client (client, fmt, ...) \ + pr_err("[%pU %llu]: " fmt, &client->fsid, \ + client->monc.auth->global_id, ##__VA_ARGS__) +#define pr_warn_ratelimited_client (client, fmt, ...) \ + pr_warn_ratelimited("[%pU %llu]: " fmt, &client->fsid, \ + client->monc.auth->global_id, ##__VA_ARGS__) +#define pr_err_ratelimited_client (client, fmt, ...) \ + pr_err_ratelimited("[%pU %llu]: " fmt, &client->fsid, \ + client->monc.auth->global_id, ##__VA_ARGS__) +#endif
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/4 ceph: rename _to_client() to _to_fs_client()
From: Xiubo Li <[email protected]>
[ Upstream commit 5995d90d2d19f337df6a50bcf4699ef053214dac ]
We need to covert the inode to ceph_client in the following commit, and will add one new helper for that, here we rename the old helper to _fs_client().
Stable-dep-of: 50958bb928ba ("ceph: fix hanging __ceph_get_caps() with stale mds_wanted")
--- fs/ceph/addr.c | 20 ++++++++++---------- fs/ceph/cache.c | 2 +- fs/ceph/caps.c | 36 ++++++++++++++++++------------------ fs/ceph/dir.c | 20 ++++++++++---------- fs/ceph/export.c | 10 +++++----- fs/ceph/file.c | 24 ++++++++++++------------ fs/ceph/inode.c | 14 +++++++------- fs/ceph/ioctl.c | 8 ++++---- fs/ceph/snap.c | 2 +- fs/ceph/super.c | 22 +++++++++++----------- fs/ceph/super.h | 8 ++++---- fs/ceph/xattr.c | 12 ++++++------ 12 files changed, 89 insertions(+), 89 deletions(-)
fs/ceph/addr.c +10 -10
@@ -196,7 +196,7 @@ static void ceph_netfs_expand_readahead(struct netfs_read_request *rreq)static bool ceph_netfs_clamp_length (struct netfs_read_subrequest *subreq) {struct inode *inode = subreq->rreq->inode; -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);struct ceph_inode_info *ci =ceph_inode (inode);u64 objno, objoff;u32 xlen;
@@ -210,7 +210,7 @@ static bool ceph_netfs_clamp_length(struct netfs_read_subrequest *subreq)static void finish_netfs_read (struct ceph_osd_request *req) { -struct ceph_fs_client *fsc =ceph_inode_to_client (req->r_inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (req->r_inode);struct ceph_osd_data *osd_data =osd_req_op_extent_osd_data (req,0 );struct netfs_read_subrequest *subreq = req->r_priv;int num_pages;
@@ -243,7 +243,7 @@ static void ceph_netfs_issue_op(struct netfs_read_subrequest *subreq)struct netfs_read_request *rreq = subreq->rreq;struct inode *inode = rreq->inode;struct ceph_inode_info *ci =ceph_inode (inode); -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);struct ceph_osd_request *req;struct ceph_vino vino =ceph_vino (inode);struct iov_iter iter;
@@ -483,7 +483,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) {struct inode *inode = page->mapping->host;struct ceph_inode_info *ci =ceph_inode (inode); -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);struct ceph_snap_context *snapc, *oldest;loff_t page_off =page_offset (page);int err;
@@ -625,7 +625,7 @@ static void writepages_finish(struct ceph_osd_request *req)int rc = req->r_result;struct ceph_snap_context *snapc = req->r_snapc;struct address_space *mapping = inode->i_mapping; -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);unsigned int len =0 ;bool remove_page;
@@ -707,7 +707,7 @@ static int ceph_writepages_start(struct address_space *mapping, {struct inode *inode = mapping->host;struct ceph_inode_info *ci =ceph_inode (inode); -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);struct ceph_vino vino =ceph_vino (inode);pgoff_t index, start_index, end =-1 ;struct ceph_snap_context *snapc =NULL , *last_snapc =NULL , *pgsnapc;
@@ -1144,7 +1144,7 @@ static struct ceph_snap_context * ceph_find_incompatible(struct page *page) {struct inode *inode = page->mapping->host; -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);struct ceph_inode_info *ci =ceph_inode (inode);if (READ_ONCE (fsc->mount_state) >=CEPH_MOUNT_SHUTDOWN ) {
@@ -1594,7 +1594,7 @@ int ceph_uninline_data(struct file *filp, struct page *locked_page) {struct inode *inode =file_inode (filp);struct ceph_inode_info *ci =ceph_inode (inode); -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);struct ceph_osd_request *req;struct page *page =NULL ;u64 len, inline_version;
@@ -1751,7 +1751,7 @@ enum {static int __ceph_pool_perm_get (struct ceph_inode_info *ci,s64 pool,struct ceph_string *pool_ns) { -struct ceph_fs_client *fsc =ceph_inode_to_client (&ci->vfs_inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (&ci->vfs_inode);struct ceph_mds_client *mdsc = fsc->mdsc;struct ceph_osd_request *rd_req =NULL , *wr_req =NULL ;struct rb_node **p, *parent;
@@ -1944,7 +1944,7 @@ int ceph_pool_perm_check(struct inode *inode, int need)return 0 ; } -if (ceph_test_mount_opt (ceph_inode_to_client (inode), +if (ceph_test_mount_opt (ceph_inode_to_fs_client (inode),NOPOOLPERM ))return 0 ;
fs/ceph/cache.c +1 -1
@@ -138,7 +138,7 @@ static const struct fscache_cookie_def ceph_fscache_inode_object_def = {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_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);struct ceph_aux_inode aux;/* No caching for filesystem */
fs/ceph/caps.c +18 -18
@@ -633,7 +633,7 @@ void ceph_add_cap(struct inode *inode, unsigned seq, unsigned mseq, u64 realmino, int flags, struct ceph_cap **new_cap) { - struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; + struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc;struct ceph_inode_info *ci =ceph_inode (inode);struct ceph_cap *cap;int mds = session->s_mds;
@@ -919,7 +919,7 @@ int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch)int __ceph_caps_issued_mask_metric (struct ceph_inode_info *ci,int mask,int touch) { -struct ceph_fs_client *fsc =ceph_sb_to_client (ci->vfs_inode.i_sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (ci->vfs_inode.i_sb);int r; r =__ceph_caps_issued_mask (ci, mask, touch);
@@ -993,7 +993,7 @@ int __ceph_caps_file_wanted(struct ceph_inode_info *ci)const int WR_SHIFT =ffs (CEPH_FILE_MODE_WR );const int LAZY_SHIFT =ffs (CEPH_FILE_MODE_LAZY );struct ceph_mount_options *opt = -ceph_inode_to_client (&ci->vfs_inode)->mount_options; +ceph_inode_to_fs_client (&ci->vfs_inode)->mount_options;unsigned long used_cutoff = jiffies - opt->caps_wanted_delay_max *HZ ;unsigned long idle_cutoff = jiffies - opt->caps_wanted_delay_min *HZ ;
@@ -1118,7 +1118,7 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)dout ("__ceph_remove_cap %p from %p\n" , cap, &ci->vfs_inode); - mdsc =ceph_inode_to_client (&ci->vfs_inode)->mdsc; + mdsc =ceph_inode_to_fs_client (&ci->vfs_inode)->mdsc;/* remove from inode's cap rbtree, and clear auth cap */ rb_erase (&cap->ci_node, &ci->i_caps);
@@ -1188,7 +1188,7 @@ void ceph_remove_cap(struct ceph_cap *cap, bool queue_release)lockdep_assert_held (&ci->i_ceph_lock); - fsc =ceph_sb_to_client (ci->vfs_inode.i_sb); + fsc =ceph_sb_to_fs_client (ci->vfs_inode.i_sb); WARN_ON_ONCE(ci->i_auth_cap == cap && !list_empty(&ci->i_dirty_item) && !fsc->blocklisted &&
@@ -1623,7 +1623,7 @@ void ceph_flush_snaps(struct ceph_inode_info *ci, struct ceph_mds_session **psession) {struct inode *inode = &ci->vfs_inode; -struct ceph_mds_client *mdsc =ceph_inode_to_client (inode)->mdsc; +struct ceph_mds_client *mdsc =ceph_inode_to_fs_client (inode)->mdsc;struct ceph_mds_session *session =NULL ;bool need_put = false;int mds;
@@ -1688,7 +1688,7 @@ int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask, struct ceph_cap_flush **pcf) {struct ceph_mds_client *mdsc = -ceph_sb_to_client (ci->vfs_inode.i_sb)->mdsc; +ceph_sb_to_fs_client (ci->vfs_inode.i_sb)->mdsc;struct inode *inode = &ci->vfs_inode;int was = ci->i_dirty_caps;int dirty =0 ;
@@ -1811,7 +1811,7 @@ static u64 __mark_caps_flushing(struct inode *inode, struct ceph_mds_session *session, bool wake, u64 *oldest_flush_tid) { - struct ceph_mds_client *mdsc = ceph_sb_to_client(inode->i_sb)->mdsc; + struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc;struct ceph_inode_info *ci =ceph_inode (inode);struct ceph_cap_flush *cf =NULL ;int flushing;
@@ -2143,7 +2143,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags,*/ static int try_flush_caps (struct inode *inode,u64 *ptid) { -struct ceph_mds_client *mdsc =ceph_sb_to_client (inode->i_sb)->mdsc; +struct ceph_mds_client *mdsc =ceph_sb_to_fs_client (inode->i_sb)->mdsc;struct ceph_inode_info *ci =ceph_inode (inode);int flushing =0 ;u64 flush_tid =0 , oldest_flush_tid =0 ;
@@ -2221,7 +2221,7 @@ static int caps_are_flushed(struct inode *inode, u64 flush_tid)*/ static int unsafe_request_wait (struct inode *inode) { -struct ceph_mds_client *mdsc =ceph_sb_to_client (inode->i_sb)->mdsc; +struct ceph_mds_client *mdsc =ceph_sb_to_fs_client (inode->i_sb)->mdsc;struct ceph_inode_info *ci =ceph_inode (inode);struct ceph_mds_request *req1 =NULL , *req2 =NULL ;int ret, err =0 ;
@@ -2400,7 +2400,7 @@ int ceph_write_inode(struct inode *inode, struct writeback_control *wbc) caps_are_flushed(inode, flush_tid)); }else {struct ceph_mds_client *mdsc = -ceph_sb_to_client (inode->i_sb)->mdsc; +ceph_sb_to_fs_client (inode->i_sb)->mdsc;spin_lock (&ci->i_ceph_lock);if (__ceph_caps_dirty (ci))
@@ -2649,7 +2649,7 @@ static int try_get_cap_refs(struct inode *inode, int need, int want, loff_t endoff, int flags, int *got) { struct ceph_inode_info *ci = ceph_inode(inode); -struct ceph_mds_client *mdsc =ceph_inode_to_client (inode)->mdsc; +struct ceph_mds_client *mdsc =ceph_inode_to_fs_client (inode)->mdsc;int ret =0 ;int have, implemented;bool snap_rwsem_locked = false;
@@ -2864,7 +2864,7 @@ int ceph_get_caps(struct file *filp, int need, int want, loff_t endoff, int *gotstruct ceph_file_info *fi = filp->private_data;struct inode *inode =file_inode (filp);struct ceph_inode_info *ci =ceph_inode (inode); -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);int ret, _got, flags; ret =ceph_pool_perm_check (inode, need);
@@ -3593,7 +3593,7 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid, __releases(ci->i_ceph_lock) {struct ceph_inode_info *ci =ceph_inode (inode); -struct ceph_mds_client *mdsc =ceph_sb_to_client (inode->i_sb)->mdsc; +struct ceph_mds_client *mdsc =ceph_sb_to_fs_client (inode->i_sb)->mdsc;struct ceph_cap_flush *cf, *tmp_cf;LIST_HEAD (to_remove);unsigned seq =le32_to_cpu (m->seq);
@@ -3699,7 +3699,7 @@ void __ceph_remove_capsnap(struct inode *inode, struct ceph_cap_snap *capsnap, bool *wake_ci, bool *wake_mdsc) { struct ceph_inode_info *ci = ceph_inode(inode); -struct ceph_mds_client *mdsc =ceph_sb_to_client (inode->i_sb)->mdsc; +struct ceph_mds_client *mdsc =ceph_sb_to_fs_client (inode->i_sb)->mdsc;bool ret;lockdep_assert_held (&ci->i_ceph_lock);
@@ -3743,7 +3743,7 @@ static void handle_cap_flushsnap_ack(struct inode *inode, u64 flush_tid, struct ceph_mds_session *session) {struct ceph_inode_info *ci =ceph_inode (inode); -struct ceph_mds_client *mdsc =ceph_sb_to_client (inode->i_sb)->mdsc; +struct ceph_mds_client *mdsc =ceph_sb_to_fs_client (inode->i_sb)->mdsc;u64 follows =le64_to_cpu (m->snap_follows);struct ceph_cap_snap *capsnap;bool flushed = false;
@@ -3827,7 +3827,7 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,struct ceph_mds_cap_peer *ph, struct ceph_mds_session *session) { - struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; + struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc;struct ceph_mds_session *tsession =NULL ;struct ceph_cap *cap, *tcap, *new_cap =NULL ;struct ceph_inode_info *ci =ceph_inode (inode);
@@ -4441,7 +4441,7 @@ int ceph_drop_caps_for_unlink(struct inode *inode)if (__ceph_caps_dirty (ci)) {struct ceph_mds_client *mdsc = -ceph_inode_to_client (inode)->mdsc; +ceph_inode_to_fs_client (inode)->mdsc;__cap_delay_requeue_front (mdsc, ci); } }
fs/ceph/dir.c +10 -10
@@ -307,7 +307,7 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)struct ceph_dir_file_info *dfi = file->private_data;struct inode *inode =file_inode (file);struct ceph_inode_info *ci =ceph_inode (inode); -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);struct ceph_mds_client *mdsc = fsc->mdsc;int i;int err;
@@ -679,7 +679,7 @@ static loff_t ceph_dir_llseek(struct file *file, loff_t offset, int whence)struct dentry *ceph_handle_snapdir (struct ceph_mds_request *req,struct dentry *dentry) { -struct ceph_fs_client *fsc =ceph_sb_to_client (dentry->d_sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (dentry->d_sb);struct inode *parent =d_inode (dentry->d_parent);/* we hold i_mutex */ /* .snap dir? */
@@ -748,7 +748,7 @@ static bool is_root_ceph_dentry(struct inode *inode, struct dentry *dentry)static struct dentry *ceph_lookup (struct inode *dir,struct dentry *dentry,unsigned int flags) { -struct ceph_fs_client *fsc =ceph_sb_to_client (dir->i_sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (dir->i_sb);struct ceph_mds_client *mdsc =ceph_sb_to_mdsc (dir->i_sb);struct ceph_mds_request *req;int op;
@@ -1147,7 +1147,7 @@ static int get_caps_for_async_unlink(struct inode *dir, struct dentry *dentry)*/ static int ceph_unlink (struct inode *dir,struct dentry *dentry) { -struct ceph_fs_client *fsc =ceph_sb_to_client (dir->i_sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (dir->i_sb);struct ceph_mds_client *mdsc = fsc->mdsc;struct inode *inode =d_inode (dentry);struct ceph_inode_info *ci =ceph_inode (inode);
@@ -1308,7 +1308,7 @@ void __ceph_dentry_lease_touch(struct ceph_dentry_info *di)return ; } - mdsc =ceph_sb_to_client (dn->d_sb)->mdsc; + mdsc =ceph_sb_to_fs_client (dn->d_sb)->mdsc;spin_lock (&mdsc->dentry_list_lock);list_move_tail (&di->lease_list, &mdsc->dentry_leases);spin_unlock (&mdsc->dentry_list_lock);
@@ -1355,7 +1355,7 @@ void __ceph_dentry_dir_lease_touch(struct ceph_dentry_info *di)return ; } - mdsc =ceph_sb_to_client (dn->d_sb)->mdsc; + mdsc =ceph_sb_to_fs_client (dn->d_sb)->mdsc;spin_lock (&mdsc->dentry_list_lock);__dentry_dir_lease_touch (mdsc, di),spin_unlock (&mdsc->dentry_list_lock);
@@ -1369,7 +1369,7 @@ static void __dentry_lease_unlist(struct ceph_dentry_info *di)if (list_empty (&di->lease_list))return ; - mdsc =ceph_sb_to_client (di->dentry->d_sb)->mdsc; + mdsc =ceph_sb_to_fs_client (di->dentry->d_sb)->mdsc;spin_lock (&mdsc->dentry_list_lock);list_del_init (&di->lease_list);spin_unlock (&mdsc->dentry_list_lock);
@@ -1722,7 +1722,7 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)dout ("d_revalidate %p '%pd' inode %p offset 0x%llx\n" , dentry, dentry, inode,ceph_dentry (dentry)->offset); - mdsc =ceph_sb_to_client (dir->i_sb)->mdsc; + mdsc =ceph_sb_to_fs_client (dir->i_sb)->mdsc;/* always trust cached snapped dentries, snapdir dentry */ if (ceph_snap (dir) !=CEPH_NOSNAP ) {
@@ -1829,7 +1829,7 @@ static int ceph_d_delete(const struct dentry *dentry)static void ceph_d_release (struct dentry *dentry) {struct ceph_dentry_info *di =ceph_dentry (dentry); -struct ceph_fs_client *fsc =ceph_sb_to_client (dentry->d_sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (dentry->d_sb);dout ("d_release %p\n" , dentry);
@@ -1898,7 +1898,7 @@ static ssize_t ceph_read_dir(struct file *file, char __user *buf, size_t size,int left;const int bufsize =1024 ; -if (!ceph_test_mount_opt (ceph_sb_to_client (inode->i_sb),DIRSTAT )) +if (!ceph_test_mount_opt (ceph_sb_to_fs_client (inode->i_sb),DIRSTAT ))return -EISDIR ;if (!dfi->dir_info) {
fs/ceph/export.c +5 -5
@@ -122,7 +122,7 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,static struct inode *__lookup_inode (struct super_block *sb,u64 ino) { -struct ceph_mds_client *mdsc =ceph_sb_to_client (sb)->mdsc; +struct ceph_mds_client *mdsc =ceph_sb_to_fs_client (sb)->mdsc;struct inode *inode;struct ceph_vino vino;int err;
@@ -198,7 +198,7 @@ static struct dentry *__snapfh_to_dentry(struct super_block *sb, struct ceph_nfs_snapfh *sfh, bool want_parent) { -struct ceph_mds_client *mdsc =ceph_sb_to_client (sb)->mdsc; +struct ceph_mds_client *mdsc =ceph_sb_to_fs_client (sb)->mdsc;struct ceph_mds_request *req;struct inode *inode;struct ceph_vino vino;
@@ -305,7 +305,7 @@ static struct dentry *ceph_fh_to_dentry(struct super_block *sb,static struct dentry *__get_parent (struct super_block *sb,struct dentry *child,u64 ino) { -struct ceph_mds_client *mdsc =ceph_sb_to_client (sb)->mdsc; +struct ceph_mds_client *mdsc =ceph_sb_to_fs_client (sb)->mdsc;struct ceph_mds_request *req;struct inode *inode;int mask;
@@ -427,7 +427,7 @@ static int __get_snap_name(struct dentry *parent, char *name, {struct inode *inode =d_inode (child);struct inode *dir =d_inode (parent); -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);struct ceph_mds_request *req =NULL ;char *last_name =NULL ;unsigned next_offset =2 ;
@@ -530,7 +530,7 @@ static int ceph_get_name(struct dentry *parent, char *name,if (ceph_snap (inode) !=CEPH_NOSNAP )return __get_snap_name (parent, name, child); - mdsc =ceph_inode_to_client (inode)->mdsc; + mdsc =ceph_inode_to_fs_client (inode)->mdsc; req =ceph_mdsc_create_request (mdsc,CEPH_MDS_OP_LOOKUPNAME ,USE_ANY_MDS );if (IS_ERR (req))
fs/ceph/file.c +12 -12
@@ -233,7 +233,7 @@ static int ceph_init_file_info(struct inode *inode, struct file *file,spin_lock_init (&fi->rw_contexts_lock);INIT_LIST_HEAD (&fi->rw_contexts); - fi->filp_gen =READ_ONCE (ceph_inode_to_client (inode)->filp_gen); + fi->filp_gen =READ_ONCE (ceph_inode_to_fs_client (inode)->filp_gen);return 0 ; }
@@ -338,7 +338,7 @@ int ceph_renew_caps(struct inode *inode, int fmode)int ceph_open (struct inode *inode,struct file *file) {struct ceph_inode_info *ci =ceph_inode (inode); -struct ceph_fs_client *fsc =ceph_sb_to_client (inode->i_sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (inode->i_sb);struct ceph_mds_client *mdsc = fsc->mdsc;struct ceph_mds_request *req;struct ceph_file_info *fi = file->private_data;
@@ -687,7 +687,7 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry,int ceph_atomic_open (struct inode *dir,struct dentry *dentry,struct file *file,unsigned flags,umode_t mode) { -struct ceph_fs_client *fsc =ceph_sb_to_client (dir->i_sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (dir->i_sb);struct ceph_mds_client *mdsc = fsc->mdsc;struct ceph_mds_request *req;struct dentry *dn;
@@ -875,7 +875,7 @@ static ssize_t ceph_sync_read(struct kiocb *iocb, struct iov_iter *to,struct file *file = iocb->ki_filp;struct inode *inode =file_inode (file);struct ceph_inode_info *ci =ceph_inode (inode); -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);struct ceph_osd_client *osdc = &fsc->client->osdc;ssize_t ret;u64 off = iocb->ki_pos;
@@ -1085,7 +1085,7 @@ static void ceph_aio_complete_req(struct ceph_osd_request *req)if (aio_work) {INIT_WORK (&aio_work->work, ceph_aio_retry_work); aio_work->req = req; -queue_work (ceph_inode_to_client (inode)->inode_wq, +queue_work (ceph_inode_to_fs_client (inode)->inode_wq, &aio_work->work);return ; }
@@ -1213,7 +1213,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,struct file *file = iocb->ki_filp;struct inode *inode =file_inode (file);struct ceph_inode_info *ci =ceph_inode (inode); -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);struct ceph_client_metric *metric = &fsc->mdsc->metric;struct ceph_vino vino;struct ceph_osd_request *req;
@@ -1423,7 +1423,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,struct file *file = iocb->ki_filp;struct inode *inode =file_inode (file);struct ceph_inode_info *ci =ceph_inode (inode); -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);struct ceph_vino vino;struct ceph_osd_request *req;struct page **pages;
@@ -1702,7 +1702,7 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)struct ceph_file_info *fi = file->private_data;struct inode *inode =file_inode (file);struct ceph_inode_info *ci =ceph_inode (inode); -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);struct ceph_osd_client *osdc = &fsc->client->osdc;struct ceph_cap_flush *prealloc_cf;ssize_t count, written =0 ;
@@ -1895,7 +1895,7 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)static loff_t ceph_llseek (struct file *file,loff_t offset,int whence) {struct inode *inode = file->f_mapping->host; -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);loff_t i_size;loff_t ret;
@@ -1988,7 +1988,7 @@ static int ceph_zero_partial_object(struct inode *inode, loff_t offset, loff_t *length) { struct ceph_inode_info *ci = ceph_inode(inode); -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);struct ceph_osd_request *req;struct ceph_snap_context *snapc;int ret =0 ;
@@ -2332,7 +2332,7 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off,struct ceph_inode_info *src_ci =ceph_inode (src_inode);struct ceph_inode_info *dst_ci =ceph_inode (dst_inode);struct ceph_cap_flush *prealloc_cf; -struct ceph_fs_client *src_fsc =ceph_inode_to_client (src_inode); +struct ceph_fs_client *src_fsc =ceph_inode_to_fs_client (src_inode);loff_t size;ssize_t ret = -EIO , bytes;u64 src_objnum, dst_objnum, src_objoff, dst_objoff;
@@ -2340,7 +2340,7 @@ static ssize_t __ceph_copy_file_range(struct file *src_file, loff_t src_off,int src_got =0 , dst_got =0 , err, dirty;if (src_inode->i_sb != dst_inode->i_sb) { -struct ceph_fs_client *dst_fsc =ceph_inode_to_client (dst_inode); +struct ceph_fs_client *dst_fsc =ceph_inode_to_fs_client (dst_inode);if (ceph_fsid_compare (&src_fsc->client->fsid, &dst_fsc->client->fsid)) {
fs/ceph/inode.c +7 -7
@@ -1272,7 +1272,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req)struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info;struct inode *in =NULL ;struct ceph_vino tvino, dvino; -struct ceph_fs_client *fsc =ceph_sb_to_client (sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (sb);int err =0 ; dout("fill_trace %p is_dentry %d is_target %d\n", req,
@@ -1828,7 +1828,7 @@ bool ceph_inode_set_size(struct inode *inode, loff_t size)void ceph_queue_inode_work (struct inode *inode,int work_bit) { -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);struct ceph_inode_info *ci =ceph_inode (inode);set_bit (work_bit, &ci->i_work_mask);
@@ -1845,7 +1845,7 @@ void ceph_queue_inode_work(struct inode *inode, int work_bit)static void ceph_do_invalidate_pages (struct inode *inode) {struct ceph_inode_info *ci =ceph_inode (inode); -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);u32 orig_gen;int check =0 ;
@@ -2000,7 +2000,7 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)struct ceph_inode_info *ci =ceph_inode (inode);unsigned int ia_valid = attr->ia_valid;struct ceph_mds_request *req; -struct ceph_mds_client *mdsc =ceph_sb_to_client (inode->i_sb)->mdsc; +struct ceph_mds_client *mdsc =ceph_sb_to_fs_client (inode->i_sb)->mdsc;struct ceph_cap_flush *prealloc_cf;int issued;int release =0 , dirtied =0 ;
@@ -2215,7 +2215,7 @@ int ceph_setattr(struct user_namespace *mnt_userns, struct dentry *dentry, struct iattr *attr) {struct inode *inode =d_inode (dentry); -struct ceph_fs_client *fsc =ceph_inode_to_client (inode); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (inode);int err;if (ceph_snap (inode) !=CEPH_NOSNAP )
@@ -2248,7 +2248,7 @@ int ceph_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,int __ceph_do_getattr (struct inode *inode,struct page *locked_page,int mask,bool force) { -struct ceph_fs_client *fsc =ceph_sb_to_client (inode->i_sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (inode->i_sb);struct ceph_mds_client *mdsc = fsc->mdsc;struct ceph_mds_request *req;int mode;
@@ -2378,7 +2378,7 @@ int ceph_getattr(struct user_namespace *mnt_userns, const struct path *path, stat->dev = ci->i_snapid_map ? ci->i_snapid_map->dev :0 ;if (S_ISDIR (inode->i_mode)) { -if (ceph_test_mount_opt (ceph_sb_to_client (inode->i_sb), +if (ceph_test_mount_opt (ceph_sb_to_fs_client (inode->i_sb),RBYTES )) stat->size = ci->i_rbytes;else
fs/ceph/ioctl.c +4 -4
@@ -64,7 +64,7 @@ static long __validate_layout(struct ceph_mds_client *mdsc,static long ceph_ioctl_set_layout (struct file *file,void __user *arg) {struct inode *inode =file_inode (file); -struct ceph_mds_client *mdsc =ceph_sb_to_client (inode->i_sb)->mdsc; +struct ceph_mds_client *mdsc =ceph_sb_to_fs_client (inode->i_sb)->mdsc;struct ceph_mds_request *req;struct ceph_ioctl_layout l;struct ceph_inode_info *ci =ceph_inode (file_inode (file));
@@ -139,7 +139,7 @@ static long ceph_ioctl_set_layout_policy (struct file *file, void __user *arg)struct ceph_mds_request *req;struct ceph_ioctl_layout l;int err; -struct ceph_mds_client *mdsc =ceph_sb_to_client (inode->i_sb)->mdsc; +struct ceph_mds_client *mdsc =ceph_sb_to_fs_client (inode->i_sb)->mdsc;/* copy and validate */ if (copy_from_user (&l, arg,sizeof (l)))
@@ -182,7 +182,7 @@ static long ceph_ioctl_get_dataloc(struct file *file, void __user *arg)struct inode *inode =file_inode (file);struct ceph_inode_info *ci =ceph_inode (inode);struct ceph_osd_client *osdc = - &ceph_sb_to_client (inode->i_sb)->client->osdc; + &ceph_sb_to_fs_client (inode->i_sb)->client->osdc;struct ceph_object_locator oloc;CEPH_DEFINE_OID_ONSTACK (oid);u32 xlen;
@@ -243,7 +243,7 @@ static long ceph_ioctl_lazyio(struct file *file)struct ceph_file_info *fi = file->private_data;struct inode *inode =file_inode (file);struct ceph_inode_info *ci =ceph_inode (inode); -struct ceph_mds_client *mdsc =ceph_inode_to_client (inode)->mdsc; +struct ceph_mds_client *mdsc =ceph_inode_to_fs_client (inode)->mdsc;if ((fi->fmode &CEPH_FILE_MODE_LAZY ) ==0 ) {spin_lock (&ci->i_ceph_lock);
fs/ceph/snap.c +1 -1
@@ -875,7 +875,7 @@ static void flush_snaps(struct ceph_mds_client *mdsc)void ceph_change_snap_realm (struct inode *inode,struct ceph_snap_realm *realm) {struct ceph_inode_info *ci =ceph_inode (inode); -struct ceph_mds_client *mdsc =ceph_inode_to_client (inode)->mdsc; +struct ceph_mds_client *mdsc =ceph_inode_to_fs_client (inode)->mdsc;struct ceph_snap_realm *oldrealm = ci->i_snap_realm;lockdep_assert_held (&ci->i_ceph_lock);
fs/ceph/super.c +11 -11
@@ -41,7 +41,7 @@ static LIST_HEAD(ceph_fsc_list);*/ static void ceph_put_super (struct super_block *s) { -struct ceph_fs_client *fsc =ceph_sb_to_client (s); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (s);dout ("put_super\n" );ceph_mdsc_close_sessions (fsc->mdsc);
@@ -49,7 +49,7 @@ static void ceph_put_super(struct super_block *s)static int ceph_statfs (struct dentry *dentry,struct kstatfs *buf) { -struct ceph_fs_client *fsc =ceph_inode_to_client (d_inode (dentry)); +struct ceph_fs_client *fsc =ceph_inode_to_fs_client (d_inode (dentry));struct ceph_mon_client *monc = &fsc->client->monc;struct ceph_statfs st;int i, err;
@@ -112,7 +112,7 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)static int ceph_sync_fs (struct super_block *sb,int wait) { -struct ceph_fs_client *fsc =ceph_sb_to_client (sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (sb);if (!wait) {dout ("sync_fs (non-blocking)\n" );
@@ -529,7 +529,7 @@ static int compare_mount_options(struct ceph_mount_options *new_fsopt,*/ static int ceph_show_options (struct seq_file *m,struct dentry *root) { -struct ceph_fs_client *fsc =ceph_sb_to_client (root->d_sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (root->d_sb);struct ceph_mount_options *fsopt = fsc->mount_options;size_t pos;int ret;
@@ -848,7 +848,7 @@ static void __ceph_umount_begin(struct ceph_fs_client *fsc)*/ static void ceph_umount_begin (struct super_block *sb) { -struct ceph_fs_client *fsc =ceph_sb_to_client (sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (sb);dout ("ceph_umount_begin - starting forced umount\n" );if (!fsc)
@@ -1006,7 +1006,7 @@ static int ceph_compare_super(struct super_block *sb, struct fs_context *fc)struct ceph_fs_client *new = fc->s_fs_info;struct ceph_mount_options *fsopt = new->mount_options;struct ceph_options *opt = new->client->options; -struct ceph_fs_client *fsc =ceph_sb_to_client (sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (sb);dout ("ceph_compare_super %p\n" , sb);
@@ -1099,9 +1099,9 @@ static int ceph_get_tree(struct fs_context *fc) goto out; } -if (ceph_sb_to_client (sb) != fsc) { +if (ceph_sb_to_fs_client (sb) != fsc) {destroy_fs_client (fsc); - fsc =ceph_sb_to_client (sb); + fsc =ceph_sb_to_fs_client (sb);dout ("get_sb got existing client %p\n" , fsc); }else {dout ("get_sb using new client %p\n" , fsc);
@@ -1152,7 +1152,7 @@ static int ceph_reconfigure_fc(struct fs_context *fc) {struct ceph_parse_opts_ctx *pctx = fc->fs_private;struct ceph_mount_options *fsopt = pctx->opts; -struct ceph_fs_client *fsc =ceph_sb_to_client (fc->root->d_sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (fc->root->d_sb);if (fsopt->flags &CEPH_MOUNT_OPT_ASYNC_DIROPS )ceph_set_mount_opt (fsc,ASYNC_DIROPS );
@@ -1223,7 +1223,7 @@ static int ceph_init_fs_context(struct fs_context *fc)static void ceph_kill_sb (struct super_block *s) { -struct ceph_fs_client *fsc =ceph_sb_to_client (s); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (s);dout ("kill_sb %p\n" , s);
@@ -1261,7 +1261,7 @@ MODULE_ALIAS_FS("ceph");int ceph_force_reconnect (struct super_block *sb) { -struct ceph_fs_client *fsc =ceph_sb_to_client (sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (sb);int err =0 ; fsc->mount_state =CEPH_MOUNT_RECOVER ;
fs/ceph/super.h +4 -4
@@ -439,13 +439,13 @@ ceph_inode(const struct inode *inode) }static inline struct ceph_fs_client * -ceph_inode_to_client (const struct inode *inode) +ceph_inode_to_fs_client (const struct inode *inode) {return (struct ceph_fs_client *)inode->i_sb->s_fs_info; }static inline struct ceph_fs_client * -ceph_sb_to_client (const struct super_block *sb) +ceph_sb_to_fs_client (const struct super_block *sb) {return (struct ceph_fs_client *)sb->s_fs_info; }
@@ -453,7 +453,7 @@ ceph_sb_to_client(const struct super_block *sb)static inline struct ceph_mds_client *ceph_sb_to_mdsc (const struct super_block *sb) { -return (struct ceph_mds_client *)ceph_sb_to_client (sb)->mdsc; +return (struct ceph_mds_client *)ceph_sb_to_fs_client (sb)->mdsc; } static inline struct ceph_vino
@@ -509,7 +509,7 @@ static inline u64 ceph_snap(struct inode *inode)*/ static inline u64 ceph_present_ino (struct super_block *sb,u64 ino) { -if (unlikely (ceph_test_mount_opt (ceph_sb_to_client (sb),INO32 ))) +if (unlikely (ceph_test_mount_opt (ceph_sb_to_fs_client (sb),INO32 )))return ceph_ino_to_ino32 (ino);return ino; }
fs/ceph/xattr.c +6 -6
@@ -57,7 +57,7 @@ static bool ceph_vxattrcb_layout_exists(struct ceph_inode_info *ci)static ssize_t ceph_vxattrcb_layout (struct ceph_inode_info *ci,char *val,size_t size) { -struct ceph_fs_client *fsc =ceph_sb_to_client (ci->vfs_inode.i_sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (ci->vfs_inode.i_sb);struct ceph_osd_client *osdc = &fsc->client->osdc;struct ceph_string *pool_ns;s64 pool = ci->i_layout.pool_id;
@@ -161,7 +161,7 @@ static ssize_t ceph_vxattrcb_layout_pool(struct ceph_inode_info *ci, char *val, size_t size) { ssize_t ret; -struct ceph_fs_client *fsc =ceph_sb_to_client (ci->vfs_inode.i_sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (ci->vfs_inode.i_sb);struct ceph_osd_client *osdc = &fsc->client->osdc;s64 pool = ci->i_layout.pool_id;const char *pool_name;
@@ -313,7 +313,7 @@ static ssize_t ceph_vxattrcb_snap_btime(struct ceph_inode_info *ci, char *val,static ssize_t ceph_vxattrcb_cluster_fsid (struct ceph_inode_info *ci,char *val,size_t size) { -struct ceph_fs_client *fsc =ceph_sb_to_client (ci->vfs_inode.i_sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (ci->vfs_inode.i_sb);return ceph_fmt_xattr (val, size,"%pU" , &fsc->client->fsid); }
@@ -321,7 +321,7 @@ static ssize_t ceph_vxattrcb_cluster_fsid(struct ceph_inode_info *ci,static ssize_t ceph_vxattrcb_client_id (struct ceph_inode_info *ci,char *val,size_t size) { -struct ceph_fs_client *fsc =ceph_sb_to_client (ci->vfs_inode.i_sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (ci->vfs_inode.i_sb);return ceph_fmt_xattr (val, size,"client%lld" ,ceph_client_gid (fsc->client));
@@ -1052,7 +1052,7 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size)static int ceph_sync_setxattr (struct inode *inode,const char *name,const char *value,size_t size,int flags) { -struct ceph_fs_client *fsc =ceph_sb_to_client (inode->i_sb); +struct ceph_fs_client *fsc =ceph_sb_to_fs_client (inode->i_sb);struct ceph_inode_info *ci =ceph_inode (inode);struct ceph_mds_request *req;struct ceph_mds_client *mdsc = fsc->mdsc;
@@ -1122,7 +1122,7 @@ int __ceph_setxattr(struct inode *inode, const char *name, {struct ceph_vxattr *vxattr;struct ceph_inode_info *ci =ceph_inode (inode); -struct ceph_mds_client *mdsc =ceph_sb_to_client (inode->i_sb)->mdsc; +struct ceph_mds_client *mdsc =ceph_sb_to_fs_client (inode->i_sb)->mdsc;struct ceph_cap_flush *prealloc_cf =NULL ;struct ceph_buffer *old_blob =NULL ;int issued;
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/4 ceph: print cluster fsid and client global_id in all debug logs
In reply to Sasha LevinFrom: Xiubo Li <[email protected]>
[ Upstream commit 38d46409c4639a1d659ebfa70e27a8bed6b8ee1d ]
Multiple CephFS mounts on a host is increasingly common so disambiguating messages like this is necessary and will make it easier to debug issues.
At the same this will improve the debug logs to make them easier to troubleshooting issues, such as print the ino# instead only printing the memory addresses of the corresponding inodes and print the dentry names instead of the corresponding memory addresses for the dentry,etc.
Stable-dep-of: 50958bb928ba ("ceph: fix hanging __ceph_get_caps() with stale mds_wanted")
--- fs/ceph/acl.c | 6 ++++-- fs/ceph/file.c | 9 ++++++--- fs/ceph/metric.c | 5 +++-- fs/ceph/super.h | 6 ++++++ 4 files changed, 19 insertions(+), 7 deletions(-)
fs/ceph/acl.c +4 -2
@@ -15,6 +15,7 @@#include <linux/slab.h> #include "super.h" +#include "mds_client.h" static inline void ceph_set_cached_acl (struct inode *inode,int type,struct posix_acl *acl)
@@ -31,6 +32,7 @@ static inline void ceph_set_cached_acl(struct inode *inode,struct posix_acl *ceph_get_acl (struct inode *inode,int type,bool rcu) { +struct ceph_client *cl =ceph_inode_to_client (inode);int size;unsigned int retry_cnt =0 ;const char *name;
@@ -72,8 +74,8 @@ struct posix_acl *ceph_get_acl(struct inode *inode, int type, bool rcu) }else if (size == -ENODATA || size ==0 ) { acl =NULL ; }else { -pr_err_ratelimited ("get acl %llx.%llx failed, err=%d\n" , -ceph_vinop (inode), size); +pr_err_ratelimited_client (cl,"%llx.%llx failed, err=%d\n" , +ceph_vinop (inode), size); acl =ERR_PTR (-EIO ); }
fs/ceph/file.c +6 -3
@@ -282,6 +282,7 @@ static int ceph_init_file(struct inode *inode, struct file *file, int fmode)int ceph_renew_caps (struct inode *inode,int fmode) {struct ceph_mds_client *mdsc =ceph_sb_to_mdsc (inode->i_sb); +struct ceph_client *cl = mdsc->fsc->client;struct ceph_inode_info *ci =ceph_inode (inode);struct ceph_mds_request *req;int err, flags, wanted;
@@ -293,8 +294,9 @@ int ceph_renew_caps(struct inode *inode, int fmode) (!(wanted & CEPH_CAP_ANY_WR) || ci->i_auth_cap)) {int issued =__ceph_caps_issued (ci,NULL );spin_unlock (&ci->i_ceph_lock); -dout ("renew caps %p want %s issued %s updating mds_wanted\n" , - inode,ceph_cap_string (wanted),ceph_cap_string (issued)); +doutc (cl,"%p %llx.%llx want %s issued %s updating mds_wanted\n" , + inode,ceph_vinop (inode),ceph_cap_string (wanted), +ceph_cap_string (issued));ceph_check_caps (ci,0 ,NULL );return 0 ; }
@@ -325,7 +327,8 @@ int ceph_renew_caps(struct inode *inode, int fmode) err =ceph_mdsc_do_request (mdsc,NULL , req);ceph_mdsc_put_request (req); out: -dout ("renew caps %p open result=%d\n" , inode, err); +doutc (cl,"%p %llx.%llx open result=%d\n" , inode,ceph_vinop (inode), + err);return err <0 ? err :0 ; }
fs/ceph/metric.c +3 -2
@@ -25,6 +25,7 @@ static bool ceph_mdsc_send_metrics(struct ceph_mds_client *mdsc,struct ceph_client_metric *m = &mdsc->metric;u64 nr_caps =atomic64_read (&m->total_caps);u32 header_len =sizeof (struct ceph_metric_header ); +struct ceph_client *cl = mdsc->fsc->client;struct ceph_msg *msg;struct timespec64 ts;s64 sum;
@@ -38,8 +39,8 @@ static bool ceph_mdsc_send_metrics(struct ceph_mds_client *mdsc, msg =ceph_msg_new (CEPH_MSG_CLIENT_METRICS , len,GFP_NOFS , true);if (!msg) { -pr_err ("send metrics to mds%d, failed to allocate message\n" , - s->s_mds); +pr_err_client (cl,"to mds%d, failed to allocate message\n" , + s->s_mds);return false; }
fs/ceph/super.h +6 -0
@@ -456,6 +456,12 @@ ceph_sb_to_mdsc(const struct super_block *sb)return (struct ceph_mds_client *)ceph_sb_to_fs_client (sb)->mdsc; } +static inline struct ceph_client * +ceph_inode_to_client (const struct inode *inode) +{ +return (struct ceph_client *)ceph_inode_to_fs_client (inode)->client; +} +static inline struct ceph_vino ceph_vino (const struct inode *inode) {
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 4/4 ceph: fix hanging __ceph_get_caps() with stale mds_wanted
In reply to Sasha LevinFrom: Max Kellermann <[email protected]>
[ Upstream commit 50958bb928bad3bdba9e5d1b7ff4bbadcf6951e6 ]
A reader can hang forever in __ceph_get_caps() when the client no longer holds FILE_RD, but local cap state still says that the capability is already wanted (via mds_wanted).
One way to trigger this is through MDS cap revocation. If another client performs a conflicting operation, the MDS can revoke FILE_RD from the reader; the next read then has to reacquire FILE_RD. If the cap update that should request FILE_RD never reaches the MDS after cap->mds_wanted was raised, the reader is left holding only non-file caps while local mds_wanted still includes the file read caps.
In that state, try_get_cap_refs() sees need <= mds_wanted and returns 0, so __ceph_get_caps() just waits on i_cap_wq. If the cap update that was supposed to request FILE_RD never reaches the MDS after cap->mds_wanted was` raised, no further request is sent and the waiter can sleep indefinitely until unrelated cap traffic happens to wake it up.
The ordering issue is that cap->mds_wanted is updated in __prep_cap() before the CEPH_MSG_CLIENT_CAPS message is actually queued for send. That makes one field serve two different meanings at
once: what this client wants, and what the client believes the MDS already knows it wants.
A proper fix would be to split those states and track whether a cap update is actually in flight or has been observed by the MDS. However, simply moving the cap->mds_wanted assignment later would not be sufficient: queueing the message in the messenger does not guarantee that the MDS processed that specific wanted set, and reconnect or message loss can still invalidate that assumption. Fixing that properly would require a larger rework of the cap state machine.
To allow simpler backports to stable kernels, this patch implements a simpler workaround:
- stop waiting forever in __ceph_get_caps(); after a bounded wait, fall back to the renew path
- make ceph_renew_caps() issue a synchronous OPEN request whenever the inode still does not actually hold the wanted caps, instead of only calling ceph_check_caps()
The extra issued-vs-wanted check in ceph_renew_caps() is necessary because the previous test only checked whether the inode still had any real caps at all. That is not enough after revocation: the client can still hold something like pLs and yet be missing FILE_RD completely. In that case, falling back to ceph_check_caps() is not sufficient, because it still trusts cap->mds_wanted and may resend nothing. By requiring (issued & wanted) == wanted before taking the asynchronous path, the code only uses ceph_check_caps() when the wanted caps are already actually issued. Otherwise, it sends the synchronous OPEN renew.
This preserves the existing asynchronous fast path when the wanted caps are already issued, avoids changing cap-state semantics, and fixes the hang by guaranteeing that a stalled waiter eventually retries through a path that does not rely on the stale mds_wanted state.
[ idryomov: move CEPH_GET_CAPS_WAIT_TIMEOUT from libceph.h to
mds_client.h, formatting ]
--- fs/ceph/caps.c | 17 +++++++++++++++-- fs/ceph/file.c | 9 +++++---- fs/ceph/mds_client.h | 2 ++ 3 files changed, 22 insertions(+), 6 deletions(-)
fs/ceph/caps.c +15 -2
@@ -2910,7 +2910,19 @@ int ceph_get_caps(struct file *filp, int need, int want, loff_t endoff, int *got ret = -ERESTARTSYS ;break ; } -wait_woken (&wait,TASK_INTERRUPTIBLE ,MAX_SCHEDULE_TIMEOUT ); + +/* +* If a cap update is lost after +* mds_wanted was raised, waiting +* forever will never make progress. +* Retry the renew path periodically +* so we can resend synchronously. +*/ +if (!wait_woken (&wait,TASK_INTERRUPTIBLE , +CEPH_GET_CAPS_WAIT_TIMEOUT )) { + ret = -ESTALE ; +break ; + } }remove_wait_queue (&ci->i_cap_wq, &wait);
@@ -2942,7 +2954,8 @@ int ceph_get_caps(struct file *filp, int need, int want, loff_t endoff, int *gotcontinue ; }if (ret == -ESTALE ) { -/* session was killed, try renew caps */ +/* session was killed or a waited cap +* request needs a retry */ ret =ceph_renew_caps (inode, flags);if (ret ==0 )continue ;
fs/ceph/file.c +5 -4
@@ -277,7 +277,7 @@ static int ceph_init_file(struct inode *inode, struct file *file, int fmode) }/* -* try renew caps after session gets killed. +* Retry cap acquisition after a stale session or a lost cap update. */ int ceph_renew_caps (struct inode *inode,int fmode) {
@@ -285,14 +285,15 @@ int ceph_renew_caps(struct inode *inode, int fmode)struct ceph_client *cl = mdsc->fsc->client;struct ceph_inode_info *ci =ceph_inode (inode);struct ceph_mds_request *req; -int err, flags, wanted; +int err, flags, wanted, issued;spin_lock (&ci->i_ceph_lock);__ceph_touch_fmode (ci, mdsc, fmode); wanted =__ceph_caps_file_wanted (ci); + issued =__ceph_caps_issued (ci,NULL );if (__ceph_is_any_real_caps (ci) && - (!(wanted &CEPH_CAP_ANY_WR ) || ci->i_auth_cap)) { -int issued =__ceph_caps_issued (ci,NULL ); + (!(wanted &CEPH_CAP_ANY_WR ) || ci->i_auth_cap) && + (issued & wanted) == wanted) {spin_unlock (&ci->i_ceph_lock); doutc(cl, "%p %llx.%llx want %s issued %s updating mds_wanted\n", inode, ceph_vinop(inode), ceph_cap_string(wanted),
fs/ceph/mds_client.h +2 -0
@@ -61,6 +61,8 @@ enum ceph_feature_type {struct ceph_fs_client ;struct ceph_cap ; +#define CEPH_GET_CAPS_WAIT_TIMEOUT (5 * HZ) +/* * parsed info about a single inode. pointers are into the encoded * on-wire structures within the mds reply message payload.
Signature · 1 line
2.53.0