From: Greg Kroah-Hartman Date: Fri, 7 Aug 2026 13:49:48 +0000 (+0200) Subject: 6.6-stable patches X-Git-Tag: v6.6.151~11 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9cd88d790248c29bfb0953d2b3ec3e4251ff1690;p=thirdparty%2Fkernel%2Fstable-queue.git 6.6-stable patches added patches: can-isotp-fix-timer-drain-order-wakeup-handling-and-tx_gen-ordering.patch can-use-skb-hash-instead-of-private-variable-in-headroom.patch ceph-fix-refcount-leak-in-ceph_readdir.patch ceph-print-cluster-fsid-and-client-global_id-in-all-debug-logs.patch drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch drm-fb-helper-allocate-and-release-fb_info-in-single-place.patch drm-i915-vrr-check-has_vrr-first-in-intel_vrr_is_capable.patch drm-i915-vrr-require-valid-min-max-vfreq-for-vrr.patch drm-renesas-move-rz-g2l-mipi-dsi-driver-to-rz-du.patch drm-renesas-rzg2l_mipi_dsi-increase-reset-deassertion-delay.patch drm-tegra-fbdev-remove-offset-into-framebuffer-memory.patch libceph-add-doutc-and-_client-debug-macros-support.patch media-i2c-imx219-access-height-from-active-format-in-imx219_set_ctrl.patch media-i2c-imx219-calculate-crop-rectangle-dynamically.patch media-i2c-imx219-don-t-store-the-current-mode-in-the-imx219-structure.patch media-i2c-imx219-drop-imx219_vts_-macros.patch media-i2c-imx219-group-functions-by-purpose.patch media-i2c-imx219-rename-vts-to-frm_length.patch media-imx219-fix-maximum-frame-length-in-lines.patch media-v4l-async-set-owner-for-async-sub-devices.patch media-v4l2-fwnode-fix-subdev-owner-overwritten-in-v4l2_async_register_subdev_sensor.patch mptcp-add-mptcp_userspace_pm_lookup_addr-helper.patch mptcp-pm-avoid-code-duplication-to-lookup-endp.patch mptcp-pm-use-addr-entry-for-get_local_id.patch mptcp-pm-userspace-fix-use-after-free-in-get_local_id.patch netfilter-nf_tables-clone-set-on-flush-only.patch rxrpc-fix-irq-disabled-in-local_bh_enable.patch sctp-avoid-auth_enable-sysctl-uaf-during-netns-teardown.patch sctp-close-udp-tunnel-sockets-during-netns-teardown.patch sysctl-treewide-constify-ctl_table_header-ctl_table_arg.patch usb-gadget-f_tcm-synchronize-delayed-set_alt-with-teardown.patch usb-musb-omap2430-clean-up-probe-error-handling.patch usb-musb-omap2430-do-not-put-borrowed-of_node-in-probe.patch usb-typec-ucsi-fix-race-condition-and-ordering-in-port-unregistration.patch usb-typec-ucsi-only-enable-supported-notifications.patch usb-typec-ucsi-split-connector-lock-classes.patch wifi-ath6kl-fix-use-after-free-in-aggr_reset_state.patch wifi-brcmfmac-drain-bus_reset-work-on-device-removal.patch wifi-brcmfmac-fix-43752-sdio-fwvid-incorrectly-labelled-as-cypress-cyw.patch wifi-brcmfmac-set-f2-blocksize-to-256-for-bcm43752.patch --- diff --git a/queue-6.6/can-isotp-fix-timer-drain-order-wakeup-handling-and-tx_gen-ordering.patch b/queue-6.6/can-isotp-fix-timer-drain-order-wakeup-handling-and-tx_gen-ordering.patch new file mode 100644 index 0000000000..a56198a95b --- /dev/null +++ b/queue-6.6/can-isotp-fix-timer-drain-order-wakeup-handling-and-tx_gen-ordering.patch @@ -0,0 +1,746 @@ +From stable+bounces-297168-greg=kroah.com@vger.kernel.org Fri Aug 7 09:48:49 2026 +From: Oliver Hartkopp +Date: Fri, 7 Aug 2026 09:47:57 +0200 +Subject: can: isotp: fix timer drain order, wakeup handling and tx_gen ordering +To: stable@vger.kernel.org +Cc: Oliver Hartkopp , Marc Kleine-Budde +Message-ID: <20260807074757.104211-2-socketcan@hartkopp.net> + +From: Oliver Hartkopp + +commit 050f010f920da17c1044a4f174766ad553e770b6 upstream. + +This patch is a follow-up to commit cf070fe33bfb ("can: isotp: serialize +TX state transitions under so->rx_lock") which addresses following +sashiko-bot findings: + +- isotp_sendmsg(): drain so->txfrtimer first so a stale callback can't + re-arm echotimer after the claim + +- isotp_release(): wake so->wait after forcing ISOTP_SHUTDOWN so a + sleeping sendmsg() claim isn't stranded + +- isotp_sendmsg(): have both wait_event_interruptible() calls in + isotp_sendmsg() also wake on ISOTP_SHUTDOWN and do not return claim to + IDLE to avoid corrupting a concurrent isotp_release() process. + +- isotp_sendmsg(): handle potential claim of a new transfer when + the wait_event_interruptible() call returns in CAN_ISOTP_WAIT_TX_DONE + mode. Don't touch timers and states of the new transfer if a new thread + incremented so->tx_gen before getting the lock at err_event_drop. + +- isotp_sendmsg(): handle a stuck can_send() and omit timer and state + changes if a new transfer was claimed. wait_tx_done() returns the error + recorded in so->tx_result[], tagged with the caller's own generation. + +- isotp_tx_timeout(): on a claimed timeout, record the ECOMM error for + the timed-out transfer's own generation in so->tx_result[]; sk->sk_err + is raised unconditionally, same as every other error path here. + +- isotp_tx_gen_done()/isotp_tx_timeout(): always read tx.state (acquire) + before tx_gen - the reverse order let a weakly ordered CPU pair a fresh + tx.state with a stale tx_gen/tx_result slot. + +- isotp_sendmsg(): wait_tx_done: drain sk_err via sock_error() once we + have read the result from so->tx_result[], so an already-reported error + doesn't stay latched for a later poll()/SO_ERROR. + +Also align the remaining lock-free so->tx.state/rx.state/cfecho accesses +and use skb->hash as unique loopback echo frame indicator. + +Fixes: cf070fe33bfb ("can: isotp: serialize TX state transitions under so->rx_lock") +Signed-off-by: Oliver Hartkopp +Link: https://patch.msgid.link/20260724181525.43556-1-socketcan@hartkopp.net +Cc: stable@kernel.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Oliver Hartkopp +Signed-off-by: Greg Kroah-Hartman +--- + net/can/isotp.c | 317 ++++++++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 230 insertions(+), 87 deletions(-) + +--- a/net/can/isotp.c ++++ b/net/can/isotp.c +@@ -125,6 +125,15 @@ MODULE_PARM_DESC(max_pdu_size, "maximum + #define ISOTP_FC_TIMEOUT 1 /* 1 sec */ + #define ISOTP_ECHO_TIMEOUT 2 /* 2 secs */ + ++/* so->tx_result[so->tx_gen % ISOTP_TX_RESULT_SLOTS] holds the packed value ++ * (err << ISOTP_TX_RESULT_GEN_BITS | gen) for each tx generation slot, so it ++ * can be handled with a single READ_ONCE()/WRITE_ONCE() access. ++ */ ++#define ISOTP_TX_RESULT_SLOTS 4 ++#define ISOTP_TX_RESULT_GEN_BITS 24 ++#define ISOTP_TX_RESULT_GEN_MASK ((1U << ISOTP_TX_RESULT_GEN_BITS) - 1) ++#define ISOTP_TX_RESULT_ERR_MASK 0xFF ++ + enum { + ISOTP_IDLE = 0, + ISOTP_WAIT_FIRST_FC, +@@ -163,7 +172,8 @@ struct isotp_sock { + u32 force_tx_stmin; + u32 force_rx_stmin; + u32 cfecho; /* consecutive frame echo tag */ +- u32 tx_gen; /* generation, bumped per new tx transfer */ ++ u32 tx_gen; /* transfer generation, increased per new tx transfer */ ++ u32 tx_result[ISOTP_TX_RESULT_SLOTS]; /* per-generation result slots */ + struct tpcon rx, tx; + struct list_head notifier; + wait_queue_head_t wait; +@@ -174,6 +184,65 @@ static LIST_HEAD(isotp_notifier_list); + static DEFINE_SPINLOCK(isotp_notifier_lock); + static struct isotp_sock *isotp_busy_notifier; + ++/* increase (24 bit) tx generation value */ ++static u32 isotp_inc_tx_gen(u32 gen) ++{ ++ return (gen + 1) & ISOTP_TX_RESULT_GEN_MASK; ++} ++ ++/* store 8 bit error and 24 bit tx generation values in packed u32 element */ ++static u32 isotp_pack_tx_result(u32 gen, int err) ++{ ++ return gen | ((u32)err << ISOTP_TX_RESULT_GEN_BITS); ++} ++ ++/* get the 24 bit tx generation value from the tx result */ ++static u32 isotp_get_tx_gen(u32 gen_err) ++{ ++ return gen_err & ISOTP_TX_RESULT_GEN_MASK; ++} ++ ++/* get the 8 bit error value from the tx result */ ++static u32 isotp_get_tx_err(u32 gen_err) ++{ ++ return (gen_err >> ISOTP_TX_RESULT_GEN_BITS) & ISOTP_TX_RESULT_ERR_MASK; ++} ++ ++/* store transfer result in per-generation%4 so->tx_result[] slot */ ++static void isotp_set_tx_result(struct isotp_sock *so, u32 gen, int err) ++{ ++ WRITE_ONCE(so->tx_result[gen % ISOTP_TX_RESULT_SLOTS], ++ isotp_pack_tx_result(gen, err)); ++} ++ ++/* fetch the result recorded for 'gen', as a (negative) errno (0 for success) */ ++static int isotp_get_tx_result(struct isotp_sock *so, u32 gen) ++{ ++ u32 result = READ_ONCE(so->tx_result[gen % ISOTP_TX_RESULT_SLOTS]); ++ ++ if (isotp_get_tx_gen(result) != gen) { ++ pr_notice_once("can-isotp: tx_result[] slot reused before read\n"); ++ ++ /* report failure rather than risk a false success */ ++ return -ECOMM; ++ } ++ ++ return -(isotp_get_tx_err(result)); ++} ++ ++/* true if done, shut down or superseded ('gen' is no longer the active ++ * transfer). Reads tx.state first (acquire) so tx_gen/tx_result reads ++ * below see at least what that state write published (common sequence). ++ */ ++static bool isotp_tx_gen_done(struct isotp_sock *so, u32 gen) ++{ ++ /* read tx.state first for the common sequence */ ++ u32 state = smp_load_acquire(&so->tx.state); ++ ++ return state == ISOTP_IDLE || state == ISOTP_SHUTDOWN || ++ READ_ONCE(so->tx_gen) != gen; ++} ++ + static inline struct isotp_sock *isotp_sk(const struct sock *sk) + { + return (struct isotp_sock *)sk; +@@ -196,7 +265,7 @@ static enum hrtimer_restart isotp_rx_tim + rxtimer); + struct sock *sk = &so->sk; + +- if (so->rx.state == ISOTP_WAIT_DATA) { ++ if (READ_ONCE(so->rx.state) == ISOTP_WAIT_DATA) { + /* we did not get new data frames in time */ + + /* report 'connection timed out' */ +@@ -205,7 +274,7 @@ static enum hrtimer_restart isotp_rx_tim + sk_error_report(sk); + + /* reset rx state */ +- so->rx.state = ISOTP_IDLE; ++ WRITE_ONCE(so->rx.state, ISOTP_IDLE); + } + + return HRTIMER_NORESTART; +@@ -362,20 +431,19 @@ static void isotp_send_cframe(struct iso + static int isotp_rcv_fc(struct isotp_sock *so, struct canfd_frame *cf, int ae) + { + struct sock *sk = &so->sk; ++ int tx_err = EBADMSG; /* default for unknown FC status */ + +- if (so->tx.state != ISOTP_WAIT_FC && +- so->tx.state != ISOTP_WAIT_FIRST_FC) ++ if (READ_ONCE(so->tx.state) != ISOTP_WAIT_FC && ++ READ_ONCE(so->tx.state) != ISOTP_WAIT_FIRST_FC) + return 0; + + hrtimer_cancel(&so->txtimer); + + /* isotp_tx_timeout() may have given up on this job while +- * hrtimer_cancel() above waited for it to finish; so->rx_lock +- * (held by our caller isotp_rcv()) rules out a concurrent claim, +- * so a plain recheck is enough here. ++ * hrtimer_cancel() above waited for it to finish => recheck + */ +- if (so->tx.state != ISOTP_WAIT_FC && +- so->tx.state != ISOTP_WAIT_FIRST_FC) ++ if (READ_ONCE(so->tx.state) != ISOTP_WAIT_FC && ++ READ_ONCE(so->tx.state) != ISOTP_WAIT_FIRST_FC) + return 1; + + if ((cf->len < ae + FC_CONTENT_SZ) || +@@ -386,13 +454,15 @@ static int isotp_rcv_fc(struct isotp_soc + if (!sock_flag(sk, SOCK_DEAD)) + sk_error_report(sk); + +- so->tx.state = ISOTP_IDLE; ++ isotp_set_tx_result(so, so->tx_gen, EBADMSG); ++ /* set to IDLE after publishing tx_result */ ++ smp_store_release(&so->tx.state, ISOTP_IDLE); + wake_up_interruptible(&so->wait); + return 1; + } + + /* get communication parameters only from the first FC frame */ +- if (so->tx.state == ISOTP_WAIT_FIRST_FC) { ++ if (READ_ONCE(so->tx.state) == ISOTP_WAIT_FIRST_FC) { + so->txfc.bs = cf->data[ae + 1]; + so->txfc.stmin = cf->data[ae + 2]; + +@@ -415,13 +485,13 @@ static int isotp_rcv_fc(struct isotp_soc + so->tx_gap = ktime_add_ns(so->tx_gap, + (so->txfc.stmin - 0xF0) + * 100000); +- so->tx.state = ISOTP_WAIT_FC; ++ WRITE_ONCE(so->tx.state, ISOTP_WAIT_FC); + } + + switch (cf->data[ae] & 0x0F) { + case ISOTP_FC_CTS: + so->tx.bs = 0; +- so->tx.state = ISOTP_SENDING; ++ WRITE_ONCE(so->tx.state, ISOTP_SENDING); + /* send CF frame and enable echo timeout handling */ + hrtimer_start(&so->echotimer, ktime_set(ISOTP_ECHO_TIMEOUT, 0), + HRTIMER_MODE_REL_SOFT); +@@ -436,14 +506,19 @@ static int isotp_rcv_fc(struct isotp_soc + + case ISOTP_FC_OVFLW: + /* overflow on receiver side - report 'message too long' */ +- sk->sk_err = EMSGSIZE; +- if (!sock_flag(sk, SOCK_DEAD)) +- sk_error_report(sk); ++ tx_err = EMSGSIZE; + fallthrough; + + default: +- /* stop this tx job */ +- so->tx.state = ISOTP_IDLE; ++ /* reserved/unknown flow status (tx_err defaults to EBADMSG) */ ++ ++ sk->sk_err = tx_err; ++ if (!sock_flag(sk, SOCK_DEAD)) ++ sk_error_report(sk); ++ ++ isotp_set_tx_result(so, so->tx_gen, tx_err); ++ /* set to IDLE after publishing tx_result */ ++ smp_store_release(&so->tx.state, ISOTP_IDLE); + wake_up_interruptible(&so->wait); + } + return 0; +@@ -456,7 +531,7 @@ static int isotp_rcv_sf(struct sock *sk, + struct sk_buff *nskb; + + hrtimer_cancel(&so->rxtimer); +- so->rx.state = ISOTP_IDLE; ++ WRITE_ONCE(so->rx.state, ISOTP_IDLE); + + if (!len || len > cf->len - pcilen) + return 1; +@@ -490,7 +565,7 @@ static int isotp_rcv_ff(struct sock *sk, + int ff_pci_sz; + + hrtimer_cancel(&so->rxtimer); +- so->rx.state = ISOTP_IDLE; ++ WRITE_ONCE(so->rx.state, ISOTP_IDLE); + + /* get the used sender LL_DL from the (first) CAN frame data length */ + so->rx.ll_dl = padlen(cf->len); +@@ -544,7 +619,7 @@ static int isotp_rcv_ff(struct sock *sk, + + /* initial setup for this pdu reception */ + so->rx.sn = 1; +- so->rx.state = ISOTP_WAIT_DATA; ++ WRITE_ONCE(so->rx.state, ISOTP_WAIT_DATA); + + /* no creation of flow control frames */ + if (so->opt.flags & CAN_ISOTP_LISTEN_MODE) +@@ -562,7 +637,7 @@ static int isotp_rcv_cf(struct sock *sk, + struct sk_buff *nskb; + int i; + +- if (so->rx.state != ISOTP_WAIT_DATA) ++ if (READ_ONCE(so->rx.state) != ISOTP_WAIT_DATA) + return 0; + + /* drop if timestamp gap is less than force_rx_stmin nano secs */ +@@ -577,11 +652,9 @@ static int isotp_rcv_cf(struct sock *sk, + hrtimer_cancel(&so->rxtimer); + + /* isotp_rx_timer_handler() may have raced us for so->rx.state +- * while hrtimer_cancel() above waited for it to finish, already +- * reporting ETIMEDOUT and resetting the reception; don't process +- * this CF into a reassembly that has already been given up on. ++ * while hrtimer_cancel() above waited for it to finish => recheck + */ +- if (so->rx.state != ISOTP_WAIT_DATA) ++ if (READ_ONCE(so->rx.state) != ISOTP_WAIT_DATA) + return 1; + + /* CFs are never longer than the FF */ +@@ -602,7 +675,7 @@ static int isotp_rcv_cf(struct sock *sk, + sk_error_report(sk); + + /* reset rx state */ +- so->rx.state = ISOTP_IDLE; ++ WRITE_ONCE(so->rx.state, ISOTP_IDLE); + return 1; + } + so->rx.sn++; +@@ -616,7 +689,7 @@ static int isotp_rcv_cf(struct sock *sk, + + if (so->rx.idx >= so->rx.len) { + /* we are done */ +- so->rx.state = ISOTP_IDLE; ++ WRITE_ONCE(so->rx.state, ISOTP_IDLE); + + if ((so->opt.flags & ISOTP_CHECK_PADDING) && + check_pad(so, cf, i + 1, so->opt.rxpad_content)) { +@@ -687,8 +760,10 @@ static void isotp_rcv(struct sk_buff *sk + + if (so->opt.flags & CAN_ISOTP_HALF_DUPLEX) { + /* check rx/tx path half duplex expectations */ +- if ((so->tx.state != ISOTP_IDLE && n_pci_type != N_PCI_FC) || +- (so->rx.state != ISOTP_IDLE && n_pci_type == N_PCI_FC)) ++ if ((READ_ONCE(so->tx.state) != ISOTP_IDLE && ++ n_pci_type != N_PCI_FC) || ++ (READ_ONCE(so->rx.state) != ISOTP_IDLE && ++ n_pci_type == N_PCI_FC)) + goto out_unlock; + } + +@@ -782,6 +857,7 @@ static void isotp_send_cframe(struct iso + struct canfd_frame *cf; + int can_send_ret; + int ae = (so->opt.flags & CAN_ISOTP_EXTEND_ADDR) ? 1 : 0; ++ u32 old_cfecho; + + dev = dev_get_by_index(sock_net(sk), so->ifindex); + if (!dev) +@@ -796,6 +872,9 @@ static void isotp_send_cframe(struct iso + can_skb_reserve(skb); + can_skb_prv(skb)->ifindex = dev->ifindex; + ++ /* set uid in tx skb to identify CF echo frames */ ++ can_set_skb_uid(skb); ++ + cf = (struct canfd_frame *)skb->data; + skb_put_zero(skb, so->ll.mtu); + +@@ -812,12 +891,15 @@ static void isotp_send_cframe(struct iso + skb->dev = dev; + can_skb_set_owner(skb, sk); + +- /* cfecho should have been zero'ed by init/isotp_rcv_echo() */ +- if (so->cfecho) +- pr_notice_once("can-isotp: cfecho is %08X != 0\n", so->cfecho); ++ /* zero'ed by init/isotp_rcv_echo(); reached lock-free via ++ * isotp_txfr_timer_handler() too, so use READ_ONCE()/WRITE_ONCE() ++ */ ++ old_cfecho = READ_ONCE(so->cfecho); ++ if (old_cfecho) ++ pr_notice_once("can-isotp: cfecho is %08X != 0\n", old_cfecho); + + /* set consecutive frame echo tag */ +- so->cfecho = *(u32 *)cf->data; ++ WRITE_ONCE(so->cfecho, skb->hash); + + /* send frame with local echo enabled */ + can_send_ret = can_send(skb, 1); +@@ -869,7 +951,6 @@ static void isotp_rcv_echo(struct sk_buf + { + struct sock *sk = (struct sock *)data; + struct isotp_sock *so = isotp_sk(sk); +- struct canfd_frame *cf = (struct canfd_frame *)skb->data; + + /* only handle my own local echo CF/SF skb's (no FF!) */ + if (skb->sk != sk) +@@ -881,32 +962,35 @@ static void isotp_rcv_echo(struct sk_buf + spin_lock(&so->rx_lock); + + /* so->cfecho may since belong to a new transfer; recheck under lock */ +- if (so->cfecho != *(u32 *)cf->data) ++ if (READ_ONCE(so->cfecho) != skb->hash) + goto out_unlock; + + /* cancel local echo timeout */ + hrtimer_cancel(&so->echotimer); + + /* local echo skb with consecutive frame has been consumed */ +- so->cfecho = 0; ++ WRITE_ONCE(so->cfecho, 0); + + /* claiming a transfer also takes so->rx_lock, so a plain recheck + * is enough: so->tx.state can't have flipped to ISOTP_SENDING for + * a new claim while we're still in here + */ +- if (so->tx.state != ISOTP_SENDING) ++ if (READ_ONCE(so->tx.state) != ISOTP_SENDING) + goto out_unlock; + + if (so->tx.idx >= so->tx.len) { + /* we are done */ +- so->tx.state = ISOTP_IDLE; ++ ++ isotp_set_tx_result(so, so->tx_gen, 0); ++ /* set to IDLE after publishing tx_result */ ++ smp_store_release(&so->tx.state, ISOTP_IDLE); + wake_up_interruptible(&so->wait); + goto out_unlock; + } + + if (so->txfc.bs && so->tx.bs >= so->txfc.bs) { + /* stop and wait for FC with timeout */ +- so->tx.state = ISOTP_WAIT_FC; ++ WRITE_ONCE(so->tx.state, ISOTP_WAIT_FC); + hrtimer_start(&so->txtimer, ktime_set(ISOTP_FC_TIMEOUT, 0), + HRTIMER_MODE_REL_SOFT); + goto out_unlock; +@@ -928,16 +1012,20 @@ out_unlock: + spin_unlock(&so->rx_lock); + } + +-/* shared by so->txtimer's and so->echotimer's callbacks. Both timers get +- * cancelled under so->rx_lock elsewhere, so this must stay lock-free to +- * avoid deadlocking with that; uses so->tx_gen instead to avoid tainting +- * a new transfer with an error from the one that just timed out. ++/* isotp_tx_timeout: we did not get any flow control or echo frame in time ++ * ++ * Shared by so->txtimer's and so->echotimer's callbacks. Both timers get ++ * cancelled under so->rx_lock elsewhere, so this must stay lock-free. ++ * ++ * tx.state is acquired before tx_gen. Common sequence in isotp_tx_gen_done(). ++ * cmpxchg() only orders itself, not the two preceding loads. + */ + static enum hrtimer_restart isotp_tx_timeout(struct isotp_sock *so) + { + struct sock *sk = &so->sk; ++ /* read tx.state first for the common sequence */ ++ u32 old_state = smp_load_acquire(&so->tx.state); + u32 gen = READ_ONCE(so->tx_gen); +- u32 old_state = READ_ONCE(so->tx.state); + + /* don't handle timeouts in IDLE or SHUTDOWN state */ + if (old_state == ISOTP_IDLE || old_state == ISOTP_SHUTDOWN) +@@ -947,14 +1035,14 @@ static enum hrtimer_restart isotp_tx_tim + if (cmpxchg(&so->tx.state, old_state, ISOTP_IDLE) != old_state) + return HRTIMER_NORESTART; + +- /* we did not get any flow control or echo frame in time */ ++ /* detected timeout: report 'communication error on send' */ + +- if (READ_ONCE(so->tx_gen) == gen) { +- /* report 'communication error on send' */ +- sk->sk_err = ECOMM; +- if (!sock_flag(sk, SOCK_DEAD)) +- sk_error_report(sk); +- } ++ /* a stale read of this slot by a waiter still falls back to ECOMM */ ++ isotp_set_tx_result(so, gen, ECOMM); ++ ++ sk->sk_err = ECOMM; ++ if (!sock_flag(sk, SOCK_DEAD)) ++ sk_error_report(sk); + + wake_up_interruptible(&so->wait); + +@@ -989,7 +1077,7 @@ static enum hrtimer_restart isotp_txfr_t + HRTIMER_MODE_REL_SOFT); + + /* cfecho should be consumed by isotp_rcv_echo() here */ +- if (so->tx.state == ISOTP_SENDING && !so->cfecho) ++ if (READ_ONCE(so->tx.state) == ISOTP_SENDING && !READ_ONCE(so->cfecho)) + isotp_send_cframe(so); + + return HRTIMER_NORESTART; +@@ -1007,10 +1095,12 @@ static int isotp_sendmsg(struct socket * + s64 hrtimer_sec = ISOTP_ECHO_TIMEOUT; + struct hrtimer *tx_hrt = &so->echotimer; + u32 new_state = ISOTP_SENDING; ++ u32 my_gen; ++ u32 old_cfecho; + int off; + int err; + +- if (!so->bound || so->tx.state == ISOTP_SHUTDOWN) ++ if (!so->bound || READ_ONCE(so->tx.state) == ISOTP_SHUTDOWN) + return -EADDRNOTAVAIL; + + /* claim the socket under so->rx_lock: this serializes the claim +@@ -1027,29 +1117,33 @@ static int isotp_sendmsg(struct socket * + if (msg->msg_flags & MSG_DONTWAIT) + return -EAGAIN; + +- if (so->tx.state == ISOTP_SHUTDOWN) ++ if (READ_ONCE(so->tx.state) == ISOTP_SHUTDOWN) + return -EADDRNOTAVAIL; + + /* wait for complete transmission of current pdu */ + err = wait_event_interruptible(so->wait, +- so->tx.state == ISOTP_IDLE); ++ READ_ONCE(so->tx.state) == ISOTP_IDLE || ++ READ_ONCE(so->tx.state) == ISOTP_SHUTDOWN); + if (err) + return err; + } + +- /* new transfer: bump so->tx_gen and drain the old one's timers, +- * still under the so->rx_lock we just claimed the socket with +- */ +- WRITE_ONCE(so->tx.state, ISOTP_SENDING); +- WRITE_ONCE(so->tx_gen, READ_ONCE(so->tx_gen) + 1); ++ /* txfrtimer's callback re-arms echotimer lock-free: drain it first */ ++ hrtimer_cancel(&so->txfrtimer); + hrtimer_cancel(&so->txtimer); + hrtimer_cancel(&so->echotimer); +- hrtimer_cancel(&so->txfrtimer); +- so->cfecho = 0; ++ ++ /* new transfer: increment so->tx_gen and set tx.state after barrier */ ++ my_gen = isotp_inc_tx_gen(READ_ONCE(so->tx_gen)); ++ isotp_set_tx_result(so, my_gen, ECOMM); /* prevent stale slot matching */ ++ WRITE_ONCE(so->tx_gen, my_gen); ++ smp_wmb(); /* see smp_load_acquire() in isotp_tx_[timeout|gen_done] */ ++ WRITE_ONCE(so->tx.state, ISOTP_SENDING); ++ WRITE_ONCE(so->cfecho, 0); + spin_unlock_bh(&so->rx_lock); + + /* so->bound is only checked once above - a wakeup may have +- * unbound/rebound the socket meanwhile, so re-validate it ++ * unbound/rebound the socket meanwhile => recheck + */ + if (!so->bound) { + err = -EADDRNOTAVAIL; +@@ -1101,6 +1195,9 @@ static int isotp_sendmsg(struct socket * + can_skb_reserve(skb); + can_skb_prv(skb)->ifindex = dev->ifindex; + ++ /* set uid in tx skb to identify CF echo frames */ ++ can_set_skb_uid(skb); ++ + so->tx.len = size; + so->tx.idx = 0; + +@@ -1108,8 +1205,9 @@ static int isotp_sendmsg(struct socket * + skb_put_zero(skb, so->ll.mtu); + + /* cfecho should have been zero'ed by init / former isotp_rcv_echo() */ +- if (so->cfecho) +- pr_notice_once("can-isotp: uninit cfecho %08X\n", so->cfecho); ++ old_cfecho = READ_ONCE(so->cfecho); ++ if (old_cfecho) ++ pr_notice_once("can-isotp: uninit cfecho %08X\n", old_cfecho); + + /* check for single frame transmission depending on TX_DL */ + if (size <= so->tx.ll_dl - SF_PCI_SZ4 - ae - off) { +@@ -1137,7 +1235,7 @@ static int isotp_sendmsg(struct socket * + cf->data[ae] |= size; + + /* set CF echo tag for isotp_rcv_echo() (SF-mode) */ +- so->cfecho = *(u32 *)cf->data; ++ WRITE_ONCE(so->cfecho, skb->hash); + } else { + /* send first frame */ + +@@ -1154,7 +1252,7 @@ static int isotp_sendmsg(struct socket * + so->txfc.bs = 0; + + /* set CF echo tag for isotp_rcv_echo() (CF-mode) */ +- so->cfecho = *(u32 *)cf->data; ++ WRITE_ONCE(so->cfecho, skb->hash); + } else { + /* standard flow control check */ + new_state = ISOTP_WAIT_FIRST_FC; +@@ -1164,12 +1262,12 @@ static int isotp_sendmsg(struct socket * + tx_hrt = &so->txtimer; + + /* no CF echo tag for isotp_rcv_echo() (FF-mode) */ +- so->cfecho = 0; ++ WRITE_ONCE(so->cfecho, 0); + } + } + + spin_lock_bh(&so->rx_lock); +- if (so->tx.state == ISOTP_SHUTDOWN) { ++ if (READ_ONCE(so->tx.state) == ISOTP_SHUTDOWN) { + /* isotp_release() has since taken over and already drained + * our timers - don't send into a socket that's going away + */ +@@ -1180,7 +1278,7 @@ static int isotp_sendmsg(struct socket * + return -EADDRNOTAVAIL; + } + /* WAIT_FIRST_FC for standard FF, else stays ISOTP_SENDING */ +- so->tx.state = new_state; ++ WRITE_ONCE(so->tx.state, new_state); + hrtimer_start(tx_hrt, ktime_set(hrtimer_sec, 0), + HRTIMER_MODE_REL_SOFT); + spin_unlock_bh(&so->rx_lock); +@@ -1197,20 +1295,49 @@ static int isotp_sendmsg(struct socket * + __func__, ERR_PTR(err)); + + spin_lock_bh(&so->rx_lock); ++ ++ /* new transfer already claimed by a concurrent completion, ++ * timeout or sendmsg() while we were stuck in can_send()? ++ */ ++ if (READ_ONCE(so->tx_gen) != my_gen) { ++ /* don't touch timers and state of the new transfer */ ++ spin_unlock_bh(&so->rx_lock); ++ return err; ++ } ++ + /* no transmission -> no timeout monitoring */ + hrtimer_cancel(tx_hrt); + goto err_out_drop_locked; + } + + if (wait_tx_done) { +- /* wait for complete transmission of current pdu */ +- err = wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE); ++ /* wake up for: ++ * - concurrent sendmsg() claiming a new transfer ++ * - complete transmission of current PDU ++ * - shutdown state change in isotp_release() ++ * isotp_tx_gen_done() uses common tx.state/tx_gen read sequence ++ */ ++ err = wait_event_interruptible(so->wait, ++ isotp_tx_gen_done(so, my_gen)); + if (err) + goto err_event_drop; + +- err = sock_error(sk); +- if (err) +- return err; ++ /* still our claim, but isotp_release() force-shut it down */ ++ if (smp_load_acquire(&so->tx.state) == ISOTP_SHUTDOWN && ++ READ_ONCE(so->tx_gen) == my_gen) { ++ err = -EADDRNOTAVAIL; ++ goto err_event_drop; ++ } ++ ++ /* own completion, or tx_gen moved on - either way this is ++ * what isotp_get_tx_result() recorded for my_gen ++ */ ++ err = isotp_get_tx_result(so, my_gen); ++ ++ /* drain to avoid stale error for a later poll()/SO_ERROR */ ++ sock_error(sk); ++ ++ return err ? err : size; + } + + return size; +@@ -1220,15 +1347,26 @@ err_out_drop: + spin_lock_bh(&so->rx_lock); + goto err_out_drop_locked; + err_event_drop: +- /* interrupted waiting on our own transfer - drain its timers */ ++ /* interrupted or shut down while waiting on our own transfer */ + spin_lock_bh(&so->rx_lock); ++ ++ /* new transfer already started by concurrent sendmsg()? */ ++ if (READ_ONCE(so->tx_gen) != my_gen) { ++ /* don't touch timers and states of the new transfer */ ++ spin_unlock_bh(&so->rx_lock); ++ return err; ++ } ++ + hrtimer_cancel(&so->txfrtimer); + hrtimer_cancel(&so->txtimer); + hrtimer_cancel(&so->echotimer); + err_out_drop_locked: + /* release the claim; so->rx_lock still held from above */ +- so->cfecho = 0; +- so->tx.state = ISOTP_IDLE; ++ WRITE_ONCE(so->cfecho, 0); ++ ++ /* only claim to IDLE if isotp_release() has not taken over */ ++ if (READ_ONCE(so->tx.state) != ISOTP_SHUTDOWN) ++ WRITE_ONCE(so->tx.state, ISOTP_IDLE); + spin_unlock_bh(&so->rx_lock); + wake_up_interruptible(&so->wait); + +@@ -1294,8 +1432,9 @@ static int isotp_release(struct socket * + /* best-effort: wait for a running pdu to finish, but don't block on + * it forever - give up after the first signal + */ +- while (so->tx.state != ISOTP_IDLE && +- wait_event_interruptible(so->wait, so->tx.state == ISOTP_IDLE) == 0) ++ while (READ_ONCE(so->tx.state) != ISOTP_IDLE && ++ wait_event_interruptible(so->wait, ++ READ_ONCE(so->tx.state) == ISOTP_IDLE) == 0) + ; + + /* claim the socket under so->rx_lock like sendmsg() does, so its +@@ -1303,9 +1442,12 @@ static int isotp_release(struct socket * + * unconditionally, even when a signal cut the wait above short + */ + spin_lock_bh(&so->rx_lock); +- so->tx.state = ISOTP_SHUTDOWN; ++ WRITE_ONCE(so->tx.state, ISOTP_SHUTDOWN); + spin_unlock_bh(&so->rx_lock); +- so->rx.state = ISOTP_IDLE; ++ WRITE_ONCE(so->rx.state, ISOTP_IDLE); ++ ++ /* forced SHUTDOWN may have skipped IDLE (gave up on a signal) */ ++ wake_up_interruptible(&so->wait); + + spin_lock(&isotp_notifier_lock); + while (isotp_busy_notifier == so) { +@@ -1420,7 +1562,8 @@ static int isotp_bind(struct socket *soc + * with so->bound in the same lock_sock() section above, so there is + * no window in which a concurrent isotp_notify() could be missed. + */ +- if (so->tx.state != ISOTP_IDLE || so->rx.state != ISOTP_IDLE) { ++ if (READ_ONCE(so->tx.state) != ISOTP_IDLE || ++ READ_ONCE(so->rx.state) != ISOTP_IDLE) { + err = -EAGAIN; + goto out; + } +@@ -1454,7 +1597,7 @@ static int isotp_bind(struct socket *soc + isotp_rcv, sk, "isotp", sk); + + /* no consecutive frame echo skb in flight */ +- so->cfecho = 0; ++ WRITE_ONCE(so->cfecho, 0); + + /* register for echo skb's */ + can_rx_register(net, dev, tx_id, SINGLE_MASK(tx_id), +@@ -1820,7 +1963,7 @@ static __poll_t isotp_poll(struct file * + poll_wait(file, &so->wait, wait); + + /* Check for false positives due to TX state */ +- if ((mask & EPOLLWRNORM) && (so->tx.state != ISOTP_IDLE)) ++ if ((mask & EPOLLWRNORM) && (READ_ONCE(so->tx.state) != ISOTP_IDLE)) + mask &= ~(EPOLLOUT | EPOLLWRNORM); + + return mask; diff --git a/queue-6.6/can-use-skb-hash-instead-of-private-variable-in-headroom.patch b/queue-6.6/can-use-skb-hash-instead-of-private-variable-in-headroom.patch new file mode 100644 index 0000000000..02ce5e5fc7 --- /dev/null +++ b/queue-6.6/can-use-skb-hash-instead-of-private-variable-in-headroom.patch @@ -0,0 +1,221 @@ +From stable+bounces-297171-greg=kroah.com@vger.kernel.org Fri Aug 7 09:51:47 2026 +From: Oliver Hartkopp +Date: Fri, 7 Aug 2026 09:47:56 +0200 +Subject: can: use skb hash instead of private variable in headroom +To: stable@vger.kernel.org +Cc: Oliver Hartkopp , Marc Kleine-Budde +Message-ID: <20260807074757.104211-1-socketcan@hartkopp.net> + +From: Oliver Hartkopp + +commit d4fb6514ff8ed6912a71294e6b66a5d59ee88007 upstream. + +The can_skb_priv::skbcnt variable is used to identify CAN skbs in the RX +path analogue to the skb->hash. + +As the skb hash is not filled in CAN skbs move the private skbcnt value to +skb->hash and set skb->sw_hash accordingly. The skb->hash is a value used +for RPS to identify skbs. Use it as intended. + +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Oliver Hartkopp +Link: https://patch.msgid.link/20260201-can_skb_ext-v8-1-3635d790fe8b@hartkopp.net +Signed-off-by: Paolo Abeni +Signed-off-by: Oliver Hartkopp +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/dev/skb.c | 2 -- + include/linux/can/core.h | 1 + + include/linux/can/skb.h | 2 -- + net/can/af_can.c | 14 +++++++++++--- + net/can/bcm.c | 2 -- + net/can/isotp.c | 3 --- + net/can/j1939/socket.c | 1 - + net/can/j1939/transport.c | 2 -- + net/can/raw.c | 7 +++---- + 9 files changed, 15 insertions(+), 19 deletions(-) + +--- a/drivers/net/can/dev/skb.c ++++ b/drivers/net/can/dev/skb.c +@@ -202,7 +202,6 @@ static void init_can_skb_reserve(struct + skb_reset_transport_header(skb); + + can_skb_reserve(skb); +- can_skb_prv(skb)->skbcnt = 0; + } + + struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf) +@@ -312,7 +311,6 @@ static bool can_skb_headroom_valid(struc + if (skb->ip_summed == CHECKSUM_NONE) { + /* init headroom */ + can_skb_prv(skb)->ifindex = dev->ifindex; +- can_skb_prv(skb)->skbcnt = 0; + + skb->ip_summed = CHECKSUM_UNNECESSARY; + +--- a/include/linux/can/core.h ++++ b/include/linux/can/core.h +@@ -58,6 +58,7 @@ extern void can_rx_unregister(struct net + void *data); + + extern int can_send(struct sk_buff *skb, int loop); ++void can_set_skb_uid(struct sk_buff *skb); + void can_sock_destruct(struct sock *sk); + + #endif /* !_CAN_CORE_H */ +--- a/include/linux/can/skb.h ++++ b/include/linux/can/skb.h +@@ -49,13 +49,11 @@ bool can_dropped_invalid_skb(struct net_ + /** + * struct can_skb_priv - private additional data inside CAN sk_buffs + * @ifindex: ifindex of the first interface the CAN frame appeared on +- * @skbcnt: atomic counter to have an unique id together with skb pointer + * @frame_len: length of CAN frame in data link layer + * @cf: align to the following CAN frame at skb->data + */ + struct can_skb_priv { + int ifindex; +- int skbcnt; + unsigned int frame_len; + struct can_frame cf[]; + }; +--- a/net/can/af_can.c ++++ b/net/can/af_can.c +@@ -639,6 +639,16 @@ static int can_rcv_filter(struct can_dev + return matches; + } + ++void can_set_skb_uid(struct sk_buff *skb) ++{ ++ /* create non-zero unique skb identifier together with *skb */ ++ while (!(skb->hash)) ++ skb->hash = atomic_inc_return(&skbcounter); ++ ++ skb->sw_hash = 1; ++} ++EXPORT_SYMBOL(can_set_skb_uid); ++ + static void can_receive(struct sk_buff *skb, struct net_device *dev) + { + struct can_dev_rcv_lists *dev_rcv_lists; +@@ -650,9 +660,7 @@ static void can_receive(struct sk_buff * + atomic_long_inc(&pkg_stats->rx_frames); + atomic_long_inc(&pkg_stats->rx_frames_delta); + +- /* create non-zero unique skb identifier together with *skb */ +- while (!(can_skb_prv(skb)->skbcnt)) +- can_skb_prv(skb)->skbcnt = atomic_inc_return(&skbcounter); ++ can_set_skb_uid(skb); + + rcu_read_lock(); + +--- a/net/can/bcm.c ++++ b/net/can/bcm.c +@@ -338,7 +338,6 @@ static void bcm_can_tx(struct bcm_op *op + + can_skb_reserve(skb); + can_skb_prv(skb)->ifindex = dev->ifindex; +- can_skb_prv(skb)->skbcnt = 0; + + skb_put_data(skb, cf, op->cfsiz); + +@@ -1582,7 +1581,6 @@ static int bcm_tx_send(struct msghdr *ms + } + + can_skb_prv(skb)->ifindex = dev->ifindex; +- can_skb_prv(skb)->skbcnt = 0; + skb->dev = dev; + can_skb_set_owner(skb, sk); + err = can_send(skb, 1); /* send with loopback */ +--- a/net/can/isotp.c ++++ b/net/can/isotp.c +@@ -231,7 +231,6 @@ static int isotp_send_fc(struct sock *sk + + can_skb_reserve(nskb); + can_skb_prv(nskb)->ifindex = dev->ifindex; +- can_skb_prv(nskb)->skbcnt = 0; + + nskb->dev = dev; + can_skb_set_owner(nskb, sk); +@@ -796,7 +795,6 @@ static void isotp_send_cframe(struct iso + + can_skb_reserve(skb); + can_skb_prv(skb)->ifindex = dev->ifindex; +- can_skb_prv(skb)->skbcnt = 0; + + cf = (struct canfd_frame *)skb->data; + skb_put_zero(skb, so->ll.mtu); +@@ -1102,7 +1100,6 @@ static int isotp_sendmsg(struct socket * + + can_skb_reserve(skb); + can_skb_prv(skb)->ifindex = dev->ifindex; +- can_skb_prv(skb)->skbcnt = 0; + + so->tx.len = size; + so->tx.idx = 0; +--- a/net/can/j1939/socket.c ++++ b/net/can/j1939/socket.c +@@ -889,7 +889,6 @@ static struct sk_buff *j1939_sk_alloc_sk + + can_skb_reserve(skb); + can_skb_prv(skb)->ifindex = ndev->ifindex; +- can_skb_prv(skb)->skbcnt = 0; + skb_reserve(skb, offsetof(struct can_frame, data)); + + ret = memcpy_from_msg(skb_put(skb, size), msg, size); +--- a/net/can/j1939/transport.c ++++ b/net/can/j1939/transport.c +@@ -613,7 +613,6 @@ sk_buff *j1939_tp_tx_dat_new(struct j193 + skb->dev = priv->ndev; + can_skb_reserve(skb); + can_skb_prv(skb)->ifindex = priv->ndev->ifindex; +- can_skb_prv(skb)->skbcnt = 0; + /* reserve CAN header */ + skb_reserve(skb, offsetof(struct can_frame, data)); + +@@ -1553,7 +1552,6 @@ j1939_session *j1939_session_fresh_new(s + skb->dev = priv->ndev; + can_skb_reserve(skb); + can_skb_prv(skb)->ifindex = priv->ndev->ifindex; +- can_skb_prv(skb)->skbcnt = 0; + skcb = j1939_skb_to_cb(skb); + memcpy(skcb, rel_skcb, sizeof(*skcb)); + +--- a/net/can/raw.c ++++ b/net/can/raw.c +@@ -75,8 +75,8 @@ MODULE_ALIAS("can-proto-1"); + */ + + struct uniqframe { +- int skbcnt; + const struct sk_buff *skb; ++ u32 hash; + unsigned int join_rx_count; + }; + +@@ -140,7 +140,7 @@ static void raw_rcv(struct sk_buff *oskb + + /* eliminate multiple filter matches for the same skb */ + if (this_cpu_ptr(ro->uniq)->skb == oskb && +- this_cpu_ptr(ro->uniq)->skbcnt == can_skb_prv(oskb)->skbcnt) { ++ this_cpu_ptr(ro->uniq)->hash == oskb->hash) { + if (!ro->join_filters) + return; + +@@ -150,7 +150,7 @@ static void raw_rcv(struct sk_buff *oskb + return; + } else { + this_cpu_ptr(ro->uniq)->skb = oskb; +- this_cpu_ptr(ro->uniq)->skbcnt = can_skb_prv(oskb)->skbcnt; ++ this_cpu_ptr(ro->uniq)->hash = oskb->hash; + this_cpu_ptr(ro->uniq)->join_rx_count = 1; + /* drop first frame to check all enabled filters? */ + if (ro->join_filters && ro->count > 1) +@@ -871,7 +871,6 @@ static int raw_sendmsg(struct socket *so + + can_skb_reserve(skb); + can_skb_prv(skb)->ifindex = dev->ifindex; +- can_skb_prv(skb)->skbcnt = 0; + + /* fill the skb before testing for valid CAN frames */ + err = memcpy_from_msg(skb_put(skb, size), msg, size); diff --git a/queue-6.6/ceph-fix-refcount-leak-in-ceph_readdir.patch b/queue-6.6/ceph-fix-refcount-leak-in-ceph_readdir.patch new file mode 100644 index 0000000000..24de5b879b --- /dev/null +++ b/queue-6.6/ceph-fix-refcount-leak-in-ceph_readdir.patch @@ -0,0 +1,55 @@ +From stable+bounces-297280-greg=kroah.com@vger.kernel.org Fri Aug 7 13:55:34 2026 +From: Sasha Levin +Date: Fri, 7 Aug 2026 07:48:08 -0400 +Subject: ceph: fix refcount leak in ceph_readdir() +To: stable@vger.kernel.org +Cc: WenTao Liang , Viacheslav Dubeyko , Alex Markuze , Ilya Dryomov , Sasha Levin +Message-ID: <20260807114809.2056244-3-sashal@kernel.org> + +From: WenTao Liang + +[ Upstream commit c3e64079d8b9663e3998d0caac9aba915b6b93ae ] + +The ceph_readdir() function allocates a ceph_mds_request via +ceph_mdsc_create_request() and stores it in dfi->last_readdir. In +the directory entry processing loop, if the entry's offset is less +than ctx->pos or if the inode pointer is unexpectedly NULL, the +function returns -EIO without releasing the reference held by +dfi->last_readdir, causing a refcount leak. + +Fix this by adding ceph_mdsc_put_request(dfi->last_readdir) before +returning on these error paths. Also set dfi->last_readdir to NULL +for safety, matching the cleanup done at the normal exit. + +Cc: stable@vger.kernel.org +Fixes: af9ffa6df7e3 ("ceph: add support to readdir for encrypted names") +Signed-off-by: WenTao Liang +Reviewed-by: Viacheslav Dubeyko +Reviewed-by: Alex Markuze +Signed-off-by: Ilya Dryomov +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/ceph/dir.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/fs/ceph/dir.c ++++ b/fs/ceph/dir.c +@@ -546,11 +546,16 @@ more: + pr_warn_client(cl, + "%p %llx.%llx rde->offset 0x%llx ctx->pos 0x%llx\n", + inode, ceph_vinop(inode), rde->offset, ctx->pos); ++ ceph_mdsc_put_request(dfi->last_readdir); ++ dfi->last_readdir = NULL; + return -EIO; + } + +- if (WARN_ON_ONCE(!rde->inode.in)) ++ if (WARN_ON_ONCE(!rde->inode.in)) { ++ ceph_mdsc_put_request(dfi->last_readdir); ++ dfi->last_readdir = NULL; + return -EIO; ++ } + + ctx->pos = rde->offset; + doutc(cl, "%p %llx.%llx (%d/%d) -> %llx '%.*s' %p\n", inode, diff --git a/queue-6.6/ceph-print-cluster-fsid-and-client-global_id-in-all-debug-logs.patch b/queue-6.6/ceph-print-cluster-fsid-and-client-global_id-in-all-debug-logs.patch new file mode 100644 index 0000000000..12595df15c --- /dev/null +++ b/queue-6.6/ceph-print-cluster-fsid-and-client-global_id-in-all-debug-logs.patch @@ -0,0 +1,9338 @@ +From stable+bounces-297288-greg=kroah.com@vger.kernel.org Fri Aug 7 13:52:14 2026 +From: Sasha Levin +Date: Fri, 7 Aug 2026 07:48:07 -0400 +Subject: ceph: print cluster fsid and client global_id in all debug logs +To: stable@vger.kernel.org +Cc: Xiubo Li , Patrick Donnelly , Milind Changire , Ilya Dryomov , Sasha Levin +Message-ID: <20260807114809.2056244-2-sashal@kernel.org> + +From: Xiubo Li + +[ 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. + +Link: https://tracker.ceph.com/issues/61590 +Signed-off-by: Xiubo Li +Reviewed-by: Patrick Donnelly +Reviewed-by: Milind Changire +Signed-off-by: Ilya Dryomov +Stable-dep-of: c3e64079d8b9 ("ceph: fix refcount leak in ceph_readdir()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + fs/ceph/acl.c | 6 + fs/ceph/addr.c | 279 +++++++++++--------- + fs/ceph/caps.c | 708 +++++++++++++++++++++++++++++---------------------- + fs/ceph/crypto.c | 39 +- + fs/ceph/debugfs.c | 6 + fs/ceph/dir.c | 218 +++++++++------ + fs/ceph/export.c | 39 +- + fs/ceph/file.c | 245 ++++++++++------- + fs/ceph/inode.c | 485 +++++++++++++++++++--------------- + fs/ceph/ioctl.c | 13 + fs/ceph/locks.c | 57 ++-- + fs/ceph/mds_client.c | 554 ++++++++++++++++++++++----------------- + fs/ceph/mdsmap.c | 24 - + fs/ceph/metric.c | 5 + fs/ceph/quota.c | 29 +- + fs/ceph/snap.c | 174 ++++++------ + fs/ceph/super.c | 70 ++--- + fs/ceph/super.h | 6 + fs/ceph/xattr.c | 96 ++++-- + 19 files changed, 1744 insertions(+), 1309 deletions(-) + +--- a/fs/ceph/acl.c ++++ b/fs/ceph/acl.c +@@ -15,6 +15,7 @@ + #include + + #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(s + + 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 @@ retry: + } 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); + } + +--- a/fs/ceph/addr.c ++++ b/fs/ceph/addr.c +@@ -79,18 +79,18 @@ static inline struct ceph_snap_context * + */ + static bool ceph_dirty_folio(struct address_space *mapping, struct folio *folio) + { +- struct inode *inode; ++ struct inode *inode = mapping->host; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci; + struct ceph_snap_context *snapc; + + if (folio_test_dirty(folio)) { +- dout("%p dirty_folio %p idx %lu -- already dirty\n", +- mapping->host, folio, folio->index); ++ doutc(cl, "%llx.%llx %p idx %lu -- already dirty\n", ++ ceph_vinop(inode), folio, folio->index); + VM_BUG_ON_FOLIO(!folio_test_private(folio), folio); + return false; + } + +- inode = mapping->host; + ci = ceph_inode(inode); + + /* dirty the head */ +@@ -110,12 +110,12 @@ static bool ceph_dirty_folio(struct addr + if (ci->i_wrbuffer_ref == 0) + ihold(inode); + ++ci->i_wrbuffer_ref; +- dout("%p dirty_folio %p idx %lu head %d/%d -> %d/%d " +- "snapc %p seq %lld (%d snaps)\n", +- mapping->host, folio, folio->index, +- ci->i_wrbuffer_ref-1, ci->i_wrbuffer_ref_head-1, +- ci->i_wrbuffer_ref, ci->i_wrbuffer_ref_head, +- snapc, snapc->seq, snapc->num_snaps); ++ doutc(cl, "%llx.%llx %p idx %lu head %d/%d -> %d/%d " ++ "snapc %p seq %lld (%d snaps)\n", ++ ceph_vinop(inode), folio, folio->index, ++ ci->i_wrbuffer_ref-1, ci->i_wrbuffer_ref_head-1, ++ ci->i_wrbuffer_ref, ci->i_wrbuffer_ref_head, ++ snapc, snapc->seq, snapc->num_snaps); + spin_unlock(&ci->i_ceph_lock); + + /* +@@ -136,23 +136,22 @@ static bool ceph_dirty_folio(struct addr + static void ceph_invalidate_folio(struct folio *folio, size_t offset, + size_t length) + { +- struct inode *inode; +- struct ceph_inode_info *ci; ++ struct inode *inode = folio->mapping->host; ++ struct ceph_client *cl = ceph_inode_to_client(inode); ++ struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_snap_context *snapc; + +- inode = folio->mapping->host; +- ci = ceph_inode(inode); + + if (offset != 0 || length != folio_size(folio)) { +- dout("%p invalidate_folio idx %lu partial dirty page %zu~%zu\n", +- inode, folio->index, offset, length); ++ doutc(cl, "%llx.%llx idx %lu partial dirty page %zu~%zu\n", ++ ceph_vinop(inode), folio->index, offset, length); + return; + } + + WARN_ON(!folio_test_locked(folio)); + if (folio_test_private(folio)) { +- dout("%p invalidate_folio idx %lu full dirty page\n", +- inode, folio->index); ++ doutc(cl, "%llx.%llx idx %lu full dirty page\n", ++ ceph_vinop(inode), folio->index); + + snapc = folio_detach_private(folio); + ceph_put_wrbuffer_cap_refs(ci, 1, snapc); +@@ -165,10 +164,10 @@ static void ceph_invalidate_folio(struct + static bool ceph_release_folio(struct folio *folio, gfp_t gfp) + { + struct inode *inode = folio->mapping->host; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + +- dout("%llx:%llx release_folio idx %lu (%sdirty)\n", +- ceph_vinop(inode), +- folio->index, folio_test_dirty(folio) ? "" : "not "); ++ doutc(cl, "%llx.%llx idx %lu (%sdirty)\n", ceph_vinop(inode), ++ folio->index, folio_test_dirty(folio) ? "" : "not "); + + if (folio_test_private(folio)) + return false; +@@ -244,6 +243,7 @@ static void finish_netfs_read(struct cep + { + struct inode *inode = req->r_inode; + struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode); ++ struct ceph_client *cl = fsc->client; + struct ceph_osd_data *osd_data = osd_req_op_extent_osd_data(req, 0); + struct netfs_io_subrequest *subreq = req->r_priv; + struct ceph_osd_req_op *op = &req->r_ops[0]; +@@ -253,8 +253,8 @@ static void finish_netfs_read(struct cep + ceph_update_read_metrics(&fsc->mdsc->metric, req->r_start_latency, + req->r_end_latency, osd_data->length, err); + +- dout("%s: result %d subreq->len=%zu i_size=%lld\n", __func__, req->r_result, +- subreq->len, i_size_read(req->r_inode)); ++ doutc(cl, "result %d subreq->len=%zu i_size=%lld\n", req->r_result, ++ subreq->len, i_size_read(req->r_inode)); + + /* no object means success but no data */ + if (err == -ENOENT) +@@ -348,6 +348,7 @@ static void ceph_netfs_issue_read(struct + struct inode *inode = rreq->inode; + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode); ++ struct ceph_client *cl = fsc->client; + struct ceph_osd_request *req = NULL; + struct ceph_vino vino = ceph_vino(inode); + struct iov_iter iter; +@@ -384,7 +385,8 @@ static void ceph_netfs_issue_read(struct + goto out; + } + +- dout("%s: pos=%llu orig_len=%zu len=%llu\n", __func__, subreq->start, subreq->len, len); ++ doutc(cl, "%llx.%llx pos=%llu orig_len=%zu len=%llu\n", ++ ceph_vinop(inode), subreq->start, subreq->len, len); + + iov_iter_xarray(&iter, ITER_DEST, &rreq->mapping->i_pages, subreq->start, len); + +@@ -401,8 +403,8 @@ static void ceph_netfs_issue_read(struct + + err = iov_iter_get_pages_alloc2(&iter, &pages, len, &page_off); + if (err < 0) { +- dout("%s: iov_ter_get_pages_alloc returned %d\n", +- __func__, err); ++ doutc(cl, "%llx.%llx failed to allocate pages, %d\n", ++ ceph_vinop(inode), err); + goto out; + } + +@@ -430,12 +432,13 @@ out: + ceph_osdc_put_request(req); + if (err) + netfs_subreq_terminated(subreq, err, false); +- dout("%s: result %d\n", __func__, err); ++ doutc(cl, "%llx.%llx result %d\n", ceph_vinop(inode), err); + } + + static int ceph_init_request(struct netfs_io_request *rreq, struct file *file) + { + struct inode *inode = rreq->inode; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + int got = 0, want = CEPH_CAP_FILE_CACHE; + struct ceph_netfs_request_data *priv; + int ret = 0; +@@ -467,12 +470,12 @@ static int ceph_init_request(struct netf + */ + ret = ceph_try_get_caps(inode, CEPH_CAP_FILE_RD, want, true, &got); + if (ret < 0) { +- dout("start_read %p, error getting cap\n", inode); ++ doutc(cl, "%llx.%llx, error getting cap\n", ceph_vinop(inode)); + goto out; + } + + if (!(got & want)) { +- dout("start_read %p, no cache cap\n", inode); ++ doutc(cl, "%llx.%llx, no cache cap\n", ceph_vinop(inode)); + ret = -EACCES; + goto out; + } +@@ -567,13 +570,14 @@ get_oldest_context(struct inode *inode, + struct ceph_snap_context *page_snapc) + { + struct ceph_inode_info *ci = ceph_inode(inode); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_snap_context *snapc = NULL; + struct ceph_cap_snap *capsnap = NULL; + + spin_lock(&ci->i_ceph_lock); + list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) { +- dout(" cap_snap %p snapc %p has %d dirty pages\n", capsnap, +- capsnap->context, capsnap->dirty_pages); ++ doutc(cl, " capsnap %p snapc %p has %d dirty pages\n", ++ capsnap, capsnap->context, capsnap->dirty_pages); + if (!capsnap->dirty_pages) + continue; + +@@ -605,8 +609,8 @@ get_oldest_context(struct inode *inode, + } + if (!snapc && ci->i_wrbuffer_ref_head) { + snapc = ceph_get_snap_context(ci->i_head_snapc); +- dout(" head snapc %p has %d dirty pages\n", +- snapc, ci->i_wrbuffer_ref_head); ++ doutc(cl, " head snapc %p has %d dirty pages\n", snapc, ++ ci->i_wrbuffer_ref_head); + if (ctl) { + ctl->i_size = i_size_read(inode); + ctl->truncate_size = ci->i_truncate_size; +@@ -663,6 +667,7 @@ static int writepage_nounlock(struct pag + struct inode *inode = page->mapping->host; + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode); ++ struct ceph_client *cl = fsc->client; + struct ceph_snap_context *snapc, *oldest; + loff_t page_off = page_offset(page); + int err; +@@ -674,7 +679,8 @@ static int writepage_nounlock(struct pag + bool caching = ceph_is_cache_enabled(inode); + struct page *bounce_page = NULL; + +- dout("writepage %p idx %lu\n", page, page->index); ++ doutc(cl, "%llx.%llx page %p idx %lu\n", ceph_vinop(inode), page, ++ page->index); + + if (ceph_inode_is_shutdown(inode)) + return -EIO; +@@ -682,13 +688,14 @@ static int writepage_nounlock(struct pag + /* verify this is a writeable snap context */ + snapc = page_snap_context(page); + if (!snapc) { +- dout("writepage %p page %p not dirty?\n", inode, page); ++ doutc(cl, "%llx.%llx page %p not dirty?\n", ceph_vinop(inode), ++ page); + return 0; + } + oldest = get_oldest_context(inode, &ceph_wbc, snapc); + if (snapc->seq > oldest->seq) { +- dout("writepage %p page %p snapc %p not writeable - noop\n", +- inode, page, snapc); ++ doutc(cl, "%llx.%llx page %p snapc %p not writeable - noop\n", ++ ceph_vinop(inode), page, snapc); + /* we should only noop if called by kswapd */ + WARN_ON(!(current->flags & PF_MEMALLOC)); + ceph_put_snap_context(oldest); +@@ -699,8 +706,8 @@ static int writepage_nounlock(struct pag + + /* is this a partial page at end of file? */ + if (page_off >= ceph_wbc.i_size) { +- dout("folio at %lu beyond eof %llu\n", folio->index, +- ceph_wbc.i_size); ++ doutc(cl, "%llx.%llx folio at %lu beyond eof %llu\n", ++ ceph_vinop(inode), folio->index, ceph_wbc.i_size); + folio_invalidate(folio, 0, folio_size(folio)); + return 0; + } +@@ -709,8 +716,9 @@ static int writepage_nounlock(struct pag + len = ceph_wbc.i_size - page_off; + + wlen = IS_ENCRYPTED(inode) ? round_up(len, CEPH_FSCRYPT_BLOCK_SIZE) : len; +- dout("writepage %p page %p index %lu on %llu~%llu snapc %p seq %lld\n", +- inode, page, page->index, page_off, wlen, snapc, snapc->seq); ++ doutc(cl, "%llx.%llx page %p index %lu on %llu~%llu snapc %p seq %lld\n", ++ ceph_vinop(inode), page, page->index, page_off, wlen, snapc, ++ snapc->seq); + + if (atomic_long_inc_return(&fsc->writeback_count) > + CONGESTION_ON_THRESH(fsc->mount_options->congestion_kb)) +@@ -751,8 +759,9 @@ static int writepage_nounlock(struct pag + osd_req_op_extent_osd_data_pages(req, 0, + bounce_page ? &bounce_page : &page, wlen, 0, + false, false); +- dout("writepage %llu~%llu (%llu bytes, %sencrypted)\n", +- page_off, len, wlen, IS_ENCRYPTED(inode) ? "" : "not "); ++ doutc(cl, "%llx.%llx %llu~%llu (%llu bytes, %sencrypted)\n", ++ ceph_vinop(inode), page_off, len, wlen, ++ IS_ENCRYPTED(inode) ? "" : "not "); + + req->r_mtime = inode->i_mtime; + ceph_osdc_start_request(osdc, req); +@@ -771,19 +780,21 @@ static int writepage_nounlock(struct pag + wbc = &tmp_wbc; + if (err == -ERESTARTSYS) { + /* killed by SIGKILL */ +- dout("writepage interrupted page %p\n", page); ++ doutc(cl, "%llx.%llx interrupted page %p\n", ++ ceph_vinop(inode), page); + redirty_page_for_writepage(wbc, page); + end_page_writeback(page); + return err; + } + if (err == -EBLOCKLISTED) + fsc->blocklisted = true; +- dout("writepage setting page/mapping error %d %p\n", +- err, page); ++ doutc(cl, "%llx.%llx setting page/mapping error %d %p\n", ++ ceph_vinop(inode), err, page); + mapping_set_error(&inode->i_data, err); + wbc->pages_skipped++; + } else { +- dout("writepage cleaned page %p\n", page); ++ doutc(cl, "%llx.%llx cleaned page %p\n", ++ ceph_vinop(inode), page); + err = 0; /* vfs expects us to return 0 */ + } + oldest = detach_page_private(page); +@@ -835,6 +846,7 @@ static void writepages_finish(struct cep + { + struct inode *inode = req->r_inode; + struct ceph_inode_info *ci = ceph_inode(inode); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_osd_data *osd_data; + struct page *page; + int num_pages, total_pages = 0; +@@ -846,7 +858,7 @@ static void writepages_finish(struct cep + unsigned int len = 0; + bool remove_page; + +- dout("writepages_finish %p rc %d\n", inode, rc); ++ doutc(cl, "%llx.%llx rc %d\n", ceph_vinop(inode), rc); + if (rc < 0) { + mapping_set_error(mapping, rc); + ceph_set_error_write(ci); +@@ -868,8 +880,10 @@ static void writepages_finish(struct cep + /* clean all pages */ + for (i = 0; i < req->r_num_ops; i++) { + if (req->r_ops[i].op != CEPH_OSD_OP_WRITE) { +- pr_warn("%s incorrect op %d req %p index %d tid %llu\n", +- __func__, req->r_ops[i].op, req, i, req->r_tid); ++ pr_warn_client(cl, ++ "%llx.%llx incorrect op %d req %p index %d tid %llu\n", ++ ceph_vinop(inode), req->r_ops[i].op, req, i, ++ req->r_tid); + break; + } + +@@ -896,7 +910,7 @@ static void writepages_finish(struct cep + + ceph_put_snap_context(detach_page_private(page)); + end_page_writeback(page); +- dout("unlocking %p\n", page); ++ doutc(cl, "unlocking %p\n", page); + + if (remove_page) + generic_error_remove_page(inode->i_mapping, +@@ -904,8 +918,9 @@ static void writepages_finish(struct cep + + unlock_page(page); + } +- dout("writepages_finish %p wrote %llu bytes cleaned %d pages\n", +- inode, osd_data->length, rc >= 0 ? num_pages : 0); ++ doutc(cl, "%llx.%llx wrote %llu bytes cleaned %d pages\n", ++ ceph_vinop(inode), osd_data->length, ++ rc >= 0 ? num_pages : 0); + + release_pages(osd_data->pages, num_pages); + } +@@ -933,6 +948,7 @@ static int ceph_writepages_start(struct + struct inode *inode = mapping->host; + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode); ++ struct ceph_client *cl = fsc->client; + struct ceph_vino vino = ceph_vino(inode); + pgoff_t index, start_index, end = -1; + struct ceph_snap_context *snapc = NULL, *last_snapc = NULL, *pgsnapc; +@@ -950,15 +966,15 @@ static int ceph_writepages_start(struct + fsc->write_congested) + return 0; + +- dout("writepages_start %p (mode=%s)\n", inode, +- wbc->sync_mode == WB_SYNC_NONE ? "NONE" : +- (wbc->sync_mode == WB_SYNC_ALL ? "ALL" : "HOLD")); ++ doutc(cl, "%llx.%llx (mode=%s)\n", ceph_vinop(inode), ++ wbc->sync_mode == WB_SYNC_NONE ? "NONE" : ++ (wbc->sync_mode == WB_SYNC_ALL ? "ALL" : "HOLD")); + + if (ceph_inode_is_shutdown(inode)) { + if (ci->i_wrbuffer_ref > 0) { +- pr_warn_ratelimited( +- "writepage_start %p %lld forced umount\n", +- inode, ceph_ino(inode)); ++ pr_warn_ratelimited_client(cl, ++ "%llx.%llx %lld forced umount\n", ++ ceph_vinop(inode), ceph_ino(inode)); + } + mapping_set_error(mapping, -EIO); + return -EIO; /* we're in a forced umount, don't write! */ +@@ -982,11 +998,11 @@ retry: + if (!snapc) { + /* hmm, why does writepages get called when there + is no dirty data? */ +- dout(" no snap context with dirty data?\n"); ++ doutc(cl, " no snap context with dirty data?\n"); + goto out; + } +- dout(" oldest snapc is %p seq %lld (%d snaps)\n", +- snapc, snapc->seq, snapc->num_snaps); ++ doutc(cl, " oldest snapc is %p seq %lld (%d snaps)\n", snapc, ++ snapc->seq, snapc->num_snaps); + + should_loop = false; + if (ceph_wbc.head_snapc && snapc != last_snapc) { +@@ -996,13 +1012,13 @@ retry: + end = -1; + if (index > 0) + should_loop = true; +- dout(" cyclic, start at %lu\n", index); ++ doutc(cl, " cyclic, start at %lu\n", index); + } else { + index = wbc->range_start >> PAGE_SHIFT; + end = wbc->range_end >> PAGE_SHIFT; + if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) + range_whole = true; +- dout(" not cyclic, %lu to %lu\n", index, end); ++ doutc(cl, " not cyclic, %lu to %lu\n", index, end); + } + } else if (!ceph_wbc.head_snapc) { + /* Do not respect wbc->range_{start,end}. Dirty pages +@@ -1011,7 +1027,7 @@ retry: + * associated with 'snapc' get written */ + if (index > 0) + should_loop = true; +- dout(" non-head snapc, range whole\n"); ++ doutc(cl, " non-head snapc, range whole\n"); + } + + if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages) +@@ -1034,12 +1050,12 @@ retry: + get_more_pages: + nr_folios = filemap_get_folios_tag(mapping, &index, + end, tag, &fbatch); +- dout("pagevec_lookup_range_tag got %d\n", nr_folios); ++ doutc(cl, "pagevec_lookup_range_tag got %d\n", nr_folios); + if (!nr_folios && !locked_pages) + break; + for (i = 0; i < nr_folios && locked_pages < max_pages; i++) { + page = &fbatch.folios[i]->page; +- dout("? %p idx %lu\n", page, page->index); ++ doutc(cl, "? %p idx %lu\n", page, page->index); + if (locked_pages == 0) + lock_page(page); /* first page */ + else if (!trylock_page(page)) +@@ -1048,15 +1064,15 @@ get_more_pages: + /* only dirty pages, or our accounting breaks */ + if (unlikely(!PageDirty(page)) || + unlikely(page->mapping != mapping)) { +- dout("!dirty or !mapping %p\n", page); ++ doutc(cl, "!dirty or !mapping %p\n", page); + unlock_page(page); + continue; + } + /* only if matching snap context */ + pgsnapc = page_snap_context(page); + if (pgsnapc != snapc) { +- dout("page snapc %p %lld != oldest %p %lld\n", +- pgsnapc, pgsnapc->seq, snapc, snapc->seq); ++ doutc(cl, "page snapc %p %lld != oldest %p %lld\n", ++ pgsnapc, pgsnapc->seq, snapc, snapc->seq); + if (!should_loop && + !ceph_wbc.head_snapc && + wbc->sync_mode != WB_SYNC_NONE) +@@ -1067,8 +1083,8 @@ get_more_pages: + if (page_offset(page) >= ceph_wbc.i_size) { + struct folio *folio = page_folio(page); + +- dout("folio at %lu beyond eof %llu\n", +- folio->index, ceph_wbc.i_size); ++ doutc(cl, "folio at %lu beyond eof %llu\n", ++ folio->index, ceph_wbc.i_size); + if ((ceph_wbc.size_stable || + folio_pos(folio) >= i_size_read(inode)) && + folio_clear_dirty_for_io(folio)) +@@ -1078,23 +1094,23 @@ get_more_pages: + continue; + } + if (strip_unit_end && (page->index > strip_unit_end)) { +- dout("end of strip unit %p\n", page); ++ doutc(cl, "end of strip unit %p\n", page); + unlock_page(page); + break; + } + if (PageWriteback(page) || PageFsCache(page)) { + if (wbc->sync_mode == WB_SYNC_NONE) { +- dout("%p under writeback\n", page); ++ doutc(cl, "%p under writeback\n", page); + unlock_page(page); + continue; + } +- dout("waiting on writeback %p\n", page); ++ doutc(cl, "waiting on writeback %p\n", page); + wait_on_page_writeback(page); + wait_on_page_fscache(page); + } + + if (!clear_page_dirty_for_io(page)) { +- dout("%p !clear_page_dirty_for_io\n", page); ++ doutc(cl, "%p !clear_page_dirty_for_io\n", page); + unlock_page(page); + continue; + } +@@ -1149,8 +1165,8 @@ get_more_pages: + } + + /* note position of first page in fbatch */ +- dout("%p will write page %p idx %lu\n", +- inode, page, page->index); ++ doutc(cl, "%llx.%llx will write page %p idx %lu\n", ++ ceph_vinop(inode), page, page->index); + + if (atomic_long_inc_return(&fsc->writeback_count) > + CONGESTION_ON_THRESH( +@@ -1164,8 +1180,9 @@ get_more_pages: + locked_pages ? GFP_NOWAIT : GFP_NOFS); + if (IS_ERR(pages[locked_pages])) { + if (PTR_ERR(pages[locked_pages]) == -EINVAL) +- pr_err("%s: inode->i_blkbits=%hhu\n", +- __func__, inode->i_blkbits); ++ pr_err_client(cl, ++ "inode->i_blkbits=%hhu\n", ++ inode->i_blkbits); + /* better not fail on first page! */ + BUG_ON(locked_pages == 0); + pages[locked_pages] = NULL; +@@ -1199,7 +1216,7 @@ get_more_pages: + + if (nr_folios && i == nr_folios && + locked_pages < max_pages) { +- dout("reached end fbatch, trying for more\n"); ++ doutc(cl, "reached end fbatch, trying for more\n"); + folio_batch_release(&fbatch); + goto get_more_pages; + } +@@ -1260,8 +1277,8 @@ new_request: + /* Start a new extent */ + osd_req_op_extent_dup_last(req, op_idx, + cur_offset - offset); +- dout("writepages got pages at %llu~%llu\n", +- offset, len); ++ doutc(cl, "got pages at %llu~%llu\n", offset, ++ len); + osd_req_op_extent_osd_data_pages(req, op_idx, + data_pages, len, 0, + from_pool, false); +@@ -1294,12 +1311,13 @@ new_request: + if (IS_ENCRYPTED(inode)) + len = round_up(len, CEPH_FSCRYPT_BLOCK_SIZE); + +- dout("writepages got pages at %llu~%llu\n", offset, len); ++ doutc(cl, "got pages at %llu~%llu\n", offset, len); + + if (IS_ENCRYPTED(inode) && + ((offset | len) & ~CEPH_FSCRYPT_BLOCK_MASK)) +- pr_warn("%s: bad encrypted write offset=%lld len=%llu\n", +- __func__, offset, len); ++ pr_warn_client(cl, ++ "bad encrypted write offset=%lld len=%llu\n", ++ offset, len); + + osd_req_op_extent_osd_data_pages(req, op_idx, data_pages, len, + 0, from_pool, false); +@@ -1351,14 +1369,14 @@ new_request: + done = true; + + release_folios: +- dout("folio_batch release on %d folios (%p)\n", (int)fbatch.nr, +- fbatch.nr ? fbatch.folios[0] : NULL); ++ doutc(cl, "folio_batch release on %d folios (%p)\n", ++ (int)fbatch.nr, fbatch.nr ? fbatch.folios[0] : NULL); + folio_batch_release(&fbatch); + } + + if (should_loop && !done) { + /* more to do; loop back to beginning of file */ +- dout("writepages looping back to beginning of file\n"); ++ doutc(cl, "looping back to beginning of file\n"); + end = start_index - 1; /* OK even when start_index == 0 */ + + /* to write dirty pages associated with next snapc, +@@ -1396,7 +1414,8 @@ release_folios: + out: + ceph_osdc_put_request(req); + ceph_put_snap_context(last_snapc); +- dout("writepages dend - startone, rc = %d\n", rc); ++ doutc(cl, "%llx.%llx dend - startone, rc = %d\n", ceph_vinop(inode), ++ rc); + return rc; + } + +@@ -1430,11 +1449,12 @@ static struct ceph_snap_context * + ceph_find_incompatible(struct page *page) + { + struct inode *inode = page->mapping->host; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + + if (ceph_inode_is_shutdown(inode)) { +- dout(" page %p %llx:%llx is shutdown\n", page, +- ceph_vinop(inode)); ++ doutc(cl, " %llx.%llx page %p is shutdown\n", ++ ceph_vinop(inode), page); + return ERR_PTR(-ESTALE); + } + +@@ -1455,13 +1475,15 @@ ceph_find_incompatible(struct page *page + if (snapc->seq > oldest->seq) { + /* not writeable -- return it for the caller to deal with */ + ceph_put_snap_context(oldest); +- dout(" page %p snapc %p not current or oldest\n", page, snapc); ++ doutc(cl, " %llx.%llx page %p snapc %p not current or oldest\n", ++ ceph_vinop(inode), page, snapc); + return ceph_get_snap_context(snapc); + } + ceph_put_snap_context(oldest); + + /* yay, writeable, do it now (without dropping page lock) */ +- dout(" page %p snapc %p not current, but oldest\n", page, snapc); ++ doutc(cl, " %llx.%llx page %p snapc %p not current, but oldest\n", ++ ceph_vinop(inode), page, snapc); + if (clear_page_dirty_for_io(page)) { + int r = writepage_nounlock(page, NULL); + if (r < 0) +@@ -1530,10 +1552,11 @@ static int ceph_write_end(struct file *f + { + struct folio *folio = page_folio(subpage); + struct inode *inode = file_inode(file); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + bool check_cap = false; + +- dout("write_end file %p inode %p folio %p %d~%d (%d)\n", file, +- inode, folio, (int)pos, (int)copied, (int)len); ++ doutc(cl, "%llx.%llx file %p folio %p %d~%d (%d)\n", ceph_vinop(inode), ++ file, folio, (int)pos, (int)copied, (int)len); + + if (!folio_test_uptodate(folio)) { + /* just return that nothing was copied on a short copy */ +@@ -1593,6 +1616,7 @@ static vm_fault_t ceph_filemap_fault(str + struct vm_area_struct *vma = vmf->vma; + struct inode *inode = file_inode(vma->vm_file); + struct ceph_inode_info *ci = ceph_inode(inode); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_file_info *fi = vma->vm_file->private_data; + loff_t off = (loff_t)vmf->pgoff << PAGE_SHIFT; + int want, got, err; +@@ -1604,8 +1628,8 @@ static vm_fault_t ceph_filemap_fault(str + + ceph_block_sigs(&oldset); + +- dout("filemap_fault %p %llx.%llx %llu trying to get caps\n", +- inode, ceph_vinop(inode), off); ++ doutc(cl, "%llx.%llx %llu trying to get caps\n", ++ ceph_vinop(inode), off); + if (fi->fmode & CEPH_FILE_MODE_LAZY) + want = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO; + else +@@ -1616,8 +1640,8 @@ static vm_fault_t ceph_filemap_fault(str + if (err < 0) + goto out_restore; + +- dout("filemap_fault %p %llu got cap refs on %s\n", +- inode, off, ceph_cap_string(got)); ++ doutc(cl, "%llx.%llx %llu got cap refs on %s\n", ceph_vinop(inode), ++ off, ceph_cap_string(got)); + + if ((got & (CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO)) || + !ceph_has_inline_data(ci)) { +@@ -1625,8 +1649,8 @@ static vm_fault_t ceph_filemap_fault(str + ceph_add_rw_context(fi, &rw_ctx); + ret = filemap_fault(vmf); + ceph_del_rw_context(fi, &rw_ctx); +- dout("filemap_fault %p %llu drop cap refs %s ret %x\n", +- inode, off, ceph_cap_string(got), ret); ++ doutc(cl, "%llx.%llx %llu drop cap refs %s ret %x\n", ++ ceph_vinop(inode), off, ceph_cap_string(got), ret); + } else + err = -EAGAIN; + +@@ -1667,8 +1691,8 @@ static vm_fault_t ceph_filemap_fault(str + ret = VM_FAULT_MAJOR | VM_FAULT_LOCKED; + out_inline: + filemap_invalidate_unlock_shared(mapping); +- dout("filemap_fault %p %llu read inline data ret %x\n", +- inode, off, ret); ++ doutc(cl, "%llx.%llx %llu read inline data ret %x\n", ++ ceph_vinop(inode), off, ret); + } + out_restore: + ceph_restore_sigs(&oldset); +@@ -1682,6 +1706,7 @@ static vm_fault_t ceph_page_mkwrite(stru + { + struct vm_area_struct *vma = vmf->vma; + struct inode *inode = file_inode(vma->vm_file); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_file_info *fi = vma->vm_file->private_data; + struct ceph_cap_flush *prealloc_cf; +@@ -1708,8 +1733,8 @@ static vm_fault_t ceph_page_mkwrite(stru + else + len = offset_in_thp(page, size); + +- dout("page_mkwrite %p %llx.%llx %llu~%zd getting caps i_size %llu\n", +- inode, ceph_vinop(inode), off, len, size); ++ doutc(cl, "%llx.%llx %llu~%zd getting caps i_size %llu\n", ++ ceph_vinop(inode), off, len, size); + if (fi->fmode & CEPH_FILE_MODE_LAZY) + want = CEPH_CAP_FILE_BUFFER | CEPH_CAP_FILE_LAZYIO; + else +@@ -1720,8 +1745,8 @@ static vm_fault_t ceph_page_mkwrite(stru + if (err < 0) + goto out_free; + +- dout("page_mkwrite %p %llu~%zd got cap refs on %s\n", +- inode, off, len, ceph_cap_string(got)); ++ doutc(cl, "%llx.%llx %llu~%zd got cap refs on %s\n", ceph_vinop(inode), ++ off, len, ceph_cap_string(got)); + + /* Update time before taking page lock */ + file_update_time(vma->vm_file); +@@ -1769,8 +1794,8 @@ static vm_fault_t ceph_page_mkwrite(stru + __mark_inode_dirty(inode, dirty); + } + +- dout("page_mkwrite %p %llu~%zd dropping cap refs on %s ret %x\n", +- inode, off, len, ceph_cap_string(got), ret); ++ doutc(cl, "%llx.%llx %llu~%zd dropping cap refs on %s ret %x\n", ++ ceph_vinop(inode), off, len, ceph_cap_string(got), ret); + ceph_put_cap_refs_async(ci, got); + out_free: + ceph_restore_sigs(&oldset); +@@ -1784,6 +1809,7 @@ out_free: + void ceph_fill_inline_data(struct inode *inode, struct page *locked_page, + char *data, size_t len) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct address_space *mapping = inode->i_mapping; + struct page *page; + +@@ -1804,8 +1830,8 @@ void ceph_fill_inline_data(struct inode + } + } + +- dout("fill_inline_data %p %llx.%llx len %zu locked_page %p\n", +- inode, ceph_vinop(inode), len, locked_page); ++ doutc(cl, "%p %llx.%llx len %zu locked_page %p\n", inode, ++ ceph_vinop(inode), len, locked_page); + + if (len > 0) { + void *kaddr = kmap_atomic(page); +@@ -1830,6 +1856,7 @@ int ceph_uninline_data(struct file *file + struct inode *inode = file_inode(file); + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode); ++ struct ceph_client *cl = fsc->client; + struct ceph_osd_request *req = NULL; + struct ceph_cap_flush *prealloc_cf = NULL; + struct folio *folio = NULL; +@@ -1843,8 +1870,8 @@ int ceph_uninline_data(struct file *file + inline_version = ci->i_inline_version; + spin_unlock(&ci->i_ceph_lock); + +- dout("uninline_data %p %llx.%llx inline_version %llu\n", +- inode, ceph_vinop(inode), inline_version); ++ doutc(cl, "%llx.%llx inline_version %llu\n", ceph_vinop(inode), ++ inline_version); + + if (ceph_inode_is_shutdown(inode)) { + err = -EIO; +@@ -1975,8 +2002,8 @@ out_unlock: + out: + ceph_put_snap_context(snapc); + ceph_free_cap_flush(prealloc_cf); +- dout("uninline_data %p %llx.%llx inline_version %llu = %d\n", +- inode, ceph_vinop(inode), inline_version, err); ++ doutc(cl, "%llx.%llx inline_version %llu = %d\n", ++ ceph_vinop(inode), inline_version, err); + return err; + } + +@@ -2005,6 +2032,7 @@ static int __ceph_pool_perm_get(struct c + { + struct ceph_fs_client *fsc = ceph_inode_to_fs_client(&ci->netfs.inode); + struct ceph_mds_client *mdsc = fsc->mdsc; ++ struct ceph_client *cl = fsc->client; + struct ceph_osd_request *rd_req = NULL, *wr_req = NULL; + struct rb_node **p, *parent; + struct ceph_pool_perm *perm; +@@ -2039,10 +2067,10 @@ static int __ceph_pool_perm_get(struct c + goto out; + + if (pool_ns) +- dout("__ceph_pool_perm_get pool %lld ns %.*s no perm cached\n", +- pool, (int)pool_ns->len, pool_ns->str); ++ doutc(cl, "pool %lld ns %.*s no perm cached\n", pool, ++ (int)pool_ns->len, pool_ns->str); + else +- dout("__ceph_pool_perm_get pool %lld no perm cached\n", pool); ++ doutc(cl, "pool %lld no perm cached\n", pool); + + down_write(&mdsc->pool_perm_rwsem); + p = &mdsc->pool_perm_tree.rb_node; +@@ -2167,15 +2195,16 @@ out: + if (!err) + err = have; + if (pool_ns) +- dout("__ceph_pool_perm_get pool %lld ns %.*s result = %d\n", +- pool, (int)pool_ns->len, pool_ns->str, err); ++ doutc(cl, "pool %lld ns %.*s result = %d\n", pool, ++ (int)pool_ns->len, pool_ns->str, err); + else +- dout("__ceph_pool_perm_get pool %lld result = %d\n", pool, err); ++ doutc(cl, "pool %lld result = %d\n", pool, err); + return err; + } + + 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; +@@ -2205,13 +2234,11 @@ int ceph_pool_perm_check(struct inode *i + check: + if (flags & CEPH_I_POOL_PERM) { + if ((need & CEPH_CAP_FILE_RD) && !(flags & CEPH_I_POOL_RD)) { +- dout("ceph_pool_perm_check pool %lld no read perm\n", +- pool); ++ doutc(cl, "pool %lld no read perm\n", pool); + return -EPERM; + } + if ((need & CEPH_CAP_FILE_WR) && !(flags & CEPH_I_POOL_WR)) { +- dout("ceph_pool_perm_check pool %lld no write perm\n", +- pool); ++ doutc(cl, "pool %lld no write perm\n", pool); + return -EPERM; + } + return 0; +--- a/fs/ceph/caps.c ++++ b/fs/ceph/caps.c +@@ -186,10 +186,10 @@ static void __ceph_unreserve_caps(struct + mdsc->caps_avail_count += nr_caps; + } + +- dout("%s: caps %d = %d used + %d resv + %d avail\n", +- __func__, +- mdsc->caps_total_count, mdsc->caps_use_count, +- mdsc->caps_reserve_count, mdsc->caps_avail_count); ++ doutc(mdsc->fsc->client, ++ "caps %d = %d used + %d resv + %d avail\n", ++ mdsc->caps_total_count, mdsc->caps_use_count, ++ mdsc->caps_reserve_count, mdsc->caps_avail_count); + BUG_ON(mdsc->caps_total_count != mdsc->caps_use_count + + mdsc->caps_reserve_count + + mdsc->caps_avail_count); +@@ -202,6 +202,7 @@ static void __ceph_unreserve_caps(struct + int ceph_reserve_caps(struct ceph_mds_client *mdsc, + struct ceph_cap_reservation *ctx, int need) + { ++ struct ceph_client *cl = mdsc->fsc->client; + int i, j; + struct ceph_cap *cap; + int have; +@@ -212,7 +213,7 @@ int ceph_reserve_caps(struct ceph_mds_cl + struct ceph_mds_session *s; + LIST_HEAD(newcaps); + +- dout("reserve caps ctx=%p need=%d\n", ctx, need); ++ doutc(cl, "ctx=%p need=%d\n", ctx, need); + + /* first reserve any caps that are already allocated */ + spin_lock(&mdsc->caps_list_lock); +@@ -272,8 +273,8 @@ int ceph_reserve_caps(struct ceph_mds_cl + continue; + } + +- pr_warn("reserve caps ctx=%p ENOMEM need=%d got=%d\n", +- ctx, need, have + alloc); ++ pr_warn_client(cl, "ctx=%p ENOMEM need=%d got=%d\n", ctx, need, ++ have + alloc); + err = -ENOMEM; + break; + } +@@ -298,20 +299,21 @@ int ceph_reserve_caps(struct ceph_mds_cl + + spin_unlock(&mdsc->caps_list_lock); + +- dout("reserve caps ctx=%p %d = %d used + %d resv + %d avail\n", +- ctx, mdsc->caps_total_count, mdsc->caps_use_count, +- mdsc->caps_reserve_count, mdsc->caps_avail_count); ++ doutc(cl, "ctx=%p %d = %d used + %d resv + %d avail\n", ctx, ++ mdsc->caps_total_count, mdsc->caps_use_count, ++ mdsc->caps_reserve_count, mdsc->caps_avail_count); + return err; + } + + void ceph_unreserve_caps(struct ceph_mds_client *mdsc, + struct ceph_cap_reservation *ctx) + { ++ struct ceph_client *cl = mdsc->fsc->client; + bool reclaim = false; + if (!ctx->count) + return; + +- dout("unreserve caps ctx=%p count=%d\n", ctx, ctx->count); ++ doutc(cl, "ctx=%p count=%d\n", ctx, ctx->count); + spin_lock(&mdsc->caps_list_lock); + __ceph_unreserve_caps(mdsc, ctx->count); + ctx->count = 0; +@@ -328,6 +330,7 @@ void ceph_unreserve_caps(struct ceph_mds + struct ceph_cap *ceph_get_cap(struct ceph_mds_client *mdsc, + struct ceph_cap_reservation *ctx) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_cap *cap = NULL; + + /* temporary, until we do something about cap import/export */ +@@ -359,9 +362,9 @@ struct ceph_cap *ceph_get_cap(struct cep + } + + spin_lock(&mdsc->caps_list_lock); +- dout("get_cap ctx=%p (%d) %d = %d used + %d resv + %d avail\n", +- ctx, ctx->count, mdsc->caps_total_count, mdsc->caps_use_count, +- mdsc->caps_reserve_count, mdsc->caps_avail_count); ++ doutc(cl, "ctx=%p (%d) %d = %d used + %d resv + %d avail\n", ctx, ++ ctx->count, mdsc->caps_total_count, mdsc->caps_use_count, ++ mdsc->caps_reserve_count, mdsc->caps_avail_count); + BUG_ON(!ctx->count); + BUG_ON(ctx->count > mdsc->caps_reserve_count); + BUG_ON(list_empty(&mdsc->caps_list)); +@@ -382,10 +385,12 @@ struct ceph_cap *ceph_get_cap(struct cep + + void ceph_put_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap) + { ++ struct ceph_client *cl = mdsc->fsc->client; ++ + spin_lock(&mdsc->caps_list_lock); +- dout("put_cap %p %d = %d used + %d resv + %d avail\n", +- cap, mdsc->caps_total_count, mdsc->caps_use_count, +- mdsc->caps_reserve_count, mdsc->caps_avail_count); ++ doutc(cl, "%p %d = %d used + %d resv + %d avail\n", cap, ++ mdsc->caps_total_count, mdsc->caps_use_count, ++ mdsc->caps_reserve_count, mdsc->caps_avail_count); + mdsc->caps_use_count--; + /* + * Keep some preallocated caps around (ceph_min_count), to +@@ -491,11 +496,13 @@ static void __insert_cap_node(struct cep + static void __cap_set_timeouts(struct ceph_mds_client *mdsc, + struct ceph_inode_info *ci) + { ++ struct inode *inode = &ci->netfs.inode; + struct ceph_mount_options *opt = mdsc->fsc->mount_options; ++ + ci->i_hold_caps_max = round_jiffies(jiffies + + opt->caps_wanted_delay_max * HZ); +- dout("__cap_set_timeouts %p %lu\n", &ci->netfs.inode, +- ci->i_hold_caps_max - jiffies); ++ doutc(mdsc->fsc->client, "%p %llx.%llx %lu\n", inode, ++ ceph_vinop(inode), ci->i_hold_caps_max - jiffies); + } + + /* +@@ -509,8 +516,11 @@ static void __cap_set_timeouts(struct ce + static void __cap_delay_requeue(struct ceph_mds_client *mdsc, + struct ceph_inode_info *ci) + { +- dout("__cap_delay_requeue %p flags 0x%lx at %lu\n", &ci->netfs.inode, +- ci->i_ceph_flags, ci->i_hold_caps_max); ++ struct inode *inode = &ci->netfs.inode; ++ ++ doutc(mdsc->fsc->client, "%p %llx.%llx flags 0x%lx at %lu\n", ++ inode, ceph_vinop(inode), ci->i_ceph_flags, ++ ci->i_hold_caps_max); + if (!mdsc->stopping) { + spin_lock(&mdsc->cap_delay_lock); + if (!list_empty(&ci->i_cap_delay_list)) { +@@ -533,7 +543,9 @@ no_change: + static void __cap_delay_requeue_front(struct ceph_mds_client *mdsc, + struct ceph_inode_info *ci) + { +- dout("__cap_delay_requeue_front %p\n", &ci->netfs.inode); ++ struct inode *inode = &ci->netfs.inode; ++ ++ doutc(mdsc->fsc->client, "%p %llx.%llx\n", inode, ceph_vinop(inode)); + spin_lock(&mdsc->cap_delay_lock); + ci->i_ceph_flags |= CEPH_I_FLUSH; + if (!list_empty(&ci->i_cap_delay_list)) +@@ -550,7 +562,9 @@ static void __cap_delay_requeue_front(st + static void __cap_delay_cancel(struct ceph_mds_client *mdsc, + struct ceph_inode_info *ci) + { +- dout("__cap_delay_cancel %p\n", &ci->netfs.inode); ++ struct inode *inode = &ci->netfs.inode; ++ ++ doutc(mdsc->fsc->client, "%p %llx.%llx\n", inode, ceph_vinop(inode)); + if (list_empty(&ci->i_cap_delay_list)) + return; + spin_lock(&mdsc->cap_delay_lock); +@@ -562,6 +576,9 @@ static void __cap_delay_cancel(struct ce + static void __check_cap_issue(struct ceph_inode_info *ci, struct ceph_cap *cap, + unsigned issued) + { ++ struct inode *inode = &ci->netfs.inode; ++ struct ceph_client *cl = ceph_inode_to_client(inode); ++ + unsigned had = __ceph_caps_issued(ci, NULL); + + lockdep_assert_held(&ci->i_ceph_lock); +@@ -586,7 +603,7 @@ static void __check_cap_issue(struct cep + if (issued & CEPH_CAP_FILE_SHARED) + atomic_inc(&ci->i_shared_gen); + if (S_ISDIR(ci->netfs.inode.i_mode)) { +- dout(" marking %p NOT complete\n", &ci->netfs.inode); ++ doutc(cl, " marking %p NOT complete\n", inode); + __ceph_dir_clear_complete(ci); + } + } +@@ -636,6 +653,7 @@ void ceph_add_cap(struct inode *inode, + struct ceph_cap **new_cap) + { + struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_cap *cap; + int mds = session->s_mds; +@@ -644,8 +662,9 @@ void ceph_add_cap(struct inode *inode, + + lockdep_assert_held(&ci->i_ceph_lock); + +- dout("add_cap %p mds%d cap %llx %s seq %d\n", inode, +- session->s_mds, cap_id, ceph_cap_string(issued), seq); ++ doutc(cl, "%p %llx.%llx mds%d cap %llx %s seq %d\n", inode, ++ ceph_vinop(inode), session->s_mds, cap_id, ++ ceph_cap_string(issued), seq); + + gen = atomic_read(&session->s_cap_gen); + +@@ -723,9 +742,9 @@ void ceph_add_cap(struct inode *inode, + actual_wanted = __ceph_caps_wanted(ci); + if ((wanted & ~actual_wanted) || + (issued & ~actual_wanted & CEPH_CAP_ANY_WR)) { +- dout(" issued %s, mds wanted %s, actual %s, queueing\n", +- ceph_cap_string(issued), ceph_cap_string(wanted), +- ceph_cap_string(actual_wanted)); ++ doutc(cl, "issued %s, mds wanted %s, actual %s, queueing\n", ++ ceph_cap_string(issued), ceph_cap_string(wanted), ++ ceph_cap_string(actual_wanted)); + __cap_delay_requeue(mdsc, ci); + } + +@@ -742,9 +761,9 @@ void ceph_add_cap(struct inode *inode, + WARN_ON(ci->i_auth_cap == cap); + } + +- dout("add_cap inode %p (%llx.%llx) cap %p %s now %s seq %d mds%d\n", +- inode, ceph_vinop(inode), cap, ceph_cap_string(issued), +- ceph_cap_string(issued|cap->issued), seq, mds); ++ doutc(cl, "inode %p %llx.%llx cap %p %s now %s seq %d mds%d\n", ++ inode, ceph_vinop(inode), cap, ceph_cap_string(issued), ++ ceph_cap_string(issued|cap->issued), seq, mds); + cap->cap_id = cap_id; + cap->issued = issued; + cap->implemented |= issued; +@@ -766,6 +785,8 @@ void ceph_add_cap(struct inode *inode, + */ + static int __cap_is_valid(struct ceph_cap *cap) + { ++ struct inode *inode = &cap->ci->netfs.inode; ++ struct ceph_client *cl = cap->session->s_mdsc->fsc->client; + unsigned long ttl; + u32 gen; + +@@ -773,9 +794,9 @@ static int __cap_is_valid(struct ceph_ca + ttl = cap->session->s_cap_ttl; + + if (cap->cap_gen < gen || time_after_eq(jiffies, ttl)) { +- dout("__cap_is_valid %p cap %p issued %s " +- "but STALE (gen %u vs %u)\n", &cap->ci->netfs.inode, +- cap, ceph_cap_string(cap->issued), cap->cap_gen, gen); ++ doutc(cl, "%p %llx.%llx cap %p issued %s but STALE (gen %u vs %u)\n", ++ inode, ceph_vinop(inode), cap, ++ ceph_cap_string(cap->issued), cap->cap_gen, gen); + return 0; + } + +@@ -789,6 +810,8 @@ static int __cap_is_valid(struct ceph_ca + */ + int __ceph_caps_issued(struct ceph_inode_info *ci, int *implemented) + { ++ struct inode *inode = &ci->netfs.inode; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + int have = ci->i_snap_caps; + struct ceph_cap *cap; + struct rb_node *p; +@@ -799,8 +822,8 @@ int __ceph_caps_issued(struct ceph_inode + cap = rb_entry(p, struct ceph_cap, ci_node); + if (!__cap_is_valid(cap)) + continue; +- dout("__ceph_caps_issued %p cap %p issued %s\n", +- &ci->netfs.inode, cap, ceph_cap_string(cap->issued)); ++ doutc(cl, "%p %llx.%llx cap %p issued %s\n", inode, ++ ceph_vinop(inode), cap, ceph_cap_string(cap->issued)); + have |= cap->issued; + if (implemented) + *implemented |= cap->implemented; +@@ -843,16 +866,18 @@ int __ceph_caps_issued_other(struct ceph + */ + static void __touch_cap(struct ceph_cap *cap) + { ++ struct inode *inode = &cap->ci->netfs.inode; + struct ceph_mds_session *s = cap->session; ++ struct ceph_client *cl = s->s_mdsc->fsc->client; + + spin_lock(&s->s_cap_lock); + if (!s->s_cap_iterator) { +- dout("__touch_cap %p cap %p mds%d\n", &cap->ci->netfs.inode, cap, +- s->s_mds); ++ doutc(cl, "%p %llx.%llx cap %p mds%d\n", inode, ++ ceph_vinop(inode), cap, s->s_mds); + list_move_tail(&cap->session_caps, &s->s_caps); + } else { +- dout("__touch_cap %p cap %p mds%d NOP, iterating over caps\n", +- &cap->ci->netfs.inode, cap, s->s_mds); ++ doutc(cl, "%p %llx.%llx cap %p mds%d NOP, iterating over caps\n", ++ inode, ceph_vinop(inode), cap, s->s_mds); + } + spin_unlock(&s->s_cap_lock); + } +@@ -864,15 +889,16 @@ static void __touch_cap(struct ceph_cap + */ + int __ceph_caps_issued_mask(struct ceph_inode_info *ci, int mask, int touch) + { ++ struct inode *inode = &ci->netfs.inode; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_cap *cap; + struct rb_node *p; + int have = ci->i_snap_caps; + + if ((have & mask) == mask) { +- dout("__ceph_caps_issued_mask ino 0x%llx snap issued %s" +- " (mask %s)\n", ceph_ino(&ci->netfs.inode), +- ceph_cap_string(have), +- ceph_cap_string(mask)); ++ doutc(cl, "mask %p %llx.%llx snap issued %s (mask %s)\n", ++ inode, ceph_vinop(inode), ceph_cap_string(have), ++ ceph_cap_string(mask)); + return 1; + } + +@@ -881,10 +907,10 @@ int __ceph_caps_issued_mask(struct ceph_ + if (!__cap_is_valid(cap)) + continue; + if ((cap->issued & mask) == mask) { +- dout("__ceph_caps_issued_mask ino 0x%llx cap %p issued %s" +- " (mask %s)\n", ceph_ino(&ci->netfs.inode), cap, +- ceph_cap_string(cap->issued), +- ceph_cap_string(mask)); ++ doutc(cl, "mask %p %llx.%llx cap %p issued %s (mask %s)\n", ++ inode, ceph_vinop(inode), cap, ++ ceph_cap_string(cap->issued), ++ ceph_cap_string(mask)); + if (touch) + __touch_cap(cap); + return 1; +@@ -893,10 +919,10 @@ int __ceph_caps_issued_mask(struct ceph_ + /* does a combination of caps satisfy mask? */ + have |= cap->issued; + if ((have & mask) == mask) { +- dout("__ceph_caps_issued_mask ino 0x%llx combo issued %s" +- " (mask %s)\n", ceph_ino(&ci->netfs.inode), +- ceph_cap_string(cap->issued), +- ceph_cap_string(mask)); ++ doutc(cl, "mask %p %llx.%llx combo issued %s (mask %s)\n", ++ inode, ceph_vinop(inode), ++ ceph_cap_string(cap->issued), ++ ceph_cap_string(mask)); + if (touch) { + struct rb_node *q; + +@@ -954,13 +980,14 @@ int __ceph_caps_revoking_other(struct ce + int ceph_caps_revoking(struct ceph_inode_info *ci, int mask) + { + struct inode *inode = &ci->netfs.inode; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + int ret; + + spin_lock(&ci->i_ceph_lock); + ret = __ceph_caps_revoking_other(ci, NULL, mask); + spin_unlock(&ci->i_ceph_lock); +- dout("ceph_caps_revoking %p %s = %d\n", inode, +- ceph_cap_string(mask), ret); ++ doutc(cl, "%p %llx.%llx %s = %d\n", inode, ceph_vinop(inode), ++ ceph_cap_string(mask), ret); + return ret; + } + +@@ -1107,19 +1134,21 @@ int ceph_is_any_caps(struct inode *inode + void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release) + { + struct ceph_mds_session *session = cap->session; ++ struct ceph_client *cl = session->s_mdsc->fsc->client; + struct ceph_inode_info *ci = cap->ci; ++ struct inode *inode = &ci->netfs.inode; + struct ceph_mds_client *mdsc; + int removed = 0; + + /* 'ci' being NULL means the remove have already occurred */ + if (!ci) { +- dout("%s: cap inode is NULL\n", __func__); ++ doutc(cl, "inode is NULL\n"); + return; + } + + lockdep_assert_held(&ci->i_ceph_lock); + +- dout("__ceph_remove_cap %p from %p\n", cap, &ci->netfs.inode); ++ doutc(cl, "%p from %p %llx.%llx\n", cap, inode, ceph_vinop(inode)); + + mdsc = ceph_inode_to_fs_client(&ci->netfs.inode)->mdsc; + +@@ -1132,8 +1161,8 @@ void __ceph_remove_cap(struct ceph_cap * + spin_lock(&session->s_cap_lock); + if (session->s_cap_iterator == cap) { + /* not yet, we are iterating over this very cap */ +- dout("__ceph_remove_cap delaying %p removal from session %p\n", +- cap, cap->session); ++ doutc(cl, "delaying %p removal from session %p\n", cap, ++ cap->session); + } else { + list_del_init(&cap->session_caps); + session->s_nr_caps--; +@@ -1186,7 +1215,7 @@ void ceph_remove_cap(struct ceph_mds_cli + + /* 'ci' being NULL means the remove have already occurred */ + if (!ci) { +- dout("%s: cap inode is NULL\n", __func__); ++ doutc(mdsc->fsc->client, "inode is NULL\n"); + return; + } + +@@ -1228,15 +1257,19 @@ static void encode_cap_msg(struct ceph_m + { + struct ceph_mds_caps *fc; + void *p; +- struct ceph_osd_client *osdc = &arg->session->s_mdsc->fsc->client->osdc; ++ struct ceph_mds_client *mdsc = arg->session->s_mdsc; ++ struct ceph_osd_client *osdc = &mdsc->fsc->client->osdc; + +- dout("%s %s %llx %llx caps %s wanted %s dirty %s seq %u/%u tid %llu/%llu mseq %u follows %lld size %llu/%llu xattr_ver %llu xattr_len %d\n", +- __func__, ceph_cap_op_name(arg->op), arg->cid, arg->ino, +- ceph_cap_string(arg->caps), ceph_cap_string(arg->wanted), +- ceph_cap_string(arg->dirty), arg->seq, arg->issue_seq, +- arg->flush_tid, arg->oldest_flush_tid, arg->mseq, arg->follows, +- arg->size, arg->max_size, arg->xattr_version, +- arg->xattr_buf ? (int)arg->xattr_buf->vec.iov_len : 0); ++ doutc(mdsc->fsc->client, ++ "%s %llx %llx caps %s wanted %s dirty %s seq %u/%u" ++ " tid %llu/%llu mseq %u follows %lld size %llu/%llu" ++ " xattr_ver %llu xattr_len %d\n", ++ ceph_cap_op_name(arg->op), arg->cid, arg->ino, ++ ceph_cap_string(arg->caps), ceph_cap_string(arg->wanted), ++ ceph_cap_string(arg->dirty), arg->seq, arg->issue_seq, ++ arg->flush_tid, arg->oldest_flush_tid, arg->mseq, arg->follows, ++ arg->size, arg->max_size, arg->xattr_version, ++ arg->xattr_buf ? (int)arg->xattr_buf->vec.iov_len : 0); + + msg->hdr.version = cpu_to_le16(12); + msg->hdr.tid = cpu_to_le64(arg->flush_tid); +@@ -1373,6 +1406,7 @@ static void __prep_cap(struct cap_msg_ar + { + struct ceph_inode_info *ci = cap->ci; + struct inode *inode = &ci->netfs.inode; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + int held, revoking; + + lockdep_assert_held(&ci->i_ceph_lock); +@@ -1381,10 +1415,10 @@ static void __prep_cap(struct cap_msg_ar + revoking = cap->implemented & ~cap->issued; + retain &= ~revoking; + +- dout("%s %p cap %p session %p %s -> %s (revoking %s)\n", +- __func__, inode, cap, cap->session, +- ceph_cap_string(held), ceph_cap_string(held & retain), +- ceph_cap_string(revoking)); ++ doutc(cl, "%p %llx.%llx cap %p session %p %s -> %s (revoking %s)\n", ++ inode, ceph_vinop(inode), cap, cap->session, ++ ceph_cap_string(held), ceph_cap_string(held & retain), ++ ceph_cap_string(revoking)); + BUG_ON((retain & CEPH_CAP_PIN) == 0); + + ci->i_ceph_flags &= ~CEPH_I_FLUSH; +@@ -1500,13 +1534,16 @@ static void __send_cap(struct cap_msg_ar + { + struct ceph_msg *msg; + struct inode *inode = &ci->netfs.inode; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + + msg = ceph_msg_new(CEPH_MSG_CLIENT_CAPS, cap_msg_size(arg), GFP_NOFS, + false); + if (!msg) { +- pr_err("error allocating cap msg: ino (%llx.%llx) flushing %s tid %llu, requeuing cap.\n", +- ceph_vinop(inode), ceph_cap_string(arg->dirty), +- arg->flush_tid); ++ pr_err_client(cl, ++ "error allocating cap msg: ino (%llx.%llx)" ++ " flushing %s tid %llu, requeuing cap.\n", ++ ceph_vinop(inode), ceph_cap_string(arg->dirty), ++ arg->flush_tid); + spin_lock(&ci->i_ceph_lock); + __cap_delay_requeue(arg->session->s_mdsc, ci); + spin_unlock(&ci->i_ceph_lock); +@@ -1596,11 +1633,13 @@ static void __ceph_flush_snaps(struct ce + { + struct inode *inode = &ci->netfs.inode; + struct ceph_mds_client *mdsc = session->s_mdsc; ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_cap_snap *capsnap; + u64 oldest_flush_tid = 0; + u64 first_tid = 1, last_tid = 0; + +- dout("__flush_snaps %p session %p\n", inode, session); ++ doutc(cl, "%p %llx.%llx session %p\n", inode, ceph_vinop(inode), ++ session); + + list_for_each_entry(capsnap, &ci->i_cap_snaps, ci_item) { + /* +@@ -1615,7 +1654,7 @@ static void __ceph_flush_snaps(struct ce + + /* only flush each capsnap once */ + if (capsnap->cap_flush.tid > 0) { +- dout(" already flushed %p, skipping\n", capsnap); ++ doutc(cl, "already flushed %p, skipping\n", capsnap); + continue; + } + +@@ -1647,8 +1686,8 @@ static void __ceph_flush_snaps(struct ce + int ret; + + if (!(cap && cap->session == session)) { +- dout("__flush_snaps %p auth cap %p not mds%d, " +- "stop\n", inode, cap, session->s_mds); ++ doutc(cl, "%p %llx.%llx auth cap %p not mds%d, stop\n", ++ inode, ceph_vinop(inode), cap, session->s_mds); + break; + } + +@@ -1669,15 +1708,17 @@ static void __ceph_flush_snaps(struct ce + refcount_inc(&capsnap->nref); + spin_unlock(&ci->i_ceph_lock); + +- dout("__flush_snaps %p capsnap %p tid %llu %s\n", +- inode, capsnap, cf->tid, ceph_cap_string(capsnap->dirty)); ++ doutc(cl, "%p %llx.%llx capsnap %p tid %llu %s\n", inode, ++ ceph_vinop(inode), capsnap, cf->tid, ++ ceph_cap_string(capsnap->dirty)); + + ret = __send_flush_snap(inode, session, capsnap, cap->mseq, + oldest_flush_tid); + if (ret < 0) { +- pr_err("__flush_snaps: error sending cap flushsnap, " +- "ino (%llx.%llx) tid %llu follows %llu\n", +- ceph_vinop(inode), cf->tid, capsnap->follows); ++ pr_err_client(cl, "error sending cap flushsnap, " ++ "ino (%llx.%llx) tid %llu follows %llu\n", ++ ceph_vinop(inode), cf->tid, ++ capsnap->follows); + } + + ceph_put_cap_snap(capsnap); +@@ -1690,27 +1731,28 @@ void ceph_flush_snaps(struct ceph_inode_ + { + struct inode *inode = &ci->netfs.inode; + struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_mds_session *session = NULL; + bool need_put = false; + int mds; + +- dout("ceph_flush_snaps %p\n", inode); ++ doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode)); + if (psession) + session = *psession; + retry: + spin_lock(&ci->i_ceph_lock); + if (!(ci->i_ceph_flags & CEPH_I_FLUSH_SNAPS)) { +- dout(" no capsnap needs flush, doing nothing\n"); ++ doutc(cl, " no capsnap needs flush, doing nothing\n"); + goto out; + } + if (!ci->i_auth_cap) { +- dout(" no auth cap (migrating?), doing nothing\n"); ++ doutc(cl, " no auth cap (migrating?), doing nothing\n"); + goto out; + } + + mds = ci->i_auth_cap->session->s_mds; + if (session && session->s_mds != mds) { +- dout(" oops, wrong session %p mutex\n", session); ++ doutc(cl, " oops, wrong session %p mutex\n", session); + ceph_put_mds_session(session); + session = NULL; + } +@@ -1756,21 +1798,23 @@ int __ceph_mark_dirty_caps(struct ceph_i + struct ceph_mds_client *mdsc = + ceph_sb_to_fs_client(ci->netfs.inode.i_sb)->mdsc; + struct inode *inode = &ci->netfs.inode; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + int was = ci->i_dirty_caps; + int dirty = 0; + + lockdep_assert_held(&ci->i_ceph_lock); + + if (!ci->i_auth_cap) { +- pr_warn("__mark_dirty_caps %p %llx mask %s, " +- "but no auth cap (session was closed?)\n", +- inode, ceph_ino(inode), ceph_cap_string(mask)); ++ pr_warn_client(cl, "%p %llx.%llx mask %s, " ++ "but no auth cap (session was closed?)\n", ++ inode, ceph_vinop(inode), ++ ceph_cap_string(mask)); + return 0; + } + +- dout("__mark_dirty_caps %p %s dirty %s -> %s\n", &ci->netfs.inode, +- ceph_cap_string(mask), ceph_cap_string(was), +- ceph_cap_string(was | mask)); ++ doutc(cl, "%p %llx.%llx %s dirty %s -> %s\n", inode, ++ ceph_vinop(inode), ceph_cap_string(mask), ++ ceph_cap_string(was), ceph_cap_string(was | mask)); + ci->i_dirty_caps |= mask; + if (was == 0) { + struct ceph_mds_session *session = ci->i_auth_cap->session; +@@ -1783,8 +1827,9 @@ int __ceph_mark_dirty_caps(struct ceph_i + ci->i_head_snapc = ceph_get_snap_context( + ci->i_snap_realm->cached_context); + } +- dout(" inode %p now dirty snapc %p auth cap %p\n", +- &ci->netfs.inode, ci->i_head_snapc, ci->i_auth_cap); ++ doutc(cl, "%p %llx.%llx now dirty snapc %p auth cap %p\n", ++ inode, ceph_vinop(inode), ci->i_head_snapc, ++ ci->i_auth_cap); + BUG_ON(!list_empty(&ci->i_dirty_item)); + spin_lock(&mdsc->cap_dirty_lock); + list_add(&ci->i_dirty_item, &session->s_cap_dirty); +@@ -1878,6 +1923,7 @@ static u64 __mark_caps_flushing(struct i + u64 *oldest_flush_tid) + { + struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_cap_flush *cf = NULL; + int flushing; +@@ -1888,13 +1934,13 @@ static u64 __mark_caps_flushing(struct i + BUG_ON(!ci->i_prealloc_cap_flush); + + flushing = ci->i_dirty_caps; +- dout("__mark_caps_flushing flushing %s, flushing_caps %s -> %s\n", +- ceph_cap_string(flushing), +- ceph_cap_string(ci->i_flushing_caps), +- ceph_cap_string(ci->i_flushing_caps | flushing)); ++ doutc(cl, "flushing %s, flushing_caps %s -> %s\n", ++ ceph_cap_string(flushing), ++ ceph_cap_string(ci->i_flushing_caps), ++ ceph_cap_string(ci->i_flushing_caps | flushing)); + ci->i_flushing_caps |= flushing; + ci->i_dirty_caps = 0; +- dout(" inode %p now !dirty\n", inode); ++ doutc(cl, "%p %llx.%llx now !dirty\n", inode, ceph_vinop(inode)); + + swap(cf, ci->i_prealloc_cap_flush); + cf->caps = flushing; +@@ -1925,6 +1971,7 @@ static int try_nonblocking_invalidate(st + __releases(ci->i_ceph_lock) + __acquires(ci->i_ceph_lock) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + u32 invalidating_gen = ci->i_rdcache_gen; + +@@ -1936,12 +1983,13 @@ static int try_nonblocking_invalidate(st + if (inode->i_data.nrpages == 0 && + invalidating_gen == ci->i_rdcache_gen) { + /* success. */ +- dout("try_nonblocking_invalidate %p success\n", inode); ++ doutc(cl, "%p %llx.%llx success\n", inode, ++ ceph_vinop(inode)); + /* save any racing async invalidate some trouble */ + ci->i_rdcache_revoking = ci->i_rdcache_gen - 1; + return 0; + } +- dout("try_nonblocking_invalidate %p failed\n", inode); ++ doutc(cl, "%p %llx.%llx failed\n", inode, ceph_vinop(inode)); + return -1; + } + +@@ -1973,6 +2021,7 @@ void ceph_check_caps(struct ceph_inode_i + { + struct inode *inode = &ci->netfs.inode; + struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_cap *cap; + u64 flush_tid, oldest_flush_tid; + int file_wanted, used, cap_used; +@@ -2047,9 +2096,9 @@ retry: + } + } + +- dout("check_caps %llx.%llx file_want %s used %s dirty %s flushing %s" +- " issued %s revoking %s retain %s %s%s%s\n", ceph_vinop(inode), +- ceph_cap_string(file_wanted), ++ doutc(cl, "%p %llx.%llx file_want %s used %s dirty %s " ++ "flushing %s issued %s revoking %s retain %s %s%s%s\n", ++ inode, ceph_vinop(inode), ceph_cap_string(file_wanted), + ceph_cap_string(used), ceph_cap_string(ci->i_dirty_caps), + ceph_cap_string(ci->i_flushing_caps), + ceph_cap_string(issued), ceph_cap_string(revoking), +@@ -2070,10 +2119,10 @@ retry: + (revoking & (CEPH_CAP_FILE_CACHE| + CEPH_CAP_FILE_LAZYIO)) && /* or revoking cache */ + !tried_invalidate) { +- dout("check_caps trying to invalidate on %llx.%llx\n", +- ceph_vinop(inode)); ++ doutc(cl, "trying to invalidate on %p %llx.%llx\n", ++ inode, ceph_vinop(inode)); + if (try_nonblocking_invalidate(inode) < 0) { +- dout("check_caps queuing invalidate\n"); ++ doutc(cl, "queuing invalidate\n"); + queue_invalidate = true; + ci->i_rdcache_revoking = ci->i_rdcache_gen; + } +@@ -2101,35 +2150,35 @@ retry: + cap_used &= ~ci->i_auth_cap->issued; + + revoking = cap->implemented & ~cap->issued; +- dout(" mds%d cap %p used %s issued %s implemented %s revoking %s\n", +- cap->mds, cap, ceph_cap_string(cap_used), +- ceph_cap_string(cap->issued), +- ceph_cap_string(cap->implemented), +- ceph_cap_string(revoking)); ++ doutc(cl, " mds%d cap %p used %s issued %s implemented %s revoking %s\n", ++ cap->mds, cap, ceph_cap_string(cap_used), ++ ceph_cap_string(cap->issued), ++ ceph_cap_string(cap->implemented), ++ ceph_cap_string(revoking)); + + if (cap == ci->i_auth_cap && + (cap->issued & CEPH_CAP_FILE_WR)) { + /* request larger max_size from MDS? */ + if (ci->i_wanted_max_size > ci->i_max_size && + ci->i_wanted_max_size > ci->i_requested_max_size) { +- dout("requesting new max_size\n"); ++ doutc(cl, "requesting new max_size\n"); + goto ack; + } + + /* approaching file_max? */ + if (__ceph_should_report_size(ci)) { +- dout("i_size approaching max_size\n"); ++ doutc(cl, "i_size approaching max_size\n"); + goto ack; + } + } + /* flush anything dirty? */ + if (cap == ci->i_auth_cap) { + if ((flags & CHECK_CAPS_FLUSH) && ci->i_dirty_caps) { +- dout("flushing dirty caps\n"); ++ doutc(cl, "flushing dirty caps\n"); + goto ack; + } + if (ci->i_ceph_flags & CEPH_I_FLUSH_SNAPS) { +- dout("flushing snap caps\n"); ++ doutc(cl, "flushing snap caps\n"); + goto ack; + } + } +@@ -2137,7 +2186,7 @@ retry: + /* completed revocation? going down and there are no caps? */ + if (revoking) { + if ((revoking & cap_used) == 0) { +- dout("completed revocation of %s\n", ++ doutc(cl, "completed revocation of %s\n", + ceph_cap_string(cap->implemented & ~cap->issued)); + goto ack; + } +@@ -2315,6 +2364,7 @@ static int caps_are_flushed(struct inode + static int flush_mdlog_and_wait_inode_unsafe_requests(struct inode *inode) + { + struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_mds_request *req1 = NULL, *req2 = NULL; + int ret, err = 0; +@@ -2404,8 +2454,9 @@ static int flush_mdlog_and_wait_inode_un + kfree(sessions); + } + +- dout("%s %p wait on tid %llu %llu\n", __func__, +- inode, req1 ? req1->r_tid : 0ULL, req2 ? req2->r_tid : 0ULL); ++ doutc(cl, "%p %llx.%llx wait on tid %llu %llu\n", inode, ++ ceph_vinop(inode), req1 ? req1->r_tid : 0ULL, ++ req2 ? req2->r_tid : 0ULL); + if (req1) { + ret = !wait_for_completion_timeout(&req1->r_safe_completion, + ceph_timeout_jiffies(req1->r_timeout)); +@@ -2431,11 +2482,13 @@ int ceph_fsync(struct file *file, loff_t + { + struct inode *inode = file->f_mapping->host; + struct ceph_inode_info *ci = ceph_inode(inode); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + u64 flush_tid; + int ret, err; + int dirty; + +- dout("fsync %p%s\n", inode, datasync ? " datasync" : ""); ++ doutc(cl, "%p %llx.%llx%s\n", inode, ceph_vinop(inode), ++ datasync ? " datasync" : ""); + + ret = file_write_and_wait_range(file, start, end); + if (datasync) +@@ -2446,7 +2499,7 @@ int ceph_fsync(struct file *file, loff_t + goto out; + + dirty = try_flush_caps(inode, &flush_tid); +- dout("fsync dirty caps are %s\n", ceph_cap_string(dirty)); ++ doutc(cl, "dirty caps are %s\n", ceph_cap_string(dirty)); + + err = flush_mdlog_and_wait_inode_unsafe_requests(inode); + +@@ -2467,7 +2520,8 @@ int ceph_fsync(struct file *file, loff_t + if (err < 0) + ret = err; + out: +- dout("fsync %p%s result=%d\n", inode, datasync ? " datasync" : "", ret); ++ doutc(cl, "%p %llx.%llx%s result=%d\n", inode, ceph_vinop(inode), ++ datasync ? " datasync" : "", ret); + return ret; + } + +@@ -2480,12 +2534,13 @@ out: + int ceph_write_inode(struct inode *inode, struct writeback_control *wbc) + { + struct ceph_inode_info *ci = ceph_inode(inode); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + u64 flush_tid; + int err = 0; + int dirty; + int wait = (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync); + +- dout("write_inode %p wait=%d\n", inode, wait); ++ doutc(cl, "%p %llx.%llx wait=%d\n", inode, ceph_vinop(inode), wait); + ceph_fscache_unpin_writeback(inode, wbc); + if (wait) { + err = ceph_wait_on_async_create(inode); +@@ -2515,6 +2570,7 @@ static void __kick_flushing_caps(struct + __acquires(ci->i_ceph_lock) + { + struct inode *inode = &ci->netfs.inode; ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_cap *cap; + struct ceph_cap_flush *cf; + int ret; +@@ -2540,8 +2596,8 @@ static void __kick_flushing_caps(struct + + cap = ci->i_auth_cap; + if (!(cap && cap->session == session)) { +- pr_err("%p auth cap %p not mds%d ???\n", +- inode, cap, session->s_mds); ++ pr_err_client(cl, "%p auth cap %p not mds%d ???\n", ++ inode, cap, session->s_mds); + break; + } + +@@ -2550,8 +2606,9 @@ static void __kick_flushing_caps(struct + if (!cf->is_capsnap) { + struct cap_msg_args arg; + +- dout("kick_flushing_caps %p cap %p tid %llu %s\n", +- inode, cap, cf->tid, ceph_cap_string(cf->caps)); ++ doutc(cl, "%p %llx.%llx cap %p tid %llu %s\n", ++ inode, ceph_vinop(inode), cap, cf->tid, ++ ceph_cap_string(cf->caps)); + __prep_cap(&arg, cap, CEPH_CAP_OP_FLUSH, + (cf->tid < last_snap_flush ? + CEPH_CLIENT_CAPS_PENDING_CAPSNAP : 0), +@@ -2565,9 +2622,9 @@ static void __kick_flushing_caps(struct + struct ceph_cap_snap *capsnap = + container_of(cf, struct ceph_cap_snap, + cap_flush); +- dout("kick_flushing_caps %p capsnap %p tid %llu %s\n", +- inode, capsnap, cf->tid, +- ceph_cap_string(capsnap->dirty)); ++ doutc(cl, "%p %llx.%llx capsnap %p tid %llu %s\n", ++ inode, ceph_vinop(inode), capsnap, cf->tid, ++ ceph_cap_string(capsnap->dirty)); + + refcount_inc(&capsnap->nref); + spin_unlock(&ci->i_ceph_lock); +@@ -2575,11 +2632,10 @@ static void __kick_flushing_caps(struct + ret = __send_flush_snap(inode, session, capsnap, cap->mseq, + oldest_flush_tid); + if (ret < 0) { +- pr_err("kick_flushing_caps: error sending " +- "cap flushsnap, ino (%llx.%llx) " +- "tid %llu follows %llu\n", +- ceph_vinop(inode), cf->tid, +- capsnap->follows); ++ pr_err_client(cl, "error sending cap flushsnap," ++ " %p %llx.%llx tid %llu follows %llu\n", ++ inode, ceph_vinop(inode), cf->tid, ++ capsnap->follows); + } + + ceph_put_cap_snap(capsnap); +@@ -2592,22 +2648,26 @@ static void __kick_flushing_caps(struct + void ceph_early_kick_flushing_caps(struct ceph_mds_client *mdsc, + struct ceph_mds_session *session) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_inode_info *ci; + struct ceph_cap *cap; + u64 oldest_flush_tid; + +- dout("early_kick_flushing_caps mds%d\n", session->s_mds); ++ doutc(cl, "mds%d\n", session->s_mds); + + spin_lock(&mdsc->cap_dirty_lock); + oldest_flush_tid = __get_oldest_flush_tid(mdsc); + spin_unlock(&mdsc->cap_dirty_lock); + + list_for_each_entry(ci, &session->s_cap_flushing, i_flushing_item) { ++ struct inode *inode = &ci->netfs.inode; ++ + spin_lock(&ci->i_ceph_lock); + cap = ci->i_auth_cap; + if (!(cap && cap->session == session)) { +- pr_err("%p auth cap %p not mds%d ???\n", +- &ci->netfs.inode, cap, session->s_mds); ++ pr_err_client(cl, "%p %llx.%llx auth cap %p not mds%d ???\n", ++ inode, ceph_vinop(inode), cap, ++ session->s_mds); + spin_unlock(&ci->i_ceph_lock); + continue; + } +@@ -2640,24 +2700,28 @@ void ceph_early_kick_flushing_caps(struc + void ceph_kick_flushing_caps(struct ceph_mds_client *mdsc, + struct ceph_mds_session *session) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_inode_info *ci; + struct ceph_cap *cap; + u64 oldest_flush_tid; + + lockdep_assert_held(&session->s_mutex); + +- dout("kick_flushing_caps mds%d\n", session->s_mds); ++ doutc(cl, "mds%d\n", session->s_mds); + + spin_lock(&mdsc->cap_dirty_lock); + oldest_flush_tid = __get_oldest_flush_tid(mdsc); + spin_unlock(&mdsc->cap_dirty_lock); + + list_for_each_entry(ci, &session->s_cap_flushing, i_flushing_item) { ++ struct inode *inode = &ci->netfs.inode; ++ + spin_lock(&ci->i_ceph_lock); + cap = ci->i_auth_cap; + if (!(cap && cap->session == session)) { +- pr_err("%p auth cap %p not mds%d ???\n", +- &ci->netfs.inode, cap, session->s_mds); ++ pr_err_client(cl, "%p %llx.%llx auth cap %p not mds%d ???\n", ++ inode, ceph_vinop(inode), cap, ++ session->s_mds); + spin_unlock(&ci->i_ceph_lock); + continue; + } +@@ -2674,11 +2738,13 @@ void ceph_kick_flushing_inode_caps(struc + { + struct ceph_mds_client *mdsc = session->s_mdsc; + struct ceph_cap *cap = ci->i_auth_cap; ++ struct inode *inode = &ci->netfs.inode; + + lockdep_assert_held(&ci->i_ceph_lock); + +- dout("%s %p flushing %s\n", __func__, &ci->netfs.inode, +- ceph_cap_string(ci->i_flushing_caps)); ++ doutc(mdsc->fsc->client, "%p %llx.%llx flushing %s\n", ++ inode, ceph_vinop(inode), ++ ceph_cap_string(ci->i_flushing_caps)); + + if (!list_empty(&ci->i_cap_flush_list)) { + u64 oldest_flush_tid; +@@ -2700,6 +2766,9 @@ void ceph_kick_flushing_inode_caps(struc + void ceph_take_cap_refs(struct ceph_inode_info *ci, int got, + bool snap_rwsem_locked) + { ++ struct inode *inode = &ci->netfs.inode; ++ struct ceph_client *cl = ceph_inode_to_client(inode); ++ + lockdep_assert_held(&ci->i_ceph_lock); + + if (got & CEPH_CAP_PIN) +@@ -2720,10 +2789,10 @@ void ceph_take_cap_refs(struct ceph_inod + } + if (got & CEPH_CAP_FILE_BUFFER) { + if (ci->i_wb_ref == 0) +- ihold(&ci->netfs.inode); ++ ihold(inode); + ci->i_wb_ref++; +- dout("%s %p wb %d -> %d (?)\n", __func__, +- &ci->netfs.inode, ci->i_wb_ref-1, ci->i_wb_ref); ++ doutc(cl, "%p %llx.%llx wb %d -> %d (?)\n", inode, ++ ceph_vinop(inode), ci->i_wb_ref-1, ci->i_wb_ref); + } + } + +@@ -2751,19 +2820,22 @@ static int try_get_cap_refs(struct inode + { + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + int ret = 0; + int have, implemented; + bool snap_rwsem_locked = false; + +- dout("get_cap_refs %p need %s want %s\n", inode, +- ceph_cap_string(need), ceph_cap_string(want)); ++ doutc(cl, "%p %llx.%llx need %s want %s\n", inode, ++ ceph_vinop(inode), ceph_cap_string(need), ++ ceph_cap_string(want)); + + again: + spin_lock(&ci->i_ceph_lock); + + if ((flags & CHECK_FILELOCK) && + (ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK)) { +- dout("try_get_cap_refs %p error filelock\n", inode); ++ doutc(cl, "%p %llx.%llx error filelock\n", inode, ++ ceph_vinop(inode)); + ret = -EIO; + goto out_unlock; + } +@@ -2783,8 +2855,8 @@ again: + + if (have & need & CEPH_CAP_FILE_WR) { + if (endoff >= 0 && endoff > (loff_t)ci->i_max_size) { +- dout("get_cap_refs %p endoff %llu > maxsize %llu\n", +- inode, endoff, ci->i_max_size); ++ doutc(cl, "%p %llx.%llx endoff %llu > maxsize %llu\n", ++ inode, ceph_vinop(inode), endoff, ci->i_max_size); + if (endoff > ci->i_requested_max_size) + ret = ci->i_auth_cap ? -EFBIG : -EUCLEAN; + goto out_unlock; +@@ -2794,7 +2866,8 @@ again: + * can get a final snapshot value for size+mtime. + */ + if (__ceph_have_pending_cap_snap(ci)) { +- dout("get_cap_refs %p cap_snap_pending\n", inode); ++ doutc(cl, "%p %llx.%llx cap_snap_pending\n", inode, ++ ceph_vinop(inode)); + goto out_unlock; + } + } +@@ -2812,9 +2885,9 @@ again: + int not = want & ~(have & need); + int revoking = implemented & ~have; + int exclude = revoking & not; +- dout("get_cap_refs %p have %s but not %s (revoking %s)\n", +- inode, ceph_cap_string(have), ceph_cap_string(not), +- ceph_cap_string(revoking)); ++ doutc(cl, "%p %llx.%llx have %s but not %s (revoking %s)\n", ++ inode, ceph_vinop(inode), ceph_cap_string(have), ++ ceph_cap_string(not), ceph_cap_string(revoking)); + if (!exclude || !(exclude & CEPH_CAP_FILE_BUFFER)) { + if (!snap_rwsem_locked && + !ci->i_head_snapc && +@@ -2854,28 +2927,31 @@ again: + spin_unlock(&s->s_cap_lock); + } + if (session_readonly) { +- dout("get_cap_refs %p need %s but mds%d readonly\n", +- inode, ceph_cap_string(need), ci->i_auth_cap->mds); ++ doutc(cl, "%p %llx.%llx need %s but mds%d readonly\n", ++ inode, ceph_vinop(inode), ceph_cap_string(need), ++ ci->i_auth_cap->mds); + ret = -EROFS; + goto out_unlock; + } + + if (ceph_inode_is_shutdown(inode)) { +- dout("get_cap_refs %p inode is shutdown\n", inode); ++ doutc(cl, "%p %llx.%llx inode is shutdown\n", ++ inode, ceph_vinop(inode)); + ret = -ESTALE; + goto out_unlock; + } + mds_wanted = __ceph_caps_mds_wanted(ci, false); + if (need & ~mds_wanted) { +- dout("get_cap_refs %p need %s > mds_wanted %s\n", +- inode, ceph_cap_string(need), +- ceph_cap_string(mds_wanted)); ++ doutc(cl, "%p %llx.%llx need %s > mds_wanted %s\n", ++ inode, ceph_vinop(inode), ceph_cap_string(need), ++ ceph_cap_string(mds_wanted)); + ret = -EUCLEAN; + goto out_unlock; + } + +- dout("get_cap_refs %p have %s need %s\n", inode, +- ceph_cap_string(have), ceph_cap_string(need)); ++ doutc(cl, "%p %llx.%llx have %s need %s\n", inode, ++ ceph_vinop(inode), ceph_cap_string(have), ++ ceph_cap_string(need)); + } + out_unlock: + +@@ -2890,8 +2966,8 @@ out_unlock: + else if (ret == 1) + ceph_update_cap_hit(&mdsc->metric); + +- dout("get_cap_refs %p ret %d got %s\n", inode, +- ret, ceph_cap_string(*got)); ++ doutc(cl, "%p %llx.%llx ret %d got %s\n", inode, ++ ceph_vinop(inode), ret, ceph_cap_string(*got)); + return ret; + } + +@@ -2903,13 +2979,14 @@ out_unlock: + static void check_max_size(struct inode *inode, loff_t endoff) + { + struct ceph_inode_info *ci = ceph_inode(inode); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + int check = 0; + + /* do we need to explicitly request a larger max_size? */ + spin_lock(&ci->i_ceph_lock); + if (endoff >= ci->i_max_size && endoff > ci->i_wanted_max_size) { +- dout("write %p at large endoff %llu, req max_size\n", +- inode, endoff); ++ doutc(cl, "write %p %llx.%llx at large endoff %llu, req max_size\n", ++ inode, ceph_vinop(inode), endoff); + ci->i_wanted_max_size = endoff; + } + /* duplicate ceph_check_caps()'s logic */ +@@ -3119,10 +3196,12 @@ void ceph_get_cap_refs(struct ceph_inode + static int ceph_try_drop_cap_snap(struct ceph_inode_info *ci, + struct ceph_cap_snap *capsnap) + { ++ struct inode *inode = &ci->netfs.inode; ++ struct ceph_client *cl = ceph_inode_to_client(inode); ++ + if (!capsnap->need_flush && + !capsnap->writing && !capsnap->dirty_pages) { +- dout("dropping cap_snap %p follows %llu\n", +- capsnap, capsnap->follows); ++ doutc(cl, "%p follows %llu\n", capsnap, capsnap->follows); + BUG_ON(capsnap->cap_flush.tid > 0); + ceph_put_snap_context(capsnap->context); + if (!list_is_last(&capsnap->ci_item, &ci->i_cap_snaps)) +@@ -3154,6 +3233,7 @@ static void __ceph_put_cap_refs(struct c + enum put_cap_refs_mode mode) + { + struct inode *inode = &ci->netfs.inode; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + int last = 0, put = 0, flushsnaps = 0, wake = 0; + bool check_flushsnaps = false; + +@@ -3176,8 +3256,8 @@ static void __ceph_put_cap_refs(struct c + put++; + check_flushsnaps = true; + } +- dout("put_cap_refs %p wb %d -> %d (?)\n", +- inode, ci->i_wb_ref+1, ci->i_wb_ref); ++ doutc(cl, "%p %llx.%llx wb %d -> %d (?)\n", inode, ++ ceph_vinop(inode), ci->i_wb_ref+1, ci->i_wb_ref); + } + if (had & CEPH_CAP_FILE_WR) { + if (--ci->i_wr_ref == 0) { +@@ -3217,8 +3297,8 @@ static void __ceph_put_cap_refs(struct c + } + spin_unlock(&ci->i_ceph_lock); + +- dout("put_cap_refs %p had %s%s%s\n", inode, ceph_cap_string(had), +- last ? " last" : "", put ? " put" : ""); ++ doutc(cl, "%p %llx.%llx had %s%s%s\n", inode, ceph_vinop(inode), ++ ceph_cap_string(had), last ? " last" : "", put ? " put" : ""); + + switch (mode) { + case PUT_CAP_REFS_SYNC: +@@ -3268,6 +3348,7 @@ void ceph_put_wrbuffer_cap_refs(struct c + struct ceph_snap_context *snapc) + { + struct inode *inode = &ci->netfs.inode; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_cap_snap *capsnap = NULL, *iter; + int put = 0; + bool last = false; +@@ -3291,11 +3372,10 @@ void ceph_put_wrbuffer_cap_refs(struct c + ceph_put_snap_context(ci->i_head_snapc); + ci->i_head_snapc = NULL; + } +- dout("put_wrbuffer_cap_refs on %p head %d/%d -> %d/%d %s\n", +- inode, +- ci->i_wrbuffer_ref+nr, ci->i_wrbuffer_ref_head+nr, +- ci->i_wrbuffer_ref, ci->i_wrbuffer_ref_head, +- last ? " LAST" : ""); ++ doutc(cl, "on %p %llx.%llx head %d/%d -> %d/%d %s\n", ++ inode, ceph_vinop(inode), ci->i_wrbuffer_ref+nr, ++ ci->i_wrbuffer_ref_head+nr, ci->i_wrbuffer_ref, ++ ci->i_wrbuffer_ref_head, last ? " LAST" : ""); + } else { + list_for_each_entry(iter, &ci->i_cap_snaps, ci_item) { + if (iter->context == snapc) { +@@ -3325,13 +3405,12 @@ void ceph_put_wrbuffer_cap_refs(struct c + } + } + } +- dout("put_wrbuffer_cap_refs on %p cap_snap %p " +- " snap %lld %d/%d -> %d/%d %s%s\n", +- inode, capsnap, capsnap->context->seq, +- ci->i_wrbuffer_ref+nr, capsnap->dirty_pages + nr, +- ci->i_wrbuffer_ref, capsnap->dirty_pages, +- last ? " (wrbuffer last)" : "", +- complete_capsnap ? " (complete capsnap)" : ""); ++ doutc(cl, "%p %llx.%llx cap_snap %p snap %lld %d/%d -> %d/%d %s%s\n", ++ inode, ceph_vinop(inode), capsnap, capsnap->context->seq, ++ ci->i_wrbuffer_ref+nr, capsnap->dirty_pages + nr, ++ ci->i_wrbuffer_ref, capsnap->dirty_pages, ++ last ? " (wrbuffer last)" : "", ++ complete_capsnap ? " (complete capsnap)" : ""); + } + + unlock: +@@ -3354,9 +3433,10 @@ unlock: + */ + static void invalidate_aliases(struct inode *inode) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct dentry *dn, *prev = NULL; + +- dout("invalidate_aliases inode %p\n", inode); ++ doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode)); + d_prune_aliases(inode); + /* + * For non-directory inode, d_find_alias() only returns +@@ -3415,6 +3495,7 @@ static void handle_cap_grant(struct inod + __releases(ci->i_ceph_lock) + __releases(session->s_mdsc->snap_rwsem) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + int seq = le32_to_cpu(grant->seq); + int newcaps = le32_to_cpu(grant->caps); +@@ -3438,10 +3519,11 @@ static void handle_cap_grant(struct inod + if (IS_ENCRYPTED(inode) && size) + size = extra_info->fscrypt_file_size; + +- dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n", +- inode, cap, session->s_mds, seq, ceph_cap_string(newcaps)); +- dout(" size %llu max_size %llu, i_size %llu\n", size, max_size, +- i_size_read(inode)); ++ doutc(cl, "%p %llx.%llx cap %p mds%d seq %d %s\n", inode, ++ ceph_vinop(inode), cap, session->s_mds, seq, ++ ceph_cap_string(newcaps)); ++ doutc(cl, " size %llu max_size %llu, i_size %llu\n", size, ++ max_size, i_size_read(inode)); + + + /* +@@ -3501,15 +3583,17 @@ static void handle_cap_grant(struct inod + inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(grant->uid)); + inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(grant->gid)); + ci->i_btime = extra_info->btime; +- dout("%p mode 0%o uid.gid %d.%d\n", inode, inode->i_mode, +- from_kuid(&init_user_ns, inode->i_uid), +- from_kgid(&init_user_ns, inode->i_gid)); ++ doutc(cl, "%p %llx.%llx mode 0%o uid.gid %d.%d\n", inode, ++ ceph_vinop(inode), inode->i_mode, ++ from_kuid(&init_user_ns, inode->i_uid), ++ from_kgid(&init_user_ns, inode->i_gid)); + #if IS_ENABLED(CONFIG_FS_ENCRYPTION) + if (ci->fscrypt_auth_len != extra_info->fscrypt_auth_len || + memcmp(ci->fscrypt_auth, extra_info->fscrypt_auth, + ci->fscrypt_auth_len)) +- pr_warn_ratelimited("%s: cap grant attempt to change fscrypt_auth on non-I_NEW inode (old len %d new len %d)\n", +- __func__, ci->fscrypt_auth_len, ++ pr_warn_ratelimited_client(cl, ++ "cap grant attempt to change fscrypt_auth on non-I_NEW inode (old len %d new len %d)\n", ++ ci->fscrypt_auth_len, + extra_info->fscrypt_auth_len); + #endif + } +@@ -3527,8 +3611,8 @@ static void handle_cap_grant(struct inod + u64 version = le64_to_cpu(grant->xattr_version); + + if (version > ci->i_xattrs.version) { +- dout(" got new xattrs v%llu on %p len %d\n", +- version, inode, len); ++ doutc(cl, " got new xattrs v%llu on %p %llx.%llx len %d\n", ++ version, inode, ceph_vinop(inode), len); + if (ci->i_xattrs.blob) + ceph_buffer_put(ci->i_xattrs.blob); + ci->i_xattrs.blob = ceph_buffer_get(xattr_buf); +@@ -3579,8 +3663,8 @@ static void handle_cap_grant(struct inod + + if (ci->i_auth_cap == cap && (newcaps & CEPH_CAP_ANY_FILE_WR)) { + if (max_size != ci->i_max_size) { +- dout("max_size %lld -> %llu\n", +- ci->i_max_size, max_size); ++ doutc(cl, "max_size %lld -> %llu\n", ci->i_max_size, ++ max_size); + ci->i_max_size = max_size; + if (max_size >= ci->i_wanted_max_size) { + ci->i_wanted_max_size = 0; /* reset */ +@@ -3594,10 +3678,9 @@ static void handle_cap_grant(struct inod + wanted = __ceph_caps_wanted(ci); + used = __ceph_caps_used(ci); + dirty = __ceph_caps_dirty(ci); +- dout(" my wanted = %s, used = %s, dirty %s\n", +- ceph_cap_string(wanted), +- ceph_cap_string(used), +- ceph_cap_string(dirty)); ++ doutc(cl, " my wanted = %s, used = %s, dirty %s\n", ++ ceph_cap_string(wanted), ceph_cap_string(used), ++ ceph_cap_string(dirty)); + + if ((was_stale || le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) && + (wanted & ~(cap->mds_wanted | newcaps))) { +@@ -3618,10 +3701,9 @@ static void handle_cap_grant(struct inod + if (cap->issued & ~newcaps) { + int revoking = cap->issued & ~newcaps; + +- dout("revocation: %s -> %s (revoking %s)\n", +- ceph_cap_string(cap->issued), +- ceph_cap_string(newcaps), +- ceph_cap_string(revoking)); ++ doutc(cl, "revocation: %s -> %s (revoking %s)\n", ++ ceph_cap_string(cap->issued), ceph_cap_string(newcaps), ++ ceph_cap_string(revoking)); + if (S_ISREG(inode->i_mode) && + (revoking & used & CEPH_CAP_FILE_BUFFER)) + writeback = true; /* initiate writeback; will delay ack */ +@@ -3639,11 +3721,12 @@ static void handle_cap_grant(struct inod + cap->issued = newcaps; + cap->implemented |= newcaps; + } else if (cap->issued == newcaps) { +- dout("caps unchanged: %s -> %s\n", +- ceph_cap_string(cap->issued), ceph_cap_string(newcaps)); ++ doutc(cl, "caps unchanged: %s -> %s\n", ++ ceph_cap_string(cap->issued), ++ ceph_cap_string(newcaps)); + } else { +- dout("grant: %s -> %s\n", ceph_cap_string(cap->issued), +- ceph_cap_string(newcaps)); ++ doutc(cl, "grant: %s -> %s\n", ceph_cap_string(cap->issued), ++ ceph_cap_string(newcaps)); + /* non-auth MDS is revoking the newly grant caps ? */ + if (cap == ci->i_auth_cap && + __ceph_caps_revoking_other(ci, cap, newcaps)) +@@ -3732,6 +3815,7 @@ static void handle_cap_flush_ack(struct + { + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc; ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_cap_flush *cf, *tmp_cf; + LIST_HEAD(to_remove); + unsigned seq = le32_to_cpu(m->seq); +@@ -3768,11 +3852,11 @@ static void handle_cap_flush_ack(struct + } + } + +- dout("handle_cap_flush_ack inode %p mds%d seq %d on %s cleaned %s," +- " flushing %s -> %s\n", +- inode, session->s_mds, seq, ceph_cap_string(dirty), +- ceph_cap_string(cleaned), ceph_cap_string(ci->i_flushing_caps), +- ceph_cap_string(ci->i_flushing_caps & ~cleaned)); ++ doutc(cl, "%p %llx.%llx mds%d seq %d on %s cleaned %s, flushing %s -> %s\n", ++ inode, ceph_vinop(inode), session->s_mds, seq, ++ ceph_cap_string(dirty), ceph_cap_string(cleaned), ++ ceph_cap_string(ci->i_flushing_caps), ++ ceph_cap_string(ci->i_flushing_caps & ~cleaned)); + + if (list_empty(&to_remove) && !cleaned) + goto out; +@@ -3788,18 +3872,21 @@ static void handle_cap_flush_ack(struct + if (list_empty(&ci->i_cap_flush_list)) { + list_del_init(&ci->i_flushing_item); + if (!list_empty(&session->s_cap_flushing)) { +- dout(" mds%d still flushing cap on %p\n", +- session->s_mds, +- &list_first_entry(&session->s_cap_flushing, +- struct ceph_inode_info, +- i_flushing_item)->netfs.inode); ++ struct inode *inode = ++ &list_first_entry(&session->s_cap_flushing, ++ struct ceph_inode_info, ++ i_flushing_item)->netfs.inode; ++ doutc(cl, " mds%d still flushing cap on %p %llx.%llx\n", ++ session->s_mds, inode, ceph_vinop(inode)); + } + } + mdsc->num_cap_flushing--; +- dout(" inode %p now !flushing\n", inode); ++ doutc(cl, " %p %llx.%llx now !flushing\n", inode, ++ ceph_vinop(inode)); + + if (ci->i_dirty_caps == 0) { +- dout(" inode %p now clean\n", inode); ++ doutc(cl, " %p %llx.%llx now clean\n", inode, ++ ceph_vinop(inode)); + BUG_ON(!list_empty(&ci->i_dirty_item)); + drop = true; + if (ci->i_wr_ref == 0 && +@@ -3838,11 +3925,13 @@ void __ceph_remove_capsnap(struct inode + { + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc; ++ struct ceph_client *cl = mdsc->fsc->client; + bool ret; + + lockdep_assert_held(&ci->i_ceph_lock); + +- dout("removing capsnap %p, inode %p ci %p\n", capsnap, inode, ci); ++ doutc(cl, "removing capsnap %p, %p %llx.%llx ci %p\n", capsnap, ++ inode, ceph_vinop(inode), ci); + + list_del_init(&capsnap->ci_item); + ret = __detach_cap_flush_from_ci(ci, &capsnap->cap_flush); +@@ -3882,28 +3971,30 @@ static void handle_cap_flushsnap_ack(str + { + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc; ++ struct ceph_client *cl = mdsc->fsc->client; + u64 follows = le64_to_cpu(m->snap_follows); + struct ceph_cap_snap *capsnap = NULL, *iter; + bool wake_ci = false; + bool wake_mdsc = false; + +- dout("handle_cap_flushsnap_ack inode %p ci %p mds%d follows %lld\n", +- inode, ci, session->s_mds, follows); ++ doutc(cl, "%p %llx.%llx ci %p mds%d follows %lld\n", inode, ++ ceph_vinop(inode), ci, session->s_mds, follows); + + spin_lock(&ci->i_ceph_lock); + list_for_each_entry(iter, &ci->i_cap_snaps, ci_item) { + if (iter->follows == follows) { + if (iter->cap_flush.tid != flush_tid) { +- dout(" cap_snap %p follows %lld tid %lld !=" +- " %lld\n", iter, follows, +- flush_tid, iter->cap_flush.tid); ++ doutc(cl, " cap_snap %p follows %lld " ++ "tid %lld != %lld\n", iter, ++ follows, flush_tid, ++ iter->cap_flush.tid); + break; + } + capsnap = iter; + break; + } else { +- dout(" skipping cap_snap %p follows %lld\n", +- iter, iter->follows); ++ doutc(cl, " skipping cap_snap %p follows %lld\n", ++ iter, iter->follows); + } + } + if (capsnap) +@@ -3932,6 +4023,7 @@ static bool handle_cap_trunc(struct inod + struct cap_extra_info *extra_info) + { + struct ceph_inode_info *ci = ceph_inode(inode); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + int mds = session->s_mds; + int seq = le32_to_cpu(trunc->seq); + u32 truncate_seq = le32_to_cpu(trunc->truncate_seq); +@@ -3954,8 +4046,8 @@ static bool handle_cap_trunc(struct inod + if (IS_ENCRYPTED(inode) && size) + size = extra_info->fscrypt_file_size; + +- dout("%s inode %p mds%d seq %d to %lld truncate seq %d\n", +- __func__, inode, mds, seq, truncate_size, truncate_seq); ++ doutc(cl, "%p %llx.%llx mds%d seq %d to %lld truncate seq %d\n", ++ inode, ceph_vinop(inode), mds, seq, truncate_size, truncate_seq); + queue_trunc = ceph_fill_file_size(inode, issued, + truncate_seq, truncate_size, size); + return queue_trunc; +@@ -3974,6 +4066,7 @@ static void handle_cap_export(struct ino + struct ceph_mds_session *session) + { + struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc; ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_session *tsession = NULL; + struct ceph_cap *cap, *tcap, *new_cap = NULL; + struct ceph_inode_info *ci = ceph_inode(inode); +@@ -3993,8 +4086,8 @@ static void handle_cap_export(struct ino + target = -1; + } + +- dout("handle_cap_export inode %p ci %p mds%d mseq %d target %d\n", +- inode, ci, mds, mseq, target); ++ doutc(cl, "%p %llx.%llx ci %p mds%d mseq %d target %d\n", ++ inode, ceph_vinop(inode), ci, mds, mseq, target); + retry: + down_read(&mdsc->snap_rwsem); + spin_lock(&ci->i_ceph_lock); +@@ -4014,12 +4107,13 @@ retry: + + issued = cap->issued; + if (issued != cap->implemented) +- pr_err_ratelimited("handle_cap_export: issued != implemented: " +- "ino (%llx.%llx) mds%d seq %d mseq %d " +- "issued %s implemented %s\n", +- ceph_vinop(inode), mds, cap->seq, cap->mseq, +- ceph_cap_string(issued), +- ceph_cap_string(cap->implemented)); ++ pr_err_ratelimited_client(cl, "issued != implemented: " ++ "%p %llx.%llx mds%d seq %d mseq %d" ++ " issued %s implemented %s\n", ++ inode, ceph_vinop(inode), mds, ++ cap->seq, cap->mseq, ++ ceph_cap_string(issued), ++ ceph_cap_string(cap->implemented)); + + + tcap = __get_cap_for_mds(ci, target); +@@ -4027,7 +4121,8 @@ retry: + /* already have caps from the target */ + if (tcap->cap_id == t_cap_id && + ceph_seq_cmp(tcap->seq, t_seq) < 0) { +- dout(" updating import cap %p mds%d\n", tcap, target); ++ doutc(cl, " updating import cap %p mds%d\n", tcap, ++ target); + tcap->cap_id = t_cap_id; + tcap->seq = t_seq - 1; + tcap->issue_seq = t_seq - 1; +@@ -4108,6 +4203,7 @@ static void handle_cap_import(struct cep + struct ceph_cap **target_cap, int *old_issued) + { + struct ceph_inode_info *ci = ceph_inode(inode); ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_cap *cap, *ocap, *new_cap = NULL; + int mds = session->s_mds; + int issued; +@@ -4128,8 +4224,8 @@ static void handle_cap_import(struct cep + peer = -1; + } + +- dout("handle_cap_import inode %p ci %p mds%d mseq %d peer %d\n", +- inode, ci, mds, mseq, peer); ++ doutc(cl, "%p %llx.%llx ci %p mds%d mseq %d peer %d\n", ++ inode, ceph_vinop(inode), ci, mds, mseq, peer); + retry: + cap = __get_cap_for_mds(ci, mds); + if (!cap) { +@@ -4155,17 +4251,17 @@ retry: + + ocap = peer >= 0 ? __get_cap_for_mds(ci, peer) : NULL; + if (ocap && ocap->cap_id == p_cap_id) { +- dout(" remove export cap %p mds%d flags %d\n", +- ocap, peer, ph->flags); ++ doutc(cl, " remove export cap %p mds%d flags %d\n", ++ ocap, peer, ph->flags); + if ((ph->flags & CEPH_CAP_FLAG_AUTH) && + (ocap->seq != le32_to_cpu(ph->seq) || + ocap->mseq != le32_to_cpu(ph->mseq))) { +- pr_err_ratelimited("handle_cap_import: " +- "mismatched seq/mseq: ino (%llx.%llx) " +- "mds%d seq %d mseq %d importer mds%d " +- "has peer seq %d mseq %d\n", +- ceph_vinop(inode), peer, ocap->seq, +- ocap->mseq, mds, le32_to_cpu(ph->seq), ++ pr_err_ratelimited_client(cl, "mismatched seq/mseq: " ++ "%p %llx.%llx mds%d seq %d mseq %d" ++ " importer mds%d has peer seq %d mseq %d\n", ++ inode, ceph_vinop(inode), peer, ++ ocap->seq, ocap->mseq, mds, ++ le32_to_cpu(ph->seq), + le32_to_cpu(ph->mseq)); + } + ceph_remove_cap(mdsc, ocap, (ph->flags & CEPH_CAP_FLAG_RELEASE)); +@@ -4231,6 +4327,7 @@ void ceph_handle_caps(struct ceph_mds_se + struct ceph_msg *msg) + { + struct ceph_mds_client *mdsc = session->s_mdsc; ++ struct ceph_client *cl = mdsc->fsc->client; + struct inode *inode; + struct ceph_inode_info *ci; + struct ceph_cap *cap; +@@ -4249,7 +4346,7 @@ void ceph_handle_caps(struct ceph_mds_se + bool close_sessions = false; + bool do_cap_release = false; + +- dout("handle_caps from mds%d\n", session->s_mds); ++ doutc(cl, "from mds%d\n", session->s_mds); + + if (!ceph_inc_mds_stopping_blocker(mdsc, session)) + return; +@@ -4352,15 +4449,15 @@ void ceph_handle_caps(struct ceph_mds_se + + /* lookup ino */ + inode = ceph_find_inode(mdsc->fsc->sb, vino); +- dout(" op %s ino %llx.%llx inode %p\n", ceph_cap_op_name(op), vino.ino, +- vino.snap, inode); ++ doutc(cl, " op %s ino %llx.%llx inode %p\n", ceph_cap_op_name(op), ++ vino.ino, vino.snap, inode); + + mutex_lock(&session->s_mutex); +- dout(" mds%d seq %lld cap seq %u\n", session->s_mds, session->s_seq, +- (unsigned)seq); ++ doutc(cl, " mds%d seq %lld cap seq %u\n", session->s_mds, ++ session->s_seq, (unsigned)seq); + + if (!inode) { +- dout(" i don't have ino %llx\n", vino.ino); ++ doutc(cl, " i don't have ino %llx\n", vino.ino); + + switch (op) { + case CEPH_CAP_OP_IMPORT: +@@ -4415,9 +4512,9 @@ void ceph_handle_caps(struct ceph_mds_se + spin_lock(&ci->i_ceph_lock); + cap = __get_cap_for_mds(ceph_inode(inode), session->s_mds); + if (!cap) { +- dout(" no cap on %p ino %llx.%llx from mds%d\n", +- inode, ceph_ino(inode), ceph_snap(inode), +- session->s_mds); ++ doutc(cl, " no cap on %p ino %llx.%llx from mds%d\n", ++ inode, ceph_ino(inode), ceph_snap(inode), ++ session->s_mds); + spin_unlock(&ci->i_ceph_lock); + switch (op) { + case CEPH_CAP_OP_REVOKE: +@@ -4455,8 +4552,8 @@ void ceph_handle_caps(struct ceph_mds_se + + default: + spin_unlock(&ci->i_ceph_lock); +- pr_err("ceph_handle_caps: unknown cap op %d %s\n", op, +- ceph_cap_op_name(op)); ++ pr_err_client(cl, "unknown cap op %d %s\n", op, ++ ceph_cap_op_name(op)); + } + + done: +@@ -4497,7 +4594,7 @@ flush_cap_releases: + goto done; + + bad: +- pr_err("ceph_handle_caps: corrupt message\n"); ++ pr_err_client(cl, "corrupt message\n"); + ceph_msg_dump(msg); + goto out; + } +@@ -4511,6 +4608,7 @@ bad: + */ + unsigned long ceph_check_delayed_caps(struct ceph_mds_client *mdsc) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct inode *inode; + struct ceph_inode_info *ci; + struct ceph_mount_options *opt = mdsc->fsc->mount_options; +@@ -4518,14 +4616,14 @@ unsigned long ceph_check_delayed_caps(st + unsigned long loop_start = jiffies; + unsigned long delay = 0; + +- dout("check_delayed_caps\n"); ++ doutc(cl, "begin\n"); + spin_lock(&mdsc->cap_delay_lock); + while (!list_empty(&mdsc->cap_delay_list)) { + ci = list_first_entry(&mdsc->cap_delay_list, + struct ceph_inode_info, + i_cap_delay_list); + if (time_before(loop_start, ci->i_hold_caps_max - delay_max)) { +- dout("%s caps added recently. Exiting loop", __func__); ++ doutc(cl, "caps added recently. Exiting loop"); + delay = ci->i_hold_caps_max; + break; + } +@@ -4537,13 +4635,15 @@ unsigned long ceph_check_delayed_caps(st + inode = igrab(&ci->netfs.inode); + if (inode) { + spin_unlock(&mdsc->cap_delay_lock); +- dout("check_delayed_caps on %p\n", inode); ++ doutc(cl, "on %p %llx.%llx\n", inode, ++ ceph_vinop(inode)); + ceph_check_caps(ci, 0); + iput(inode); + spin_lock(&mdsc->cap_delay_lock); + } + } + spin_unlock(&mdsc->cap_delay_lock); ++ doutc(cl, "done\n"); + + return delay; + } +@@ -4554,17 +4654,18 @@ unsigned long ceph_check_delayed_caps(st + static void flush_dirty_session_caps(struct ceph_mds_session *s) + { + struct ceph_mds_client *mdsc = s->s_mdsc; ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_inode_info *ci; + struct inode *inode; + +- dout("flush_dirty_caps\n"); ++ doutc(cl, "begin\n"); + spin_lock(&mdsc->cap_dirty_lock); + while (!list_empty(&s->s_cap_dirty)) { + ci = list_first_entry(&s->s_cap_dirty, struct ceph_inode_info, + i_dirty_item); + inode = &ci->netfs.inode; + ihold(inode); +- dout("flush_dirty_caps %llx.%llx\n", ceph_vinop(inode)); ++ doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode)); + spin_unlock(&mdsc->cap_dirty_lock); + ceph_wait_on_async_create(inode); + ceph_check_caps(ci, CHECK_CAPS_FLUSH); +@@ -4572,7 +4673,7 @@ static void flush_dirty_session_caps(str + spin_lock(&mdsc->cap_dirty_lock); + } + spin_unlock(&mdsc->cap_dirty_lock); +- dout("flush_dirty_caps done\n"); ++ doutc(cl, "done\n"); + } + + void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc) +@@ -4697,6 +4798,7 @@ int ceph_encode_inode_release(void **p, + int mds, int drop, int unless, int force) + { + struct ceph_inode_info *ci = ceph_inode(inode); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_cap *cap; + struct ceph_mds_request_release *rel = *p; + int used, dirty; +@@ -4706,9 +4808,9 @@ int ceph_encode_inode_release(void **p, + used = __ceph_caps_used(ci); + dirty = __ceph_caps_dirty(ci); + +- dout("encode_inode_release %p mds%d used|dirty %s drop %s unless %s\n", +- inode, mds, ceph_cap_string(used|dirty), ceph_cap_string(drop), +- ceph_cap_string(unless)); ++ doutc(cl, "%p %llx.%llx mds%d used|dirty %s drop %s unless %s\n", ++ inode, ceph_vinop(inode), mds, ceph_cap_string(used|dirty), ++ ceph_cap_string(drop), ceph_cap_string(unless)); + + /* only drop unused, clean caps */ + drop &= ~(used | dirty); +@@ -4730,12 +4832,13 @@ int ceph_encode_inode_release(void **p, + if (force || (cap->issued & drop)) { + if (cap->issued & drop) { + int wanted = __ceph_caps_wanted(ci); +- dout("encode_inode_release %p cap %p " +- "%s -> %s, wanted %s -> %s\n", inode, cap, +- ceph_cap_string(cap->issued), +- ceph_cap_string(cap->issued & ~drop), +- ceph_cap_string(cap->mds_wanted), +- ceph_cap_string(wanted)); ++ doutc(cl, "%p %llx.%llx cap %p %s -> %s, " ++ "wanted %s -> %s\n", inode, ++ ceph_vinop(inode), cap, ++ ceph_cap_string(cap->issued), ++ ceph_cap_string(cap->issued & ~drop), ++ ceph_cap_string(cap->mds_wanted), ++ ceph_cap_string(wanted)); + + cap->issued &= ~drop; + cap->implemented &= ~drop; +@@ -4744,9 +4847,9 @@ int ceph_encode_inode_release(void **p, + !(wanted & CEPH_CAP_ANY_FILE_WR)) + ci->i_requested_max_size = 0; + } else { +- dout("encode_inode_release %p cap %p %s" +- " (force)\n", inode, cap, +- ceph_cap_string(cap->issued)); ++ doutc(cl, "%p %llx.%llx cap %p %s (force)\n", ++ inode, ceph_vinop(inode), cap, ++ ceph_cap_string(cap->issued)); + } + + rel->ino = cpu_to_le64(ceph_ino(inode)); +@@ -4761,8 +4864,9 @@ int ceph_encode_inode_release(void **p, + *p += sizeof(*rel); + ret = 1; + } else { +- dout("encode_inode_release %p cap %p %s (noop)\n", +- inode, cap, ceph_cap_string(cap->issued)); ++ doutc(cl, "%p %llx.%llx cap %p %s (noop)\n", ++ inode, ceph_vinop(inode), cap, ++ ceph_cap_string(cap->issued)); + } + } + spin_unlock(&ci->i_ceph_lock); +@@ -4787,6 +4891,7 @@ int ceph_encode_dentry_release(void **p, + { + struct ceph_mds_request_release *rel = *p; + struct ceph_dentry_info *di = ceph_dentry(dentry); ++ struct ceph_client *cl; + int force = 0; + int ret; + +@@ -4806,10 +4911,11 @@ int ceph_encode_dentry_release(void **p, + + ret = ceph_encode_inode_release(p, dir, mds, drop, unless, force); + ++ cl = ceph_inode_to_client(dir); + spin_lock(&dentry->d_lock); + if (ret && di->lease_session && di->lease_session->s_mds == mds) { +- dout("encode_dentry_release %p mds%d seq %d\n", +- dentry, mds, (int)di->lease_seq); ++ doutc(cl, "%p mds%d seq %d\n", dentry, mds, ++ (int)di->lease_seq); + rel->dname_seq = cpu_to_le32(di->lease_seq); + __ceph_mdsc_drop_dentry_lease(dentry); + spin_unlock(&dentry->d_lock); +@@ -4835,12 +4941,14 @@ int ceph_encode_dentry_release(void **p, + static int remove_capsnaps(struct ceph_mds_client *mdsc, struct inode *inode) + { + struct ceph_inode_info *ci = ceph_inode(inode); ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_cap_snap *capsnap; + int capsnap_release = 0; + + lockdep_assert_held(&ci->i_ceph_lock); + +- dout("removing capsnaps, ci is %p, inode is %p\n", ci, inode); ++ doutc(cl, "removing capsnaps, ci is %p, %p %llx.%llx\n", ++ ci, inode, ceph_vinop(inode)); + + while (!list_empty(&ci->i_cap_snaps)) { + capsnap = list_first_entry(&ci->i_cap_snaps, +@@ -4859,6 +4967,7 @@ int ceph_purge_inode_cap(struct inode *i + { + struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode); + struct ceph_mds_client *mdsc = fsc->mdsc; ++ struct ceph_client *cl = fsc->client; + struct ceph_inode_info *ci = ceph_inode(inode); + bool is_auth; + bool dirty_dropped = false; +@@ -4866,8 +4975,8 @@ int ceph_purge_inode_cap(struct inode *i + + lockdep_assert_held(&ci->i_ceph_lock); + +- dout("removing cap %p, ci is %p, inode is %p\n", +- cap, ci, &ci->netfs.inode); ++ doutc(cl, "removing cap %p, ci is %p, %p %llx.%llx\n", ++ cap, ci, inode, ceph_vinop(inode)); + + is_auth = (cap == ci->i_auth_cap); + __ceph_remove_cap(cap, false); +@@ -4894,19 +5003,19 @@ int ceph_purge_inode_cap(struct inode *i + } + + if (!list_empty(&ci->i_dirty_item)) { +- pr_warn_ratelimited( +- " dropping dirty %s state for %p %lld\n", ++ pr_warn_ratelimited_client(cl, ++ " dropping dirty %s state for %p %llx.%llx\n", + ceph_cap_string(ci->i_dirty_caps), +- inode, ceph_ino(inode)); ++ inode, ceph_vinop(inode)); + ci->i_dirty_caps = 0; + list_del_init(&ci->i_dirty_item); + dirty_dropped = true; + } + if (!list_empty(&ci->i_flushing_item)) { +- pr_warn_ratelimited( +- " dropping dirty+flushing %s state for %p %lld\n", ++ pr_warn_ratelimited_client(cl, ++ " dropping dirty+flushing %s state for %p %llx.%llx\n", + ceph_cap_string(ci->i_flushing_caps), +- inode, ceph_ino(inode)); ++ inode, ceph_vinop(inode)); + ci->i_flushing_caps = 0; + list_del_init(&ci->i_flushing_item); + mdsc->num_cap_flushing--; +@@ -4929,8 +5038,9 @@ int ceph_purge_inode_cap(struct inode *i + if (atomic_read(&ci->i_filelock_ref) > 0) { + /* make further file lock syscall return -EIO */ + ci->i_ceph_flags |= CEPH_I_ERROR_FILELOCK; +- pr_warn_ratelimited(" dropping file locks for %p %lld\n", +- inode, ceph_ino(inode)); ++ pr_warn_ratelimited_client(cl, ++ " dropping file locks for %p %llx.%llx\n", ++ inode, ceph_vinop(inode)); + } + + if (!ci->i_dirty_caps && ci->i_prealloc_cap_flush) { +--- a/fs/ceph/crypto.c ++++ b/fs/ceph/crypto.c +@@ -211,6 +211,7 @@ void ceph_fscrypt_as_ctx_to_req(struct c + static struct inode *parse_longname(const struct inode *parent, + const char *name, int *name_len) + { ++ struct ceph_client *cl = ceph_inode_to_client(parent); + struct inode *dir = NULL; + struct ceph_vino vino = { .snap = CEPH_NOSNAP }; + char *inode_number; +@@ -222,12 +223,12 @@ static struct inode *parse_longname(cons + name++; + name_end = strrchr(name, '_'); + if (!name_end) { +- dout("Failed to parse long snapshot name: %s\n", name); ++ doutc(cl, "failed to parse long snapshot name: %s\n", name); + return ERR_PTR(-EIO); + } + *name_len = (name_end - name); + if (*name_len <= 0) { +- pr_err("Failed to parse long snapshot name\n"); ++ pr_err_client(cl, "failed to parse long snapshot name\n"); + return ERR_PTR(-EIO); + } + +@@ -239,7 +240,7 @@ static struct inode *parse_longname(cons + return ERR_PTR(-ENOMEM); + ret = kstrtou64(inode_number, 10, &vino.ino); + if (ret) { +- dout("Failed to parse inode number: %s\n", name); ++ doutc(cl, "failed to parse inode number: %s\n", name); + dir = ERR_PTR(ret); + goto out; + } +@@ -250,7 +251,7 @@ static struct inode *parse_longname(cons + /* This can happen if we're not mounting cephfs on the root */ + dir = ceph_get_inode(parent->i_sb, vino, NULL); + if (IS_ERR(dir)) +- dout("Can't find inode %s (%s)\n", inode_number, name); ++ doutc(cl, "can't find inode %s (%s)\n", inode_number, name); + } + + out: +@@ -261,6 +262,7 @@ out: + int ceph_encode_encrypted_dname(struct inode *parent, struct qstr *d_name, + char *buf) + { ++ struct ceph_client *cl = ceph_inode_to_client(parent); + struct inode *dir = parent; + struct qstr iname; + u32 len; +@@ -329,7 +331,7 @@ int ceph_encode_encrypted_dname(struct i + + /* base64 encode the encrypted name */ + elen = ceph_base64_encode(cryptbuf, len, buf); +- dout("base64-encoded ciphertext name = %.*s\n", elen, buf); ++ doutc(cl, "base64-encoded ciphertext name = %.*s\n", elen, buf); + + /* To understand the 240 limit, see CEPH_NOHASH_NAME_MAX comments */ + WARN_ON(elen > 240); +@@ -504,7 +506,10 @@ int ceph_fscrypt_decrypt_block_inplace(c + struct page *page, unsigned int len, + unsigned int offs, u64 lblk_num) + { +- dout("%s: len %u offs %u blk %llu\n", __func__, len, offs, lblk_num); ++ struct ceph_client *cl = ceph_inode_to_client(inode); ++ ++ doutc(cl, "%p %llx.%llx len %u offs %u blk %llu\n", inode, ++ ceph_vinop(inode), len, offs, lblk_num); + return fscrypt_decrypt_block_inplace(inode, page, len, offs, lblk_num); + } + +@@ -513,7 +518,10 @@ int ceph_fscrypt_encrypt_block_inplace(c + unsigned int offs, u64 lblk_num, + gfp_t gfp_flags) + { +- dout("%s: len %u offs %u blk %llu\n", __func__, len, offs, lblk_num); ++ struct ceph_client *cl = ceph_inode_to_client(inode); ++ ++ doutc(cl, "%p %llx.%llx len %u offs %u blk %llu\n", inode, ++ ceph_vinop(inode), len, offs, lblk_num); + return fscrypt_encrypt_block_inplace(inode, page, len, offs, lblk_num, + gfp_flags); + } +@@ -582,6 +590,7 @@ int ceph_fscrypt_decrypt_extents(struct + u64 off, struct ceph_sparse_extent *map, + u32 ext_cnt) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + int i, ret = 0; + struct ceph_inode_info *ci = ceph_inode(inode); + u64 objno, objoff; +@@ -589,7 +598,8 @@ int ceph_fscrypt_decrypt_extents(struct + + /* Nothing to do for empty array */ + if (ext_cnt == 0) { +- dout("%s: empty array, ret 0\n", __func__); ++ doutc(cl, "%p %llx.%llx empty array, ret 0\n", inode, ++ ceph_vinop(inode)); + return 0; + } + +@@ -603,14 +613,17 @@ int ceph_fscrypt_decrypt_extents(struct + int fret; + + if ((ext->off | ext->len) & ~CEPH_FSCRYPT_BLOCK_MASK) { +- pr_warn("%s: bad encrypted sparse extent idx %d off %llx len %llx\n", +- __func__, i, ext->off, ext->len); ++ pr_warn_client(cl, ++ "%p %llx.%llx bad encrypted sparse extent " ++ "idx %d off %llx len %llx\n", ++ inode, ceph_vinop(inode), i, ext->off, ++ ext->len); + return -EIO; + } + fret = ceph_fscrypt_decrypt_pages(inode, &page[pgidx], + off + pgsoff, ext->len); +- dout("%s: [%d] 0x%llx~0x%llx fret %d\n", __func__, i, +- ext->off, ext->len, fret); ++ doutc(cl, "%p %llx.%llx [%d] 0x%llx~0x%llx fret %d\n", inode, ++ ceph_vinop(inode), i, ext->off, ext->len, fret); + if (fret < 0) { + if (ret == 0) + ret = fret; +@@ -618,7 +631,7 @@ int ceph_fscrypt_decrypt_extents(struct + } + ret = pgsoff + fret; + } +- dout("%s: ret %d\n", __func__, ret); ++ doutc(cl, "ret %d\n", ret); + return ret; + } + +--- a/fs/ceph/debugfs.c ++++ b/fs/ceph/debugfs.c +@@ -398,7 +398,7 @@ DEFINE_SIMPLE_ATTRIBUTE(congestion_kb_fo + + void ceph_fs_debugfs_cleanup(struct ceph_fs_client *fsc) + { +- dout("ceph_fs_debugfs_cleanup\n"); ++ doutc(fsc->client, "begin\n"); + debugfs_remove(fsc->debugfs_bdi); + debugfs_remove(fsc->debugfs_congestion_kb); + debugfs_remove(fsc->debugfs_mdsmap); +@@ -407,13 +407,14 @@ void ceph_fs_debugfs_cleanup(struct ceph + debugfs_remove(fsc->debugfs_status); + debugfs_remove(fsc->debugfs_mdsc); + debugfs_remove_recursive(fsc->debugfs_metrics_dir); ++ doutc(fsc->client, "done\n"); + } + + void ceph_fs_debugfs_init(struct ceph_fs_client *fsc) + { + char name[100]; + +- dout("ceph_fs_debugfs_init\n"); ++ doutc(fsc->client, "begin\n"); + fsc->debugfs_congestion_kb = + debugfs_create_file("writeback_congestion_kb", + 0600, +@@ -469,6 +470,7 @@ void ceph_fs_debugfs_init(struct ceph_fs + &metrics_size_fops); + debugfs_create_file("caps", 0400, fsc->debugfs_metrics_dir, fsc, + &metrics_caps_fops); ++ doutc(fsc->client, "done\n"); + } + + +--- a/fs/ceph/dir.c ++++ b/fs/ceph/dir.c +@@ -109,7 +109,9 @@ static int fpos_cmp(loff_t l, loff_t r) + * regardless of what dir changes take place on the + * server. + */ +-static int note_last_dentry(struct ceph_dir_file_info *dfi, const char *name, ++static int note_last_dentry(struct ceph_fs_client *fsc, ++ struct ceph_dir_file_info *dfi, ++ const char *name, + int len, unsigned next_offset) + { + char *buf = kmalloc(len+1, GFP_KERNEL); +@@ -120,7 +122,7 @@ static int note_last_dentry(struct ceph_ + memcpy(dfi->last_name, name, len); + dfi->last_name[len] = 0; + dfi->next_offset = next_offset; +- dout("note_last_dentry '%s'\n", dfi->last_name); ++ doutc(fsc->client, "'%s'\n", dfi->last_name); + return 0; + } + +@@ -130,6 +132,7 @@ __dcache_find_get_entry(struct dentry *p + struct ceph_readdir_cache_control *cache_ctl) + { + struct inode *dir = d_inode(parent); ++ struct ceph_client *cl = ceph_inode_to_client(dir); + struct dentry *dentry; + unsigned idx_mask = (PAGE_SIZE / sizeof(struct dentry *)) - 1; + loff_t ptr_pos = idx * sizeof(struct dentry *); +@@ -142,7 +145,7 @@ __dcache_find_get_entry(struct dentry *p + ceph_readdir_cache_release(cache_ctl); + cache_ctl->page = find_lock_page(&dir->i_data, ptr_pgoff); + if (!cache_ctl->page) { +- dout(" page %lu not found\n", ptr_pgoff); ++ doutc(cl, " page %lu not found\n", ptr_pgoff); + return ERR_PTR(-EAGAIN); + } + /* reading/filling the cache are serialized by +@@ -185,13 +188,16 @@ static int __dcache_readdir(struct file + struct ceph_dir_file_info *dfi = file->private_data; + struct dentry *parent = file->f_path.dentry; + struct inode *dir = d_inode(parent); ++ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(dir); ++ struct ceph_client *cl = ceph_inode_to_client(dir); + struct dentry *dentry, *last = NULL; + struct ceph_dentry_info *di; + struct ceph_readdir_cache_control cache_ctl = {}; + u64 idx = 0; + int err = 0; + +- dout("__dcache_readdir %p v%u at %llx\n", dir, (unsigned)shared_gen, ctx->pos); ++ doutc(cl, "%p %llx.%llx v%u at %llx\n", dir, ceph_vinop(dir), ++ (unsigned)shared_gen, ctx->pos); + + /* search start position */ + if (ctx->pos > 2) { +@@ -221,7 +227,8 @@ static int __dcache_readdir(struct file + dput(dentry); + } + +- dout("__dcache_readdir %p cache idx %llu\n", dir, idx); ++ doutc(cl, "%p %llx.%llx cache idx %llu\n", dir, ++ ceph_vinop(dir), idx); + } + + +@@ -257,8 +264,8 @@ static int __dcache_readdir(struct file + spin_unlock(&dentry->d_lock); + + if (emit_dentry) { +- dout(" %llx dentry %p %pd %p\n", di->offset, +- dentry, dentry, d_inode(dentry)); ++ doutc(cl, " %llx dentry %p %pd %p\n", di->offset, ++ dentry, dentry, d_inode(dentry)); + ctx->pos = di->offset; + if (!dir_emit(ctx, dentry->d_name.name, + dentry->d_name.len, ceph_present_inode(d_inode(dentry)), +@@ -281,7 +288,8 @@ out: + if (last) { + int ret; + di = ceph_dentry(last); +- ret = note_last_dentry(dfi, last->d_name.name, last->d_name.len, ++ ret = note_last_dentry(fsc, dfi, last->d_name.name, ++ last->d_name.len, + fpos_off(di->offset) + 1); + if (ret < 0) + err = ret; +@@ -312,18 +320,21 @@ static int ceph_readdir(struct file *fil + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode); + struct ceph_mds_client *mdsc = fsc->mdsc; ++ struct ceph_client *cl = fsc->client; + int i; + int err; + unsigned frag = -1; + struct ceph_mds_reply_info_parsed *rinfo; + +- dout("readdir %p file %p pos %llx\n", inode, file, ctx->pos); ++ doutc(cl, "%p %llx.%llx file %p pos %llx\n", inode, ++ ceph_vinop(inode), file, ctx->pos); + if (dfi->file_info.flags & CEPH_F_ATEND) + return 0; + + /* always start with . and .. */ + if (ctx->pos == 0) { +- dout("readdir off 0 -> '.'\n"); ++ doutc(cl, "%p %llx.%llx off 0 -> '.'\n", inode, ++ ceph_vinop(inode)); + if (!dir_emit(ctx, ".", 1, ceph_present_inode(inode), + inode->i_mode >> 12)) + return 0; +@@ -337,7 +348,8 @@ static int ceph_readdir(struct file *fil + ino = ceph_present_inode(dentry->d_parent->d_inode); + spin_unlock(&dentry->d_lock); + +- dout("readdir off 1 -> '..'\n"); ++ doutc(cl, "%p %llx.%llx off 1 -> '..'\n", inode, ++ ceph_vinop(inode)); + if (!dir_emit(ctx, "..", 2, ino, inode->i_mode >> 12)) + return 0; + ctx->pos = 2; +@@ -391,8 +403,8 @@ more: + frag = fpos_frag(ctx->pos); + } + +- dout("readdir fetching %llx.%llx frag %x offset '%s'\n", +- ceph_vinop(inode), frag, dfi->last_name); ++ doutc(cl, "fetching %p %llx.%llx frag %x offset '%s'\n", ++ inode, ceph_vinop(inode), frag, dfi->last_name); + req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS); + if (IS_ERR(req)) + return PTR_ERR(req); +@@ -446,12 +458,12 @@ more: + ceph_mdsc_put_request(req); + return err; + } +- dout("readdir got and parsed readdir result=%d on " +- "frag %x, end=%d, complete=%d, hash_order=%d\n", +- err, frag, +- (int)req->r_reply_info.dir_end, +- (int)req->r_reply_info.dir_complete, +- (int)req->r_reply_info.hash_order); ++ doutc(cl, "%p %llx.%llx got and parsed readdir result=%d" ++ "on frag %x, end=%d, complete=%d, hash_order=%d\n", ++ inode, ceph_vinop(inode), err, frag, ++ (int)req->r_reply_info.dir_end, ++ (int)req->r_reply_info.dir_complete, ++ (int)req->r_reply_info.hash_order); + + rinfo = &req->r_reply_info; + if (le32_to_cpu(rinfo->dir_dir->frag) != frag) { +@@ -481,7 +493,8 @@ more: + dfi->dir_ordered_count = req->r_dir_ordered_cnt; + } + } else { +- dout("readdir !did_prepopulate\n"); ++ doutc(cl, "%p %llx.%llx !did_prepopulate\n", inode, ++ ceph_vinop(inode)); + /* disable readdir cache */ + dfi->readdir_cache_idx = -1; + /* preclude from marking dir complete */ +@@ -494,8 +507,8 @@ more: + rinfo->dir_entries + (rinfo->dir_nr-1); + unsigned next_offset = req->r_reply_info.dir_end ? + 2 : (fpos_off(rde->offset) + 1); +- err = note_last_dentry(dfi, rde->name, rde->name_len, +- next_offset); ++ err = note_last_dentry(fsc, dfi, rde->name, ++ rde->name_len, next_offset); + if (err) { + ceph_mdsc_put_request(dfi->last_readdir); + dfi->last_readdir = NULL; +@@ -508,9 +521,9 @@ more: + } + + rinfo = &dfi->last_readdir->r_reply_info; +- dout("readdir frag %x num %d pos %llx chunk first %llx\n", +- dfi->frag, rinfo->dir_nr, ctx->pos, +- rinfo->dir_nr ? rinfo->dir_entries[0].offset : 0LL); ++ doutc(cl, "%p %llx.%llx frag %x num %d pos %llx chunk first %llx\n", ++ inode, ceph_vinop(inode), dfi->frag, rinfo->dir_nr, ctx->pos, ++ rinfo->dir_nr ? rinfo->dir_entries[0].offset : 0LL); + + i = 0; + /* search start position */ +@@ -530,8 +543,9 @@ more: + struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + i; + + if (rde->offset < ctx->pos) { +- pr_warn("%s: rde->offset 0x%llx ctx->pos 0x%llx\n", +- __func__, rde->offset, ctx->pos); ++ pr_warn_client(cl, ++ "%p %llx.%llx rde->offset 0x%llx ctx->pos 0x%llx\n", ++ inode, ceph_vinop(inode), rde->offset, ctx->pos); + return -EIO; + } + +@@ -539,9 +553,9 @@ more: + return -EIO; + + ctx->pos = rde->offset; +- dout("readdir (%d/%d) -> %llx '%.*s' %p\n", +- i, rinfo->dir_nr, ctx->pos, +- rde->name_len, rde->name, &rde->inode.in); ++ doutc(cl, "%p %llx.%llx (%d/%d) -> %llx '%.*s' %p\n", inode, ++ ceph_vinop(inode), i, rinfo->dir_nr, ctx->pos, ++ rde->name_len, rde->name, &rde->inode.in); + + if (!dir_emit(ctx, rde->name, rde->name_len, + ceph_present_ino(inode->i_sb, le64_to_cpu(rde->inode.in->ino)), +@@ -552,7 +566,7 @@ more: + * doesn't have enough memory, etc. So for next readdir + * it will continue. + */ +- dout("filldir stopping us...\n"); ++ doutc(cl, "filldir stopping us...\n"); + return 0; + } + +@@ -583,7 +597,8 @@ more: + kfree(dfi->last_name); + dfi->last_name = NULL; + } +- dout("readdir next frag is %x\n", frag); ++ doutc(cl, "%p %llx.%llx next frag is %x\n", inode, ++ ceph_vinop(inode), frag); + goto more; + } + dfi->file_info.flags |= CEPH_F_ATEND; +@@ -598,20 +613,23 @@ more: + spin_lock(&ci->i_ceph_lock); + if (dfi->dir_ordered_count == + atomic64_read(&ci->i_ordered_count)) { +- dout(" marking %p complete and ordered\n", inode); ++ doutc(cl, " marking %p %llx.%llx complete and ordered\n", ++ inode, ceph_vinop(inode)); + /* use i_size to track number of entries in + * readdir cache */ + BUG_ON(dfi->readdir_cache_idx < 0); + i_size_write(inode, dfi->readdir_cache_idx * + sizeof(struct dentry*)); + } else { +- dout(" marking %p complete\n", inode); ++ doutc(cl, " marking %llx.%llx complete\n", ++ ceph_vinop(inode)); + } + __ceph_dir_set_complete(ci, dfi->dir_release_count, + dfi->dir_ordered_count); + spin_unlock(&ci->i_ceph_lock); + } +- dout("readdir %p file %p done.\n", inode, file); ++ doutc(cl, "%p %llx.%llx file %p done.\n", inode, ceph_vinop(inode), ++ file); + return 0; + } + +@@ -657,6 +675,7 @@ static loff_t ceph_dir_llseek(struct fil + { + struct ceph_dir_file_info *dfi = file->private_data; + struct inode *inode = file->f_mapping->host; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + loff_t retval; + + inode_lock(inode); +@@ -676,7 +695,8 @@ static loff_t ceph_dir_llseek(struct fil + + if (offset >= 0) { + if (need_reset_readdir(dfi, offset)) { +- dout("dir_llseek dropping %p content\n", file); ++ doutc(cl, "%p %llx.%llx dropping %p content\n", ++ inode, ceph_vinop(inode), file); + reset_readdir(dfi); + } else if (is_hash_order(offset) && offset > file->f_pos) { + /* for hash offset, we don't know if a forward seek +@@ -705,6 +725,7 @@ struct dentry *ceph_handle_snapdir(struc + { + struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dentry->d_sb); + struct inode *parent = d_inode(dentry->d_parent); /* we hold i_rwsem */ ++ struct ceph_client *cl = ceph_inode_to_client(parent); + + /* .snap dir? */ + if (ceph_snap(parent) == CEPH_NOSNAP && +@@ -713,8 +734,9 @@ struct dentry *ceph_handle_snapdir(struc + struct inode *inode = ceph_get_snapdir(parent); + + res = d_splice_alias(inode, dentry); +- dout("ENOENT on snapdir %p '%pd', linking to snapdir %p. Spliced dentry %p\n", +- dentry, dentry, inode, res); ++ doutc(cl, "ENOENT on snapdir %p '%pd', linking to " ++ "snapdir %p %llx.%llx. Spliced dentry %p\n", ++ dentry, dentry, inode, ceph_vinop(inode), res); + if (res) + dentry = res; + } +@@ -735,12 +757,15 @@ struct dentry *ceph_handle_snapdir(struc + struct dentry *ceph_finish_lookup(struct ceph_mds_request *req, + struct dentry *dentry, int err) + { ++ struct ceph_client *cl = req->r_mdsc->fsc->client; ++ + if (err == -ENOENT) { + /* no trace? */ + err = 0; + if (!req->r_reply_info.head->is_dentry) { +- dout("ENOENT and no trace, dentry %p inode %p\n", +- dentry, d_inode(dentry)); ++ doutc(cl, ++ "ENOENT and no trace, dentry %p inode %llx.%llx\n", ++ dentry, ceph_vinop(d_inode(dentry))); + if (d_really_is_positive(dentry)) { + d_drop(dentry); + err = -ENOENT; +@@ -774,13 +799,14 @@ static struct dentry *ceph_lookup(struct + { + 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_client *cl = fsc->client; + struct ceph_mds_request *req; + int op; + int mask; + int err; + +- dout("lookup %p dentry %p '%pd'\n", +- dir, dentry, dentry); ++ doutc(cl, "%p %llx.%llx/'%pd' dentry %p\n", dir, ceph_vinop(dir), ++ dentry, dentry); + + if (dentry->d_name.len > NAME_MAX) + return ERR_PTR(-ENAMETOOLONG); +@@ -803,7 +829,8 @@ static struct dentry *ceph_lookup(struct + struct ceph_dentry_info *di = ceph_dentry(dentry); + + spin_lock(&ci->i_ceph_lock); +- dout(" dir %p flags are 0x%lx\n", dir, ci->i_ceph_flags); ++ doutc(cl, " dir %llx.%llx flags are 0x%lx\n", ++ ceph_vinop(dir), ci->i_ceph_flags); + if (strncmp(dentry->d_name.name, + fsc->mount_options->snapdir_name, + dentry->d_name.len) && +@@ -813,7 +840,8 @@ static struct dentry *ceph_lookup(struct + __ceph_caps_issued_mask_metric(ci, CEPH_CAP_FILE_SHARED, 1)) { + __ceph_touch_fmode(ci, mdsc, CEPH_FILE_MODE_RD); + spin_unlock(&ci->i_ceph_lock); +- dout(" dir %p complete, -ENOENT\n", dir); ++ doutc(cl, " dir %llx.%llx complete, -ENOENT\n", ++ ceph_vinop(dir)); + if (d_unhashed(dentry)) + d_add(dentry, NULL); + di->lease_shared_gen = atomic_read(&ci->i_shared_gen); +@@ -852,7 +880,7 @@ static struct dentry *ceph_lookup(struct + } + dentry = ceph_finish_lookup(req, dentry, err); + ceph_mdsc_put_request(req); /* will dput(dentry) */ +- dout("lookup result=%p\n", dentry); ++ doutc(cl, "result=%p\n", dentry); + return dentry; + } + +@@ -887,6 +915,7 @@ static int ceph_mknod(struct mnt_idmap * + struct dentry *dentry, umode_t mode, dev_t rdev) + { + struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb); ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_request *req; + struct ceph_acl_sec_ctx as_ctx = {}; + int err; +@@ -903,8 +932,8 @@ static int ceph_mknod(struct mnt_idmap * + goto out; + } + +- dout("mknod in dir %p dentry %p mode 0%ho rdev %d\n", +- dir, dentry, mode, rdev); ++ doutc(cl, "%p %llx.%llx/'%pd' dentry %p mode 0%ho rdev %d\n", ++ dir, ceph_vinop(dir), dentry, dentry, mode, rdev); + req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_MKNOD, USE_AUTH_MDS); + if (IS_ERR(req)) { + err = PTR_ERR(req); +@@ -995,6 +1024,7 @@ static int ceph_symlink(struct mnt_idmap + struct dentry *dentry, const char *dest) + { + struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb); ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_request *req; + struct ceph_acl_sec_ctx as_ctx = {}; + umode_t mode = S_IFLNK | 0777; +@@ -1012,7 +1042,8 @@ static int ceph_symlink(struct mnt_idmap + goto out; + } + +- dout("symlink in dir %p dentry %p to '%s'\n", dir, dentry, dest); ++ doutc(cl, "%p %llx.%llx/'%pd' to '%s'\n", dir, ceph_vinop(dir), dentry, ++ dest); + req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_SYMLINK, USE_AUTH_MDS); + if (IS_ERR(req)) { + err = PTR_ERR(req); +@@ -1066,6 +1097,7 @@ static int ceph_mkdir(struct mnt_idmap * + struct dentry *dentry, umode_t mode) + { + struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb); ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_request *req; + struct ceph_acl_sec_ctx as_ctx = {}; + int err; +@@ -1078,10 +1110,11 @@ static int ceph_mkdir(struct mnt_idmap * + if (ceph_snap(dir) == CEPH_SNAPDIR) { + /* mkdir .snap/foo is a MKSNAP */ + op = CEPH_MDS_OP_MKSNAP; +- dout("mksnap dir %p snap '%pd' dn %p\n", dir, +- dentry, dentry); ++ doutc(cl, "mksnap %llx.%llx/'%pd' dentry %p\n", ++ ceph_vinop(dir), dentry, dentry); + } else if (ceph_snap(dir) == CEPH_NOSNAP) { +- dout("mkdir dir %p dn %p mode 0%ho\n", dir, dentry, mode); ++ doutc(cl, "mkdir %llx.%llx/'%pd' dentry %p mode 0%ho\n", ++ ceph_vinop(dir), dentry, dentry, mode); + op = CEPH_MDS_OP_MKDIR; + } else { + err = -EROFS; +@@ -1146,6 +1179,7 @@ static int ceph_link(struct dentry *old_ + struct dentry *dentry) + { + struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb); ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_request *req; + int err; + +@@ -1163,8 +1197,8 @@ static int ceph_link(struct dentry *old_ + if (err) + return err; + +- dout("link in dir %p %llx.%llx old_dentry %p:'%pd' dentry %p:'%pd'\n", +- dir, ceph_vinop(dir), old_dentry, old_dentry, dentry, dentry); ++ doutc(cl, "%p %llx.%llx/'%pd' to '%pd'\n", dir, ceph_vinop(dir), ++ old_dentry, dentry); + req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LINK, USE_AUTH_MDS); + if (IS_ERR(req)) { + d_drop(dentry); +@@ -1202,13 +1236,15 @@ static void ceph_async_unlink_cb(struct + { + struct dentry *dentry = req->r_dentry; + struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dentry->d_sb); ++ struct ceph_client *cl = fsc->client; + struct ceph_dentry_info *di = ceph_dentry(dentry); + int result = req->r_err ? req->r_err : + le32_to_cpu(req->r_reply_info.head->result); + + if (!test_bit(CEPH_DENTRY_ASYNC_UNLINK_BIT, &di->flags)) +- pr_warn("%s dentry %p:%pd async unlink bit is not set\n", +- __func__, dentry, dentry); ++ pr_warn_client(cl, ++ "dentry %p:%pd async unlink bit is not set\n", ++ dentry, dentry); + + spin_lock(&fsc->async_unlink_conflict_lock); + hash_del_rcu(&di->hnode); +@@ -1241,8 +1277,8 @@ static void ceph_async_unlink_cb(struct + /* mark inode itself for an error (since metadata is bogus) */ + mapping_set_error(req->r_old_inode->i_mapping, result); + +- pr_warn("async unlink failure path=(%llx)%s result=%d!\n", +- base, IS_ERR(path) ? "<>" : path, result); ++ pr_warn_client(cl, "failure path=(%llx)%s result=%d!\n", ++ base, IS_ERR(path) ? "<>" : path, result); + ceph_mdsc_free_path(path, pathlen); + } + out: +@@ -1292,6 +1328,7 @@ static int get_caps_for_async_unlink(str + static int ceph_unlink(struct inode *dir, struct dentry *dentry) + { + struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dir->i_sb); ++ struct ceph_client *cl = fsc->client; + struct ceph_mds_client *mdsc = fsc->mdsc; + struct inode *inode = d_inode(dentry); + struct ceph_inode_info *ci = ceph_inode(inode); +@@ -1302,11 +1339,12 @@ static int ceph_unlink(struct inode *dir + + if (ceph_snap(dir) == CEPH_SNAPDIR) { + /* rmdir .snap/foo is RMSNAP */ +- dout("rmsnap dir %p '%pd' dn %p\n", dir, 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) { +- dout("unlink/rmdir dir %p dn %p inode %p\n", +- dir, dentry, inode); ++ doutc(cl, "unlink/rmdir %llx.%llx/'%pd' inode %llx.%llx\n", ++ ceph_vinop(dir), dentry, ceph_vinop(inode)); + op = d_is_dir(dentry) ? + CEPH_MDS_OP_RMDIR : CEPH_MDS_OP_UNLINK; + } else +@@ -1329,9 +1367,9 @@ retry: + (req->r_dir_caps = get_caps_for_async_unlink(dir, dentry))) { + struct ceph_dentry_info *di = ceph_dentry(dentry); + +- dout("async unlink on %llu/%.*s caps=%s", ceph_ino(dir), +- dentry->d_name.len, dentry->d_name.name, +- ceph_cap_string(req->r_dir_caps)); ++ doutc(cl, "async unlink on %llx.%llx/'%pd' caps=%s", ++ ceph_vinop(dir), dentry, ++ ceph_cap_string(req->r_dir_caps)); + set_bit(CEPH_MDS_R_ASYNC, &req->r_req_flags); + req->r_callback = ceph_async_unlink_cb; + req->r_old_inode = d_inode(dentry); +@@ -1398,6 +1436,7 @@ static int ceph_rename(struct mnt_idmap + struct dentry *new_dentry, unsigned int flags) + { + struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(old_dir->i_sb); ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_request *req; + int op = CEPH_MDS_OP_RENAME; + int err; +@@ -1427,8 +1466,9 @@ static int ceph_rename(struct mnt_idmap + if (err) + return err; + +- dout("rename dir %p dentry %p to dir %p dentry %p\n", +- old_dir, old_dentry, new_dir, new_dentry); ++ doutc(cl, "%llx.%llx/'%pd' to %llx.%llx/'%pd'\n", ++ ceph_vinop(old_dir), old_dentry, ceph_vinop(new_dir), ++ new_dentry); + req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS); + if (IS_ERR(req)) + return PTR_ERR(req); +@@ -1473,9 +1513,10 @@ static int ceph_rename(struct mnt_idmap + void __ceph_dentry_lease_touch(struct ceph_dentry_info *di) + { + struct dentry *dn = di->dentry; +- struct ceph_mds_client *mdsc; ++ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(dn->d_sb)->mdsc; ++ struct ceph_client *cl = mdsc->fsc->client; + +- dout("dentry_lease_touch %p %p '%pd'\n", di, dn, dn); ++ doutc(cl, "%p %p '%pd'\n", di, dn, dn); + + di->flags |= CEPH_DENTRY_LEASE_LIST; + if (di->flags & CEPH_DENTRY_SHRINK_LIST) { +@@ -1483,7 +1524,6 @@ void __ceph_dentry_lease_touch(struct ce + return; + } + +- 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); +@@ -1507,10 +1547,10 @@ static void __dentry_dir_lease_touch(str + void __ceph_dentry_dir_lease_touch(struct ceph_dentry_info *di) + { + struct dentry *dn = di->dentry; +- struct ceph_mds_client *mdsc; ++ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(dn->d_sb)->mdsc; ++ struct ceph_client *cl = mdsc->fsc->client; + +- dout("dentry_dir_lease_touch %p %p '%pd' (offset 0x%llx)\n", +- di, dn, dn, di->offset); ++ doutc(cl, "%p %p '%pd' (offset 0x%llx)\n", di, dn, dn, di->offset); + + if (!list_empty(&di->lease_list)) { + if (di->flags & CEPH_DENTRY_LEASE_LIST) { +@@ -1530,7 +1570,6 @@ void __ceph_dentry_dir_lease_touch(struc + return; + } + +- 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); +@@ -1771,6 +1810,8 @@ static int dentry_lease_is_valid(struct + { + struct ceph_dentry_info *di; + struct ceph_mds_session *session = NULL; ++ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(dentry->d_sb)->mdsc; ++ struct ceph_client *cl = mdsc->fsc->client; + u32 seq = 0; + int valid = 0; + +@@ -1803,7 +1844,7 @@ static int dentry_lease_is_valid(struct + CEPH_MDS_LEASE_RENEW, seq); + ceph_put_mds_session(session); + } +- dout("dentry_lease_is_valid - dentry %p = %d\n", dentry, valid); ++ doutc(cl, "dentry %p = %d\n", dentry, valid); + return valid; + } + +@@ -1846,6 +1887,7 @@ static int dir_lease_is_valid(struct ino + struct ceph_mds_client *mdsc) + { + struct ceph_inode_info *ci = ceph_inode(dir); ++ struct ceph_client *cl = mdsc->fsc->client; + int valid; + int shared_gen; + +@@ -1867,8 +1909,9 @@ static int dir_lease_is_valid(struct ino + valid = 0; + spin_unlock(&dentry->d_lock); + } +- dout("dir_lease_is_valid dir %p v%u dentry %p = %d\n", +- dir, (unsigned)atomic_read(&ci->i_shared_gen), dentry, valid); ++ doutc(cl, "dir %p %llx.%llx v%u dentry %p '%pd' = %d\n", dir, ++ ceph_vinop(dir), (unsigned)atomic_read(&ci->i_shared_gen), ++ dentry, dentry, valid); + return valid; + } + +@@ -1877,10 +1920,11 @@ static int dir_lease_is_valid(struct ino + */ + static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags) + { ++ struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(dentry->d_sb)->mdsc; ++ struct ceph_client *cl = mdsc->fsc->client; + int valid = 0; + struct dentry *parent; + struct inode *dir, *inode; +- struct ceph_mds_client *mdsc; + + valid = fscrypt_d_revalidate(dentry, flags); + if (valid <= 0) +@@ -1898,16 +1942,16 @@ static int ceph_d_revalidate(struct dent + inode = d_inode(dentry); + } + +- dout("d_revalidate %p '%pd' inode %p offset 0x%llx nokey %d\n", dentry, +- dentry, inode, ceph_dentry(dentry)->offset, +- !!(dentry->d_flags & DCACHE_NOKEY_NAME)); ++ doutc(cl, "%p '%pd' inode %p offset 0x%llx nokey %d\n", ++ dentry, dentry, inode, ceph_dentry(dentry)->offset, ++ !!(dentry->d_flags & DCACHE_NOKEY_NAME)); + + mdsc = ceph_sb_to_fs_client(dir->i_sb)->mdsc; + + /* always trust cached snapped dentries, snapdir dentry */ + if (ceph_snap(dir) != CEPH_NOSNAP) { +- dout("d_revalidate %p '%pd' inode %p is SNAPPED\n", dentry, +- dentry, inode); ++ doutc(cl, "%p '%pd' inode %p is SNAPPED\n", dentry, ++ dentry, inode); + valid = 1; + } else if (inode && ceph_snap(inode) == CEPH_SNAPDIR) { + valid = 1; +@@ -1962,14 +2006,14 @@ static int ceph_d_revalidate(struct dent + break; + } + ceph_mdsc_put_request(req); +- dout("d_revalidate %p lookup result=%d\n", +- dentry, err); ++ doutc(cl, "%p '%pd', lookup result=%d\n", dentry, ++ dentry, err); + } + } else { + percpu_counter_inc(&mdsc->metric.d_lease_hit); + } + +- dout("d_revalidate %p %s\n", dentry, valid ? "valid" : "invalid"); ++ doutc(cl, "%p '%pd' %s\n", dentry, dentry, valid ? "valid" : "invalid"); + if (!valid) + ceph_dir_clear_complete(dir); + +@@ -2011,7 +2055,7 @@ static void ceph_d_release(struct dentry + struct ceph_dentry_info *di = ceph_dentry(dentry); + struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dentry->d_sb); + +- dout("d_release %p\n", dentry); ++ doutc(fsc->client, "dentry %p '%pd'\n", dentry, dentry); + + atomic64_dec(&fsc->mdsc->metric.total_dentries); + +@@ -2032,10 +2076,12 @@ static void ceph_d_release(struct dentry + */ + static void ceph_d_prune(struct dentry *dentry) + { ++ struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dentry->d_sb); ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_inode_info *dir_ci; + struct ceph_dentry_info *di; + +- dout("ceph_d_prune %pd %p\n", dentry, dentry); ++ doutc(cl, "dentry %p '%pd'\n", dentry, dentry); + + /* do we have a valid parent? */ + if (IS_ROOT(dentry)) +--- a/fs/ceph/export.c ++++ b/fs/ceph/export.c +@@ -36,6 +36,7 @@ struct ceph_nfs_snapfh { + static int ceph_encode_snapfh(struct inode *inode, u32 *rawfh, int *max_len, + struct inode *parent_inode) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + static const int snap_handle_length = + sizeof(struct ceph_nfs_snapfh) >> 2; + struct ceph_nfs_snapfh *sfh = (void *)rawfh; +@@ -79,13 +80,14 @@ static int ceph_encode_snapfh(struct ino + *max_len = snap_handle_length; + ret = FILEID_BTRFS_WITH_PARENT; + out: +- dout("encode_snapfh %llx.%llx ret=%d\n", ceph_vinop(inode), ret); ++ doutc(cl, "%p %llx.%llx ret=%d\n", inode, ceph_vinop(inode), ret); + return ret; + } + + static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len, + struct inode *parent_inode) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + static const int handle_length = + sizeof(struct ceph_nfs_fh) >> 2; + static const int connected_handle_length = +@@ -105,15 +107,15 @@ static int ceph_encode_fh(struct inode * + + if (parent_inode) { + struct ceph_nfs_confh *cfh = (void *)rawfh; +- dout("encode_fh %llx with parent %llx\n", +- ceph_ino(inode), ceph_ino(parent_inode)); ++ doutc(cl, "%p %llx.%llx with parent %p %llx.%llx\n", inode, ++ ceph_vinop(inode), parent_inode, ceph_vinop(parent_inode)); + cfh->ino = ceph_ino(inode); + cfh->parent_ino = ceph_ino(parent_inode); + *max_len = connected_handle_length; + type = FILEID_INO32_GEN_PARENT; + } else { + struct ceph_nfs_fh *fh = (void *)rawfh; +- dout("encode_fh %llx\n", ceph_ino(inode)); ++ doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode)); + fh->ino = ceph_ino(inode); + *max_len = handle_length; + type = FILEID_INO32_GEN; +@@ -206,6 +208,7 @@ static struct dentry *__snapfh_to_dentry + bool want_parent) + { + struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(sb)->mdsc; ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_request *req; + struct inode *inode; + struct ceph_vino vino; +@@ -278,11 +281,10 @@ static struct dentry *__snapfh_to_dentry + ceph_mdsc_put_request(req); + + if (want_parent) { +- dout("snapfh_to_parent %llx.%llx\n err=%d\n", +- vino.ino, vino.snap, err); ++ doutc(cl, "%llx.%llx\n err=%d\n", vino.ino, vino.snap, err); + } else { +- dout("snapfh_to_dentry %llx.%llx parent %llx hash %x err=%d", +- vino.ino, vino.snap, sfh->parent_ino, sfh->hash, err); ++ doutc(cl, "%llx.%llx parent %llx hash %x err=%d", vino.ino, ++ vino.snap, sfh->parent_ino, sfh->hash, err); + } + if (IS_ERR(inode)) + return ERR_CAST(inode); +@@ -297,6 +299,7 @@ static struct dentry *ceph_fh_to_dentry( + struct fid *fid, + int fh_len, int fh_type) + { ++ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb); + struct ceph_nfs_fh *fh = (void *)fid->raw; + + if (fh_type == FILEID_BTRFS_WITH_PARENT) { +@@ -310,7 +313,7 @@ static struct dentry *ceph_fh_to_dentry( + if (fh_len < sizeof(*fh) / 4) + return NULL; + +- dout("fh_to_dentry %llx\n", fh->ino); ++ doutc(fsc->client, "%llx\n", fh->ino); + return __fh_to_dentry(sb, fh->ino); + } + +@@ -363,6 +366,7 @@ static struct dentry *__get_parent(struc + static struct dentry *ceph_get_parent(struct dentry *child) + { + struct inode *inode = d_inode(child); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct dentry *dn; + + if (ceph_snap(inode) != CEPH_NOSNAP) { +@@ -402,8 +406,8 @@ static struct dentry *ceph_get_parent(st + dn = __get_parent(child->d_sb, child, 0); + } + out: +- dout("get_parent %p ino %llx.%llx err=%ld\n", +- child, ceph_vinop(inode), (long)PTR_ERR_OR_ZERO(dn)); ++ doutc(cl, "child %p %p %llx.%llx err=%ld\n", child, inode, ++ ceph_vinop(inode), (long)PTR_ERR_OR_ZERO(dn)); + return dn; + } + +@@ -414,6 +418,7 @@ static struct dentry *ceph_fh_to_parent( + struct fid *fid, + int fh_len, int fh_type) + { ++ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb); + struct ceph_nfs_confh *cfh = (void *)fid->raw; + struct dentry *dentry; + +@@ -427,7 +432,7 @@ static struct dentry *ceph_fh_to_parent( + if (fh_len < sizeof(*cfh) / 4) + return NULL; + +- dout("fh_to_parent %llx\n", cfh->parent_ino); ++ doutc(fsc->client, "%llx\n", cfh->parent_ino); + dentry = __get_parent(sb, NULL, cfh->ino); + if (unlikely(dentry == ERR_PTR(-ENOENT))) + dentry = __fh_to_dentry(sb, cfh->parent_ino); +@@ -526,8 +531,8 @@ out: + if (req) + ceph_mdsc_put_request(req); + kfree(last_name); +- dout("get_snap_name %p ino %llx.%llx err=%d\n", +- child, ceph_vinop(inode), err); ++ doutc(fsc->client, "child dentry %p %p %llx.%llx err=%d\n", child, ++ inode, ceph_vinop(inode), err); + return err; + } + +@@ -588,9 +593,9 @@ static int ceph_get_name(struct dentry * + ceph_fname_free_buffer(dir, &oname); + } + out: +- dout("get_name %p ino %llx.%llx err %d %s%s\n", +- child, ceph_vinop(inode), err, +- err ? "" : "name ", err ? "" : name); ++ doutc(mdsc->fsc->client, "child dentry %p %p %llx.%llx err %d %s%s\n", ++ child, inode, ceph_vinop(inode), err, err ? "" : "name ", ++ err ? "" : name); + ceph_mdsc_put_request(req); + return err; + } +--- a/fs/ceph/file.c ++++ b/fs/ceph/file.c +@@ -19,8 +19,9 @@ + #include "io.h" + #include "metric.h" + +-static __le32 ceph_flags_sys2wire(u32 flags) ++static __le32 ceph_flags_sys2wire(struct ceph_mds_client *mdsc, u32 flags) + { ++ struct ceph_client *cl = mdsc->fsc->client; + u32 wire_flags = 0; + + switch (flags & O_ACCMODE) { +@@ -48,7 +49,7 @@ static __le32 ceph_flags_sys2wire(u32 fl + #undef ceph_sys2wire + + if (flags) +- dout("unused open flags: %x\n", flags); ++ doutc(cl, "unused open flags: %x\n", flags); + + return cpu_to_le32(wire_flags); + } +@@ -189,7 +190,7 @@ prepare_open_request(struct super_block + if (IS_ERR(req)) + goto out; + req->r_fmode = ceph_flags_to_mode(flags); +- req->r_args.open.flags = ceph_flags_sys2wire(flags); ++ req->r_args.open.flags = ceph_flags_sys2wire(mdsc, flags); + req->r_args.open.mode = cpu_to_le32(create_mode); + out: + return req; +@@ -201,11 +202,12 @@ static int ceph_init_file_info(struct in + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_mount_options *opt = + ceph_inode_to_fs_client(&ci->netfs.inode)->mount_options; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_file_info *fi; + int ret; + +- dout("%s %p %p 0%o (%s)\n", __func__, inode, file, +- inode->i_mode, isdir ? "dir" : "regular"); ++ doutc(cl, "%p %llx.%llx %p 0%o (%s)\n", inode, ceph_vinop(inode), ++ file, inode->i_mode, isdir ? "dir" : "regular"); + BUG_ON(inode->i_fop->release != ceph_release); + + if (isdir) { +@@ -259,6 +261,7 @@ error: + */ + static int ceph_init_file(struct inode *inode, struct file *file, int fmode) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + int ret = 0; + + switch (inode->i_mode & S_IFMT) { +@@ -271,13 +274,13 @@ static int ceph_init_file(struct inode * + break; + + case S_IFLNK: +- dout("init_file %p %p 0%o (symlink)\n", inode, file, +- inode->i_mode); ++ doutc(cl, "%p %llx.%llx %p 0%o (symlink)\n", inode, ++ ceph_vinop(inode), file, inode->i_mode); + break; + + default: +- dout("init_file %p %p 0%o (special)\n", inode, file, +- inode->i_mode); ++ doutc(cl, "%p %llx.%llx %p 0%o (special)\n", inode, ++ ceph_vinop(inode), file, inode->i_mode); + /* + * we need to drop the open ref now, since we don't + * have .release set to ceph_release. +@@ -296,6 +299,7 @@ static int ceph_init_file(struct inode * + 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; +@@ -307,8 +311,9 @@ int ceph_renew_caps(struct inode *inode, + (!(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); + return 0; + } +@@ -339,7 +344,8 @@ int ceph_renew_caps(struct inode *inode, + 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; + } + +@@ -353,6 +359,7 @@ int ceph_open(struct inode *inode, struc + { + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_fs_client *fsc = ceph_sb_to_fs_client(inode->i_sb); ++ struct ceph_client *cl = fsc->client; + struct ceph_mds_client *mdsc = fsc->mdsc; + struct ceph_mds_request *req; + struct ceph_file_info *fi = file->private_data; +@@ -360,7 +367,7 @@ int ceph_open(struct inode *inode, struc + int flags, fmode, wanted; + + if (fi) { +- dout("open file %p is already opened\n", file); ++ doutc(cl, "file %p is already opened\n", file); + return 0; + } + +@@ -374,8 +381,8 @@ int ceph_open(struct inode *inode, struc + return err; + } + +- dout("open inode %p ino %llx.%llx file %p flags %d (%d)\n", inode, +- ceph_vinop(inode), file, flags, file->f_flags); ++ doutc(cl, "%p %llx.%llx file %p flags %d (%d)\n", inode, ++ ceph_vinop(inode), file, flags, file->f_flags); + fmode = ceph_flags_to_mode(flags); + wanted = ceph_caps_for_mode(fmode); + +@@ -399,9 +406,9 @@ int ceph_open(struct inode *inode, struc + int mds_wanted = __ceph_caps_mds_wanted(ci, true); + int issued = __ceph_caps_issued(ci, NULL); + +- dout("open %p fmode %d want %s issued %s using existing\n", +- inode, fmode, ceph_cap_string(wanted), +- ceph_cap_string(issued)); ++ doutc(cl, "open %p fmode %d want %s issued %s using existing\n", ++ inode, fmode, ceph_cap_string(wanted), ++ ceph_cap_string(issued)); + __ceph_touch_fmode(ci, mdsc, fmode); + spin_unlock(&ci->i_ceph_lock); + +@@ -421,7 +428,7 @@ int ceph_open(struct inode *inode, struc + + spin_unlock(&ci->i_ceph_lock); + +- dout("open fmode %d wants %s\n", fmode, ceph_cap_string(wanted)); ++ doutc(cl, "open fmode %d wants %s\n", fmode, ceph_cap_string(wanted)); + req = prepare_open_request(inode->i_sb, flags, 0); + if (IS_ERR(req)) { + err = PTR_ERR(req); +@@ -435,7 +442,7 @@ int ceph_open(struct inode *inode, struc + if (!err) + err = ceph_init_file(inode, file, req->r_fmode); + ceph_mdsc_put_request(req); +- dout("open result=%d on %llx.%llx\n", err, ceph_vinop(inode)); ++ doutc(cl, "open result=%d on %llx.%llx\n", err, ceph_vinop(inode)); + out: + return err; + } +@@ -515,6 +522,7 @@ no_async: + + static void restore_deleg_ino(struct inode *dir, u64 ino) + { ++ struct ceph_client *cl = ceph_inode_to_client(dir); + struct ceph_inode_info *ci = ceph_inode(dir); + struct ceph_mds_session *s = NULL; + +@@ -525,7 +533,8 @@ static void restore_deleg_ino(struct ino + if (s) { + int err = ceph_restore_deleg_ino(s, ino); + if (err) +- pr_warn("ceph: unable to restore delegated ino 0x%llx to session: %d\n", ++ pr_warn_client(cl, ++ "unable to restore delegated ino 0x%llx to session: %d\n", + ino, err); + ceph_put_mds_session(s); + } +@@ -556,6 +565,7 @@ static void wake_async_create_waiters(st + static void ceph_async_create_cb(struct ceph_mds_client *mdsc, + struct ceph_mds_request *req) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct dentry *dentry = req->r_dentry; + struct inode *dinode = d_inode(dentry); + struct inode *tinode = req->r_target_inode; +@@ -576,7 +586,8 @@ static void ceph_async_create_cb(struct + char *path = ceph_mdsc_build_path(mdsc, req->r_dentry, &pathlen, + &base, 0); + +- pr_warn("async create failure path=(%llx)%s result=%d!\n", ++ pr_warn_client(cl, ++ "async create failure path=(%llx)%s result=%d!\n", + base, IS_ERR(path) ? "<>" : path, result); + ceph_mdsc_free_path(path, pathlen); + +@@ -595,14 +606,15 @@ static void ceph_async_create_cb(struct + u64 ino = ceph_vino(tinode).ino; + + if (req->r_deleg_ino != ino) +- pr_warn("%s: inode number mismatch! err=%d deleg_ino=0x%llx target=0x%llx\n", +- __func__, req->r_err, req->r_deleg_ino, ino); ++ pr_warn_client(cl, ++ "inode number mismatch! err=%d deleg_ino=0x%llx target=0x%llx\n", ++ req->r_err, req->r_deleg_ino, ino); + + mapping_set_error(tinode->i_mapping, result); + wake_async_create_waiters(tinode, req->r_session); + } else if (!result) { +- pr_warn("%s: no req->r_target_inode for 0x%llx\n", __func__, +- req->r_deleg_ino); ++ pr_warn_client(cl, "no req->r_target_inode for 0x%llx\n", ++ req->r_deleg_ino); + } + out: + ceph_mdsc_release_dir_caps(req); +@@ -624,6 +636,7 @@ static int ceph_finish_async_create(stru + struct timespec64 now; + struct ceph_string *pool_ns; + struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb); ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_vino vino = { .ino = req->r_deleg_ino, + .snap = CEPH_NOSNAP }; + +@@ -682,7 +695,7 @@ static int ceph_finish_async_create(stru + req->r_fmode, NULL); + up_read(&mdsc->snap_rwsem); + if (ret) { +- dout("%s failed to fill inode: %d\n", __func__, ret); ++ doutc(cl, "failed to fill inode: %d\n", ret); + ceph_dir_clear_complete(dir); + if (!d_unhashed(dentry)) + d_drop(dentry); +@@ -690,8 +703,8 @@ static int ceph_finish_async_create(stru + } else { + struct dentry *dn; + +- dout("%s d_adding new inode 0x%llx to 0x%llx/%s\n", __func__, +- vino.ino, ceph_ino(dir), dentry->d_name.name); ++ doutc(cl, "d_adding new inode 0x%llx to 0x%llx/%s\n", ++ vino.ino, ceph_ino(dir), dentry->d_name.name); + ceph_dir_clear_ordered(dir); + ceph_init_inode_acls(inode, as_ctx); + if (inode->i_state & I_NEW) { +@@ -729,6 +742,7 @@ int ceph_atomic_open(struct inode *dir, + struct file *file, unsigned flags, umode_t mode) + { + struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dir->i_sb); ++ struct ceph_client *cl = fsc->client; + struct ceph_mds_client *mdsc = fsc->mdsc; + struct ceph_mds_request *req; + struct inode *new_inode = NULL; +@@ -738,9 +752,9 @@ int ceph_atomic_open(struct inode *dir, + int mask; + int err; + +- dout("atomic_open %p dentry %p '%pd' %s flags %d mode 0%o\n", +- dir, dentry, dentry, +- d_unhashed(dentry) ? "unhashed" : "hashed", flags, mode); ++ doutc(cl, "%p %llx.%llx dentry %p '%pd' %s flags %d mode 0%o\n", ++ dir, ceph_vinop(dir), dentry, dentry, ++ d_unhashed(dentry) ? "unhashed" : "hashed", flags, mode); + + if (dentry->d_name.len > NAME_MAX) + return -ENAMETOOLONG; +@@ -878,17 +892,18 @@ retry: + goto out_req; + if (dn || d_really_is_negative(dentry) || d_is_symlink(dentry)) { + /* make vfs retry on splice, ENOENT, or symlink */ +- dout("atomic_open finish_no_open on dn %p\n", dn); ++ doutc(cl, "finish_no_open on dn %p\n", dn); + err = finish_no_open(file, dn); + } else { + if (IS_ENCRYPTED(dir) && + !fscrypt_has_permitted_context(dir, d_inode(dentry))) { +- pr_warn("Inconsistent encryption context (parent %llx:%llx child %llx:%llx)\n", ++ pr_warn_client(cl, ++ "Inconsistent encryption context (parent %llx:%llx child %llx:%llx)\n", + ceph_vinop(dir), ceph_vinop(d_inode(dentry))); + goto out_req; + } + +- dout("atomic_open finish_open on dn %p\n", dn); ++ doutc(cl, "finish_open on dn %p\n", dn); + if (req->r_op == CEPH_MDS_OP_CREATE && req->r_reply_info.has_create_ino) { + struct inode *newino = d_inode(dentry); + +@@ -903,17 +918,19 @@ out_req: + iput(new_inode); + out_ctx: + ceph_release_acl_sec_ctx(&as_ctx); +- dout("atomic_open result=%d\n", err); ++ doutc(cl, "result=%d\n", err); + return err; + } + + int ceph_release(struct inode *inode, struct file *file) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + + if (S_ISDIR(inode->i_mode)) { + struct ceph_dir_file_info *dfi = file->private_data; +- dout("release inode %p dir file %p\n", inode, file); ++ doutc(cl, "%p %llx.%llx dir file %p\n", inode, ++ ceph_vinop(inode), file); + WARN_ON(!list_empty(&dfi->file_info.rw_contexts)); + + ceph_put_fmode(ci, dfi->file_info.fmode, 1); +@@ -925,7 +942,8 @@ int ceph_release(struct inode *inode, st + kmem_cache_free(ceph_dir_file_cachep, dfi); + } else { + struct ceph_file_info *fi = file->private_data; +- dout("release inode %p regular file %p\n", inode, file); ++ doutc(cl, "%p %llx.%llx regular file %p\n", inode, ++ ceph_vinop(inode), file); + WARN_ON(!list_empty(&fi->rw_contexts)); + + ceph_fscache_unuse_cookie(inode, file->f_mode & FMODE_WRITE); +@@ -961,6 +979,7 @@ ssize_t __ceph_sync_read(struct inode *i + { + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode); ++ struct ceph_client *cl = fsc->client; + struct ceph_osd_client *osdc = &fsc->client->osdc; + ssize_t ret; + u64 off = *ki_pos; +@@ -969,7 +988,8 @@ ssize_t __ceph_sync_read(struct inode *i + bool sparse = IS_ENCRYPTED(inode) || ceph_test_mount_opt(fsc, SPARSEREAD); + u64 objver = 0; + +- dout("sync_read on inode %p %llx~%llx\n", inode, *ki_pos, len); ++ doutc(cl, "on inode %p %llx.%llx %llx~%llx\n", inode, ++ ceph_vinop(inode), *ki_pos, len); + + if (ceph_inode_is_shutdown(inode)) + return -EIO; +@@ -1004,8 +1024,8 @@ ssize_t __ceph_sync_read(struct inode *i + /* determine new offset/length if encrypted */ + ceph_fscrypt_adjust_off_and_len(inode, &read_off, &read_len); + +- dout("sync_read orig %llu~%llu reading %llu~%llu", +- off, len, read_off, read_len); ++ doutc(cl, "orig %llu~%llu reading %llu~%llu", off, len, ++ read_off, read_len); + + req = ceph_osdc_new_request(osdc, &ci->i_layout, + ci->i_vino, read_off, &read_len, 0, 1, +@@ -1059,8 +1079,8 @@ ssize_t __ceph_sync_read(struct inode *i + objver = req->r_version; + + i_size = i_size_read(inode); +- dout("sync_read %llu~%llu got %zd i_size %llu%s\n", +- off, len, ret, i_size, (more ? " MORE" : "")); ++ doutc(cl, "%llu~%llu got %zd i_size %llu%s\n", off, len, ++ ret, i_size, (more ? " MORE" : "")); + + /* Fix it to go to end of extent map */ + if (sparse && ret >= 0) +@@ -1106,8 +1126,8 @@ ssize_t __ceph_sync_read(struct inode *i + int zlen = min(len - ret, i_size - off - ret); + int zoff = page_off + ret; + +- dout("sync_read zero gap %llu~%llu\n", +- off + ret, off + ret + zlen); ++ doutc(cl, "zero gap %llu~%llu\n", off + ret, ++ off + ret + zlen); + ceph_zero_page_vector_range(zoff, zlen, pages); + ret += zlen; + } +@@ -1152,7 +1172,7 @@ ssize_t __ceph_sync_read(struct inode *i + if (last_objver) + *last_objver = objver; + } +- dout("sync_read result %zd retry_op %d\n", ret, *retry_op); ++ doutc(cl, "result %zd retry_op %d\n", ret, *retry_op); + return ret; + } + +@@ -1161,9 +1181,11 @@ static ssize_t ceph_sync_read(struct kio + { + struct file *file = iocb->ki_filp; + struct inode *inode = file_inode(file); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + +- dout("sync_read on file %p %llx~%zx %s\n", file, iocb->ki_pos, +- iov_iter_count(to), (file->f_flags & O_DIRECT) ? "O_DIRECT" : ""); ++ doutc(cl, "on file %p %llx~%zx %s\n", file, iocb->ki_pos, ++ iov_iter_count(to), ++ (file->f_flags & O_DIRECT) ? "O_DIRECT" : ""); + + return __ceph_sync_read(inode, &iocb->ki_pos, to, retry_op, NULL); + } +@@ -1191,6 +1213,7 @@ static void ceph_aio_retry_work(struct w + static void ceph_aio_complete(struct inode *inode, + struct ceph_aio_request *aio_req) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + int ret; + +@@ -1204,7 +1227,7 @@ static void ceph_aio_complete(struct ino + if (!ret) + ret = aio_req->total_len; + +- dout("ceph_aio_complete %p rc %d\n", inode, ret); ++ doutc(cl, "%p %llx.%llx rc %d\n", inode, ceph_vinop(inode), ret); + + if (ret >= 0 && aio_req->write) { + int dirty; +@@ -1243,11 +1266,13 @@ static void ceph_aio_complete_req(struct + struct ceph_client_metric *metric = &ceph_sb_to_mdsc(inode->i_sb)->metric; + unsigned int len = osd_data->bvec_pos.iter.bi_size; + bool sparse = (op->op == CEPH_OSD_OP_SPARSE_READ); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + + BUG_ON(osd_data->type != CEPH_OSD_DATA_TYPE_BVECS); + BUG_ON(!osd_data->num_bvecs); + +- dout("ceph_aio_complete_req %p rc %d bytes %u\n", inode, rc, len); ++ doutc(cl, "req %p inode %p %llx.%llx, rc %d bytes %u\n", req, ++ inode, ceph_vinop(inode), rc, len); + + if (rc == -EOLDSNAPC) { + struct ceph_aio_work *aio_work; +@@ -1388,6 +1413,7 @@ ceph_direct_read_write(struct kiocb *ioc + struct inode *inode = file_inode(file); + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode); ++ struct ceph_client *cl = fsc->client; + struct ceph_client_metric *metric = &fsc->mdsc->metric; + struct ceph_vino vino; + struct ceph_osd_request *req; +@@ -1406,9 +1432,9 @@ ceph_direct_read_write(struct kiocb *ioc + if (write && ceph_snap(file_inode(file)) != CEPH_NOSNAP) + return -EROFS; + +- dout("sync_direct_%s on file %p %lld~%u snapc %p seq %lld\n", +- (write ? "write" : "read"), file, pos, (unsigned)count, +- snapc, snapc ? snapc->seq : 0); ++ doutc(cl, "sync_direct_%s on file %p %lld~%u snapc %p seq %lld\n", ++ (write ? "write" : "read"), file, pos, (unsigned)count, ++ snapc, snapc ? snapc->seq : 0); + + if (write) { + int ret2; +@@ -1419,7 +1445,8 @@ ceph_direct_read_write(struct kiocb *ioc + pos >> PAGE_SHIFT, + (pos + count - 1) >> PAGE_SHIFT); + if (ret2 < 0) +- dout("invalidate_inode_pages2_range returned %d\n", ret2); ++ doutc(cl, "invalidate_inode_pages2_range returned %d\n", ++ ret2); + + flags = /* CEPH_OSD_FLAG_ORDERSNAP | */ CEPH_OSD_FLAG_WRITE; + } else { +@@ -1615,6 +1642,7 @@ ceph_sync_write(struct kiocb *iocb, stru + struct inode *inode = file_inode(file); + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode); ++ struct ceph_client *cl = fsc->client; + struct ceph_osd_client *osdc = &fsc->client->osdc; + struct ceph_osd_request *req; + struct page **pages; +@@ -1629,8 +1657,8 @@ ceph_sync_write(struct kiocb *iocb, stru + if (ceph_snap(file_inode(file)) != CEPH_NOSNAP) + return -EROFS; + +- dout("sync_write on file %p %lld~%u snapc %p seq %lld\n", +- file, pos, (unsigned)count, snapc, snapc->seq); ++ doutc(cl, "on file %p %lld~%u snapc %p seq %lld\n", file, pos, ++ (unsigned)count, snapc, snapc->seq); + + ret = filemap_write_and_wait_range(inode->i_mapping, + pos, pos + count - 1); +@@ -1674,9 +1702,9 @@ ceph_sync_write(struct kiocb *iocb, stru + last = (pos + len) != (write_pos + write_len); + rmw = first || last; + +- dout("sync_write ino %llx %lld~%llu adjusted %lld~%llu -- %srmw\n", +- ci->i_vino.ino, pos, len, write_pos, write_len, +- rmw ? "" : "no "); ++ doutc(cl, "ino %llx %lld~%llu adjusted %lld~%llu -- %srmw\n", ++ ci->i_vino.ino, pos, len, write_pos, write_len, ++ rmw ? "" : "no "); + + /* + * The data is emplaced into the page as it would be if it were +@@ -1885,7 +1913,7 @@ ceph_sync_write(struct kiocb *iocb, stru + left -= ret; + } + if (ret < 0) { +- dout("sync_write write failed with %d\n", ret); ++ doutc(cl, "write failed with %d\n", ret); + ceph_release_page_vector(pages, num_pages); + break; + } +@@ -1895,7 +1923,7 @@ ceph_sync_write(struct kiocb *iocb, stru + write_pos, write_len, + GFP_KERNEL); + if (ret < 0) { +- dout("encryption failed with %d\n", ret); ++ doutc(cl, "encryption failed with %d\n", ret); + ceph_release_page_vector(pages, num_pages); + break; + } +@@ -1914,7 +1942,7 @@ ceph_sync_write(struct kiocb *iocb, stru + break; + } + +- dout("sync_write write op %lld~%llu\n", write_pos, write_len); ++ doutc(cl, "write op %lld~%llu\n", write_pos, write_len); + osd_req_op_extent_osd_data_pages(req, rmw ? 1 : 0, pages, write_len, + offset_in_page(write_pos), false, + true); +@@ -1945,7 +1973,7 @@ ceph_sync_write(struct kiocb *iocb, stru + req->r_end_latency, len, ret); + ceph_osdc_put_request(req); + if (ret != 0) { +- dout("sync_write osd write returned %d\n", ret); ++ doutc(cl, "osd write returned %d\n", ret); + /* Version changed! Must re-do the rmw cycle */ + if ((assert_ver && (ret == -ERANGE || ret == -EOVERFLOW)) || + (!assert_ver && ret == -EEXIST)) { +@@ -1975,13 +2003,13 @@ ceph_sync_write(struct kiocb *iocb, stru + pos >> PAGE_SHIFT, + (pos + len - 1) >> PAGE_SHIFT); + if (ret < 0) { +- dout("invalidate_inode_pages2_range returned %d\n", +- ret); ++ doutc(cl, "invalidate_inode_pages2_range returned %d\n", ++ ret); + ret = 0; + } + pos += len; + written += len; +- dout("sync_write written %d\n", written); ++ doutc(cl, "written %d\n", written); + if (pos > i_size_read(inode)) { + check_caps = ceph_inode_set_size(inode, pos); + if (check_caps) +@@ -1995,7 +2023,7 @@ ceph_sync_write(struct kiocb *iocb, stru + ret = written; + iocb->ki_pos = pos; + } +- dout("sync_write returning %d\n", ret); ++ doutc(cl, "returning %d\n", ret); + return ret; + } + +@@ -2014,13 +2042,14 @@ static ssize_t ceph_read_iter(struct kio + struct inode *inode = file_inode(filp); + struct ceph_inode_info *ci = ceph_inode(inode); + bool direct_lock = iocb->ki_flags & IOCB_DIRECT; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + ssize_t ret; + int want = 0, got = 0; + int retry_op = 0, read = 0; + + again: +- dout("aio_read %p %llx.%llx %llu~%u trying to get caps on %p\n", +- inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len, inode); ++ doutc(cl, "%llu~%u trying to get caps on %p %llx.%llx\n", ++ iocb->ki_pos, (unsigned)len, inode, ceph_vinop(inode)); + + if (ceph_inode_is_shutdown(inode)) + return -ESTALE; +@@ -2048,9 +2077,9 @@ again: + (iocb->ki_flags & IOCB_DIRECT) || + (fi->flags & CEPH_F_SYNC)) { + +- dout("aio_sync_read %p %llx.%llx %llu~%u got cap refs on %s\n", +- inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len, +- ceph_cap_string(got)); ++ doutc(cl, "sync %p %llx.%llx %llu~%u got cap refs on %s\n", ++ inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len, ++ ceph_cap_string(got)); + + if (!ceph_has_inline_data(ci)) { + if (!retry_op && +@@ -2068,16 +2097,16 @@ again: + } + } else { + CEPH_DEFINE_RW_CONTEXT(rw_ctx, got); +- dout("aio_read %p %llx.%llx %llu~%u got cap refs on %s\n", +- inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len, +- ceph_cap_string(got)); ++ doutc(cl, "async %p %llx.%llx %llu~%u got cap refs on %s\n", ++ inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len, ++ ceph_cap_string(got)); + ceph_add_rw_context(fi, &rw_ctx); + ret = generic_file_read_iter(iocb, to); + ceph_del_rw_context(fi, &rw_ctx); + } + +- dout("aio_read %p %llx.%llx dropping cap refs on %s = %d\n", +- inode, ceph_vinop(inode), ceph_cap_string(got), (int)ret); ++ doutc(cl, "%p %llx.%llx dropping cap refs on %s = %d\n", ++ inode, ceph_vinop(inode), ceph_cap_string(got), (int)ret); + ceph_put_cap_refs(ci, got); + + if (direct_lock) +@@ -2137,8 +2166,8 @@ again: + /* hit EOF or hole? */ + if (retry_op == CHECK_EOF && iocb->ki_pos < i_size && + ret < len) { +- dout("sync_read hit hole, ppos %lld < size %lld" +- ", reading more\n", iocb->ki_pos, i_size); ++ doutc(cl, "hit hole, ppos %lld < size %lld, reading more\n", ++ iocb->ki_pos, i_size); + + read += ret; + len -= ret; +@@ -2233,6 +2262,7 @@ static ssize_t ceph_write_iter(struct ki + struct inode *inode = file_inode(file); + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode); ++ struct ceph_client *cl = fsc->client; + struct ceph_osd_client *osdc = &fsc->client->osdc; + struct ceph_cap_flush *prealloc_cf; + ssize_t count, written = 0; +@@ -2300,8 +2330,9 @@ retry_snap: + if (err) + goto out; + +- dout("aio_write %p %llx.%llx %llu~%zd getting caps. i_size %llu\n", +- inode, ceph_vinop(inode), pos, count, i_size_read(inode)); ++ doutc(cl, "%p %llx.%llx %llu~%zd getting caps. i_size %llu\n", ++ inode, ceph_vinop(inode), pos, count, ++ i_size_read(inode)); + if (!(fi->flags & CEPH_F_SYNC) && !direct_lock) + want |= CEPH_CAP_FILE_BUFFER; + if (fi->fmode & CEPH_FILE_MODE_LAZY) +@@ -2317,8 +2348,8 @@ retry_snap: + + inode_inc_iversion_raw(inode); + +- dout("aio_write %p %llx.%llx %llu~%zd got cap refs on %s\n", +- inode, ceph_vinop(inode), pos, count, ceph_cap_string(got)); ++ doutc(cl, "%p %llx.%llx %llu~%zd got cap refs on %s\n", ++ inode, ceph_vinop(inode), pos, count, ceph_cap_string(got)); + + if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 || + (iocb->ki_flags & IOCB_DIRECT) || (fi->flags & CEPH_F_SYNC) || +@@ -2378,14 +2409,14 @@ retry_snap: + ceph_check_caps(ci, CHECK_CAPS_FLUSH); + } + +- dout("aio_write %p %llx.%llx %llu~%u dropping cap refs on %s\n", +- inode, ceph_vinop(inode), pos, (unsigned)count, +- ceph_cap_string(got)); ++ doutc(cl, "%p %llx.%llx %llu~%u dropping cap refs on %s\n", ++ inode, ceph_vinop(inode), pos, (unsigned)count, ++ ceph_cap_string(got)); + ceph_put_cap_refs(ci, got); + + if (written == -EOLDSNAPC) { +- dout("aio_write %p %llx.%llx %llu~%u" "got EOLDSNAPC, retrying\n", +- inode, ceph_vinop(inode), pos, (unsigned)count); ++ doutc(cl, "%p %llx.%llx %llu~%u" "got EOLDSNAPC, retrying\n", ++ inode, ceph_vinop(inode), pos, (unsigned)count); + goto retry_snap; + } + +@@ -2572,14 +2603,15 @@ static long ceph_fallocate(struct file * + struct inode *inode = file_inode(file); + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_cap_flush *prealloc_cf; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + int want, got = 0; + int dirty; + int ret = 0; + loff_t endoff = 0; + loff_t size; + +- dout("%s %p %llx.%llx mode %x, offset %llu length %llu\n", __func__, +- inode, ceph_vinop(inode), mode, offset, length); ++ doutc(cl, "%p %llx.%llx mode %x, offset %llu length %llu\n", ++ inode, ceph_vinop(inode), mode, offset, length); + + if (mode != (FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) + return -EOPNOTSUPP; +@@ -2708,6 +2740,7 @@ static void put_rd_wr_caps(struct ceph_i + static int is_file_size_ok(struct inode *src_inode, struct inode *dst_inode, + loff_t src_off, loff_t dst_off, size_t len) + { ++ struct ceph_client *cl = ceph_inode_to_client(src_inode); + loff_t size, endoff; + + size = i_size_read(src_inode); +@@ -2718,8 +2751,8 @@ static int is_file_size_ok(struct inode + * inode. + */ + if (src_off + len > size) { +- dout("Copy beyond EOF (%llu + %zu > %llu)\n", +- src_off, len, size); ++ doutc(cl, "Copy beyond EOF (%llu + %zu > %llu)\n", src_off, ++ len, size); + return -EOPNOTSUPP; + } + size = i_size_read(dst_inode); +@@ -2795,6 +2828,7 @@ static ssize_t ceph_do_objects_copy(stru + u64 src_objnum, src_objoff, dst_objnum, dst_objoff; + u32 src_objlen, dst_objlen; + u32 object_size = src_ci->i_layout.object_size; ++ struct ceph_client *cl = fsc->client; + int ret; + + src_oloc.pool = src_ci->i_layout.pool_id; +@@ -2836,9 +2870,10 @@ static ssize_t ceph_do_objects_copy(stru + if (ret) { + if (ret == -EOPNOTSUPP) { + fsc->have_copy_from2 = false; +- pr_notice("OSDs don't support copy-from2; disabling copy offload\n"); ++ pr_notice_client(cl, ++ "OSDs don't support copy-from2; disabling copy offload\n"); + } +- dout("ceph_osdc_copy_from returned %d\n", ret); ++ doutc(cl, "returned %d\n", ret); + if (!bytes) + bytes = ret; + goto out; +@@ -2865,6 +2900,7 @@ static ssize_t __ceph_copy_file_range(st + 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_fs_client(src_inode); ++ struct ceph_client *cl = src_fsc->client; + loff_t size; + ssize_t ret = -EIO, bytes; + u64 src_objnum, dst_objnum, src_objoff, dst_objoff; +@@ -2907,7 +2943,7 @@ static ssize_t __ceph_copy_file_range(st + (src_ci->i_layout.stripe_count != 1) || + (dst_ci->i_layout.stripe_count != 1) || + (src_ci->i_layout.object_size != dst_ci->i_layout.object_size)) { +- dout("Invalid src/dst files layout\n"); ++ doutc(cl, "Invalid src/dst files layout\n"); + return -EOPNOTSUPP; + } + +@@ -2925,12 +2961,12 @@ static ssize_t __ceph_copy_file_range(st + /* Start by sync'ing the source and destination files */ + ret = file_write_and_wait_range(src_file, src_off, (src_off + len)); + if (ret < 0) { +- dout("failed to write src file (%zd)\n", ret); ++ doutc(cl, "failed to write src file (%zd)\n", ret); + goto out; + } + ret = file_write_and_wait_range(dst_file, dst_off, (dst_off + len)); + if (ret < 0) { +- dout("failed to write dst file (%zd)\n", ret); ++ doutc(cl, "failed to write dst file (%zd)\n", ret); + goto out; + } + +@@ -2942,7 +2978,7 @@ static ssize_t __ceph_copy_file_range(st + err = get_rd_wr_caps(src_file, &src_got, + dst_file, (dst_off + len), &dst_got); + if (err < 0) { +- dout("get_rd_wr_caps returned %d\n", err); ++ doutc(cl, "get_rd_wr_caps returned %d\n", err); + ret = -EOPNOTSUPP; + goto out; + } +@@ -2957,7 +2993,8 @@ static ssize_t __ceph_copy_file_range(st + dst_off >> PAGE_SHIFT, + (dst_off + len) >> PAGE_SHIFT); + if (ret < 0) { +- dout("Failed to invalidate inode pages (%zd)\n", ret); ++ doutc(cl, "Failed to invalidate inode pages (%zd)\n", ++ ret); + ret = 0; /* XXX */ + } + ceph_calc_file_object_mapping(&src_ci->i_layout, src_off, +@@ -2978,7 +3015,7 @@ static ssize_t __ceph_copy_file_range(st + * starting at the src_off + */ + if (src_objoff) { +- dout("Initial partial copy of %u bytes\n", src_objlen); ++ doutc(cl, "Initial partial copy of %u bytes\n", src_objlen); + + /* + * we need to temporarily drop all caps as we'll be calling +@@ -2989,7 +3026,7 @@ static ssize_t __ceph_copy_file_range(st + &dst_off, src_objlen, flags); + /* Abort on short copies or on error */ + if (ret < (long)src_objlen) { +- dout("Failed partial copy (%zd)\n", ret); ++ doutc(cl, "Failed partial copy (%zd)\n", ret); + goto out; + } + len -= ret; +@@ -3011,7 +3048,7 @@ static ssize_t __ceph_copy_file_range(st + ret = bytes; + goto out_caps; + } +- dout("Copied %zu bytes out of %zu\n", bytes, len); ++ doutc(cl, "Copied %zu bytes out of %zu\n", bytes, len); + len -= bytes; + ret += bytes; + +@@ -3039,13 +3076,13 @@ out_caps: + * there were errors in remote object copies (len >= object_size). + */ + if (len && (len < src_ci->i_layout.object_size)) { +- dout("Final partial copy of %zu bytes\n", len); ++ doutc(cl, "Final partial copy of %zu bytes\n", len); + bytes = do_splice_direct(src_file, &src_off, dst_file, + &dst_off, len, flags); + if (bytes > 0) + ret += bytes; + else +- dout("Failed partial copy (%zd)\n", bytes); ++ doutc(cl, "Failed partial copy (%zd)\n", bytes); + } + + out: +--- a/fs/ceph/inode.c ++++ b/fs/ceph/inode.c +@@ -129,6 +129,8 @@ void ceph_as_ctx_to_req(struct ceph_mds_ + struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino, + struct inode *newino) + { ++ struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(sb); ++ struct ceph_client *cl = mdsc->fsc->client; + struct inode *inode; + + if (ceph_vino_is_reserved(vino)) +@@ -145,12 +147,13 @@ struct inode *ceph_get_inode(struct supe + } + + if (!inode) { +- dout("No inode found for %llx.%llx\n", vino.ino, vino.snap); ++ doutc(cl, "no inode found for %llx.%llx\n", vino.ino, vino.snap); + return ERR_PTR(-ENOMEM); + } + +- dout("get_inode on %llu=%llx.%llx got %p new %d\n", ceph_present_inode(inode), +- ceph_vinop(inode), inode, !!(inode->i_state & I_NEW)); ++ doutc(cl, "on %llx=%llx.%llx got %p new %d\n", ++ ceph_present_inode(inode), ceph_vinop(inode), inode, ++ !!(inode->i_state & I_NEW)); + return inode; + } + +@@ -159,6 +162,7 @@ struct inode *ceph_get_inode(struct supe + */ + struct inode *ceph_get_snapdir(struct inode *parent) + { ++ struct ceph_client *cl = ceph_inode_to_client(parent); + struct ceph_vino vino = { + .ino = ceph_ino(parent), + .snap = CEPH_SNAPDIR, +@@ -171,14 +175,14 @@ struct inode *ceph_get_snapdir(struct in + return inode; + + if (!S_ISDIR(parent->i_mode)) { +- pr_warn_once("bad snapdir parent type (mode=0%o)\n", +- parent->i_mode); ++ pr_warn_once_client(cl, "bad snapdir parent type (mode=0%o)\n", ++ parent->i_mode); + goto err; + } + + if (!(inode->i_state & I_NEW) && !S_ISDIR(inode->i_mode)) { +- pr_warn_once("bad snapdir inode type (mode=0%o)\n", +- inode->i_mode); ++ pr_warn_once_client(cl, "bad snapdir inode type (mode=0%o)\n", ++ inode->i_mode); + goto err; + } + +@@ -203,7 +207,7 @@ struct inode *ceph_get_snapdir(struct in + inode->i_flags |= S_ENCRYPTED; + ci->fscrypt_auth_len = pci->fscrypt_auth_len; + } else { +- dout("Failed to alloc snapdir fscrypt_auth\n"); ++ doutc(cl, "Failed to alloc snapdir fscrypt_auth\n"); + ret = -ENOMEM; + goto err; + } +@@ -249,6 +253,8 @@ const struct inode_operations ceph_file_ + static struct ceph_inode_frag *__get_or_create_frag(struct ceph_inode_info *ci, + u32 f) + { ++ struct inode *inode = &ci->netfs.inode; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct rb_node **p; + struct rb_node *parent = NULL; + struct ceph_inode_frag *frag; +@@ -279,8 +285,7 @@ static struct ceph_inode_frag *__get_or_ + rb_link_node(&frag->node, parent, p); + rb_insert_color(&frag->node, &ci->i_fragtree); + +- dout("get_or_create_frag added %llx.%llx frag %x\n", +- ceph_vinop(&ci->netfs.inode), f); ++ doutc(cl, "added %p %llx.%llx frag %x\n", inode, ceph_vinop(inode), f); + return frag; + } + +@@ -313,6 +318,7 @@ struct ceph_inode_frag *__ceph_find_frag + static u32 __ceph_choose_frag(struct ceph_inode_info *ci, u32 v, + struct ceph_inode_frag *pfrag, int *found) + { ++ struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode); + u32 t = ceph_frag_make(0, 0); + struct ceph_inode_frag *frag; + unsigned nway, i; +@@ -336,8 +342,8 @@ static u32 __ceph_choose_frag(struct cep + + /* choose child */ + nway = 1 << frag->split_by; +- dout("choose_frag(%x) %x splits by %d (%d ways)\n", v, t, +- frag->split_by, nway); ++ doutc(cl, "frag(%x) %x splits by %d (%d ways)\n", v, t, ++ frag->split_by, nway); + for (i = 0; i < nway; i++) { + n = ceph_frag_make_child(t, frag->split_by, i); + if (ceph_frag_contains_value(n, v)) { +@@ -347,7 +353,7 @@ static u32 __ceph_choose_frag(struct cep + } + BUG_ON(i == nway); + } +- dout("choose_frag(%x) = %x\n", v, t); ++ doutc(cl, "frag(%x) = %x\n", v, t); + + return t; + } +@@ -371,6 +377,7 @@ static int ceph_fill_dirfrag(struct inod + struct ceph_mds_reply_dirfrag *dirinfo) + { + struct ceph_inode_info *ci = ceph_inode(inode); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_frag *frag; + u32 id = le32_to_cpu(dirinfo->frag); + int mds = le32_to_cpu(dirinfo->auth); +@@ -395,14 +402,14 @@ static int ceph_fill_dirfrag(struct inod + goto out; + if (frag->split_by == 0) { + /* tree leaf, remove */ +- dout("fill_dirfrag removed %llx.%llx frag %x" +- " (no ref)\n", ceph_vinop(inode), id); ++ doutc(cl, "removed %p %llx.%llx frag %x (no ref)\n", ++ inode, ceph_vinop(inode), id); + rb_erase(&frag->node, &ci->i_fragtree); + kfree(frag); + } else { + /* tree branch, keep and clear */ +- dout("fill_dirfrag cleared %llx.%llx frag %x" +- " referral\n", ceph_vinop(inode), id); ++ doutc(cl, "cleared %p %llx.%llx frag %x referral\n", ++ inode, ceph_vinop(inode), id); + frag->mds = -1; + frag->ndist = 0; + } +@@ -415,8 +422,9 @@ static int ceph_fill_dirfrag(struct inod + if (IS_ERR(frag)) { + /* this is not the end of the world; we can continue + with bad/inaccurate delegation info */ +- pr_err("fill_dirfrag ENOMEM on mds ref %llx.%llx fg %x\n", +- ceph_vinop(inode), le32_to_cpu(dirinfo->frag)); ++ pr_err_client(cl, "ENOMEM on mds ref %p %llx.%llx fg %x\n", ++ inode, ceph_vinop(inode), ++ le32_to_cpu(dirinfo->frag)); + err = -ENOMEM; + goto out; + } +@@ -425,8 +433,8 @@ static int ceph_fill_dirfrag(struct inod + frag->ndist = min_t(u32, ndist, CEPH_MAX_DIRFRAG_REP); + for (i = 0; i < frag->ndist; i++) + frag->dist[i] = le32_to_cpu(dirinfo->dist[i]); +- dout("fill_dirfrag %llx.%llx frag %x ndist=%d\n", +- ceph_vinop(inode), frag->frag, frag->ndist); ++ doutc(cl, "%p %llx.%llx frag %x ndist=%d\n", inode, ++ ceph_vinop(inode), frag->frag, frag->ndist); + + out: + mutex_unlock(&ci->i_fragtree_mutex); +@@ -454,6 +462,7 @@ static int ceph_fill_fragtree(struct ino + struct ceph_frag_tree_head *fragtree, + struct ceph_mds_reply_dirfrag *dirinfo) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_inode_frag *frag, *prev_frag = NULL; + struct rb_node *rb_node; +@@ -489,15 +498,15 @@ static int ceph_fill_fragtree(struct ino + frag_tree_split_cmp, NULL); + } + +- dout("fill_fragtree %llx.%llx\n", ceph_vinop(inode)); ++ doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode)); + rb_node = rb_first(&ci->i_fragtree); + for (i = 0; i < nsplits; i++) { + id = le32_to_cpu(fragtree->splits[i].frag); + split_by = le32_to_cpu(fragtree->splits[i].by); + if (split_by == 0 || ceph_frag_bits(id) + split_by > 24) { +- pr_err("fill_fragtree %llx.%llx invalid split %d/%u, " +- "frag %x split by %d\n", ceph_vinop(inode), +- i, nsplits, id, split_by); ++ pr_err_client(cl, "%p %llx.%llx invalid split %d/%u, " ++ "frag %x split by %d\n", inode, ++ ceph_vinop(inode), i, nsplits, id, split_by); + continue; + } + frag = NULL; +@@ -529,7 +538,7 @@ static int ceph_fill_fragtree(struct ino + if (frag->split_by == 0) + ci->i_fragtree_nsplits++; + frag->split_by = split_by; +- dout(" frag %x split by %d\n", frag->frag, frag->split_by); ++ doutc(cl, " frag %x split by %d\n", frag->frag, frag->split_by); + prev_frag = frag; + } + while (rb_node) { +@@ -554,6 +563,7 @@ out_unlock: + */ + struct inode *ceph_alloc_inode(struct super_block *sb) + { ++ struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb); + struct ceph_inode_info *ci; + int i; + +@@ -561,7 +571,7 @@ struct inode *ceph_alloc_inode(struct su + if (!ci) + return NULL; + +- dout("alloc_inode %p\n", &ci->netfs.inode); ++ doutc(fsc->client, "%p\n", &ci->netfs.inode); + + /* Set parameters for the netfs library */ + netfs_inode_init(&ci->netfs, &ceph_netfs_ops); +@@ -675,10 +685,11 @@ void ceph_evict_inode(struct inode *inod + { + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_frag *frag; + struct rb_node *n; + +- dout("evict_inode %p ino %llx.%llx\n", inode, ceph_vinop(inode)); ++ doutc(cl, "%p ino %llx.%llx\n", inode, ceph_vinop(inode)); + + percpu_counter_dec(&mdsc->metric.total_inodes); + +@@ -701,8 +712,8 @@ void ceph_evict_inode(struct inode *inod + */ + if (ci->i_snap_realm) { + if (ceph_snap(inode) == CEPH_NOSNAP) { +- dout(" dropping residual ref to snap realm %p\n", +- ci->i_snap_realm); ++ doutc(cl, " dropping residual ref to snap realm %p\n", ++ ci->i_snap_realm); + ceph_change_snap_realm(inode, NULL); + } else { + ceph_put_snapid_map(mdsc, ci->i_snapid_map); +@@ -743,15 +754,16 @@ static inline blkcnt_t calc_inode_blocks + int ceph_fill_file_size(struct inode *inode, int issued, + u32 truncate_seq, u64 truncate_size, u64 size) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + int queue_trunc = 0; + loff_t isize = i_size_read(inode); + + if (ceph_seq_cmp(truncate_seq, ci->i_truncate_seq) > 0 || + (truncate_seq == ci->i_truncate_seq && size > isize)) { +- dout("size %lld -> %llu\n", isize, size); ++ doutc(cl, "size %lld -> %llu\n", isize, size); + if (size > 0 && S_ISDIR(inode->i_mode)) { +- pr_err("fill_file_size non-zero size for directory\n"); ++ pr_err_client(cl, "non-zero size for directory\n"); + size = 0; + } + i_size_write(inode, size); +@@ -764,8 +776,8 @@ int ceph_fill_file_size(struct inode *in + ceph_fscache_update(inode); + ci->i_reported_size = size; + if (truncate_seq != ci->i_truncate_seq) { +- dout("%s truncate_seq %u -> %u\n", __func__, +- ci->i_truncate_seq, truncate_seq); ++ doutc(cl, "truncate_seq %u -> %u\n", ++ ci->i_truncate_seq, truncate_seq); + ci->i_truncate_seq = truncate_seq; + + /* the MDS should have revoked these caps */ +@@ -794,14 +806,15 @@ int ceph_fill_file_size(struct inode *in + * anyway. + */ + if (ceph_seq_cmp(truncate_seq, ci->i_truncate_seq) >= 0) { +- dout("%s truncate_size %lld -> %llu, encrypted %d\n", __func__, +- ci->i_truncate_size, truncate_size, !!IS_ENCRYPTED(inode)); ++ doutc(cl, "truncate_size %lld -> %llu, encrypted %d\n", ++ ci->i_truncate_size, truncate_size, ++ !!IS_ENCRYPTED(inode)); + + ci->i_truncate_size = truncate_size; + + if (IS_ENCRYPTED(inode)) { +- dout("%s truncate_pagecache_size %lld -> %llu\n", +- __func__, ci->i_truncate_pagecache_size, size); ++ doutc(cl, "truncate_pagecache_size %lld -> %llu\n", ++ ci->i_truncate_pagecache_size, size); + ci->i_truncate_pagecache_size = size; + } else { + ci->i_truncate_pagecache_size = truncate_size; +@@ -814,6 +827,7 @@ void ceph_fill_file_time(struct inode *i + u64 time_warp_seq, struct timespec64 *ctime, + struct timespec64 *mtime, struct timespec64 *atime) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + struct timespec64 ictime = inode_get_ctime(inode); + int warn = 0; +@@ -825,7 +839,7 @@ void ceph_fill_file_time(struct inode *i + CEPH_CAP_XATTR_EXCL)) { + if (ci->i_version == 0 || + timespec64_compare(ctime, &ictime) > 0) { +- dout("ctime %lld.%09ld -> %lld.%09ld inc w/ cap\n", ++ doutc(cl, "ctime %lld.%09ld -> %lld.%09ld inc w/ cap\n", + ictime.tv_sec, ictime.tv_nsec, + ctime->tv_sec, ctime->tv_nsec); + inode_set_ctime_to_ts(inode, *ctime); +@@ -833,11 +847,10 @@ void ceph_fill_file_time(struct inode *i + if (ci->i_version == 0 || + ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) > 0) { + /* the MDS did a utimes() */ +- dout("mtime %lld.%09ld -> %lld.%09ld " +- "tw %d -> %d\n", +- inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec, +- mtime->tv_sec, mtime->tv_nsec, +- ci->i_time_warp_seq, (int)time_warp_seq); ++ doutc(cl, "mtime %lld.%09ld -> %lld.%09ld tw %d -> %d\n", ++ inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec, ++ mtime->tv_sec, mtime->tv_nsec, ++ ci->i_time_warp_seq, (int)time_warp_seq); + + inode->i_mtime = *mtime; + inode->i_atime = *atime; +@@ -845,17 +858,17 @@ void ceph_fill_file_time(struct inode *i + } else if (time_warp_seq == ci->i_time_warp_seq) { + /* nobody did utimes(); take the max */ + if (timespec64_compare(mtime, &inode->i_mtime) > 0) { +- dout("mtime %lld.%09ld -> %lld.%09ld inc\n", +- inode->i_mtime.tv_sec, +- inode->i_mtime.tv_nsec, +- mtime->tv_sec, mtime->tv_nsec); ++ doutc(cl, "mtime %lld.%09ld -> %lld.%09ld inc\n", ++ inode->i_mtime.tv_sec, ++ inode->i_mtime.tv_nsec, ++ mtime->tv_sec, mtime->tv_nsec); + inode->i_mtime = *mtime; + } + if (timespec64_compare(atime, &inode->i_atime) > 0) { +- dout("atime %lld.%09ld -> %lld.%09ld inc\n", +- inode->i_atime.tv_sec, +- inode->i_atime.tv_nsec, +- atime->tv_sec, atime->tv_nsec); ++ doutc(cl, "atime %lld.%09ld -> %lld.%09ld inc\n", ++ inode->i_atime.tv_sec, ++ inode->i_atime.tv_nsec, ++ atime->tv_sec, atime->tv_nsec); + inode->i_atime = *atime; + } + } else if (issued & CEPH_CAP_FILE_EXCL) { +@@ -875,13 +888,16 @@ void ceph_fill_file_time(struct inode *i + } + } + if (warn) /* time_warp_seq shouldn't go backwards */ +- dout("%p mds time_warp_seq %llu < %u\n", +- inode, time_warp_seq, ci->i_time_warp_seq); ++ doutc(cl, "%p mds time_warp_seq %llu < %u\n", inode, ++ time_warp_seq, ci->i_time_warp_seq); + } + + #if IS_ENABLED(CONFIG_FS_ENCRYPTION) +-static int decode_encrypted_symlink(const char *encsym, int enclen, u8 **decsym) ++static int decode_encrypted_symlink(struct ceph_mds_client *mdsc, ++ const char *encsym, ++ int enclen, u8 **decsym) + { ++ struct ceph_client *cl = mdsc->fsc->client; + int declen; + u8 *sym; + +@@ -891,8 +907,9 @@ static int decode_encrypted_symlink(cons + + declen = ceph_base64_decode(encsym, enclen, sym); + if (declen < 0) { +- pr_err("%s: can't decode symlink (%d). Content: %.*s\n", +- __func__, declen, enclen, encsym); ++ pr_err_client(cl, ++ "can't decode symlink (%d). Content: %.*s\n", ++ declen, enclen, encsym); + kfree(sym); + return -EIO; + } +@@ -901,7 +918,9 @@ static int decode_encrypted_symlink(cons + return declen; + } + #else +-static int decode_encrypted_symlink(const char *encsym, int symlen, u8 **decsym) ++static int decode_encrypted_symlink(struct ceph_mds_client *mdsc, ++ const char *encsym, ++ int symlen, u8 **decsym) + { + return -EOPNOTSUPP; + } +@@ -918,6 +937,7 @@ int ceph_fill_inode(struct inode *inode, + struct ceph_cap_reservation *caps_reservation) + { + struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb); ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_reply_inode *info = iinfo->in; + struct ceph_inode_info *ci = ceph_inode(inode); + int issued, new_issued, info_caps; +@@ -936,25 +956,26 @@ int ceph_fill_inode(struct inode *inode, + + lockdep_assert_held(&mdsc->snap_rwsem); + +- dout("%s %p ino %llx.%llx v %llu had %llu\n", __func__, +- inode, ceph_vinop(inode), le64_to_cpu(info->version), +- ci->i_version); ++ doutc(cl, "%p ino %llx.%llx v %llu had %llu\n", inode, ceph_vinop(inode), ++ le64_to_cpu(info->version), ci->i_version); + + /* Once I_NEW is cleared, we can't change type or dev numbers */ + if (inode->i_state & I_NEW) { + inode->i_mode = mode; + } else { + if (inode_wrong_type(inode, mode)) { +- pr_warn_once("inode type changed! (ino %llx.%llx is 0%o, mds says 0%o)\n", +- ceph_vinop(inode), inode->i_mode, mode); ++ pr_warn_once_client(cl, ++ "inode type changed! (ino %llx.%llx is 0%o, mds says 0%o)\n", ++ ceph_vinop(inode), inode->i_mode, mode); + return -ESTALE; + } + + if ((S_ISCHR(mode) || S_ISBLK(mode)) && inode->i_rdev != rdev) { +- pr_warn_once("dev inode rdev changed! (ino %llx.%llx is %u:%u, mds says %u:%u)\n", +- ceph_vinop(inode), MAJOR(inode->i_rdev), +- MINOR(inode->i_rdev), MAJOR(rdev), +- MINOR(rdev)); ++ pr_warn_once_client(cl, ++ "dev inode rdev changed! (ino %llx.%llx is %u:%u, mds says %u:%u)\n", ++ ceph_vinop(inode), MAJOR(inode->i_rdev), ++ MINOR(inode->i_rdev), MAJOR(rdev), ++ MINOR(rdev)); + return -ESTALE; + } + } +@@ -976,8 +997,8 @@ int ceph_fill_inode(struct inode *inode, + if (iinfo->xattr_len > 4) { + xattr_blob = ceph_buffer_new(iinfo->xattr_len, GFP_NOFS); + if (!xattr_blob) +- pr_err("%s ENOMEM xattr blob %d bytes\n", __func__, +- iinfo->xattr_len); ++ pr_err_client(cl, "ENOMEM xattr blob %d bytes\n", ++ iinfo->xattr_len); + } + + if (iinfo->pool_ns_len > 0) +@@ -1031,9 +1052,10 @@ int ceph_fill_inode(struct inode *inode, + inode->i_mode = mode; + inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(info->uid)); + inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(info->gid)); +- dout("%p mode 0%o uid.gid %d.%d\n", inode, inode->i_mode, +- from_kuid(&init_user_ns, inode->i_uid), +- from_kgid(&init_user_ns, inode->i_gid)); ++ doutc(cl, "%p %llx.%llx mode 0%o uid.gid %d.%d\n", inode, ++ ceph_vinop(inode), inode->i_mode, ++ from_kuid(&init_user_ns, inode->i_uid), ++ from_kgid(&init_user_ns, inode->i_gid)); + ceph_decode_timespec64(&ci->i_btime, &iinfo->btime); + ceph_decode_timespec64(&ci->i_snap_btime, &iinfo->snap_btime); + } +@@ -1089,7 +1111,8 @@ int ceph_fill_inode(struct inode *inode, + if (size == round_up(fsize, CEPH_FSCRYPT_BLOCK_SIZE)) { + size = fsize; + } else { +- pr_warn("fscrypt size mismatch: size=%llu fscrypt_file=%llu, discarding fscrypt_file size.\n", ++ pr_warn_client(cl, ++ "fscrypt size mismatch: size=%llu fscrypt_file=%llu, discarding fscrypt_file size.\n", + info->size, size); + } + } +@@ -1101,8 +1124,8 @@ int ceph_fill_inode(struct inode *inode, + /* only update max_size on auth cap */ + if ((info->cap.flags & CEPH_CAP_FLAG_AUTH) && + ci->i_max_size != le64_to_cpu(info->max_size)) { +- dout("max_size %lld -> %llu\n", ci->i_max_size, +- le64_to_cpu(info->max_size)); ++ doutc(cl, "max_size %lld -> %llu\n", ++ ci->i_max_size, le64_to_cpu(info->max_size)); + ci->i_max_size = le64_to_cpu(info->max_size); + } + } +@@ -1165,15 +1188,17 @@ int ceph_fill_inode(struct inode *inode, + + if (IS_ENCRYPTED(inode)) { + if (symlen != i_size_read(inode)) +- pr_err("%s %llx.%llx BAD symlink size %lld\n", +- __func__, ceph_vinop(inode), ++ pr_err_client(cl, ++ "%p %llx.%llx BAD symlink size %lld\n", ++ inode, ceph_vinop(inode), + i_size_read(inode)); + +- err = decode_encrypted_symlink(iinfo->symlink, ++ err = decode_encrypted_symlink(mdsc, iinfo->symlink, + symlen, (u8 **)&sym); + if (err < 0) { +- pr_err("%s decoding encrypted symlink failed: %d\n", +- __func__, err); ++ pr_err_client(cl, ++ "decoding encrypted symlink failed: %d\n", ++ err); + goto out; + } + symlen = err; +@@ -1181,8 +1206,9 @@ int ceph_fill_inode(struct inode *inode, + inode->i_blocks = calc_inode_blocks(symlen); + } else { + if (symlen != i_size_read(inode)) { +- pr_err("%s %llx.%llx BAD symlink size %lld\n", +- __func__, ceph_vinop(inode), ++ pr_err_client(cl, ++ "%p %llx.%llx BAD symlink size %lld\n", ++ inode, ceph_vinop(inode), + i_size_read(inode)); + i_size_write(inode, symlen); + inode->i_blocks = calc_inode_blocks(symlen); +@@ -1217,8 +1243,8 @@ int ceph_fill_inode(struct inode *inode, + inode->i_fop = &ceph_dir_fops; + break; + default: +- pr_err("%s %llx.%llx BAD mode 0%o\n", __func__, +- ceph_vinop(inode), inode->i_mode); ++ pr_err_client(cl, "%p %llx.%llx BAD mode 0%o\n", inode, ++ ceph_vinop(inode), inode->i_mode); + } + + /* were we issued a capability? */ +@@ -1239,7 +1265,8 @@ int ceph_fill_inode(struct inode *inode, + (info_caps & CEPH_CAP_FILE_SHARED) && + (issued & CEPH_CAP_FILE_EXCL) == 0 && + !__ceph_dir_is_complete(ci)) { +- dout(" marking %p complete (empty)\n", inode); ++ doutc(cl, " marking %p complete (empty)\n", ++ inode); + i_size_write(inode, 0); + __ceph_dir_set_complete(ci, + atomic64_read(&ci->i_release_count), +@@ -1248,8 +1275,8 @@ int ceph_fill_inode(struct inode *inode, + + wake = true; + } else { +- dout(" %p got snap_caps %s\n", inode, +- ceph_cap_string(info_caps)); ++ doutc(cl, " %p got snap_caps %s\n", inode, ++ ceph_cap_string(info_caps)); + ci->i_snap_caps |= info_caps; + } + } +@@ -1265,8 +1292,8 @@ int ceph_fill_inode(struct inode *inode, + + if (cap_fmode >= 0) { + if (!info_caps) +- pr_warn("mds issued no caps on %llx.%llx\n", +- ceph_vinop(inode)); ++ pr_warn_client(cl, "mds issued no caps on %llx.%llx\n", ++ ceph_vinop(inode)); + __ceph_touch_fmode(ci, mdsc, cap_fmode); + } + +@@ -1312,14 +1339,14 @@ static void __update_dentry_lease(struct + unsigned long from_time, + struct ceph_mds_session **old_lease_session) + { ++ struct ceph_client *cl = ceph_inode_to_client(dir); + struct ceph_dentry_info *di = ceph_dentry(dentry); + unsigned mask = le16_to_cpu(lease->mask); + long unsigned duration = le32_to_cpu(lease->duration_ms); + long unsigned ttl = from_time + (duration * HZ) / 1000; + long unsigned half_ttl = from_time + (duration * HZ / 2) / 1000; + +- dout("update_dentry_lease %p duration %lu ms ttl %lu\n", +- dentry, duration, ttl); ++ doutc(cl, "%p duration %lu ms ttl %lu\n", dentry, duration, ttl); + + /* only track leases on regular dentries */ + if (ceph_snap(dir) != CEPH_NOSNAP) +@@ -1420,6 +1447,7 @@ out_unlock: + */ + static int splice_dentry(struct dentry **pdn, struct inode *in) + { ++ struct ceph_client *cl = ceph_inode_to_client(in); + struct dentry *dn = *pdn; + struct dentry *realdn; + +@@ -1451,23 +1479,21 @@ static int splice_dentry(struct dentry * + d_drop(dn); + realdn = d_splice_alias(in, dn); + if (IS_ERR(realdn)) { +- pr_err("splice_dentry error %ld %p inode %p ino %llx.%llx\n", +- PTR_ERR(realdn), dn, in, ceph_vinop(in)); ++ pr_err_client(cl, "error %ld %p inode %p ino %llx.%llx\n", ++ PTR_ERR(realdn), dn, in, ceph_vinop(in)); + return PTR_ERR(realdn); + } + + if (realdn) { +- dout("dn %p (%d) spliced with %p (%d) " +- "inode %p ino %llx.%llx\n", +- dn, d_count(dn), +- realdn, d_count(realdn), +- d_inode(realdn), ceph_vinop(d_inode(realdn))); ++ doutc(cl, "dn %p (%d) spliced with %p (%d) inode %p ino %llx.%llx\n", ++ dn, d_count(dn), realdn, d_count(realdn), ++ d_inode(realdn), ceph_vinop(d_inode(realdn))); + dput(dn); + *pdn = realdn; + } else { + BUG_ON(!ceph_dentry(dn)); +- dout("dn %p attached to %p ino %llx.%llx\n", +- dn, d_inode(dn), ceph_vinop(d_inode(dn))); ++ doutc(cl, "dn %p attached to %p ino %llx.%llx\n", dn, ++ d_inode(dn), ceph_vinop(d_inode(dn))); + } + return 0; + } +@@ -1490,13 +1516,14 @@ int ceph_fill_trace(struct super_block * + struct inode *in = NULL; + struct ceph_vino tvino, dvino; + struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb); ++ struct ceph_client *cl = fsc->client; + int err = 0; + +- dout("fill_trace %p is_dentry %d is_target %d\n", req, +- rinfo->head->is_dentry, rinfo->head->is_target); ++ doutc(cl, "%p is_dentry %d is_target %d\n", req, ++ rinfo->head->is_dentry, rinfo->head->is_target); + + if (!rinfo->head->is_target && !rinfo->head->is_dentry) { +- dout("fill_trace reply is empty!\n"); ++ doutc(cl, "reply is empty!\n"); + if (rinfo->head->result == 0 && req->r_parent) + ceph_invalidate_dir_request(req); + return 0; +@@ -1553,13 +1580,13 @@ int ceph_fill_trace(struct super_block * + tvino.snap = le64_to_cpu(rinfo->targeti.in->snapid); + retry_lookup: + dn = d_lookup(parent, &dname); +- dout("d_lookup on parent=%p name=%.*s got %p\n", +- parent, dname.len, dname.name, dn); ++ doutc(cl, "d_lookup on parent=%p name=%.*s got %p\n", ++ parent, dname.len, dname.name, dn); + + if (!dn) { + dn = d_alloc(parent, &dname); +- dout("d_alloc %p '%.*s' = %p\n", parent, +- dname.len, dname.name, dn); ++ doutc(cl, "d_alloc %p '%.*s' = %p\n", parent, ++ dname.len, dname.name, dn); + if (!dn) { + dput(parent); + ceph_fname_free_buffer(dir, &oname); +@@ -1575,8 +1602,8 @@ retry_lookup: + } else if (d_really_is_positive(dn) && + (ceph_ino(d_inode(dn)) != tvino.ino || + ceph_snap(d_inode(dn)) != tvino.snap)) { +- dout(" dn %p points to wrong inode %p\n", +- dn, d_inode(dn)); ++ doutc(cl, " dn %p points to wrong inode %p\n", ++ dn, d_inode(dn)); + ceph_dir_clear_ordered(dir); + d_delete(dn); + dput(dn); +@@ -1601,8 +1628,8 @@ retry_lookup: + rinfo->head->result == 0) ? req->r_fmode : -1, + &req->r_caps_reservation); + if (err < 0) { +- pr_err("ceph_fill_inode badness %p %llx.%llx\n", +- in, ceph_vinop(in)); ++ pr_err_client(cl, "badness %p %llx.%llx\n", in, ++ ceph_vinop(in)); + req->r_target_inode = NULL; + if (in->i_state & I_NEW) + discard_new_inode(in); +@@ -1652,36 +1679,32 @@ retry_lookup: + have_lease = have_dir_cap || + le32_to_cpu(rinfo->dlease->duration_ms); + if (!have_lease) +- dout("fill_trace no dentry lease or dir cap\n"); ++ doutc(cl, "no dentry lease or dir cap\n"); + + /* rename? */ + if (req->r_old_dentry && req->r_op == CEPH_MDS_OP_RENAME) { + struct inode *olddir = req->r_old_dentry_dir; + BUG_ON(!olddir); + +- dout(" src %p '%pd' dst %p '%pd'\n", +- req->r_old_dentry, +- req->r_old_dentry, +- dn, dn); +- dout("fill_trace doing d_move %p -> %p\n", +- req->r_old_dentry, dn); ++ doutc(cl, " src %p '%pd' dst %p '%pd'\n", ++ req->r_old_dentry, req->r_old_dentry, dn, dn); ++ doutc(cl, "doing d_move %p -> %p\n", req->r_old_dentry, dn); + + /* d_move screws up sibling dentries' offsets */ + ceph_dir_clear_ordered(dir); + ceph_dir_clear_ordered(olddir); + + d_move(req->r_old_dentry, dn); +- dout(" src %p '%pd' dst %p '%pd'\n", +- req->r_old_dentry, +- req->r_old_dentry, +- dn, dn); ++ doutc(cl, " src %p '%pd' dst %p '%pd'\n", ++ req->r_old_dentry, req->r_old_dentry, dn, dn); + + /* ensure target dentry is invalidated, despite + rehashing bug in vfs_rename_dir */ + ceph_invalidate_dentry_lease(dn); + +- dout("dn %p gets new offset %lld\n", req->r_old_dentry, +- ceph_dentry(req->r_old_dentry)->offset); ++ doutc(cl, "dn %p gets new offset %lld\n", ++ req->r_old_dentry, ++ ceph_dentry(req->r_old_dentry)->offset); + + /* swap r_dentry and r_old_dentry in case that + * splice_dentry() gets called later. This is safe +@@ -1693,9 +1716,9 @@ retry_lookup: + + /* null dentry? */ + if (!rinfo->head->is_target) { +- dout("fill_trace null dentry\n"); ++ doutc(cl, "null dentry\n"); + if (d_really_is_positive(dn)) { +- dout("d_delete %p\n", dn); ++ doutc(cl, "d_delete %p\n", dn); + ceph_dir_clear_ordered(dir); + d_delete(dn); + } else if (have_lease) { +@@ -1719,9 +1742,9 @@ retry_lookup: + goto done; + dn = req->r_dentry; /* may have spliced */ + } else if (d_really_is_positive(dn) && d_inode(dn) != in) { +- dout(" %p links to %p %llx.%llx, not %llx.%llx\n", +- dn, d_inode(dn), ceph_vinop(d_inode(dn)), +- ceph_vinop(in)); ++ doutc(cl, " %p links to %p %llx.%llx, not %llx.%llx\n", ++ dn, d_inode(dn), ceph_vinop(d_inode(dn)), ++ ceph_vinop(in)); + d_invalidate(dn); + have_lease = false; + } +@@ -1731,7 +1754,7 @@ retry_lookup: + rinfo->dlease, session, + req->r_request_started); + } +- dout(" final dn %p\n", dn); ++ doutc(cl, " final dn %p\n", dn); + } else if ((req->r_op == CEPH_MDS_OP_LOOKUPSNAP || + req->r_op == CEPH_MDS_OP_MKSNAP) && + test_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags) && +@@ -1742,7 +1765,8 @@ retry_lookup: + BUG_ON(!dir); + BUG_ON(ceph_snap(dir) != CEPH_SNAPDIR); + BUG_ON(!req->r_dentry); +- dout(" linking snapped dir %p to dn %p\n", in, req->r_dentry); ++ doutc(cl, " linking snapped dir %p to dn %p\n", in, ++ req->r_dentry); + ceph_dir_clear_ordered(dir); + ihold(in); + err = splice_dentry(&req->r_dentry, in); +@@ -1764,7 +1788,7 @@ retry_lookup: + &dvino, ptvino); + } + done: +- dout("fill_trace done err=%d\n", err); ++ doutc(cl, "done err=%d\n", err); + return err; + } + +@@ -1775,6 +1799,7 @@ static int readdir_prepopulate_inodes_on + struct ceph_mds_session *session) + { + struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info; ++ struct ceph_client *cl = session->s_mdsc->fsc->client; + int i, err = 0; + + for (i = 0; i < rinfo->dir_nr; i++) { +@@ -1789,14 +1814,14 @@ static int readdir_prepopulate_inodes_on + in = ceph_get_inode(req->r_dentry->d_sb, vino, NULL); + if (IS_ERR(in)) { + err = PTR_ERR(in); +- dout("new_inode badness got %d\n", err); ++ doutc(cl, "badness got %d\n", err); + continue; + } + rc = ceph_fill_inode(in, NULL, &rde->inode, NULL, session, + -1, &req->r_caps_reservation); + if (rc < 0) { +- pr_err("ceph_fill_inode badness on %p got %d\n", +- in, rc); ++ pr_err_client(cl, "inode badness on %p got %d\n", in, ++ rc); + err = rc; + if (in->i_state & I_NEW) { + ihold(in); +@@ -1825,6 +1850,7 @@ static int fill_readdir_cache(struct ino + struct ceph_readdir_cache_control *ctl, + struct ceph_mds_request *req) + { ++ struct ceph_client *cl = ceph_inode_to_client(dir); + struct ceph_inode_info *ci = ceph_inode(dir); + unsigned nsize = PAGE_SIZE / sizeof(struct dentry*); + unsigned idx = ctl->index % nsize; +@@ -1850,11 +1876,11 @@ static int fill_readdir_cache(struct ino + + if (req->r_dir_release_cnt == atomic64_read(&ci->i_release_count) && + req->r_dir_ordered_cnt == atomic64_read(&ci->i_ordered_count)) { +- dout("readdir cache dn %p idx %d\n", dn, ctl->index); ++ doutc(cl, "dn %p idx %d\n", dn, ctl->index); + ctl->dentries[idx] = dn; + ctl->index++; + } else { +- dout("disable readdir cache\n"); ++ doutc(cl, "disable readdir cache\n"); + ctl->index = -1; + } + return 0; +@@ -1867,6 +1893,7 @@ int ceph_readdir_prepopulate(struct ceph + struct inode *inode = d_inode(parent); + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info; ++ struct ceph_client *cl = session->s_mdsc->fsc->client; + struct qstr dname; + struct dentry *dn; + struct inode *in; +@@ -1894,19 +1921,18 @@ int ceph_readdir_prepopulate(struct ceph + + if (rinfo->dir_dir && + le32_to_cpu(rinfo->dir_dir->frag) != frag) { +- dout("readdir_prepopulate got new frag %x -> %x\n", +- frag, le32_to_cpu(rinfo->dir_dir->frag)); ++ doutc(cl, "got new frag %x -> %x\n", frag, ++ le32_to_cpu(rinfo->dir_dir->frag)); + frag = le32_to_cpu(rinfo->dir_dir->frag); + if (!rinfo->hash_order) + req->r_readdir_offset = 2; + } + + if (le32_to_cpu(rinfo->head->op) == CEPH_MDS_OP_LSSNAP) { +- dout("readdir_prepopulate %d items under SNAPDIR dn %p\n", +- rinfo->dir_nr, parent); ++ doutc(cl, "%d items under SNAPDIR dn %p\n", ++ rinfo->dir_nr, parent); + } else { +- dout("readdir_prepopulate %d items under dn %p\n", +- rinfo->dir_nr, parent); ++ doutc(cl, "%d items under dn %p\n", rinfo->dir_nr, parent); + if (rinfo->dir_dir) + ceph_fill_dirfrag(d_inode(parent), rinfo->dir_dir); + +@@ -1950,15 +1976,15 @@ int ceph_readdir_prepopulate(struct ceph + + retry_lookup: + dn = d_lookup(parent, &dname); +- dout("d_lookup on parent=%p name=%.*s got %p\n", +- parent, dname.len, dname.name, dn); ++ doutc(cl, "d_lookup on parent=%p name=%.*s got %p\n", ++ parent, dname.len, dname.name, dn); + + if (!dn) { + dn = d_alloc(parent, &dname); +- dout("d_alloc %p '%.*s' = %p\n", parent, +- dname.len, dname.name, dn); ++ doutc(cl, "d_alloc %p '%.*s' = %p\n", parent, ++ dname.len, dname.name, dn); + if (!dn) { +- dout("d_alloc badness\n"); ++ doutc(cl, "d_alloc badness\n"); + err = -ENOMEM; + goto out; + } +@@ -1971,8 +1997,8 @@ retry_lookup: + (ceph_ino(d_inode(dn)) != tvino.ino || + ceph_snap(d_inode(dn)) != tvino.snap)) { + struct ceph_dentry_info *di = ceph_dentry(dn); +- dout(" dn %p points to wrong inode %p\n", +- dn, d_inode(dn)); ++ doutc(cl, " dn %p points to wrong inode %p\n", ++ dn, d_inode(dn)); + + spin_lock(&dn->d_lock); + if (di->offset > 0 && +@@ -1994,7 +2020,7 @@ retry_lookup: + } else { + in = ceph_get_inode(parent->d_sb, tvino, NULL); + if (IS_ERR(in)) { +- dout("new_inode badness\n"); ++ doutc(cl, "new_inode badness\n"); + d_drop(dn); + dput(dn); + err = PTR_ERR(in); +@@ -2005,7 +2031,8 @@ retry_lookup: + ret = ceph_fill_inode(in, NULL, &rde->inode, NULL, session, + -1, &req->r_caps_reservation); + if (ret < 0) { +- pr_err("ceph_fill_inode badness on %p\n", in); ++ pr_err_client(cl, "badness on %p %llx.%llx\n", in, ++ ceph_vinop(in)); + if (d_really_is_negative(dn)) { + if (in->i_state & I_NEW) { + ihold(in); +@@ -2022,8 +2049,8 @@ retry_lookup: + + if (d_really_is_negative(dn)) { + if (ceph_security_xattr_deadlock(in)) { +- dout(" skip splicing dn %p to inode %p" +- " (security xattr deadlock)\n", dn, in); ++ doutc(cl, " skip splicing dn %p to inode %p" ++ " (security xattr deadlock)\n", dn, in); + iput(in); + skipped++; + goto next_item; +@@ -2055,17 +2082,18 @@ out: + req->r_readdir_cache_idx = cache_ctl.index; + } + ceph_readdir_cache_release(&cache_ctl); +- dout("readdir_prepopulate done\n"); ++ doutc(cl, "done\n"); + return err; + } + + bool ceph_inode_set_size(struct inode *inode, loff_t size) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + bool ret; + + spin_lock(&ci->i_ceph_lock); +- dout("set_size %p %llu -> %llu\n", inode, i_size_read(inode), size); ++ doutc(cl, "set_size %p %llu -> %llu\n", inode, i_size_read(inode), size); + i_size_write(inode, size); + ceph_fscache_update(inode); + inode->i_blocks = calc_inode_blocks(size); +@@ -2080,21 +2108,24 @@ bool ceph_inode_set_size(struct inode *i + void ceph_queue_inode_work(struct inode *inode, int work_bit) + { + struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode); ++ struct ceph_client *cl = fsc->client; + struct ceph_inode_info *ci = ceph_inode(inode); + set_bit(work_bit, &ci->i_work_mask); + + ihold(inode); + if (queue_work(fsc->inode_wq, &ci->i_work)) { +- dout("queue_inode_work %p, mask=%lx\n", inode, ci->i_work_mask); ++ doutc(cl, "%p %llx.%llx mask=%lx\n", inode, ++ ceph_vinop(inode), ci->i_work_mask); + } else { +- dout("queue_inode_work %p already queued, mask=%lx\n", +- inode, ci->i_work_mask); ++ doutc(cl, "%p %llx.%llx already queued, mask=%lx\n", ++ inode, ceph_vinop(inode), ci->i_work_mask); + iput(inode); + } + } + + static void ceph_do_invalidate_pages(struct inode *inode) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + u32 orig_gen; + int check = 0; +@@ -2104,8 +2135,9 @@ static void ceph_do_invalidate_pages(str + mutex_lock(&ci->i_truncate_mutex); + + if (ceph_inode_is_shutdown(inode)) { +- pr_warn_ratelimited("%s: inode %llx.%llx is shut down\n", +- __func__, ceph_vinop(inode)); ++ pr_warn_ratelimited_client(cl, ++ "%p %llx.%llx is shut down\n", inode, ++ ceph_vinop(inode)); + mapping_set_error(inode->i_mapping, -EIO); + truncate_pagecache(inode, 0); + mutex_unlock(&ci->i_truncate_mutex); +@@ -2113,8 +2145,8 @@ static void ceph_do_invalidate_pages(str + } + + spin_lock(&ci->i_ceph_lock); +- dout("invalidate_pages %p gen %d revoking %d\n", inode, +- ci->i_rdcache_gen, ci->i_rdcache_revoking); ++ doutc(cl, "%p %llx.%llx gen %d revoking %d\n", inode, ++ ceph_vinop(inode), ci->i_rdcache_gen, ci->i_rdcache_revoking); + if (ci->i_rdcache_revoking != ci->i_rdcache_gen) { + if (__ceph_caps_revoking_other(ci, NULL, CEPH_CAP_FILE_CACHE)) + check = 1; +@@ -2126,21 +2158,21 @@ static void ceph_do_invalidate_pages(str + spin_unlock(&ci->i_ceph_lock); + + if (invalidate_inode_pages2(inode->i_mapping) < 0) { +- pr_err("invalidate_inode_pages2 %llx.%llx failed\n", +- ceph_vinop(inode)); ++ pr_err_client(cl, "invalidate_inode_pages2 %llx.%llx failed\n", ++ ceph_vinop(inode)); + } + + spin_lock(&ci->i_ceph_lock); + if (orig_gen == ci->i_rdcache_gen && + orig_gen == ci->i_rdcache_revoking) { +- dout("invalidate_pages %p gen %d successful\n", inode, +- ci->i_rdcache_gen); ++ doutc(cl, "%p %llx.%llx gen %d successful\n", inode, ++ ceph_vinop(inode), ci->i_rdcache_gen); + ci->i_rdcache_revoking--; + check = 1; + } else { +- dout("invalidate_pages %p gen %d raced, now %d revoking %d\n", +- inode, orig_gen, ci->i_rdcache_gen, +- ci->i_rdcache_revoking); ++ doutc(cl, "%p %llx.%llx gen %d raced, now %d revoking %d\n", ++ inode, ceph_vinop(inode), orig_gen, ci->i_rdcache_gen, ++ ci->i_rdcache_revoking); + if (__ceph_caps_revoking_other(ci, NULL, CEPH_CAP_FILE_CACHE)) + check = 1; + } +@@ -2157,6 +2189,7 @@ out: + */ + void __ceph_do_pending_vmtruncate(struct inode *inode) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + u64 to; + int wrbuffer_refs, finish = 0; +@@ -2165,7 +2198,8 @@ void __ceph_do_pending_vmtruncate(struct + retry: + spin_lock(&ci->i_ceph_lock); + if (ci->i_truncate_pending == 0) { +- dout("%s %p none pending\n", __func__, inode); ++ doutc(cl, "%p %llx.%llx none pending\n", inode, ++ ceph_vinop(inode)); + spin_unlock(&ci->i_ceph_lock); + mutex_unlock(&ci->i_truncate_mutex); + return; +@@ -2177,7 +2211,8 @@ retry: + */ + if (ci->i_wrbuffer_ref_head < ci->i_wrbuffer_ref) { + spin_unlock(&ci->i_ceph_lock); +- dout("%s %p flushing snaps first\n", __func__, inode); ++ doutc(cl, "%p %llx.%llx flushing snaps first\n", inode, ++ ceph_vinop(inode)); + filemap_write_and_wait_range(&inode->i_data, 0, + inode->i_sb->s_maxbytes); + goto retry; +@@ -2188,8 +2223,8 @@ retry: + + to = ci->i_truncate_pagecache_size; + wrbuffer_refs = ci->i_wrbuffer_ref; +- dout("%s %p (%d) to %lld\n", __func__, inode, +- ci->i_truncate_pending, to); ++ doutc(cl, "%p %llx.%llx (%d) to %lld\n", inode, ceph_vinop(inode), ++ ci->i_truncate_pending, to); + spin_unlock(&ci->i_ceph_lock); + + ceph_fscache_resize(inode, to); +@@ -2217,9 +2252,10 @@ static void ceph_inode_work(struct work_ + struct ceph_inode_info *ci = container_of(work, struct ceph_inode_info, + i_work); + struct inode *inode = &ci->netfs.inode; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + + if (test_and_clear_bit(CEPH_I_WORK_WRITEBACK, &ci->i_work_mask)) { +- dout("writeback %p\n", inode); ++ doutc(cl, "writeback %p %llx.%llx\n", inode, ceph_vinop(inode)); + filemap_fdatawrite(&inode->i_data); + } + if (test_and_clear_bit(CEPH_I_WORK_INVALIDATE_PAGES, &ci->i_work_mask)) +@@ -2291,6 +2327,7 @@ static int fill_fscrypt_truncate(struct + struct ceph_mds_request *req, + struct iattr *attr) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + int boff = attr->ia_size % CEPH_FSCRYPT_BLOCK_SIZE; + loff_t pos, orig_pos = round_down(attr->ia_size, +@@ -2313,9 +2350,9 @@ static int fill_fscrypt_truncate(struct + + issued = __ceph_caps_issued(ci, NULL); + +- dout("%s size %lld -> %lld got cap refs on %s, issued %s\n", __func__, +- i_size, attr->ia_size, ceph_cap_string(got), +- ceph_cap_string(issued)); ++ doutc(cl, "size %lld -> %lld got cap refs on %s, issued %s\n", ++ i_size, attr->ia_size, ceph_cap_string(got), ++ ceph_cap_string(issued)); + + /* Try to writeback the dirty pagecaches */ + if (issued & (CEPH_CAP_FILE_BUFFER)) { +@@ -2370,8 +2407,7 @@ static int fill_fscrypt_truncate(struct + * If the Rados object doesn't exist, it will be set to 0. + */ + if (!objver) { +- dout("%s hit hole, ppos %lld < size %lld\n", __func__, +- pos, i_size); ++ doutc(cl, "hit hole, ppos %lld < size %lld\n", pos, i_size); + + header.data_len = cpu_to_le32(8 + 8 + 4); + header.file_offset = 0; +@@ -2380,8 +2416,8 @@ static int fill_fscrypt_truncate(struct + header.data_len = cpu_to_le32(8 + 8 + 4 + CEPH_FSCRYPT_BLOCK_SIZE); + header.file_offset = cpu_to_le64(orig_pos); + +- dout("%s encrypt block boff/bsize %d/%lu\n", __func__, +- boff, CEPH_FSCRYPT_BLOCK_SIZE); ++ doutc(cl, "encrypt block boff/bsize %d/%lu\n", boff, ++ CEPH_FSCRYPT_BLOCK_SIZE); + + /* truncate and zero out the extra contents for the last block */ + memset(iov.iov_base + boff, 0, PAGE_SIZE - boff); +@@ -2409,8 +2445,8 @@ static int fill_fscrypt_truncate(struct + } + req->r_pagelist = pagelist; + out: +- dout("%s %p size dropping cap refs on %s\n", __func__, +- inode, ceph_cap_string(got)); ++ doutc(cl, "%p %llx.%llx size dropping cap refs on %s\n", inode, ++ ceph_vinop(inode), ceph_cap_string(got)); + ceph_put_cap_refs(ci, got); + if (iov.iov_base) + kunmap_local(iov.iov_base); +@@ -2428,6 +2464,7 @@ int __ceph_setattr(struct inode *inode, + unsigned int ia_valid = attr->ia_valid; + struct ceph_mds_request *req; + struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_cap_flush *prealloc_cf; + loff_t isize = i_size_read(inode); + int issued; +@@ -2466,7 +2503,8 @@ retry: + } + } + +- dout("setattr %p issued %s\n", inode, ceph_cap_string(issued)); ++ doutc(cl, "%p %llx.%llx issued %s\n", inode, ceph_vinop(inode), ++ ceph_cap_string(issued)); + #if IS_ENABLED(CONFIG_FS_ENCRYPTION) + if (cia && cia->fscrypt_auth) { + u32 len = ceph_fscrypt_auth_len(cia->fscrypt_auth); +@@ -2477,8 +2515,8 @@ retry: + goto out; + } + +- dout("setattr %llx:%llx fscrypt_auth len %u to %u)\n", +- ceph_vinop(inode), ci->fscrypt_auth_len, len); ++ doutc(cl, "%p %llx.%llx fscrypt_auth len %u to %u)\n", inode, ++ ceph_vinop(inode), ci->fscrypt_auth_len, len); + + /* It should never be re-set once set */ + WARN_ON_ONCE(ci->fscrypt_auth); +@@ -2506,9 +2544,10 @@ retry: + #endif /* CONFIG_FS_ENCRYPTION */ + + if (ia_valid & ATTR_UID) { +- dout("setattr %p uid %d -> %d\n", inode, +- from_kuid(&init_user_ns, inode->i_uid), +- from_kuid(&init_user_ns, attr->ia_uid)); ++ doutc(cl, "%p %llx.%llx uid %d -> %d\n", inode, ++ ceph_vinop(inode), ++ from_kuid(&init_user_ns, inode->i_uid), ++ from_kuid(&init_user_ns, attr->ia_uid)); + if (issued & CEPH_CAP_AUTH_EXCL) { + inode->i_uid = attr->ia_uid; + dirtied |= CEPH_CAP_AUTH_EXCL; +@@ -2521,9 +2560,10 @@ retry: + } + } + if (ia_valid & ATTR_GID) { +- dout("setattr %p gid %d -> %d\n", inode, +- from_kgid(&init_user_ns, inode->i_gid), +- from_kgid(&init_user_ns, attr->ia_gid)); ++ doutc(cl, "%p %llx.%llx gid %d -> %d\n", inode, ++ ceph_vinop(inode), ++ from_kgid(&init_user_ns, inode->i_gid), ++ from_kgid(&init_user_ns, attr->ia_gid)); + if (issued & CEPH_CAP_AUTH_EXCL) { + inode->i_gid = attr->ia_gid; + dirtied |= CEPH_CAP_AUTH_EXCL; +@@ -2536,8 +2576,8 @@ retry: + } + } + if (ia_valid & ATTR_MODE) { +- dout("setattr %p mode 0%o -> 0%o\n", inode, inode->i_mode, +- attr->ia_mode); ++ doutc(cl, "%p %llx.%llx mode 0%o -> 0%o\n", inode, ++ ceph_vinop(inode), inode->i_mode, attr->ia_mode); + if (issued & CEPH_CAP_AUTH_EXCL) { + inode->i_mode = attr->ia_mode; + dirtied |= CEPH_CAP_AUTH_EXCL; +@@ -2551,9 +2591,10 @@ retry: + } + + if (ia_valid & ATTR_ATIME) { +- dout("setattr %p atime %lld.%ld -> %lld.%ld\n", inode, +- inode->i_atime.tv_sec, inode->i_atime.tv_nsec, +- attr->ia_atime.tv_sec, attr->ia_atime.tv_nsec); ++ doutc(cl, "%p %llx.%llx atime %lld.%ld -> %lld.%ld\n", ++ inode, ceph_vinop(inode), inode->i_atime.tv_sec, ++ inode->i_atime.tv_nsec, attr->ia_atime.tv_sec, ++ attr->ia_atime.tv_nsec); + if (issued & CEPH_CAP_FILE_EXCL) { + ci->i_time_warp_seq++; + inode->i_atime = attr->ia_atime; +@@ -2573,7 +2614,8 @@ retry: + } + } + if (ia_valid & ATTR_SIZE) { +- dout("setattr %p size %lld -> %lld\n", inode, isize, attr->ia_size); ++ doutc(cl, "%p %llx.%llx size %lld -> %lld\n", inode, ++ ceph_vinop(inode), isize, attr->ia_size); + /* + * Only when the new size is smaller and not aligned to + * CEPH_FSCRYPT_BLOCK_SIZE will the RMW is needed. +@@ -2624,9 +2666,10 @@ retry: + } + } + if (ia_valid & ATTR_MTIME) { +- dout("setattr %p mtime %lld.%ld -> %lld.%ld\n", inode, +- inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec, +- attr->ia_mtime.tv_sec, attr->ia_mtime.tv_nsec); ++ doutc(cl, "%p %llx.%llx mtime %lld.%ld -> %lld.%ld\n", ++ inode, ceph_vinop(inode), inode->i_mtime.tv_sec, ++ inode->i_mtime.tv_nsec, attr->ia_mtime.tv_sec, ++ attr->ia_mtime.tv_nsec); + if (issued & CEPH_CAP_FILE_EXCL) { + ci->i_time_warp_seq++; + inode->i_mtime = attr->ia_mtime; +@@ -2650,11 +2693,12 @@ retry: + if (ia_valid & ATTR_CTIME) { + bool only = (ia_valid & (ATTR_SIZE|ATTR_MTIME|ATTR_ATIME| + ATTR_MODE|ATTR_UID|ATTR_GID)) == 0; +- dout("setattr %p ctime %lld.%ld -> %lld.%ld (%s)\n", inode, +- inode_get_ctime(inode).tv_sec, +- inode_get_ctime(inode).tv_nsec, +- attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec, +- only ? "ctime only" : "ignored"); ++ doutc(cl, "%p %llx.%llx ctime %lld.%ld -> %lld.%ld (%s)\n", ++ inode, ceph_vinop(inode), inode_get_ctime(inode).tv_sec, ++ inode_get_ctime(inode).tv_nsec, ++ attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec, ++ only ? "ctime only" : "ignored"); ++ + if (only) { + /* + * if kernel wants to dirty ctime but nothing else, +@@ -2672,7 +2716,8 @@ retry: + } + } + if (ia_valid & ATTR_FILE) +- dout("setattr %p ATTR_FILE ... hrm!\n", inode); ++ doutc(cl, "%p %llx.%llx ATTR_FILE ... hrm!\n", inode, ++ ceph_vinop(inode)); + + if (dirtied) { + inode_dirty_flags = __ceph_mark_dirty_caps(ci, dirtied, +@@ -2713,16 +2758,17 @@ retry: + */ + err = ceph_mdsc_do_request(mdsc, NULL, req); + if (err == -EAGAIN && truncate_retry--) { +- dout("setattr %p result=%d (%s locally, %d remote), retry it!\n", +- inode, err, ceph_cap_string(dirtied), mask); ++ doutc(cl, "%p %llx.%llx result=%d (%s locally, %d remote), retry it!\n", ++ inode, ceph_vinop(inode), err, ++ ceph_cap_string(dirtied), mask); + ceph_mdsc_put_request(req); + ceph_free_cap_flush(prealloc_cf); + goto retry; + } + } + out: +- dout("setattr %p result=%d (%s locally, %d remote)\n", inode, err, +- ceph_cap_string(dirtied), mask); ++ doutc(cl, "%p %llx.%llx result=%d (%s locally, %d remote)\n", inode, ++ ceph_vinop(inode), err, ceph_cap_string(dirtied), mask); + + ceph_mdsc_put_request(req); + ceph_free_cap_flush(prealloc_cf); +@@ -2811,18 +2857,20 @@ int __ceph_do_getattr(struct inode *inod + int mask, bool force) + { + struct ceph_fs_client *fsc = ceph_sb_to_fs_client(inode->i_sb); ++ struct ceph_client *cl = fsc->client; + struct ceph_mds_client *mdsc = fsc->mdsc; + struct ceph_mds_request *req; + int mode; + int err; + + if (ceph_snap(inode) == CEPH_SNAPDIR) { +- dout("do_getattr inode %p SNAPDIR\n", inode); ++ doutc(cl, "inode %p %llx.%llx SNAPDIR\n", inode, ++ ceph_vinop(inode)); + return 0; + } + +- dout("do_getattr inode %p mask %s mode 0%o\n", +- inode, ceph_cap_string(mask), inode->i_mode); ++ doutc(cl, "inode %p %llx.%llx mask %s mode 0%o\n", inode, ++ ceph_vinop(inode), ceph_cap_string(mask), inode->i_mode); + if (!force && ceph_caps_issued_mask_metric(ceph_inode(inode), mask, 1)) + return 0; + +@@ -2849,7 +2897,7 @@ int __ceph_do_getattr(struct inode *inod + } + } + ceph_mdsc_put_request(req); +- dout("do_getattr result=%d\n", err); ++ doutc(cl, "result=%d\n", err); + return err; + } + +@@ -2857,6 +2905,7 @@ int ceph_do_getvxattr(struct inode *inod + size_t size) + { + struct ceph_fs_client *fsc = ceph_sb_to_fs_client(inode->i_sb); ++ struct ceph_client *cl = fsc->client; + struct ceph_mds_client *mdsc = fsc->mdsc; + struct ceph_mds_request *req; + int mode = USE_AUTH_MDS; +@@ -2886,7 +2935,7 @@ int ceph_do_getvxattr(struct inode *inod + xattr_value = req->r_reply_info.xattr_info.xattr_value; + xattr_value_len = req->r_reply_info.xattr_info.xattr_value_len; + +- dout("do_getvxattr xattr_value_len:%zu, size:%zu\n", xattr_value_len, size); ++ doutc(cl, "xattr_value_len:%zu, size:%zu\n", xattr_value_len, size); + + err = (int)xattr_value_len; + if (size == 0) +@@ -2901,7 +2950,7 @@ int ceph_do_getvxattr(struct inode *inod + put: + ceph_mdsc_put_request(req); + out: +- dout("do_getvxattr result=%d\n", err); ++ doutc(cl, "result=%d\n", err); + return err; + } + +--- a/fs/ceph/ioctl.c ++++ b/fs/ceph/ioctl.c +@@ -245,6 +245,7 @@ static long ceph_ioctl_lazyio(struct fil + struct inode *inode = file_inode(file); + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc; ++ struct ceph_client *cl = mdsc->fsc->client; + + if ((fi->fmode & CEPH_FILE_MODE_LAZY) == 0) { + spin_lock(&ci->i_ceph_lock); +@@ -252,11 +253,13 @@ static long ceph_ioctl_lazyio(struct fil + ci->i_nr_by_mode[ffs(CEPH_FILE_MODE_LAZY)]++; + __ceph_touch_fmode(ci, mdsc, fi->fmode); + spin_unlock(&ci->i_ceph_lock); +- dout("ioctl_layzio: file %p marked lazy\n", file); ++ doutc(cl, "file %p %p %llx.%llx marked lazy\n", file, inode, ++ ceph_vinop(inode)); + + ceph_check_caps(ci, 0); + } else { +- dout("ioctl_layzio: file %p already lazy\n", file); ++ doutc(cl, "file %p %p %llx.%llx already lazy\n", file, inode, ++ ceph_vinop(inode)); + } + return 0; + } +@@ -355,10 +358,12 @@ static const char *ceph_ioctl_cmd_name(c + + long ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg) + { ++ struct inode *inode = file_inode(file); ++ struct ceph_fs_client *fsc = ceph_inode_to_fs_client(inode); + int ret; + +- dout("ioctl file %p cmd %s arg %lu\n", file, +- ceph_ioctl_cmd_name(cmd), arg); ++ doutc(fsc->client, "file %p %p %llx.%llx cmd %s arg %lu\n", file, ++ inode, ceph_vinop(inode), ceph_ioctl_cmd_name(cmd), arg); + switch (cmd) { + case CEPH_IOC_GET_LAYOUT: + return ceph_ioctl_get_layout(file, (void __user *)arg); +--- a/fs/ceph/locks.c ++++ b/fs/ceph/locks.c +@@ -77,6 +77,7 @@ static int ceph_lock_message(u8 lock_typ + int cmd, u8 wait, struct file_lock *fl) + { + struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb); ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_request *req; + int err; + u64 length = 0; +@@ -111,10 +112,10 @@ static int ceph_lock_message(u8 lock_typ + + owner = secure_addr(fl->fl_owner); + +- dout("ceph_lock_message: rule: %d, op: %d, owner: %llx, pid: %llu, " +- "start: %llu, length: %llu, wait: %d, type: %d\n", (int)lock_type, +- (int)operation, owner, (u64)fl->fl_pid, fl->fl_start, length, +- wait, fl->fl_type); ++ doutc(cl, "rule: %d, op: %d, owner: %llx, pid: %llu, " ++ "start: %llu, length: %llu, wait: %d, type: %d\n", ++ (int)lock_type, (int)operation, owner, (u64)fl->fl_pid, ++ fl->fl_start, length, wait, fl->fl_type); + + req->r_args.filelock_change.rule = lock_type; + req->r_args.filelock_change.type = cmd; +@@ -147,16 +148,17 @@ static int ceph_lock_message(u8 lock_typ + + } + ceph_mdsc_put_request(req); +- dout("ceph_lock_message: rule: %d, op: %d, pid: %llu, start: %llu, " +- "length: %llu, wait: %d, type: %d, err code %d\n", (int)lock_type, +- (int)operation, (u64)fl->fl_pid, fl->fl_start, +- length, wait, fl->fl_type, err); ++ doutc(cl, "rule: %d, op: %d, pid: %llu, start: %llu, " ++ "length: %llu, wait: %d, type: %d, err code %d\n", ++ (int)lock_type, (int)operation, (u64)fl->fl_pid, ++ fl->fl_start, length, wait, fl->fl_type, err); + return err; + } + + static int ceph_lock_wait_for_completion(struct ceph_mds_client *mdsc, + struct ceph_mds_request *req) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_request *intr_req; + struct inode *inode = req->r_inode; + int err, lock_type; +@@ -174,8 +176,7 @@ static int ceph_lock_wait_for_completion + if (!err) + return 0; + +- dout("ceph_lock_wait_for_completion: request %llu was interrupted\n", +- req->r_tid); ++ doutc(cl, "request %llu was interrupted\n", req->r_tid); + + mutex_lock(&mdsc->mutex); + if (test_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags)) { +@@ -249,6 +250,7 @@ int ceph_lock(struct file *file, int cmd + { + struct inode *inode = file_inode(file); + struct ceph_inode_info *ci = ceph_inode(inode); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + int err = 0; + u16 op = CEPH_MDS_OP_SETFILELOCK; + u8 wait = 0; +@@ -260,7 +262,7 @@ int ceph_lock(struct file *file, int cmd + if (ceph_inode_is_shutdown(inode)) + return -ESTALE; + +- dout("ceph_lock, fl_owner: %p\n", fl->fl_owner); ++ doutc(cl, "fl_owner: %p\n", fl->fl_owner); + + /* set wait bit as appropriate, then make command as Ceph expects it*/ + if (IS_GETLK(cmd)) +@@ -295,7 +297,7 @@ int ceph_lock(struct file *file, int cmd + err = ceph_lock_message(CEPH_LOCK_FCNTL, op, inode, lock_cmd, wait, fl); + if (!err) { + if (op == CEPH_MDS_OP_SETFILELOCK && F_UNLCK != fl->fl_type) { +- dout("mds locked, locking locally\n"); ++ doutc(cl, "locking locally\n"); + err = posix_lock_file(file, fl, NULL); + if (err) { + /* undo! This should only happen if +@@ -303,8 +305,8 @@ int ceph_lock(struct file *file, int cmd + * deadlock. */ + ceph_lock_message(CEPH_LOCK_FCNTL, op, inode, + CEPH_LOCK_UNLOCK, 0, fl); +- dout("got %d on posix_lock_file, undid lock\n", +- err); ++ doutc(cl, "got %d on posix_lock_file, undid lock\n", ++ err); + } + } + } +@@ -315,6 +317,7 @@ int ceph_flock(struct file *file, int cm + { + struct inode *inode = file_inode(file); + struct ceph_inode_info *ci = ceph_inode(inode); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + int err = 0; + u8 wait = 0; + u8 lock_cmd; +@@ -325,7 +328,7 @@ int ceph_flock(struct file *file, int cm + if (ceph_inode_is_shutdown(inode)) + return -ESTALE; + +- dout("ceph_flock, fl_file: %p\n", fl->fl_file); ++ doutc(cl, "fl_file: %p\n", fl->fl_file); + + spin_lock(&ci->i_ceph_lock); + if (ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK) { +@@ -362,7 +365,8 @@ int ceph_flock(struct file *file, int cm + ceph_lock_message(CEPH_LOCK_FLOCK, + CEPH_MDS_OP_SETFILELOCK, + inode, CEPH_LOCK_UNLOCK, 0, fl); +- dout("got %d on locks_lock_file_wait, undid lock\n", err); ++ doutc(cl, "got %d on locks_lock_file_wait, undid lock\n", ++ err); + } + } + return err; +@@ -374,6 +378,7 @@ int ceph_flock(struct file *file, int cm + */ + void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct file_lock *lock; + struct file_lock_context *ctx; + +@@ -389,17 +394,20 @@ void ceph_count_locks(struct inode *inod + ++(*flock_count); + spin_unlock(&ctx->flc_lock); + } +- dout("counted %d flock locks and %d fcntl locks\n", +- *flock_count, *fcntl_count); ++ doutc(cl, "counted %d flock locks and %d fcntl locks\n", ++ *flock_count, *fcntl_count); + } + + /* + * Given a pointer to a lock, convert it to a ceph filelock + */ +-static int lock_to_ceph_filelock(struct file_lock *lock, ++static int lock_to_ceph_filelock(struct inode *inode, ++ struct file_lock *lock, + struct ceph_filelock *cephlock) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + int err = 0; ++ + cephlock->start = cpu_to_le64(lock->fl_start); + cephlock->length = cpu_to_le64(lock->fl_end - lock->fl_start + 1); + cephlock->client = cpu_to_le64(0); +@@ -417,7 +425,7 @@ static int lock_to_ceph_filelock(struct + cephlock->type = CEPH_LOCK_UNLOCK; + break; + default: +- dout("Have unknown lock type %d\n", lock->fl_type); ++ doutc(cl, "Have unknown lock type %d\n", lock->fl_type); + err = -EINVAL; + } + +@@ -435,13 +443,14 @@ int ceph_encode_locks_to_buffer(struct i + { + struct file_lock *lock; + struct file_lock_context *ctx = locks_inode_context(inode); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + int err = 0; + int seen_fcntl = 0; + int seen_flock = 0; + int l = 0; + +- dout("encoding %d flock and %d fcntl locks\n", num_flock_locks, +- num_fcntl_locks); ++ doutc(cl, "encoding %d flock and %d fcntl locks\n", num_flock_locks, ++ num_fcntl_locks); + + if (!ctx) + return 0; +@@ -453,7 +462,7 @@ int ceph_encode_locks_to_buffer(struct i + err = -ENOSPC; + goto fail; + } +- err = lock_to_ceph_filelock(lock, &flocks[l]); ++ err = lock_to_ceph_filelock(inode, lock, &flocks[l]); + if (err) + goto fail; + ++l; +@@ -464,7 +473,7 @@ int ceph_encode_locks_to_buffer(struct i + err = -ENOSPC; + goto fail; + } +- err = lock_to_ceph_filelock(lock, &flocks[l]); ++ err = lock_to_ceph_filelock(inode, lock, &flocks[l]); + if (err) + goto fail; + ++l; +--- a/fs/ceph/mds_client.c ++++ b/fs/ceph/mds_client.c +@@ -411,6 +411,7 @@ static int parse_reply_info_readdir(void + u64 features) + { + struct ceph_mds_reply_info_parsed *info = &req->r_reply_info; ++ struct ceph_client *cl = req->r_mdsc->fsc->client; + u32 num, i = 0; + int err; + +@@ -433,7 +434,7 @@ static int parse_reply_info_readdir(void + BUG_ON(!info->dir_entries); + if ((unsigned long)(info->dir_entries + num) > + (unsigned long)info->dir_entries + info->dir_buf_size) { +- pr_err("dir contents are larger than expected\n"); ++ pr_err_client(cl, "dir contents are larger than expected\n"); + WARN_ON(1); + goto bad; + } +@@ -454,7 +455,7 @@ static int parse_reply_info_readdir(void + ceph_decode_need(p, end, _name_len, bad); + _name = *p; + *p += _name_len; +- dout("parsed dir dname '%.*s'\n", _name_len, _name); ++ doutc(cl, "parsed dir dname '%.*s'\n", _name_len, _name); + + if (info->hash_order) + rde->raw_hash = ceph_str_hash(ci->i_dir_layout.dl_dir_hash, +@@ -514,8 +515,8 @@ static int parse_reply_info_readdir(void + rde->is_nokey = false; + err = ceph_fname_to_usr(&fname, &tname, &oname, &rde->is_nokey); + if (err) { +- pr_err("%s unable to decode %.*s, got %d\n", __func__, +- _name_len, _name, err); ++ pr_err_client(cl, "unable to decode %.*s, got %d\n", ++ _name_len, _name, err); + goto out_bad; + } + rde->name = oname.name; +@@ -539,7 +540,7 @@ done: + bad: + err = -EIO; + out_bad: +- pr_err("problem parsing dir contents %d\n", err); ++ pr_err_client(cl, "problem parsing dir contents %d\n", err); + return err; + } + +@@ -570,10 +571,11 @@ bad: + static int ceph_parse_deleg_inos(void **p, void *end, + struct ceph_mds_session *s) + { ++ struct ceph_client *cl = s->s_mdsc->fsc->client; + u32 sets; + + ceph_decode_32_safe(p, end, sets, bad); +- dout("got %u sets of delegated inodes\n", sets); ++ doutc(cl, "got %u sets of delegated inodes\n", sets); + while (sets--) { + u64 start, len; + +@@ -582,8 +584,9 @@ static int ceph_parse_deleg_inos(void ** + + /* Don't accept a delegation of system inodes */ + if (start < CEPH_INO_SYSTEM_BASE) { +- pr_warn_ratelimited("ceph: ignoring reserved inode range delegation (start=0x%llx len=0x%llx)\n", +- start, len); ++ pr_warn_ratelimited_client(cl, ++ "ignoring reserved inode range delegation (start=0x%llx len=0x%llx)\n", ++ start, len); + continue; + } + while (len--) { +@@ -591,10 +594,10 @@ static int ceph_parse_deleg_inos(void ** + DELEGATED_INO_AVAILABLE, + GFP_KERNEL); + if (!err) { +- dout("added delegated inode 0x%llx\n", +- start - 1); ++ doutc(cl, "added delegated inode 0x%llx\n", start - 1); + } else if (err == -EBUSY) { +- pr_warn("MDS delegated inode 0x%llx more than once.\n", ++ pr_warn_client(cl, ++ "MDS delegated inode 0x%llx more than once.\n", + start - 1); + } else { + return err; +@@ -744,6 +747,7 @@ static int parse_reply_info(struct ceph_ + struct ceph_mds_request *req, u64 features) + { + struct ceph_mds_reply_info_parsed *info = &req->r_reply_info; ++ struct ceph_client *cl = s->s_mdsc->fsc->client; + void *p, *end; + u32 len; + int err; +@@ -783,7 +787,7 @@ static int parse_reply_info(struct ceph_ + bad: + err = -EIO; + out_bad: +- pr_err("mds parse_reply err %d\n", err); ++ pr_err_client(cl, "mds parse_reply err %d\n", err); + ceph_msg_dump(msg); + return err; + } +@@ -831,6 +835,7 @@ static void destroy_reply_info(struct ce + int ceph_wait_on_conflict_unlink(struct dentry *dentry) + { + struct ceph_fs_client *fsc = ceph_sb_to_fs_client(dentry->d_sb); ++ struct ceph_client *cl = fsc->client; + struct dentry *pdentry = dentry->d_parent; + struct dentry *udentry, *found = NULL; + struct ceph_dentry_info *di; +@@ -855,8 +860,8 @@ int ceph_wait_on_conflict_unlink(struct + goto next; + + if (!test_bit(CEPH_DENTRY_ASYNC_UNLINK_BIT, &di->flags)) +- pr_warn("%s dentry %p:%pd async unlink bit is not set\n", +- __func__, dentry, dentry); ++ pr_warn_client(cl, "dentry %p:%pd async unlink bit is not set\n", ++ dentry, dentry); + + if (!d_same_name(udentry, pdentry, &dname)) + goto next; +@@ -872,8 +877,8 @@ next: + if (likely(!found)) + return 0; + +- dout("%s dentry %p:%pd conflict with old %p:%pd\n", __func__, +- dentry, dentry, found, found); ++ doutc(cl, "dentry %p:%pd conflict with old %p:%pd\n", dentry, dentry, ++ found, found); + + err = wait_on_bit(&di->flags, CEPH_DENTRY_ASYNC_UNLINK_BIT, + TASK_KILLABLE); +@@ -957,6 +962,7 @@ static int __verify_registered_session(s + static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, + int mds) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_session *s; + + if (READ_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_FENCE_IO) +@@ -973,7 +979,7 @@ static struct ceph_mds_session *register + int newmax = 1 << get_count_order(mds + 1); + struct ceph_mds_session **sa; + +- dout("%s: realloc to %d\n", __func__, newmax); ++ doutc(cl, "realloc to %d\n", newmax); + sa = kcalloc(newmax, sizeof(void *), GFP_NOFS); + if (!sa) + goto fail_realloc; +@@ -986,7 +992,7 @@ static struct ceph_mds_session *register + mdsc->max_sessions = newmax; + } + +- dout("%s: mds%d\n", __func__, mds); ++ doutc(cl, "mds%d\n", mds); + s->s_mdsc = mdsc; + s->s_mds = mds; + s->s_state = CEPH_MDS_SESSION_NEW; +@@ -1029,7 +1035,7 @@ fail_realloc: + static void __unregister_session(struct ceph_mds_client *mdsc, + struct ceph_mds_session *s) + { +- dout("__unregister_session mds%d %p\n", s->s_mds, s); ++ doutc(mdsc->fsc->client, "mds%d %p\n", s->s_mds, s); + BUG_ON(mdsc->sessions[s->s_mds] != s); + mdsc->sessions[s->s_mds] = NULL; + ceph_con_close(&s->s_con); +@@ -1155,6 +1161,7 @@ static void __register_request(struct ce + struct ceph_mds_request *req, + struct inode *dir) + { ++ struct ceph_client *cl = mdsc->fsc->client; + int ret = 0; + + req->r_tid = ++mdsc->last_tid; +@@ -1162,14 +1169,14 @@ static void __register_request(struct ce + ret = ceph_reserve_caps(mdsc, &req->r_caps_reservation, + req->r_num_caps); + if (ret < 0) { +- pr_err("__register_request %p " +- "failed to reserve caps: %d\n", req, ret); ++ pr_err_client(cl, "%p failed to reserve caps: %d\n", ++ req, ret); + /* set req->r_err to fail early from __do_request */ + req->r_err = ret; + return; + } + } +- dout("__register_request %p tid %lld\n", req, req->r_tid); ++ doutc(cl, "%p tid %lld\n", req, req->r_tid); + ceph_mdsc_get_request(req); + insert_request(&mdsc->request_tree, req); + +@@ -1192,7 +1199,7 @@ static void __register_request(struct ce + static void __unregister_request(struct ceph_mds_client *mdsc, + struct ceph_mds_request *req) + { +- dout("__unregister_request %p tid %lld\n", req, req->r_tid); ++ doutc(mdsc->fsc->client, "%p tid %lld\n", req, req->r_tid); + + /* Never leave an unregistered request on an unsafe list! */ + list_del_init(&req->r_unsafe_item); +@@ -1278,6 +1285,7 @@ static int __choose_mds(struct ceph_mds_ + int mds = -1; + u32 hash = req->r_direct_hash; + bool is_hash = test_bit(CEPH_MDS_R_DIRECT_IS_HASH, &req->r_req_flags); ++ struct ceph_client *cl = mdsc->fsc->client; + + if (random) + *random = false; +@@ -1289,8 +1297,7 @@ static int __choose_mds(struct ceph_mds_ + if (req->r_resend_mds >= 0 && + (__have_session(mdsc, req->r_resend_mds) || + ceph_mdsmap_get_state(mdsc->mdsmap, req->r_resend_mds) > 0)) { +- dout("%s using resend_mds mds%d\n", __func__, +- req->r_resend_mds); ++ doutc(cl, "using resend_mds mds%d\n", req->r_resend_mds); + return req->r_resend_mds; + } + +@@ -1307,7 +1314,8 @@ static int __choose_mds(struct ceph_mds_ + rcu_read_lock(); + inode = get_nonsnap_parent(req->r_dentry); + rcu_read_unlock(); +- dout("%s using snapdir's parent %p\n", __func__, inode); ++ doutc(cl, "using snapdir's parent %p %llx.%llx\n", ++ inode, ceph_vinop(inode)); + } + } else if (req->r_dentry) { + /* ignore race with rename; old or new d_parent is okay */ +@@ -1327,7 +1335,8 @@ static int __choose_mds(struct ceph_mds_ + /* direct snapped/virtual snapdir requests + * based on parent dir inode */ + inode = get_nonsnap_parent(parent); +- dout("%s using nonsnap parent %p\n", __func__, inode); ++ doutc(cl, "using nonsnap parent %p %llx.%llx\n", ++ inode, ceph_vinop(inode)); + } else { + /* dentry target */ + inode = d_inode(req->r_dentry); +@@ -1343,10 +1352,11 @@ static int __choose_mds(struct ceph_mds_ + rcu_read_unlock(); + } + +- dout("%s %p is_hash=%d (0x%x) mode %d\n", __func__, inode, (int)is_hash, +- hash, mode); + if (!inode) + goto random; ++ ++ doutc(cl, "%p %llx.%llx is_hash=%d (0x%x) mode %d\n", inode, ++ ceph_vinop(inode), (int)is_hash, hash, mode); + ci = ceph_inode(inode); + + if (is_hash && S_ISDIR(inode->i_mode)) { +@@ -1362,9 +1372,9 @@ static int __choose_mds(struct ceph_mds_ + get_random_bytes(&r, 1); + r %= frag.ndist; + mds = frag.dist[r]; +- dout("%s %p %llx.%llx frag %u mds%d (%d/%d)\n", +- __func__, inode, ceph_vinop(inode), +- frag.frag, mds, (int)r, frag.ndist); ++ doutc(cl, "%p %llx.%llx frag %u mds%d (%d/%d)\n", ++ inode, ceph_vinop(inode), frag.frag, ++ mds, (int)r, frag.ndist); + if (ceph_mdsmap_get_state(mdsc->mdsmap, mds) >= + CEPH_MDS_STATE_ACTIVE && + !ceph_mdsmap_is_laggy(mdsc->mdsmap, mds)) +@@ -1377,9 +1387,8 @@ static int __choose_mds(struct ceph_mds_ + if (frag.mds >= 0) { + /* choose auth mds */ + mds = frag.mds; +- dout("%s %p %llx.%llx frag %u mds%d (auth)\n", +- __func__, inode, ceph_vinop(inode), +- frag.frag, mds); ++ doutc(cl, "%p %llx.%llx frag %u mds%d (auth)\n", ++ inode, ceph_vinop(inode), frag.frag, mds); + if (ceph_mdsmap_get_state(mdsc->mdsmap, mds) >= + CEPH_MDS_STATE_ACTIVE) { + if (!ceph_mdsmap_is_laggy(mdsc->mdsmap, +@@ -1403,9 +1412,9 @@ static int __choose_mds(struct ceph_mds_ + goto random; + } + mds = cap->session->s_mds; +- dout("%s %p %llx.%llx mds%d (%scap %p)\n", __func__, +- inode, ceph_vinop(inode), mds, +- cap == ci->i_auth_cap ? "auth " : "", cap); ++ doutc(cl, "%p %llx.%llx mds%d (%scap %p)\n", inode, ++ ceph_vinop(inode), mds, ++ cap == ci->i_auth_cap ? "auth " : "", cap); + spin_unlock(&ci->i_ceph_lock); + out: + iput(inode); +@@ -1416,7 +1425,7 @@ random: + *random = true; + + mds = ceph_mdsmap_get_random_mds(mdsc->mdsmap); +- dout("%s chose random mds%d\n", __func__, mds); ++ doutc(cl, "chose random mds%d\n", mds); + return mds; + } + +@@ -1529,6 +1538,7 @@ static struct ceph_msg *create_session_o + int metadata_key_count = 0; + struct ceph_options *opt = mdsc->fsc->client->options; + struct ceph_mount_options *fsopt = mdsc->fsc->mount_options; ++ struct ceph_client *cl = mdsc->fsc->client; + size_t size, count; + void *p, *end; + int ret; +@@ -1567,7 +1577,7 @@ static struct ceph_msg *create_session_o + msg = ceph_msg_new(CEPH_MSG_CLIENT_SESSION, sizeof(*h) + extra_bytes, + GFP_NOFS, false); + if (!msg) { +- pr_err("ENOMEM creating session open msg\n"); ++ pr_err_client(cl, "ENOMEM creating session open msg\n"); + return ERR_PTR(-ENOMEM); + } + p = msg->front.iov_base; +@@ -1607,14 +1617,14 @@ static struct ceph_msg *create_session_o + + ret = encode_supported_features(&p, end); + if (ret) { +- pr_err("encode_supported_features failed!\n"); ++ pr_err_client(cl, "encode_supported_features failed!\n"); + ceph_msg_put(msg); + return ERR_PTR(ret); + } + + ret = encode_metric_spec(&p, end); + if (ret) { +- pr_err("encode_metric_spec failed!\n"); ++ pr_err_client(cl, "encode_metric_spec failed!\n"); + ceph_msg_put(msg); + return ERR_PTR(ret); + } +@@ -1642,8 +1652,8 @@ static int __open_session(struct ceph_md + + /* wait for mds to go active? */ + mstate = ceph_mdsmap_get_state(mdsc->mdsmap, mds); +- dout("open_session to mds%d (%s)\n", mds, +- ceph_mds_state_name(mstate)); ++ doutc(mdsc->fsc->client, "open_session to mds%d (%s)\n", mds, ++ ceph_mds_state_name(mstate)); + session->s_state = CEPH_MDS_SESSION_OPENING; + session->s_renew_requested = jiffies; + +@@ -1686,8 +1696,9 @@ struct ceph_mds_session * + ceph_mdsc_open_export_target_session(struct ceph_mds_client *mdsc, int target) + { + struct ceph_mds_session *session; ++ struct ceph_client *cl = mdsc->fsc->client; + +- dout("open_export_target_session to mds%d\n", target); ++ doutc(cl, "to mds%d\n", target); + + mutex_lock(&mdsc->mutex); + session = __open_export_target_session(mdsc, target); +@@ -1702,13 +1713,14 @@ static void __open_export_target_session + struct ceph_mds_info *mi; + struct ceph_mds_session *ts; + int i, mds = session->s_mds; ++ struct ceph_client *cl = mdsc->fsc->client; + + if (mds >= mdsc->mdsmap->possible_max_rank) + return; + + mi = &mdsc->mdsmap->m_info[mds]; +- dout("open_export_target_sessions for mds%d (%d targets)\n", +- session->s_mds, mi->num_export_targets); ++ doutc(cl, "for mds%d (%d targets)\n", session->s_mds, ++ mi->num_export_targets); + + for (i = 0; i < mi->num_export_targets; i++) { + ts = __open_export_target_session(mdsc, mi->export_targets[i]); +@@ -1731,11 +1743,13 @@ void ceph_mdsc_open_export_target_sessio + static void detach_cap_releases(struct ceph_mds_session *session, + struct list_head *target) + { ++ struct ceph_client *cl = session->s_mdsc->fsc->client; ++ + lockdep_assert_held(&session->s_cap_lock); + + list_splice_init(&session->s_cap_releases, target); + session->s_num_cap_releases = 0; +- dout("dispose_cap_releases mds%d\n", session->s_mds); ++ doutc(cl, "mds%d\n", session->s_mds); + } + + static void dispose_cap_releases(struct ceph_mds_client *mdsc, +@@ -1753,16 +1767,17 @@ static void dispose_cap_releases(struct + static void cleanup_session_requests(struct ceph_mds_client *mdsc, + struct ceph_mds_session *session) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_request *req; + struct rb_node *p; + +- dout("cleanup_session_requests mds%d\n", session->s_mds); ++ doutc(cl, "mds%d\n", session->s_mds); + mutex_lock(&mdsc->mutex); + while (!list_empty(&session->s_unsafe)) { + req = list_first_entry(&session->s_unsafe, + struct ceph_mds_request, r_unsafe_item); +- pr_warn_ratelimited(" dropping unsafe request %llu\n", +- req->r_tid); ++ pr_warn_ratelimited_client(cl, " dropping unsafe request %llu\n", ++ req->r_tid); + if (req->r_target_inode) + mapping_set_error(req->r_target_inode->i_mapping, -EIO); + if (req->r_unsafe_dir) +@@ -1791,13 +1806,14 @@ int ceph_iterate_session_caps(struct cep + int (*cb)(struct inode *, int mds, void *), + void *arg) + { ++ struct ceph_client *cl = session->s_mdsc->fsc->client; + struct list_head *p; + struct ceph_cap *cap; + struct inode *inode, *last_inode = NULL; + struct ceph_cap *old_cap = NULL; + int ret; + +- dout("iterate_session_caps %p mds%d\n", session, session->s_mds); ++ doutc(cl, "%p mds%d\n", session, session->s_mds); + spin_lock(&session->s_cap_lock); + p = session->s_caps.next; + while (p != &session->s_caps) { +@@ -1828,8 +1844,7 @@ int ceph_iterate_session_caps(struct cep + spin_lock(&session->s_cap_lock); + p = p->next; + if (!cap->ci) { +- dout("iterate_session_caps finishing cap %p removal\n", +- cap); ++ doutc(cl, "finishing cap %p removal\n", cap); + BUG_ON(cap->session != session); + cap->session = NULL; + list_del_init(&cap->session_caps); +@@ -1858,6 +1873,7 @@ out: + static int remove_session_caps_cb(struct inode *inode, int mds, void *arg) + { + struct ceph_inode_info *ci = ceph_inode(inode); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + bool invalidate = false; + struct ceph_cap *cap; + int iputs = 0; +@@ -1865,8 +1881,8 @@ static int remove_session_caps_cb(struct + spin_lock(&ci->i_ceph_lock); + cap = __get_cap_for_mds(ci, mds); + if (cap) { +- dout(" removing cap %p, ci is %p, inode is %p\n", +- cap, ci, &ci->netfs.inode); ++ doutc(cl, " removing cap %p, ci is %p, inode is %p\n", ++ cap, ci, &ci->netfs.inode); + + iputs = ceph_purge_inode_cap(inode, cap, &invalidate); + } +@@ -1890,7 +1906,7 @@ static void remove_session_caps(struct c + struct super_block *sb = fsc->sb; + LIST_HEAD(dispose); + +- dout("remove_session_caps on %p\n", session); ++ doutc(fsc->client, "on %p\n", session); + ceph_iterate_session_caps(session, remove_session_caps_cb, fsc); + + wake_up_all(&fsc->mdsc->cap_flushing_wq); +@@ -1971,7 +1987,9 @@ static int wake_up_session_cb(struct ino + + static void wake_up_session_caps(struct ceph_mds_session *session, int ev) + { +- dout("wake_up_session_caps %p mds%d\n", session, session->s_mds); ++ struct ceph_client *cl = session->s_mdsc->fsc->client; ++ ++ doutc(cl, "session %p mds%d\n", session, session->s_mds); + ceph_iterate_session_caps(session, wake_up_session_cb, + (void *)(unsigned long)ev); + } +@@ -1985,25 +2003,26 @@ static void wake_up_session_caps(struct + static int send_renew_caps(struct ceph_mds_client *mdsc, + struct ceph_mds_session *session) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_msg *msg; + int state; + + if (time_after_eq(jiffies, session->s_cap_ttl) && + time_after_eq(session->s_cap_ttl, session->s_renew_requested)) +- pr_info("mds%d caps stale\n", session->s_mds); ++ pr_info_client(cl, "mds%d caps stale\n", session->s_mds); + session->s_renew_requested = jiffies; + + /* do not try to renew caps until a recovering mds has reconnected + * with its clients. */ + state = ceph_mdsmap_get_state(mdsc->mdsmap, session->s_mds); + if (state < CEPH_MDS_STATE_RECONNECT) { +- dout("send_renew_caps ignoring mds%d (%s)\n", +- session->s_mds, ceph_mds_state_name(state)); ++ doutc(cl, "ignoring mds%d (%s)\n", session->s_mds, ++ ceph_mds_state_name(state)); + return 0; + } + +- dout("send_renew_caps to mds%d (%s)\n", session->s_mds, +- ceph_mds_state_name(state)); ++ doutc(cl, "to mds%d (%s)\n", session->s_mds, ++ ceph_mds_state_name(state)); + msg = ceph_create_session_msg(CEPH_SESSION_REQUEST_RENEWCAPS, + ++session->s_renew_seq); + if (!msg) +@@ -2015,10 +2034,11 @@ static int send_renew_caps(struct ceph_m + static int send_flushmsg_ack(struct ceph_mds_client *mdsc, + struct ceph_mds_session *session, u64 seq) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_msg *msg; + +- dout("send_flushmsg_ack to mds%d (%s)s seq %lld\n", +- session->s_mds, ceph_session_state_name(session->s_state), seq); ++ doutc(cl, "to mds%d (%s)s seq %lld\n", session->s_mds, ++ ceph_session_state_name(session->s_state), seq); + msg = ceph_create_session_msg(CEPH_SESSION_FLUSHMSG_ACK, seq); + if (!msg) + return -ENOMEM; +@@ -2035,6 +2055,7 @@ static int send_flushmsg_ack(struct ceph + static void renewed_caps(struct ceph_mds_client *mdsc, + struct ceph_mds_session *session, int is_renew) + { ++ struct ceph_client *cl = mdsc->fsc->client; + int was_stale; + int wake = 0; + +@@ -2046,15 +2067,17 @@ static void renewed_caps(struct ceph_mds + + if (was_stale) { + if (time_before(jiffies, session->s_cap_ttl)) { +- pr_info("mds%d caps renewed\n", session->s_mds); ++ pr_info_client(cl, "mds%d caps renewed\n", ++ session->s_mds); + wake = 1; + } else { +- pr_info("mds%d caps still stale\n", session->s_mds); ++ pr_info_client(cl, "mds%d caps still stale\n", ++ session->s_mds); + } + } +- dout("renewed_caps mds%d ttl now %lu, was %s, now %s\n", +- session->s_mds, session->s_cap_ttl, was_stale ? "stale" : "fresh", +- time_before(jiffies, session->s_cap_ttl) ? "stale" : "fresh"); ++ doutc(cl, "mds%d ttl now %lu, was %s, now %s\n", session->s_mds, ++ session->s_cap_ttl, was_stale ? "stale" : "fresh", ++ time_before(jiffies, session->s_cap_ttl) ? "stale" : "fresh"); + spin_unlock(&session->s_cap_lock); + + if (wake) +@@ -2066,11 +2089,11 @@ static void renewed_caps(struct ceph_mds + */ + static int request_close_session(struct ceph_mds_session *session) + { ++ struct ceph_client *cl = session->s_mdsc->fsc->client; + struct ceph_msg *msg; + +- dout("request_close_session mds%d state %s seq %lld\n", +- session->s_mds, ceph_session_state_name(session->s_state), +- session->s_seq); ++ doutc(cl, "mds%d state %s seq %lld\n", session->s_mds, ++ ceph_session_state_name(session->s_state), session->s_seq); + msg = ceph_create_session_msg(CEPH_SESSION_REQUEST_CLOSE, + session->s_seq); + if (!msg) +@@ -2127,6 +2150,7 @@ out: + static int trim_caps_cb(struct inode *inode, int mds, void *arg) + { + struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb); ++ struct ceph_client *cl = mdsc->fsc->client; + int *remaining = arg; + struct ceph_inode_info *ci = ceph_inode(inode); + int used, wanted, oissued, mine; +@@ -2146,9 +2170,10 @@ static int trim_caps_cb(struct inode *in + wanted = __ceph_caps_file_wanted(ci); + oissued = __ceph_caps_issued_other(ci, cap); + +- dout("trim_caps_cb %p cap %p mine %s oissued %s used %s wanted %s\n", +- inode, cap, ceph_cap_string(mine), ceph_cap_string(oissued), +- ceph_cap_string(used), ceph_cap_string(wanted)); ++ doutc(cl, "%p %llx.%llx cap %p mine %s oissued %s used %s wanted %s\n", ++ inode, ceph_vinop(inode), cap, ceph_cap_string(mine), ++ ceph_cap_string(oissued), ceph_cap_string(used), ++ ceph_cap_string(wanted)); + if (cap == ci->i_auth_cap) { + if (ci->i_dirty_caps || ci->i_flushing_caps || + !list_empty(&ci->i_cap_snaps)) +@@ -2188,8 +2213,8 @@ static int trim_caps_cb(struct inode *in + count = atomic_read(&inode->i_count); + if (count == 1) + (*remaining)--; +- dout("trim_caps_cb %p cap %p pruned, count now %d\n", +- inode, cap, count); ++ doutc(cl, "%p %llx.%llx cap %p pruned, count now %d\n", ++ inode, ceph_vinop(inode), cap, count); + } else { + dput(dentry); + } +@@ -2208,17 +2233,18 @@ int ceph_trim_caps(struct ceph_mds_clien + struct ceph_mds_session *session, + int max_caps) + { ++ struct ceph_client *cl = mdsc->fsc->client; + int trim_caps = session->s_nr_caps - max_caps; + +- dout("trim_caps mds%d start: %d / %d, trim %d\n", +- session->s_mds, session->s_nr_caps, max_caps, trim_caps); ++ doutc(cl, "mds%d start: %d / %d, trim %d\n", session->s_mds, ++ session->s_nr_caps, max_caps, trim_caps); + if (trim_caps > 0) { + int remaining = trim_caps; + + ceph_iterate_session_caps(session, trim_caps_cb, &remaining); +- dout("trim_caps mds%d done: %d / %d, trimmed %d\n", +- session->s_mds, session->s_nr_caps, max_caps, +- trim_caps - remaining); ++ doutc(cl, "mds%d done: %d / %d, trimmed %d\n", ++ session->s_mds, session->s_nr_caps, max_caps, ++ trim_caps - remaining); + } + + ceph_flush_cap_releases(mdsc, session); +@@ -2228,6 +2254,7 @@ int ceph_trim_caps(struct ceph_mds_clien + static int check_caps_flush(struct ceph_mds_client *mdsc, + u64 want_flush_tid) + { ++ struct ceph_client *cl = mdsc->fsc->client; + int ret = 1; + + spin_lock(&mdsc->cap_dirty_lock); +@@ -2236,8 +2263,8 @@ static int check_caps_flush(struct ceph_ + list_first_entry(&mdsc->cap_flush_list, + struct ceph_cap_flush, g_list); + if (cf->tid <= want_flush_tid) { +- dout("check_caps_flush still flushing tid " +- "%llu <= %llu\n", cf->tid, want_flush_tid); ++ doutc(cl, "still flushing tid %llu <= %llu\n", ++ cf->tid, want_flush_tid); + ret = 0; + } + } +@@ -2253,12 +2280,14 @@ static int check_caps_flush(struct ceph_ + static void wait_caps_flush(struct ceph_mds_client *mdsc, + u64 want_flush_tid) + { +- dout("check_caps_flush want %llu\n", want_flush_tid); ++ struct ceph_client *cl = mdsc->fsc->client; ++ ++ doutc(cl, "want %llu\n", want_flush_tid); + + wait_event(mdsc->cap_flushing_wq, + check_caps_flush(mdsc, want_flush_tid)); + +- dout("check_caps_flush ok, flushed thru %llu\n", want_flush_tid); ++ doutc(cl, "ok, flushed thru %llu\n", want_flush_tid); + } + + /* +@@ -2267,6 +2296,7 @@ static void wait_caps_flush(struct ceph_ + static void ceph_send_cap_releases(struct ceph_mds_client *mdsc, + struct ceph_mds_session *session) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_msg *msg = NULL; + struct ceph_mds_cap_release *head; + struct ceph_mds_cap_item *item; +@@ -2325,7 +2355,7 @@ again: + msg->front.iov_len += sizeof(*cap_barrier); + + msg->hdr.front_len = cpu_to_le32(msg->front.iov_len); +- dout("send_cap_releases mds%d %p\n", session->s_mds, msg); ++ doutc(cl, "mds%d %p\n", session->s_mds, msg); + ceph_con_send(&session->s_con, msg); + msg = NULL; + } +@@ -2345,13 +2375,13 @@ again: + msg->front.iov_len += sizeof(*cap_barrier); + + msg->hdr.front_len = cpu_to_le32(msg->front.iov_len); +- dout("send_cap_releases mds%d %p\n", session->s_mds, msg); ++ doutc(cl, "mds%d %p\n", session->s_mds, msg); + ceph_con_send(&session->s_con, msg); + } + return; + out_err: +- pr_err("send_cap_releases mds%d, failed to allocate message\n", +- session->s_mds); ++ pr_err_client(cl, "mds%d, failed to allocate message\n", ++ session->s_mds); + spin_lock(&session->s_cap_lock); + list_splice(&tmp_list, &session->s_cap_releases); + session->s_num_cap_releases += num_cap_releases; +@@ -2374,16 +2404,17 @@ static void ceph_cap_release_work(struct + void ceph_flush_cap_releases(struct ceph_mds_client *mdsc, + struct ceph_mds_session *session) + { ++ struct ceph_client *cl = mdsc->fsc->client; + if (mdsc->stopping) + return; + + ceph_get_mds_session(session); + if (queue_work(mdsc->fsc->cap_wq, + &session->s_cap_release_work)) { +- dout("cap release work queued\n"); ++ doutc(cl, "cap release work queued\n"); + } else { + ceph_put_mds_session(session); +- dout("failed to queue cap release work\n"); ++ doutc(cl, "failed to queue cap release work\n"); + } + } + +@@ -2411,13 +2442,14 @@ static void ceph_cap_reclaim_work(struct + + void ceph_queue_cap_reclaim_work(struct ceph_mds_client *mdsc) + { ++ struct ceph_client *cl = mdsc->fsc->client; + if (mdsc->stopping) + return; + + if (queue_work(mdsc->fsc->cap_wq, &mdsc->cap_reclaim_work)) { +- dout("caps reclaim work queued\n"); ++ doutc(cl, "caps reclaim work queued\n"); + } else { +- dout("failed to queue caps release work\n"); ++ doutc(cl, "failed to queue caps release work\n"); + } + } + +@@ -2612,6 +2644,7 @@ static u8 *get_fscrypt_altname(const str + char *ceph_mdsc_build_path(struct ceph_mds_client *mdsc, struct dentry *dentry, + int *plen, u64 *pbase, int for_wire) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct dentry *cur; + struct inode *inode; + char *path; +@@ -2637,8 +2670,7 @@ retry: + spin_lock(&cur->d_lock); + inode = d_inode(cur); + if (inode && ceph_snap(inode) == CEPH_SNAPDIR) { +- dout("build_path path+%d: %p SNAPDIR\n", +- pos, cur); ++ doutc(cl, "path+%d: %p SNAPDIR\n", pos, cur); + spin_unlock(&cur->d_lock); + parent = dget_parent(cur); + } else if (for_wire && inode && dentry != cur && +@@ -2725,8 +2757,8 @@ retry: + + *pbase = base; + *plen = PATH_MAX - 1 - pos; +- dout("build_path on %p %d built %llx '%.*s'\n", +- dentry, d_count(dentry), base, *plen, path + pos); ++ doutc(cl, "on %p %d built %llx '%.*s'\n", dentry, d_count(dentry), ++ base, *plen, path + pos); + return path + pos; + } + +@@ -2789,22 +2821,22 @@ static int set_request_path_attr(struct + int *pathlen, u64 *ino, bool *freepath, + bool parent_locked) + { ++ struct ceph_client *cl = mdsc->fsc->client; + int r = 0; + + if (rinode) { + r = build_inode_path(rinode, ppath, pathlen, ino, freepath); +- dout(" inode %p %llx.%llx\n", rinode, ceph_ino(rinode), +- ceph_snap(rinode)); ++ doutc(cl, " inode %p %llx.%llx\n", rinode, ceph_ino(rinode), ++ ceph_snap(rinode)); + } else if (rdentry) { + r = build_dentry_path(mdsc, rdentry, rdiri, ppath, pathlen, ino, + freepath, parent_locked); +- dout(" dentry %p %llx/%.*s\n", rdentry, *ino, *pathlen, +- *ppath); ++ doutc(cl, " dentry %p %llx/%.*s\n", rdentry, *ino, *pathlen, *ppath); + } else if (rpath || rino) { + *ino = rino; + *ppath = rpath; + *pathlen = rpath ? strlen(rpath) : 0; +- dout(" path %.*s\n", *pathlen, rpath); ++ doutc(cl, " path %.*s\n", *pathlen, rpath); + } + + return r; +@@ -3105,6 +3137,7 @@ static int __prepare_send_request(struct + { + int mds = session->s_mds; + struct ceph_mds_client *mdsc = session->s_mdsc; ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_request_head_legacy *lhead; + struct ceph_mds_request_head *nhead; + struct ceph_msg *msg; +@@ -3123,8 +3156,8 @@ static int __prepare_send_request(struct + old_max_retry = 1 << (old_max_retry * BITS_PER_BYTE); + if ((old_version && req->r_attempts >= old_max_retry) || + ((uint32_t)req->r_attempts >= U32_MAX)) { +- pr_warn_ratelimited("%s request tid %llu seq overflow\n", +- __func__, req->r_tid); ++ pr_warn_ratelimited_client(cl, "request tid %llu seq overflow\n", ++ req->r_tid); + return -EMULTIHOP; + } + } +@@ -3139,8 +3172,8 @@ static int __prepare_send_request(struct + else + req->r_sent_on_mseq = -1; + } +- dout("%s %p tid %lld %s (attempt %d)\n", __func__, req, +- req->r_tid, ceph_mds_op_name(req->r_op), req->r_attempts); ++ doutc(cl, "%p tid %lld %s (attempt %d)\n", req, req->r_tid, ++ ceph_mds_op_name(req->r_op), req->r_attempts); + + if (test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags)) { + void *p; +@@ -3208,7 +3241,7 @@ static int __prepare_send_request(struct + nhead->ext_num_retry = cpu_to_le32(req->r_attempts - 1); + } + +- dout(" r_parent = %p\n", req->r_parent); ++ doutc(cl, " r_parent = %p\n", req->r_parent); + return 0; + } + +@@ -3236,6 +3269,7 @@ static int __send_request(struct ceph_md + static void __do_request(struct ceph_mds_client *mdsc, + struct ceph_mds_request *req) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_session *session = NULL; + int mds = -1; + int err = 0; +@@ -3248,29 +3282,29 @@ static void __do_request(struct ceph_mds + } + + if (READ_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_FENCE_IO) { +- dout("do_request metadata corrupted\n"); ++ doutc(cl, "metadata corrupted\n"); + err = -EIO; + goto finish; + } + if (req->r_timeout && + time_after_eq(jiffies, req->r_started + req->r_timeout)) { +- dout("do_request timed out\n"); ++ doutc(cl, "timed out\n"); + err = -ETIMEDOUT; + goto finish; + } + if (READ_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_SHUTDOWN) { +- dout("do_request forced umount\n"); ++ doutc(cl, "forced umount\n"); + err = -EIO; + goto finish; + } + if (READ_ONCE(mdsc->fsc->mount_state) == CEPH_MOUNT_MOUNTING) { + if (mdsc->mdsmap_err) { + err = mdsc->mdsmap_err; +- dout("do_request mdsmap err %d\n", err); ++ doutc(cl, "mdsmap err %d\n", err); + goto finish; + } + if (mdsc->mdsmap->m_epoch == 0) { +- dout("do_request no mdsmap, waiting for map\n"); ++ doutc(cl, "no mdsmap, waiting for map\n"); + list_add(&req->r_wait, &mdsc->waiting_for_map); + return; + } +@@ -3291,7 +3325,7 @@ static void __do_request(struct ceph_mds + err = -EJUKEBOX; + goto finish; + } +- dout("do_request no mds or not active, waiting for map\n"); ++ doutc(cl, "no mds or not active, waiting for map\n"); + list_add(&req->r_wait, &mdsc->waiting_for_map); + return; + } +@@ -3307,8 +3341,8 @@ static void __do_request(struct ceph_mds + } + req->r_session = ceph_get_mds_session(session); + +- dout("do_request mds%d session %p state %s\n", mds, session, +- ceph_session_state_name(session->s_state)); ++ doutc(cl, "mds%d session %p state %s\n", mds, session, ++ ceph_session_state_name(session->s_state)); + + /* + * The old ceph will crash the MDSs when see unknown OPs +@@ -3399,8 +3433,8 @@ static void __do_request(struct ceph_mds + spin_lock(&ci->i_ceph_lock); + cap = ci->i_auth_cap; + if (ci->i_ceph_flags & CEPH_I_ASYNC_CREATE && mds != cap->mds) { +- dout("do_request session changed for auth cap %d -> %d\n", +- cap->session->s_mds, session->s_mds); ++ doutc(cl, "session changed for auth cap %d -> %d\n", ++ cap->session->s_mds, session->s_mds); + + /* Remove the auth cap from old session */ + spin_lock(&cap->session->s_cap_lock); +@@ -3427,7 +3461,7 @@ out_session: + ceph_put_mds_session(session); + finish: + if (err) { +- dout("__do_request early error %d\n", err); ++ doutc(cl, "early error %d\n", err); + req->r_err = err; + complete_request(mdsc, req); + __unregister_request(mdsc, req); +@@ -3441,6 +3475,7 @@ finish: + static void __wake_requests(struct ceph_mds_client *mdsc, + struct list_head *head) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_request *req; + LIST_HEAD(tmp_list); + +@@ -3450,7 +3485,8 @@ static void __wake_requests(struct ceph_ + req = list_entry(tmp_list.next, + struct ceph_mds_request, r_wait); + list_del_init(&req->r_wait); +- dout(" wake request %p tid %llu\n", req, req->r_tid); ++ doutc(cl, " wake request %p tid %llu\n", req, ++ req->r_tid); + __do_request(mdsc, req); + } + } +@@ -3461,10 +3497,11 @@ static void __wake_requests(struct ceph_ + */ + static void kick_requests(struct ceph_mds_client *mdsc, int mds) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_request *req; + struct rb_node *p = rb_first(&mdsc->request_tree); + +- dout("kick_requests mds%d\n", mds); ++ doutc(cl, "kick_requests mds%d\n", mds); + while (p) { + req = rb_entry(p, struct ceph_mds_request, r_node); + p = rb_next(p); +@@ -3474,7 +3511,7 @@ static void kick_requests(struct ceph_md + continue; /* only new requests */ + if (req->r_session && + req->r_session->s_mds == mds) { +- dout(" kicking tid %llu\n", req->r_tid); ++ doutc(cl, " kicking tid %llu\n", req->r_tid); + list_del_init(&req->r_wait); + __do_request(mdsc, req); + } +@@ -3484,6 +3521,7 @@ static void kick_requests(struct ceph_md + int ceph_mdsc_submit_request(struct ceph_mds_client *mdsc, struct inode *dir, + struct ceph_mds_request *req) + { ++ struct ceph_client *cl = mdsc->fsc->client; + int err = 0; + + /* take CAP_PIN refs for r_inode, r_parent, r_old_dentry */ +@@ -3505,8 +3543,7 @@ int ceph_mdsc_submit_request(struct ceph + if (req->r_inode) { + err = ceph_wait_on_async_create(req->r_inode); + if (err) { +- dout("%s: wait for async create returned: %d\n", +- __func__, err); ++ doutc(cl, "wait for async create returned: %d\n", err); + return err; + } + } +@@ -3514,13 +3551,12 @@ int ceph_mdsc_submit_request(struct ceph + if (!err && req->r_old_inode) { + err = ceph_wait_on_async_create(req->r_old_inode); + if (err) { +- dout("%s: wait for async create returned: %d\n", +- __func__, err); ++ doutc(cl, "wait for async create returned: %d\n", err); + return err; + } + } + +- dout("submit_request on %p for inode %p\n", req, dir); ++ doutc(cl, "submit_request on %p for inode %p\n", req, dir); + mutex_lock(&mdsc->mutex); + __register_request(mdsc, req, dir); + __do_request(mdsc, req); +@@ -3533,10 +3569,11 @@ int ceph_mdsc_wait_request(struct ceph_m + struct ceph_mds_request *req, + ceph_mds_request_wait_callback_t wait_func) + { ++ struct ceph_client *cl = mdsc->fsc->client; + int err; + + /* wait */ +- dout("do_request waiting\n"); ++ doutc(cl, "do_request waiting\n"); + if (wait_func) { + err = wait_func(mdsc, req); + } else { +@@ -3550,14 +3587,14 @@ int ceph_mdsc_wait_request(struct ceph_m + else + err = timeleft; /* killed */ + } +- dout("do_request waited, got %d\n", err); ++ doutc(cl, "do_request waited, got %d\n", err); + mutex_lock(&mdsc->mutex); + + /* only abort if we didn't race with a real reply */ + if (test_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags)) { + err = le32_to_cpu(req->r_reply_info.head->result); + } else if (err < 0) { +- dout("aborted request %lld with %d\n", req->r_tid, err); ++ doutc(cl, "aborted request %lld with %d\n", req->r_tid, err); + + /* + * ensure we aren't running concurrently with +@@ -3588,15 +3625,16 @@ int ceph_mdsc_do_request(struct ceph_mds + struct inode *dir, + struct ceph_mds_request *req) + { ++ struct ceph_client *cl = mdsc->fsc->client; + int err; + +- dout("do_request on %p\n", req); ++ doutc(cl, "do_request on %p\n", req); + + /* issue */ + err = ceph_mdsc_submit_request(mdsc, dir, req); + if (!err) + err = ceph_mdsc_wait_request(mdsc, req, NULL); +- dout("do_request %p done, result %d\n", req, err); ++ doutc(cl, "do_request %p done, result %d\n", req, err); + return err; + } + +@@ -3608,8 +3646,10 @@ void ceph_invalidate_dir_request(struct + { + struct inode *dir = req->r_parent; + struct inode *old_dir = req->r_old_dentry_dir; ++ struct ceph_client *cl = req->r_mdsc->fsc->client; + +- dout("invalidate_dir_request %p %p (complete, lease(s))\n", dir, old_dir); ++ doutc(cl, "invalidate_dir_request %p %p (complete, lease(s))\n", ++ dir, old_dir); + + ceph_dir_clear_complete(dir); + if (old_dir) +@@ -3630,6 +3670,7 @@ void ceph_invalidate_dir_request(struct + static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) + { + struct ceph_mds_client *mdsc = session->s_mdsc; ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_request *req; + struct ceph_mds_reply_head *head = msg->front.iov_base; + struct ceph_mds_reply_info_parsed *rinfo; /* parsed reply info */ +@@ -3640,7 +3681,7 @@ static void handle_reply(struct ceph_mds + bool close_sessions = false; + + if (msg->front.iov_len < sizeof(*head)) { +- pr_err("mdsc_handle_reply got corrupt (short) reply\n"); ++ pr_err_client(cl, "got corrupt (short) reply\n"); + ceph_msg_dump(msg); + return; + } +@@ -3650,17 +3691,17 @@ static void handle_reply(struct ceph_mds + mutex_lock(&mdsc->mutex); + req = lookup_get_request(mdsc, tid); + if (!req) { +- dout("handle_reply on unknown tid %llu\n", tid); ++ doutc(cl, "on unknown tid %llu\n", tid); + mutex_unlock(&mdsc->mutex); + return; + } +- dout("handle_reply %p\n", req); ++ doutc(cl, "handle_reply %p\n", req); + + /* correct session? */ + if (req->r_session != session) { +- pr_err("mdsc_handle_reply got %llu on session mds%d" +- " not mds%d\n", tid, session->s_mds, +- req->r_session ? req->r_session->s_mds : -1); ++ pr_err_client(cl, "got %llu on session mds%d not mds%d\n", ++ tid, session->s_mds, ++ req->r_session ? req->r_session->s_mds : -1); + mutex_unlock(&mdsc->mutex); + goto out; + } +@@ -3668,14 +3709,14 @@ static void handle_reply(struct ceph_mds + /* dup? */ + if ((test_bit(CEPH_MDS_R_GOT_UNSAFE, &req->r_req_flags) && !head->safe) || + (test_bit(CEPH_MDS_R_GOT_SAFE, &req->r_req_flags) && head->safe)) { +- pr_warn("got a dup %s reply on %llu from mds%d\n", +- head->safe ? "safe" : "unsafe", tid, mds); ++ pr_warn_client(cl, "got a dup %s reply on %llu from mds%d\n", ++ head->safe ? "safe" : "unsafe", tid, mds); + mutex_unlock(&mdsc->mutex); + goto out; + } + if (test_bit(CEPH_MDS_R_GOT_SAFE, &req->r_req_flags)) { +- pr_warn("got unsafe after safe on %llu from mds%d\n", +- tid, mds); ++ pr_warn_client(cl, "got unsafe after safe on %llu from mds%d\n", ++ tid, mds); + mutex_unlock(&mdsc->mutex); + goto out; + } +@@ -3698,7 +3739,7 @@ static void handle_reply(struct ceph_mds + * response. And even if it did, there is nothing + * useful we could do with a revised return value. + */ +- dout("got safe reply %llu, mds%d\n", tid, mds); ++ doutc(cl, "got safe reply %llu, mds%d\n", tid, mds); + + mutex_unlock(&mdsc->mutex); + goto out; +@@ -3708,7 +3749,7 @@ static void handle_reply(struct ceph_mds + list_add_tail(&req->r_unsafe_item, &req->r_session->s_unsafe); + } + +- dout("handle_reply tid %lld result %d\n", tid, result); ++ doutc(cl, "tid %lld result %d\n", tid, result); + if (test_bit(CEPHFS_FEATURE_REPLY_ENCODING, &session->s_features)) + err = parse_reply_info(session, msg, req, (u64)-1); + else +@@ -3748,7 +3789,8 @@ static void handle_reply(struct ceph_mds + + mutex_lock(&session->s_mutex); + if (err < 0) { +- pr_err("mdsc_handle_reply got corrupt reply mds%d(tid:%lld)\n", mds, tid); ++ pr_err_client(cl, "got corrupt reply mds%d(tid:%lld)\n", ++ mds, tid); + ceph_msg_dump(msg); + goto out_err; + } +@@ -3812,7 +3854,7 @@ out_err: + set_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags); + } + } else { +- dout("reply arrived after request %lld was aborted\n", tid); ++ doutc(cl, "reply arrived after request %lld was aborted\n", tid); + } + mutex_unlock(&mdsc->mutex); + +@@ -3841,6 +3883,7 @@ static void handle_forward(struct ceph_m + struct ceph_mds_session *session, + struct ceph_msg *msg) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_request *req; + u64 tid = le64_to_cpu(msg->hdr.tid); + u32 next_mds; +@@ -3858,12 +3901,12 @@ static void handle_forward(struct ceph_m + req = lookup_get_request(mdsc, tid); + if (!req) { + mutex_unlock(&mdsc->mutex); +- dout("forward tid %llu to mds%d - req dne\n", tid, next_mds); ++ doutc(cl, "forward tid %llu to mds%d - req dne\n", tid, next_mds); + return; /* dup reply? */ + } + + if (test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags)) { +- dout("forward tid %llu aborted, unregistering\n", tid); ++ doutc(cl, "forward tid %llu aborted, unregistering\n", tid); + __unregister_request(mdsc, req); + } else if (fwd_seq <= req->r_num_fwd || (uint32_t)fwd_seq >= U32_MAX) { + /* +@@ -3879,10 +3922,11 @@ static void handle_forward(struct ceph_m + set_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags); + mutex_unlock(&req->r_fill_mutex); + aborted = true; +- pr_warn_ratelimited("forward tid %llu seq overflow\n", tid); ++ pr_warn_ratelimited_client(cl, "forward tid %llu seq overflow\n", ++ tid); + } else { + /* resend. forward race not possible; mds would drop */ +- dout("forward tid %llu to mds%d (we resend)\n", tid, next_mds); ++ doutc(cl, "forward tid %llu to mds%d (we resend)\n", tid, next_mds); + BUG_ON(req->r_err); + BUG_ON(test_bit(CEPH_MDS_R_GOT_RESULT, &req->r_req_flags)); + req->r_attempts = 0; +@@ -3900,7 +3944,7 @@ static void handle_forward(struct ceph_m + return; + + bad: +- pr_err("mdsc_handle_forward decode error err=%d\n", err); ++ pr_err_client(cl, "decode error err=%d\n", err); + ceph_msg_dump(msg); + } + +@@ -3939,6 +3983,7 @@ static void handle_session(struct ceph_m + struct ceph_msg *msg) + { + struct ceph_mds_client *mdsc = session->s_mdsc; ++ struct ceph_client *cl = mdsc->fsc->client; + int mds = session->s_mds; + int msg_version = le16_to_cpu(msg->hdr.version); + void *p = msg->front.iov_base; +@@ -3986,7 +4031,8 @@ static void handle_session(struct ceph_m + /* version >= 5, flags */ + ceph_decode_32_safe(&p, end, flags, bad); + if (flags & CEPH_SESSION_BLOCKLISTED) { +- pr_warn("mds%d session blocklisted\n", session->s_mds); ++ pr_warn_client(cl, "mds%d session blocklisted\n", ++ session->s_mds); + blocklisted = true; + } + } +@@ -4002,23 +4048,25 @@ static void handle_session(struct ceph_m + + mutex_lock(&session->s_mutex); + +- dout("handle_session mds%d %s %p state %s seq %llu\n", +- mds, ceph_session_op_name(op), session, +- ceph_session_state_name(session->s_state), seq); ++ doutc(cl, "mds%d %s %p state %s seq %llu\n", mds, ++ ceph_session_op_name(op), session, ++ ceph_session_state_name(session->s_state), seq); + + if (session->s_state == CEPH_MDS_SESSION_HUNG) { + session->s_state = CEPH_MDS_SESSION_OPEN; +- pr_info("mds%d came back\n", session->s_mds); ++ pr_info_client(cl, "mds%d came back\n", session->s_mds); + } + + switch (op) { + case CEPH_SESSION_OPEN: + if (session->s_state == CEPH_MDS_SESSION_RECONNECTING) +- pr_info("mds%d reconnect success\n", session->s_mds); ++ pr_info_client(cl, "mds%d reconnect success\n", ++ session->s_mds); + + session->s_features = features; + if (session->s_state == CEPH_MDS_SESSION_OPEN) { +- pr_notice("mds%d is already opened\n", session->s_mds); ++ pr_notice_client(cl, "mds%d is already opened\n", ++ session->s_mds); + } else { + session->s_state = CEPH_MDS_SESSION_OPEN; + renewed_caps(mdsc, session, 0); +@@ -4047,7 +4095,8 @@ static void handle_session(struct ceph_m + + case CEPH_SESSION_CLOSE: + if (session->s_state == CEPH_MDS_SESSION_RECONNECTING) +- pr_info("mds%d reconnect denied\n", session->s_mds); ++ pr_info_client(cl, "mds%d reconnect denied\n", ++ session->s_mds); + session->s_state = CEPH_MDS_SESSION_CLOSED; + cleanup_session_requests(mdsc, session); + remove_session_caps(session); +@@ -4056,8 +4105,8 @@ static void handle_session(struct ceph_m + break; + + case CEPH_SESSION_STALE: +- pr_info("mds%d caps went stale, renewing\n", +- session->s_mds); ++ pr_info_client(cl, "mds%d caps went stale, renewing\n", ++ session->s_mds); + atomic_inc(&session->s_cap_gen); + session->s_cap_ttl = jiffies - 1; + send_renew_caps(mdsc, session); +@@ -4078,7 +4127,7 @@ static void handle_session(struct ceph_m + break; + + case CEPH_SESSION_FORCE_RO: +- dout("force_session_readonly %p\n", session); ++ doutc(cl, "force_session_readonly %p\n", session); + spin_lock(&session->s_cap_lock); + session->s_readonly = true; + spin_unlock(&session->s_cap_lock); +@@ -4087,7 +4136,8 @@ static void handle_session(struct ceph_m + + case CEPH_SESSION_REJECT: + WARN_ON(session->s_state != CEPH_MDS_SESSION_OPENING); +- pr_info("mds%d rejected session\n", session->s_mds); ++ pr_info_client(cl, "mds%d rejected session\n", ++ session->s_mds); + session->s_state = CEPH_MDS_SESSION_REJECTED; + cleanup_session_requests(mdsc, session); + remove_session_caps(session); +@@ -4097,7 +4147,7 @@ static void handle_session(struct ceph_m + break; + + default: +- pr_err("mdsc_handle_session bad op %d mds%d\n", op, mds); ++ pr_err_client(cl, "bad op %d mds%d\n", op, mds); + WARN_ON(1); + } + +@@ -4114,30 +4164,32 @@ static void handle_session(struct ceph_m + return; + + bad: +- pr_err("mdsc_handle_session corrupt message mds%d len %d\n", mds, +- (int)msg->front.iov_len); ++ pr_err_client(cl, "corrupt message mds%d len %d\n", mds, ++ (int)msg->front.iov_len); + ceph_msg_dump(msg); + return; + } + + void ceph_mdsc_release_dir_caps(struct ceph_mds_request *req) + { ++ struct ceph_client *cl = req->r_mdsc->fsc->client; + int dcaps; + + dcaps = xchg(&req->r_dir_caps, 0); + if (dcaps) { +- dout("releasing r_dir_caps=%s\n", ceph_cap_string(dcaps)); ++ doutc(cl, "releasing r_dir_caps=%s\n", ceph_cap_string(dcaps)); + ceph_put_cap_refs(ceph_inode(req->r_parent), dcaps); + } + } + + void ceph_mdsc_release_dir_caps_no_check(struct ceph_mds_request *req) + { ++ struct ceph_client *cl = req->r_mdsc->fsc->client; + int dcaps; + + dcaps = xchg(&req->r_dir_caps, 0); + if (dcaps) { +- dout("releasing r_dir_caps=%s\n", ceph_cap_string(dcaps)); ++ doutc(cl, "releasing r_dir_caps=%s\n", ceph_cap_string(dcaps)); + ceph_put_cap_refs_no_check_caps(ceph_inode(req->r_parent), + dcaps); + } +@@ -4152,7 +4204,7 @@ static void replay_unsafe_requests(struc + struct ceph_mds_request *req, *nreq; + struct rb_node *p; + +- dout("replay_unsafe_requests mds%d\n", session->s_mds); ++ doutc(mdsc->fsc->client, "mds%d\n", session->s_mds); + + mutex_lock(&mdsc->mutex); + list_for_each_entry_safe(req, nreq, &session->s_unsafe, r_unsafe_item) +@@ -4297,6 +4349,7 @@ out_unlock: + static int reconnect_caps_cb(struct inode *inode, int mds, void *arg) + { + struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + union { + struct ceph_mds_cap_reconnect v2; + struct ceph_mds_cap_reconnect_v1 v1; +@@ -4333,9 +4386,9 @@ static int reconnect_caps_cb(struct inod + err = 0; + goto out_err; + } +- dout(" adding %p ino %llx.%llx cap %p %lld %s\n", +- inode, ceph_vinop(inode), cap, cap->cap_id, +- ceph_cap_string(cap->issued)); ++ doutc(cl, " adding %p ino %llx.%llx cap %p %lld %s\n", inode, ++ ceph_vinop(inode), cap, cap->cap_id, ++ ceph_cap_string(cap->issued)); + + cap->seq = 0; /* reset cap seq */ + cap->issue_seq = 0; /* and issue_seq */ +@@ -4485,6 +4538,7 @@ static int encode_snap_realms(struct cep + { + struct rb_node *p; + struct ceph_pagelist *pagelist = recon_state->pagelist; ++ struct ceph_client *cl = mdsc->fsc->client; + int err = 0; + + if (recon_state->msg_version >= 4) { +@@ -4523,8 +4577,8 @@ static int encode_snap_realms(struct cep + ceph_pagelist_encode_32(pagelist, sizeof(sr_rec)); + } + +- dout(" adding snap realm %llx seq %lld parent %llx\n", +- realm->ino, realm->seq, realm->parent_ino); ++ doutc(cl, " adding snap realm %llx seq %lld parent %llx\n", ++ realm->ino, realm->seq, realm->parent_ino); + sr_rec.ino = cpu_to_le64(realm->ino); + sr_rec.seq = cpu_to_le64(realm->seq); + sr_rec.parent = cpu_to_le64(realm->parent_ino); +@@ -4553,6 +4607,7 @@ fail: + static void send_mds_reconnect(struct ceph_mds_client *mdsc, + struct ceph_mds_session *session) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_msg *reply; + int mds = session->s_mds; + int err = -ENOMEM; +@@ -4561,7 +4616,7 @@ static void send_mds_reconnect(struct ce + }; + LIST_HEAD(dispose); + +- pr_info("mds%d reconnect start\n", mds); ++ pr_info_client(cl, "mds%d reconnect start\n", mds); + + recon_state.pagelist = ceph_pagelist_alloc(GFP_NOFS); + if (!recon_state.pagelist) +@@ -4577,8 +4632,8 @@ static void send_mds_reconnect(struct ce + session->s_state = CEPH_MDS_SESSION_RECONNECTING; + session->s_seq = 0; + +- dout("session %p state %s\n", session, +- ceph_session_state_name(session->s_state)); ++ doutc(cl, "session %p state %s\n", session, ++ ceph_session_state_name(session->s_state)); + + atomic_inc(&session->s_cap_gen); + +@@ -4712,7 +4767,8 @@ fail: + fail_nomsg: + ceph_pagelist_release(recon_state.pagelist); + fail_nopagelist: +- pr_err("error %d preparing reconnect for mds%d\n", err, mds); ++ pr_err_client(cl, "error %d preparing reconnect for mds%d\n", ++ err, mds); + return; + } + +@@ -4731,9 +4787,9 @@ static void check_new_map(struct ceph_md + int oldstate, newstate; + struct ceph_mds_session *s; + unsigned long targets[DIV_ROUND_UP(CEPH_MAX_MDS, sizeof(unsigned long))] = {0}; ++ struct ceph_client *cl = mdsc->fsc->client; + +- dout("check_new_map new %u old %u\n", +- newmap->m_epoch, oldmap->m_epoch); ++ doutc(cl, "new %u old %u\n", newmap->m_epoch, oldmap->m_epoch); + + if (newmap->m_info) { + for (i = 0; i < newmap->possible_max_rank; i++) { +@@ -4749,12 +4805,12 @@ static void check_new_map(struct ceph_md + oldstate = ceph_mdsmap_get_state(oldmap, i); + newstate = ceph_mdsmap_get_state(newmap, i); + +- dout("check_new_map mds%d state %s%s -> %s%s (session %s)\n", +- i, ceph_mds_state_name(oldstate), +- ceph_mdsmap_is_laggy(oldmap, i) ? " (laggy)" : "", +- ceph_mds_state_name(newstate), +- ceph_mdsmap_is_laggy(newmap, i) ? " (laggy)" : "", +- ceph_session_state_name(s->s_state)); ++ doutc(cl, "mds%d state %s%s -> %s%s (session %s)\n", ++ i, ceph_mds_state_name(oldstate), ++ ceph_mdsmap_is_laggy(oldmap, i) ? " (laggy)" : "", ++ ceph_mds_state_name(newstate), ++ ceph_mdsmap_is_laggy(newmap, i) ? " (laggy)" : "", ++ ceph_session_state_name(s->s_state)); + + if (i >= newmap->possible_max_rank) { + /* force close session for stopped mds */ +@@ -4807,7 +4863,8 @@ static void check_new_map(struct ceph_md + newstate >= CEPH_MDS_STATE_ACTIVE) { + if (oldstate != CEPH_MDS_STATE_CREATING && + oldstate != CEPH_MDS_STATE_STARTING) +- pr_info("mds%d recovery completed\n", s->s_mds); ++ pr_info_client(cl, "mds%d recovery completed\n", ++ s->s_mds); + kick_requests(mdsc, i); + mutex_unlock(&mdsc->mutex); + mutex_lock(&s->s_mutex); +@@ -4851,12 +4908,13 @@ static void check_new_map(struct ceph_md + s = __open_export_target_session(mdsc, i); + if (IS_ERR(s)) { + err = PTR_ERR(s); +- pr_err("failed to open export target session, err %d\n", +- err); ++ pr_err_client(cl, ++ "failed to open export target session, err %d\n", ++ err); + continue; + } + } +- dout("send reconnect to export target mds.%d\n", i); ++ doutc(cl, "send reconnect to export target mds.%d\n", i); + mutex_unlock(&mdsc->mutex); + send_mds_reconnect(mdsc, s); + ceph_put_mds_session(s); +@@ -4872,8 +4930,7 @@ static void check_new_map(struct ceph_md + if (s->s_state == CEPH_MDS_SESSION_OPEN || + s->s_state == CEPH_MDS_SESSION_HUNG || + s->s_state == CEPH_MDS_SESSION_CLOSING) { +- dout(" connecting to export targets of laggy mds%d\n", +- i); ++ doutc(cl, " connecting to export targets of laggy mds%d\n", i); + __open_export_target_sessions(mdsc, s); + } + } +@@ -4900,6 +4957,7 @@ static void handle_lease(struct ceph_mds + struct ceph_mds_session *session, + struct ceph_msg *msg) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct super_block *sb = mdsc->fsc->sb; + struct inode *inode; + struct dentry *parent, *dentry; +@@ -4911,7 +4969,7 @@ static void handle_lease(struct ceph_mds + struct qstr dname; + int release = 0; + +- dout("handle_lease from mds%d\n", mds); ++ doutc(cl, "from mds%d\n", mds); + + if (!ceph_inc_mds_stopping_blocker(mdsc, session)) + return; +@@ -4929,20 +4987,19 @@ static void handle_lease(struct ceph_mds + + /* lookup inode */ + inode = ceph_find_inode(sb, vino); +- dout("handle_lease %s, ino %llx %p %.*s\n", +- ceph_lease_op_name(h->action), vino.ino, inode, +- dname.len, dname.name); ++ doutc(cl, "%s, ino %llx %p %.*s\n", ceph_lease_op_name(h->action), ++ vino.ino, inode, dname.len, dname.name); + + mutex_lock(&session->s_mutex); + if (!inode) { +- dout("handle_lease no inode %llx\n", vino.ino); ++ doutc(cl, "no inode %llx\n", vino.ino); + goto release; + } + + /* dentry */ + parent = d_find_alias(inode); + if (!parent) { +- dout("no parent dentry on inode %p\n", inode); ++ doutc(cl, "no parent dentry on inode %p\n", inode); + WARN_ON(1); + goto release; /* hrm... */ + } +@@ -5002,7 +5059,7 @@ out: + bad: + ceph_dec_mds_stopping_blocker(mdsc); + +- pr_err("corrupt lease message\n"); ++ pr_err_client(cl, "corrupt lease message\n"); + ceph_msg_dump(msg); + } + +@@ -5010,13 +5067,14 @@ void ceph_mdsc_lease_send_msg(struct cep + struct dentry *dentry, char action, + u32 seq) + { ++ struct ceph_client *cl = session->s_mdsc->fsc->client; + struct ceph_msg *msg; + struct ceph_mds_lease *lease; + struct inode *dir; + int len = sizeof(*lease) + sizeof(u32) + NAME_MAX; + +- dout("lease_send_msg identry %p %s to mds%d\n", +- dentry, ceph_lease_op_name(action), session->s_mds); ++ doutc(cl, "identry %p %s to mds%d\n", dentry, ceph_lease_op_name(action), ++ session->s_mds); + + msg = ceph_msg_new(CEPH_MSG_CLIENT_LEASE, len, GFP_NOFS, false); + if (!msg) +@@ -5049,6 +5107,7 @@ static void lock_unlock_session(struct c + + static void maybe_recover_session(struct ceph_mds_client *mdsc) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_fs_client *fsc = mdsc->fsc; + + if (!ceph_test_mount_opt(fsc, CLEANRECOVER)) +@@ -5060,17 +5119,19 @@ static void maybe_recover_session(struct + if (!READ_ONCE(fsc->blocklisted)) + return; + +- pr_info("auto reconnect after blocklisted\n"); ++ pr_info_client(cl, "auto reconnect after blocklisted\n"); + ceph_force_reconnect(fsc->sb); + } + + bool check_session_state(struct ceph_mds_session *s) + { ++ struct ceph_client *cl = s->s_mdsc->fsc->client; ++ + switch (s->s_state) { + case CEPH_MDS_SESSION_OPEN: + if (s->s_ttl && time_after(jiffies, s->s_ttl)) { + s->s_state = CEPH_MDS_SESSION_HUNG; +- pr_info("mds%d hung\n", s->s_mds); ++ pr_info_client(cl, "mds%d hung\n", s->s_mds); + } + break; + case CEPH_MDS_SESSION_CLOSING: +@@ -5090,6 +5151,8 @@ bool check_session_state(struct ceph_mds + */ + void inc_session_sequence(struct ceph_mds_session *s) + { ++ struct ceph_client *cl = s->s_mdsc->fsc->client; ++ + lockdep_assert_held(&s->s_mutex); + + s->s_seq++; +@@ -5097,11 +5160,11 @@ void inc_session_sequence(struct ceph_md + if (s->s_state == CEPH_MDS_SESSION_CLOSING) { + int ret; + +- dout("resending session close request for mds%d\n", s->s_mds); ++ doutc(cl, "resending session close request for mds%d\n", s->s_mds); + ret = request_close_session(s); + if (ret < 0) +- pr_err("unable to close session to mds%d: %d\n", +- s->s_mds, ret); ++ pr_err_client(cl, "unable to close session to mds%d: %d\n", ++ s->s_mds, ret); + } + } + +@@ -5130,7 +5193,7 @@ static void delayed_work(struct work_str + int renew_caps; + int i; + +- dout("mdsc delayed_work\n"); ++ doutc(mdsc->fsc->client, "mdsc delayed_work\n"); + + if (mdsc->stopping >= CEPH_MDSC_STOPPING_FLUSHED) + return; +@@ -5259,6 +5322,7 @@ err_mdsc: + */ + static void wait_requests(struct ceph_mds_client *mdsc) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_options *opts = mdsc->fsc->client->options; + struct ceph_mds_request *req; + +@@ -5266,25 +5330,25 @@ static void wait_requests(struct ceph_md + if (__get_oldest_req(mdsc)) { + mutex_unlock(&mdsc->mutex); + +- dout("wait_requests waiting for requests\n"); ++ doutc(cl, "waiting for requests\n"); + wait_for_completion_timeout(&mdsc->safe_umount_waiters, + ceph_timeout_jiffies(opts->mount_timeout)); + + /* tear down remaining requests */ + mutex_lock(&mdsc->mutex); + while ((req = __get_oldest_req(mdsc))) { +- dout("wait_requests timed out on tid %llu\n", +- req->r_tid); ++ doutc(cl, "timed out on tid %llu\n", req->r_tid); + list_del_init(&req->r_wait); + __unregister_request(mdsc, req); + } + } + mutex_unlock(&mdsc->mutex); +- dout("wait_requests done\n"); ++ doutc(cl, "done\n"); + } + + void send_flush_mdlog(struct ceph_mds_session *s) + { ++ struct ceph_client *cl = s->s_mdsc->fsc->client; + struct ceph_msg *msg; + + /* +@@ -5294,13 +5358,13 @@ void send_flush_mdlog(struct ceph_mds_se + return; + + mutex_lock(&s->s_mutex); +- dout("request mdlog flush to mds%d (%s)s seq %lld\n", s->s_mds, +- ceph_session_state_name(s->s_state), s->s_seq); ++ doutc(cl, "request mdlog flush to mds%d (%s)s seq %lld\n", ++ s->s_mds, ceph_session_state_name(s->s_state), s->s_seq); + msg = ceph_create_session_msg(CEPH_SESSION_REQUEST_FLUSH_MDLOG, + s->s_seq); + if (!msg) { +- pr_err("failed to request mdlog flush to mds%d (%s) seq %lld\n", +- s->s_mds, ceph_session_state_name(s->s_state), s->s_seq); ++ pr_err_client(cl, "failed to request mdlog flush to mds%d (%s) seq %lld\n", ++ s->s_mds, ceph_session_state_name(s->s_state), s->s_seq); + } else { + ceph_con_send(&s->s_con, msg); + } +@@ -5313,7 +5377,7 @@ void send_flush_mdlog(struct ceph_mds_se + */ + void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc) + { +- dout("pre_umount\n"); ++ doutc(mdsc->fsc->client, "begin\n"); + mdsc->stopping = CEPH_MDSC_STOPPING_BEGIN; + + ceph_mdsc_iterate_sessions(mdsc, send_flush_mdlog, true); +@@ -5328,6 +5392,7 @@ void ceph_mdsc_pre_umount(struct ceph_md + ceph_msgr_flush(); + + ceph_cleanup_quotarealms_inodes(mdsc); ++ doutc(mdsc->fsc->client, "done\n"); + } + + /* +@@ -5336,12 +5401,13 @@ void ceph_mdsc_pre_umount(struct ceph_md + static void flush_mdlog_and_wait_mdsc_unsafe_requests(struct ceph_mds_client *mdsc, + u64 want_tid) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_request *req = NULL, *nextreq; + struct ceph_mds_session *last_session = NULL; + struct rb_node *n; + + mutex_lock(&mdsc->mutex); +- dout("%s want %lld\n", __func__, want_tid); ++ doutc(cl, "want %lld\n", want_tid); + restart: + req = __get_oldest_req(mdsc); + while (req && req->r_tid <= want_tid) { +@@ -5375,8 +5441,8 @@ restart: + } else { + ceph_put_mds_session(s); + } +- dout("%s wait on %llu (want %llu)\n", __func__, +- req->r_tid, want_tid); ++ doutc(cl, "wait on %llu (want %llu)\n", ++ req->r_tid, want_tid); + wait_for_completion(&req->r_safe_completion); + + mutex_lock(&mdsc->mutex); +@@ -5394,17 +5460,18 @@ restart: + } + mutex_unlock(&mdsc->mutex); + ceph_put_mds_session(last_session); +- dout("%s done\n", __func__); ++ doutc(cl, "done\n"); + } + + void ceph_mdsc_sync(struct ceph_mds_client *mdsc) + { ++ struct ceph_client *cl = mdsc->fsc->client; + u64 want_tid, want_flush; + + if (READ_ONCE(mdsc->fsc->mount_state) >= CEPH_MOUNT_SHUTDOWN) + return; + +- dout("sync\n"); ++ doutc(cl, "sync\n"); + mutex_lock(&mdsc->mutex); + want_tid = mdsc->last_tid; + mutex_unlock(&mdsc->mutex); +@@ -5420,8 +5487,7 @@ void ceph_mdsc_sync(struct ceph_mds_clie + } + spin_unlock(&mdsc->cap_dirty_lock); + +- dout("sync want tid %lld flush_seq %lld\n", +- want_tid, want_flush); ++ doutc(cl, "sync want tid %lld flush_seq %lld\n", want_tid, want_flush); + + flush_mdlog_and_wait_mdsc_unsafe_requests(mdsc, want_tid); + wait_caps_flush(mdsc, want_flush); +@@ -5443,11 +5509,12 @@ static bool done_closing_sessions(struct + void ceph_mdsc_close_sessions(struct ceph_mds_client *mdsc) + { + struct ceph_options *opts = mdsc->fsc->client->options; ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_session *session; + int i; + int skipped = 0; + +- dout("close_sessions\n"); ++ doutc(cl, "begin\n"); + + /* close sessions */ + mutex_lock(&mdsc->mutex); +@@ -5465,7 +5532,7 @@ void ceph_mdsc_close_sessions(struct cep + } + mutex_unlock(&mdsc->mutex); + +- dout("waiting for sessions to close\n"); ++ doutc(cl, "waiting for sessions to close\n"); + wait_event_timeout(mdsc->session_close_wq, + done_closing_sessions(mdsc, skipped), + ceph_timeout_jiffies(opts->mount_timeout)); +@@ -5493,7 +5560,7 @@ void ceph_mdsc_close_sessions(struct cep + cancel_work_sync(&mdsc->cap_reclaim_work); + cancel_delayed_work_sync(&mdsc->delayed_work); /* cancel timer */ + +- dout("stopped\n"); ++ doutc(cl, "done\n"); + } + + void ceph_mdsc_force_umount(struct ceph_mds_client *mdsc) +@@ -5501,7 +5568,7 @@ void ceph_mdsc_force_umount(struct ceph_ + struct ceph_mds_session *session; + int mds; + +- dout("force umount\n"); ++ doutc(mdsc->fsc->client, "force umount\n"); + + mutex_lock(&mdsc->mutex); + for (mds = 0; mds < mdsc->max_sessions; mds++) { +@@ -5532,7 +5599,7 @@ void ceph_mdsc_force_umount(struct ceph_ + + static void ceph_mdsc_stop(struct ceph_mds_client *mdsc) + { +- dout("stop\n"); ++ doutc(mdsc->fsc->client, "stop\n"); + /* + * Make sure the delayed work stopped before releasing + * the resources. +@@ -5553,7 +5620,7 @@ static void ceph_mdsc_stop(struct ceph_m + void ceph_mdsc_destroy(struct ceph_fs_client *fsc) + { + struct ceph_mds_client *mdsc = fsc->mdsc; +- dout("mdsc_destroy %p\n", mdsc); ++ doutc(fsc->client, "%p\n", mdsc); + + if (!mdsc) + return; +@@ -5567,12 +5634,13 @@ void ceph_mdsc_destroy(struct ceph_fs_cl + + fsc->mdsc = NULL; + kfree(mdsc); +- dout("mdsc_destroy %p done\n", mdsc); ++ doutc(fsc->client, "%p done\n", mdsc); + } + + void ceph_mdsc_handle_fsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg) + { + struct ceph_fs_client *fsc = mdsc->fsc; ++ struct ceph_client *cl = fsc->client; + const char *mds_namespace = fsc->mount_options->mds_namespace; + void *p = msg->front.iov_base; + void *end = p + msg->front.iov_len; +@@ -5584,7 +5652,7 @@ void ceph_mdsc_handle_fsmap(struct ceph_ + ceph_decode_need(&p, end, sizeof(u32), bad); + epoch = ceph_decode_32(&p); + +- dout("handle_fsmap epoch %u\n", epoch); ++ doutc(cl, "epoch %u\n", epoch); + + /* struct_v, struct_cv, map_len, epoch, legacy_client_fscid */ + ceph_decode_skip_n(&p, end, 2 + sizeof(u32) * 3, bad); +@@ -5629,7 +5697,8 @@ void ceph_mdsc_handle_fsmap(struct ceph_ + return; + + bad: +- pr_err("error decoding fsmap %d. Shutting down mount.\n", err); ++ pr_err_client(cl, "error decoding fsmap %d. Shutting down mount.\n", ++ err); + ceph_umount_begin(mdsc->fsc->sb); + ceph_msg_dump(msg); + err_out: +@@ -5644,6 +5713,7 @@ err_out: + */ + void ceph_mdsc_handle_mdsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg) + { ++ struct ceph_client *cl = mdsc->fsc->client; + u32 epoch; + u32 maplen; + void *p = msg->front.iov_base; +@@ -5658,13 +5728,12 @@ void ceph_mdsc_handle_mdsmap(struct ceph + return; + epoch = ceph_decode_32(&p); + maplen = ceph_decode_32(&p); +- dout("handle_map epoch %u len %d\n", epoch, (int)maplen); ++ doutc(cl, "epoch %u len %d\n", epoch, (int)maplen); + + /* do we need it? */ + mutex_lock(&mdsc->mutex); + if (mdsc->mdsmap && epoch <= mdsc->mdsmap->m_epoch) { +- dout("handle_map epoch %u <= our %u\n", +- epoch, mdsc->mdsmap->m_epoch); ++ doutc(cl, "epoch %u <= our %u\n", epoch, mdsc->mdsmap->m_epoch); + mutex_unlock(&mdsc->mutex); + return; + } +@@ -5698,7 +5767,8 @@ void ceph_mdsc_handle_mdsmap(struct ceph + bad_unlock: + mutex_unlock(&mdsc->mutex); + bad: +- pr_err("error decoding mdsmap %d. Shutting down mount.\n", err); ++ pr_err_client(cl, "error decoding mdsmap %d. Shutting down mount.\n", ++ err); + ceph_umount_begin(mdsc->fsc->sb); + ceph_msg_dump(msg); + return; +@@ -5729,7 +5799,8 @@ static void mds_peer_reset(struct ceph_c + struct ceph_mds_session *s = con->private; + struct ceph_mds_client *mdsc = s->s_mdsc; + +- pr_warn("mds%d closed our session\n", s->s_mds); ++ pr_warn_client(mdsc->fsc->client, "mds%d closed our session\n", ++ s->s_mds); + if (READ_ONCE(mdsc->fsc->mount_state) != CEPH_MOUNT_FENCE_IO) + send_mds_reconnect(mdsc, s); + } +@@ -5738,6 +5809,7 @@ static void mds_dispatch(struct ceph_con + { + struct ceph_mds_session *s = con->private; + struct ceph_mds_client *mdsc = s->s_mdsc; ++ struct ceph_client *cl = mdsc->fsc->client; + int type = le16_to_cpu(msg->hdr.type); + + mutex_lock(&mdsc->mutex); +@@ -5777,8 +5849,8 @@ static void mds_dispatch(struct ceph_con + break; + + default: +- pr_err("received unknown message type %d %s\n", type, +- ceph_msg_type_name(type)); ++ pr_err_client(cl, "received unknown message type %d %s\n", ++ type, ceph_msg_type_name(type)); + } + out: + ceph_msg_put(msg); +--- a/fs/ceph/mdsmap.c ++++ b/fs/ceph/mdsmap.c +@@ -11,6 +11,7 @@ + #include + #include + ++#include "mds_client.h" + #include "super.h" + + #define CEPH_MDS_IS_READY(i, ignore_laggy) \ +@@ -117,6 +118,7 @@ bad: + struct ceph_mdsmap *ceph_mdsmap_decode(struct ceph_mds_client *mdsc, void **p, + void *end, bool msgr2) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mdsmap *m; + const void *start = *p; + int i, j, n; +@@ -234,20 +236,18 @@ struct ceph_mdsmap *ceph_mdsmap_decode(s + *p = info_end; + } + +- dout("mdsmap_decode %d/%d %lld mds%d.%d %s %s%s\n", +- i+1, n, global_id, mds, inc, +- ceph_pr_addr(&addr), +- ceph_mds_state_name(state), +- laggy ? "(laggy)" : ""); ++ doutc(cl, "%d/%d %lld mds%d.%d %s %s%s\n", i+1, n, global_id, ++ mds, inc, ceph_pr_addr(&addr), ++ ceph_mds_state_name(state), laggy ? "(laggy)" : ""); + + if (mds < 0 || mds >= m->possible_max_rank) { +- pr_warn("mdsmap_decode got incorrect mds(%d)\n", mds); ++ pr_warn_client(cl, "got incorrect mds(%d)\n", mds); + continue; + } + + if (state <= 0) { +- dout("mdsmap_decode got incorrect state(%s)\n", +- ceph_mds_state_name(state)); ++ doutc(cl, "got incorrect state(%s)\n", ++ ceph_mds_state_name(state)); + continue; + } + +@@ -387,16 +387,16 @@ struct ceph_mdsmap *ceph_mdsmap_decode(s + ceph_decode_64_safe(p, end, m->m_max_xattr_size, bad_ext); + } + bad_ext: +- dout("mdsmap_decode m_enabled: %d, m_damaged: %d, m_num_laggy: %d\n", +- !!m->m_enabled, !!m->m_damaged, m->m_num_laggy); ++ doutc(cl, "m_enabled: %d, m_damaged: %d, m_num_laggy: %d\n", ++ !!m->m_enabled, !!m->m_damaged, m->m_num_laggy); + *p = end; +- dout("mdsmap_decode success epoch %u\n", m->m_epoch); ++ doutc(cl, "success epoch %u\n", m->m_epoch); + return m; + nomem: + err = -ENOMEM; + goto out_err; + corrupt: +- pr_err("corrupt mdsmap\n"); ++ pr_err_client(cl, "corrupt mdsmap\n"); + print_hex_dump(KERN_DEBUG, "mdsmap: ", + DUMP_PREFIX_OFFSET, 16, 1, + start, end - start, true); +--- a/fs/ceph/metric.c ++++ b/fs/ceph/metric.c +@@ -31,6 +31,7 @@ static bool ceph_mdsc_send_metrics(struc + 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; + s64 sum; + s32 items = 0; +@@ -51,8 +52,8 @@ static bool ceph_mdsc_send_metrics(struc + + 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; + } + +--- a/fs/ceph/quota.c ++++ b/fs/ceph/quota.c +@@ -43,6 +43,7 @@ void ceph_handle_quota(struct ceph_mds_c + { + struct super_block *sb = mdsc->fsc->sb; + struct ceph_mds_quota *h = msg->front.iov_base; ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_vino vino; + struct inode *inode; + struct ceph_inode_info *ci; +@@ -51,8 +52,8 @@ void ceph_handle_quota(struct ceph_mds_c + return; + + if (msg->front.iov_len < sizeof(*h)) { +- pr_err("%s corrupt message mds%d len %d\n", __func__, +- session->s_mds, (int)msg->front.iov_len); ++ pr_err_client(cl, "corrupt message mds%d len %d\n", ++ session->s_mds, (int)msg->front.iov_len); + ceph_msg_dump(msg); + goto out; + } +@@ -62,7 +63,7 @@ void ceph_handle_quota(struct ceph_mds_c + vino.snap = CEPH_NOSNAP; + inode = ceph_find_inode(sb, vino); + if (!inode) { +- pr_warn("Failed to find inode %llu\n", vino.ino); ++ pr_warn_client(cl, "failed to find inode %llx\n", vino.ino); + goto out; + } + ci = ceph_inode(inode); +@@ -85,6 +86,7 @@ find_quotarealm_inode(struct ceph_mds_cl + { + struct ceph_quotarealm_inode *qri = NULL; + struct rb_node **node, *parent = NULL; ++ struct ceph_client *cl = mdsc->fsc->client; + + mutex_lock(&mdsc->quotarealms_inodes_mutex); + node = &(mdsc->quotarealms_inodes.rb_node); +@@ -110,7 +112,7 @@ find_quotarealm_inode(struct ceph_mds_cl + rb_link_node(&qri->node, parent, node); + rb_insert_color(&qri->node, &mdsc->quotarealms_inodes); + } else +- pr_warn("Failed to alloc quotarealms_inode\n"); ++ pr_warn_client(cl, "Failed to alloc quotarealms_inode\n"); + } + mutex_unlock(&mdsc->quotarealms_inodes_mutex); + +@@ -129,6 +131,7 @@ static struct inode *lookup_quotarealm_i + struct super_block *sb, + struct ceph_snap_realm *realm) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_quotarealm_inode *qri; + struct inode *in; + +@@ -161,8 +164,8 @@ static struct inode *lookup_quotarealm_i + } + + if (IS_ERR(in)) { +- dout("Can't lookup inode %llx (err: %ld)\n", +- realm->ino, PTR_ERR(in)); ++ doutc(cl, "Can't lookup inode %llx (err: %ld)\n", realm->ino, ++ PTR_ERR(in)); + qri->timeout = jiffies + msecs_to_jiffies(60 * 1000); /* XXX */ + } else { + qri->timeout = 0; +@@ -212,6 +215,7 @@ static int get_quota_realm(struct ceph_m + enum quota_get_realm which_quota, + struct ceph_snap_realm **realmp, bool retry) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_inode_info *ci = NULL; + struct ceph_snap_realm *realm, *next; + struct inode *in; +@@ -227,8 +231,9 @@ restart: + if (realm) + ceph_get_snap_realm(mdsc, realm); + else +- pr_err_ratelimited("get_quota_realm: ino (%llx.%llx) " +- "null i_snap_realm\n", ceph_vinop(inode)); ++ pr_err_ratelimited_client(cl, ++ "%p %llx.%llx null i_snap_realm\n", ++ inode, ceph_vinop(inode)); + while (realm) { + bool has_inode; + +@@ -322,6 +327,7 @@ static bool check_quota_exceeded(struct + loff_t delta) + { + struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb); ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_inode_info *ci; + struct ceph_snap_realm *realm, *next; + struct inode *in; +@@ -337,8 +343,9 @@ restart: + if (realm) + ceph_get_snap_realm(mdsc, realm); + else +- pr_err_ratelimited("check_quota_exceeded: ino (%llx.%llx) " +- "null i_snap_realm\n", ceph_vinop(inode)); ++ pr_err_ratelimited_client(cl, ++ "%p %llx.%llx null i_snap_realm\n", ++ inode, ceph_vinop(inode)); + while (realm) { + bool has_inode; + +@@ -388,7 +395,7 @@ restart: + break; + default: + /* Shouldn't happen */ +- pr_warn("Invalid quota check op (%d)\n", op); ++ pr_warn_client(cl, "Invalid quota check op (%d)\n", op); + exceeded = true; /* Just break the loop */ + } + iput(in); +--- a/fs/ceph/snap.c ++++ b/fs/ceph/snap.c +@@ -138,7 +138,7 @@ static struct ceph_snap_realm *ceph_crea + __insert_snap_realm(&mdsc->snap_realms, realm); + mdsc->num_snap_realms++; + +- dout("%s %llx %p\n", __func__, realm->ino, realm); ++ doutc(mdsc->fsc->client, "%llx %p\n", realm->ino, realm); + return realm; + } + +@@ -150,6 +150,7 @@ static struct ceph_snap_realm *ceph_crea + static struct ceph_snap_realm *__lookup_snap_realm(struct ceph_mds_client *mdsc, + u64 ino) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct rb_node *n = mdsc->snap_realms.rb_node; + struct ceph_snap_realm *r; + +@@ -162,7 +163,7 @@ static struct ceph_snap_realm *__lookup_ + else if (ino > r->ino) + n = n->rb_right; + else { +- dout("%s %llx %p\n", __func__, r->ino, r); ++ doutc(cl, "%llx %p\n", r->ino, r); + return r; + } + } +@@ -188,9 +189,10 @@ static void __put_snap_realm(struct ceph + static void __destroy_snap_realm(struct ceph_mds_client *mdsc, + struct ceph_snap_realm *realm) + { ++ struct ceph_client *cl = mdsc->fsc->client; + lockdep_assert_held_write(&mdsc->snap_rwsem); + +- dout("%s %p %llx\n", __func__, realm, realm->ino); ++ doutc(cl, "%p %llx\n", realm, realm->ino); + + rb_erase(&realm->node, &mdsc->snap_realms); + mdsc->num_snap_realms--; +@@ -290,6 +292,7 @@ static int adjust_snap_realm_parent(stru + struct ceph_snap_realm *realm, + u64 parentino) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_snap_realm *parent; + + lockdep_assert_held_write(&mdsc->snap_rwsem); +@@ -303,8 +306,8 @@ static int adjust_snap_realm_parent(stru + if (IS_ERR(parent)) + return PTR_ERR(parent); + } +- dout("%s %llx %p: %llx %p -> %llx %p\n", __func__, realm->ino, +- realm, realm->parent_ino, realm->parent, parentino, parent); ++ doutc(cl, "%llx %p: %llx %p -> %llx %p\n", realm->ino, realm, ++ realm->parent_ino, realm->parent, parentino, parent); + if (realm->parent) { + list_del_init(&realm->child_item); + ceph_put_snap_realm(mdsc, realm->parent); +@@ -334,6 +337,7 @@ static int build_snap_context(struct cep + struct list_head *realm_queue, + struct list_head *dirty_realms) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_snap_realm *parent = realm->parent; + struct ceph_snap_context *snapc; + int err = 0; +@@ -361,10 +365,10 @@ static int build_snap_context(struct cep + realm->cached_context->seq == realm->seq && + (!parent || + realm->cached_context->seq >= parent->cached_context->seq)) { +- dout("%s %llx %p: %p seq %lld (%u snaps) (unchanged)\n", +- __func__, realm->ino, realm, realm->cached_context, +- realm->cached_context->seq, +- (unsigned int)realm->cached_context->num_snaps); ++ doutc(cl, "%llx %p: %p seq %lld (%u snaps) (unchanged)\n", ++ realm->ino, realm, realm->cached_context, ++ realm->cached_context->seq, ++ (unsigned int)realm->cached_context->num_snaps); + return 0; + } + +@@ -401,8 +405,8 @@ static int build_snap_context(struct cep + + sort(snapc->snaps, num, sizeof(u64), cmpu64_rev, NULL); + snapc->num_snaps = num; +- dout("%s %llx %p: %p seq %lld (%u snaps)\n", __func__, realm->ino, +- realm, snapc, snapc->seq, (unsigned int) snapc->num_snaps); ++ doutc(cl, "%llx %p: %p seq %lld (%u snaps)\n", realm->ino, realm, ++ snapc, snapc->seq, (unsigned int) snapc->num_snaps); + + ceph_put_snap_context(realm->cached_context); + realm->cached_context = snapc; +@@ -419,7 +423,7 @@ fail: + ceph_put_snap_context(realm->cached_context); + realm->cached_context = NULL; + } +- pr_err("%s %llx %p fail %d\n", __func__, realm->ino, realm, err); ++ pr_err_client(cl, "%llx %p fail %d\n", realm->ino, realm, err); + return err; + } + +@@ -430,6 +434,7 @@ static void rebuild_snap_realms(struct c + struct ceph_snap_realm *realm, + struct list_head *dirty_realms) + { ++ struct ceph_client *cl = mdsc->fsc->client; + LIST_HEAD(realm_queue); + int last = 0; + bool skip = false; +@@ -455,8 +460,8 @@ static void rebuild_snap_realms(struct c + + last = build_snap_context(mdsc, _realm, &realm_queue, + dirty_realms); +- dout("%s %llx %p, %s\n", __func__, _realm->ino, _realm, +- last > 0 ? "is deferred" : !last ? "succeeded" : "failed"); ++ doutc(cl, "%llx %p, %s\n", realm->ino, realm, ++ last > 0 ? "is deferred" : !last ? "succeeded" : "failed"); + + /* is any child in the list ? */ + list_for_each_entry(child, &_realm->children, child_item) { +@@ -526,6 +531,7 @@ static void ceph_queue_cap_snap(struct c + struct ceph_cap_snap **pcapsnap) + { + struct inode *inode = &ci->netfs.inode; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_snap_context *old_snapc, *new_snapc; + struct ceph_cap_snap *capsnap = *pcapsnap; + struct ceph_buffer *old_blob = NULL; +@@ -551,14 +557,14 @@ static void ceph_queue_cap_snap(struct c + as no new writes are allowed to start when pending, so any + writes in progress now were started before the previous + cap_snap. lucky us. */ +- dout("%s %p %llx.%llx already pending\n", +- __func__, inode, ceph_vinop(inode)); ++ doutc(cl, "%p %llx.%llx already pending\n", inode, ++ ceph_vinop(inode)); + goto update_snapc; + } + if (ci->i_wrbuffer_ref_head == 0 && + !(dirty & (CEPH_CAP_ANY_EXCL|CEPH_CAP_FILE_WR))) { +- dout("%s %p %llx.%llx nothing dirty|writing\n", +- __func__, inode, ceph_vinop(inode)); ++ doutc(cl, "%p %llx.%llx nothing dirty|writing\n", inode, ++ ceph_vinop(inode)); + goto update_snapc; + } + +@@ -578,15 +584,15 @@ static void ceph_queue_cap_snap(struct c + } else { + if (!(used & CEPH_CAP_FILE_WR) && + ci->i_wrbuffer_ref_head == 0) { +- dout("%s %p %llx.%llx no new_snap|dirty_page|writing\n", +- __func__, inode, ceph_vinop(inode)); ++ doutc(cl, "%p %llx.%llx no new_snap|dirty_page|writing\n", ++ inode, ceph_vinop(inode)); + goto update_snapc; + } + } + +- dout("%s %p %llx.%llx cap_snap %p queuing under %p %s %s\n", +- __func__, inode, ceph_vinop(inode), capsnap, old_snapc, +- ceph_cap_string(dirty), capsnap->need_flush ? "" : "no_flush"); ++ doutc(cl, "%p %llx.%llx cap_snap %p queuing under %p %s %s\n", ++ inode, ceph_vinop(inode), capsnap, old_snapc, ++ ceph_cap_string(dirty), capsnap->need_flush ? "" : "no_flush"); + ihold(inode); + + capsnap->follows = old_snapc->seq; +@@ -618,9 +624,9 @@ static void ceph_queue_cap_snap(struct c + list_add_tail(&capsnap->ci_item, &ci->i_cap_snaps); + + if (used & CEPH_CAP_FILE_WR) { +- dout("%s %p %llx.%llx cap_snap %p snapc %p seq %llu used WR," +- " now pending\n", __func__, inode, ceph_vinop(inode), +- capsnap, old_snapc, old_snapc->seq); ++ 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; + } else { + /* note mtime, size NOW. */ +@@ -637,7 +643,7 @@ update_snapc: + ci->i_head_snapc = NULL; + } else { + ci->i_head_snapc = ceph_get_snap_context(new_snapc); +- dout(" new snapc is %p\n", new_snapc); ++ doutc(cl, " new snapc is %p\n", new_snapc); + } + spin_unlock(&ci->i_ceph_lock); + +@@ -658,6 +664,7 @@ int __ceph_finish_cap_snap(struct ceph_i + { + struct inode *inode = &ci->netfs.inode; + struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(inode->i_sb); ++ struct ceph_client *cl = mdsc->fsc->client; + + BUG_ON(capsnap->writing); + capsnap->size = i_size_read(inode); +@@ -670,11 +677,12 @@ int __ceph_finish_cap_snap(struct ceph_i + capsnap->truncate_size = ci->i_truncate_size; + capsnap->truncate_seq = ci->i_truncate_seq; + if (capsnap->dirty_pages) { +- dout("%s %p %llx.%llx cap_snap %p snapc %p %llu %s s=%llu " +- "still has %d dirty pages\n", __func__, inode, +- ceph_vinop(inode), capsnap, capsnap->context, +- capsnap->context->seq, ceph_cap_string(capsnap->dirty), +- capsnap->size, capsnap->dirty_pages); ++ doutc(cl, "%p %llx.%llx cap_snap %p snapc %p %llu %s " ++ "s=%llu still has %d dirty pages\n", inode, ++ ceph_vinop(inode), capsnap, capsnap->context, ++ capsnap->context->seq, ++ ceph_cap_string(capsnap->dirty), ++ capsnap->size, capsnap->dirty_pages); + return 0; + } + +@@ -683,20 +691,20 @@ int __ceph_finish_cap_snap(struct ceph_i + * And trigger to flush the buffer immediately. + */ + if (ci->i_wrbuffer_ref) { +- dout("%s %p %llx.%llx cap_snap %p snapc %p %llu %s s=%llu " +- "used WRBUFFER, delaying\n", __func__, inode, +- ceph_vinop(inode), capsnap, capsnap->context, +- capsnap->context->seq, ceph_cap_string(capsnap->dirty), +- capsnap->size); ++ doutc(cl, "%p %llx.%llx cap_snap %p snapc %p %llu %s " ++ "s=%llu used WRBUFFER, delaying\n", inode, ++ ceph_vinop(inode), capsnap, capsnap->context, ++ capsnap->context->seq, ceph_cap_string(capsnap->dirty), ++ capsnap->size); + ceph_queue_writeback(inode); + return 0; + } + + ci->i_ceph_flags |= CEPH_I_FLUSH_SNAPS; +- dout("%s %p %llx.%llx cap_snap %p snapc %p %llu %s s=%llu\n", +- __func__, inode, ceph_vinop(inode), capsnap, capsnap->context, +- capsnap->context->seq, ceph_cap_string(capsnap->dirty), +- capsnap->size); ++ doutc(cl, "%p %llx.%llx cap_snap %p snapc %p %llu %s s=%llu\n", ++ inode, ceph_vinop(inode), capsnap, capsnap->context, ++ capsnap->context->seq, ceph_cap_string(capsnap->dirty), ++ capsnap->size); + + spin_lock(&mdsc->snap_flush_lock); + if (list_empty(&ci->i_snap_flush_item)) { +@@ -714,11 +722,12 @@ int __ceph_finish_cap_snap(struct ceph_i + static void queue_realm_cap_snaps(struct ceph_mds_client *mdsc, + struct ceph_snap_realm *realm) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_inode_info *ci; + struct inode *lastinode = NULL; + struct ceph_cap_snap *capsnap = NULL; + +- dout("%s %p %llx inode\n", __func__, realm, realm->ino); ++ doutc(cl, "%p %llx inode\n", realm, realm->ino); + + spin_lock(&realm->inodes_with_caps_lock); + list_for_each_entry(ci, &realm->inodes_with_caps, i_snap_realm_item) { +@@ -737,8 +746,9 @@ static void queue_realm_cap_snaps(struct + if (!capsnap) { + capsnap = kmem_cache_zalloc(ceph_cap_snap_cachep, GFP_NOFS); + if (!capsnap) { +- pr_err("ENOMEM allocating ceph_cap_snap on %p\n", +- inode); ++ pr_err_client(cl, ++ "ENOMEM allocating ceph_cap_snap on %p\n", ++ inode); + return; + } + } +@@ -756,7 +766,7 @@ static void queue_realm_cap_snaps(struct + + if (capsnap) + kmem_cache_free(ceph_cap_snap_cachep, capsnap); +- dout("%s %p %llx done\n", __func__, realm, realm->ino); ++ doutc(cl, "%p %llx done\n", realm, realm->ino); + } + + /* +@@ -770,6 +780,7 @@ int ceph_update_snap_trace(struct ceph_m + void *p, void *e, bool deletion, + struct ceph_snap_realm **realm_ret) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_mds_snap_realm *ri; /* encoded */ + __le64 *snaps; /* encoded */ + __le64 *prior_parent_snaps; /* encoded */ +@@ -784,7 +795,7 @@ int ceph_update_snap_trace(struct ceph_m + + lockdep_assert_held_write(&mdsc->snap_rwsem); + +- dout("%s deletion=%d\n", __func__, deletion); ++ doutc(cl, "deletion=%d\n", deletion); + more: + realm = NULL; + rebuild_snapcs = 0; +@@ -814,8 +825,8 @@ more: + rebuild_snapcs += err; + + if (le64_to_cpu(ri->seq) > realm->seq) { +- dout("%s updating %llx %p %lld -> %lld\n", __func__, +- realm->ino, realm, realm->seq, le64_to_cpu(ri->seq)); ++ doutc(cl, "updating %llx %p %lld -> %lld\n", realm->ino, ++ realm, realm->seq, le64_to_cpu(ri->seq)); + /* update realm parameters, snap lists */ + realm->seq = le64_to_cpu(ri->seq); + realm->created = le64_to_cpu(ri->created); +@@ -838,16 +849,16 @@ more: + + rebuild_snapcs = 1; + } else if (!realm->cached_context) { +- dout("%s %llx %p seq %lld new\n", __func__, +- realm->ino, realm, realm->seq); ++ doutc(cl, "%llx %p seq %lld new\n", realm->ino, realm, ++ realm->seq); + rebuild_snapcs = 1; + } else { +- dout("%s %llx %p seq %lld unchanged\n", __func__, +- realm->ino, realm, realm->seq); ++ doutc(cl, "%llx %p seq %lld unchanged\n", realm->ino, realm, ++ realm->seq); + } + +- dout("done with %llx %p, rebuild_snapcs=%d, %p %p\n", realm->ino, +- realm, rebuild_snapcs, p, e); ++ doutc(cl, "done with %llx %p, rebuild_snapcs=%d, %p %p\n", realm->ino, ++ realm, rebuild_snapcs, p, e); + + /* + * this will always track the uppest parent realm from which +@@ -895,7 +906,7 @@ fail: + ceph_put_snap_realm(mdsc, realm); + if (first_realm) + ceph_put_snap_realm(mdsc, first_realm); +- pr_err("%s error %d\n", __func__, err); ++ pr_err_client(cl, "error %d\n", err); + + /* + * When receiving a corrupted snap trace we don't know what +@@ -909,11 +920,12 @@ fail: + WRITE_ONCE(mdsc->fsc->mount_state, CEPH_MOUNT_FENCE_IO); + ret = ceph_monc_blocklist_add(&client->monc, &client->msgr.inst.addr); + if (ret) +- pr_err("%s failed to blocklist %s: %d\n", __func__, +- ceph_pr_addr(&client->msgr.inst.addr), ret); ++ pr_err_client(cl, "failed to blocklist %s: %d\n", ++ ceph_pr_addr(&client->msgr.inst.addr), ret); + +- WARN(1, "%s: %s%sdo remount to continue%s", +- __func__, ret ? "" : ceph_pr_addr(&client->msgr.inst.addr), ++ WARN(1, "[client.%lld] %s %s%sdo remount to continue%s", ++ client->monc.auth->global_id, __func__, ++ ret ? "" : ceph_pr_addr(&client->msgr.inst.addr), + ret ? "" : " was blocklisted, ", + err == -EIO ? " after corrupted snaptrace is fixed" : ""); + +@@ -929,11 +941,12 @@ fail: + */ + static void flush_snaps(struct ceph_mds_client *mdsc) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_inode_info *ci; + struct inode *inode; + struct ceph_mds_session *session = NULL; + +- dout("%s\n", __func__); ++ doutc(cl, "begin\n"); + spin_lock(&mdsc->snap_flush_lock); + while (!list_empty(&mdsc->snap_flush_list)) { + ci = list_first_entry(&mdsc->snap_flush_list, +@@ -948,7 +961,7 @@ static void flush_snaps(struct ceph_mds_ + spin_unlock(&mdsc->snap_flush_lock); + + ceph_put_mds_session(session); +- dout("%s done\n", __func__); ++ doutc(cl, "done\n"); + } + + /** +@@ -1004,6 +1017,7 @@ void ceph_handle_snap(struct ceph_mds_cl + struct ceph_mds_session *session, + struct ceph_msg *msg) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct super_block *sb = mdsc->fsc->sb; + int mds = session->s_mds; + u64 split; +@@ -1034,8 +1048,8 @@ void ceph_handle_snap(struct ceph_mds_cl + trace_len = le32_to_cpu(h->trace_len); + p += sizeof(*h); + +- dout("%s from mds%d op %s split %llx tracelen %d\n", __func__, +- mds, ceph_snap_op_name(op), split, trace_len); ++ doutc(cl, "from mds%d op %s split %llx tracelen %d\n", mds, ++ ceph_snap_op_name(op), split, trace_len); + + down_write(&mdsc->snap_rwsem); + locked_rwsem = 1; +@@ -1066,7 +1080,7 @@ void ceph_handle_snap(struct ceph_mds_cl + goto out; + } + +- dout("splitting snap_realm %llx %p\n", realm->ino, realm); ++ doutc(cl, "splitting snap_realm %llx %p\n", realm->ino, realm); + for (i = 0; i < num_split_inos; i++) { + struct ceph_vino vino = { + .ino = le64_to_cpu(split_inos[i]), +@@ -1091,13 +1105,13 @@ void ceph_handle_snap(struct ceph_mds_cl + */ + if (ci->i_snap_realm->created > + le64_to_cpu(ri->created)) { +- dout(" leaving %p %llx.%llx in newer realm %llx %p\n", +- inode, ceph_vinop(inode), ci->i_snap_realm->ino, +- ci->i_snap_realm); ++ doutc(cl, " leaving %p %llx.%llx in newer realm %llx %p\n", ++ inode, ceph_vinop(inode), ci->i_snap_realm->ino, ++ ci->i_snap_realm); + goto skip_inode; + } +- dout(" will move %p %llx.%llx to split realm %llx %p\n", +- inode, ceph_vinop(inode), realm->ino, realm); ++ doutc(cl, " will move %p %llx.%llx to split realm %llx %p\n", ++ inode, ceph_vinop(inode), realm->ino, realm); + + ceph_get_snap_realm(mdsc, realm); + ceph_change_snap_realm(inode, realm); +@@ -1158,7 +1172,7 @@ skip_inode: + return; + + bad: +- pr_err("%s corrupt snap message from mds%d\n", __func__, mds); ++ pr_err_client(cl, "corrupt snap message from mds%d\n", mds); + ceph_msg_dump(msg); + out: + if (locked_rwsem) +@@ -1174,6 +1188,7 @@ out: + struct ceph_snapid_map* ceph_get_snapid_map(struct ceph_mds_client *mdsc, + u64 snap) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_snapid_map *sm, *exist; + struct rb_node **p, *parent; + int ret; +@@ -1196,8 +1211,8 @@ struct ceph_snapid_map* ceph_get_snapid_ + } + spin_unlock(&mdsc->snapid_map_lock); + if (exist) { +- dout("%s found snapid map %llx -> %x\n", __func__, +- exist->snap, exist->dev); ++ doutc(cl, "found snapid map %llx -> %x\n", exist->snap, ++ exist->dev); + return exist; + } + +@@ -1241,13 +1256,12 @@ struct ceph_snapid_map* ceph_get_snapid_ + if (exist) { + free_anon_bdev(sm->dev); + kfree(sm); +- dout("%s found snapid map %llx -> %x\n", __func__, +- exist->snap, exist->dev); ++ doutc(cl, "found snapid map %llx -> %x\n", exist->snap, ++ exist->dev); + return exist; + } + +- dout("%s create snapid map %llx -> %x\n", __func__, +- sm->snap, sm->dev); ++ doutc(cl, "create snapid map %llx -> %x\n", sm->snap, sm->dev); + return sm; + } + +@@ -1272,6 +1286,7 @@ void ceph_put_snapid_map(struct ceph_mds + + void ceph_trim_snapid_map(struct ceph_mds_client *mdsc) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_snapid_map *sm; + unsigned long now; + LIST_HEAD(to_free); +@@ -1293,7 +1308,7 @@ void ceph_trim_snapid_map(struct ceph_md + while (!list_empty(&to_free)) { + sm = list_first_entry(&to_free, struct ceph_snapid_map, lru); + list_del(&sm->lru); +- dout("trim snapid map %llx -> %x\n", sm->snap, sm->dev); ++ doutc(cl, "trim snapid map %llx -> %x\n", sm->snap, sm->dev); + free_anon_bdev(sm->dev); + kfree(sm); + } +@@ -1301,6 +1316,7 @@ void ceph_trim_snapid_map(struct ceph_md + + void ceph_cleanup_snapid_map(struct ceph_mds_client *mdsc) + { ++ struct ceph_client *cl = mdsc->fsc->client; + struct ceph_snapid_map *sm; + struct rb_node *p; + LIST_HEAD(to_free); +@@ -1319,8 +1335,8 @@ void ceph_cleanup_snapid_map(struct ceph + list_del(&sm->lru); + free_anon_bdev(sm->dev); + if (WARN_ON_ONCE(atomic_read(&sm->ref))) { +- pr_err("snapid map %llx -> %x still in use\n", +- sm->snap, sm->dev); ++ pr_err_client(cl, "snapid map %llx -> %x still in use\n", ++ sm->snap, sm->dev); + } + kfree(sm); + } +--- a/fs/ceph/super.c ++++ b/fs/ceph/super.c +@@ -46,9 +46,10 @@ static void ceph_put_super(struct super_ + { + struct ceph_fs_client *fsc = ceph_sb_to_fs_client(s); + +- dout("put_super\n"); ++ doutc(fsc->client, "begin\n"); + ceph_fscrypt_free_dummy_policy(fsc); + ceph_mdsc_close_sessions(fsc->mdsc); ++ doutc(fsc->client, "done\n"); + } + + static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf) +@@ -59,13 +60,13 @@ static int ceph_statfs(struct dentry *de + int i, err; + u64 data_pool; + ++ doutc(fsc->client, "begin\n"); + if (fsc->mdsc->mdsmap->m_num_data_pg_pools == 1) { + data_pool = fsc->mdsc->mdsmap->m_data_pg_pools[0]; + } else { + data_pool = CEPH_NOPOOL; + } + +- dout("statfs\n"); + err = ceph_monc_do_statfs(monc, data_pool, &st); + if (err < 0) + return err; +@@ -113,24 +114,26 @@ static int ceph_statfs(struct dentry *de + /* fold the fs_cluster_id into the upper bits */ + buf->f_fsid.val[1] = monc->fs_cluster_id; + ++ doutc(fsc->client, "done\n"); + return 0; + } + + static int ceph_sync_fs(struct super_block *sb, int wait) + { + struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb); ++ struct ceph_client *cl = fsc->client; + + if (!wait) { +- dout("sync_fs (non-blocking)\n"); ++ doutc(cl, "(non-blocking)\n"); + ceph_flush_dirty_caps(fsc->mdsc); +- dout("sync_fs (non-blocking) done\n"); ++ doutc(cl, "(non-blocking) done\n"); + return 0; + } + +- dout("sync_fs (blocking)\n"); ++ doutc(cl, "(blocking)\n"); + ceph_osdc_sync(&fsc->client->osdc); + ceph_mdsc_sync(fsc->mdsc); +- dout("sync_fs (blocking) done\n"); ++ doutc(cl, "(blocking) done\n"); + return 0; + } + +@@ -349,7 +352,7 @@ static int ceph_parse_source(struct fs_p + char *dev_name = param->string, *dev_name_end; + int ret; + +- dout("%s '%s'\n", __func__, dev_name); ++ dout("'%s'\n", dev_name); + if (!dev_name || !*dev_name) + return invalfc(fc, "Empty source"); + +@@ -421,7 +424,7 @@ static int ceph_parse_mount_param(struct + return ret; + + token = fs_parse(fc, ceph_mount_parameters, param, &result); +- dout("%s fs_parse '%s' token %d\n", __func__, param->key, token); ++ dout("%s: fs_parse '%s' token %d\n",__func__, param->key, token); + if (token < 0) + return token; + +@@ -891,7 +894,7 @@ static void flush_fs_workqueues(struct c + + static void destroy_fs_client(struct ceph_fs_client *fsc) + { +- dout("destroy_fs_client %p\n", fsc); ++ doutc(fsc->client, "%p\n", fsc); + + spin_lock(&ceph_fsc_lock); + list_del(&fsc->metric_wakeup); +@@ -906,7 +909,7 @@ static void destroy_fs_client(struct cep + ceph_destroy_client(fsc->client); + + kfree(fsc); +- dout("destroy_fs_client %p done\n", fsc); ++ dout("%s: %p done\n", __func__, fsc); + } + + /* +@@ -1028,7 +1031,7 @@ void ceph_umount_begin(struct super_bloc + { + struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb); + +- dout("ceph_umount_begin - starting forced umount\n"); ++ doutc(fsc->client, "starting forced umount\n"); + if (!fsc) + return; + fsc->mount_state = CEPH_MOUNT_SHUTDOWN; +@@ -1056,13 +1059,14 @@ static struct dentry *open_root_dentry(s + const char *path, + unsigned long started) + { ++ struct ceph_client *cl = fsc->client; + struct ceph_mds_client *mdsc = fsc->mdsc; + struct ceph_mds_request *req = NULL; + int err; + struct dentry *root; + + /* open dir */ +- dout("open_root_inode opening '%s'\n", path); ++ doutc(cl, "opening '%s'\n", path); + req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, USE_ANY_MDS); + if (IS_ERR(req)) + return ERR_CAST(req); +@@ -1082,13 +1086,13 @@ static struct dentry *open_root_dentry(s + if (err == 0) { + struct inode *inode = req->r_target_inode; + req->r_target_inode = NULL; +- dout("open_root_inode success\n"); ++ doutc(cl, "success\n"); + root = d_make_root(inode); + if (!root) { + root = ERR_PTR(-ENOMEM); + goto out; + } +- dout("open_root_inode success, root dentry is %p\n", root); ++ doutc(cl, "success, root dentry is %p\n", root); + } else { + root = ERR_PTR(err); + } +@@ -1147,11 +1151,12 @@ static int ceph_apply_test_dummy_encrypt + static struct dentry *ceph_real_mount(struct ceph_fs_client *fsc, + struct fs_context *fc) + { ++ struct ceph_client *cl = fsc->client; + int err; + unsigned long started = jiffies; /* note the start time */ + struct dentry *root; + +- dout("mount start %p\n", fsc); ++ doutc(cl, "mount start %p\n", fsc); + mutex_lock(&fsc->client->mount_mutex); + + if (!fsc->sb->s_root) { +@@ -1174,7 +1179,7 @@ static struct dentry *ceph_real_mount(st + if (err) + goto out; + +- dout("mount opening path '%s'\n", path); ++ doutc(cl, "mount opening path '%s'\n", path); + + ceph_fs_debugfs_init(fsc); + +@@ -1189,7 +1194,7 @@ static struct dentry *ceph_real_mount(st + } + + fsc->mount_state = CEPH_MOUNT_MOUNTED; +- dout("mount success\n"); ++ doutc(cl, "mount success\n"); + mutex_unlock(&fsc->client->mount_mutex); + return root; + +@@ -1202,9 +1207,10 @@ out: + static int ceph_set_super(struct super_block *s, struct fs_context *fc) + { + struct ceph_fs_client *fsc = s->s_fs_info; ++ struct ceph_client *cl = fsc->client; + int ret; + +- dout("set_super %p\n", s); ++ doutc(cl, "%p\n", s); + + s->s_maxbytes = MAX_LFS_FILESIZE; + +@@ -1239,30 +1245,31 @@ static int ceph_compare_super(struct sup + struct ceph_mount_options *fsopt = new->mount_options; + struct ceph_options *opt = new->client->options; + struct ceph_fs_client *fsc = ceph_sb_to_fs_client(sb); ++ struct ceph_client *cl = fsc->client; + +- dout("ceph_compare_super %p\n", sb); ++ doutc(cl, "%p\n", sb); + + if (compare_mount_options(fsopt, opt, fsc)) { +- dout("monitor(s)/mount options don't match\n"); ++ doutc(cl, "monitor(s)/mount options don't match\n"); + return 0; + } + if ((opt->flags & CEPH_OPT_FSID) && + ceph_fsid_compare(&opt->fsid, &fsc->client->fsid)) { +- dout("fsid doesn't match\n"); ++ doutc(cl, "fsid doesn't match\n"); + return 0; + } + if (fc->sb_flags != (sb->s_flags & ~SB_BORN)) { +- dout("flags differ\n"); ++ doutc(cl, "flags differ\n"); + return 0; + } + + if (fsc->blocklisted && !ceph_test_mount_opt(fsc, CLEANRECOVER)) { +- dout("client is blocklisted (and CLEANRECOVER is not set)\n"); ++ doutc(cl, "client is blocklisted (and CLEANRECOVER is not set)\n"); + return 0; + } + + if (fsc->mount_state == CEPH_MOUNT_SHUTDOWN) { +- dout("client has been forcibly unmounted\n"); ++ doutc(cl, "client has been forcibly unmounted\n"); + return 0; + } + +@@ -1350,8 +1357,9 @@ static int ceph_get_tree(struct fs_conte + err = PTR_ERR(res); + goto out_splat; + } +- dout("root %p inode %p ino %llx.%llx\n", res, +- d_inode(res), ceph_vinop(d_inode(res))); ++ ++ doutc(fsc->client, "root %p inode %p ino %llx.%llx\n", res, ++ d_inode(res), ceph_vinop(d_inode(res))); + fc->root = fsc->sb->s_root; + return 0; + +@@ -1409,7 +1417,8 @@ static int ceph_reconfigure_fc(struct fs + kfree(fsc->mount_options->mon_addr); + fsc->mount_options->mon_addr = fsopt->mon_addr; + fsopt->mon_addr = NULL; +- pr_notice("ceph: monitor addresses recorded, but not used for reconnection"); ++ pr_notice_client(fsc->client, ++ "monitor addresses recorded, but not used for reconnection"); + } + + sync_filesystem(sb); +@@ -1529,10 +1538,11 @@ void ceph_dec_osd_stopping_blocker(struc + static void ceph_kill_sb(struct super_block *s) + { + struct ceph_fs_client *fsc = ceph_sb_to_fs_client(s); ++ struct ceph_client *cl = fsc->client; + struct ceph_mds_client *mdsc = fsc->mdsc; + bool wait; + +- dout("kill_sb %p\n", s); ++ doutc(cl, "%p\n", s); + + ceph_mdsc_pre_umount(mdsc); + flush_fs_workqueues(fsc); +@@ -1563,9 +1573,9 @@ static void ceph_kill_sb(struct super_bl + &mdsc->stopping_waiter, + fsc->client->options->mount_timeout); + if (!timeleft) /* timed out */ +- pr_warn("umount timed out, %ld\n", timeleft); ++ pr_warn_client(cl, "umount timed out, %ld\n", timeleft); + else if (timeleft < 0) /* killed */ +- pr_warn("umount was killed, %ld\n", timeleft); ++ pr_warn_client(cl, "umount was killed, %ld\n", timeleft); + } + + mdsc->stopping = CEPH_MDSC_STOPPING_FLUSHED; +--- a/fs/ceph/super.h ++++ b/fs/ceph/super.h +@@ -506,6 +506,12 @@ ceph_sb_to_mdsc(const struct super_block + 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) + { +--- a/fs/ceph/xattr.c ++++ b/fs/ceph/xattr.c +@@ -58,6 +58,7 @@ static ssize_t ceph_vxattrcb_layout(stru + size_t size) + { + struct ceph_fs_client *fsc = ceph_sb_to_fs_client(ci->netfs.inode.i_sb); ++ 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; +@@ -69,7 +70,7 @@ static ssize_t ceph_vxattrcb_layout(stru + + pool_ns = ceph_try_get_string(ci->i_layout.pool_ns); + +- dout("ceph_vxattrcb_layout %p\n", &ci->netfs.inode); ++ doutc(cl, "%p\n", &ci->netfs.inode); + down_read(&osdc->lock); + pool_name = ceph_pg_pool_name_by_id(osdc->osdmap, pool); + if (pool_name) { +@@ -570,6 +571,8 @@ static int __set_xattr(struct ceph_inode + int flags, int update_xattr, + struct ceph_inode_xattr **newxattr) + { ++ struct inode *inode = &ci->netfs.inode; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct rb_node **p; + struct rb_node *parent = NULL; + struct ceph_inode_xattr *xattr = NULL; +@@ -626,7 +629,7 @@ static int __set_xattr(struct ceph_inode + xattr->should_free_name = update_xattr; + + ci->i_xattrs.count++; +- dout("%s count=%d\n", __func__, ci->i_xattrs.count); ++ doutc(cl, "count=%d\n", ci->i_xattrs.count); + } else { + kfree(*newxattr); + *newxattr = NULL; +@@ -654,13 +657,13 @@ static int __set_xattr(struct ceph_inode + if (new) { + rb_link_node(&xattr->node, parent, p); + rb_insert_color(&xattr->node, &ci->i_xattrs.index); +- dout("%s p=%p\n", __func__, p); ++ doutc(cl, "p=%p\n", p); + } + +- dout("%s added %llx.%llx xattr %p %.*s=%.*s%s\n", __func__, +- ceph_vinop(&ci->netfs.inode), xattr, name_len, name, +- min(val_len, MAX_XATTR_VAL_PRINT_LEN), val, +- val_len > MAX_XATTR_VAL_PRINT_LEN ? "..." : ""); ++ doutc(cl, "added %p %llx.%llx xattr %p %.*s=%.*s%s\n", inode, ++ ceph_vinop(inode), xattr, name_len, name, min(val_len, ++ MAX_XATTR_VAL_PRINT_LEN), val, ++ val_len > MAX_XATTR_VAL_PRINT_LEN ? "..." : ""); + + return 0; + } +@@ -668,6 +671,7 @@ static int __set_xattr(struct ceph_inode + static struct ceph_inode_xattr *__get_xattr(struct ceph_inode_info *ci, + const char *name) + { ++ struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode); + struct rb_node **p; + struct rb_node *parent = NULL; + struct ceph_inode_xattr *xattr = NULL; +@@ -688,13 +692,13 @@ static struct ceph_inode_xattr *__get_xa + else { + int len = min(xattr->val_len, MAX_XATTR_VAL_PRINT_LEN); + +- dout("%s %s: found %.*s%s\n", __func__, name, len, +- xattr->val, xattr->val_len > len ? "..." : ""); ++ doutc(cl, "%s found %.*s%s\n", name, len, xattr->val, ++ xattr->val_len > len ? "..." : ""); + return xattr; + } + } + +- dout("%s %s: not found\n", __func__, name); ++ doutc(cl, "%s not found\n", name); + + return NULL; + } +@@ -735,19 +739,20 @@ static int __remove_xattr(struct ceph_in + static char *__copy_xattr_names(struct ceph_inode_info *ci, + char *dest) + { ++ struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode); + struct rb_node *p; + struct ceph_inode_xattr *xattr = NULL; + + p = rb_first(&ci->i_xattrs.index); +- dout("__copy_xattr_names count=%d\n", ci->i_xattrs.count); ++ doutc(cl, "count=%d\n", ci->i_xattrs.count); + + while (p) { + xattr = rb_entry(p, struct ceph_inode_xattr, node); + memcpy(dest, xattr->name, xattr->name_len); + dest[xattr->name_len] = '\0'; + +- dout("dest=%s %p (%s) (%d/%d)\n", dest, xattr, xattr->name, +- xattr->name_len, ci->i_xattrs.names_size); ++ doutc(cl, "dest=%s %p (%s) (%d/%d)\n", dest, xattr, xattr->name, ++ xattr->name_len, ci->i_xattrs.names_size); + + dest += xattr->name_len + 1; + p = rb_next(p); +@@ -758,19 +763,19 @@ static char *__copy_xattr_names(struct c + + void __ceph_destroy_xattrs(struct ceph_inode_info *ci) + { ++ struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode); + struct rb_node *p, *tmp; + struct ceph_inode_xattr *xattr = NULL; + + p = rb_first(&ci->i_xattrs.index); + +- dout("__ceph_destroy_xattrs p=%p\n", p); ++ doutc(cl, "p=%p\n", p); + + while (p) { + xattr = rb_entry(p, struct ceph_inode_xattr, node); + tmp = p; + p = rb_next(tmp); +- dout("__ceph_destroy_xattrs next p=%p (%.*s)\n", p, +- xattr->name_len, xattr->name); ++ doutc(cl, "next p=%p (%.*s)\n", p, xattr->name_len, xattr->name); + rb_erase(tmp, &ci->i_xattrs.index); + + __free_xattr(xattr); +@@ -787,6 +792,7 @@ static int __build_xattrs(struct inode * + __releases(ci->i_ceph_lock) + __acquires(ci->i_ceph_lock) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + u32 namelen; + u32 numattr = 0; + void *p, *end; +@@ -798,8 +804,8 @@ static int __build_xattrs(struct inode * + int err = 0; + int i; + +- dout("__build_xattrs() len=%d\n", +- ci->i_xattrs.blob ? (int)ci->i_xattrs.blob->vec.iov_len : 0); ++ doutc(cl, "len=%d\n", ++ ci->i_xattrs.blob ? (int)ci->i_xattrs.blob->vec.iov_len : 0); + + if (ci->i_xattrs.index_version >= ci->i_xattrs.version) + return 0; /* already built */ +@@ -874,6 +880,8 @@ bad: + static int __get_required_blob_size(struct ceph_inode_info *ci, int name_size, + int val_size) + { ++ struct ceph_client *cl = ceph_inode_to_client(&ci->netfs.inode); ++ + /* + * 4 bytes for the length, and additional 4 bytes per each xattr name, + * 4 bytes per each value +@@ -881,9 +889,8 @@ static int __get_required_blob_size(stru + int size = 4 + ci->i_xattrs.count*(4 + 4) + + ci->i_xattrs.names_size + + ci->i_xattrs.vals_size; +- dout("__get_required_blob_size c=%d names.size=%d vals.size=%d\n", +- ci->i_xattrs.count, ci->i_xattrs.names_size, +- ci->i_xattrs.vals_size); ++ doutc(cl, "c=%d names.size=%d vals.size=%d\n", ci->i_xattrs.count, ++ ci->i_xattrs.names_size, ci->i_xattrs.vals_size); + + if (name_size) + size += 4 + 4 + name_size + val_size; +@@ -899,12 +906,14 @@ static int __get_required_blob_size(stru + */ + struct ceph_buffer *__ceph_build_xattrs_blob(struct ceph_inode_info *ci) + { ++ struct inode *inode = &ci->netfs.inode; ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct rb_node *p; + struct ceph_inode_xattr *xattr = NULL; + struct ceph_buffer *old_blob = NULL; + void *dest; + +- dout("__build_xattrs_blob %p\n", &ci->netfs.inode); ++ doutc(cl, "%p %llx.%llx\n", inode, ceph_vinop(inode)); + if (ci->i_xattrs.dirty) { + int need = __get_required_blob_size(ci, 0, 0); + +@@ -962,6 +971,7 @@ static inline int __get_request_mask(str + ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value, + size_t size) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_inode_xattr *xattr; + struct ceph_vxattr *vxattr; +@@ -1000,8 +1010,9 @@ handle_non_vxattrs: + req_mask = __get_request_mask(inode); + + spin_lock(&ci->i_ceph_lock); +- dout("getxattr %p name '%s' ver=%lld index_ver=%lld\n", inode, name, +- ci->i_xattrs.version, ci->i_xattrs.index_version); ++ doutc(cl, "%p %llx.%llx name '%s' ver=%lld index_ver=%lld\n", inode, ++ ceph_vinop(inode), name, ci->i_xattrs.version, ++ ci->i_xattrs.index_version); + + if (ci->i_xattrs.version == 0 || + !((req_mask & CEPH_CAP_XATTR_SHARED) || +@@ -1010,8 +1021,9 @@ handle_non_vxattrs: + + /* security module gets xattr while filling trace */ + if (current->journal_info) { +- pr_warn_ratelimited("sync getxattr %p " +- "during filling trace\n", inode); ++ pr_warn_ratelimited_client(cl, ++ "sync %p %llx.%llx during filling trace\n", ++ inode, ceph_vinop(inode)); + return -EBUSY; + } + +@@ -1053,14 +1065,16 @@ out: + ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size) + { + struct inode *inode = d_inode(dentry); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + bool len_only = (size == 0); + u32 namelen; + int err; + + spin_lock(&ci->i_ceph_lock); +- dout("listxattr %p ver=%lld index_ver=%lld\n", inode, +- ci->i_xattrs.version, ci->i_xattrs.index_version); ++ doutc(cl, "%p %llx.%llx ver=%lld index_ver=%lld\n", inode, ++ ceph_vinop(inode), ci->i_xattrs.version, ++ ci->i_xattrs.index_version); + + if (ci->i_xattrs.version == 0 || + !__ceph_caps_issued_mask_metric(ci, CEPH_CAP_XATTR_SHARED, 1)) { +@@ -1095,6 +1109,7 @@ static int ceph_sync_setxattr(struct ino + const char *value, size_t size, int flags) + { + struct ceph_fs_client *fsc = ceph_sb_to_fs_client(inode->i_sb); ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_mds_request *req; + struct ceph_mds_client *mdsc = fsc->mdsc; +@@ -1119,7 +1134,7 @@ static int ceph_sync_setxattr(struct ino + flags |= CEPH_XATTR_REMOVE; + } + +- dout("setxattr value size: %zu\n", size); ++ doutc(cl, "name %s value size %zu\n", name, size); + + /* do request */ + req = ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS); +@@ -1148,10 +1163,10 @@ static int ceph_sync_setxattr(struct ino + req->r_num_caps = 1; + req->r_inode_drop = CEPH_CAP_XATTR_SHARED; + +- dout("xattr.ver (before): %lld\n", ci->i_xattrs.version); ++ doutc(cl, "xattr.ver (before): %lld\n", ci->i_xattrs.version); + err = ceph_mdsc_do_request(mdsc, NULL, req); + ceph_mdsc_put_request(req); +- dout("xattr.ver (after): %lld\n", ci->i_xattrs.version); ++ doutc(cl, "xattr.ver (after): %lld\n", ci->i_xattrs.version); + + out: + if (pagelist) +@@ -1162,6 +1177,7 @@ out: + int __ceph_setxattr(struct inode *inode, const char *name, + const void *value, size_t size, int flags) + { ++ struct ceph_client *cl = ceph_inode_to_client(inode); + struct ceph_vxattr *vxattr; + struct ceph_inode_info *ci = ceph_inode(inode); + struct ceph_mds_client *mdsc = ceph_sb_to_fs_client(inode->i_sb)->mdsc; +@@ -1220,9 +1236,9 @@ retry: + required_blob_size = __get_required_blob_size(ci, name_len, val_len); + if ((ci->i_xattrs.version == 0) || !(issued & CEPH_CAP_XATTR_EXCL) || + (required_blob_size > mdsc->mdsmap->m_max_xattr_size)) { +- dout("%s do sync setxattr: version: %llu size: %d max: %llu\n", +- __func__, ci->i_xattrs.version, required_blob_size, +- mdsc->mdsmap->m_max_xattr_size); ++ doutc(cl, "sync version: %llu size: %d max: %llu\n", ++ ci->i_xattrs.version, required_blob_size, ++ mdsc->mdsmap->m_max_xattr_size); + goto do_sync; + } + +@@ -1236,8 +1252,8 @@ retry: + } + } + +- dout("setxattr %p name '%s' issued %s\n", inode, name, +- ceph_cap_string(issued)); ++ doutc(cl, "%p %llx.%llx name '%s' issued %s\n", inode, ++ ceph_vinop(inode), name, ceph_cap_string(issued)); + __build_xattrs(inode); + + if (!ci->i_xattrs.prealloc_blob || +@@ -1246,7 +1262,8 @@ retry: + + spin_unlock(&ci->i_ceph_lock); + ceph_buffer_put(old_blob); /* Shouldn't be required */ +- dout(" pre-allocating new blob size=%d\n", required_blob_size); ++ doutc(cl, " pre-allocating new blob size=%d\n", ++ required_blob_size); + blob = ceph_buffer_new(required_blob_size, GFP_NOFS); + if (!blob) + goto do_sync_unlocked; +@@ -1286,8 +1303,9 @@ do_sync_unlocked: + + /* security module set xattr while filling trace */ + if (current->journal_info) { +- pr_warn_ratelimited("sync setxattr %p " +- "during filling trace\n", inode); ++ pr_warn_ratelimited_client(cl, ++ "sync %p %llx.%llx during filling trace\n", ++ inode, ceph_vinop(inode)); + err = -EBUSY; + } else { + err = ceph_sync_setxattr(inode, name, value, size, flags); diff --git a/queue-6.6/drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch b/queue-6.6/drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch new file mode 100644 index 0000000000..1f4ba07751 --- /dev/null +++ b/queue-6.6/drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch @@ -0,0 +1,75 @@ +From stable+bounces-294163-greg=kroah.com@vger.kernel.org Fri Jul 31 19:12:12 2026 +From: Sasha Levin +Date: Fri, 31 Jul 2026 12:57:01 -0400 +Subject: drm/amdgpu: Respect placement requirements in amdgpu_gtt_mgr functions +To: stable@vger.kernel.org +Cc: "Timur Kristóf" , "Christian König" , "Alex Deucher" , "Sasha Levin" +Message-ID: <20260731165701.883388-1-sashal@kernel.org> + +From: Timur Kristóf + +[ Upstream commit 8882f8897e554053af9e72f4c2da8b1e2cce56c7 ] + +When testing intersection and compatibility, respect +the actual placement requirements. This is a pre-requisite +for ensuring that UVD CS BOs do not cross 256M segments. + +Fixes: ded910f368a5 ("drm/amdgpu: Implement intersect/compatible functions") +Suggested-by: Christian König +Signed-off-by: Timur Kristóf +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +(cherry picked from commit bc06579ca29dee9c245a41b12e39c7bb6938af5d) +Cc: stable@vger.kernel.org +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 30 ++++++++++++++++++++++++++-- + 1 file changed, 28 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +@@ -219,7 +219,20 @@ static bool amdgpu_gtt_mgr_intersects(st + const struct ttm_place *place, + size_t size) + { +- return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res); ++ const struct drm_mm_node *const node = &to_ttm_range_mgr_node(res)->mm_nodes[0]; ++ const u32 num_pages = PFN_UP(size); ++ ++ if (!place->lpfn) ++ return true; ++ ++ if (!amdgpu_gtt_mgr_has_gart_addr(res)) ++ return false; ++ ++ if (place->fpfn >= (node->start + num_pages) || ++ (place->lpfn && place->lpfn <= node->start)) ++ return false; ++ ++ return true; + } + + /** +@@ -237,7 +250,20 @@ static bool amdgpu_gtt_mgr_compatible(st + const struct ttm_place *place, + size_t size) + { +- return !place->lpfn || amdgpu_gtt_mgr_has_gart_addr(res); ++ const struct drm_mm_node *const node = &to_ttm_range_mgr_node(res)->mm_nodes[0]; ++ const u32 num_pages = PFN_UP(size); ++ ++ if (!place->lpfn) ++ return true; ++ ++ if (!amdgpu_gtt_mgr_has_gart_addr(res)) ++ return false; ++ ++ if (node->start < place->fpfn || ++ (place->lpfn && (node->start + num_pages) > place->lpfn)) ++ return false; ++ ++ return true; + } + + /** diff --git a/queue-6.6/drm-fb-helper-allocate-and-release-fb_info-in-single-place.patch b/queue-6.6/drm-fb-helper-allocate-and-release-fb_info-in-single-place.patch new file mode 100644 index 0000000000..e6d6062ed7 --- /dev/null +++ b/queue-6.6/drm-fb-helper-allocate-and-release-fb_info-in-single-place.patch @@ -0,0 +1,486 @@ +From stable+bounces-294128-greg=kroah.com@vger.kernel.org Fri Jul 31 17:59:52 2026 +From: Sasha Levin +Date: Fri, 31 Jul 2026 11:50:19 -0400 +Subject: drm/fb-helper: Allocate and release fb_info in single place +To: stable@vger.kernel.org +Cc: "Thomas Zimmermann" , "Christian König" , "Dmitry Baryshkov" , "Javier Martinez Canillas" , "Sasha Levin" +Message-ID: <20260731155020.604703-1-sashal@kernel.org> + +From: Thomas Zimmermann + +[ Upstream commit 63c971af40365ee706c7e24f6a7900d693518f09 ] + +Move the calls to drm_fb_helper_alloc_info() from drivers into a +single place in fbdev helpers. Allocates struct fb_info for a new +framebuffer device. Then call drm_fb_helper_single_fb_probe() to +create an fbdev screen buffer. Also release the instance on errors +by calling drm_fb_helper_release_info(). + +Simplifies the code and fixes the error cleanup for some of the +drivers. + +Regular release of the struct fb_info instance still happens in +drm_fb_helper_fini() as before. + +v2: +- remove error rollback in driver implementations (kernel test robot) +- initialize info in TTM implementation (kernel test robot) + +Signed-off-by: Thomas Zimmermann +Acked-by: Christian König # radeon +Acked-by: Dmitry Baryshkov # msm +Acked-by: Javier Martinez Canillas +Link: https://patch.msgid.link/20251027081245.80262-1-tzimmermann@suse.de +Stable-dep-of: a18b6e30ecd6 ("drm/tegra: fbdev: Remove offset into framebuffer memory") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/armada/armada_fbdev.c | 12 -------- + drivers/gpu/drm/drm_fb_helper.c | 41 +++++++++-------------------- + drivers/gpu/drm/drm_fbdev_dma.c | 12 -------- + drivers/gpu/drm/drm_fbdev_generic.c | 12 +------- + drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 9 ------ + drivers/gpu/drm/gma500/fbdev.c | 13 --------- + drivers/gpu/drm/i915/display/intel_fbdev.c | 9 ------ + drivers/gpu/drm/msm/msm_fbdev.c | 9 ------ + drivers/gpu/drm/omapdrm/omap_fbdev.c | 9 ------ + drivers/gpu/drm/radeon/radeon_fbdev.c | 13 --------- + drivers/gpu/drm/tegra/fbdev.c | 9 ------ + include/drm/drm_fb_helper.h | 12 -------- + 12 files changed, 25 insertions(+), 135 deletions(-) + +--- a/drivers/gpu/drm/armada/armada_fbdev.c ++++ b/drivers/gpu/drm/armada/armada_fbdev.c +@@ -43,10 +43,10 @@ static int armada_fbdev_create(struct dr + struct drm_fb_helper_surface_size *sizes) + { + struct drm_device *dev = fbh->dev; ++ struct fb_info *info = fbh->info; + struct drm_mode_fb_cmd2 mode; + struct armada_framebuffer *dfb; + struct armada_gem_object *obj; +- struct fb_info *info; + int size, ret; + void *ptr; + +@@ -87,12 +87,6 @@ static int armada_fbdev_create(struct dr + if (IS_ERR(dfb)) + return PTR_ERR(dfb); + +- info = drm_fb_helper_alloc_info(fbh); +- if (IS_ERR(info)) { +- ret = PTR_ERR(info); +- goto err_fballoc; +- } +- + info->fbops = &armada_fb_ops; + info->fix.smem_start = obj->phys_addr; + info->fix.smem_len = obj->obj.size; +@@ -107,10 +101,6 @@ static int armada_fbdev_create(struct dr + (unsigned long long)obj->phys_addr); + + return 0; +- +- err_fballoc: +- dfb->fb.funcs->destroy(&dfb->fb); +- return ret; + } + + static int armada_fb_probe(struct drm_fb_helper *fbh, +--- a/drivers/gpu/drm/drm_fb_helper.c ++++ b/drivers/gpu/drm/drm_fb_helper.c +@@ -499,20 +499,7 @@ int drm_fb_helper_init(struct drm_device + } + EXPORT_SYMBOL(drm_fb_helper_init); + +-/** +- * drm_fb_helper_alloc_info - allocate fb_info and some of its members +- * @fb_helper: driver-allocated fbdev helper +- * +- * A helper to alloc fb_info and the member cmap. Called by the driver +- * within the fb_probe fb_helper callback function. Drivers do not +- * need to release the allocated fb_info structure themselves, this is +- * automatically done when calling drm_fb_helper_fini(). +- * +- * RETURNS: +- * fb_info pointer if things went okay, pointer containing error code +- * otherwise +- */ +-struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper) ++static struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper) + { + struct device *dev = fb_helper->dev->dev; + struct fb_info *info; +@@ -538,17 +525,8 @@ err_release: + framebuffer_release(info); + return ERR_PTR(ret); + } +-EXPORT_SYMBOL(drm_fb_helper_alloc_info); + +-/** +- * drm_fb_helper_release_info - release fb_info and its members +- * @fb_helper: driver-allocated fbdev helper +- * +- * A helper to release fb_info and the member cmap. Drivers do not +- * need to release the allocated fb_info structure themselves, this is +- * automatically done when calling drm_fb_helper_fini(). +- */ +-void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper) ++static void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper) + { + struct fb_info *info = fb_helper->info; + +@@ -561,7 +539,6 @@ void drm_fb_helper_release_info(struct d + fb_dealloc_cmap(&info->cmap); + framebuffer_release(info); + } +-EXPORT_SYMBOL(drm_fb_helper_release_info); + + /** + * drm_fb_helper_unregister_info - unregister fb_info framebuffer device +@@ -1851,6 +1828,13 @@ __drm_fb_helper_initial_config_and_unloc + height = dev->mode_config.max_height; + + drm_client_modeset_probe(&fb_helper->client, width, height); ++ ++ info = drm_fb_helper_alloc_info(fb_helper); ++ if (IS_ERR(info)) { ++ mutex_unlock(&fb_helper->lock); ++ return PTR_ERR(info); ++ } ++ + ret = drm_fb_helper_single_fb_probe(fb_helper); + if (ret < 0) { + if (ret == -EAGAIN) { +@@ -1859,13 +1843,12 @@ __drm_fb_helper_initial_config_and_unloc + } + mutex_unlock(&fb_helper->lock); + +- return ret; ++ goto err_drm_fb_helper_release_info; + } + drm_setup_crtcs_fb(fb_helper); + + fb_helper->deferred_setup = false; + +- info = fb_helper->info; + info->var.pixclock = 0; + + /* Need to drop locks to avoid recursive deadlock in +@@ -1888,6 +1871,10 @@ __drm_fb_helper_initial_config_and_unloc + mutex_unlock(&kernel_fb_helper_lock); + + return 0; ++ ++err_drm_fb_helper_release_info: ++ drm_fb_helper_release_info(fb_helper); ++ return ret; + } + + /** +--- a/drivers/gpu/drm/drm_fbdev_dma.c ++++ b/drivers/gpu/drm/drm_fbdev_dma.c +@@ -78,10 +78,10 @@ static int drm_fbdev_dma_helper_fb_probe + { + struct drm_client_dev *client = &fb_helper->client; + struct drm_device *dev = fb_helper->dev; ++ struct fb_info *info = fb_helper->info; + struct drm_client_buffer *buffer; + struct drm_gem_dma_object *dma_obj; + struct drm_framebuffer *fb; +- struct fb_info *info; + u32 format; + struct iosys_map map; + int ret; +@@ -114,12 +114,6 @@ static int drm_fbdev_dma_helper_fb_probe + fb_helper->buffer = buffer; + fb_helper->fb = buffer->fb; + +- info = drm_fb_helper_alloc_info(fb_helper); +- if (IS_ERR(info)) { +- ret = PTR_ERR(info); +- goto err_drm_client_buffer_vunmap; +- } +- + drm_fb_helper_fill_info(info, fb_helper, sizes); + + info->fbops = &drm_fbdev_dma_fb_ops; +@@ -138,10 +132,6 @@ static int drm_fbdev_dma_helper_fb_probe + + return 0; + +-err_drm_client_buffer_vunmap: +- fb_helper->fb = NULL; +- fb_helper->buffer = NULL; +- drm_client_buffer_vunmap(buffer); + err_drm_client_buffer_delete: + drm_client_framebuffer_delete(buffer); + return ret; +--- a/drivers/gpu/drm/drm_fbdev_generic.c ++++ b/drivers/gpu/drm/drm_fbdev_generic.c +@@ -73,8 +73,8 @@ static int drm_fbdev_generic_helper_fb_p + { + struct drm_client_dev *client = &fb_helper->client; + struct drm_device *dev = fb_helper->dev; ++ struct fb_info *info = fb_helper->info; + struct drm_client_buffer *buffer; +- struct fb_info *info; + size_t screen_size; + void *screen_buffer; + u32 format; +@@ -100,12 +100,6 @@ static int drm_fbdev_generic_helper_fb_p + goto err_drm_client_framebuffer_delete; + } + +- info = drm_fb_helper_alloc_info(fb_helper); +- if (IS_ERR(info)) { +- ret = PTR_ERR(info); +- goto err_vfree; +- } +- + drm_fb_helper_fill_info(info, fb_helper, sizes); + + info->fbops = &drm_fbdev_generic_fb_ops; +@@ -122,12 +116,10 @@ static int drm_fbdev_generic_helper_fb_p + info->fbdefio = &fb_helper->fbdefio; + ret = fb_deferred_io_init(info); + if (ret) +- goto err_drm_fb_helper_release_info; ++ goto err_vfree; + + return 0; + +-err_drm_fb_helper_release_info: +- drm_fb_helper_release_info(fb_helper); + err_vfree: + vfree(screen_buffer); + err_drm_client_framebuffer_delete: +--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c ++++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +@@ -60,18 +60,11 @@ static int exynos_drm_fbdev_update(struc + struct drm_fb_helper_surface_size *sizes, + struct exynos_drm_gem *exynos_gem) + { +- struct fb_info *fbi; ++ struct fb_info *fbi = helper->info; + struct drm_framebuffer *fb = helper->fb; + unsigned int size = fb->width * fb->height * fb->format->cpp[0]; + unsigned long offset; + +- fbi = drm_fb_helper_alloc_info(helper); +- if (IS_ERR(fbi)) { +- DRM_DEV_ERROR(to_dma_dev(helper->dev), +- "failed to allocate fb info.\n"); +- return PTR_ERR(fbi); +- } +- + fbi->fbops = &exynos_drm_fb_ops; + + drm_fb_helper_fill_info(fbi, helper, sizes); +--- a/drivers/gpu/drm/gma500/fbdev.c ++++ b/drivers/gpu/drm/gma500/fbdev.c +@@ -110,7 +110,7 @@ static int psb_fbdev_fb_probe(struct drm + struct drm_device *dev = fb_helper->dev; + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + struct pci_dev *pdev = to_pci_dev(dev->dev); +- struct fb_info *info; ++ struct fb_info *info = fb_helper->info; + struct drm_framebuffer *fb; + struct drm_mode_fb_cmd2 mode_cmd = { }; + int size; +@@ -165,12 +165,6 @@ static int psb_fbdev_fb_probe(struct drm + + fb_helper->fb = fb; + +- info = drm_fb_helper_alloc_info(fb_helper); +- if (IS_ERR(info)) { +- ret = PTR_ERR(info); +- goto err_drm_framebuffer_unregister_private; +- } +- + info->fbops = &psb_fbdev_fb_ops; + + /* Accessed stolen memory directly */ +@@ -194,11 +188,6 @@ static int psb_fbdev_fb_probe(struct drm + + return 0; + +-err_drm_framebuffer_unregister_private: +- drm_framebuffer_unregister_private(fb); +- fb->obj[0] = NULL; +- drm_framebuffer_cleanup(fb); +- kfree(fb); + err_drm_gem_object_put: + drm_gem_object_put(obj); + return ret; +--- a/drivers/gpu/drm/i915/display/intel_fbdev.c ++++ b/drivers/gpu/drm/i915/display/intel_fbdev.c +@@ -218,7 +218,7 @@ static int intelfb_create(struct drm_fb_ + .type = I915_GTT_VIEW_NORMAL, + }; + intel_wakeref_t wakeref; +- struct fb_info *info; ++ struct fb_info *info = helper->info; + struct i915_vma *vma; + unsigned long flags = 0; + bool prealloc = false; +@@ -271,13 +271,6 @@ static int intelfb_create(struct drm_fb_ + goto out_unlock; + } + +- info = drm_fb_helper_alloc_info(helper); +- if (IS_ERR(info)) { +- drm_err(&dev_priv->drm, "Failed to allocate fb_info (%pe)\n", info); +- ret = PTR_ERR(info); +- goto out_unpin; +- } +- + ifbdev->helper.fb = &ifbdev->fb->base; + + info->fbops = &intelfb_ops; +--- a/drivers/gpu/drm/msm/msm_fbdev.c ++++ b/drivers/gpu/drm/msm/msm_fbdev.c +@@ -70,9 +70,9 @@ static int msm_fbdev_create(struct drm_f + { + struct drm_device *dev = helper->dev; + struct msm_drm_private *priv = dev->dev_private; ++ struct fb_info *fbi = helper->info; + struct drm_framebuffer *fb = NULL; + struct drm_gem_object *bo; +- struct fb_info *fbi = NULL; + uint64_t paddr; + uint32_t format; + int ret, pitch; +@@ -105,13 +105,6 @@ static int msm_fbdev_create(struct drm_f + goto fail; + } + +- fbi = drm_fb_helper_alloc_info(helper); +- if (IS_ERR(fbi)) { +- DRM_DEV_ERROR(dev->dev, "failed to allocate fb info\n"); +- ret = PTR_ERR(fbi); +- goto fail; +- } +- + DBG("fbi=%p, dev=%p", fbi, dev); + + helper->fb = fb; +--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c ++++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c +@@ -131,9 +131,9 @@ static int omap_fbdev_create(struct drm_ + struct omap_fbdev *fbdev = to_omap_fbdev(helper); + struct drm_device *dev = helper->dev; + struct omap_drm_private *priv = dev->dev_private; ++ struct fb_info *fbi = helper->info; + struct drm_framebuffer *fb = NULL; + union omap_gem_size gsize; +- struct fb_info *fbi = NULL; + struct drm_mode_fb_cmd2 mode_cmd = {0}; + struct drm_gem_object *bo; + dma_addr_t dma_addr; +@@ -199,13 +199,6 @@ static int omap_fbdev_create(struct drm_ + goto fail; + } + +- fbi = drm_fb_helper_alloc_info(helper); +- if (IS_ERR(fbi)) { +- dev_err(dev->dev, "failed to allocate fb info\n"); +- ret = PTR_ERR(fbi); +- goto fail; +- } +- + DBG("fbi=%p, dev=%p", fbi, dev); + + helper->fb = fb; +--- a/drivers/gpu/drm/radeon/radeon_fbdev.c ++++ b/drivers/gpu/drm/radeon/radeon_fbdev.c +@@ -207,7 +207,7 @@ static int radeon_fbdev_fb_helper_fb_pro + { + struct radeon_device *rdev = fb_helper->dev->dev_private; + struct drm_mode_fb_cmd2 mode_cmd = { }; +- struct fb_info *info; ++ struct fb_info *info = fb_helper->info; + struct drm_gem_object *gobj; + struct radeon_bo *rbo; + struct drm_framebuffer *fb; +@@ -245,13 +245,6 @@ static int radeon_fbdev_fb_helper_fb_pro + /* setup helper */ + fb_helper->fb = fb; + +- /* okay we have an object now allocate the framebuffer */ +- info = drm_fb_helper_alloc_info(fb_helper); +- if (IS_ERR(info)) { +- ret = PTR_ERR(info); +- goto err_drm_framebuffer_unregister_private; +- } +- + info->fbops = &radeon_fbdev_fb_ops; + + /* radeon resume is fragile and needs a vt switch to help it along */ +@@ -277,10 +270,6 @@ static int radeon_fbdev_fb_helper_fb_pro + + return 0; + +-err_drm_framebuffer_unregister_private: +- fb_helper->fb = NULL; +- drm_framebuffer_unregister_private(fb); +- drm_framebuffer_cleanup(fb); + err_kfree: + kfree(fb); + err_radeon_fbdev_destroy_pinned_object: +--- a/drivers/gpu/drm/tegra/fbdev.c ++++ b/drivers/gpu/drm/tegra/fbdev.c +@@ -72,10 +72,10 @@ static int tegra_fbdev_probe(struct drm_ + struct tegra_drm *tegra = helper->dev->dev_private; + struct drm_device *drm = helper->dev; + struct drm_mode_fb_cmd2 cmd = { 0 }; ++ struct fb_info *info = helper->info; + unsigned int bytes_per_pixel; + struct drm_framebuffer *fb; + unsigned long offset; +- struct fb_info *info; + struct tegra_bo *bo; + size_t size; + int err; +@@ -96,13 +96,6 @@ static int tegra_fbdev_probe(struct drm_ + if (IS_ERR(bo)) + return PTR_ERR(bo); + +- info = drm_fb_helper_alloc_info(helper); +- if (IS_ERR(info)) { +- dev_err(drm->dev, "failed to allocate framebuffer info\n"); +- drm_gem_object_put(&bo->gem); +- return PTR_ERR(info); +- } +- + fb = tegra_fb_alloc(drm, &cmd, &bo, 1); + if (IS_ERR(fb)) { + err = PTR_ERR(fb); +--- a/include/drm/drm_fb_helper.h ++++ b/include/drm/drm_fb_helper.h +@@ -246,8 +246,6 @@ int drm_fb_helper_check_var(struct fb_va + + int drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper); + +-struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper); +-void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper); + void drm_fb_helper_unregister_info(struct drm_fb_helper *fb_helper); + void drm_fb_helper_fill_info(struct fb_info *info, + struct drm_fb_helper *fb_helper, +@@ -330,16 +328,6 @@ drm_fb_helper_restore_fbdev_mode_unlocke + return 0; + } + +-static inline struct fb_info * +-drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper) +-{ +- return NULL; +-} +- +-static inline void drm_fb_helper_release_info(struct drm_fb_helper *fb_helper) +-{ +-} +- + static inline void drm_fb_helper_unregister_info(struct drm_fb_helper *fb_helper) + { + } diff --git a/queue-6.6/drm-i915-vrr-check-has_vrr-first-in-intel_vrr_is_capable.patch b/queue-6.6/drm-i915-vrr-check-has_vrr-first-in-intel_vrr_is_capable.patch new file mode 100644 index 0000000000..9912721839 --- /dev/null +++ b/queue-6.6/drm-i915-vrr-check-has_vrr-first-in-intel_vrr_is_capable.patch @@ -0,0 +1,48 @@ +From stable+bounces-294471-greg=kroah.com@vger.kernel.org Sun Aug 2 05:43:57 2026 +From: Sasha Levin +Date: Sat, 1 Aug 2026 23:42:44 -0400 +Subject: drm/i915/vrr: Check HAS_VRR() first in intel_vrr_is_capable() +To: stable@vger.kernel.org +Cc: "Ville Syrjälä" , "Ankit Nautiyal" , "Sasha Levin" +Message-ID: <20260802034245.2976489-1-sashal@kernel.org> + +From: Ville Syrjälä + +[ Upstream commit 4b274b0b61ab2a529e5c22e9aa033f3028e639fc ] + +There's no point in doing all the other checks in +intel_vrr_is_capable() if the platform doesn't support VRR at all +Check HAS_VRR() before wasting time on the other checks. + +Signed-off-by: Ville Syrjälä +Link: https://patchwork.freedesktop.org/patch/msgid/20251020185038.4272-23-ville.syrjala@linux.intel.com +Reviewed-by: Ankit Nautiyal +Stable-dep-of: f8a9262c7a6f ("drm/i915/vrr: require valid min/max vfreq for VRR") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/display/intel_vrr.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/i915/display/intel_vrr.c ++++ b/drivers/gpu/drm/i915/display/intel_vrr.c +@@ -16,6 +16,9 @@ bool intel_vrr_is_capable(struct intel_c + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct intel_dp *intel_dp; + ++ if (!HAS_VRR(i915)) ++ return false; ++ + /* + * DP Sink is capable of VRR video timings if + * Ignore MSA bit is set in DPCD. +@@ -38,8 +41,7 @@ bool intel_vrr_is_capable(struct intel_c + return false; + } + +- return HAS_VRR(i915) && +- info->monitor_range.max_vfreq - info->monitor_range.min_vfreq > 10; ++ return info->monitor_range.max_vfreq - info->monitor_range.min_vfreq > 10; + } + + void diff --git a/queue-6.6/drm-i915-vrr-require-valid-min-max-vfreq-for-vrr.patch b/queue-6.6/drm-i915-vrr-require-valid-min-max-vfreq-for-vrr.patch new file mode 100644 index 0000000000..fa59b8c70c --- /dev/null +++ b/queue-6.6/drm-i915-vrr-require-valid-min-max-vfreq-for-vrr.patch @@ -0,0 +1,49 @@ +From stable+bounces-294472-greg=kroah.com@vger.kernel.org Sun Aug 2 05:44:02 2026 +From: Sasha Levin +Date: Sat, 1 Aug 2026 23:42:45 -0400 +Subject: drm/i915/vrr: require valid min/max vfreq for VRR +To: stable@vger.kernel.org +Cc: Jani Nikula , Martin Hodo , Ankit Nautiyal , Joonas Lahtinen , Sasha Levin +Message-ID: <20260802034245.2976489-2-sashal@kernel.org> + +From: Jani Nikula + +[ Upstream commit f8a9262c7a6fc2de9802e14b0228114f0333869e ] + +Ensure the EDID provided min/max vfreq are valid. Most scenarios are +already covered (by coincidence) through the checks in +intel_vrr_is_capable() and intel_vrr_is_in_range(), but be more explicit +about it. At worst, a zero min_vfreq could lead to a division by zero in +intel_vrr_compute_vmax(). + +Discovered using AI-assisted static analysis confirmed by Intel Product +Security. + +Reported-by: Martin Hodo +Fixes: 117cd09ba528 ("drm/i915/display/dp: Compute VRR state in atomic_check") +Cc: stable@vger.kernel.org # v5.12+ +Cc: Ankit Nautiyal +Reviewed-by: Ankit Nautiyal +Link: https://patch.msgid.link/20260625131040.1051272-1-jani.nikula@intel.com +Signed-off-by: Jani Nikula +(cherry picked from commit 1765cf59f517b02f3b0591fe5120930d08bddeb6) +Signed-off-by: Joonas Lahtinen +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/i915/display/intel_vrr.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/gpu/drm/i915/display/intel_vrr.c ++++ b/drivers/gpu/drm/i915/display/intel_vrr.c +@@ -41,6 +41,10 @@ bool intel_vrr_is_capable(struct intel_c + return false; + } + ++ if (!info->monitor_range.min_vfreq || !info->monitor_range.max_vfreq || ++ info->monitor_range.min_vfreq > info->monitor_range.max_vfreq) ++ return false; ++ + return info->monitor_range.max_vfreq - info->monitor_range.min_vfreq > 10; + } + diff --git a/queue-6.6/drm-renesas-move-rz-g2l-mipi-dsi-driver-to-rz-du.patch b/queue-6.6/drm-renesas-move-rz-g2l-mipi-dsi-driver-to-rz-du.patch new file mode 100644 index 0000000000..bceb56623e --- /dev/null +++ b/queue-6.6/drm-renesas-move-rz-g2l-mipi-dsi-driver-to-rz-du.patch @@ -0,0 +1,2054 @@ +From stable+bounces-293837-greg=kroah.com@vger.kernel.org Thu Jul 30 21:39:22 2026 +From: Sasha Levin +Date: Thu, 30 Jul 2026 15:29:54 -0400 +Subject: drm: renesas: Move RZ/G2L MIPI DSI driver to rz-du +To: stable@vger.kernel.org +Cc: Lad Prabhakar , Biju Das , Laurent Pinchart , Tomi Valkeinen , Sasha Levin +Message-ID: <20260730192955.3124753-1-sashal@kernel.org> + +From: Lad Prabhakar + +[ Upstream commit 1b5dfd1881dbe303536d4167500b94549ff2f6a7 ] + +All the RZ/G2L DU specific components are located under the rz-du folder, +so it makes sense to move the RZ/G2L MIPI DSI driver there instead of +keeping it in the rcar-du folder. This change improves the organization +and modularity of the driver configuration by grouping related settings together. + +Signed-off-by: Lad Prabhakar +Acked-by: Biju Das +Reviewed-by: Laurent Pinchart +Signed-off-by: Tomi Valkeinen +Link: https://patchwork.freedesktop.org/patch/msgid/20240625123244.200533-1-prabhakar.mahadev-lad.rj@bp.renesas.com +Stable-dep-of: 7cbba8a8ba02 ("drm: renesas: rzg2l_mipi_dsi: Increase reset deassertion delay") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/renesas/Kconfig | 1 + + drivers/gpu/drm/renesas/Makefile | 1 + + drivers/gpu/drm/renesas/rcar-du/Kconfig | 8 -------- + drivers/gpu/drm/renesas/rcar-du/Makefile | 2 -- + drivers/gpu/drm/renesas/rz-du/Kconfig | 8 ++++++++ + drivers/gpu/drm/renesas/rz-du/Makefile | 3 +++ + .../gpu/drm/renesas/{rcar-du => rz-du}/rzg2l_mipi_dsi.c | 0 + .../drm/renesas/{rcar-du => rz-du}/rzg2l_mipi_dsi_regs.h | 0 + drivers/gpu/drm/renesas/Kconfig | 1 + drivers/gpu/drm/renesas/Makefile | 1 + drivers/gpu/drm/renesas/rcar-du/Kconfig | 8 + drivers/gpu/drm/renesas/rcar-du/Makefile | 2 + drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi.c | 816 ------------------ + drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi_regs.h | 151 --- + drivers/gpu/drm/renesas/rz-du/Kconfig | 8 + drivers/gpu/drm/renesas/rz-du/Makefile | 3 + drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c | 816 ++++++++++++++++++ + drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h | 151 +++ + 10 files changed, 980 insertions(+), 977 deletions(-) + create mode 100644 drivers/gpu/drm/renesas/rz-du/Kconfig + create mode 100644 drivers/gpu/drm/renesas/rz-du/Makefile + rename drivers/gpu/drm/renesas/{rcar-du => rz-du}/rzg2l_mipi_dsi.c (100%) + rename drivers/gpu/drm/renesas/{rcar-du => rz-du}/rzg2l_mipi_dsi_regs.h (100%) + +--- a/drivers/gpu/drm/renesas/Kconfig ++++ b/drivers/gpu/drm/renesas/Kconfig +@@ -1,4 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0-only + + source "drivers/gpu/drm/renesas/rcar-du/Kconfig" ++source "drivers/gpu/drm/renesas/rz-du/Kconfig" + source "drivers/gpu/drm/renesas/shmobile/Kconfig" +--- a/drivers/gpu/drm/renesas/Makefile ++++ b/drivers/gpu/drm/renesas/Makefile +@@ -1,4 +1,5 @@ + # SPDX-License-Identifier: GPL-2.0 + + obj-y += rcar-du/ ++obj-y += rz-du/ + obj-$(CONFIG_DRM_SHMOBILE) += shmobile/ +--- a/drivers/gpu/drm/renesas/rcar-du/Kconfig ++++ b/drivers/gpu/drm/renesas/rcar-du/Kconfig +@@ -60,14 +60,6 @@ config DRM_RCAR_MIPI_DSI + select DRM_MIPI_DSI + select RESET_CONTROLLER + +-config DRM_RZG2L_MIPI_DSI +- tristate "RZ/G2L MIPI DSI Encoder Support" +- depends on DRM && DRM_BRIDGE && OF +- depends on ARCH_RENESAS || COMPILE_TEST +- select DRM_MIPI_DSI +- help +- Enable support for the RZ/G2L Display Unit embedded MIPI DSI encoders. +- + config DRM_RCAR_VSP + bool "R-Car DU VSP Compositor Support" if ARM + default y if ARM64 +--- a/drivers/gpu/drm/renesas/rcar-du/Makefile ++++ b/drivers/gpu/drm/renesas/rcar-du/Makefile +@@ -14,5 +14,3 @@ obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-dr + obj-$(CONFIG_DRM_RCAR_DW_HDMI) += rcar_dw_hdmi.o + obj-$(CONFIG_DRM_RCAR_LVDS) += rcar_lvds.o + obj-$(CONFIG_DRM_RCAR_MIPI_DSI) += rcar_mipi_dsi.o +- +-obj-$(CONFIG_DRM_RZG2L_MIPI_DSI) += rzg2l_mipi_dsi.o +--- a/drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi.c ++++ /dev/null +@@ -1,816 +0,0 @@ +-// SPDX-License-Identifier: GPL-2.0 +-/* +- * RZ/G2L MIPI DSI Encoder Driver +- * +- * Copyright (C) 2022 Renesas Electronics Corporation +- */ +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "rzg2l_mipi_dsi_regs.h" +- +-struct rzg2l_mipi_dsi { +- struct device *dev; +- void __iomem *mmio; +- +- struct reset_control *rstc; +- struct reset_control *arstc; +- struct reset_control *prstc; +- +- struct mipi_dsi_host host; +- struct drm_bridge bridge; +- struct drm_bridge *next_bridge; +- +- struct clk *vclk; +- +- enum mipi_dsi_pixel_format format; +- unsigned int num_data_lanes; +- unsigned int lanes; +- unsigned long mode_flags; +-}; +- +-static inline struct rzg2l_mipi_dsi * +-bridge_to_rzg2l_mipi_dsi(struct drm_bridge *bridge) +-{ +- return container_of(bridge, struct rzg2l_mipi_dsi, bridge); +-} +- +-static inline struct rzg2l_mipi_dsi * +-host_to_rzg2l_mipi_dsi(struct mipi_dsi_host *host) +-{ +- return container_of(host, struct rzg2l_mipi_dsi, host); +-} +- +-struct rzg2l_mipi_dsi_timings { +- unsigned long hsfreq_max; +- u32 t_init; +- u32 tclk_prepare; +- u32 ths_prepare; +- u32 tclk_zero; +- u32 tclk_pre; +- u32 tclk_post; +- u32 tclk_trail; +- u32 ths_zero; +- u32 ths_trail; +- u32 ths_exit; +- u32 tlpx; +-}; +- +-static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = { +- { +- .hsfreq_max = 80000, +- .t_init = 79801, +- .tclk_prepare = 8, +- .ths_prepare = 13, +- .tclk_zero = 33, +- .tclk_pre = 24, +- .tclk_post = 94, +- .tclk_trail = 10, +- .ths_zero = 23, +- .ths_trail = 17, +- .ths_exit = 13, +- .tlpx = 6, +- }, +- { +- .hsfreq_max = 125000, +- .t_init = 79801, +- .tclk_prepare = 8, +- .ths_prepare = 12, +- .tclk_zero = 33, +- .tclk_pre = 15, +- .tclk_post = 94, +- .tclk_trail = 10, +- .ths_zero = 23, +- .ths_trail = 17, +- .ths_exit = 13, +- .tlpx = 6, +- }, +- { +- .hsfreq_max = 250000, +- .t_init = 79801, +- .tclk_prepare = 8, +- .ths_prepare = 12, +- .tclk_zero = 33, +- .tclk_pre = 13, +- .tclk_post = 94, +- .tclk_trail = 10, +- .ths_zero = 23, +- .ths_trail = 16, +- .ths_exit = 13, +- .tlpx = 6, +- }, +- { +- .hsfreq_max = 360000, +- .t_init = 79801, +- .tclk_prepare = 8, +- .ths_prepare = 10, +- .tclk_zero = 33, +- .tclk_pre = 4, +- .tclk_post = 35, +- .tclk_trail = 7, +- .ths_zero = 16, +- .ths_trail = 9, +- .ths_exit = 13, +- .tlpx = 6, +- }, +- { +- .hsfreq_max = 720000, +- .t_init = 79801, +- .tclk_prepare = 8, +- .ths_prepare = 9, +- .tclk_zero = 33, +- .tclk_pre = 4, +- .tclk_post = 35, +- .tclk_trail = 7, +- .ths_zero = 16, +- .ths_trail = 9, +- .ths_exit = 13, +- .tlpx = 6, +- }, +- { +- .hsfreq_max = 1500000, +- .t_init = 79801, +- .tclk_prepare = 8, +- .ths_prepare = 9, +- .tclk_zero = 33, +- .tclk_pre = 4, +- .tclk_post = 35, +- .tclk_trail = 7, +- .ths_zero = 16, +- .ths_trail = 9, +- .ths_exit = 13, +- .tlpx = 6, +- }, +-}; +- +-static void rzg2l_mipi_dsi_phy_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data) +-{ +- iowrite32(data, dsi->mmio + reg); +-} +- +-static void rzg2l_mipi_dsi_link_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data) +-{ +- iowrite32(data, dsi->mmio + LINK_REG_OFFSET + reg); +-} +- +-static u32 rzg2l_mipi_dsi_phy_read(struct rzg2l_mipi_dsi *dsi, u32 reg) +-{ +- return ioread32(dsi->mmio + reg); +-} +- +-static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg) +-{ +- return ioread32(dsi->mmio + LINK_REG_OFFSET + reg); +-} +- +-/* ----------------------------------------------------------------------------- +- * Hardware Setup +- */ +- +-static int rzg2l_mipi_dsi_dphy_init(struct rzg2l_mipi_dsi *dsi, +- unsigned long hsfreq) +-{ +- const struct rzg2l_mipi_dsi_timings *dphy_timings; +- unsigned int i; +- u32 dphyctrl0; +- u32 dphytim0; +- u32 dphytim1; +- u32 dphytim2; +- u32 dphytim3; +- int ret; +- +- /* All DSI global operation timings are set with recommended setting */ +- for (i = 0; i < ARRAY_SIZE(rzg2l_mipi_dsi_global_timings); ++i) { +- dphy_timings = &rzg2l_mipi_dsi_global_timings[i]; +- if (hsfreq <= dphy_timings->hsfreq_max) +- break; +- } +- +- /* Initializing DPHY before accessing LINK */ +- dphyctrl0 = DSIDPHYCTRL0_CAL_EN_HSRX_OFS | DSIDPHYCTRL0_CMN_MASTER_EN | +- DSIDPHYCTRL0_RE_VDD_DETVCCQLV18 | DSIDPHYCTRL0_EN_BGR; +- +- rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0); +- usleep_range(20, 30); +- +- dphyctrl0 |= DSIDPHYCTRL0_EN_LDO1200; +- rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0); +- usleep_range(10, 20); +- +- dphytim0 = DSIDPHYTIM0_TCLK_MISS(0) | +- DSIDPHYTIM0_T_INIT(dphy_timings->t_init); +- dphytim1 = DSIDPHYTIM1_THS_PREPARE(dphy_timings->ths_prepare) | +- DSIDPHYTIM1_TCLK_PREPARE(dphy_timings->tclk_prepare) | +- DSIDPHYTIM1_THS_SETTLE(0) | +- DSIDPHYTIM1_TCLK_SETTLE(0); +- dphytim2 = DSIDPHYTIM2_TCLK_TRAIL(dphy_timings->tclk_trail) | +- DSIDPHYTIM2_TCLK_POST(dphy_timings->tclk_post) | +- DSIDPHYTIM2_TCLK_PRE(dphy_timings->tclk_pre) | +- DSIDPHYTIM2_TCLK_ZERO(dphy_timings->tclk_zero); +- dphytim3 = DSIDPHYTIM3_TLPX(dphy_timings->tlpx) | +- DSIDPHYTIM3_THS_EXIT(dphy_timings->ths_exit) | +- DSIDPHYTIM3_THS_TRAIL(dphy_timings->ths_trail) | +- DSIDPHYTIM3_THS_ZERO(dphy_timings->ths_zero); +- +- rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM0, dphytim0); +- rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM1, dphytim1); +- rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM2, dphytim2); +- rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM3, dphytim3); +- +- ret = reset_control_deassert(dsi->rstc); +- if (ret < 0) +- return ret; +- +- udelay(1); +- +- return 0; +-} +- +-static void rzg2l_mipi_dsi_dphy_exit(struct rzg2l_mipi_dsi *dsi) +-{ +- u32 dphyctrl0; +- +- dphyctrl0 = rzg2l_mipi_dsi_phy_read(dsi, DSIDPHYCTRL0); +- +- dphyctrl0 &= ~(DSIDPHYCTRL0_EN_LDO1200 | DSIDPHYCTRL0_EN_BGR); +- rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0); +- +- reset_control_assert(dsi->rstc); +-} +- +-static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, +- const struct drm_display_mode *mode) +-{ +- unsigned long hsfreq; +- unsigned int bpp; +- u32 txsetr; +- u32 clstptsetr; +- u32 lptrnstsetr; +- u32 clkkpt; +- u32 clkbfht; +- u32 clkstpt; +- u32 golpbkt; +- int ret; +- +- /* +- * Relationship between hsclk and vclk must follow +- * vclk * bpp = hsclk * 8 * lanes +- * where vclk: video clock (Hz) +- * bpp: video pixel bit depth +- * hsclk: DSI HS Byte clock frequency (Hz) +- * lanes: number of data lanes +- * +- * hsclk(bit) = hsclk(byte) * 8 +- */ +- bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); +- hsfreq = (mode->clock * bpp * 8) / (8 * dsi->lanes); +- +- ret = pm_runtime_resume_and_get(dsi->dev); +- if (ret < 0) +- return ret; +- +- clk_set_rate(dsi->vclk, mode->clock * 1000); +- +- ret = rzg2l_mipi_dsi_dphy_init(dsi, hsfreq); +- if (ret < 0) +- goto err_phy; +- +- /* Enable Data lanes and Clock lanes */ +- txsetr = TXSETR_DLEN | TXSETR_NUMLANEUSE(dsi->lanes - 1) | TXSETR_CLEN; +- rzg2l_mipi_dsi_link_write(dsi, TXSETR, txsetr); +- +- /* +- * Global timings characteristic depends on high speed Clock Frequency +- * Currently MIPI DSI-IF just supports maximum FHD@60 with: +- * - videoclock = 148.5 (MHz) +- * - bpp: maximum 24bpp +- * - data lanes: maximum 4 lanes +- * Therefore maximum hsclk will be 891 Mbps. +- */ +- if (hsfreq > 445500) { +- clkkpt = 12; +- clkbfht = 15; +- clkstpt = 48; +- golpbkt = 75; +- } else if (hsfreq > 250000) { +- clkkpt = 7; +- clkbfht = 8; +- clkstpt = 27; +- golpbkt = 40; +- } else { +- clkkpt = 8; +- clkbfht = 6; +- clkstpt = 24; +- golpbkt = 29; +- } +- +- clstptsetr = CLSTPTSETR_CLKKPT(clkkpt) | CLSTPTSETR_CLKBFHT(clkbfht) | +- CLSTPTSETR_CLKSTPT(clkstpt); +- rzg2l_mipi_dsi_link_write(dsi, CLSTPTSETR, clstptsetr); +- +- lptrnstsetr = LPTRNSTSETR_GOLPBKT(golpbkt); +- rzg2l_mipi_dsi_link_write(dsi, LPTRNSTSETR, lptrnstsetr); +- +- return 0; +- +-err_phy: +- rzg2l_mipi_dsi_dphy_exit(dsi); +- pm_runtime_put(dsi->dev); +- +- return ret; +-} +- +-static void rzg2l_mipi_dsi_stop(struct rzg2l_mipi_dsi *dsi) +-{ +- rzg2l_mipi_dsi_dphy_exit(dsi); +- pm_runtime_put(dsi->dev); +-} +- +-static void rzg2l_mipi_dsi_set_display_timing(struct rzg2l_mipi_dsi *dsi, +- const struct drm_display_mode *mode) +-{ +- u32 vich1ppsetr; +- u32 vich1vssetr; +- u32 vich1vpsetr; +- u32 vich1hssetr; +- u32 vich1hpsetr; +- int dsi_format; +- u32 delay[2]; +- u8 index; +- +- /* Configuration for Pixel Packet */ +- dsi_format = mipi_dsi_pixel_format_to_bpp(dsi->format); +- switch (dsi_format) { +- case 24: +- vich1ppsetr = VICH1PPSETR_DT_RGB24; +- break; +- case 18: +- vich1ppsetr = VICH1PPSETR_DT_RGB18; +- break; +- } +- +- if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) && +- !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)) +- vich1ppsetr |= VICH1PPSETR_TXESYNC_PULSE; +- +- rzg2l_mipi_dsi_link_write(dsi, VICH1PPSETR, vich1ppsetr); +- +- /* Configuration for Video Parameters */ +- vich1vssetr = VICH1VSSETR_VACTIVE(mode->vdisplay) | +- VICH1VSSETR_VSA(mode->vsync_end - mode->vsync_start); +- vich1vssetr |= (mode->flags & DRM_MODE_FLAG_PVSYNC) ? +- VICH1VSSETR_VSPOL_HIGH : VICH1VSSETR_VSPOL_LOW; +- +- vich1vpsetr = VICH1VPSETR_VFP(mode->vsync_start - mode->vdisplay) | +- VICH1VPSETR_VBP(mode->vtotal - mode->vsync_end); +- +- vich1hssetr = VICH1HSSETR_HACTIVE(mode->hdisplay) | +- VICH1HSSETR_HSA(mode->hsync_end - mode->hsync_start); +- vich1hssetr |= (mode->flags & DRM_MODE_FLAG_PHSYNC) ? +- VICH1HSSETR_HSPOL_HIGH : VICH1HSSETR_HSPOL_LOW; +- +- vich1hpsetr = VICH1HPSETR_HFP(mode->hsync_start - mode->hdisplay) | +- VICH1HPSETR_HBP(mode->htotal - mode->hsync_end); +- +- rzg2l_mipi_dsi_link_write(dsi, VICH1VSSETR, vich1vssetr); +- rzg2l_mipi_dsi_link_write(dsi, VICH1VPSETR, vich1vpsetr); +- rzg2l_mipi_dsi_link_write(dsi, VICH1HSSETR, vich1hssetr); +- rzg2l_mipi_dsi_link_write(dsi, VICH1HPSETR, vich1hpsetr); +- +- /* +- * Configuration for Delay Value +- * Delay value based on 2 ranges of video clock. +- * 74.25MHz is videoclock of HD@60p or FHD@30p +- */ +- if (mode->clock > 74250) { +- delay[0] = 231; +- delay[1] = 216; +- } else { +- delay[0] = 220; +- delay[1] = 212; +- } +- +- if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) +- index = 0; +- else +- index = 1; +- +- rzg2l_mipi_dsi_link_write(dsi, VICH1SET1R, +- VICH1SET1R_DLY(delay[index])); +-} +- +-static int rzg2l_mipi_dsi_start_hs_clock(struct rzg2l_mipi_dsi *dsi) +-{ +- bool is_clk_cont; +- u32 hsclksetr; +- u32 status; +- int ret; +- +- is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS); +- +- /* Start HS clock */ +- hsclksetr = HSCLKSETR_HSCLKRUN_HS | (is_clk_cont ? +- HSCLKSETR_HSCLKMODE_CONT : +- HSCLKSETR_HSCLKMODE_NON_CONT); +- rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR, hsclksetr); +- +- if (is_clk_cont) { +- ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status, +- status & PLSR_CLLP2HS, +- 2000, 20000, false, dsi, PLSR); +- if (ret < 0) { +- dev_err(dsi->dev, "failed to start HS clock\n"); +- return ret; +- } +- } +- +- dev_dbg(dsi->dev, "Start High Speed Clock with %s clock mode", +- is_clk_cont ? "continuous" : "non-continuous"); +- +- return 0; +-} +- +-static int rzg2l_mipi_dsi_stop_hs_clock(struct rzg2l_mipi_dsi *dsi) +-{ +- bool is_clk_cont; +- u32 status; +- int ret; +- +- is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS); +- +- /* Stop HS clock */ +- rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR, +- is_clk_cont ? HSCLKSETR_HSCLKMODE_CONT : +- HSCLKSETR_HSCLKMODE_NON_CONT); +- +- if (is_clk_cont) { +- ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status, +- status & PLSR_CLHS2LP, +- 2000, 20000, false, dsi, PLSR); +- if (ret < 0) { +- dev_err(dsi->dev, "failed to stop HS clock\n"); +- return ret; +- } +- } +- +- return 0; +-} +- +-static int rzg2l_mipi_dsi_start_video(struct rzg2l_mipi_dsi *dsi) +-{ +- u32 vich1set0r; +- u32 status; +- int ret; +- +- /* Configuration for Blanking sequence and start video input*/ +- vich1set0r = VICH1SET0R_HFPNOLP | VICH1SET0R_HBPNOLP | +- VICH1SET0R_HSANOLP | VICH1SET0R_VSTART; +- rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, vich1set0r); +- +- ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status, +- status & VICH1SR_VIRDY, +- 2000, 20000, false, dsi, VICH1SR); +- if (ret < 0) +- dev_err(dsi->dev, "Failed to start video signal input\n"); +- +- return ret; +-} +- +-static int rzg2l_mipi_dsi_stop_video(struct rzg2l_mipi_dsi *dsi) +-{ +- u32 status; +- int ret; +- +- rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, VICH1SET0R_VSTPAFT); +- ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status, +- (status & VICH1SR_STOP) && (!(status & VICH1SR_RUNNING)), +- 2000, 20000, false, dsi, VICH1SR); +- if (ret < 0) +- goto err; +- +- ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status, +- !(status & LINKSR_HSBUSY), +- 2000, 20000, false, dsi, LINKSR); +- if (ret < 0) +- goto err; +- +- return 0; +- +-err: +- dev_err(dsi->dev, "Failed to stop video signal input\n"); +- return ret; +-} +- +-/* ----------------------------------------------------------------------------- +- * Bridge +- */ +- +-static int rzg2l_mipi_dsi_attach(struct drm_bridge *bridge, +- enum drm_bridge_attach_flags flags) +-{ +- struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge); +- +- return drm_bridge_attach(bridge->encoder, dsi->next_bridge, bridge, +- flags); +-} +- +-static void rzg2l_mipi_dsi_atomic_enable(struct drm_bridge *bridge, +- struct drm_bridge_state *old_bridge_state) +-{ +- struct drm_atomic_state *state = old_bridge_state->base.state; +- struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge); +- const struct drm_display_mode *mode; +- struct drm_connector *connector; +- struct drm_crtc *crtc; +- int ret; +- +- connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); +- crtc = drm_atomic_get_new_connector_state(state, connector)->crtc; +- mode = &drm_atomic_get_new_crtc_state(state, crtc)->adjusted_mode; +- +- ret = rzg2l_mipi_dsi_startup(dsi, mode); +- if (ret < 0) +- return; +- +- rzg2l_mipi_dsi_set_display_timing(dsi, mode); +- +- ret = rzg2l_mipi_dsi_start_hs_clock(dsi); +- if (ret < 0) +- goto err_stop; +- +- ret = rzg2l_mipi_dsi_start_video(dsi); +- if (ret < 0) +- goto err_stop_clock; +- +- return; +- +-err_stop_clock: +- rzg2l_mipi_dsi_stop_hs_clock(dsi); +-err_stop: +- rzg2l_mipi_dsi_stop(dsi); +-} +- +-static void rzg2l_mipi_dsi_atomic_disable(struct drm_bridge *bridge, +- struct drm_bridge_state *old_bridge_state) +-{ +- struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge); +- +- rzg2l_mipi_dsi_stop_video(dsi); +- rzg2l_mipi_dsi_stop_hs_clock(dsi); +- rzg2l_mipi_dsi_stop(dsi); +-} +- +-static enum drm_mode_status +-rzg2l_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge, +- const struct drm_display_info *info, +- const struct drm_display_mode *mode) +-{ +- if (mode->clock > 148500) +- return MODE_CLOCK_HIGH; +- +- if (mode->clock < 5803) +- return MODE_CLOCK_LOW; +- +- return MODE_OK; +-} +- +-static const struct drm_bridge_funcs rzg2l_mipi_dsi_bridge_ops = { +- .attach = rzg2l_mipi_dsi_attach, +- .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, +- .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, +- .atomic_reset = drm_atomic_helper_bridge_reset, +- .atomic_enable = rzg2l_mipi_dsi_atomic_enable, +- .atomic_disable = rzg2l_mipi_dsi_atomic_disable, +- .mode_valid = rzg2l_mipi_dsi_bridge_mode_valid, +-}; +- +-/* ----------------------------------------------------------------------------- +- * Host setting +- */ +- +-static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host, +- struct mipi_dsi_device *device) +-{ +- struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host); +- int ret; +- +- if (device->lanes > dsi->num_data_lanes) { +- dev_err(dsi->dev, +- "Number of lines of device (%u) exceeds host (%u)\n", +- device->lanes, dsi->num_data_lanes); +- return -EINVAL; +- } +- +- switch (mipi_dsi_pixel_format_to_bpp(device->format)) { +- case 24: +- case 18: +- break; +- default: +- dev_err(dsi->dev, "Unsupported format 0x%04x\n", device->format); +- return -EINVAL; +- } +- +- dsi->lanes = device->lanes; +- dsi->format = device->format; +- dsi->mode_flags = device->mode_flags; +- +- dsi->next_bridge = devm_drm_of_get_bridge(dsi->dev, dsi->dev->of_node, +- 1, 0); +- if (IS_ERR(dsi->next_bridge)) { +- ret = PTR_ERR(dsi->next_bridge); +- dev_err(dsi->dev, "failed to get next bridge: %d\n", ret); +- return ret; +- } +- +- drm_bridge_add(&dsi->bridge); +- +- return 0; +-} +- +-static int rzg2l_mipi_dsi_host_detach(struct mipi_dsi_host *host, +- struct mipi_dsi_device *device) +-{ +- struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host); +- +- drm_bridge_remove(&dsi->bridge); +- +- return 0; +-} +- +-static const struct mipi_dsi_host_ops rzg2l_mipi_dsi_host_ops = { +- .attach = rzg2l_mipi_dsi_host_attach, +- .detach = rzg2l_mipi_dsi_host_detach, +-}; +- +-/* ----------------------------------------------------------------------------- +- * Power Management +- */ +- +-static int __maybe_unused rzg2l_mipi_pm_runtime_suspend(struct device *dev) +-{ +- struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev); +- +- reset_control_assert(dsi->prstc); +- reset_control_assert(dsi->arstc); +- +- return 0; +-} +- +-static int __maybe_unused rzg2l_mipi_pm_runtime_resume(struct device *dev) +-{ +- struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev); +- int ret; +- +- ret = reset_control_deassert(dsi->arstc); +- if (ret < 0) +- return ret; +- +- ret = reset_control_deassert(dsi->prstc); +- if (ret < 0) +- reset_control_assert(dsi->arstc); +- +- return ret; +-} +- +-static const struct dev_pm_ops rzg2l_mipi_pm_ops = { +- SET_RUNTIME_PM_OPS(rzg2l_mipi_pm_runtime_suspend, rzg2l_mipi_pm_runtime_resume, NULL) +-}; +- +-/* ----------------------------------------------------------------------------- +- * Probe & Remove +- */ +- +-static int rzg2l_mipi_dsi_probe(struct platform_device *pdev) +-{ +- unsigned int num_data_lanes; +- struct rzg2l_mipi_dsi *dsi; +- u32 txsetr; +- int ret; +- +- dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL); +- if (!dsi) +- return -ENOMEM; +- +- platform_set_drvdata(pdev, dsi); +- dsi->dev = &pdev->dev; +- +- ret = drm_of_get_data_lanes_count_ep(dsi->dev->of_node, 1, 0, 1, 4); +- if (ret < 0) +- return dev_err_probe(dsi->dev, ret, +- "missing or invalid data-lanes property\n"); +- +- num_data_lanes = ret; +- +- dsi->mmio = devm_platform_ioremap_resource(pdev, 0); +- if (IS_ERR(dsi->mmio)) +- return PTR_ERR(dsi->mmio); +- +- dsi->vclk = devm_clk_get(dsi->dev, "vclk"); +- if (IS_ERR(dsi->vclk)) +- return PTR_ERR(dsi->vclk); +- +- dsi->rstc = devm_reset_control_get_exclusive(dsi->dev, "rst"); +- if (IS_ERR(dsi->rstc)) +- return dev_err_probe(dsi->dev, PTR_ERR(dsi->rstc), +- "failed to get rst\n"); +- +- dsi->arstc = devm_reset_control_get_exclusive(dsi->dev, "arst"); +- if (IS_ERR(dsi->arstc)) +- return dev_err_probe(&pdev->dev, PTR_ERR(dsi->arstc), +- "failed to get arst\n"); +- +- dsi->prstc = devm_reset_control_get_exclusive(dsi->dev, "prst"); +- if (IS_ERR(dsi->prstc)) +- return dev_err_probe(dsi->dev, PTR_ERR(dsi->prstc), +- "failed to get prst\n"); +- +- platform_set_drvdata(pdev, dsi); +- +- pm_runtime_enable(dsi->dev); +- +- ret = pm_runtime_resume_and_get(dsi->dev); +- if (ret < 0) +- goto err_pm_disable; +- +- /* +- * TXSETR register can be read only after DPHY init. But during probe +- * mode->clock and format are not available. So initialize DPHY with +- * timing parameters for 80Mbps. +- */ +- ret = rzg2l_mipi_dsi_dphy_init(dsi, 80000); +- if (ret < 0) +- goto err_phy; +- +- txsetr = rzg2l_mipi_dsi_link_read(dsi, TXSETR); +- dsi->num_data_lanes = min(((txsetr >> 16) & 3) + 1, num_data_lanes); +- rzg2l_mipi_dsi_dphy_exit(dsi); +- pm_runtime_put(dsi->dev); +- +- /* Initialize the DRM bridge. */ +- dsi->bridge.funcs = &rzg2l_mipi_dsi_bridge_ops; +- dsi->bridge.of_node = dsi->dev->of_node; +- +- /* Init host device */ +- dsi->host.dev = dsi->dev; +- dsi->host.ops = &rzg2l_mipi_dsi_host_ops; +- ret = mipi_dsi_host_register(&dsi->host); +- if (ret < 0) +- goto err_pm_disable; +- +- return 0; +- +-err_phy: +- rzg2l_mipi_dsi_dphy_exit(dsi); +- pm_runtime_put(dsi->dev); +-err_pm_disable: +- pm_runtime_disable(dsi->dev); +- return ret; +-} +- +-static void rzg2l_mipi_dsi_remove(struct platform_device *pdev) +-{ +- struct rzg2l_mipi_dsi *dsi = platform_get_drvdata(pdev); +- +- mipi_dsi_host_unregister(&dsi->host); +- pm_runtime_disable(&pdev->dev); +-} +- +-static const struct of_device_id rzg2l_mipi_dsi_of_table[] = { +- { .compatible = "renesas,rzg2l-mipi-dsi" }, +- { /* sentinel */ } +-}; +- +-MODULE_DEVICE_TABLE(of, rzg2l_mipi_dsi_of_table); +- +-static struct platform_driver rzg2l_mipi_dsi_platform_driver = { +- .probe = rzg2l_mipi_dsi_probe, +- .remove_new = rzg2l_mipi_dsi_remove, +- .driver = { +- .name = "rzg2l-mipi-dsi", +- .pm = &rzg2l_mipi_pm_ops, +- .of_match_table = rzg2l_mipi_dsi_of_table, +- }, +-}; +- +-module_platform_driver(rzg2l_mipi_dsi_platform_driver); +- +-MODULE_AUTHOR("Biju Das "); +-MODULE_DESCRIPTION("Renesas RZ/G2L MIPI DSI Encoder Driver"); +-MODULE_LICENSE("GPL"); +--- a/drivers/gpu/drm/renesas/rcar-du/rzg2l_mipi_dsi_regs.h ++++ /dev/null +@@ -1,151 +0,0 @@ +-/* SPDX-License-Identifier: GPL-2.0 */ +-/* +- * RZ/G2L MIPI DSI Interface Registers Definitions +- * +- * Copyright (C) 2022 Renesas Electronics Corporation +- */ +- +-#ifndef __RZG2L_MIPI_DSI_REGS_H__ +-#define __RZG2L_MIPI_DSI_REGS_H__ +- +-#include +- +-/* DPHY Registers */ +-#define DSIDPHYCTRL0 0x00 +-#define DSIDPHYCTRL0_CAL_EN_HSRX_OFS BIT(16) +-#define DSIDPHYCTRL0_CMN_MASTER_EN BIT(8) +-#define DSIDPHYCTRL0_RE_VDD_DETVCCQLV18 BIT(2) +-#define DSIDPHYCTRL0_EN_LDO1200 BIT(1) +-#define DSIDPHYCTRL0_EN_BGR BIT(0) +- +-#define DSIDPHYTIM0 0x04 +-#define DSIDPHYTIM0_TCLK_MISS(x) ((x) << 24) +-#define DSIDPHYTIM0_T_INIT(x) ((x) << 0) +- +-#define DSIDPHYTIM1 0x08 +-#define DSIDPHYTIM1_THS_PREPARE(x) ((x) << 24) +-#define DSIDPHYTIM1_TCLK_PREPARE(x) ((x) << 16) +-#define DSIDPHYTIM1_THS_SETTLE(x) ((x) << 8) +-#define DSIDPHYTIM1_TCLK_SETTLE(x) ((x) << 0) +- +-#define DSIDPHYTIM2 0x0c +-#define DSIDPHYTIM2_TCLK_TRAIL(x) ((x) << 24) +-#define DSIDPHYTIM2_TCLK_POST(x) ((x) << 16) +-#define DSIDPHYTIM2_TCLK_PRE(x) ((x) << 8) +-#define DSIDPHYTIM2_TCLK_ZERO(x) ((x) << 0) +- +-#define DSIDPHYTIM3 0x10 +-#define DSIDPHYTIM3_TLPX(x) ((x) << 24) +-#define DSIDPHYTIM3_THS_EXIT(x) ((x) << 16) +-#define DSIDPHYTIM3_THS_TRAIL(x) ((x) << 8) +-#define DSIDPHYTIM3_THS_ZERO(x) ((x) << 0) +- +-/* --------------------------------------------------------*/ +-/* Link Registers */ +-#define LINK_REG_OFFSET 0x10000 +- +-/* Link Status Register */ +-#define LINKSR 0x10 +-#define LINKSR_LPBUSY BIT(13) +-#define LINKSR_HSBUSY BIT(12) +-#define LINKSR_VICHRUN1 BIT(8) +-#define LINKSR_SQCHRUN1 BIT(4) +-#define LINKSR_SQCHRUN0 BIT(0) +- +-/* Tx Set Register */ +-#define TXSETR 0x100 +-#define TXSETR_NUMLANECAP (0x3 << 16) +-#define TXSETR_DLEN (1 << 9) +-#define TXSETR_CLEN (1 << 8) +-#define TXSETR_NUMLANEUSE(x) (((x) & 0x3) << 0) +- +-/* HS Clock Set Register */ +-#define HSCLKSETR 0x104 +-#define HSCLKSETR_HSCLKMODE_CONT (1 << 1) +-#define HSCLKSETR_HSCLKMODE_NON_CONT (0 << 1) +-#define HSCLKSETR_HSCLKRUN_HS (1 << 0) +-#define HSCLKSETR_HSCLKRUN_LP (0 << 0) +- +-/* Reset Control Register */ +-#define RSTCR 0x110 +-#define RSTCR_SWRST BIT(0) +-#define RSTCR_FCETXSTP BIT(16) +- +-/* Reset Status Register */ +-#define RSTSR 0x114 +-#define RSTSR_DL0DIR (1 << 15) +-#define RSTSR_DLSTPST (0xf << 8) +-#define RSTSR_SWRSTV1 (1 << 4) +-#define RSTSR_SWRSTIB (1 << 3) +-#define RSTSR_SWRSTAPB (1 << 2) +-#define RSTSR_SWRSTLP (1 << 1) +-#define RSTSR_SWRSTHS (1 << 0) +- +-/* Clock Lane Stop Time Set Register */ +-#define CLSTPTSETR 0x314 +-#define CLSTPTSETR_CLKKPT(x) ((x) << 24) +-#define CLSTPTSETR_CLKBFHT(x) ((x) << 16) +-#define CLSTPTSETR_CLKSTPT(x) ((x) << 2) +- +-/* LP Transition Time Set Register */ +-#define LPTRNSTSETR 0x318 +-#define LPTRNSTSETR_GOLPBKT(x) ((x) << 0) +- +-/* Physical Lane Status Register */ +-#define PLSR 0x320 +-#define PLSR_CLHS2LP BIT(27) +-#define PLSR_CLLP2HS BIT(26) +- +-/* Video-Input Channel 1 Set 0 Register */ +-#define VICH1SET0R 0x400 +-#define VICH1SET0R_VSEN BIT(12) +-#define VICH1SET0R_HFPNOLP BIT(10) +-#define VICH1SET0R_HBPNOLP BIT(9) +-#define VICH1SET0R_HSANOLP BIT(8) +-#define VICH1SET0R_VSTPAFT BIT(1) +-#define VICH1SET0R_VSTART BIT(0) +- +-/* Video-Input Channel 1 Set 1 Register */ +-#define VICH1SET1R 0x404 +-#define VICH1SET1R_DLY(x) (((x) & 0xfff) << 2) +- +-/* Video-Input Channel 1 Status Register */ +-#define VICH1SR 0x410 +-#define VICH1SR_VIRDY BIT(3) +-#define VICH1SR_RUNNING BIT(2) +-#define VICH1SR_STOP BIT(1) +-#define VICH1SR_START BIT(0) +- +-/* Video-Input Channel 1 Pixel Packet Set Register */ +-#define VICH1PPSETR 0x420 +-#define VICH1PPSETR_DT_RGB18 (0x1e << 16) +-#define VICH1PPSETR_DT_RGB18_LS (0x2e << 16) +-#define VICH1PPSETR_DT_RGB24 (0x3e << 16) +-#define VICH1PPSETR_TXESYNC_PULSE (1 << 15) +-#define VICH1PPSETR_VC(x) ((x) << 22) +- +-/* Video-Input Channel 1 Vertical Size Set Register */ +-#define VICH1VSSETR 0x428 +-#define VICH1VSSETR_VACTIVE(x) (((x) & 0x7fff) << 16) +-#define VICH1VSSETR_VSPOL_LOW (1 << 15) +-#define VICH1VSSETR_VSPOL_HIGH (0 << 15) +-#define VICH1VSSETR_VSA(x) (((x) & 0xfff) << 0) +- +-/* Video-Input Channel 1 Vertical Porch Set Register */ +-#define VICH1VPSETR 0x42c +-#define VICH1VPSETR_VFP(x) (((x) & 0x1fff) << 16) +-#define VICH1VPSETR_VBP(x) (((x) & 0x1fff) << 0) +- +-/* Video-Input Channel 1 Horizontal Size Set Register */ +-#define VICH1HSSETR 0x430 +-#define VICH1HSSETR_HACTIVE(x) (((x) & 0x7fff) << 16) +-#define VICH1HSSETR_HSPOL_LOW (1 << 15) +-#define VICH1HSSETR_HSPOL_HIGH (0 << 15) +-#define VICH1HSSETR_HSA(x) (((x) & 0xfff) << 0) +- +-/* Video-Input Channel 1 Horizontal Porch Set Register */ +-#define VICH1HPSETR 0x434 +-#define VICH1HPSETR_HFP(x) (((x) & 0x1fff) << 16) +-#define VICH1HPSETR_HBP(x) (((x) & 0x1fff) << 0) +- +-#endif /* __RZG2L_MIPI_DSI_REGS_H__ */ +--- /dev/null ++++ b/drivers/gpu/drm/renesas/rz-du/Kconfig +@@ -0,0 +1,8 @@ ++# SPDX-License-Identifier: GPL-2.0 ++config DRM_RZG2L_MIPI_DSI ++ tristate "RZ/G2L MIPI DSI Encoder Support" ++ depends on DRM && DRM_BRIDGE && OF ++ depends on ARCH_RENESAS || COMPILE_TEST ++ select DRM_MIPI_DSI ++ help ++ Enable support for the RZ/G2L Display Unit embedded MIPI DSI encoders. +--- /dev/null ++++ b/drivers/gpu/drm/renesas/rz-du/Makefile +@@ -0,0 +1,3 @@ ++# SPDX-License-Identifier: GPL-2.0 ++ ++obj-$(CONFIG_DRM_RZG2L_MIPI_DSI) += rzg2l_mipi_dsi.o +--- /dev/null ++++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c +@@ -0,0 +1,816 @@ ++// SPDX-License-Identifier: GPL-2.0 ++/* ++ * RZ/G2L MIPI DSI Encoder Driver ++ * ++ * Copyright (C) 2022 Renesas Electronics Corporation ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "rzg2l_mipi_dsi_regs.h" ++ ++struct rzg2l_mipi_dsi { ++ struct device *dev; ++ void __iomem *mmio; ++ ++ struct reset_control *rstc; ++ struct reset_control *arstc; ++ struct reset_control *prstc; ++ ++ struct mipi_dsi_host host; ++ struct drm_bridge bridge; ++ struct drm_bridge *next_bridge; ++ ++ struct clk *vclk; ++ ++ enum mipi_dsi_pixel_format format; ++ unsigned int num_data_lanes; ++ unsigned int lanes; ++ unsigned long mode_flags; ++}; ++ ++static inline struct rzg2l_mipi_dsi * ++bridge_to_rzg2l_mipi_dsi(struct drm_bridge *bridge) ++{ ++ return container_of(bridge, struct rzg2l_mipi_dsi, bridge); ++} ++ ++static inline struct rzg2l_mipi_dsi * ++host_to_rzg2l_mipi_dsi(struct mipi_dsi_host *host) ++{ ++ return container_of(host, struct rzg2l_mipi_dsi, host); ++} ++ ++struct rzg2l_mipi_dsi_timings { ++ unsigned long hsfreq_max; ++ u32 t_init; ++ u32 tclk_prepare; ++ u32 ths_prepare; ++ u32 tclk_zero; ++ u32 tclk_pre; ++ u32 tclk_post; ++ u32 tclk_trail; ++ u32 ths_zero; ++ u32 ths_trail; ++ u32 ths_exit; ++ u32 tlpx; ++}; ++ ++static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = { ++ { ++ .hsfreq_max = 80000, ++ .t_init = 79801, ++ .tclk_prepare = 8, ++ .ths_prepare = 13, ++ .tclk_zero = 33, ++ .tclk_pre = 24, ++ .tclk_post = 94, ++ .tclk_trail = 10, ++ .ths_zero = 23, ++ .ths_trail = 17, ++ .ths_exit = 13, ++ .tlpx = 6, ++ }, ++ { ++ .hsfreq_max = 125000, ++ .t_init = 79801, ++ .tclk_prepare = 8, ++ .ths_prepare = 12, ++ .tclk_zero = 33, ++ .tclk_pre = 15, ++ .tclk_post = 94, ++ .tclk_trail = 10, ++ .ths_zero = 23, ++ .ths_trail = 17, ++ .ths_exit = 13, ++ .tlpx = 6, ++ }, ++ { ++ .hsfreq_max = 250000, ++ .t_init = 79801, ++ .tclk_prepare = 8, ++ .ths_prepare = 12, ++ .tclk_zero = 33, ++ .tclk_pre = 13, ++ .tclk_post = 94, ++ .tclk_trail = 10, ++ .ths_zero = 23, ++ .ths_trail = 16, ++ .ths_exit = 13, ++ .tlpx = 6, ++ }, ++ { ++ .hsfreq_max = 360000, ++ .t_init = 79801, ++ .tclk_prepare = 8, ++ .ths_prepare = 10, ++ .tclk_zero = 33, ++ .tclk_pre = 4, ++ .tclk_post = 35, ++ .tclk_trail = 7, ++ .ths_zero = 16, ++ .ths_trail = 9, ++ .ths_exit = 13, ++ .tlpx = 6, ++ }, ++ { ++ .hsfreq_max = 720000, ++ .t_init = 79801, ++ .tclk_prepare = 8, ++ .ths_prepare = 9, ++ .tclk_zero = 33, ++ .tclk_pre = 4, ++ .tclk_post = 35, ++ .tclk_trail = 7, ++ .ths_zero = 16, ++ .ths_trail = 9, ++ .ths_exit = 13, ++ .tlpx = 6, ++ }, ++ { ++ .hsfreq_max = 1500000, ++ .t_init = 79801, ++ .tclk_prepare = 8, ++ .ths_prepare = 9, ++ .tclk_zero = 33, ++ .tclk_pre = 4, ++ .tclk_post = 35, ++ .tclk_trail = 7, ++ .ths_zero = 16, ++ .ths_trail = 9, ++ .ths_exit = 13, ++ .tlpx = 6, ++ }, ++}; ++ ++static void rzg2l_mipi_dsi_phy_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data) ++{ ++ iowrite32(data, dsi->mmio + reg); ++} ++ ++static void rzg2l_mipi_dsi_link_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data) ++{ ++ iowrite32(data, dsi->mmio + LINK_REG_OFFSET + reg); ++} ++ ++static u32 rzg2l_mipi_dsi_phy_read(struct rzg2l_mipi_dsi *dsi, u32 reg) ++{ ++ return ioread32(dsi->mmio + reg); ++} ++ ++static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg) ++{ ++ return ioread32(dsi->mmio + LINK_REG_OFFSET + reg); ++} ++ ++/* ----------------------------------------------------------------------------- ++ * Hardware Setup ++ */ ++ ++static int rzg2l_mipi_dsi_dphy_init(struct rzg2l_mipi_dsi *dsi, ++ unsigned long hsfreq) ++{ ++ const struct rzg2l_mipi_dsi_timings *dphy_timings; ++ unsigned int i; ++ u32 dphyctrl0; ++ u32 dphytim0; ++ u32 dphytim1; ++ u32 dphytim2; ++ u32 dphytim3; ++ int ret; ++ ++ /* All DSI global operation timings are set with recommended setting */ ++ for (i = 0; i < ARRAY_SIZE(rzg2l_mipi_dsi_global_timings); ++i) { ++ dphy_timings = &rzg2l_mipi_dsi_global_timings[i]; ++ if (hsfreq <= dphy_timings->hsfreq_max) ++ break; ++ } ++ ++ /* Initializing DPHY before accessing LINK */ ++ dphyctrl0 = DSIDPHYCTRL0_CAL_EN_HSRX_OFS | DSIDPHYCTRL0_CMN_MASTER_EN | ++ DSIDPHYCTRL0_RE_VDD_DETVCCQLV18 | DSIDPHYCTRL0_EN_BGR; ++ ++ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0); ++ usleep_range(20, 30); ++ ++ dphyctrl0 |= DSIDPHYCTRL0_EN_LDO1200; ++ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0); ++ usleep_range(10, 20); ++ ++ dphytim0 = DSIDPHYTIM0_TCLK_MISS(0) | ++ DSIDPHYTIM0_T_INIT(dphy_timings->t_init); ++ dphytim1 = DSIDPHYTIM1_THS_PREPARE(dphy_timings->ths_prepare) | ++ DSIDPHYTIM1_TCLK_PREPARE(dphy_timings->tclk_prepare) | ++ DSIDPHYTIM1_THS_SETTLE(0) | ++ DSIDPHYTIM1_TCLK_SETTLE(0); ++ dphytim2 = DSIDPHYTIM2_TCLK_TRAIL(dphy_timings->tclk_trail) | ++ DSIDPHYTIM2_TCLK_POST(dphy_timings->tclk_post) | ++ DSIDPHYTIM2_TCLK_PRE(dphy_timings->tclk_pre) | ++ DSIDPHYTIM2_TCLK_ZERO(dphy_timings->tclk_zero); ++ dphytim3 = DSIDPHYTIM3_TLPX(dphy_timings->tlpx) | ++ DSIDPHYTIM3_THS_EXIT(dphy_timings->ths_exit) | ++ DSIDPHYTIM3_THS_TRAIL(dphy_timings->ths_trail) | ++ DSIDPHYTIM3_THS_ZERO(dphy_timings->ths_zero); ++ ++ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM0, dphytim0); ++ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM1, dphytim1); ++ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM2, dphytim2); ++ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM3, dphytim3); ++ ++ ret = reset_control_deassert(dsi->rstc); ++ if (ret < 0) ++ return ret; ++ ++ udelay(1); ++ ++ return 0; ++} ++ ++static void rzg2l_mipi_dsi_dphy_exit(struct rzg2l_mipi_dsi *dsi) ++{ ++ u32 dphyctrl0; ++ ++ dphyctrl0 = rzg2l_mipi_dsi_phy_read(dsi, DSIDPHYCTRL0); ++ ++ dphyctrl0 &= ~(DSIDPHYCTRL0_EN_LDO1200 | DSIDPHYCTRL0_EN_BGR); ++ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0); ++ ++ reset_control_assert(dsi->rstc); ++} ++ ++static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, ++ const struct drm_display_mode *mode) ++{ ++ unsigned long hsfreq; ++ unsigned int bpp; ++ u32 txsetr; ++ u32 clstptsetr; ++ u32 lptrnstsetr; ++ u32 clkkpt; ++ u32 clkbfht; ++ u32 clkstpt; ++ u32 golpbkt; ++ int ret; ++ ++ /* ++ * Relationship between hsclk and vclk must follow ++ * vclk * bpp = hsclk * 8 * lanes ++ * where vclk: video clock (Hz) ++ * bpp: video pixel bit depth ++ * hsclk: DSI HS Byte clock frequency (Hz) ++ * lanes: number of data lanes ++ * ++ * hsclk(bit) = hsclk(byte) * 8 ++ */ ++ bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); ++ hsfreq = (mode->clock * bpp * 8) / (8 * dsi->lanes); ++ ++ ret = pm_runtime_resume_and_get(dsi->dev); ++ if (ret < 0) ++ return ret; ++ ++ clk_set_rate(dsi->vclk, mode->clock * 1000); ++ ++ ret = rzg2l_mipi_dsi_dphy_init(dsi, hsfreq); ++ if (ret < 0) ++ goto err_phy; ++ ++ /* Enable Data lanes and Clock lanes */ ++ txsetr = TXSETR_DLEN | TXSETR_NUMLANEUSE(dsi->lanes - 1) | TXSETR_CLEN; ++ rzg2l_mipi_dsi_link_write(dsi, TXSETR, txsetr); ++ ++ /* ++ * Global timings characteristic depends on high speed Clock Frequency ++ * Currently MIPI DSI-IF just supports maximum FHD@60 with: ++ * - videoclock = 148.5 (MHz) ++ * - bpp: maximum 24bpp ++ * - data lanes: maximum 4 lanes ++ * Therefore maximum hsclk will be 891 Mbps. ++ */ ++ if (hsfreq > 445500) { ++ clkkpt = 12; ++ clkbfht = 15; ++ clkstpt = 48; ++ golpbkt = 75; ++ } else if (hsfreq > 250000) { ++ clkkpt = 7; ++ clkbfht = 8; ++ clkstpt = 27; ++ golpbkt = 40; ++ } else { ++ clkkpt = 8; ++ clkbfht = 6; ++ clkstpt = 24; ++ golpbkt = 29; ++ } ++ ++ clstptsetr = CLSTPTSETR_CLKKPT(clkkpt) | CLSTPTSETR_CLKBFHT(clkbfht) | ++ CLSTPTSETR_CLKSTPT(clkstpt); ++ rzg2l_mipi_dsi_link_write(dsi, CLSTPTSETR, clstptsetr); ++ ++ lptrnstsetr = LPTRNSTSETR_GOLPBKT(golpbkt); ++ rzg2l_mipi_dsi_link_write(dsi, LPTRNSTSETR, lptrnstsetr); ++ ++ return 0; ++ ++err_phy: ++ rzg2l_mipi_dsi_dphy_exit(dsi); ++ pm_runtime_put(dsi->dev); ++ ++ return ret; ++} ++ ++static void rzg2l_mipi_dsi_stop(struct rzg2l_mipi_dsi *dsi) ++{ ++ rzg2l_mipi_dsi_dphy_exit(dsi); ++ pm_runtime_put(dsi->dev); ++} ++ ++static void rzg2l_mipi_dsi_set_display_timing(struct rzg2l_mipi_dsi *dsi, ++ const struct drm_display_mode *mode) ++{ ++ u32 vich1ppsetr; ++ u32 vich1vssetr; ++ u32 vich1vpsetr; ++ u32 vich1hssetr; ++ u32 vich1hpsetr; ++ int dsi_format; ++ u32 delay[2]; ++ u8 index; ++ ++ /* Configuration for Pixel Packet */ ++ dsi_format = mipi_dsi_pixel_format_to_bpp(dsi->format); ++ switch (dsi_format) { ++ case 24: ++ vich1ppsetr = VICH1PPSETR_DT_RGB24; ++ break; ++ case 18: ++ vich1ppsetr = VICH1PPSETR_DT_RGB18; ++ break; ++ } ++ ++ if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) && ++ !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)) ++ vich1ppsetr |= VICH1PPSETR_TXESYNC_PULSE; ++ ++ rzg2l_mipi_dsi_link_write(dsi, VICH1PPSETR, vich1ppsetr); ++ ++ /* Configuration for Video Parameters */ ++ vich1vssetr = VICH1VSSETR_VACTIVE(mode->vdisplay) | ++ VICH1VSSETR_VSA(mode->vsync_end - mode->vsync_start); ++ vich1vssetr |= (mode->flags & DRM_MODE_FLAG_PVSYNC) ? ++ VICH1VSSETR_VSPOL_HIGH : VICH1VSSETR_VSPOL_LOW; ++ ++ vich1vpsetr = VICH1VPSETR_VFP(mode->vsync_start - mode->vdisplay) | ++ VICH1VPSETR_VBP(mode->vtotal - mode->vsync_end); ++ ++ vich1hssetr = VICH1HSSETR_HACTIVE(mode->hdisplay) | ++ VICH1HSSETR_HSA(mode->hsync_end - mode->hsync_start); ++ vich1hssetr |= (mode->flags & DRM_MODE_FLAG_PHSYNC) ? ++ VICH1HSSETR_HSPOL_HIGH : VICH1HSSETR_HSPOL_LOW; ++ ++ vich1hpsetr = VICH1HPSETR_HFP(mode->hsync_start - mode->hdisplay) | ++ VICH1HPSETR_HBP(mode->htotal - mode->hsync_end); ++ ++ rzg2l_mipi_dsi_link_write(dsi, VICH1VSSETR, vich1vssetr); ++ rzg2l_mipi_dsi_link_write(dsi, VICH1VPSETR, vich1vpsetr); ++ rzg2l_mipi_dsi_link_write(dsi, VICH1HSSETR, vich1hssetr); ++ rzg2l_mipi_dsi_link_write(dsi, VICH1HPSETR, vich1hpsetr); ++ ++ /* ++ * Configuration for Delay Value ++ * Delay value based on 2 ranges of video clock. ++ * 74.25MHz is videoclock of HD@60p or FHD@30p ++ */ ++ if (mode->clock > 74250) { ++ delay[0] = 231; ++ delay[1] = 216; ++ } else { ++ delay[0] = 220; ++ delay[1] = 212; ++ } ++ ++ if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) ++ index = 0; ++ else ++ index = 1; ++ ++ rzg2l_mipi_dsi_link_write(dsi, VICH1SET1R, ++ VICH1SET1R_DLY(delay[index])); ++} ++ ++static int rzg2l_mipi_dsi_start_hs_clock(struct rzg2l_mipi_dsi *dsi) ++{ ++ bool is_clk_cont; ++ u32 hsclksetr; ++ u32 status; ++ int ret; ++ ++ is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS); ++ ++ /* Start HS clock */ ++ hsclksetr = HSCLKSETR_HSCLKRUN_HS | (is_clk_cont ? ++ HSCLKSETR_HSCLKMODE_CONT : ++ HSCLKSETR_HSCLKMODE_NON_CONT); ++ rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR, hsclksetr); ++ ++ if (is_clk_cont) { ++ ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status, ++ status & PLSR_CLLP2HS, ++ 2000, 20000, false, dsi, PLSR); ++ if (ret < 0) { ++ dev_err(dsi->dev, "failed to start HS clock\n"); ++ return ret; ++ } ++ } ++ ++ dev_dbg(dsi->dev, "Start High Speed Clock with %s clock mode", ++ is_clk_cont ? "continuous" : "non-continuous"); ++ ++ return 0; ++} ++ ++static int rzg2l_mipi_dsi_stop_hs_clock(struct rzg2l_mipi_dsi *dsi) ++{ ++ bool is_clk_cont; ++ u32 status; ++ int ret; ++ ++ is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS); ++ ++ /* Stop HS clock */ ++ rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR, ++ is_clk_cont ? HSCLKSETR_HSCLKMODE_CONT : ++ HSCLKSETR_HSCLKMODE_NON_CONT); ++ ++ if (is_clk_cont) { ++ ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status, ++ status & PLSR_CLHS2LP, ++ 2000, 20000, false, dsi, PLSR); ++ if (ret < 0) { ++ dev_err(dsi->dev, "failed to stop HS clock\n"); ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++static int rzg2l_mipi_dsi_start_video(struct rzg2l_mipi_dsi *dsi) ++{ ++ u32 vich1set0r; ++ u32 status; ++ int ret; ++ ++ /* Configuration for Blanking sequence and start video input*/ ++ vich1set0r = VICH1SET0R_HFPNOLP | VICH1SET0R_HBPNOLP | ++ VICH1SET0R_HSANOLP | VICH1SET0R_VSTART; ++ rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, vich1set0r); ++ ++ ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status, ++ status & VICH1SR_VIRDY, ++ 2000, 20000, false, dsi, VICH1SR); ++ if (ret < 0) ++ dev_err(dsi->dev, "Failed to start video signal input\n"); ++ ++ return ret; ++} ++ ++static int rzg2l_mipi_dsi_stop_video(struct rzg2l_mipi_dsi *dsi) ++{ ++ u32 status; ++ int ret; ++ ++ rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, VICH1SET0R_VSTPAFT); ++ ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status, ++ (status & VICH1SR_STOP) && (!(status & VICH1SR_RUNNING)), ++ 2000, 20000, false, dsi, VICH1SR); ++ if (ret < 0) ++ goto err; ++ ++ ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status, ++ !(status & LINKSR_HSBUSY), ++ 2000, 20000, false, dsi, LINKSR); ++ if (ret < 0) ++ goto err; ++ ++ return 0; ++ ++err: ++ dev_err(dsi->dev, "Failed to stop video signal input\n"); ++ return ret; ++} ++ ++/* ----------------------------------------------------------------------------- ++ * Bridge ++ */ ++ ++static int rzg2l_mipi_dsi_attach(struct drm_bridge *bridge, ++ enum drm_bridge_attach_flags flags) ++{ ++ struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge); ++ ++ return drm_bridge_attach(bridge->encoder, dsi->next_bridge, bridge, ++ flags); ++} ++ ++static void rzg2l_mipi_dsi_atomic_enable(struct drm_bridge *bridge, ++ struct drm_bridge_state *old_bridge_state) ++{ ++ struct drm_atomic_state *state = old_bridge_state->base.state; ++ struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge); ++ const struct drm_display_mode *mode; ++ struct drm_connector *connector; ++ struct drm_crtc *crtc; ++ int ret; ++ ++ connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); ++ crtc = drm_atomic_get_new_connector_state(state, connector)->crtc; ++ mode = &drm_atomic_get_new_crtc_state(state, crtc)->adjusted_mode; ++ ++ ret = rzg2l_mipi_dsi_startup(dsi, mode); ++ if (ret < 0) ++ return; ++ ++ rzg2l_mipi_dsi_set_display_timing(dsi, mode); ++ ++ ret = rzg2l_mipi_dsi_start_hs_clock(dsi); ++ if (ret < 0) ++ goto err_stop; ++ ++ ret = rzg2l_mipi_dsi_start_video(dsi); ++ if (ret < 0) ++ goto err_stop_clock; ++ ++ return; ++ ++err_stop_clock: ++ rzg2l_mipi_dsi_stop_hs_clock(dsi); ++err_stop: ++ rzg2l_mipi_dsi_stop(dsi); ++} ++ ++static void rzg2l_mipi_dsi_atomic_disable(struct drm_bridge *bridge, ++ struct drm_bridge_state *old_bridge_state) ++{ ++ struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge); ++ ++ rzg2l_mipi_dsi_stop_video(dsi); ++ rzg2l_mipi_dsi_stop_hs_clock(dsi); ++ rzg2l_mipi_dsi_stop(dsi); ++} ++ ++static enum drm_mode_status ++rzg2l_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge, ++ const struct drm_display_info *info, ++ const struct drm_display_mode *mode) ++{ ++ if (mode->clock > 148500) ++ return MODE_CLOCK_HIGH; ++ ++ if (mode->clock < 5803) ++ return MODE_CLOCK_LOW; ++ ++ return MODE_OK; ++} ++ ++static const struct drm_bridge_funcs rzg2l_mipi_dsi_bridge_ops = { ++ .attach = rzg2l_mipi_dsi_attach, ++ .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, ++ .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, ++ .atomic_reset = drm_atomic_helper_bridge_reset, ++ .atomic_enable = rzg2l_mipi_dsi_atomic_enable, ++ .atomic_disable = rzg2l_mipi_dsi_atomic_disable, ++ .mode_valid = rzg2l_mipi_dsi_bridge_mode_valid, ++}; ++ ++/* ----------------------------------------------------------------------------- ++ * Host setting ++ */ ++ ++static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host, ++ struct mipi_dsi_device *device) ++{ ++ struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host); ++ int ret; ++ ++ if (device->lanes > dsi->num_data_lanes) { ++ dev_err(dsi->dev, ++ "Number of lines of device (%u) exceeds host (%u)\n", ++ device->lanes, dsi->num_data_lanes); ++ return -EINVAL; ++ } ++ ++ switch (mipi_dsi_pixel_format_to_bpp(device->format)) { ++ case 24: ++ case 18: ++ break; ++ default: ++ dev_err(dsi->dev, "Unsupported format 0x%04x\n", device->format); ++ return -EINVAL; ++ } ++ ++ dsi->lanes = device->lanes; ++ dsi->format = device->format; ++ dsi->mode_flags = device->mode_flags; ++ ++ dsi->next_bridge = devm_drm_of_get_bridge(dsi->dev, dsi->dev->of_node, ++ 1, 0); ++ if (IS_ERR(dsi->next_bridge)) { ++ ret = PTR_ERR(dsi->next_bridge); ++ dev_err(dsi->dev, "failed to get next bridge: %d\n", ret); ++ return ret; ++ } ++ ++ drm_bridge_add(&dsi->bridge); ++ ++ return 0; ++} ++ ++static int rzg2l_mipi_dsi_host_detach(struct mipi_dsi_host *host, ++ struct mipi_dsi_device *device) ++{ ++ struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host); ++ ++ drm_bridge_remove(&dsi->bridge); ++ ++ return 0; ++} ++ ++static const struct mipi_dsi_host_ops rzg2l_mipi_dsi_host_ops = { ++ .attach = rzg2l_mipi_dsi_host_attach, ++ .detach = rzg2l_mipi_dsi_host_detach, ++}; ++ ++/* ----------------------------------------------------------------------------- ++ * Power Management ++ */ ++ ++static int __maybe_unused rzg2l_mipi_pm_runtime_suspend(struct device *dev) ++{ ++ struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev); ++ ++ reset_control_assert(dsi->prstc); ++ reset_control_assert(dsi->arstc); ++ ++ return 0; ++} ++ ++static int __maybe_unused rzg2l_mipi_pm_runtime_resume(struct device *dev) ++{ ++ struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev); ++ int ret; ++ ++ ret = reset_control_deassert(dsi->arstc); ++ if (ret < 0) ++ return ret; ++ ++ ret = reset_control_deassert(dsi->prstc); ++ if (ret < 0) ++ reset_control_assert(dsi->arstc); ++ ++ return ret; ++} ++ ++static const struct dev_pm_ops rzg2l_mipi_pm_ops = { ++ SET_RUNTIME_PM_OPS(rzg2l_mipi_pm_runtime_suspend, rzg2l_mipi_pm_runtime_resume, NULL) ++}; ++ ++/* ----------------------------------------------------------------------------- ++ * Probe & Remove ++ */ ++ ++static int rzg2l_mipi_dsi_probe(struct platform_device *pdev) ++{ ++ unsigned int num_data_lanes; ++ struct rzg2l_mipi_dsi *dsi; ++ u32 txsetr; ++ int ret; ++ ++ dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL); ++ if (!dsi) ++ return -ENOMEM; ++ ++ platform_set_drvdata(pdev, dsi); ++ dsi->dev = &pdev->dev; ++ ++ ret = drm_of_get_data_lanes_count_ep(dsi->dev->of_node, 1, 0, 1, 4); ++ if (ret < 0) ++ return dev_err_probe(dsi->dev, ret, ++ "missing or invalid data-lanes property\n"); ++ ++ num_data_lanes = ret; ++ ++ dsi->mmio = devm_platform_ioremap_resource(pdev, 0); ++ if (IS_ERR(dsi->mmio)) ++ return PTR_ERR(dsi->mmio); ++ ++ dsi->vclk = devm_clk_get(dsi->dev, "vclk"); ++ if (IS_ERR(dsi->vclk)) ++ return PTR_ERR(dsi->vclk); ++ ++ dsi->rstc = devm_reset_control_get_exclusive(dsi->dev, "rst"); ++ if (IS_ERR(dsi->rstc)) ++ return dev_err_probe(dsi->dev, PTR_ERR(dsi->rstc), ++ "failed to get rst\n"); ++ ++ dsi->arstc = devm_reset_control_get_exclusive(dsi->dev, "arst"); ++ if (IS_ERR(dsi->arstc)) ++ return dev_err_probe(&pdev->dev, PTR_ERR(dsi->arstc), ++ "failed to get arst\n"); ++ ++ dsi->prstc = devm_reset_control_get_exclusive(dsi->dev, "prst"); ++ if (IS_ERR(dsi->prstc)) ++ return dev_err_probe(dsi->dev, PTR_ERR(dsi->prstc), ++ "failed to get prst\n"); ++ ++ platform_set_drvdata(pdev, dsi); ++ ++ pm_runtime_enable(dsi->dev); ++ ++ ret = pm_runtime_resume_and_get(dsi->dev); ++ if (ret < 0) ++ goto err_pm_disable; ++ ++ /* ++ * TXSETR register can be read only after DPHY init. But during probe ++ * mode->clock and format are not available. So initialize DPHY with ++ * timing parameters for 80Mbps. ++ */ ++ ret = rzg2l_mipi_dsi_dphy_init(dsi, 80000); ++ if (ret < 0) ++ goto err_phy; ++ ++ txsetr = rzg2l_mipi_dsi_link_read(dsi, TXSETR); ++ dsi->num_data_lanes = min(((txsetr >> 16) & 3) + 1, num_data_lanes); ++ rzg2l_mipi_dsi_dphy_exit(dsi); ++ pm_runtime_put(dsi->dev); ++ ++ /* Initialize the DRM bridge. */ ++ dsi->bridge.funcs = &rzg2l_mipi_dsi_bridge_ops; ++ dsi->bridge.of_node = dsi->dev->of_node; ++ ++ /* Init host device */ ++ dsi->host.dev = dsi->dev; ++ dsi->host.ops = &rzg2l_mipi_dsi_host_ops; ++ ret = mipi_dsi_host_register(&dsi->host); ++ if (ret < 0) ++ goto err_pm_disable; ++ ++ return 0; ++ ++err_phy: ++ rzg2l_mipi_dsi_dphy_exit(dsi); ++ pm_runtime_put(dsi->dev); ++err_pm_disable: ++ pm_runtime_disable(dsi->dev); ++ return ret; ++} ++ ++static void rzg2l_mipi_dsi_remove(struct platform_device *pdev) ++{ ++ struct rzg2l_mipi_dsi *dsi = platform_get_drvdata(pdev); ++ ++ mipi_dsi_host_unregister(&dsi->host); ++ pm_runtime_disable(&pdev->dev); ++} ++ ++static const struct of_device_id rzg2l_mipi_dsi_of_table[] = { ++ { .compatible = "renesas,rzg2l-mipi-dsi" }, ++ { /* sentinel */ } ++}; ++ ++MODULE_DEVICE_TABLE(of, rzg2l_mipi_dsi_of_table); ++ ++static struct platform_driver rzg2l_mipi_dsi_platform_driver = { ++ .probe = rzg2l_mipi_dsi_probe, ++ .remove_new = rzg2l_mipi_dsi_remove, ++ .driver = { ++ .name = "rzg2l-mipi-dsi", ++ .pm = &rzg2l_mipi_pm_ops, ++ .of_match_table = rzg2l_mipi_dsi_of_table, ++ }, ++}; ++ ++module_platform_driver(rzg2l_mipi_dsi_platform_driver); ++ ++MODULE_AUTHOR("Biju Das "); ++MODULE_DESCRIPTION("Renesas RZ/G2L MIPI DSI Encoder Driver"); ++MODULE_LICENSE("GPL"); +--- /dev/null ++++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h +@@ -0,0 +1,151 @@ ++/* SPDX-License-Identifier: GPL-2.0 */ ++/* ++ * RZ/G2L MIPI DSI Interface Registers Definitions ++ * ++ * Copyright (C) 2022 Renesas Electronics Corporation ++ */ ++ ++#ifndef __RZG2L_MIPI_DSI_REGS_H__ ++#define __RZG2L_MIPI_DSI_REGS_H__ ++ ++#include ++ ++/* DPHY Registers */ ++#define DSIDPHYCTRL0 0x00 ++#define DSIDPHYCTRL0_CAL_EN_HSRX_OFS BIT(16) ++#define DSIDPHYCTRL0_CMN_MASTER_EN BIT(8) ++#define DSIDPHYCTRL0_RE_VDD_DETVCCQLV18 BIT(2) ++#define DSIDPHYCTRL0_EN_LDO1200 BIT(1) ++#define DSIDPHYCTRL0_EN_BGR BIT(0) ++ ++#define DSIDPHYTIM0 0x04 ++#define DSIDPHYTIM0_TCLK_MISS(x) ((x) << 24) ++#define DSIDPHYTIM0_T_INIT(x) ((x) << 0) ++ ++#define DSIDPHYTIM1 0x08 ++#define DSIDPHYTIM1_THS_PREPARE(x) ((x) << 24) ++#define DSIDPHYTIM1_TCLK_PREPARE(x) ((x) << 16) ++#define DSIDPHYTIM1_THS_SETTLE(x) ((x) << 8) ++#define DSIDPHYTIM1_TCLK_SETTLE(x) ((x) << 0) ++ ++#define DSIDPHYTIM2 0x0c ++#define DSIDPHYTIM2_TCLK_TRAIL(x) ((x) << 24) ++#define DSIDPHYTIM2_TCLK_POST(x) ((x) << 16) ++#define DSIDPHYTIM2_TCLK_PRE(x) ((x) << 8) ++#define DSIDPHYTIM2_TCLK_ZERO(x) ((x) << 0) ++ ++#define DSIDPHYTIM3 0x10 ++#define DSIDPHYTIM3_TLPX(x) ((x) << 24) ++#define DSIDPHYTIM3_THS_EXIT(x) ((x) << 16) ++#define DSIDPHYTIM3_THS_TRAIL(x) ((x) << 8) ++#define DSIDPHYTIM3_THS_ZERO(x) ((x) << 0) ++ ++/* --------------------------------------------------------*/ ++/* Link Registers */ ++#define LINK_REG_OFFSET 0x10000 ++ ++/* Link Status Register */ ++#define LINKSR 0x10 ++#define LINKSR_LPBUSY BIT(13) ++#define LINKSR_HSBUSY BIT(12) ++#define LINKSR_VICHRUN1 BIT(8) ++#define LINKSR_SQCHRUN1 BIT(4) ++#define LINKSR_SQCHRUN0 BIT(0) ++ ++/* Tx Set Register */ ++#define TXSETR 0x100 ++#define TXSETR_NUMLANECAP (0x3 << 16) ++#define TXSETR_DLEN (1 << 9) ++#define TXSETR_CLEN (1 << 8) ++#define TXSETR_NUMLANEUSE(x) (((x) & 0x3) << 0) ++ ++/* HS Clock Set Register */ ++#define HSCLKSETR 0x104 ++#define HSCLKSETR_HSCLKMODE_CONT (1 << 1) ++#define HSCLKSETR_HSCLKMODE_NON_CONT (0 << 1) ++#define HSCLKSETR_HSCLKRUN_HS (1 << 0) ++#define HSCLKSETR_HSCLKRUN_LP (0 << 0) ++ ++/* Reset Control Register */ ++#define RSTCR 0x110 ++#define RSTCR_SWRST BIT(0) ++#define RSTCR_FCETXSTP BIT(16) ++ ++/* Reset Status Register */ ++#define RSTSR 0x114 ++#define RSTSR_DL0DIR (1 << 15) ++#define RSTSR_DLSTPST (0xf << 8) ++#define RSTSR_SWRSTV1 (1 << 4) ++#define RSTSR_SWRSTIB (1 << 3) ++#define RSTSR_SWRSTAPB (1 << 2) ++#define RSTSR_SWRSTLP (1 << 1) ++#define RSTSR_SWRSTHS (1 << 0) ++ ++/* Clock Lane Stop Time Set Register */ ++#define CLSTPTSETR 0x314 ++#define CLSTPTSETR_CLKKPT(x) ((x) << 24) ++#define CLSTPTSETR_CLKBFHT(x) ((x) << 16) ++#define CLSTPTSETR_CLKSTPT(x) ((x) << 2) ++ ++/* LP Transition Time Set Register */ ++#define LPTRNSTSETR 0x318 ++#define LPTRNSTSETR_GOLPBKT(x) ((x) << 0) ++ ++/* Physical Lane Status Register */ ++#define PLSR 0x320 ++#define PLSR_CLHS2LP BIT(27) ++#define PLSR_CLLP2HS BIT(26) ++ ++/* Video-Input Channel 1 Set 0 Register */ ++#define VICH1SET0R 0x400 ++#define VICH1SET0R_VSEN BIT(12) ++#define VICH1SET0R_HFPNOLP BIT(10) ++#define VICH1SET0R_HBPNOLP BIT(9) ++#define VICH1SET0R_HSANOLP BIT(8) ++#define VICH1SET0R_VSTPAFT BIT(1) ++#define VICH1SET0R_VSTART BIT(0) ++ ++/* Video-Input Channel 1 Set 1 Register */ ++#define VICH1SET1R 0x404 ++#define VICH1SET1R_DLY(x) (((x) & 0xfff) << 2) ++ ++/* Video-Input Channel 1 Status Register */ ++#define VICH1SR 0x410 ++#define VICH1SR_VIRDY BIT(3) ++#define VICH1SR_RUNNING BIT(2) ++#define VICH1SR_STOP BIT(1) ++#define VICH1SR_START BIT(0) ++ ++/* Video-Input Channel 1 Pixel Packet Set Register */ ++#define VICH1PPSETR 0x420 ++#define VICH1PPSETR_DT_RGB18 (0x1e << 16) ++#define VICH1PPSETR_DT_RGB18_LS (0x2e << 16) ++#define VICH1PPSETR_DT_RGB24 (0x3e << 16) ++#define VICH1PPSETR_TXESYNC_PULSE (1 << 15) ++#define VICH1PPSETR_VC(x) ((x) << 22) ++ ++/* Video-Input Channel 1 Vertical Size Set Register */ ++#define VICH1VSSETR 0x428 ++#define VICH1VSSETR_VACTIVE(x) (((x) & 0x7fff) << 16) ++#define VICH1VSSETR_VSPOL_LOW (1 << 15) ++#define VICH1VSSETR_VSPOL_HIGH (0 << 15) ++#define VICH1VSSETR_VSA(x) (((x) & 0xfff) << 0) ++ ++/* Video-Input Channel 1 Vertical Porch Set Register */ ++#define VICH1VPSETR 0x42c ++#define VICH1VPSETR_VFP(x) (((x) & 0x1fff) << 16) ++#define VICH1VPSETR_VBP(x) (((x) & 0x1fff) << 0) ++ ++/* Video-Input Channel 1 Horizontal Size Set Register */ ++#define VICH1HSSETR 0x430 ++#define VICH1HSSETR_HACTIVE(x) (((x) & 0x7fff) << 16) ++#define VICH1HSSETR_HSPOL_LOW (1 << 15) ++#define VICH1HSSETR_HSPOL_HIGH (0 << 15) ++#define VICH1HSSETR_HSA(x) (((x) & 0xfff) << 0) ++ ++/* Video-Input Channel 1 Horizontal Porch Set Register */ ++#define VICH1HPSETR 0x434 ++#define VICH1HPSETR_HFP(x) (((x) & 0x1fff) << 16) ++#define VICH1HPSETR_HBP(x) (((x) & 0x1fff) << 0) ++ ++#endif /* __RZG2L_MIPI_DSI_REGS_H__ */ diff --git a/queue-6.6/drm-renesas-rzg2l_mipi_dsi-increase-reset-deassertion-delay.patch b/queue-6.6/drm-renesas-rzg2l_mipi_dsi-increase-reset-deassertion-delay.patch new file mode 100644 index 0000000000..d72ba091d6 --- /dev/null +++ b/queue-6.6/drm-renesas-rzg2l_mipi_dsi-increase-reset-deassertion-delay.patch @@ -0,0 +1,40 @@ +From stable+bounces-293838-greg=kroah.com@vger.kernel.org Thu Jul 30 21:39:33 2026 +From: Sasha Levin +Date: Thu, 30 Jul 2026 15:29:55 -0400 +Subject: drm: renesas: rzg2l_mipi_dsi: Increase reset deassertion delay +To: stable@vger.kernel.org +Cc: Biju Das , Tommaso Merciai , Sasha Levin +Message-ID: <20260730192955.3124753-2-sashal@kernel.org> + +From: Biju Das + +[ Upstream commit 7cbba8a8ba0219a267844d3116dbc77cecb4fcf8 ] + +The RZ/G2L hardware manual (Rev. 1.50, May 2025), Section 34.4.2.1, +requires waiting at least 1 msec after deasserting the CMN_RSTB signal +before the DSI-Tx module is ready. Increase the delay from 1 usec to +1 msec by replacing udelay(1) with fsleep(1000) for RZ/G2L SoCs. + +Fixes: 7a043f978ed1 ("drm: rcar-du: Add RZ/G2L DSI driver") +Cc: stable@vger.kernel.org +Reviewed-by: Tommaso Merciai +Tested-by: Tommaso Merciai +Link: https://patch.msgid.link/20260330104450.128512-3-biju.das.jz@bp.renesas.com +Signed-off-by: Biju Das +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c ++++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c +@@ -238,7 +238,7 @@ static int rzg2l_mipi_dsi_dphy_init(stru + if (ret < 0) + return ret; + +- udelay(1); ++ fsleep(1000); + + return 0; + } diff --git a/queue-6.6/drm-tegra-fbdev-remove-offset-into-framebuffer-memory.patch b/queue-6.6/drm-tegra-fbdev-remove-offset-into-framebuffer-memory.patch new file mode 100644 index 0000000000..be64e37d18 --- /dev/null +++ b/queue-6.6/drm-tegra-fbdev-remove-offset-into-framebuffer-memory.patch @@ -0,0 +1,61 @@ +From stable+bounces-294127-greg=kroah.com@vger.kernel.org Fri Jul 31 18:00:34 2026 +From: Sasha Levin +Date: Fri, 31 Jul 2026 11:50:20 -0400 +Subject: drm/tegra: fbdev: Remove offset into framebuffer memory +To: stable@vger.kernel.org +Cc: Thomas Zimmermann , dri-devel@lists.freedesktop.org, linux-tegra@vger.kernel.org, Thierry Reding , Sasha Levin +Message-ID: <20260731155020.604703-2-sashal@kernel.org> + +From: Thomas Zimmermann + +[ Upstream commit a18b6e30ecd69096beda4a0c96d2570900c3879a ] + +The screen_buffer field in struct fb_info contains the kernel address +of the first byte of framebuffer memory. Do not add the display offset. +This offset only describes scrolling during scanout. + +Signed-off-by: Thomas Zimmermann +Fixes: de2ba664c30f ("gpu: host1x: drm: Add memory manager and fb") +Cc: dri-devel@lists.freedesktop.org +Cc: linux-tegra@vger.kernel.org +Cc: # v3.10+ +Signed-off-by: Thierry Reding +Link: https://patch.msgid.link/20260421073646.144712-3-tzimmermann@suse.de +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/tegra/fbdev.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/tegra/fbdev.c ++++ b/drivers/gpu/drm/tegra/fbdev.c +@@ -75,7 +75,6 @@ static int tegra_fbdev_probe(struct drm_ + struct fb_info *info = helper->info; + unsigned int bytes_per_pixel; + struct drm_framebuffer *fb; +- unsigned long offset; + struct tegra_bo *bo; + size_t size; + int err; +@@ -112,9 +111,6 @@ static int tegra_fbdev_probe(struct drm_ + + drm_fb_helper_fill_info(info, helper, sizes); + +- offset = info->var.xoffset * bytes_per_pixel + +- info->var.yoffset * fb->pitches[0]; +- + if (bo->pages) { + bo->vaddr = vmap(bo->pages, bo->num_pages, VM_MAP, + pgprot_writecombine(PAGE_KERNEL)); +@@ -126,9 +122,9 @@ static int tegra_fbdev_probe(struct drm_ + } + + info->flags |= FBINFO_VIRTFB; +- info->screen_buffer = bo->vaddr + offset; ++ info->screen_buffer = bo->vaddr; + info->screen_size = size; +- info->fix.smem_start = (unsigned long)(bo->iova + offset); ++ info->fix.smem_start = (unsigned long)(bo->iova); + info->fix.smem_len = size; + + return 0; diff --git a/queue-6.6/libceph-add-doutc-and-_client-debug-macros-support.patch b/queue-6.6/libceph-add-doutc-and-_client-debug-macros-support.patch new file mode 100644 index 0000000000..392988e2a9 --- /dev/null +++ b/queue-6.6/libceph-add-doutc-and-_client-debug-macros-support.patch @@ -0,0 +1,91 @@ +From stable+bounces-297277-greg=kroah.com@vger.kernel.org Fri Aug 7 13:51:19 2026 +From: Sasha Levin +Date: Fri, 7 Aug 2026 07:48:06 -0400 +Subject: libceph: add doutc and *_client debug macros support +To: stable@vger.kernel.org +Cc: Xiubo Li , Patrick Donnelly , Milind Changire , Ilya Dryomov , Sasha Levin +Message-ID: <20260807114809.2056244-1-sashal@kernel.org> + +From: Xiubo Li + +[ 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 ] + +Link: https://tracker.ceph.com/issues/61590 +Signed-off-by: Xiubo Li +Reviewed-by: Patrick Donnelly +Reviewed-by: Milind Changire +Signed-off-by: Ilya Dryomov +Stable-dep-of: c3e64079d8b9 ("ceph: fix refcount leak in ceph_readdir()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/ceph/ceph_debug.h | 38 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +--- a/include/linux/ceph/ceph_debug.h ++++ b/include/linux/ceph/ceph_debug.h +@@ -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 diff --git a/queue-6.6/media-i2c-imx219-access-height-from-active-format-in-imx219_set_ctrl.patch b/queue-6.6/media-i2c-imx219-access-height-from-active-format-in-imx219_set_ctrl.patch new file mode 100644 index 0000000000..439ebc5a6a --- /dev/null +++ b/queue-6.6/media-i2c-imx219-access-height-from-active-format-in-imx219_set_ctrl.patch @@ -0,0 +1,62 @@ +From stable+bounces-295114-greg=kroah.com@vger.kernel.org Tue Aug 4 13:08:19 2026 +From: Sasha Levin +Date: Tue, 4 Aug 2026 06:47:31 -0400 +Subject: media: i2c: imx219: Access height from active format in imx219_set_ctrl +To: stable@vger.kernel.org +Cc: Laurent Pinchart , Jacopo Mondi , Dave Stevenson , Sakari Ailus , Hans Verkuil , Sasha Levin +Message-ID: <20260804104737.2827302-1-sashal@kernel.org> + +From: Laurent Pinchart + +[ Upstream commit aa86ac42eec4dd7e987c12390a0a487187e2d9ae ] + +Use the active format height instead of the mode height in +imx219_set_ctrl(). This prepares for dropping the mode field from the +imx219 structure. + +The state is retrieved using v4l2_subdev_get_locked_active_state() as +the subdev active state and the control handler share the same lock. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Jacopo Mondi +Reviewed-by: Dave Stevenson +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Stable-dep-of: 2c4f1ba73543 ("media: imx219: Fix maximum frame length in lines") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/i2c/imx219.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +--- a/drivers/media/i2c/imx219.c ++++ b/drivers/media/i2c/imx219.c +@@ -500,13 +500,18 @@ static int imx219_set_ctrl(struct v4l2_c + struct imx219 *imx219 = + container_of(ctrl->handler, struct imx219, ctrl_handler); + struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); ++ const struct v4l2_mbus_framefmt *format; ++ struct v4l2_subdev_state *state; + int ret = 0; + ++ state = v4l2_subdev_get_locked_active_state(&imx219->sd); ++ format = v4l2_subdev_get_pad_format(&imx219->sd, state, 0); ++ + if (ctrl->id == V4L2_CID_VBLANK) { + int exposure_max, exposure_def; + + /* Update max exposure while meeting expected vblanking */ +- exposure_max = imx219->mode->height + ctrl->val - 4; ++ exposure_max = format->height + ctrl->val - 4; + exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ? + exposure_max : IMX219_EXPOSURE_DEFAULT; + __v4l2_ctrl_modify_range(imx219->exposure, +@@ -546,7 +551,7 @@ static int imx219_set_ctrl(struct v4l2_c + break; + case V4L2_CID_VBLANK: + cci_write(imx219->regmap, IMX219_REG_VTS, +- imx219->mode->height + ctrl->val, &ret); ++ format->height + ctrl->val, &ret); + break; + case V4L2_CID_TEST_PATTERN_RED: + cci_write(imx219->regmap, IMX219_REG_TESTP_RED, diff --git a/queue-6.6/media-i2c-imx219-calculate-crop-rectangle-dynamically.patch b/queue-6.6/media-i2c-imx219-calculate-crop-rectangle-dynamically.patch new file mode 100644 index 0000000000..e4c13be1ed --- /dev/null +++ b/queue-6.6/media-i2c-imx219-calculate-crop-rectangle-dynamically.patch @@ -0,0 +1,131 @@ +From stable+bounces-295119-greg=kroah.com@vger.kernel.org Tue Aug 4 12:57:41 2026 +From: Sasha Levin +Date: Tue, 4 Aug 2026 06:47:35 -0400 +Subject: media: i2c: imx219: Calculate crop rectangle dynamically +To: stable@vger.kernel.org +Cc: Laurent Pinchart , Jacopo Mondi , Sakari Ailus , Hans Verkuil , Sasha Levin +Message-ID: <20260804104737.2827302-5-sashal@kernel.org> + +From: Laurent Pinchart + +[ Upstream commit 0af46fbc333d1a52c72823d935590410357bab47 ] + +Calculate the crop rectangle size and location dynamically when setting +the format, instead of storing it in the imx219_mode structure. This +removes duplicated information from the mode, to guarantee consistency. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Jacopo Mondi +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Stable-dep-of: 2c4f1ba73543 ("media: imx219: Fix maximum frame length in lines") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/i2c/imx219.c | 45 +++++++++++++++------------------------------ + 1 file changed, 15 insertions(+), 30 deletions(-) + +--- a/drivers/media/i2c/imx219.c ++++ b/drivers/media/i2c/imx219.c +@@ -18,6 +18,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -161,9 +162,6 @@ struct imx219_mode { + /* Frame height */ + unsigned int height; + +- /* Analog crop rectangle. */ +- struct v4l2_rect crop; +- + /* V-timing */ + unsigned int vts_def; + +@@ -365,12 +363,6 @@ static const struct imx219_mode supporte + /* 8MPix 15fps mode */ + .width = 3280, + .height = 2464, +- .crop = { +- .left = IMX219_PIXEL_ARRAY_LEFT, +- .top = IMX219_PIXEL_ARRAY_TOP, +- .width = 3280, +- .height = 2464 +- }, + .vts_def = 3526, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs), +@@ -382,12 +374,6 @@ static const struct imx219_mode supporte + /* 1080P 30fps cropped */ + .width = 1920, + .height = 1080, +- .crop = { +- .left = 688, +- .top = 700, +- .width = 1920, +- .height = 1080 +- }, + .vts_def = 1763, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1920_1080_regs), +@@ -399,12 +385,6 @@ static const struct imx219_mode supporte + /* 2x2 binned 30fps mode */ + .width = 1640, + .height = 1232, +- .crop = { +- .left = IMX219_PIXEL_ARRAY_LEFT, +- .top = IMX219_PIXEL_ARRAY_TOP, +- .width = 3280, +- .height = 2464 +- }, + .vts_def = 1763, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1640_1232_regs), +@@ -416,12 +396,6 @@ static const struct imx219_mode supporte + /* 640x480 30fps mode */ + .width = 640, + .height = 480, +- .crop = { +- .left = 1008, +- .top = 760, +- .width = 1280, +- .height = 960 +- }, + .vts_def = 1763, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_640_480_regs), +@@ -966,6 +940,7 @@ static int imx219_set_pad_format(struct + int exposure_max, exposure_def, hblank; + struct v4l2_mbus_framefmt *format; + struct v4l2_rect *crop; ++ unsigned int bin_h, bin_v; + + mode = v4l2_find_nearest_size(supported_modes, + ARRAY_SIZE(supported_modes), +@@ -975,10 +950,20 @@ static int imx219_set_pad_format(struct + imx219_update_pad_format(imx219, mode, &fmt->format, fmt->format.code); + + format = v4l2_subdev_get_pad_format(sd, sd_state, 0); +- crop = v4l2_subdev_get_pad_crop(sd, sd_state, 0); +- + *format = fmt->format; +- *crop = mode->crop; ++ ++ /* ++ * Use binning to maximize the crop rectangle size, and centre it in the ++ * sensor. ++ */ ++ bin_h = min(IMX219_PIXEL_ARRAY_WIDTH / format->width, 2U); ++ bin_v = min(IMX219_PIXEL_ARRAY_HEIGHT / format->height, 2U); ++ ++ crop = v4l2_subdev_get_pad_crop(sd, sd_state, 0); ++ crop->width = format->width * bin_h; ++ crop->height = format->height * bin_v; ++ crop->left = (IMX219_NATIVE_WIDTH - crop->width) / 2; ++ crop->top = (IMX219_NATIVE_HEIGHT - crop->height) / 2; + + if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { + imx219->mode = mode; diff --git a/queue-6.6/media-i2c-imx219-don-t-store-the-current-mode-in-the-imx219-structure.patch b/queue-6.6/media-i2c-imx219-don-t-store-the-current-mode-in-the-imx219-structure.patch new file mode 100644 index 0000000000..8df6f8a0eb --- /dev/null +++ b/queue-6.6/media-i2c-imx219-don-t-store-the-current-mode-in-the-imx219-structure.patch @@ -0,0 +1,71 @@ +From stable+bounces-295115-greg=kroah.com@vger.kernel.org Tue Aug 4 14:11:26 2026 +From: Sasha Levin +Date: Tue, 4 Aug 2026 06:47:32 -0400 +Subject: media: i2c: imx219: Don't store the current mode in the imx219 structure +To: stable@vger.kernel.org +Cc: Laurent Pinchart , Jacopo Mondi , Dave Stevenson , Sakari Ailus , Hans Verkuil , Sasha Levin +Message-ID: <20260804104737.2827302-2-sashal@kernel.org> + +From: Laurent Pinchart + +[ Upstream commit e3e5d172d5fce9151bc101427554a158d4759856 ] + +The mode field of the imx219 structure is only used in +imx219_init_controls(), after the probe function sets it to point to the +default mode. Use the default mode directly when initializing controls, +and drop the mode field from the imx219 structure. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Jacopo Mondi +Reviewed-by: Dave Stevenson +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Stable-dep-of: 2c4f1ba73543 ("media: imx219: Fix maximum frame length in lines") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/i2c/imx219.c | 13 +++++++------ + 1 file changed, 7 insertions(+), 6 deletions(-) + +--- a/drivers/media/i2c/imx219.c ++++ b/drivers/media/i2c/imx219.c +@@ -1067,8 +1067,8 @@ static unsigned long imx219_get_pixel_ra + static int imx219_init_controls(struct imx219 *imx219) + { + struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); ++ const struct imx219_mode *mode = &supported_modes[0]; + struct v4l2_ctrl_handler *ctrl_hdlr; +- unsigned int height = imx219->mode->height; + struct v4l2_fwnode_device_properties props; + int exposure_max, exposure_def, hblank; + int i, ret; +@@ -1097,15 +1097,15 @@ static int imx219_init_controls(struct i + /* Initial vblank/hblank/exposure parameters based on current mode */ + imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, + V4L2_CID_VBLANK, IMX219_VBLANK_MIN, +- IMX219_VTS_MAX - height, 1, +- imx219->mode->vts_def - height); +- hblank = IMX219_PPL_DEFAULT - imx219->mode->width; ++ IMX219_VTS_MAX - mode->height, 1, ++ mode->vts_def - mode->height); ++ hblank = IMX219_PPL_DEFAULT - mode->width; + imx219->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, + V4L2_CID_HBLANK, hblank, hblank, + 1, hblank); + if (imx219->hblank) + imx219->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; +- exposure_max = imx219->mode->vts_def - 4; ++ exposure_max = mode->vts_def - 4; + exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ? + exposure_max : IMX219_EXPOSURE_DEFAULT; + imx219->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, +@@ -1298,7 +1298,8 @@ static int imx219_probe(struct i2c_clien + /* Set default mode to max resolution */ + imx219->mode = &supported_modes[0]; + +- /* sensor doesn't enter LP-11 state upon power up until and unless ++ /* ++ * Sensor doesn't enter LP-11 state upon power up until and unless + * streaming is started, so upon power up switch the modes to: + * streaming -> standby + */ diff --git a/queue-6.6/media-i2c-imx219-drop-imx219_vts_-macros.patch b/queue-6.6/media-i2c-imx219-drop-imx219_vts_-macros.patch new file mode 100644 index 0000000000..0265ce8c2c --- /dev/null +++ b/queue-6.6/media-i2c-imx219-drop-imx219_vts_-macros.patch @@ -0,0 +1,88 @@ +From stable+bounces-295116-greg=kroah.com@vger.kernel.org Tue Aug 4 13:08:30 2026 +From: Sasha Levin +Date: Tue, 4 Aug 2026 06:47:33 -0400 +Subject: media: i2c: imx219: Drop IMX219_VTS_* macros +To: stable@vger.kernel.org +Cc: Laurent Pinchart , Dave Stevenson , Jacopo Mondi , Sakari Ailus , Hans Verkuil , Sasha Levin +Message-ID: <20260804104737.2827302-3-sashal@kernel.org> + +From: Laurent Pinchart + +[ Upstream commit 5ebbdd7aab3321e60a8be23aac1fee4f16644021 ] + +The IMX219_VTS_* macros define default VTS values for the modes +supported by the driver. They are used in a single place, and hinder +readability compared to using the value directly as a decimal number. +Drop them. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Dave Stevenson +Reviewed-by: Jacopo Mondi +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Stable-dep-of: 2c4f1ba73543 ("media: imx219: Fix maximum frame length in lines") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/i2c/imx219.c | 18 ++++-------------- + 1 file changed, 4 insertions(+), 14 deletions(-) + +--- a/drivers/media/i2c/imx219.c ++++ b/drivers/media/i2c/imx219.c +@@ -71,20 +71,10 @@ + + /* V_TIMING internal */ + #define IMX219_REG_VTS CCI_REG16(0x0160) +-#define IMX219_VTS_15FPS 0x0dc6 +-#define IMX219_VTS_30FPS_1080P 0x06e3 +-#define IMX219_VTS_30FPS_BINNED 0x06e3 +-#define IMX219_VTS_30FPS_640x480 0x06e3 + #define IMX219_VTS_MAX 0xffff + + #define IMX219_VBLANK_MIN 32 + +-/*Frame Length Line*/ +-#define IMX219_FLL_MIN 0x08a6 +-#define IMX219_FLL_MAX 0xffff +-#define IMX219_FLL_STEP 1 +-#define IMX219_FLL_DEFAULT 0x0c98 +- + /* HBLANK control - read only */ + #define IMX219_PPL_DEFAULT 3448 + +@@ -381,7 +371,7 @@ static const struct imx219_mode supporte + .width = 3280, + .height = 2464 + }, +- .vts_def = IMX219_VTS_15FPS, ++ .vts_def = 3526, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs), + .regs = mode_3280x2464_regs, +@@ -398,7 +388,7 @@ static const struct imx219_mode supporte + .width = 1920, + .height = 1080 + }, +- .vts_def = IMX219_VTS_30FPS_1080P, ++ .vts_def = 1763, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1920_1080_regs), + .regs = mode_1920_1080_regs, +@@ -415,7 +405,7 @@ static const struct imx219_mode supporte + .width = 3280, + .height = 2464 + }, +- .vts_def = IMX219_VTS_30FPS_BINNED, ++ .vts_def = 1763, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1640_1232_regs), + .regs = mode_1640_1232_regs, +@@ -432,7 +422,7 @@ static const struct imx219_mode supporte + .width = 1280, + .height = 960 + }, +- .vts_def = IMX219_VTS_30FPS_640x480, ++ .vts_def = 1763, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_640_480_regs), + .regs = mode_640_480_regs, diff --git a/queue-6.6/media-i2c-imx219-group-functions-by-purpose.patch b/queue-6.6/media-i2c-imx219-group-functions-by-purpose.patch new file mode 100644 index 0000000000..275dc4ab4e --- /dev/null +++ b/queue-6.6/media-i2c-imx219-group-functions-by-purpose.patch @@ -0,0 +1,673 @@ +From stable+bounces-295117-greg=kroah.com@vger.kernel.org Tue Aug 4 12:57:32 2026 +From: Sasha Levin +Date: Tue, 4 Aug 2026 06:47:34 -0400 +Subject: media: i2c: imx219: Group functions by purpose +To: stable@vger.kernel.org +Cc: Laurent Pinchart , Dave Stevenson , Sakari Ailus , Hans Verkuil , Sasha Levin +Message-ID: <20260804104737.2827302-4-sashal@kernel.org> + +From: Laurent Pinchart + +[ Upstream commit d03dfb7d4c5fae0d3f297536063e00ea2c1129d5 ] + +Move functions around to group them by purpose, in order to improve +readability. No functional change is intended. + +Signed-off-by: Laurent Pinchart +Reviewed-by: Dave Stevenson +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Stable-dep-of: 2c4f1ba73543 ("media: imx219: Fix maximum frame length in lines") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/i2c/imx219.c | 580 +++++++++++++++++++++++---------------------- + 1 file changed, 298 insertions(+), 282 deletions(-) + +--- a/drivers/media/i2c/imx219.c ++++ b/drivers/media/i2c/imx219.c +@@ -485,6 +485,10 @@ static u32 imx219_get_format_code(struct + return imx219_mbus_formats[i]; + } + ++/* ----------------------------------------------------------------------------- ++ * Controls ++ */ ++ + static int imx219_set_ctrl(struct v4l2_ctrl *ctrl) + { + struct imx219 *imx219 = +@@ -576,130 +580,135 @@ static const struct v4l2_ctrl_ops imx219 + .s_ctrl = imx219_set_ctrl, + }; + +-static void imx219_update_pad_format(struct imx219 *imx219, +- const struct imx219_mode *mode, +- struct v4l2_mbus_framefmt *fmt, u32 code) ++static unsigned long imx219_get_pixel_rate(struct imx219 *imx219) + { +- /* Bayer order varies with flips */ +- fmt->code = imx219_get_format_code(imx219, code); +- fmt->width = mode->width; +- fmt->height = mode->height; +- fmt->field = V4L2_FIELD_NONE; +- fmt->colorspace = V4L2_COLORSPACE_RAW; +- fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE; +- fmt->xfer_func = V4L2_XFER_FUNC_NONE; ++ return (imx219->lanes == 2) ? IMX219_PIXEL_RATE : IMX219_PIXEL_RATE_4LANE; + } + +-static int imx219_init_cfg(struct v4l2_subdev *sd, +- struct v4l2_subdev_state *state) ++/* Initialize control handlers */ ++static int imx219_init_controls(struct imx219 *imx219) + { +- struct imx219 *imx219 = to_imx219(sd); +- struct v4l2_mbus_framefmt *format; +- struct v4l2_rect *crop; +- +- /* Initialize the format. */ +- format = v4l2_subdev_get_pad_format(sd, state, 0); +- imx219_update_pad_format(imx219, &supported_modes[0], format, +- MEDIA_BUS_FMT_SRGGB10_1X10); +- +- /* Initialize the crop rectangle. */ +- crop = v4l2_subdev_get_pad_crop(sd, state, 0); +- crop->top = IMX219_PIXEL_ARRAY_TOP; +- crop->left = IMX219_PIXEL_ARRAY_LEFT; +- crop->width = IMX219_PIXEL_ARRAY_WIDTH; +- crop->height = IMX219_PIXEL_ARRAY_HEIGHT; ++ struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); ++ const struct imx219_mode *mode = &supported_modes[0]; ++ struct v4l2_ctrl_handler *ctrl_hdlr; ++ struct v4l2_fwnode_device_properties props; ++ int exposure_max, exposure_def, hblank; ++ int i, ret; + +- return 0; +-} ++ ctrl_hdlr = &imx219->ctrl_handler; ++ ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12); ++ if (ret) ++ return ret; + +-static int imx219_enum_mbus_code(struct v4l2_subdev *sd, +- struct v4l2_subdev_state *sd_state, +- struct v4l2_subdev_mbus_code_enum *code) +-{ +- struct imx219 *imx219 = to_imx219(sd); ++ /* By default, PIXEL_RATE is read only */ ++ imx219->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, ++ V4L2_CID_PIXEL_RATE, ++ imx219_get_pixel_rate(imx219), ++ imx219_get_pixel_rate(imx219), 1, ++ imx219_get_pixel_rate(imx219)); + +- if (code->index >= (ARRAY_SIZE(imx219_mbus_formats) / 4)) +- return -EINVAL; ++ imx219->link_freq = ++ v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx219_ctrl_ops, ++ V4L2_CID_LINK_FREQ, ++ ARRAY_SIZE(imx219_link_freq_menu) - 1, 0, ++ (imx219->lanes == 2) ? imx219_link_freq_menu : ++ imx219_link_freq_4lane_menu); ++ if (imx219->link_freq) ++ imx219->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; + +- code->code = imx219_get_format_code(imx219, imx219_mbus_formats[code->index * 4]); ++ /* Initial vblank/hblank/exposure parameters based on current mode */ ++ imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, ++ V4L2_CID_VBLANK, IMX219_VBLANK_MIN, ++ IMX219_VTS_MAX - mode->height, 1, ++ mode->vts_def - mode->height); ++ hblank = IMX219_PPL_DEFAULT - mode->width; ++ imx219->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, ++ V4L2_CID_HBLANK, hblank, hblank, ++ 1, hblank); ++ if (imx219->hblank) ++ imx219->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; ++ exposure_max = mode->vts_def - 4; ++ exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ? ++ exposure_max : IMX219_EXPOSURE_DEFAULT; ++ imx219->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, ++ V4L2_CID_EXPOSURE, ++ IMX219_EXPOSURE_MIN, exposure_max, ++ IMX219_EXPOSURE_STEP, ++ exposure_def); + +- return 0; +-} ++ v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, ++ IMX219_ANA_GAIN_MIN, IMX219_ANA_GAIN_MAX, ++ IMX219_ANA_GAIN_STEP, IMX219_ANA_GAIN_DEFAULT); + +-static int imx219_enum_frame_size(struct v4l2_subdev *sd, +- struct v4l2_subdev_state *sd_state, +- struct v4l2_subdev_frame_size_enum *fse) +-{ +- struct imx219 *imx219 = to_imx219(sd); +- u32 code; ++ v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_DIGITAL_GAIN, ++ IMX219_DGTL_GAIN_MIN, IMX219_DGTL_GAIN_MAX, ++ IMX219_DGTL_GAIN_STEP, IMX219_DGTL_GAIN_DEFAULT); + +- if (fse->index >= ARRAY_SIZE(supported_modes)) +- return -EINVAL; ++ imx219->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, ++ V4L2_CID_HFLIP, 0, 1, 1, 0); ++ if (imx219->hflip) ++ imx219->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; + +- code = imx219_get_format_code(imx219, fse->code); +- if (fse->code != code) +- return -EINVAL; ++ imx219->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, ++ V4L2_CID_VFLIP, 0, 1, 1, 0); ++ if (imx219->vflip) ++ imx219->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; + +- fse->min_width = supported_modes[fse->index].width; +- fse->max_width = fse->min_width; +- fse->min_height = supported_modes[fse->index].height; +- fse->max_height = fse->min_height; ++ v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx219_ctrl_ops, ++ V4L2_CID_TEST_PATTERN, ++ ARRAY_SIZE(imx219_test_pattern_menu) - 1, ++ 0, 0, imx219_test_pattern_menu); ++ for (i = 0; i < 4; i++) { ++ /* ++ * The assumption is that ++ * V4L2_CID_TEST_PATTERN_GREENR == V4L2_CID_TEST_PATTERN_RED + 1 ++ * V4L2_CID_TEST_PATTERN_BLUE == V4L2_CID_TEST_PATTERN_RED + 2 ++ * V4L2_CID_TEST_PATTERN_GREENB == V4L2_CID_TEST_PATTERN_RED + 3 ++ */ ++ v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, ++ V4L2_CID_TEST_PATTERN_RED + i, ++ IMX219_TESTP_COLOUR_MIN, ++ IMX219_TESTP_COLOUR_MAX, ++ IMX219_TESTP_COLOUR_STEP, ++ IMX219_TESTP_COLOUR_MAX); ++ /* The "Solid color" pattern is white by default */ ++ } + +- return 0; +-} ++ if (ctrl_hdlr->error) { ++ ret = ctrl_hdlr->error; ++ dev_err(&client->dev, "%s control init failed (%d)\n", ++ __func__, ret); ++ goto error; ++ } + +-static int imx219_set_pad_format(struct v4l2_subdev *sd, +- struct v4l2_subdev_state *sd_state, +- struct v4l2_subdev_format *fmt) +-{ +- struct imx219 *imx219 = to_imx219(sd); +- const struct imx219_mode *mode; +- int exposure_max, exposure_def, hblank; +- struct v4l2_mbus_framefmt *format; +- struct v4l2_rect *crop; ++ ret = v4l2_fwnode_device_parse(&client->dev, &props); ++ if (ret) ++ goto error; + +- mode = v4l2_find_nearest_size(supported_modes, +- ARRAY_SIZE(supported_modes), +- width, height, +- fmt->format.width, fmt->format.height); ++ ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx219_ctrl_ops, ++ &props); ++ if (ret) ++ goto error; + +- imx219_update_pad_format(imx219, mode, &fmt->format, fmt->format.code); ++ imx219->sd.ctrl_handler = ctrl_hdlr; + +- format = v4l2_subdev_get_pad_format(sd, sd_state, 0); +- crop = v4l2_subdev_get_pad_crop(sd, sd_state, 0); ++ return 0; + +- *format = fmt->format; +- *crop = mode->crop; ++error: ++ v4l2_ctrl_handler_free(ctrl_hdlr); + +- if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { +- imx219->mode = mode; +- /* Update limits and set FPS to default */ +- __v4l2_ctrl_modify_range(imx219->vblank, IMX219_VBLANK_MIN, +- IMX219_VTS_MAX - mode->height, 1, +- mode->vts_def - mode->height); +- __v4l2_ctrl_s_ctrl(imx219->vblank, +- mode->vts_def - mode->height); +- /* Update max exposure while meeting expected vblanking */ +- exposure_max = mode->vts_def - 4; +- exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ? +- exposure_max : IMX219_EXPOSURE_DEFAULT; +- __v4l2_ctrl_modify_range(imx219->exposure, +- imx219->exposure->minimum, +- exposure_max, imx219->exposure->step, +- exposure_def); +- /* +- * Currently PPL is fixed to IMX219_PPL_DEFAULT, so hblank +- * depends on mode->width only, and is not changeble in any +- * way other than changing the mode. +- */ +- hblank = IMX219_PPL_DEFAULT - mode->width; +- __v4l2_ctrl_modify_range(imx219->hblank, hblank, hblank, 1, +- hblank); +- } ++ return ret; ++} + +- return 0; ++static void imx219_free_controls(struct imx219 *imx219) ++{ ++ v4l2_ctrl_handler_free(imx219->sd.ctrl_handler); + } + ++/* ----------------------------------------------------------------------------- ++ * Subdev operations ++ */ ++ + static int imx219_set_framefmt(struct imx219 *imx219, + const struct v4l2_mbus_framefmt *format) + { +@@ -748,37 +757,6 @@ static int imx219_set_binning(struct imx + return -EINVAL; + } + +-static int imx219_get_selection(struct v4l2_subdev *sd, +- struct v4l2_subdev_state *sd_state, +- struct v4l2_subdev_selection *sel) +-{ +- switch (sel->target) { +- case V4L2_SEL_TGT_CROP: { +- sel->r = *v4l2_subdev_get_pad_crop(sd, sd_state, 0); +- return 0; +- } +- +- case V4L2_SEL_TGT_NATIVE_SIZE: +- sel->r.top = 0; +- sel->r.left = 0; +- sel->r.width = IMX219_NATIVE_WIDTH; +- sel->r.height = IMX219_NATIVE_HEIGHT; +- +- return 0; +- +- case V4L2_SEL_TGT_CROP_DEFAULT: +- case V4L2_SEL_TGT_CROP_BOUNDS: +- sel->r.top = IMX219_PIXEL_ARRAY_TOP; +- sel->r.left = IMX219_PIXEL_ARRAY_LEFT; +- sel->r.width = IMX219_PIXEL_ARRAY_WIDTH; +- sel->r.height = IMX219_PIXEL_ARRAY_HEIGHT; +- +- return 0; +- } +- +- return -EINVAL; +-} +- + static int imx219_configure_lanes(struct imx219 *imx219) + { + return cci_write(imx219->regmap, IMX219_REG_CSI_LANE_MODE, +@@ -907,6 +885,190 @@ unlock: + } + + /* Power/clock management functions */ ++static void imx219_update_pad_format(struct imx219 *imx219, ++ const struct imx219_mode *mode, ++ struct v4l2_mbus_framefmt *fmt, u32 code) ++{ ++ /* Bayer order varies with flips */ ++ fmt->code = imx219_get_format_code(imx219, code); ++ fmt->width = mode->width; ++ fmt->height = mode->height; ++ fmt->field = V4L2_FIELD_NONE; ++ fmt->colorspace = V4L2_COLORSPACE_RAW; ++ fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE; ++ fmt->xfer_func = V4L2_XFER_FUNC_NONE; ++} ++ ++static int imx219_init_cfg(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *state) ++{ ++ struct imx219 *imx219 = to_imx219(sd); ++ struct v4l2_mbus_framefmt *format; ++ struct v4l2_rect *crop; ++ ++ /* Initialize the format. */ ++ format = v4l2_subdev_get_pad_format(sd, state, 0); ++ imx219_update_pad_format(imx219, &supported_modes[0], format, ++ MEDIA_BUS_FMT_SRGGB10_1X10); ++ ++ /* Initialize the crop rectangle. */ ++ crop = v4l2_subdev_get_pad_crop(sd, state, 0); ++ crop->top = IMX219_PIXEL_ARRAY_TOP; ++ crop->left = IMX219_PIXEL_ARRAY_LEFT; ++ crop->width = IMX219_PIXEL_ARRAY_WIDTH; ++ crop->height = IMX219_PIXEL_ARRAY_HEIGHT; ++ ++ return 0; ++} ++ ++static int imx219_enum_mbus_code(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *sd_state, ++ struct v4l2_subdev_mbus_code_enum *code) ++{ ++ struct imx219 *imx219 = to_imx219(sd); ++ ++ if (code->index >= (ARRAY_SIZE(imx219_mbus_formats) / 4)) ++ return -EINVAL; ++ ++ code->code = imx219_get_format_code(imx219, imx219_mbus_formats[code->index * 4]); ++ ++ return 0; ++} ++ ++static int imx219_enum_frame_size(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *sd_state, ++ struct v4l2_subdev_frame_size_enum *fse) ++{ ++ struct imx219 *imx219 = to_imx219(sd); ++ u32 code; ++ ++ if (fse->index >= ARRAY_SIZE(supported_modes)) ++ return -EINVAL; ++ ++ code = imx219_get_format_code(imx219, fse->code); ++ if (fse->code != code) ++ return -EINVAL; ++ ++ fse->min_width = supported_modes[fse->index].width; ++ fse->max_width = fse->min_width; ++ fse->min_height = supported_modes[fse->index].height; ++ fse->max_height = fse->min_height; ++ ++ return 0; ++} ++ ++static int imx219_set_pad_format(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *sd_state, ++ struct v4l2_subdev_format *fmt) ++{ ++ struct imx219 *imx219 = to_imx219(sd); ++ const struct imx219_mode *mode; ++ int exposure_max, exposure_def, hblank; ++ struct v4l2_mbus_framefmt *format; ++ struct v4l2_rect *crop; ++ ++ mode = v4l2_find_nearest_size(supported_modes, ++ ARRAY_SIZE(supported_modes), ++ width, height, ++ fmt->format.width, fmt->format.height); ++ ++ imx219_update_pad_format(imx219, mode, &fmt->format, fmt->format.code); ++ ++ format = v4l2_subdev_get_pad_format(sd, sd_state, 0); ++ crop = v4l2_subdev_get_pad_crop(sd, sd_state, 0); ++ ++ *format = fmt->format; ++ *crop = mode->crop; ++ ++ if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) { ++ imx219->mode = mode; ++ /* Update limits and set FPS to default */ ++ __v4l2_ctrl_modify_range(imx219->vblank, IMX219_VBLANK_MIN, ++ IMX219_VTS_MAX - mode->height, 1, ++ mode->vts_def - mode->height); ++ __v4l2_ctrl_s_ctrl(imx219->vblank, ++ mode->vts_def - mode->height); ++ /* Update max exposure while meeting expected vblanking */ ++ exposure_max = mode->vts_def - 4; ++ exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ? ++ exposure_max : IMX219_EXPOSURE_DEFAULT; ++ __v4l2_ctrl_modify_range(imx219->exposure, ++ imx219->exposure->minimum, ++ exposure_max, imx219->exposure->step, ++ exposure_def); ++ /* ++ * Currently PPL is fixed to IMX219_PPL_DEFAULT, so hblank ++ * depends on mode->width only, and is not changeble in any ++ * way other than changing the mode. ++ */ ++ hblank = IMX219_PPL_DEFAULT - mode->width; ++ __v4l2_ctrl_modify_range(imx219->hblank, hblank, hblank, 1, ++ hblank); ++ } ++ ++ return 0; ++} ++ ++static int imx219_get_selection(struct v4l2_subdev *sd, ++ struct v4l2_subdev_state *sd_state, ++ struct v4l2_subdev_selection *sel) ++{ ++ switch (sel->target) { ++ case V4L2_SEL_TGT_CROP: { ++ sel->r = *v4l2_subdev_get_pad_crop(sd, sd_state, 0); ++ return 0; ++ } ++ ++ case V4L2_SEL_TGT_NATIVE_SIZE: ++ sel->r.top = 0; ++ sel->r.left = 0; ++ sel->r.width = IMX219_NATIVE_WIDTH; ++ sel->r.height = IMX219_NATIVE_HEIGHT; ++ ++ return 0; ++ ++ case V4L2_SEL_TGT_CROP_DEFAULT: ++ case V4L2_SEL_TGT_CROP_BOUNDS: ++ sel->r.top = IMX219_PIXEL_ARRAY_TOP; ++ sel->r.left = IMX219_PIXEL_ARRAY_LEFT; ++ sel->r.width = IMX219_PIXEL_ARRAY_WIDTH; ++ sel->r.height = IMX219_PIXEL_ARRAY_HEIGHT; ++ ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++static const struct v4l2_subdev_core_ops imx219_core_ops = { ++ .subscribe_event = v4l2_ctrl_subdev_subscribe_event, ++ .unsubscribe_event = v4l2_event_subdev_unsubscribe, ++}; ++ ++static const struct v4l2_subdev_video_ops imx219_video_ops = { ++ .s_stream = imx219_set_stream, ++}; ++ ++static const struct v4l2_subdev_pad_ops imx219_pad_ops = { ++ .init_cfg = imx219_init_cfg, ++ .enum_mbus_code = imx219_enum_mbus_code, ++ .get_fmt = v4l2_subdev_get_fmt, ++ .set_fmt = imx219_set_pad_format, ++ .get_selection = imx219_get_selection, ++ .enum_frame_size = imx219_enum_frame_size, ++}; ++ ++static const struct v4l2_subdev_ops imx219_subdev_ops = { ++ .core = &imx219_core_ops, ++ .video = &imx219_video_ops, ++ .pad = &imx219_pad_ops, ++}; ++ ++ ++/* ----------------------------------------------------------------------------- ++ * Power management ++ */ ++ + static int imx219_power_on(struct device *dev) + { + struct v4l2_subdev *sd = dev_get_drvdata(dev); +@@ -987,6 +1149,10 @@ error: + return ret; + } + ++/* ----------------------------------------------------------------------------- ++ * Probe & remove ++ */ ++ + static int imx219_get_regulators(struct imx219 *imx219) + { + struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); +@@ -1023,156 +1189,6 @@ static int imx219_identify_module(struct + return 0; + } + +-static const struct v4l2_subdev_core_ops imx219_core_ops = { +- .subscribe_event = v4l2_ctrl_subdev_subscribe_event, +- .unsubscribe_event = v4l2_event_subdev_unsubscribe, +-}; +- +-static const struct v4l2_subdev_video_ops imx219_video_ops = { +- .s_stream = imx219_set_stream, +-}; +- +-static const struct v4l2_subdev_pad_ops imx219_pad_ops = { +- .init_cfg = imx219_init_cfg, +- .enum_mbus_code = imx219_enum_mbus_code, +- .get_fmt = v4l2_subdev_get_fmt, +- .set_fmt = imx219_set_pad_format, +- .get_selection = imx219_get_selection, +- .enum_frame_size = imx219_enum_frame_size, +-}; +- +-static const struct v4l2_subdev_ops imx219_subdev_ops = { +- .core = &imx219_core_ops, +- .video = &imx219_video_ops, +- .pad = &imx219_pad_ops, +-}; +- +- +-static unsigned long imx219_get_pixel_rate(struct imx219 *imx219) +-{ +- return (imx219->lanes == 2) ? IMX219_PIXEL_RATE : IMX219_PIXEL_RATE_4LANE; +-} +- +-/* Initialize control handlers */ +-static int imx219_init_controls(struct imx219 *imx219) +-{ +- struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd); +- const struct imx219_mode *mode = &supported_modes[0]; +- struct v4l2_ctrl_handler *ctrl_hdlr; +- struct v4l2_fwnode_device_properties props; +- int exposure_max, exposure_def, hblank; +- int i, ret; +- +- ctrl_hdlr = &imx219->ctrl_handler; +- ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12); +- if (ret) +- return ret; +- +- /* By default, PIXEL_RATE is read only */ +- imx219->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, +- V4L2_CID_PIXEL_RATE, +- imx219_get_pixel_rate(imx219), +- imx219_get_pixel_rate(imx219), 1, +- imx219_get_pixel_rate(imx219)); +- +- imx219->link_freq = +- v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx219_ctrl_ops, +- V4L2_CID_LINK_FREQ, +- ARRAY_SIZE(imx219_link_freq_menu) - 1, 0, +- (imx219->lanes == 2) ? imx219_link_freq_menu : +- imx219_link_freq_4lane_menu); +- if (imx219->link_freq) +- imx219->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; +- +- /* Initial vblank/hblank/exposure parameters based on current mode */ +- imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, +- V4L2_CID_VBLANK, IMX219_VBLANK_MIN, +- IMX219_VTS_MAX - mode->height, 1, +- mode->vts_def - mode->height); +- hblank = IMX219_PPL_DEFAULT - mode->width; +- imx219->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, +- V4L2_CID_HBLANK, hblank, hblank, +- 1, hblank); +- if (imx219->hblank) +- imx219->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; +- exposure_max = mode->vts_def - 4; +- exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ? +- exposure_max : IMX219_EXPOSURE_DEFAULT; +- imx219->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, +- V4L2_CID_EXPOSURE, +- IMX219_EXPOSURE_MIN, exposure_max, +- IMX219_EXPOSURE_STEP, +- exposure_def); +- +- v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_ANALOGUE_GAIN, +- IMX219_ANA_GAIN_MIN, IMX219_ANA_GAIN_MAX, +- IMX219_ANA_GAIN_STEP, IMX219_ANA_GAIN_DEFAULT); +- +- v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, V4L2_CID_DIGITAL_GAIN, +- IMX219_DGTL_GAIN_MIN, IMX219_DGTL_GAIN_MAX, +- IMX219_DGTL_GAIN_STEP, IMX219_DGTL_GAIN_DEFAULT); +- +- imx219->hflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, +- V4L2_CID_HFLIP, 0, 1, 1, 0); +- if (imx219->hflip) +- imx219->hflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; +- +- imx219->vflip = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, +- V4L2_CID_VFLIP, 0, 1, 1, 0); +- if (imx219->vflip) +- imx219->vflip->flags |= V4L2_CTRL_FLAG_MODIFY_LAYOUT; +- +- v4l2_ctrl_new_std_menu_items(ctrl_hdlr, &imx219_ctrl_ops, +- V4L2_CID_TEST_PATTERN, +- ARRAY_SIZE(imx219_test_pattern_menu) - 1, +- 0, 0, imx219_test_pattern_menu); +- for (i = 0; i < 4; i++) { +- /* +- * The assumption is that +- * V4L2_CID_TEST_PATTERN_GREENR == V4L2_CID_TEST_PATTERN_RED + 1 +- * V4L2_CID_TEST_PATTERN_BLUE == V4L2_CID_TEST_PATTERN_RED + 2 +- * V4L2_CID_TEST_PATTERN_GREENB == V4L2_CID_TEST_PATTERN_RED + 3 +- */ +- v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, +- V4L2_CID_TEST_PATTERN_RED + i, +- IMX219_TESTP_COLOUR_MIN, +- IMX219_TESTP_COLOUR_MAX, +- IMX219_TESTP_COLOUR_STEP, +- IMX219_TESTP_COLOUR_MAX); +- /* The "Solid color" pattern is white by default */ +- } +- +- if (ctrl_hdlr->error) { +- ret = ctrl_hdlr->error; +- dev_err(&client->dev, "%s control init failed (%d)\n", +- __func__, ret); +- goto error; +- } +- +- ret = v4l2_fwnode_device_parse(&client->dev, &props); +- if (ret) +- goto error; +- +- ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &imx219_ctrl_ops, +- &props); +- if (ret) +- goto error; +- +- imx219->sd.ctrl_handler = ctrl_hdlr; +- +- return 0; +- +-error: +- v4l2_ctrl_handler_free(ctrl_hdlr); +- +- return ret; +-} +- +-static void imx219_free_controls(struct imx219 *imx219) +-{ +- v4l2_ctrl_handler_free(imx219->sd.ctrl_handler); +-} +- + static int imx219_check_hwcfg(struct device *dev, struct imx219 *imx219) + { + struct fwnode_handle *endpoint; diff --git a/queue-6.6/media-i2c-imx219-rename-vts-to-frm_length.patch b/queue-6.6/media-i2c-imx219-rename-vts-to-frm_length.patch new file mode 100644 index 0000000000..641331b65c --- /dev/null +++ b/queue-6.6/media-i2c-imx219-rename-vts-to-frm_length.patch @@ -0,0 +1,130 @@ +From stable+bounces-295118-greg=kroah.com@vger.kernel.org Tue Aug 4 13:08:40 2026 +From: Sasha Levin +Date: Tue, 4 Aug 2026 06:47:36 -0400 +Subject: media: i2c: imx219: Rename VTS to FRM_LENGTH +To: stable@vger.kernel.org +Cc: Jai Luthra , Dave Stevenson , Sakari Ailus , Hans Verkuil , Sasha Levin +Message-ID: <20260804104737.2827302-6-sashal@kernel.org> + +From: Jai Luthra + +[ Upstream commit 04f78503f99ae7e9887c7fe5e4bc54a7cfb10fe0 ] + +The IMX219 datasheet refers to the vertical length + blanking as +FRM_LENGTH instead of VTS. + +Reviewed-by: Dave Stevenson +Signed-off-by: Jai Luthra +Signed-off-by: Sakari Ailus +Signed-off-by: Hans Verkuil +Stable-dep-of: 2c4f1ba73543 ("media: imx219: Fix maximum frame length in lines") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/i2c/imx219.c | 31 +++++++++++++++---------------- + 1 file changed, 15 insertions(+), 16 deletions(-) + +--- a/drivers/media/i2c/imx219.c ++++ b/drivers/media/i2c/imx219.c +@@ -71,9 +71,8 @@ + #define IMX219_EXPOSURE_MAX 65535 + + /* V_TIMING internal */ +-#define IMX219_REG_VTS CCI_REG16(0x0160) +-#define IMX219_VTS_MAX 0xffff +- ++#define IMX219_REG_FRM_LENGTH_A CCI_REG16(0x0160) ++#define IMX219_FLL_MAX 0xffff + #define IMX219_VBLANK_MIN 32 + + /* HBLANK control - read only */ +@@ -163,7 +162,7 @@ struct imx219_mode { + unsigned int height; + + /* V-timing */ +- unsigned int vts_def; ++ unsigned int fll_def; + + /* Default register values */ + struct imx219_reg_list reg_list; +@@ -363,7 +362,7 @@ static const struct imx219_mode supporte + /* 8MPix 15fps mode */ + .width = 3280, + .height = 2464, +- .vts_def = 3526, ++ .fll_def = 3526, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_3280x2464_regs), + .regs = mode_3280x2464_regs, +@@ -374,7 +373,7 @@ static const struct imx219_mode supporte + /* 1080P 30fps cropped */ + .width = 1920, + .height = 1080, +- .vts_def = 1763, ++ .fll_def = 1763, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1920_1080_regs), + .regs = mode_1920_1080_regs, +@@ -385,7 +384,7 @@ static const struct imx219_mode supporte + /* 2x2 binned 30fps mode */ + .width = 1640, + .height = 1232, +- .vts_def = 1763, ++ .fll_def = 1763, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_1640_1232_regs), + .regs = mode_1640_1232_regs, +@@ -396,7 +395,7 @@ static const struct imx219_mode supporte + /* 640x480 30fps mode */ + .width = 640, + .height = 480, +- .vts_def = 1763, ++ .fll_def = 1763, + .reg_list = { + .num_of_regs = ARRAY_SIZE(mode_640_480_regs), + .regs = mode_640_480_regs, +@@ -518,7 +517,7 @@ static int imx219_set_ctrl(struct v4l2_c + imx219->hflip->val | imx219->vflip->val << 1, &ret); + break; + case V4L2_CID_VBLANK: +- cci_write(imx219->regmap, IMX219_REG_VTS, ++ cci_write(imx219->regmap, IMX219_REG_FRM_LENGTH_A, + format->height + ctrl->val, &ret); + break; + case V4L2_CID_TEST_PATTERN_RED: +@@ -593,15 +592,15 @@ static int imx219_init_controls(struct i + /* Initial vblank/hblank/exposure parameters based on current mode */ + imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, + V4L2_CID_VBLANK, IMX219_VBLANK_MIN, +- IMX219_VTS_MAX - mode->height, 1, +- mode->vts_def - mode->height); ++ IMX219_FLL_MAX - mode->height, 1, ++ mode->fll_def - mode->height); + hblank = IMX219_PPL_DEFAULT - mode->width; + imx219->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, + V4L2_CID_HBLANK, hblank, hblank, + 1, hblank); + if (imx219->hblank) + imx219->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; +- exposure_max = mode->vts_def - 4; ++ exposure_max = mode->fll_def - 4; + exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ? + exposure_max : IMX219_EXPOSURE_DEFAULT; + imx219->exposure = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops, +@@ -969,12 +968,12 @@ static int imx219_set_pad_format(struct + imx219->mode = mode; + /* Update limits and set FPS to default */ + __v4l2_ctrl_modify_range(imx219->vblank, IMX219_VBLANK_MIN, +- IMX219_VTS_MAX - mode->height, 1, +- mode->vts_def - mode->height); ++ IMX219_FLL_MAX - mode->height, 1, ++ mode->fll_def - mode->height); + __v4l2_ctrl_s_ctrl(imx219->vblank, +- mode->vts_def - mode->height); ++ mode->fll_def - mode->height); + /* Update max exposure while meeting expected vblanking */ +- exposure_max = mode->vts_def - 4; ++ exposure_max = mode->fll_def - 4; + exposure_def = (exposure_max < IMX219_EXPOSURE_DEFAULT) ? + exposure_max : IMX219_EXPOSURE_DEFAULT; + __v4l2_ctrl_modify_range(imx219->exposure, diff --git a/queue-6.6/media-imx219-fix-maximum-frame-length-in-lines.patch b/queue-6.6/media-imx219-fix-maximum-frame-length-in-lines.patch new file mode 100644 index 0000000000..e9003225ca --- /dev/null +++ b/queue-6.6/media-imx219-fix-maximum-frame-length-in-lines.patch @@ -0,0 +1,37 @@ +From stable+bounces-295120-greg=kroah.com@vger.kernel.org Tue Aug 4 12:57:41 2026 +From: Sasha Levin +Date: Tue, 4 Aug 2026 06:47:37 -0400 +Subject: media: imx219: Fix maximum frame length in lines +To: stable@vger.kernel.org +Cc: Sakari Ailus , Dave Stevenson , Laurent Pinchart , Sasha Levin +Message-ID: <20260804104737.2827302-7-sashal@kernel.org> + +From: Sakari Ailus + +[ Upstream commit 2c4f1ba7354312ad2d6e34e70a518a51a9344715 ] + +The driver used the maximum frame length in lines value of 0xffff, but the +maximum appears to be 0xfffe instead. Fix it. + +Fixes: 1283b3b8f82b ("media: i2c: Add driver for Sony IMX219 sensor") +Cc: stable@vger.kernel.org +Signed-off-by: Sakari Ailus +Reviewed-by: Dave Stevenson +Reviewed-by: Laurent Pinchart +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/i2c/imx219.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/media/i2c/imx219.c ++++ b/drivers/media/i2c/imx219.c +@@ -72,7 +72,7 @@ + + /* V_TIMING internal */ + #define IMX219_REG_FRM_LENGTH_A CCI_REG16(0x0160) +-#define IMX219_FLL_MAX 0xffff ++#define IMX219_FLL_MAX 0xfffe + #define IMX219_VBLANK_MIN 32 + + /* HBLANK control - read only */ diff --git a/queue-6.6/media-v4l-async-set-owner-for-async-sub-devices.patch b/queue-6.6/media-v4l-async-set-owner-for-async-sub-devices.patch new file mode 100644 index 0000000000..db1ad4ac88 --- /dev/null +++ b/queue-6.6/media-v4l-async-set-owner-for-async-sub-devices.patch @@ -0,0 +1,71 @@ +From stable+bounces-296825-greg=kroah.com@vger.kernel.org Thu Aug 6 15:38:06 2026 +From: Sasha Levin +Date: Thu, 6 Aug 2026 09:36:14 -0400 +Subject: media: v4l: async: Set owner for async sub-devices +To: stable@vger.kernel.org +Cc: Sakari Ailus , Mauro Carvalho Chehab , Sasha Levin +Message-ID: <20260806133615.470300-1-sashal@kernel.org> + +From: Sakari Ailus + +[ Upstream commit 8a718752f5c339137c5b05e54f116cd26d5a4143 ] + +Set the owner field of the async sub-devices by making +v4l2_async_register_subdev() a macro and obtaining THIS_MODULE that way. + +Signed-off-by: Sakari Ailus +Signed-off-by: Mauro Carvalho Chehab +Stable-dep-of: 06cb687a5132 ("media: v4l2-fwnode: Fix subdev owner overwritten in v4l2_async_register_subdev_sensor()") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/v4l2-core/v4l2-async.c | 8 ++++++-- + include/media/v4l2-async.h | 4 +++- + 2 files changed, 9 insertions(+), 3 deletions(-) + +--- a/drivers/media/v4l2-core/v4l2-async.c ++++ b/drivers/media/v4l2-core/v4l2-async.c +@@ -798,7 +798,7 @@ v4l2_async_connection_unique(struct v4l2 + } + EXPORT_SYMBOL_GPL(v4l2_async_connection_unique); + +-int v4l2_async_register_subdev(struct v4l2_subdev *sd) ++int __v4l2_async_register_subdev(struct v4l2_subdev *sd, struct module *module) + { + struct v4l2_async_notifier *subdev_notifier; + struct v4l2_async_notifier *notifier; +@@ -822,6 +822,8 @@ int v4l2_async_register_subdev(struct v4 + return -EINVAL; + } + ++ sd->owner = module; ++ + mutex_lock(&list_lock); + + list_for_each_entry(notifier, ¬ifier_list, notifier_entry) { +@@ -869,9 +871,11 @@ err_unbind_one: + err_unlock: + mutex_unlock(&list_lock); + ++ sd->owner = NULL; ++ + return ret; + } +-EXPORT_SYMBOL(v4l2_async_register_subdev); ++EXPORT_SYMBOL(__v4l2_async_register_subdev); + + void v4l2_async_unregister_subdev(struct v4l2_subdev *sd) + { +--- a/include/media/v4l2-async.h ++++ b/include/media/v4l2-async.h +@@ -310,7 +310,9 @@ void v4l2_async_nf_cleanup(struct v4l2_a + * + * @sd: pointer to &struct v4l2_subdev + */ +-int v4l2_async_register_subdev(struct v4l2_subdev *sd); ++#define v4l2_async_register_subdev(sd) \ ++ __v4l2_async_register_subdev(sd, THIS_MODULE) ++int __v4l2_async_register_subdev(struct v4l2_subdev *sd, struct module *module); + + /** + * v4l2_async_register_subdev_sensor - registers a sensor sub-device to the diff --git a/queue-6.6/media-v4l2-fwnode-fix-subdev-owner-overwritten-in-v4l2_async_register_subdev_sensor.patch b/queue-6.6/media-v4l2-fwnode-fix-subdev-owner-overwritten-in-v4l2_async_register_subdev_sensor.patch new file mode 100644 index 0000000000..ee6d5d8111 --- /dev/null +++ b/queue-6.6/media-v4l2-fwnode-fix-subdev-owner-overwritten-in-v4l2_async_register_subdev_sensor.patch @@ -0,0 +1,93 @@ +From stable+bounces-296826-greg=kroah.com@vger.kernel.org Thu Aug 6 15:45:56 2026 +From: Sasha Levin +Date: Thu, 6 Aug 2026 09:36:15 -0400 +Subject: media: v4l2-fwnode: Fix subdev owner overwritten in v4l2_async_register_subdev_sensor() +To: stable@vger.kernel.org +Cc: Mirela Rabulea , Frank Li , Laurent Pinchart , Sakari Ailus , Sasha Levin +Message-ID: <20260806133615.470300-2-sashal@kernel.org> + +From: Mirela Rabulea + +[ Upstream commit 06cb687a5132fcffe624c0070576ab852ac6b568 ] + +The v4l2 helper v4l2_async_register_subdev_sensor() calls +v4l2_async_register_subdev(), which is a macro that expands to +__v4l2_async_register_subdev(sd,THIS_MODULE). Since the macro is expanded +inside v4l2-fwnode.c, THIS_MODULE resolves to the v4l2-fwnode module +rather than the sensor driver module that originally set sd->owner. When +v4l2-fwnode is built-in, THIS_MODULE evaluates to NULL, which then +overwrites the sensor driver's owner with NULL. + +This causes the problem that the sensor module's reference count is never +incremented during async registration, so the module can be removed while +the subdevice is still in use by a notifier (e.g., a CSI-2 receiver +bridge driver). + +Fix this by renaming v4l2_async_register_subdev_sensor() to +__v4l2_async_register_subdev_sensor() with an added explicit module +argument and introducing a wrapper macro: + #define v4l2_async_register_subdev_sensor(sd) \ + __v4l2_async_register_subdev_sensor(sd, THIS_MODULE) + +This ensures the sensor driver module is properly referenced even when +the sensor driver does not init the owner field before calling +v4l2_async_register_subdev_sensor() and prevents premature module removal. + +Fixes: aef69d54755d ("media: v4l: fwnode: Add a convenience function for registering sensors") +Cc: stable@vger.kernel.org +Suggested-by: Frank Li +Link: https://lore.kernel.org/linux-media/20240315073125.275501-2-sakari.ailus@linux.intel.com/ +Signed-off-by: Mirela Rabulea +Reviewed-by: Laurent Pinchart +Reviewed-by: Frank Li +Signed-off-by: Sakari Ailus +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/media/v4l2-core/v4l2-fwnode.c | 6 +++--- + include/media/v4l2-async.h | 4 +++- + 2 files changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/media/v4l2-core/v4l2-fwnode.c ++++ b/drivers/media/v4l2-core/v4l2-fwnode.c +@@ -1203,7 +1203,7 @@ v4l2_async_nf_parse_fwnode_sensor(struct + return 0; + } + +-int v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd) ++int __v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd, struct module *module) + { + struct v4l2_async_notifier *notifier; + int ret; +@@ -1229,7 +1229,7 @@ int v4l2_async_register_subdev_sensor(st + if (ret < 0) + goto out_cleanup; + +- ret = v4l2_async_register_subdev(sd); ++ ret = __v4l2_async_register_subdev(sd, module); + if (ret < 0) + goto out_unregister; + +@@ -1247,7 +1247,7 @@ out_cleanup: + + return ret; + } +-EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor); ++EXPORT_SYMBOL_GPL(__v4l2_async_register_subdev_sensor); + + MODULE_LICENSE("GPL"); + MODULE_AUTHOR("Sakari Ailus "); +--- a/include/media/v4l2-async.h ++++ b/include/media/v4l2-async.h +@@ -333,8 +333,10 @@ int __v4l2_async_register_subdev(struct + * An error is returned if the module is no longer loaded on any attempts + * to register it. + */ ++#define v4l2_async_register_subdev_sensor(sd) \ ++ __v4l2_async_register_subdev_sensor(sd, THIS_MODULE) + int __must_check +-v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd); ++__v4l2_async_register_subdev_sensor(struct v4l2_subdev *sd, struct module *module); + + /** + * v4l2_async_unregister_subdev - unregisters a sub-device to the asynchronous diff --git a/queue-6.6/mptcp-add-mptcp_userspace_pm_lookup_addr-helper.patch b/queue-6.6/mptcp-add-mptcp_userspace_pm_lookup_addr-helper.patch new file mode 100644 index 0000000000..4d1f99a1db --- /dev/null +++ b/queue-6.6/mptcp-add-mptcp_userspace_pm_lookup_addr-helper.patch @@ -0,0 +1,155 @@ +From stable+bounces-297278-greg=kroah.com@vger.kernel.org Fri Aug 7 13:55:47 2026 +From: Sasha Levin +Date: Fri, 7 Aug 2026 07:48:11 -0400 +Subject: mptcp: add mptcp_userspace_pm_lookup_addr helper +To: stable@vger.kernel.org +Cc: Geliang Tang , "Matthieu Baerts (NGI0)" , Jakub Kicinski , Sasha Levin +Message-ID: <20260807114813.2056374-2-sashal@kernel.org> + +From: Geliang Tang + +[ Upstream commit e7b4083b90b7213902124d13fd1ed808360e32b1 ] + +Like __lookup_addr() helper in pm_netlink.c, a new helper +mptcp_userspace_pm_lookup_addr() is also defined in pm_userspace.c. +It looks up the corresponding mptcp_pm_addr_entry address in +userspace_pm_local_addr_list through the passed "addr" parameter +and returns the found address entry. + +This helper can be used in mptcp_userspace_pm_delete_local_addr(), +mptcp_userspace_pm_set_flags(), mptcp_userspace_pm_get_local_id() +and mptcp_userspace_pm_is_backup() to simplify the code. + +Please note that with this change now list_for_each_entry() is used in +mptcp_userspace_pm_append_new_local_addr(), not list_for_each_entry_safe(), +but that's OK to do so because mptcp_userspace_pm_lookup_addr() only +returns an entry from the list, the list hasn't been modified here. + +Signed-off-by: Geliang Tang +Reviewed-by: Matthieu Baerts (NGI0) +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20241213-net-next-mptcp-pm-misc-cleanup-v1-1-ddb6d00109a8@kernel.org +Signed-off-by: Jakub Kicinski +Stable-dep-of: 9bc6d5e4ca9f ("mptcp: pm: userspace: fix use-after-free in get_local_id") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/mptcp/pm_userspace.c | 71 +++++++++++++++++++++++------------------------ + 1 file changed, 36 insertions(+), 35 deletions(-) + +--- a/net/mptcp/pm_userspace.c ++++ b/net/mptcp/pm_userspace.c +@@ -25,6 +25,19 @@ void mptcp_free_local_addr_list(struct m + } + } + ++static struct mptcp_pm_addr_entry * ++mptcp_userspace_pm_lookup_addr(struct mptcp_sock *msk, ++ const struct mptcp_addr_info *addr) ++{ ++ struct mptcp_pm_addr_entry *entry; ++ ++ list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) { ++ if (mptcp_addresses_equal(&entry->addr, addr, false)) ++ return entry; ++ } ++ return NULL; ++} ++ + static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk, + struct mptcp_pm_addr_entry *entry, + bool needs_id) +@@ -89,22 +102,20 @@ append_err: + static int mptcp_userspace_pm_delete_local_addr(struct mptcp_sock *msk, + struct mptcp_pm_addr_entry *addr) + { +- struct mptcp_pm_addr_entry *entry, *tmp; + struct sock *sk = (struct sock *)msk; ++ struct mptcp_pm_addr_entry *entry; + +- list_for_each_entry_safe(entry, tmp, &msk->pm.userspace_pm_local_addr_list, list) { +- if (mptcp_addresses_equal(&entry->addr, &addr->addr, false)) { +- /* TODO: a refcount is needed because the entry can +- * be used multiple times (e.g. fullmesh mode). +- */ +- list_del_rcu(&entry->list); +- sock_kfree_s(sk, entry, sizeof(*entry)); +- msk->pm.local_addr_used--; +- return 0; +- } +- } +- +- return -EINVAL; ++ entry = mptcp_userspace_pm_lookup_addr(msk, &addr->addr); ++ if (!entry) ++ return -EINVAL; ++ ++ /* TODO: a refcount is needed because the entry can ++ * be used multiple times (e.g. fullmesh mode). ++ */ ++ list_del_rcu(&entry->list); ++ sock_kfree_s(sk, entry, sizeof(*entry)); ++ msk->pm.local_addr_used--; ++ return 0; + } + + static struct mptcp_pm_addr_entry * +@@ -139,17 +150,12 @@ int mptcp_userspace_pm_get_flags_and_ifi + int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk, + struct mptcp_addr_info *skc) + { +- struct mptcp_pm_addr_entry *entry = NULL, *e, new_entry; ++ struct mptcp_pm_addr_entry *entry = NULL, new_entry; + __be16 msk_sport = ((struct inet_sock *) + inet_sk((struct sock *)msk))->inet_sport; + + spin_lock_bh(&msk->pm.lock); +- list_for_each_entry(e, &msk->pm.userspace_pm_local_addr_list, list) { +- if (mptcp_addresses_equal(&e->addr, skc, false)) { +- entry = e; +- break; +- } +- } ++ entry = mptcp_userspace_pm_lookup_addr(msk, skc); + spin_unlock_bh(&msk->pm.lock); + if (entry) + return entry->addr.id; +@@ -169,15 +175,11 @@ bool mptcp_userspace_pm_is_backup(struct + struct mptcp_addr_info *skc) + { + struct mptcp_pm_addr_entry *entry; +- bool backup = false; ++ bool backup; + + spin_lock_bh(&msk->pm.lock); +- list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) { +- if (mptcp_addresses_equal(&entry->addr, skc, false)) { +- backup = !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP); +- break; +- } +- } ++ entry = mptcp_userspace_pm_lookup_addr(msk, skc); ++ backup = entry && !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP); + spin_unlock_bh(&msk->pm.lock); + + return backup; +@@ -591,13 +593,12 @@ int mptcp_userspace_pm_set_flags(struct + goto set_flags_err; + + spin_lock_bh(&msk->pm.lock); +- list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) { +- if (mptcp_addresses_equal(&entry->addr, &loc->addr, false)) { +- if (bkup) +- entry->flags |= MPTCP_PM_ADDR_FLAG_BACKUP; +- else +- entry->flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP; +- } ++ entry = mptcp_userspace_pm_lookup_addr(msk, &loc->addr); ++ if (entry) { ++ if (bkup) ++ entry->flags |= MPTCP_PM_ADDR_FLAG_BACKUP; ++ else ++ entry->flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP; + } + spin_unlock_bh(&msk->pm.lock); + diff --git a/queue-6.6/mptcp-pm-avoid-code-duplication-to-lookup-endp.patch b/queue-6.6/mptcp-pm-avoid-code-duplication-to-lookup-endp.patch new file mode 100644 index 0000000000..5925eb753f --- /dev/null +++ b/queue-6.6/mptcp-pm-avoid-code-duplication-to-lookup-endp.patch @@ -0,0 +1,71 @@ +From stable+bounces-297279-greg=kroah.com@vger.kernel.org Fri Aug 7 13:55:51 2026 +From: Sasha Levin +Date: Fri, 7 Aug 2026 07:48:10 -0400 +Subject: mptcp: pm: avoid code duplication to lookup endp +To: stable@vger.kernel.org +Cc: Geliang Tang , "Matthieu Baerts (NGI0)" , Jakub Kicinski , Sasha Levin +Message-ID: <20260807114813.2056374-1-sashal@kernel.org> + +From: Geliang Tang + +[ Upstream commit 1d7fa6ceb91fddbe38cae3521d5d1075bce6a00e ] + +The helper __lookup_addr() can be used in mptcp_pm_nl_get_local_id() +and mptcp_pm_nl_is_backup() to simplify the code, and avoid code +duplication. + +Co-developed-by: Matthieu Baerts (NGI0) +Signed-off-by: Matthieu Baerts (NGI0) +Signed-off-by: Geliang Tang +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20241115-net-next-mptcp-pm-lockless-dump-v1-2-f4a1bcb4ca2c@kernel.org +Signed-off-by: Jakub Kicinski +Stable-dep-of: 9bc6d5e4ca9f ("mptcp: pm: userspace: fix use-after-free in get_local_id") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/mptcp/pm_netlink.c | 20 ++++++-------------- + 1 file changed, 6 insertions(+), 14 deletions(-) + +--- a/net/mptcp/pm_netlink.c ++++ b/net/mptcp/pm_netlink.c +@@ -1281,17 +1281,13 @@ int mptcp_pm_nl_get_local_id(struct mptc + { + struct mptcp_pm_addr_entry *entry; + struct pm_nl_pernet *pernet; +- int ret = -1; ++ int ret; + + pernet = pm_nl_get_pernet_from_msk(msk); + + rcu_read_lock(); +- list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) { +- if (mptcp_addresses_equal(&entry->addr, skc, entry->addr.port)) { +- ret = entry->addr.id; +- break; +- } +- } ++ entry = __lookup_addr(pernet, skc); ++ ret = entry ? entry->addr.id : -1; + rcu_read_unlock(); + if (ret >= 0) + return ret; +@@ -1318,15 +1314,11 @@ bool mptcp_pm_nl_is_backup(struct mptcp_ + { + struct pm_nl_pernet *pernet = pm_nl_get_pernet_from_msk(msk); + struct mptcp_pm_addr_entry *entry; +- bool backup = false; ++ bool backup; + + rcu_read_lock(); +- list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) { +- if (mptcp_addresses_equal(&entry->addr, skc, entry->addr.port)) { +- backup = !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP); +- break; +- } +- } ++ entry = __lookup_addr(pernet, skc); ++ backup = entry && !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP); + rcu_read_unlock(); + + return backup; diff --git a/queue-6.6/mptcp-pm-use-addr-entry-for-get_local_id.patch b/queue-6.6/mptcp-pm-use-addr-entry-for-get_local_id.patch new file mode 100644 index 0000000000..d533b15f84 --- /dev/null +++ b/queue-6.6/mptcp-pm-use-addr-entry-for-get_local_id.patch @@ -0,0 +1,155 @@ +From stable+bounces-297281-greg=kroah.com@vger.kernel.org Fri Aug 7 13:51:26 2026 +From: Sasha Levin +Date: Fri, 7 Aug 2026 07:48:12 -0400 +Subject: mptcp: pm: use addr entry for get_local_id +To: stable@vger.kernel.org +Cc: Geliang Tang , "Matthieu Baerts (NGI0)" , Jakub Kicinski , Sasha Levin +Message-ID: <20260807114813.2056374-3-sashal@kernel.org> + +From: Geliang Tang + +[ Upstream commit 7462fe22cc74321eb663768848976d42eba3ddbb ] + +The following code in mptcp_userspace_pm_get_local_id() that assigns "skc" +to "new_entry" is not allowed in BPF if we use the same code to implement +the get_local_id() interface of a BFP path manager: + + memset(&new_entry, 0, sizeof(struct mptcp_pm_addr_entry)); + new_entry.addr = *skc; + new_entry.addr.id = 0; + new_entry.flags = MPTCP_PM_ADDR_FLAG_IMPLICIT; + +To solve the issue, this patch moves this assignment to "new_entry" forward +to mptcp_pm_get_local_id(), and then passing "new_entry" as a parameter to +both mptcp_pm_nl_get_local_id() and mptcp_userspace_pm_get_local_id(). + +No behavioural changes intended. + +Signed-off-by: Geliang Tang +Reviewed-by: Matthieu Baerts (NGI0) +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20250307-net-next-mptcp-pm-reorg-v1-1-abef20ada03b@kernel.org +Signed-off-by: Jakub Kicinski +Stable-dep-of: 9bc6d5e4ca9f ("mptcp: pm: userspace: fix use-after-free in get_local_id") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/mptcp/pm.c | 9 ++++++--- + net/mptcp/pm_netlink.c | 11 ++++------- + net/mptcp/pm_userspace.c | 17 ++++++----------- + net/mptcp/protocol.h | 6 ++++-- + 4 files changed, 20 insertions(+), 23 deletions(-) + +--- a/net/mptcp/pm.c ++++ b/net/mptcp/pm.c +@@ -428,7 +428,7 @@ out_unlock: + + int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc) + { +- struct mptcp_addr_info skc_local; ++ struct mptcp_pm_addr_entry skc_local = { 0 }; + struct mptcp_addr_info msk_local; + + if (WARN_ON_ONCE(!msk)) +@@ -438,10 +438,13 @@ int mptcp_pm_get_local_id(struct mptcp_s + * addr + */ + mptcp_local_address((struct sock_common *)msk, &msk_local); +- mptcp_local_address((struct sock_common *)skc, &skc_local); +- if (mptcp_addresses_equal(&msk_local, &skc_local, false)) ++ mptcp_local_address((struct sock_common *)skc, &skc_local.addr); ++ if (mptcp_addresses_equal(&msk_local, &skc_local.addr, false)) + return 0; + ++ skc_local.addr.id = 0; ++ skc_local.flags = MPTCP_PM_ADDR_FLAG_IMPLICIT; ++ + if (mptcp_pm_is_userspace(msk)) + return mptcp_userspace_pm_get_local_id(msk, &skc_local); + return mptcp_pm_nl_get_local_id(msk, &skc_local); +--- a/net/mptcp/pm_netlink.c ++++ b/net/mptcp/pm_netlink.c +@@ -1277,7 +1277,8 @@ static int mptcp_pm_nl_create_listen_soc + return err; + } + +-int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc) ++int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, ++ struct mptcp_pm_addr_entry *skc) + { + struct mptcp_pm_addr_entry *entry; + struct pm_nl_pernet *pernet; +@@ -1286,7 +1287,7 @@ int mptcp_pm_nl_get_local_id(struct mptc + pernet = pm_nl_get_pernet_from_msk(msk); + + rcu_read_lock(); +- entry = __lookup_addr(pernet, skc); ++ entry = __lookup_addr(pernet, &skc->addr); + ret = entry ? entry->addr.id : -1; + rcu_read_unlock(); + if (ret >= 0) +@@ -1297,12 +1298,8 @@ int mptcp_pm_nl_get_local_id(struct mptc + if (!entry) + return -ENOMEM; + +- entry->addr = *skc; +- entry->addr.id = 0; ++ *entry = *skc; + entry->addr.port = 0; +- entry->ifindex = 0; +- entry->flags = MPTCP_PM_ADDR_FLAG_IMPLICIT; +- entry->lsk = NULL; + ret = mptcp_pm_nl_append_new_local_addr(pernet, entry, false); + if (ret < 0) + kfree(entry); +--- a/net/mptcp/pm_userspace.c ++++ b/net/mptcp/pm_userspace.c +@@ -148,27 +148,22 @@ int mptcp_userspace_pm_get_flags_and_ifi + } + + int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk, +- struct mptcp_addr_info *skc) ++ struct mptcp_pm_addr_entry *skc) + { +- struct mptcp_pm_addr_entry *entry = NULL, new_entry; + __be16 msk_sport = ((struct inet_sock *) + inet_sk((struct sock *)msk))->inet_sport; ++ struct mptcp_pm_addr_entry *entry; + + spin_lock_bh(&msk->pm.lock); +- entry = mptcp_userspace_pm_lookup_addr(msk, skc); ++ entry = mptcp_userspace_pm_lookup_addr(msk, &skc->addr); + spin_unlock_bh(&msk->pm.lock); + if (entry) + return entry->addr.id; + +- memset(&new_entry, 0, sizeof(struct mptcp_pm_addr_entry)); +- new_entry.addr = *skc; +- new_entry.addr.id = 0; +- new_entry.flags = MPTCP_PM_ADDR_FLAG_IMPLICIT; ++ if (skc->addr.port == msk_sport) ++ skc->addr.port = 0; + +- if (new_entry.addr.port == msk_sport) +- new_entry.addr.port = 0; +- +- return mptcp_userspace_pm_append_new_local_addr(msk, &new_entry, true); ++ return mptcp_userspace_pm_append_new_local_addr(msk, skc, true); + } + + bool mptcp_userspace_pm_is_backup(struct mptcp_sock *msk, +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -1048,8 +1048,10 @@ bool mptcp_pm_add_addr_signal(struct mpt + bool mptcp_pm_rm_addr_signal(struct mptcp_sock *msk, unsigned int remaining, + struct mptcp_rm_list *rm_list); + int mptcp_pm_get_local_id(struct mptcp_sock *msk, struct sock_common *skc); +-int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc); +-int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc); ++int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, ++ struct mptcp_pm_addr_entry *skc); ++int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk, ++ struct mptcp_pm_addr_entry *skc); + bool mptcp_pm_is_backup(struct mptcp_sock *msk, struct sock_common *skc); + bool mptcp_pm_nl_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc); + bool mptcp_userspace_pm_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc); diff --git a/queue-6.6/mptcp-pm-userspace-fix-use-after-free-in-get_local_id.patch b/queue-6.6/mptcp-pm-userspace-fix-use-after-free-in-get_local_id.patch new file mode 100644 index 0000000000..c4770846b1 --- /dev/null +++ b/queue-6.6/mptcp-pm-userspace-fix-use-after-free-in-get_local_id.patch @@ -0,0 +1,93 @@ +From stable+bounces-297282-greg=kroah.com@vger.kernel.org Fri Aug 7 13:58:29 2026 +From: Sasha Levin +Date: Fri, 7 Aug 2026 07:48:13 -0400 +Subject: mptcp: pm: userspace: fix use-after-free in get_local_id +To: stable@vger.kernel.org +Cc: Geliang Tang , Xuanqiang Luo , "Matthieu Baerts (NGI0)" , Jakub Kicinski , Sasha Levin +Message-ID: <20260807114813.2056374-4-sashal@kernel.org> + +From: Geliang Tang + +[ Upstream commit 9bc6d5e4ca9f3cbb41d43400b3a31cb0403796c9 ] + +In mptcp_pm_userspace_get_local_id(), the address entry is looked up under +spinlock, but its id is read after dropping the lock. A concurrent deletion +can free the entry between the unlock and the read, leading to UAF. + +The race window is narrow. It was reproduced only with a locally +constructed stress test that repeatedly overlaps an MP_JOIN SYN with a +MPTCP_PM_CMD_SUBFLOW_DESTROY request. + +However, the KASAN report below confirms that the race is reachable: + + [ 666.319376] BUG: KASAN: slab-use-after-free in mptcp_userspace_pm_get_local_id+0x1dc/0x1f0 + [ 666.319386] Read of size 1 at addr ffff888124845610 by task swapper/0/0 + ... + [ 666.319401] Call Trace: + [ 666.319405] + [ 666.319408] dump_stack_lvl+0x53/0x70 + [ 666.319412] print_address_description.constprop.0+0x2c/0x3b0 + [ 666.319418] print_report+0xbe/0x2b0 + [ 666.319421] ? mptcp_userspace_pm_get_local_id+0x1dc/0x1f0 + [ 666.319423] kasan_report+0xce/0x100 + [ 666.319426] ? mptcp_userspace_pm_get_local_id+0x1dc/0x1f0 + [ 666.319429] mptcp_userspace_pm_get_local_id+0x1dc/0x1f0 + [ 666.319433] mptcp_pm_get_local_id+0x371/0x440 + ... + [ 666.319821] Allocated by task 45539: + [ 666.319844] kasan_save_stack+0x33/0x60 + [ 666.319855] kasan_save_track+0x14/0x30 + [ 666.319858] __kasan_kmalloc+0x8f/0xa0 + [ 666.319863] __kmalloc_noprof+0x1e7/0x520 + [ 666.319867] sock_kmalloc+0xdf/0x130 + [ 666.319885] sock_kmemdup+0x1b/0x40 + [ 666.319888] mptcp_userspace_pm_append_new_local_addr+0x261/0x500 + [ 666.319910] mptcp_pm_nl_announce_doit+0x16a/0x610 + ... + [ 666.319967] Freed by task 45560: + [ 666.319988] kasan_save_stack+0x33/0x60 + [ 666.319991] kasan_save_track+0x14/0x30 + [ 666.319994] kasan_save_free_info+0x3b/0x60 + [ 666.319998] __kasan_slab_free+0x43/0x70 + [ 666.320000] kfree+0x166/0x440 + [ 666.320003] sock_kfree_s+0x1d/0x50 + [ 666.320007] mptcp_userspace_pm_delete_local_addr.isra.0+0x157/0x200 + [ 666.320011] mptcp_pm_nl_subflow_destroy_doit+0x51d/0xea0 + +Fix by copying the id into a local variable while still holding the lock, +and use -1 as a "not found" sentinel. + +Fixes: f012d796a6de ("mptcp: check addrs list in userspace_pm_get_local_id") +Cc: stable@vger.kernel.org +Signed-off-by: Geliang Tang +Tested-by: Xuanqiang Luo +Reviewed-by: Matthieu Baerts (NGI0) +Signed-off-by: Matthieu Baerts (NGI0) +Link: https://patch.msgid.link/20260722-net-mptcp-misc-fixes-7-2-rc5-v1-2-6fb595bc86ef@kernel.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/mptcp/pm_userspace.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/net/mptcp/pm_userspace.c ++++ b/net/mptcp/pm_userspace.c +@@ -153,12 +153,15 @@ int mptcp_userspace_pm_get_local_id(stru + __be16 msk_sport = ((struct inet_sock *) + inet_sk((struct sock *)msk))->inet_sport; + struct mptcp_pm_addr_entry *entry; ++ int id; + + spin_lock_bh(&msk->pm.lock); + entry = mptcp_userspace_pm_lookup_addr(msk, &skc->addr); ++ id = entry ? entry->addr.id : -1; + spin_unlock_bh(&msk->pm.lock); +- if (entry) +- return entry->addr.id; ++ ++ if (id != -1) ++ return id; + + if (skc->addr.port == msk_sport) + skc->addr.port = 0; diff --git a/queue-6.6/netfilter-nf_tables-clone-set-on-flush-only.patch b/queue-6.6/netfilter-nf_tables-clone-set-on-flush-only.patch new file mode 100644 index 0000000000..227e5c0e4e --- /dev/null +++ b/queue-6.6/netfilter-nf_tables-clone-set-on-flush-only.patch @@ -0,0 +1,136 @@ +From stable+bounces-296811-greg=kroah.com@vger.kernel.org Thu Aug 6 15:13:08 2026 +From: Sasha Levin +Date: Thu, 6 Aug 2026 09:06:52 -0400 +Subject: netfilter: nf_tables: clone set on flush only +To: stable@vger.kernel.org +Cc: Pablo Neira Ayuso , syzbot+4924a0edc148e8b4b342@syzkaller.appspotmail.com, Florian Westphal , Sasha Levin +Message-ID: <20260806130652.335098-1-sashal@kernel.org> + +From: Pablo Neira Ayuso + +[ Upstream commit fb7fb4016300ac622c964069e286dc83166a5d52 ] + +Syzbot with fault injection triggered a failing memory allocation with +GFP_KERNEL which results in a WARN splat: + +iter.err +WARNING: net/netfilter/nf_tables_api.c:845 at nft_map_deactivate+0x34e/0x3c0 net/netfilter/nf_tables_api.c:845, CPU#0: syz.0.17/5992 +Modules linked in: +CPU: 0 UID: 0 PID: 5992 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full) +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/12/2026 +RIP: 0010:nft_map_deactivate+0x34e/0x3c0 net/netfilter/nf_tables_api.c:845 +Code: 8b 05 86 5a 4e 09 48 3b 84 24 a0 00 00 00 75 62 48 8d 65 d8 5b 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc cc e8 63 6d fa f7 90 <0f> 0b 90 43 ++80 7c 35 00 00 0f 85 23 fe ff ff e9 26 fe ff ff 89 d9 +RSP: 0018:ffffc900045af780 EFLAGS: 00010293 +RAX: ffffffff89ca45bd RBX: 00000000fffffff4 RCX: ffff888028111e40 +RDX: 0000000000000000 RSI: 00000000fffffff4 RDI: 0000000000000000 +RBP: ffffc900045af870 R08: 0000000000400dc0 R09: 00000000ffffffff +R10: dffffc0000000000 R11: fffffbfff1d141db R12: ffffc900045af7e0 +R13: 1ffff920008b5f24 R14: dffffc0000000000 R15: ffffc900045af920 +FS: 000055557a6a5500(0000) GS:ffff888125496000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007fb5ea271fc0 CR3: 000000003269e000 CR4: 00000000003526f0 +Call Trace: + + __nft_release_table+0xceb/0x11f0 net/netfilter/nf_tables_api.c:12115 + nft_rcv_nl_event+0xc25/0xdb0 net/netfilter/nf_tables_api.c:12187 + notifier_call_chain+0x19d/0x3a0 kernel/notifier.c:85 + blocking_notifier_call_chain+0x6a/0x90 kernel/notifier.c:380 + netlink_release+0x123b/0x1ad0 net/netlink/af_netlink.c:761 + __sock_release net/socket.c:662 [inline] + sock_close+0xc3/0x240 net/socket.c:1455 + +Restrict set clone to the flush set command in the preparation phase. +Add NFT_ITER_UPDATE_CLONE and use it for this purpose, update the rbtree +and pipapo backends to only clone the set when this iteration type is +used. + +As for the existing NFT_ITER_UPDATE type, update the pipapo backend to +use the existing set clone if available, otherwise use the existing set +representation. After this update, there is no need to clone a set that +is being deleted, this includes bound anonymous set. + +An alternative approach to NFT_ITER_UPDATE_CLONE is to add a .clone +interface and call it from the flush set path. + +Reported-by: syzbot+4924a0edc148e8b4b342@syzkaller.appspotmail.com +Fixes: 3f1d886cc7c3 ("netfilter: nft_set_pipapo: move cloning of match info to insert/removal path") +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + include/net/netfilter/nf_tables.h | 2 ++ + net/netfilter/nf_tables_api.c | 10 +++++++++- + net/netfilter/nft_set_pipapo.c | 11 +++++++++-- + 3 files changed, 20 insertions(+), 3 deletions(-) + +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -302,11 +302,13 @@ struct nft_set_elem { + * + * @NFT_ITER_READ: read-only iteration over set elements + * @NFT_ITER_UPDATE: iteration under mutex to update set element state ++ * @NFT_ITER_UPDATE_CLONE: clone set before iteration under mutex to update element + */ + enum nft_iter_type { + NFT_ITER_UNSPEC, + NFT_ITER_READ, + NFT_ITER_UPDATE, ++ NFT_ITER_UPDATE_CLONE, + }; + + struct nft_set; +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -655,6 +655,11 @@ static void nft_map_catchall_deactivate( + } + } + ++/* Use NFT_ITER_UPDATE iterator even if this may be called from the preparation ++ * phase, the set clone might already exist from a previous command, or it might ++ * be a set that is going away and does not require a clone. The netns and ++ * netlink release paths also need to work on the live set. ++ */ + static void nft_map_deactivate(const struct nft_ctx *ctx, struct nft_set *set) + { + struct nft_set_iter iter = { +@@ -7396,9 +7401,12 @@ static int nft_set_catchall_flush(const + + static int nft_set_flush(struct nft_ctx *ctx, struct nft_set *set, u8 genmask) + { ++ /* The set backend might need to clone the set, do it now from the ++ * preparation phase, use NFT_ITER_UPDATE_CLONE iterator type. ++ */ + struct nft_set_iter iter = { + .genmask = genmask, +- .type = NFT_ITER_UPDATE, ++ .type = NFT_ITER_UPDATE_CLONE, + .fn = nft_setelem_flush, + }; + +--- a/net/netfilter/nft_set_pipapo.c ++++ b/net/netfilter/nft_set_pipapo.c +@@ -2199,13 +2199,20 @@ static void nft_pipapo_walk(const struct + const struct nft_pipapo_match *m; + + switch (iter->type) { +- case NFT_ITER_UPDATE: ++ case NFT_ITER_UPDATE_CLONE: + m = pipapo_maybe_clone(set); + if (!m) { + iter->err = -ENOMEM; + return; + } +- ++ nft_pipapo_do_walk(ctx, set, m, iter); ++ break; ++ case NFT_ITER_UPDATE: ++ if (priv->clone) ++ m = priv->clone; ++ else ++ m = rcu_dereference_protected(priv->match, ++ nft_pipapo_transaction_mutex_held(set)); + nft_pipapo_do_walk(ctx, set, m, iter); + break; + case NFT_ITER_READ: diff --git a/queue-6.6/rxrpc-fix-irq-disabled-in-local_bh_enable.patch b/queue-6.6/rxrpc-fix-irq-disabled-in-local_bh_enable.patch new file mode 100644 index 0000000000..31f98fa140 --- /dev/null +++ b/queue-6.6/rxrpc-fix-irq-disabled-in-local_bh_enable.patch @@ -0,0 +1,148 @@ +From stable+bounces-296804-greg=kroah.com@vger.kernel.org Thu Aug 6 14:49:19 2026 +From: Sasha Levin +Date: Thu, 6 Aug 2026 08:46:13 -0400 +Subject: rxrpc: Fix irq-disabled in local_bh_enable() +To: stable@vger.kernel.org +Cc: David Howells , Jeffrey Altman , Marc Dionne , "Junvyyang, Tencent Zhuque Lab" , LePremierHomme , Simon Horman , linux-afs@lists.infradead.org, Jakub Kicinski , Sasha Levin +Message-ID: <20260806124613.299390-1-sashal@kernel.org> + +From: David Howells + +[ Upstream commit e4d2878369d590bf8455e3678a644e503172eafa ] + +The rxrpc_assess_MTU_size() function calls down into the IP layer to find +out the MTU size for a route. When accepting an incoming call, this is +called from rxrpc_new_incoming_call() which holds interrupts disabled +across the code that calls down to it. Unfortunately, the IP layer uses +local_bh_enable() which, config dependent, throws a warning if IRQs are +enabled: + +WARNING: CPU: 1 PID: 5544 at kernel/softirq.c:387 __local_bh_enable_ip+0x43/0xd0 +... +RIP: 0010:__local_bh_enable_ip+0x43/0xd0 +... +Call Trace: + + rt_cache_route+0x7e/0xa0 + rt_set_nexthop.isra.0+0x3b3/0x3f0 + __mkroute_output+0x43a/0x460 + ip_route_output_key_hash+0xf7/0x140 + ip_route_output_flow+0x1b/0x90 + rxrpc_assess_MTU_size.isra.0+0x2a0/0x590 + rxrpc_new_incoming_peer+0x46/0x120 + rxrpc_alloc_incoming_call+0x1b1/0x400 + rxrpc_new_incoming_call+0x1da/0x5e0 + rxrpc_input_packet+0x827/0x900 + rxrpc_io_thread+0x403/0xb60 + kthread+0x2f7/0x310 + ret_from_fork+0x2a/0x230 + ret_from_fork_asm+0x1a/0x30 +... +hardirqs last enabled at (23): _raw_spin_unlock_irq+0x24/0x50 +hardirqs last disabled at (24): _raw_read_lock_irq+0x17/0x70 +softirqs last enabled at (0): copy_process+0xc61/0x2730 +softirqs last disabled at (25): rt_add_uncached_list+0x3c/0x90 + +Fix this by moving the call to rxrpc_assess_MTU_size() out of +rxrpc_init_peer() and further up the stack where it can be done without +interrupts disabled. + +It shouldn't be a problem for rxrpc_new_incoming_call() to do it after the +locks are dropped as pmtud is going to be performed by the I/O thread - and +we're in the I/O thread at this point. + +Fixes: a2ea9a907260 ("rxrpc: Use irq-disabling spinlocks between app and I/O thread") +Signed-off-by: David Howells +Reviewed-by: Jeffrey Altman +cc: Marc Dionne +cc: Junvyyang, Tencent Zhuque Lab +cc: LePremierHomme +cc: Simon Horman +cc: linux-afs@lists.infradead.org +Link: https://patch.msgid.link/20250717074350.3767366-2-dhowells@redhat.com +Signed-off-by: Jakub Kicinski +[ moved `peer->mtu`/`peer->maxdata` derivation into `rxrpc_assess_MTU_size()` at both exits since 6.12 predates the `max_data` rework ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/rxrpc/ar-internal.h | 1 + + net/rxrpc/call_accept.c | 1 + + net/rxrpc/peer_object.c | 12 +++++++----- + 3 files changed, 9 insertions(+), 5 deletions(-) + +--- a/net/rxrpc/ar-internal.h ++++ b/net/rxrpc/ar-internal.h +@@ -1188,6 +1188,7 @@ struct rxrpc_peer *rxrpc_lookup_peer_rcu + const struct sockaddr_rxrpc *); + struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_local *local, + struct sockaddr_rxrpc *srx, gfp_t gfp); ++void rxrpc_assess_MTU_size(struct rxrpc_local *local, struct rxrpc_peer *peer); + struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *, gfp_t, + enum rxrpc_peer_trace); + void rxrpc_new_incoming_peer(struct rxrpc_local *local, struct rxrpc_peer *peer); +--- a/net/rxrpc/call_accept.c ++++ b/net/rxrpc/call_accept.c +@@ -407,6 +407,7 @@ bool rxrpc_new_incoming_call(struct rxrp + + spin_unlock(&rx->incoming_lock); + read_unlock_irq(&local->services_lock); ++ rxrpc_assess_MTU_size(local, call->peer); + + if (hlist_unhashed(&call->error_link)) { + spin_lock_irq(&call->peer->lock); +--- a/net/rxrpc/peer_object.c ++++ b/net/rxrpc/peer_object.c +@@ -147,8 +147,7 @@ struct rxrpc_peer *rxrpc_lookup_peer_rcu + * assess the MTU size for the network interface through which this peer is + * reached + */ +-static void rxrpc_assess_MTU_size(struct rxrpc_local *local, +- struct rxrpc_peer *peer) ++void rxrpc_assess_MTU_size(struct rxrpc_local *local, struct rxrpc_peer *peer) + { + struct net *net = local->net; + struct dst_entry *dst; +@@ -160,6 +159,8 @@ static void rxrpc_assess_MTU_size(struct + #endif + + peer->if_mtu = 1500; ++ peer->mtu = peer->if_mtu; ++ peer->maxdata = peer->mtu - peer->hdrsize; + + memset(&fl, 0, sizeof(fl)); + switch (peer->srx.transport.family) { +@@ -199,6 +200,9 @@ static void rxrpc_assess_MTU_size(struct + peer->if_mtu = dst_mtu(dst); + dst_release(dst); + ++ peer->mtu = peer->if_mtu; ++ peer->maxdata = peer->mtu - peer->hdrsize; ++ + _leave(" [if_mtu %u]", peer->if_mtu); + } + +@@ -240,8 +244,6 @@ static void rxrpc_init_peer(struct rxrpc + unsigned long hash_key) + { + peer->hash_key = hash_key; +- rxrpc_assess_MTU_size(local, peer); +- peer->mtu = peer->if_mtu; + peer->rtt_last_req = ktime_get_real(); + + switch (peer->srx.transport.family) { +@@ -266,7 +268,6 @@ static void rxrpc_init_peer(struct rxrpc + } + + peer->hdrsize += sizeof(struct rxrpc_wire_header); +- peer->maxdata = peer->mtu - peer->hdrsize; + } + + /* +@@ -285,6 +286,7 @@ static struct rxrpc_peer *rxrpc_create_p + if (peer) { + memcpy(&peer->srx, srx, sizeof(*srx)); + rxrpc_init_peer(local, peer, hash_key); ++ rxrpc_assess_MTU_size(local, peer); + } + + _leave(" = %p", peer); diff --git a/queue-6.6/sctp-avoid-auth_enable-sysctl-uaf-during-netns-teardown.patch b/queue-6.6/sctp-avoid-auth_enable-sysctl-uaf-during-netns-teardown.patch new file mode 100644 index 0000000000..15ad8b9640 --- /dev/null +++ b/queue-6.6/sctp-avoid-auth_enable-sysctl-uaf-during-netns-teardown.patch @@ -0,0 +1,134 @@ +From stable+bounces-297098-greg=kroah.com@vger.kernel.org Fri Aug 7 04:36:10 2026 +From: Sasha Levin +Date: Thu, 6 Aug 2026 22:35:56 -0400 +Subject: sctp: avoid auth_enable sysctl UAF during netns teardown +To: stable@vger.kernel.org +Cc: Zhiling Zou , Yuan Tan , Yifan Wu , Juefei Pu , Xin Liu , Qi Tang , Ren Wei , Xin Long , Jakub Kicinski , Sasha Levin +Message-ID: <20260807023556.1682974-2-sashal@kernel.org> + +From: Zhiling Zou + +[ Upstream commit f8d5e7846025f4ab15a461235f8ebae9094a361a ] + +proc_sctp_do_auth() updates the SCTP control socket after changing +net.sctp.auth_enable. The handler gets the per-net SCTP state from +ctl->data, so an already opened sysctl file can still target a network +namespace while that namespace is being torn down. + +SCTP previously registered its per-net sysctls from sctp_defaults_init(), +while the control socket is created later from sctp_ctrlsock_init(). This +exposed a window during initialization where auth_enable was writable +before net->sctp.ctl_sock existed, and a teardown window where auth_enable +stayed writable after inet_ctl_sock_destroy() had released the control +socket. + +Move the per-net SCTP sysctl registration into sctp_ctrlsock_init() after +sctp_ctl_sock_init() succeeds, and unregister the sysctl table before +destroying the control socket in sctp_ctrlsock_exit(). If sysctl +registration fails after the control socket was created, destroy the +control socket in the same init path. + +Make sctp_sysctl_net_unregister() tolerate a missing header and clear the +saved pointer so init-error and exit paths can safely share the unregister +helper. + +Fixes: 15649fd5415e ("sctp: sysctl: auth_enable: avoid using current->nsproxy") +Cc: stable@vger.kernel.org +Reported-by: Yuan Tan +Reported-by: Yifan Wu +Reported-by: Juefei Pu +Reported-by: Xin Liu +Co-developed-by: Qi Tang +Signed-off-by: Qi Tang +Signed-off-by: Zhiling Zou +Signed-off-by: Ren Wei +Acked-by: Xin Long +Link: https://patch.msgid.link/390cd5e91ed60eea27b0b64d0468301a9e73b808.1784033357.git.roxy520tt@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/protocol.c | 20 ++++++++++++-------- + net/sctp/sysctl.c | 9 +++++++-- + 2 files changed, 19 insertions(+), 10 deletions(-) + +--- a/net/sctp/protocol.c ++++ b/net/sctp/protocol.c +@@ -1394,10 +1394,6 @@ static int __net_init sctp_defaults_init + net->sctp.l3mdev_accept = 1; + #endif + +- status = sctp_sysctl_net_register(net); +- if (status) +- goto err_sysctl_register; +- + /* Allocate and initialise sctp mibs. */ + status = init_sctp_mibs(net); + if (status) +@@ -1431,8 +1427,6 @@ err_init_proc: + cleanup_sctp_mibs(net); + #endif + err_init_mibs: +- sctp_sysctl_net_unregister(net); +-err_sysctl_register: + return status; + } + +@@ -1447,7 +1441,6 @@ static void __net_exit sctp_defaults_exi + net->sctp.proc_net_sctp = NULL; + #endif + cleanup_sctp_mibs(net); +- sctp_sysctl_net_unregister(net); + } + + static struct pernet_operations sctp_defaults_ops = { +@@ -1461,16 +1454,27 @@ static int __net_init sctp_ctrlsock_init + + /* Initialize the control inode/socket for handling OOTB packets. */ + status = sctp_ctl_sock_init(net); +- if (status) ++ if (status) { + pr_err("Failed to initialize the SCTP control sock\n"); ++ return status; ++ } ++ ++ status = sctp_sysctl_net_register(net); ++ if (status) { ++ inet_ctl_sock_destroy(net->sctp.ctl_sock); ++ net->sctp.ctl_sock = NULL; ++ } + + return status; + } + + static void __net_exit sctp_ctrlsock_exit(struct net *net) + { ++ sctp_sysctl_net_unregister(net); ++ + /* Free the control endpoint. */ + inet_ctl_sock_destroy(net->sctp.ctl_sock); ++ net->sctp.ctl_sock = NULL; + } + + static struct pernet_operations sctp_ctrlsock_ops = { +--- a/net/sctp/sysctl.c ++++ b/net/sctp/sysctl.c +@@ -630,11 +630,16 @@ int sctp_sysctl_net_register(struct net + + void sctp_sysctl_net_unregister(struct net *net) + { ++ struct ctl_table_header *header = net->sctp.sysctl_header; + const struct ctl_table *table; + +- table = net->sctp.sysctl_header->ctl_table_arg; +- unregister_net_sysctl_table(net->sctp.sysctl_header); ++ if (!header) ++ return; ++ ++ table = header->ctl_table_arg; ++ unregister_net_sysctl_table(header); + kfree(table); ++ net->sctp.sysctl_header = NULL; + } + + static struct ctl_table_header *sctp_sysctl_header; diff --git a/queue-6.6/sctp-close-udp-tunnel-sockets-during-netns-teardown.patch b/queue-6.6/sctp-close-udp-tunnel-sockets-during-netns-teardown.patch new file mode 100644 index 0000000000..d42ee66aaf --- /dev/null +++ b/queue-6.6/sctp-close-udp-tunnel-sockets-during-netns-teardown.patch @@ -0,0 +1,47 @@ +From stable+bounces-297287-greg=kroah.com@vger.kernel.org Fri Aug 7 13:55:49 2026 +From: Sasha Levin +Date: Fri, 7 Aug 2026 07:48:23 -0400 +Subject: sctp: close UDP tunnel sockets during netns teardown +To: stable@vger.kernel.org +Cc: Zhiling Zou , Sashiko , Ren Wei , Xin Long , Jakub Kicinski , Sasha Levin +Message-ID: <20260807114823.2056694-3-sashal@kernel.org> + +From: Zhiling Zou + +[ Upstream commit ffb2bd7ade36ec4da32c46a6eddbf4515316d08c ] + +proc_sctp_do_udp_port() starts per-net SCTP UDP tunneling sockets when +net.sctp.udp_port is set, and stops/restarts them when the sysctl value +changes. The netns exit path does not stop these sockets, so a namespace +can be torn down while its SCTP UDP tunnel sockets are still installed. + +Close the UDP tunnel sockets from sctp_ctrlsock_exit() after unregistering +the per-net sysctl table. This prevents new sysctl writes from racing in +while the sockets are being released, and closes the sockets before the +control socket is destroyed. + +Fixes: 046c052b475e ("sctp: enable udp tunneling socks") +Cc: stable@vger.kernel.org +Reported-by: Sashiko +Closes: https://sashiko.dev/#/patchset/b9f1f02b0780ad6a719e2413f5f0bb8eb7702d94.1782585631.git.roxy520tt%40gmail.com +Signed-off-by: Zhiling Zou +Signed-off-by: Ren Wei +Acked-by: Xin Long +Link: https://patch.msgid.link/6dab75f22855cb219e2e30a5497cab03b970ab91.1784033357.git.roxy520tt@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/protocol.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/sctp/protocol.c ++++ b/net/sctp/protocol.c +@@ -1471,6 +1471,7 @@ static int __net_init sctp_ctrlsock_init + static void __net_exit sctp_ctrlsock_exit(struct net *net) + { + sctp_sysctl_net_unregister(net); ++ sctp_udp_sock_stop(net); + + /* Free the control endpoint. */ + inet_ctl_sock_destroy(net->sctp.ctl_sock); diff --git a/queue-6.6/series b/queue-6.6/series index eef58279d2..0348a7ef1d 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -211,3 +211,43 @@ mm-huge_memory-unlock-i_mmap_rwsem-before-releasing-.patch firmware-stratix10-svc-fix-memory-leaks-and-list-cor.patch gpio-pch-use-raw_spinlock_t-for-the-register-lock.patch revert-ia64-make-acpi_cpufreq_cpu_exit-return-void.patch +usb-musb-omap2430-clean-up-probe-error-handling.patch +usb-musb-omap2430-do-not-put-borrowed-of_node-in-probe.patch +drm-renesas-move-rz-g2l-mipi-dsi-driver-to-rz-du.patch +drm-renesas-rzg2l_mipi_dsi-increase-reset-deassertion-delay.patch +usb-gadget-f_tcm-synchronize-delayed-set_alt-with-teardown.patch +usb-typec-ucsi-only-enable-supported-notifications.patch +usb-typec-ucsi-split-connector-lock-classes.patch +usb-typec-ucsi-fix-race-condition-and-ordering-in-port-unregistration.patch +drm-fb-helper-allocate-and-release-fb_info-in-single-place.patch +drm-tegra-fbdev-remove-offset-into-framebuffer-memory.patch +drm-amdgpu-respect-placement-requirements-in-amdgpu_gtt_mgr-functions.patch +drm-i915-vrr-check-has_vrr-first-in-intel_vrr_is_capable.patch +drm-i915-vrr-require-valid-min-max-vfreq-for-vrr.patch +media-i2c-imx219-access-height-from-active-format-in-imx219_set_ctrl.patch +media-i2c-imx219-don-t-store-the-current-mode-in-the-imx219-structure.patch +media-i2c-imx219-drop-imx219_vts_-macros.patch +media-i2c-imx219-group-functions-by-purpose.patch +media-i2c-imx219-calculate-crop-rectangle-dynamically.patch +media-i2c-imx219-rename-vts-to-frm_length.patch +media-imx219-fix-maximum-frame-length-in-lines.patch +rxrpc-fix-irq-disabled-in-local_bh_enable.patch +netfilter-nf_tables-clone-set-on-flush-only.patch +media-v4l-async-set-owner-for-async-sub-devices.patch +media-v4l2-fwnode-fix-subdev-owner-overwritten-in-v4l2_async_register_subdev_sensor.patch +wifi-ath6kl-fix-use-after-free-in-aggr_reset_state.patch +wifi-brcmfmac-fix-43752-sdio-fwvid-incorrectly-labelled-as-cypress-cyw.patch +wifi-brcmfmac-set-f2-blocksize-to-256-for-bcm43752.patch +wifi-brcmfmac-drain-bus_reset-work-on-device-removal.patch +sysctl-treewide-constify-ctl_table_header-ctl_table_arg.patch +sctp-avoid-auth_enable-sysctl-uaf-during-netns-teardown.patch +can-use-skb-hash-instead-of-private-variable-in-headroom.patch +can-isotp-fix-timer-drain-order-wakeup-handling-and-tx_gen-ordering.patch +libceph-add-doutc-and-_client-debug-macros-support.patch +ceph-print-cluster-fsid-and-client-global_id-in-all-debug-logs.patch +ceph-fix-refcount-leak-in-ceph_readdir.patch +mptcp-pm-avoid-code-duplication-to-lookup-endp.patch +mptcp-add-mptcp_userspace_pm_lookup_addr-helper.patch +mptcp-pm-use-addr-entry-for-get_local_id.patch +mptcp-pm-userspace-fix-use-after-free-in-get_local_id.patch +sctp-close-udp-tunnel-sockets-during-netns-teardown.patch diff --git a/queue-6.6/sysctl-treewide-constify-ctl_table_header-ctl_table_arg.patch b/queue-6.6/sysctl-treewide-constify-ctl_table_header-ctl_table_arg.patch new file mode 100644 index 0000000000..b2b057b2d3 --- /dev/null +++ b/queue-6.6/sysctl-treewide-constify-ctl_table_header-ctl_table_arg.patch @@ -0,0 +1,367 @@ +From stable+bounces-297097-greg=kroah.com@vger.kernel.org Fri Aug 7 04:36:09 2026 +From: Sasha Levin +Date: Thu, 6 Aug 2026 22:35:55 -0400 +Subject: sysctl: treewide: constify ctl_table_header::ctl_table_arg +To: stable@vger.kernel.org +Cc: "Thomas Weißschuh" , "Kees Cook" , "David S. Miller" , "Sasha Levin" +Message-ID: <20260807023556.1682974-1-sashal@kernel.org> + +From: Thomas Weißschuh + +[ Upstream commit bfa858f220ab8c950dd3e1310fee61950d0ecdae ] + +To be able to constify instances of struct ctl_tables it is necessary to +remove ways through which non-const versions are exposed from the +sysctl core. +One of these is the ctl_table_arg member of struct ctl_table_header. + +Constify this reference as a prerequisite for the full constification of +struct ctl_table instances. +No functional change. + +Signed-off-by: Thomas Weißschuh +Reviewed-by: Kees Cook +Signed-off-by: David S. Miller +Stable-dep-of: f8d5e7846025 ("sctp: avoid auth_enable sysctl UAF during netns teardown") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/vrf.c | 2 +- + include/linux/sysctl.h | 2 +- + ipc/ipc_sysctl.c | 2 +- + ipc/mq_sysctl.c | 2 +- + kernel/ucount.c | 2 +- + net/ax25/sysctl_net_ax25.c | 2 +- + net/bridge/br_netfilter_hooks.c | 2 +- + net/core/sysctl_net_core.c | 2 +- + net/ieee802154/6lowpan/reassembly.c | 2 +- + net/ipv4/devinet.c | 2 +- + net/ipv4/ip_fragment.c | 2 +- + net/ipv4/route.c | 2 +- + net/ipv4/sysctl_net_ipv4.c | 2 +- + net/ipv4/xfrm4_policy.c | 2 +- + net/ipv6/addrconf.c | 2 +- + net/ipv6/netfilter/nf_conntrack_reasm.c | 2 +- + net/ipv6/reassembly.c | 2 +- + net/ipv6/sysctl_net_ipv6.c | 6 +++--- + net/ipv6/xfrm6_policy.c | 2 +- + net/mpls/af_mpls.c | 4 ++-- + net/mptcp/ctrl.c | 2 +- + net/netfilter/nf_conntrack_standalone.c | 2 +- + net/netfilter/nf_log.c | 2 +- + net/sctp/sysctl.c | 2 +- + net/smc/smc_sysctl.c | 2 +- + net/unix/sysctl_net_unix.c | 2 +- + net/xfrm/xfrm_sysctl.c | 2 +- + 27 files changed, 30 insertions(+), 30 deletions(-) + +--- a/drivers/net/vrf.c ++++ b/drivers/net/vrf.c +@@ -1983,7 +1983,7 @@ static int vrf_netns_init_sysctl(struct + static void vrf_netns_exit_sysctl(struct net *net) + { + struct netns_vrf *nn_vrf = net_generic(net, vrf_net_id); +- struct ctl_table *table; ++ const struct ctl_table *table; + + table = nn_vrf->ctl_hdr->ctl_table_arg; + unregister_net_sysctl_table(nn_vrf->ctl_hdr); +--- a/include/linux/sysctl.h ++++ b/include/linux/sysctl.h +@@ -182,7 +182,7 @@ struct ctl_table_header { + struct rcu_head rcu; + }; + struct completion *unregistering; +- struct ctl_table *ctl_table_arg; ++ const struct ctl_table *ctl_table_arg; + struct ctl_table_root *root; + struct ctl_table_set *set; + struct ctl_dir *parent; +--- a/ipc/ipc_sysctl.c ++++ b/ipc/ipc_sysctl.c +@@ -306,7 +306,7 @@ bool setup_ipc_sysctls(struct ipc_namesp + + void retire_ipc_sysctls(struct ipc_namespace *ns) + { +- struct ctl_table *tbl; ++ const struct ctl_table *tbl; + + tbl = ns->ipc_sysctls->ctl_table_arg; + unregister_sysctl_table(ns->ipc_sysctls); +--- a/ipc/mq_sysctl.c ++++ b/ipc/mq_sysctl.c +@@ -159,7 +159,7 @@ bool setup_mq_sysctls(struct ipc_namespa + + void retire_mq_sysctls(struct ipc_namespace *ns) + { +- struct ctl_table *tbl; ++ const struct ctl_table *tbl; + + tbl = ns->mq_sysctls->ctl_table_arg; + unregister_sysctl_table(ns->mq_sysctls); +--- a/kernel/ucount.c ++++ b/kernel/ucount.c +@@ -119,7 +119,7 @@ bool setup_userns_sysctls(struct user_na + void retire_userns_sysctls(struct user_namespace *ns) + { + #ifdef CONFIG_SYSCTL +- struct ctl_table *tbl; ++ const struct ctl_table *tbl; + + tbl = ns->sysctls->ctl_table_arg; + unregister_sysctl_table(ns->sysctls); +--- a/net/ax25/sysctl_net_ax25.c ++++ b/net/ax25/sysctl_net_ax25.c +@@ -171,7 +171,7 @@ int ax25_register_dev_sysctl(ax25_dev *a + void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev) + { + struct ctl_table_header *header = ax25_dev->sysheader; +- struct ctl_table *table; ++ const struct ctl_table *table; + + if (header) { + ax25_dev->sysheader = NULL; +--- a/net/bridge/br_netfilter_hooks.c ++++ b/net/bridge/br_netfilter_hooks.c +@@ -1290,7 +1290,7 @@ static int br_netfilter_sysctl_init_net( + static void br_netfilter_sysctl_exit_net(struct net *net, + struct brnf_net *brnet) + { +- struct ctl_table *table = brnet->ctl_hdr->ctl_table_arg; ++ const struct ctl_table *table = brnet->ctl_hdr->ctl_table_arg; + + unregister_net_sysctl_table(brnet->ctl_hdr); + if (!net_eq(net, &init_net)) +--- a/net/core/sysctl_net_core.c ++++ b/net/core/sysctl_net_core.c +@@ -741,7 +741,7 @@ err_dup: + + static __net_exit void sysctl_core_net_exit(struct net *net) + { +- struct ctl_table *tbl; ++ const struct ctl_table *tbl; + + tbl = net->core.sysctl_hdr->ctl_table_arg; + unregister_net_sysctl_table(net->core.sysctl_hdr); +--- a/net/ieee802154/6lowpan/reassembly.c ++++ b/net/ieee802154/6lowpan/reassembly.c +@@ -399,7 +399,7 @@ err_alloc: + + static void __net_exit lowpan_frags_ns_sysctl_unregister(struct net *net) + { +- struct ctl_table *table; ++ const struct ctl_table *table; + struct netns_ieee802154_lowpan *ieee802154_lowpan = + net_ieee802154_lowpan(net); + +--- a/net/ipv4/devinet.c ++++ b/net/ipv4/devinet.c +@@ -2793,7 +2793,7 @@ err_alloc_all: + static __net_exit void devinet_exit_net(struct net *net) + { + #ifdef CONFIG_SYSCTL +- struct ctl_table *tbl; ++ const struct ctl_table *tbl; + + tbl = net->ipv4.forw_hdr->ctl_table_arg; + unregister_net_sysctl_table(net->ipv4.forw_hdr); +--- a/net/ipv4/ip_fragment.c ++++ b/net/ipv4/ip_fragment.c +@@ -632,7 +632,7 @@ err_alloc: + + static void __net_exit ip4_frags_ns_ctl_unregister(struct net *net) + { +- struct ctl_table *table; ++ const struct ctl_table *table; + + table = net->ipv4.frags_hdr->ctl_table_arg; + unregister_net_sysctl_table(net->ipv4.frags_hdr); +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -3621,7 +3621,7 @@ err_dup: + + static __net_exit void sysctl_route_net_exit(struct net *net) + { +- struct ctl_table *tbl; ++ const struct ctl_table *tbl; + + tbl = net->ipv4.route_hdr->ctl_table_arg; + unregister_net_sysctl_table(net->ipv4.route_hdr); +--- a/net/ipv4/sysctl_net_ipv4.c ++++ b/net/ipv4/sysctl_net_ipv4.c +@@ -1564,7 +1564,7 @@ err_alloc: + + static __net_exit void ipv4_sysctl_exit_net(struct net *net) + { +- struct ctl_table *table; ++ const struct ctl_table *table; + + table = net->ipv4.ipv4_hdr->ctl_table_arg; + unregister_net_sysctl_table(net->ipv4.ipv4_hdr); +--- a/net/ipv4/xfrm4_policy.c ++++ b/net/ipv4/xfrm4_policy.c +@@ -182,7 +182,7 @@ err_alloc: + + static __net_exit void xfrm4_net_sysctl_exit(struct net *net) + { +- struct ctl_table *table; ++ const struct ctl_table *table; + + if (!net->ipv4.xfrm4_hdr) + return; +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -7251,7 +7251,7 @@ out: + static void __addrconf_sysctl_unregister(struct net *net, + struct ipv6_devconf *p, int ifindex) + { +- struct ctl_table *table; ++ const struct ctl_table *table; + + if (!p->sysctl_header) + return; +--- a/net/ipv6/netfilter/nf_conntrack_reasm.c ++++ b/net/ipv6/netfilter/nf_conntrack_reasm.c +@@ -105,7 +105,7 @@ err_alloc: + static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net) + { + struct nft_ct_frag6_pernet *nf_frag = nf_frag_pernet(net); +- struct ctl_table *table; ++ const struct ctl_table *table; + + table = nf_frag->nf_frag_frags_hdr->ctl_table_arg; + unregister_net_sysctl_table(nf_frag->nf_frag_frags_hdr); +--- a/net/ipv6/reassembly.c ++++ b/net/ipv6/reassembly.c +@@ -487,7 +487,7 @@ err_alloc: + + static void __net_exit ip6_frags_ns_sysctl_unregister(struct net *net) + { +- struct ctl_table *table; ++ const struct ctl_table *table; + + table = net->ipv6.sysctl.frags_hdr->ctl_table_arg; + unregister_net_sysctl_table(net->ipv6.sysctl.frags_hdr); +--- a/net/ipv6/sysctl_net_ipv6.c ++++ b/net/ipv6/sysctl_net_ipv6.c +@@ -313,9 +313,9 @@ out_ipv6_table: + + static void __net_exit ipv6_sysctl_net_exit(struct net *net) + { +- struct ctl_table *ipv6_table; +- struct ctl_table *ipv6_route_table; +- struct ctl_table *ipv6_icmp_table; ++ const struct ctl_table *ipv6_table; ++ const struct ctl_table *ipv6_route_table; ++ const struct ctl_table *ipv6_icmp_table; + + ipv6_table = net->ipv6.sysctl.hdr->ctl_table_arg; + ipv6_route_table = net->ipv6.sysctl.route_hdr->ctl_table_arg; +--- a/net/ipv6/xfrm6_policy.c ++++ b/net/ipv6/xfrm6_policy.c +@@ -229,7 +229,7 @@ err_alloc: + + static void __net_exit xfrm6_net_sysctl_exit(struct net *net) + { +- struct ctl_table *table; ++ const struct ctl_table *table; + + if (!net->ipv6.sysctl.xfrm6_hdr) + return; +--- a/net/mpls/af_mpls.c ++++ b/net/mpls/af_mpls.c +@@ -1422,7 +1422,7 @@ static void mpls_dev_sysctl_unregister(s + struct mpls_dev *mdev) + { + struct net *net = dev_net(dev); +- struct ctl_table *table; ++ const struct ctl_table *table; + + if (!mdev->sysctl) + return; +@@ -2692,7 +2692,7 @@ static void mpls_net_exit(struct net *ne + { + struct mpls_route __rcu **platform_label; + size_t platform_labels; +- struct ctl_table *table; ++ const struct ctl_table *table; + unsigned int index; + + table = net->mpls.ctl->ctl_table_arg; +--- a/net/mptcp/ctrl.c ++++ b/net/mptcp/ctrl.c +@@ -218,7 +218,7 @@ err_alloc: + + static void mptcp_pernet_del_table(struct mptcp_pernet *pernet) + { +- struct ctl_table *table = pernet->ctl_table_hdr->ctl_table_arg; ++ const struct ctl_table *table = pernet->ctl_table_hdr->ctl_table_arg; + + unregister_net_sysctl_table(pernet->ctl_table_hdr); + +--- a/net/netfilter/nf_conntrack_standalone.c ++++ b/net/netfilter/nf_conntrack_standalone.c +@@ -1113,7 +1113,7 @@ out_unregister_netfilter: + static void nf_conntrack_standalone_fini_sysctl(struct net *net) + { + struct nf_conntrack_net *cnet = nf_ct_pernet(net); +- struct ctl_table *table; ++ const struct ctl_table *table; + + table = cnet->sysctl_header->ctl_table_arg; + unregister_net_sysctl_table(cnet->sysctl_header); +--- a/net/netfilter/nf_log.c ++++ b/net/netfilter/nf_log.c +@@ -509,7 +509,7 @@ err_alloc: + + static void netfilter_log_sysctl_exit(struct net *net) + { +- struct ctl_table *table; ++ const struct ctl_table *table; + + table = net->nf.nf_log_dir_header->ctl_table_arg; + unregister_net_sysctl_table(net->nf.nf_log_dir_header); +--- a/net/sctp/sysctl.c ++++ b/net/sctp/sysctl.c +@@ -630,7 +630,7 @@ int sctp_sysctl_net_register(struct net + + void sctp_sysctl_net_unregister(struct net *net) + { +- struct ctl_table *table; ++ const struct ctl_table *table; + + table = net->sctp.sysctl_header->ctl_table_arg; + unregister_net_sysctl_table(net->sctp.sysctl_header); +--- a/net/smc/smc_sysctl.c ++++ b/net/smc/smc_sysctl.c +@@ -109,7 +109,7 @@ err_alloc: + + void __net_exit smc_sysctl_net_exit(struct net *net) + { +- struct ctl_table *table; ++ const struct ctl_table *table; + + table = net->smc.smc_hdr->ctl_table_arg; + unregister_net_sysctl_table(net->smc.smc_hdr); +--- a/net/unix/sysctl_net_unix.c ++++ b/net/unix/sysctl_net_unix.c +@@ -52,7 +52,7 @@ err_alloc: + + void unix_sysctl_unregister(struct net *net) + { +- struct ctl_table *table; ++ const struct ctl_table *table; + + table = net->unx.ctl->ctl_table_arg; + unregister_net_sysctl_table(net->unx.ctl); +--- a/net/xfrm/xfrm_sysctl.c ++++ b/net/xfrm/xfrm_sysctl.c +@@ -76,7 +76,7 @@ out_kmemdup: + + void __net_exit xfrm_sysctl_fini(struct net *net) + { +- struct ctl_table *table; ++ const struct ctl_table *table; + + table = net->xfrm.sysctl_hdr->ctl_table_arg; + unregister_net_sysctl_table(net->xfrm.sysctl_hdr); diff --git a/queue-6.6/usb-gadget-f_tcm-synchronize-delayed-set_alt-with-teardown.patch b/queue-6.6/usb-gadget-f_tcm-synchronize-delayed-set_alt-with-teardown.patch new file mode 100644 index 0000000000..ec765cda35 --- /dev/null +++ b/queue-6.6/usb-gadget-f_tcm-synchronize-delayed-set_alt-with-teardown.patch @@ -0,0 +1,388 @@ +From sashal@kernel.org Thu Jul 30 21:39:06 2026 +From: Sasha Levin +Date: Thu, 30 Jul 2026 15:39:02 -0400 +Subject: usb: gadget: f_tcm: synchronize delayed set_alt with teardown +To: stable@vger.kernel.org +Cc: Cen Zhang , stable , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260730193902.3130410-1-sashal@kernel.org> + +From: Cen Zhang + +[ Upstream commit 79e2d75725c85607f8a9d87ae9cace62a19f767d ] + +The f_tcm set_alt() path defers endpoint setup to a work item and +completes the delayed status response from process context. The delayed +work uses f_tcm private state and may complete the setup request after +disconnect or function teardown has already moved on. + +Cancel and drain the delayed set_alt work when the function is unbound or +freed. For disable paths, which are reached under the composite device +lock, use a small state machine and a non-sleeping cancellation path +instead of cancel_work_sync(). If the work is already running, mark it +cancelled and let the worker own the cleanup; otherwise tcm_disable() can +cancel the queued work and clean up immediately. + +Also serialize the final delayed-status completion with the cancellation +check while holding the composite device lock. This prevents a disconnect +from clearing delayed_status while the worker is about to complete the +control request. + +Validation reproduced this kernel report: +BUG: KASAN: slab-use-after-free in tcm_delayed_set_alt+0x6c/0xef0 + +Call Trace: + + dump_stack_lvl+0x66/0xa0 + print_report+0xce/0x630 + ? tcm_delayed_set_alt+0x6c/0xef0 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? __virt_addr_valid+0x188/0x320 + ? tcm_delayed_set_alt+0x6c/0xef0 + kasan_report+0xe0/0x110 + ? tcm_delayed_set_alt+0x6c/0xef0 + tcm_delayed_set_alt+0x6c/0xef0 + ? __pfx_tcm_delayed_set_alt+0x10/0x10 + ? process_one_work+0x4cb/0xb90 + ? rcu_is_watching+0x20/0x50 + ? tcm_delayed_set_alt+0x9/0xef0 + process_one_work+0x4d7/0xb90 + ? __pfx_process_one_work+0x10/0x10 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? __list_add_valid_or_report+0x37/0xf0 + ? __pfx_tcm_delayed_set_alt+0x10/0x10 + ? srso_alias_return_thunk+0x5/0xfbef5 + worker_thread+0x2d8/0x570 + ? __pfx_worker_thread+0x10/0x10 + kthread+0x1ad/0x1f0 + ? __pfx_kthread+0x10/0x10 + ret_from_fork+0x3c9/0x540 + ? __pfx_ret_from_fork+0x10/0x10 + ? srso_alias_return_thunk+0x5/0xfbef5 + ? __switch_to+0x2e9/0x730 + ? __pfx_kthread+0x10/0x10 + ret_from_fork_asm+0x1a/0x30 + + +Allocated by task 544: + kasan_save_stack+0x33/0x60 + kasan_save_track+0x14/0x30 + __kasan_kmalloc+0x8f/0xa0 + tcm_alloc+0x68/0x180 + usb_get_function+0x36/0x60 + config_usb_cfg_link+0x125/0x1b0 + configfs_symlink+0x322/0x890 + vfs_symlink+0xc2/0x270 + filename_symlinkat+0x295/0x2f0 + __x64_sys_symlinkat+0x62/0x90 + do_syscall_64+0x115/0x6a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Freed by task 661: + kasan_save_stack+0x33/0x60 + kasan_save_track+0x14/0x30 + kasan_save_free_info+0x3b/0x60 + __kasan_slab_free+0x43/0x70 + kfree+0x2f9/0x530 + config_usb_cfg_unlink+0x173/0x1e0 + configfs_unlink+0x1fa/0x340 + vfs_unlink+0x15c/0x510 + filename_unlinkat+0x2ba/0x450 + __x64_sys_unlinkat+0x63/0x90 + do_syscall_64+0x115/0x6a0 + entry_SYSCALL_64_after_hwframe+0x77/0x7f + +Fixes: c52661d60f63 ("usb-gadget: Initial merge of target module for UASP + BOT") +Cc: stable +Assisted-by: Codex:gpt-5.5 +Signed-off-by: Cen Zhang +Link: https://patch.msgid.link/20260627104153.3822495-1-zzzccc427@gmail.com +Signed-off-by: Greg Kroah-Hartman +[ adjusted context for 6.12's scalar `struct usbg_cdb cmd` and missing `stream_hash`, dropping the `hash_init()` context line ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/gadget/function/f_tcm.c | 192 ++++++++++++++++++++++++++++++------ + drivers/usb/gadget/function/tcm.h | 13 ++ + 2 files changed, 177 insertions(+), 28 deletions(-) + +--- a/drivers/usb/gadget/function/f_tcm.c ++++ b/drivers/usb/gadget/function/f_tcm.c +@@ -2011,31 +2011,158 @@ ep_fail: + return -ENOTSUPP; + } + +-struct guas_setup_wq { +- struct work_struct work; +- struct f_uas *fu; +- unsigned int alt; +-}; ++static void tcm_cleanup_old_alt(struct f_uas *fu) ++{ ++ if (fu->flags & USBG_IS_UAS) ++ uasp_cleanup_old_alt(fu); ++ else if (fu->flags & USBG_IS_BOT) ++ bot_cleanup_old_alt(fu); ++ fu->flags = 0; ++} ++ ++static void tcm_delayed_set_alt_done(struct f_uas *fu) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags); ++ fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_IDLE; ++ fu->delayed_set_alt_cancel = false; ++ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags); ++} ++ ++static bool tcm_delayed_set_alt_cancelled(struct f_uas *fu) ++{ ++ bool cancelled; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags); ++ cancelled = fu->delayed_set_alt_cancel; ++ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags); ++ ++ return cancelled; ++} ++ ++static bool tcm_complete_delayed_status(struct f_uas *fu) ++{ ++ struct usb_composite_dev *cdev = fu->function.config->cdev; ++ struct usb_request *req = cdev->req; ++ unsigned long cdev_flags; ++ bool cancelled; ++ int ret; ++ ++ spin_lock_irqsave(&cdev->lock, cdev_flags); ++ spin_lock(&fu->delayed_set_alt_lock); ++ cancelled = fu->delayed_set_alt_cancel; ++ if (!cancelled) { ++ fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_IDLE; ++ fu->delayed_set_alt_cancel = false; ++ } ++ spin_unlock(&fu->delayed_set_alt_lock); ++ ++ if (cancelled) { ++ spin_unlock_irqrestore(&cdev->lock, cdev_flags); ++ return false; ++ } ++ ++ if (cdev->delayed_status == 0) { ++ WARN(cdev, "%s: Unexpected call\n", __func__); ++ } else if (--cdev->delayed_status == 0) { ++ req->length = 0; ++ req->context = cdev; ++ ret = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); ++ if (ret == 0) { ++ cdev->setup_pending = true; ++ } else { ++ req->status = 0; ++ req->complete(cdev->gadget->ep0, req); ++ } ++ } ++ ++ spin_unlock_irqrestore(&cdev->lock, cdev_flags); ++ ++ return true; ++} ++ ++static bool tcm_cancel_delayed_set_alt(struct f_uas *fu) ++{ ++ bool cleanup = false; ++ bool cancel = false; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags); ++ switch (fu->delayed_set_alt_state) { ++ case USBG_DELAYED_SET_ALT_IDLE: ++ cleanup = true; ++ break; ++ case USBG_DELAYED_SET_ALT_QUEUED: ++ case USBG_DELAYED_SET_ALT_RUNNING: ++ fu->delayed_set_alt_cancel = true; ++ cancel = true; ++ break; ++ } ++ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags); ++ ++ if (cancel && cancel_work(&fu->delayed_set_alt)) { ++ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags); ++ if (fu->delayed_set_alt_state == USBG_DELAYED_SET_ALT_QUEUED) { ++ fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_IDLE; ++ fu->delayed_set_alt_cancel = false; ++ cleanup = true; ++ } ++ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags); ++ } ++ ++ return cleanup; ++} ++ ++static void tcm_cancel_delayed_set_alt_sync(struct f_uas *fu) ++{ ++ unsigned long flags; ++ ++ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags); ++ if (fu->delayed_set_alt_state != USBG_DELAYED_SET_ALT_IDLE) ++ fu->delayed_set_alt_cancel = true; ++ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags); ++ ++ cancel_work_sync(&fu->delayed_set_alt); ++ ++ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags); ++ fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_IDLE; ++ fu->delayed_set_alt_cancel = false; ++ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags); ++} + + static void tcm_delayed_set_alt(struct work_struct *wq) + { +- struct guas_setup_wq *work = container_of(wq, struct guas_setup_wq, +- work); +- struct f_uas *fu = work->fu; +- int alt = work->alt; ++ struct f_uas *fu = container_of(wq, struct f_uas, delayed_set_alt); ++ unsigned long flags; ++ unsigned int alt; ++ ++ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags); ++ if (fu->delayed_set_alt_state != USBG_DELAYED_SET_ALT_QUEUED) { ++ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags); ++ return; ++ } ++ fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_RUNNING; ++ alt = fu->delayed_alt; ++ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags); + +- kfree(work); ++ tcm_cleanup_old_alt(fu); + +- if (fu->flags & USBG_IS_BOT) +- bot_cleanup_old_alt(fu); +- if (fu->flags & USBG_IS_UAS) +- uasp_cleanup_old_alt(fu); ++ if (tcm_delayed_set_alt_cancelled(fu)) ++ goto out_done; + + if (alt == USB_G_ALT_INT_BBB) + bot_set_alt(fu); + else if (alt == USB_G_ALT_INT_UAS) + uasp_set_alt(fu); +- usb_composite_setup_continue(fu->function.config->cdev); ++ ++ if (tcm_complete_delayed_status(fu)) ++ return; ++ ++ tcm_cleanup_old_alt(fu); ++out_done: ++ tcm_delayed_set_alt_done(fu); + } + + static int tcm_get_alt(struct usb_function *f, unsigned intf) +@@ -2061,15 +2188,20 @@ static int tcm_set_alt(struct usb_functi + return -EOPNOTSUPP; + + if ((alt == USB_G_ALT_INT_BBB) || (alt == USB_G_ALT_INT_UAS)) { +- struct guas_setup_wq *work; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&fu->delayed_set_alt_lock, flags); ++ if (fu->delayed_set_alt_state != USBG_DELAYED_SET_ALT_IDLE) { ++ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, ++ flags); ++ return -EBUSY; ++ } ++ fu->delayed_alt = alt; ++ fu->delayed_set_alt_cancel = false; ++ fu->delayed_set_alt_state = USBG_DELAYED_SET_ALT_QUEUED; ++ spin_unlock_irqrestore(&fu->delayed_set_alt_lock, flags); + +- work = kmalloc(sizeof(*work), GFP_ATOMIC); +- if (!work) +- return -ENOMEM; +- INIT_WORK(&work->work, tcm_delayed_set_alt); +- work->fu = fu; +- work->alt = alt; +- schedule_work(&work->work); ++ schedule_work(&fu->delayed_set_alt); + return USB_GADGET_DELAYED_STATUS; + } + return -EOPNOTSUPP; +@@ -2079,11 +2211,8 @@ static void tcm_disable(struct usb_funct + { + struct f_uas *fu = to_f_uas(f); + +- if (fu->flags & USBG_IS_UAS) +- uasp_cleanup_old_alt(fu); +- else if (fu->flags & USBG_IS_BOT) +- bot_cleanup_old_alt(fu); +- fu->flags = 0; ++ if (tcm_cancel_delayed_set_alt(fu)) ++ tcm_cleanup_old_alt(fu); + } + + static int tcm_setup(struct usb_function *f, +@@ -2231,11 +2360,16 @@ static void tcm_free(struct usb_function + { + struct f_uas *tcm = to_f_uas(f); + ++ tcm_cancel_delayed_set_alt_sync(tcm); + kfree(tcm); + } + + static void tcm_unbind(struct usb_configuration *c, struct usb_function *f) + { ++ struct f_uas *fu = to_f_uas(f); ++ ++ tcm_cancel_delayed_set_alt_sync(fu); ++ tcm_cleanup_old_alt(fu); + usb_free_all_descriptors(f); + } + +@@ -2268,6 +2402,8 @@ static struct usb_function *tcm_alloc(st + fu->function.disable = tcm_disable; + fu->function.free_func = tcm_free; + fu->tpg = tpg_instances[i].tpg; ++ INIT_WORK(&fu->delayed_set_alt, tcm_delayed_set_alt); ++ spin_lock_init(&fu->delayed_set_alt_lock); + mutex_unlock(&tpg_instances_lock); + + return &fu->function; +--- a/drivers/usb/gadget/function/tcm.h ++++ b/drivers/usb/gadget/function/tcm.h +@@ -3,6 +3,7 @@ + #define __TARGET_USB_GADGET_H__ + + #include ++#include + /* #include */ + #include + #include +@@ -26,6 +27,12 @@ enum { + + #define USB_G_DEFAULT_SESSION_TAGS 128 + ++enum { ++ USBG_DELAYED_SET_ALT_IDLE = 0, ++ USBG_DELAYED_SET_ALT_QUEUED, ++ USBG_DELAYED_SET_ALT_RUNNING, ++}; ++ + struct tcm_usbg_nexus { + struct se_session *tvn_se_sess; + }; +@@ -117,6 +124,12 @@ struct f_uas { + #define USBG_IS_BOT (1 << 3) + #define USBG_BOT_CMD_PEND (1 << 4) + ++ struct work_struct delayed_set_alt; ++ spinlock_t delayed_set_alt_lock; /* protects delayed_set_alt_* */ ++ unsigned int delayed_alt; ++ unsigned int delayed_set_alt_state; ++ bool delayed_set_alt_cancel; ++ + struct usbg_cdb cmd; + struct usb_ep *ep_in; + struct usb_ep *ep_out; diff --git a/queue-6.6/usb-musb-omap2430-clean-up-probe-error-handling.patch b/queue-6.6/usb-musb-omap2430-clean-up-probe-error-handling.patch new file mode 100644 index 0000000000..07c6cc7b21 --- /dev/null +++ b/queue-6.6/usb-musb-omap2430-clean-up-probe-error-handling.patch @@ -0,0 +1,103 @@ +From sashal@kernel.org Thu Jul 30 15:13:40 2026 +From: Sasha Levin +Date: Thu, 30 Jul 2026 09:13:35 -0400 +Subject: usb: musb: omap2430: clean up probe error handling +To: stable@vger.kernel.org +Cc: Johan Hovold , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260730131336.2345145-1-sashal@kernel.org> + +From: Johan Hovold + +[ Upstream commit 51d4b0a44c82e5eff056ef76acd2c3c605a8eb74 ] + +Using numbered error labels is discouraged (e.g. as it requires +renumbering them when adding a new intermediate error path). + +Rename the error labels after what they do. + +While at it, drop the redundant platform allocation failure dev_err() +as the error would already have been logged by the allocator. + +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20250724091910.21092-6-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: c947360ae63e ("usb: musb: omap2430: Do not put borrowed of_node in probe") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/musb/omap2430.c | 23 ++++++++++------------- + 1 file changed, 10 insertions(+), 13 deletions(-) + +--- a/drivers/usb/musb/omap2430.c ++++ b/drivers/usb/musb/omap2430.c +@@ -318,13 +318,11 @@ static int omap2430_probe(struct platfor + + glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL); + if (!glue) +- goto err0; ++ return -ENOMEM; + + musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO); +- if (!musb) { +- dev_err(&pdev->dev, "failed to allocate musb device\n"); +- goto err0; +- } ++ if (!musb) ++ return -ENOMEM; + + musb->dev.parent = &pdev->dev; + musb->dev.dma_mask = &omap2430_dmamask; +@@ -348,15 +346,15 @@ static int omap2430_probe(struct platfor + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) +- goto err2; ++ goto err_put_musb; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) +- goto err2; ++ goto err_put_musb; + + config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL); + if (!config) +- goto err2; ++ goto err_put_musb; + + of_property_read_u32(np, "mode", (u32 *)&pdata->mode); + of_property_read_u32(np, "interface-type", +@@ -379,7 +377,7 @@ static int omap2430_probe(struct platfor + if (!control_pdev) { + dev_err(&pdev->dev, "Failed to get control device\n"); + ret = -EINVAL; +- goto err2; ++ goto err_put_musb; + } + glue->control_otghs = &control_pdev->dev; + } +@@ -455,22 +453,21 @@ static int omap2430_probe(struct platfor + ret = platform_device_add(musb); + if (ret) { + dev_err(&pdev->dev, "failed to register musb device\n"); +- goto err3; ++ goto err_disable_rpm; + } + of_node_put(np); + + return 0; + +-err3: ++err_disable_rpm: + pm_runtime_disable(glue->dev); + err_put_control_otghs: + if (!IS_ERR(glue->control_otghs)) + put_device(glue->control_otghs); +-err2: ++err_put_musb: + of_node_put(np); + platform_device_put(musb); + +-err0: + return ret; + } + diff --git a/queue-6.6/usb-musb-omap2430-do-not-put-borrowed-of_node-in-probe.patch b/queue-6.6/usb-musb-omap2430-do-not-put-borrowed-of_node-in-probe.patch new file mode 100644 index 0000000000..9b064c1fa9 --- /dev/null +++ b/queue-6.6/usb-musb-omap2430-do-not-put-borrowed-of_node-in-probe.patch @@ -0,0 +1,54 @@ +From sashal@kernel.org Thu Jul 30 15:13:40 2026 +From: Sasha Levin +Date: Thu, 30 Jul 2026 09:13:36 -0400 +Subject: usb: musb: omap2430: Do not put borrowed of_node in probe +To: stable@vger.kernel.org +Cc: Guangshuo Li , stable , Johan Hovold , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260730131336.2345145-2-sashal@kernel.org> + +From: Guangshuo Li + +[ Upstream commit c947360ae63eee1c9eacc030dd6f5a53f717addf ] + +omap2430_probe() stores pdev->dev.of_node in a local np variable. This is +a borrowed pointer and the probe function does not take a reference to +it. + +The success and error paths nevertheless call of_node_put(np). This drops +a reference that is owned by the platform device, and can leave +pdev->dev.of_node with an unbalanced reference count. + +Do not put the borrowed platform device node from omap2430_probe(). +References taken for the child MUSB device are handled by the device core, +and the ctrl-module phandle reference is still released separately. + +Fixes: ffbe2feac59b ("usb: musb: omap2430: Fix probe regression for missing resources") +Cc: stable +Reviewed-by: Johan Hovold +Signed-off-by: Guangshuo Li +Link: https://patch.msgid.link/20260713114711.955253-1-lgs201920130244@gmail.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/musb/omap2430.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/usb/musb/omap2430.c ++++ b/drivers/usb/musb/omap2430.c +@@ -455,7 +455,6 @@ static int omap2430_probe(struct platfor + dev_err(&pdev->dev, "failed to register musb device\n"); + goto err_disable_rpm; + } +- of_node_put(np); + + return 0; + +@@ -465,7 +464,6 @@ err_put_control_otghs: + if (!IS_ERR(glue->control_otghs)) + put_device(glue->control_otghs); + err_put_musb: +- of_node_put(np); + platform_device_put(musb); + + return ret; diff --git a/queue-6.6/usb-typec-ucsi-fix-race-condition-and-ordering-in-port-unregistration.patch b/queue-6.6/usb-typec-ucsi-fix-race-condition-and-ordering-in-port-unregistration.patch new file mode 100644 index 0000000000..3b51fba593 --- /dev/null +++ b/queue-6.6/usb-typec-ucsi-fix-race-condition-and-ordering-in-port-unregistration.patch @@ -0,0 +1,173 @@ +From stable+bounces-293910-greg=kroah.com@vger.kernel.org Fri Jul 31 04:41:04 2026 +From: Sasha Levin +Date: Thu, 30 Jul 2026 22:40:57 -0400 +Subject: usb: typec: ucsi: Fix race condition and ordering in port unregistration +To: stable@vger.kernel.org +Cc: Andrei Kuchynski , stable , Benson Leung , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260731024057.3338855-3-sashal@kernel.org> + +From: Andrei Kuchynski + +[ Upstream commit 7aa7d4bf9d3fa9a6a47b640ad103ab433b7ff261 ] + +A synchronization issue exists during port unregistration where pending +partner work items can race against workqueue destruction, leading to +use-after-free conditions: + + cros_ec_ucsi cros_ec_ucsi.3.auto: error -ETIMEDOUT: PPM init failed + BUG: kernel NULL pointer dereference, address: 0000000000000000 + RIP: 0010:__queue_work+0x83/0x4a0 + Call Trace: + + __cfi_delayed_work_timer_fn+0x10/0x10 + run_timer_softirq+0x3b6/0xbd0 + sched_clock_cpu+0xc/0x110 + irq_exit_rcu+0x18d/0x330 + fred_sysvec_apic_timer_interrupt+0x5e/0x80 + +Fix this by ensuring strict ordering and proper serialization during +teardown: + +1. Move ucsi_unregister_partner() to the beginning of the teardown +sequence and protect it under the connector mutex lock. +2. Ensure all pending partner tasks are explicitly flushed and finished +before the workqueue is destroyed. +3. Switch from mod_delayed_work() to a cancel_delayed_work() and +queue_delayed_work() sequence. This guarantees that items currently marked +as pending won't be scheduled an additional time, preventing a double +release of resources which leads to the following crash: + + Oops: general protection fault, probably for non-canonical address + 0xdead000000000122: 0000 [#1] SMP NOPTI + Workqueue: cros_ec_ucsi.3.auto-con2 ucsi_poll_worker + RIP: 0010:ucsi_poll_worker+0x65/0x1e0 + Call Trace: + + process_scheduled_works+0x218/0x6d0 + worker_thread+0x188/0x3f0 + __cfi_worker_thread+0x10/0x10 + kthread+0x226/0x2a0 + +To ensure these rules are applied identically across both the normal +teardown and the ucsi_init() error paths, consolidate the cleanup logic +into a new helper, ucsi_unregister_port(). + +Cc: stable +Fixes: b9aa02ca39a4 ("usb: typec: ucsi: Add polling mechanism for partner tasks like alt mode checking") +Fixes: b13abcb7ddd8 ("usb: typec: ucsi: Fix NULL pointer access") +Fixes: fac4b8633fd6 ("usb: ucsi: Ensure connector delayed work items are flushed") +Signed-off-by: Andrei Kuchynski +Reviewed-by: Benson Leung +Link: https://patch.msgid.link/20260707141736.1635698-1-akuchynski@chromium.org +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/typec/ucsi/ucsi.c | 82 +++++++++++++++++++----------------------- + 1 file changed, 39 insertions(+), 43 deletions(-) + +--- a/drivers/usb/typec/ucsi/ucsi.c ++++ b/drivers/usb/typec/ucsi/ucsi.c +@@ -1407,6 +1407,42 @@ out_unlock: + return ret; + } + ++static void ucsi_unregister_port(struct ucsi_connector *con) ++{ ++ struct ucsi_work *uwork; ++ ++ if (con->wq) { ++ mutex_lock(&con->lock); ++ ucsi_unregister_partner(con); ++ /* ++ * queue delayed items immediately so they can execute ++ * and free themselves before the wq is destroyed ++ */ ++ list_for_each_entry(uwork, &con->partner_tasks, node) { ++ if (cancel_delayed_work(&uwork->work)) ++ queue_delayed_work(con->wq, &uwork->work, 0); ++ } ++ mutex_unlock(&con->lock); ++ ++ destroy_workqueue(con->wq); ++ con->wq = NULL; ++ } else { ++ ucsi_unregister_partner(con); ++ } ++ ++ ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON); ++ ucsi_unregister_port_psy(con); ++ ++ usb_power_delivery_unregister_capabilities(con->port_sink_caps); ++ con->port_sink_caps = NULL; ++ usb_power_delivery_unregister_capabilities(con->port_source_caps); ++ con->port_source_caps = NULL; ++ usb_power_delivery_unregister(con->pd); ++ con->pd = NULL; ++ typec_unregister_port(con->port); ++ con->port = NULL; ++} ++ + static u64 ucsi_get_supported_notifications(struct ucsi *ucsi) + { + u8 features = ucsi->cap.features; +@@ -1515,22 +1551,8 @@ err_unregister: + for (i = 0; i < ucsi->cap.num_connectors; i++) + lockdep_unregister_key(&connector[i].lock_key); + +- for (con = connector; con->port; con++) { +- if (con->wq) +- destroy_workqueue(con->wq); +- ucsi_unregister_partner(con); +- ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON); +- ucsi_unregister_port_psy(con); +- +- usb_power_delivery_unregister_capabilities(con->port_sink_caps); +- con->port_sink_caps = NULL; +- usb_power_delivery_unregister_capabilities(con->port_source_caps); +- con->port_source_caps = NULL; +- usb_power_delivery_unregister(con->pd); +- con->pd = NULL; +- typec_unregister_port(con->port); +- con->port = NULL; +- } ++ for (con = connector; con->port; con++) ++ ucsi_unregister_port(con); + kfree(connector); + err_reset: + memset(&ucsi->cap, 0, sizeof(ucsi->cap)); +@@ -1756,33 +1778,7 @@ void ucsi_unregister(struct ucsi *ucsi) + + for (i = 0; i < ucsi->cap.num_connectors; i++) { + cancel_work_sync(&ucsi->connector[i].work); +- +- if (ucsi->connector[i].wq) { +- struct ucsi_work *uwork; +- +- mutex_lock(&ucsi->connector[i].lock); +- /* +- * queue delayed items immediately so they can execute +- * and free themselves before the wq is destroyed +- */ +- list_for_each_entry(uwork, &ucsi->connector[i].partner_tasks, node) +- mod_delayed_work(ucsi->connector[i].wq, &uwork->work, 0); +- mutex_unlock(&ucsi->connector[i].lock); +- destroy_workqueue(ucsi->connector[i].wq); +- } +- +- ucsi_unregister_partner(&ucsi->connector[i]); +- ucsi_unregister_altmodes(&ucsi->connector[i], +- UCSI_RECIPIENT_CON); +- ucsi_unregister_port_psy(&ucsi->connector[i]); +- +- usb_power_delivery_unregister_capabilities(ucsi->connector[i].port_sink_caps); +- ucsi->connector[i].port_sink_caps = NULL; +- usb_power_delivery_unregister_capabilities(ucsi->connector[i].port_source_caps); +- ucsi->connector[i].port_source_caps = NULL; +- usb_power_delivery_unregister(ucsi->connector[i].pd); +- ucsi->connector[i].pd = NULL; +- typec_unregister_port(ucsi->connector[i].port); ++ ucsi_unregister_port(&ucsi->connector[i]); + lockdep_unregister_key(&ucsi->connector[i].lock_key); + } + diff --git a/queue-6.6/usb-typec-ucsi-only-enable-supported-notifications.patch b/queue-6.6/usb-typec-ucsi-only-enable-supported-notifications.patch new file mode 100644 index 0000000000..cdfebadc5b --- /dev/null +++ b/queue-6.6/usb-typec-ucsi-only-enable-supported-notifications.patch @@ -0,0 +1,68 @@ +From sashal@kernel.org Fri Jul 31 04:41:00 2026 +From: Sasha Levin +Date: Thu, 30 Jul 2026 22:40:55 -0400 +Subject: usb: typec: ucsi: Only enable supported notifications +To: stable@vger.kernel.org +Cc: Diogo Ivo , Heikki Krogerus , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260731024057.3338855-1-sashal@kernel.org> + +From: Diogo Ivo + +[ Upstream commit 27ffe4ff0b33b3dcc97fd448fd1e38d31ade575b ] + +The UCSI specification defines some notifications to be optional for the +PPM to support. From these only enable the ones the PPM informs us are +actually supported. + +Signed-off-by: Diogo Ivo +Reviewed-by: Heikki Krogerus +Link: https://lore.kernel.org/r/yhz7nq622mbg3rqsyvqz632pc756niagpfbnzayfswhzo7esho@vrdtx5c3hjgx +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 7aa7d4bf9d3f ("usb: typec: ucsi: Fix race condition and ordering in port unregistration") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/typec/ucsi/ucsi.c | 25 +++++++++++++++++++++++-- + 1 file changed, 23 insertions(+), 2 deletions(-) + +--- a/drivers/usb/typec/ucsi/ucsi.c ++++ b/drivers/usb/typec/ucsi/ucsi.c +@@ -1406,6 +1406,27 @@ out_unlock: + return ret; + } + ++static u64 ucsi_get_supported_notifications(struct ucsi *ucsi) ++{ ++ u8 features = ucsi->cap.features; ++ u64 ntfy = UCSI_ENABLE_NTFY_ALL; ++ ++ if (!(features & UCSI_CAP_ALT_MODE_DETAILS)) ++ ntfy &= ~UCSI_ENABLE_NTFY_CAM_CHANGE; ++ ++ if (!(features & UCSI_CAP_PDO_DETAILS)) ++ ntfy &= ~(UCSI_ENABLE_NTFY_PWR_LEVEL_CHANGE | ++ UCSI_ENABLE_NTFY_CAP_CHANGE); ++ ++ if (!(features & UCSI_CAP_EXT_SUPPLY_NOTIFICATIONS)) ++ ntfy &= ~UCSI_ENABLE_NTFY_EXT_PWR_SRC_CHANGE; ++ ++ if (!(features & UCSI_CAP_PD_RESET)) ++ ntfy &= ~UCSI_ENABLE_NTFY_PD_RESET_COMPLETE; ++ ++ return ntfy; ++} ++ + /** + * ucsi_init - Initialize UCSI interface + * @ucsi: UCSI to be initialized +@@ -1466,8 +1487,8 @@ static int ucsi_init(struct ucsi *ucsi) + goto err_unregister; + } + +- /* Enable all notifications */ +- ntfy = UCSI_ENABLE_NTFY_ALL; ++ /* Enable all supported notifications */ ++ ntfy = ucsi_get_supported_notifications(ucsi); + command = UCSI_SET_NOTIFICATION_ENABLE | ntfy; + ret = ucsi_send_command(ucsi, command, NULL, 0); + if (ret < 0) diff --git a/queue-6.6/usb-typec-ucsi-split-connector-lock-classes.patch b/queue-6.6/usb-typec-ucsi-split-connector-lock-classes.patch new file mode 100644 index 0000000000..80a57a857d --- /dev/null +++ b/queue-6.6/usb-typec-ucsi-split-connector-lock-classes.patch @@ -0,0 +1,124 @@ +From sashal@kernel.org Fri Jul 31 04:41:00 2026 +From: Sasha Levin +Date: Thu, 30 Jul 2026 22:40:56 -0400 +Subject: usb: typec: ucsi: split connector lock classes +To: stable@vger.kernel.org +Cc: Sergey Senozhatsky , Heikki Krogerus , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260731024057.3338855-2-sashal@kernel.org> + +From: Sergey Senozhatsky + +[ Upstream commit 8c22256bbafad3dc5fdbe9f684d045b67ff06a68 ] + +Lockdep detects a possible recursive locking scenario during +ucsi init: + +[ 5.418616] ============================================ +[ 5.418634] WARNING: possible recursive locking detected +[ 5.418706] -------------------------------------------- +[ 5.418725] kworker/4:1/82 is trying to acquire lock: +[ 5.418759] ffff888119a34648 (&con->lock){+.+.}-{3:3}, at: ucsi_init_work+0x1a78/0x2eb0 [typec_ucsi] +[ 5.418801] + but task is already holding lock: +[ 5.418835] ffff888119a34080 (&con->lock){+.+.}-{3:3}, at: ucsi_init_work+0x1a78/0x2eb0 [typec_ucsi] +[ 5.418884] + other info that might help us debug this: +[ 5.418904] Possible unsafe locking scenario: + +[ 5.418937] CPU0 +[ 5.418956] ---- +[ 5.418991] lock(&con->lock); +[ 5.419013] lock(&con->lock); +[ 5.419033] + *** DEADLOCK *** + +[ 5.419387] Call Trace: +[ 5.419406] +[ 5.419425] dump_stack_lvl+0x61/0xa0 +[ 5.419448] print_deadlock_bug+0x4a6/0x650 +[ 5.419483] __lock_acquire+0x62b6/0x7f50 +[ 5.419507] lock_acquire+0x11b/0x390 +[ 5.419654] __mutex_lock+0xbc/0xcd0 +[ 5.419741] ucsi_init_work+0x1a78/0x2eb0 +[ 5.419785] ? worker_thread+0xf53/0x2bc0 +[ 5.419819] worker_thread+0xff4/0x2bc0 +[ 5.419842] kthread+0x2a7/0x330 +[ 5.419863] ? __pfx_worker_thread+0x10/0x10 +[ 5.419896] ? __pfx_kthread+0x10/0x10 +[ 5.419916] ret_from_fork+0x38/0x70 +[ 5.419936] ? __pfx_kthread+0x10/0x10 +[ 5.419969] ret_from_fork_asm+0x1b/0x30 +[ 5.419991] +[ 5.420009] ---[ end trace 0000000000000000 ]--- + +The problem is that all connector locks belong to the same +lockdep lock class, so the following loop: + + for (i = 0; i < ucsi->cap.num_connectors; i++) + ucsi_register_port(connector[i]) + mutex_lock(&connector[i]->lock) + +looks like a recursive acquire of the same mutex. Put each connector +lock into a dedicated lock class so that lockdep doesn't see it as a +possible recursion. + +Signed-off-by: Sergey Senozhatsky +Reviewed-by: Heikki Krogerus +Link: https://patch.msgid.link/20260515060042.136083-1-senozhatsky@chromium.org +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: 7aa7d4bf9d3f ("usb: typec: ucsi: Fix race condition and ordering in port unregistration") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/typec/ucsi/ucsi.c | 8 ++++++++ + drivers/usb/typec/ucsi/ucsi.h | 1 + + 2 files changed, 9 insertions(+) + +--- a/drivers/usb/typec/ucsi/ucsi.c ++++ b/drivers/usb/typec/ucsi/ucsi.c +@@ -1231,6 +1231,7 @@ static int ucsi_register_port(struct ucs + INIT_WORK(&con->work, ucsi_handle_connector_change); + init_completion(&con->complete); + mutex_init(&con->lock); ++ lockdep_set_class(&con->lock, &con->lock_key); + INIT_LIST_HEAD(&con->partner_tasks); + con->ucsi = ucsi; + +@@ -1479,6 +1480,9 @@ static int ucsi_init(struct ucsi *ucsi) + goto err_reset; + } + ++ for (i = 0; i < ucsi->cap.num_connectors; i++) ++ lockdep_register_key(&connector[i].lock_key); ++ + /* Register all connectors */ + for (i = 0; i < ucsi->cap.num_connectors; i++) { + connector[i].num = i + 1; +@@ -1508,6 +1512,9 @@ static int ucsi_init(struct ucsi *ucsi) + return 0; + + err_unregister: ++ for (i = 0; i < ucsi->cap.num_connectors; i++) ++ lockdep_unregister_key(&connector[i].lock_key); ++ + for (con = connector; con->port; con++) { + if (con->wq) + destroy_workqueue(con->wq); +@@ -1776,6 +1783,7 @@ void ucsi_unregister(struct ucsi *ucsi) + usb_power_delivery_unregister(ucsi->connector[i].pd); + ucsi->connector[i].pd = NULL; + typec_unregister_port(ucsi->connector[i].port); ++ lockdep_unregister_key(&ucsi->connector[i].lock_key); + } + + kfree(ucsi->connector); +--- a/drivers/usb/typec/ucsi/ucsi.h ++++ b/drivers/usb/typec/ucsi/ucsi.h +@@ -350,6 +350,7 @@ struct ucsi_connector { + + struct ucsi *ucsi; + struct mutex lock; /* port lock */ ++ struct lock_class_key lock_key; + struct work_struct work; + struct completion complete; + struct workqueue_struct *wq; diff --git a/queue-6.6/wifi-ath6kl-fix-use-after-free-in-aggr_reset_state.patch b/queue-6.6/wifi-ath6kl-fix-use-after-free-in-aggr_reset_state.patch new file mode 100644 index 0000000000..3dd838aee7 --- /dev/null +++ b/queue-6.6/wifi-ath6kl-fix-use-after-free-in-aggr_reset_state.patch @@ -0,0 +1,50 @@ +From stable+bounces-296839-greg=kroah.com@vger.kernel.org Thu Aug 6 15:56:28 2026 +From: Sasha Levin +Date: Thu, 6 Aug 2026 09:50:25 -0400 +Subject: wifi: ath6kl: fix use-after-free in aggr_reset_state() +To: stable@vger.kernel.org +Cc: Daniel Hodges , Vasanthakumar Thiagarajan , Jeff Johnson , Sasha Levin +Message-ID: <20260806135025.603479-1-sashal@kernel.org> + +From: Daniel Hodges + +[ Upstream commit ba7debb4dd6427386862220e8335a53a4bfc235d ] + +The aggr_reset_state() function uses timer_delete() (non-synchronous) +for the aggregation timer before proceeding to delete TID state and +before the structure is freed by callers like aggr_module_destroy(). + +If the timer callback (aggr_timeout) is executing when aggr_reset_state() +is called, the callback will continue to access aggr_conn fields like +rx_tid[] and stat[] which may be freed immediately after by +kfree(aggr_info->aggr_conn) in aggr_module_destroy(). + +Additionally, the timer callback can re-arm itself via mod_timer() while +aggr_reset_state() is running, creating a more complex race condition. + +Use timer_delete_sync() instead to ensure any running timer callback +has completed before returning. + +Fixes: bdcd81707973 ("Add ath6kl cleaned up driver") +Cc: stable@vger.kernel.org +Signed-off-by: Daniel Hodges +Reviewed-by: Vasanthakumar Thiagarajan +Link: https://patch.msgid.link/20260206185207.30098-1-git@danielhodges.dev +Signed-off-by: Jeff Johnson +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/ath/ath6kl/txrx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath6kl/txrx.c ++++ b/drivers/net/wireless/ath/ath6kl/txrx.c +@@ -1829,7 +1829,7 @@ void aggr_reset_state(struct aggr_info_c + return; + + if (aggr_conn->timer_scheduled) { +- del_timer(&aggr_conn->timer); ++ timer_delete_sync(&aggr_conn->timer); + aggr_conn->timer_scheduled = false; + } + diff --git a/queue-6.6/wifi-brcmfmac-drain-bus_reset-work-on-device-removal.patch b/queue-6.6/wifi-brcmfmac-drain-bus_reset-work-on-device-removal.patch new file mode 100644 index 0000000000..29c3d23c70 --- /dev/null +++ b/queue-6.6/wifi-brcmfmac-drain-bus_reset-work-on-device-removal.patch @@ -0,0 +1,292 @@ +From stable+bounces-296847-greg=kroah.com@vger.kernel.org Thu Aug 6 16:01:52 2026 +From: Sasha Levin +Date: Thu, 6 Aug 2026 10:01:39 -0400 +Subject: wifi: brcmfmac: drain bus_reset work on device removal +To: stable@vger.kernel.org +Cc: Fan Wu , Arend van Spriel , Johannes Berg , Sasha Levin +Message-ID: <20260806140139.635428-1-sashal@kernel.org> + +From: Fan Wu + +[ Upstream commit 43b25879f004c98defa2776bedc6ca4763c51945 ] + +brcmf_fw_crashed() and the debugfs "reset" entry both schedule +drvr->bus_reset, whose callback recovers drvr through container_of() +and dereferences it. The removal path frees drvr (brcmf_free -> +wiphy_free) without draining the work, so a bus_reset callback pending +or running during removal can outlive drvr. + +Cancellation cannot live in brcmf_detach() or brcmf_free(): the work +callback reaches teardown through the bus .reset op (PCIe +brcmf_pcie_reset -> brcmf_detach; SDIO brcmf_sdio_bus_reset -> +brcmf_sdiod_remove -> brcmf_free), so cancelling there would wait for +the running work and deadlock. + +Add a per-bus mutex (bus_reset_lock) and route all arming through +brcmf_bus_schedule_reset(), which under the lock skips when the bus is +marked removing. Each bus remove entry calls +brcmf_bus_cancel_reset_work(), which under the same lock sets removing +and cancels the work. Holding the mutex across cancel_work_sync() makes +the set-removing + drain step atomic. Every producer reaches the arming +path from process context -- the PCIe firmware-halt notification runs in +the threaded IRQ handler (brcmf_pcie_isr_thread) and the SDIO hostmail +path runs from the data workqueue -- so the mutex is taken only in +sleepable contexts. Where applicable the remove entry first stops the +firmware-crash producer: on PCIe mask the mailbox and synchronize_irq; +on SDIO unregister the bus interrupt and cancel the data worker, which +also reports firmware halts through brcmf_fw_crashed(). The mutex is +initialized at bus allocation. The SDIO suspend power-off path frees +drvr through the same brcmf_sdiod_remove() and takes the same lock; +resume re-allows the work only on a successful re-probe. + +Also guard brcmf_fw_crashed() against a NULL bus_if/drvr: it can fire +before brcmf_attach() wires up drvr, and it dereferences drvr +(bphy_err/brcmf_dev_coredump) before reaching the arming gate. + +The bus_reset work is shared across buses, so the drain is applied to +every remove path: PCIe (the .reset op introduced by the Fixes commit), +SDIO (arms the same work through brcmf_fw_crashed()), and USB (via the +debugfs "reset" entry). cancel_work_sync() drains a running or pending +bus_reset work item before removal frees drvr, and patch 1/2 makes the +scratch-buffer release safe when reset teardown has already released +those DMA buffers. + +This patch fixes the lifetime of the bus_reset work item itself. It does +not attempt to address the separate, pre-existing lifetime of the +asynchronous firmware completion started by the PCIe reset path. That +callback needs its own lifetime/ownership protocol and is being tracked +separately. + +This issue was found by an in-house static analysis tool. + +Fixes: 4684997d9eea ("brcmfmac: reset PCIe bus on a firmware crash") +Cc: stable@vger.kernel.org +Signed-off-by: Fan Wu +Assisted-by: Codex:gpt-5.6 +Acked-by: Arend van Spriel +Link: https://patch.msgid.link/20260718024353.3147201-3-fanwu01@zju.edu.cn +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 13 +++ + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 6 + + drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 46 ++++++++++++-- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 6 + + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 6 + + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 1 + drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 3 + 7 files changed, 77 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -1065,6 +1065,7 @@ static int brcmf_ops_sdio_probe(struct s + bus_if = kzalloc(sizeof(struct brcmf_bus), GFP_KERNEL); + if (!bus_if) + return -ENOMEM; ++ mutex_init(&bus_if->bus_reset_lock); + sdiodev = kzalloc(sizeof(struct brcmf_sdio_dev), GFP_KERNEL); + if (!sdiodev) { + kfree(bus_if); +@@ -1126,6 +1127,14 @@ static void brcmf_ops_sdio_remove(struct + if (func->num != 1) + return; + ++ /* Drain bus_reset before the shared brcmf_sdiod_remove() ++ * teardown, which the SDIO reset callback also reaches. The ++ * data worker can arm bus_reset via brcmf_fw_crashed(); cancel ++ * it first. ++ */ ++ brcmf_sdio_cancel_datawork(sdiodev->bus); ++ brcmf_bus_cancel_reset_work(bus_if); ++ + /* only proceed with rest of cleanup if func 1 */ + brcmf_sdiod_remove(sdiodev); + +@@ -1200,6 +1209,8 @@ static int brcmf_ops_sdio_suspend(struct + } else { + /* power will be cut so remove device, probe again in resume */ + brcmf_sdiod_intr_unregister(sdiodev); ++ brcmf_sdio_cancel_datawork(sdiodev->bus); ++ brcmf_bus_cancel_reset_work(bus_if); + ret = brcmf_sdiod_remove(sdiodev); + if (ret) + brcmf_err("Failed to remove device on suspend\n"); +@@ -1225,6 +1236,8 @@ static int brcmf_ops_sdio_resume(struct + ret = brcmf_sdiod_probe(sdiodev); + if (ret) + brcmf_err("Failed to probe device on resume\n"); ++ else ++ brcmf_bus_allow_reset_work(bus_if); + } else { + if (sdiodev->wowl_enabled && sdiodev->settings->bus.sdio.oob_irq_supported) + disable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr); +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + #include "debug.h" + + /* IDs of the 6 default common rings of msgbuf protocol */ +@@ -179,6 +180,8 @@ struct brcmf_bus { + enum brcmf_fwvendor fwvid; + bool always_use_fws_queue; + bool wowl_supported; ++ bool removing; /* device removal in progress; quiesce async work */ ++ struct mutex bus_reset_lock; + + const struct brcmf_bus_ops *ops; + struct brcmf_bus_msgbuf *msgbuf; +@@ -186,6 +189,9 @@ struct brcmf_bus { + struct list_head list; + }; + ++void brcmf_bus_cancel_reset_work(struct brcmf_bus *bus_if); ++void brcmf_bus_allow_reset_work(struct brcmf_bus *bus_if); ++ + /* + * callback wrappers + */ +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +@@ -1162,6 +1162,35 @@ static int brcmf_revinfo_read(struct seq + return 0; + } + ++/* ++ * Serialize arming from debugfs reset and brcmf_fw_crashed() against ++ * teardown. The remove path sets ->removing and drains the work while ++ * holding bus_reset_lock, so a racing armer is either drained or skips it. ++ */ ++static void brcmf_bus_schedule_reset(struct brcmf_bus *bus_if) ++{ ++ mutex_lock(&bus_if->bus_reset_lock); ++ if (bus_if->drvr && bus_if->drvr->bus_reset.func && !bus_if->removing) ++ schedule_work(&bus_if->drvr->bus_reset); ++ mutex_unlock(&bus_if->bus_reset_lock); ++} ++ ++void brcmf_bus_cancel_reset_work(struct brcmf_bus *bus_if) ++{ ++ mutex_lock(&bus_if->bus_reset_lock); ++ bus_if->removing = true; ++ if (bus_if->drvr) ++ cancel_work_sync(&bus_if->drvr->bus_reset); ++ mutex_unlock(&bus_if->bus_reset_lock); ++} ++ ++void brcmf_bus_allow_reset_work(struct brcmf_bus *bus_if) ++{ ++ mutex_lock(&bus_if->bus_reset_lock); ++ bus_if->removing = false; ++ mutex_unlock(&bus_if->bus_reset_lock); ++} ++ + static void brcmf_core_bus_reset(struct work_struct *work) + { + struct brcmf_pub *drvr = container_of(work, struct brcmf_pub, +@@ -1182,7 +1211,7 @@ static ssize_t bus_reset_write(struct fi + if (value != 1) + return -EINVAL; + +- schedule_work(&drvr->bus_reset); ++ brcmf_bus_schedule_reset(drvr->bus_if); + + return count; + } +@@ -1407,14 +1436,23 @@ void brcmf_dev_coredump(struct device *d + void brcmf_fw_crashed(struct device *dev) + { + struct brcmf_bus *bus_if = dev_get_drvdata(dev); +- struct brcmf_pub *drvr = bus_if->drvr; ++ struct brcmf_pub *drvr; ++ ++ /* May fire before brcmf_attach() wires up drvr, or after removal ++ * has cleared it; guard the derefs below (and the arming gate in ++ * brcmf_bus_schedule_reset() already checks drvr/->removing). ++ */ ++ if (!bus_if) ++ return; ++ drvr = bus_if->drvr; ++ if (!drvr) ++ return; + + bphy_err(drvr, "Firmware has halted or crashed\n"); + + brcmf_dev_coredump(dev); + +- if (drvr->bus_reset.func) +- schedule_work(&drvr->bus_reset); ++ brcmf_bus_schedule_reset(bus_if); + } + + void brcmf_detach(struct device *dev) +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +@@ -2467,6 +2467,7 @@ brcmf_pcie_probe(struct pci_dev *pdev, c + ret = -ENOMEM; + goto fail; + } ++ mutex_init(&bus->bus_reset_lock); + bus->msgbuf = kzalloc(sizeof(*bus->msgbuf), GFP_KERNEL); + if (!bus->msgbuf) { + ret = -ENOMEM; +@@ -2552,6 +2553,11 @@ brcmf_pcie_remove(struct pci_dev *pdev) + if (devinfo->ci) + brcmf_pcie_intr_disable(devinfo); + ++ if (devinfo->irq_allocated) ++ synchronize_irq(pdev->irq); ++ ++ brcmf_bus_cancel_reset_work(bus); ++ + brcmf_detach(&pdev->dev); + brcmf_free(&pdev->dev); + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -4550,6 +4550,12 @@ fail: + return NULL; + } + ++void brcmf_sdio_cancel_datawork(struct brcmf_sdio *bus) ++{ ++ if (bus) ++ cancel_work_sync(&bus->datawork); ++} ++ + /* Detach and free everything */ + void brcmf_sdio_remove(struct brcmf_sdio *bus) + { +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +@@ -361,6 +361,7 @@ int brcmf_sdiod_remove(struct brcmf_sdio + struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev); + void brcmf_sdio_remove(struct brcmf_sdio *bus); + void brcmf_sdio_isr(struct brcmf_sdio *bus, bool in_isr); ++void brcmf_sdio_cancel_datawork(struct brcmf_sdio *bus); + + void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, bool active); + void brcmf_sdio_wowl_config(struct device *dev, bool enabled); +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +@@ -1261,6 +1261,7 @@ static int brcmf_usb_probe_cb(struct brc + ret = -ENOMEM; + goto fail; + } ++ mutex_init(&bus->bus_reset_lock); + + bus->dev = dev; + bus_pub->bus = bus; +@@ -1327,6 +1328,8 @@ brcmf_usb_disconnect_cb(struct brcmf_usb + return; + brcmf_dbg(USB, "Enter, bus_pub %p\n", devinfo); + ++ brcmf_bus_cancel_reset_work(devinfo->bus_pub.bus); ++ + brcmf_detach(devinfo->dev); + brcmf_free(devinfo->dev); + kfree(devinfo->bus_pub.bus); diff --git a/queue-6.6/wifi-brcmfmac-fix-43752-sdio-fwvid-incorrectly-labelled-as-cypress-cyw.patch b/queue-6.6/wifi-brcmfmac-fix-43752-sdio-fwvid-incorrectly-labelled-as-cypress-cyw.patch new file mode 100644 index 0000000000..5eefd866ef --- /dev/null +++ b/queue-6.6/wifi-brcmfmac-fix-43752-sdio-fwvid-incorrectly-labelled-as-cypress-cyw.patch @@ -0,0 +1,130 @@ +From stable+bounces-296844-greg=kroah.com@vger.kernel.org Thu Aug 6 15:59:58 2026 +From: Sasha Levin +Date: Thu, 6 Aug 2026 09:57:56 -0400 +Subject: wifi: brcmfmac: fix 43752 SDIO FWVID incorrectly labelled as Cypress (CYW) +To: stable@vger.kernel.org +Cc: Gokul Sivakumar , Arend van Spriel , Johannes Berg , Sasha Levin +Message-ID: <20260806135757.628201-1-sashal@kernel.org> + +From: Gokul Sivakumar + +[ Upstream commit 74e2ef72bd4b25ce21c8f309d4f5b91b5df9ff5b ] + +Cypress(Infineon) is not the vendor for this 43752 SDIO WLAN chip, and so +has not officially released any firmware binary for it. It is incorrect to +maintain this WLAN chip with firmware vendor ID as "CYW". So relabel the +chip's firmware Vendor ID as "WCC" as suggested by the maintainer. + +Fixes: d2587c57ffd8 ("brcmfmac: add 43752 SDIO ids and initialization") +Fixes: f74f1ec22dc2 ("wifi: brcmfmac: add support for Cypress firmware api") +Signed-off-by: Gokul Sivakumar +Acked-by: Arend van Spriel +Link: https://patch.msgid.link/20250724101136.6691-1-gokulkumar.sivakumar@infineon.com +Signed-off-by: Johannes Berg +Stable-dep-of: 29ab31f3f271 ("wifi: brcmfmac: set F2 blocksize to 256 for BCM43752") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 2 +- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c | 4 ++-- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 8 ++++---- + drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h | 2 +- + include/linux/mmc/sdio_ids.h | 2 +- + 5 files changed, 9 insertions(+), 9 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -991,9 +991,9 @@ static const struct sdio_device_id brcmf + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354, WCC), + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4356, WCC), + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4359, WCC), ++ BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43752, WCC), + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373, CYW), + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43012, CYW), +- BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752, CYW), + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_89359, CYW), + CYW_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439, CYW), + { /* end: all zeroes */ } +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +@@ -738,7 +738,7 @@ static u32 brcmf_chip_tcm_rambase(struct + case BRCM_CC_4364_CHIP_ID: + case CY_CC_4373_CHIP_ID: + return 0x160000; +- case CY_CC_43752_CHIP_ID: ++ case BRCM_CC_43752_CHIP_ID: + case BRCM_CC_4377_CHIP_ID: + return 0x170000; + case BRCM_CC_4378_CHIP_ID: +@@ -1465,7 +1465,7 @@ bool brcmf_chip_sr_capable(struct brcmf_ + reg = chip->ops->read32(chip->ctx, addr); + return (reg & CC_SR_CTL0_ENABLE_MASK) != 0; + case BRCM_CC_4359_CHIP_ID: +- case CY_CC_43752_CHIP_ID: ++ case BRCM_CC_43752_CHIP_ID: + case CY_CC_43012_CHIP_ID: + addr = CORE_CC_REG(pmu->base, retention_ctl); + reg = chip->ops->read32(chip->ctx, addr); +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -654,10 +654,10 @@ static const struct brcmf_firmware_mappi + BRCMF_FW_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354), + BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356), + BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359), ++ BRCMF_FW_ENTRY(BRCM_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752), + BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373), + BRCMF_FW_ENTRY(CY_CC_43012_CHIP_ID, 0xFFFFFFFF, 43012), + BRCMF_FW_ENTRY(CY_CC_43439_CHIP_ID, 0xFFFFFFFF, 43439), +- BRCMF_FW_ENTRY(CY_CC_43752_CHIP_ID, 0xFFFFFFFF, 43752) + }; + + #define TXCTL_CREDITS 2 +@@ -3425,8 +3425,8 @@ err: + + static bool brcmf_sdio_aos_no_decode(struct brcmf_sdio *bus) + { +- if (bus->ci->chip == CY_CC_43012_CHIP_ID || +- bus->ci->chip == CY_CC_43752_CHIP_ID) ++ if (bus->ci->chip == BRCM_CC_43752_CHIP_ID || ++ bus->ci->chip == CY_CC_43012_CHIP_ID) + return true; + else + return false; +@@ -4274,8 +4274,8 @@ static void brcmf_sdio_firmware_callback + bus->hostintmask, NULL); + + switch (sdiod->func1->device) { ++ case SDIO_DEVICE_ID_BROADCOM_43752: + case SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373: +- case SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752: + brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes\n", + CY_4373_F2_WATERMARK); + brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK, +--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h ++++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h +@@ -52,13 +52,13 @@ + #define BRCM_CC_43664_CHIP_ID 43664 + #define BRCM_CC_43666_CHIP_ID 43666 + #define BRCM_CC_4371_CHIP_ID 0x4371 ++#define BRCM_CC_43752_CHIP_ID 43752 + #define BRCM_CC_4377_CHIP_ID 0x4377 + #define BRCM_CC_4378_CHIP_ID 0x4378 + #define BRCM_CC_4387_CHIP_ID 0x4387 + #define CY_CC_4373_CHIP_ID 0x4373 + #define CY_CC_43012_CHIP_ID 43012 + #define CY_CC_43439_CHIP_ID 43439 +-#define CY_CC_43752_CHIP_ID 43752 + + /* USB Device IDs */ + #define BRCM_USB_43143_DEVICE_ID 0xbd1e +--- a/include/linux/mmc/sdio_ids.h ++++ b/include/linux/mmc/sdio_ids.h +@@ -76,7 +76,7 @@ + #define SDIO_DEVICE_ID_BROADCOM_43430 0xa9a6 + #define SDIO_DEVICE_ID_BROADCOM_43439 0xa9af + #define SDIO_DEVICE_ID_BROADCOM_43455 0xa9bf +-#define SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752 0xaae8 ++#define SDIO_DEVICE_ID_BROADCOM_43752 0xaae8 + + #define SDIO_VENDOR_ID_CYPRESS 0x04b4 + #define SDIO_DEVICE_ID_BROADCOM_CYPRESS_43439 0xbd3d diff --git a/queue-6.6/wifi-brcmfmac-set-f2-blocksize-to-256-for-bcm43752.patch b/queue-6.6/wifi-brcmfmac-set-f2-blocksize-to-256-for-bcm43752.patch new file mode 100644 index 0000000000..1cf9756322 --- /dev/null +++ b/queue-6.6/wifi-brcmfmac-set-f2-blocksize-to-256-for-bcm43752.patch @@ -0,0 +1,59 @@ +From stable+bounces-296843-greg=kroah.com@vger.kernel.org Thu Aug 6 15:59:49 2026 +From: Sasha Levin +Date: Thu, 6 Aug 2026 09:57:57 -0400 +Subject: wifi: brcmfmac: set F2 blocksize to 256 for BCM43752 +To: stable@vger.kernel.org +Cc: LiangCheng Wang , Arend van Spriel , Johannes Berg , Sasha Levin +Message-ID: <20260806135757.628201-2-sashal@kernel.org> + +From: LiangCheng Wang + +[ Upstream commit 29ab31f3f27157648f2f7e6d5e1fd9792fdf0614 ] + +The BCM43752 is not reliable with the default 512-byte SDIO function 2 +block size: on an i.MX8MP board with an AMPAK AP6275S module at +SDR104 / 200 MHz, an iperf TX stress test kills WLAN within seconds: + + mmc_submit_one: CMD53 sg block write failed -84 + brcmf_sdio_dpc: failed backplane access over SDIO, halting operation + +Commit d2587c57ffd8 ("brcmfmac: add 43752 SDIO ids and initialization") +set up the 43752 like the 4373 for the F2 watermark but missed the F2 +block size, which the 4373 limits to 256 bytes. The vendor driver +(bcmdhd) also programs a 256-byte F2 block size for this chip and runs +the same hardware without errors. + +Group the 43752 with the 4373, matching the F2 watermark handling. +With this change a 10-minute bidirectional iperf3 soak completes with +zero SDIO errors at ~270 Mbit/s in each direction. + +Backporting note: kernels before v6.18 name this id +SDIO_DEVICE_ID_BROADCOM_CYPRESS_43752, so on those trees the case +label added by this patch must be adjusted to that name. Cherry-picking +the rename commit 74e2ef72bd4b ("wifi: brcmfmac: fix 43752 SDIO FWVID +incorrectly labelled as Cypress (CYW)") first is not a clean +alternative: on trees before v6.17 its context collides with the 43751 +additions, and trees before v6.2 lack the FWVID framework it touches. + +Fixes: d2587c57ffd8 ("brcmfmac: add 43752 SDIO ids and initialization") +Cc: stable@vger.kernel.org # see patch description, needs adjustments for <= 6.17 +Signed-off-by: LiangCheng Wang +Acked-by: Arend van Spriel +Link: https://patch.msgid.link/20260715-b43752-f2-blksz-v2-1-f9be49856050@gmail.com +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -906,6 +906,7 @@ int brcmf_sdiod_probe(struct brcmf_sdio_ + return ret; + } + switch (sdiodev->func2->device) { ++ case SDIO_DEVICE_ID_BROADCOM_43752: + case SDIO_DEVICE_ID_BROADCOM_CYPRESS_4373: + f2_blksz = SDIO_4373_FUNC2_BLOCKSIZE; + break;