mirror of
https://github.com/torvalds/linux.git
synced 2026-10-07 19:16:02 +02:00
ksmbd: extend procfs server statistics
The server proc entry does not expose configured limits or enough outcome data to distinguish protocol errors from transport stalls. Report the server state, listener and signing configuration, connection limits, timeout values, current client and open-file totals, IPC activity, and durable scavenger state. Classify processed SMB2 response statuses by NTSTATUS severity and provide counters for common error groups while retaining the per-command counters. Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
1248f400e0
commit
4c670ccd57
|
|
@ -11,10 +11,12 @@
|
|||
#include <linux/seq_file.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "connection.h"
|
||||
#include "server.h"
|
||||
#include "stats.h"
|
||||
#include "smb_common.h"
|
||||
#include "smb2pdu.h"
|
||||
#include "vfs_cache.h"
|
||||
|
||||
static struct proc_dir_entry *ksmbd_proc_fs;
|
||||
struct ksmbd_counters ksmbd_counters;
|
||||
|
|
@ -90,34 +92,127 @@ static const struct ksmbd_const_smb2_process_req smb2_process_req[KSMBD_COUNTER_
|
|||
{le16_to_cpu(SMB2_OPLOCK_BREAK), "SMB2_OPLOCK_BREAK"},
|
||||
};
|
||||
|
||||
static const char *ksmbd_server_state_string(void)
|
||||
{
|
||||
switch (READ_ONCE(server_conf.state)) {
|
||||
case SERVER_STATE_STARTING_UP:
|
||||
return "starting";
|
||||
case SERVER_STATE_RUNNING:
|
||||
return "running";
|
||||
case SERVER_STATE_RESETTING:
|
||||
return "resetting";
|
||||
case SERVER_STATE_SHUTTING_DOWN:
|
||||
return "shutdown";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *ksmbd_signing_mode_string(void)
|
||||
{
|
||||
switch (server_conf.signing) {
|
||||
case KSMBD_CONFIG_OPT_DISABLED:
|
||||
return "disabled";
|
||||
case KSMBD_CONFIG_OPT_MANDATORY:
|
||||
return "mandatory";
|
||||
case KSMBD_CONFIG_OPT_AUTO:
|
||||
return "auto";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static void proc_show_runtime_totals(struct seq_file *m)
|
||||
{
|
||||
struct ksmbd_conn *conn;
|
||||
unsigned int clients = 0;
|
||||
unsigned int open_files = 0;
|
||||
int i;
|
||||
|
||||
down_read(&conn_list_lock);
|
||||
hash_for_each(conn_list, i, conn, hlist) {
|
||||
clients++;
|
||||
open_files += atomic_read(&conn->stats.open_files_count);
|
||||
}
|
||||
up_read(&conn_list_lock);
|
||||
|
||||
seq_printf(m, "clients:\t%u\n", clients);
|
||||
seq_printf(m, "open_files:\t%u\n", open_files);
|
||||
}
|
||||
|
||||
static int proc_show_ksmbd_stats(struct seq_file *m, void *v)
|
||||
{
|
||||
int i;
|
||||
|
||||
seq_puts(m, "Server\n");
|
||||
seq_printf(m, "name: %s\n", ksmbd_server_string());
|
||||
seq_printf(m, "netbios: %s\n", ksmbd_netbios_name());
|
||||
seq_printf(m, "work group: %s\n", ksmbd_work_group());
|
||||
seq_printf(m, "min protocol: %s\n", ksmbd_get_protocol_string(server_conf.min_protocol));
|
||||
seq_printf(m, "max protocol: %s\n", ksmbd_get_protocol_string(server_conf.max_protocol));
|
||||
seq_printf(m, "flags: 0x%08x\n", server_conf.flags);
|
||||
seq_printf(m, "share_fake_fscaps: 0x%08x\n",
|
||||
seq_printf(m, "state:\t%s\n", ksmbd_server_state_string());
|
||||
seq_printf(m, "name:\t%s\n", ksmbd_server_string());
|
||||
seq_printf(m, "netbios:\t%s\n", ksmbd_netbios_name());
|
||||
seq_printf(m, "work_group:\t%s\n", ksmbd_work_group());
|
||||
seq_printf(m, "min_protocol:\t%s\n", ksmbd_get_protocol_string(server_conf.min_protocol));
|
||||
seq_printf(m, "max_protocol:\t%s\n", ksmbd_get_protocol_string(server_conf.max_protocol));
|
||||
seq_printf(m, "flags:\t0x%08x\n", server_conf.flags);
|
||||
seq_printf(m, "tcp_port:\t%u\n", server_conf.tcp_port);
|
||||
seq_printf(m, "signing:\t%s\n", ksmbd_signing_mode_string());
|
||||
seq_printf(m, "signing_enforced:\t%s\n",
|
||||
server_conf.enforced_signing ? "yes" : "no");
|
||||
seq_printf(m, "bind_interfaces_only:\t%s\n",
|
||||
server_conf.bind_interfaces_only ? "yes" : "no");
|
||||
seq_printf(m, "max_connections:\t%u\n", server_conf.max_connections);
|
||||
seq_printf(m, "max_connections_per_ip:\t%u\n",
|
||||
server_conf.max_ip_connections);
|
||||
seq_printf(m, "max_inflight_requests:\t%u\n",
|
||||
server_conf.max_inflight_req);
|
||||
seq_printf(m, "deadtime_seconds:\t%lu\n", server_conf.deadtime / HZ);
|
||||
seq_printf(m, "ipc_timeout_seconds:\t%u\n", server_conf.ipc_timeout / HZ);
|
||||
if (server_conf.ipc_last_active)
|
||||
seq_printf(m, "ipc_last_active_seconds:\t%lu\n",
|
||||
jiffies_to_msecs(jiffies - server_conf.ipc_last_active) /
|
||||
MSEC_PER_SEC);
|
||||
else
|
||||
seq_puts(m, "ipc_last_active_seconds:\tnever\n");
|
||||
seq_printf(m, "durable_scavenger:\t%s\n",
|
||||
ksmbd_durable_scavenger_active() ? "running" : "stopped");
|
||||
seq_printf(m, "share_fake_fscaps:\t0x%08x\n",
|
||||
server_conf.share_fake_fscaps);
|
||||
seq_printf(m, "sessions: %lld\n",
|
||||
proc_show_runtime_totals(m);
|
||||
seq_printf(m, "sessions:\t%lld\n",
|
||||
ksmbd_counter_sum(KSMBD_COUNTER_SESSIONS));
|
||||
seq_printf(m, "tree connects: %lld\n",
|
||||
seq_printf(m, "tree_connects:\t%lld\n",
|
||||
ksmbd_counter_sum(KSMBD_COUNTER_TREE_CONNS));
|
||||
seq_printf(m, "requests: %lld\n",
|
||||
seq_printf(m, "requests:\t%lld\n",
|
||||
ksmbd_counter_sum(KSMBD_COUNTER_REQUESTS));
|
||||
seq_printf(m, "read bytes: %lld\n",
|
||||
seq_printf(m, "read_bytes:\t%lld\n",
|
||||
ksmbd_counter_sum(KSMBD_COUNTER_READ_BYTES));
|
||||
seq_printf(m, "written bytes: %lld\n",
|
||||
seq_printf(m, "written_bytes:\t%lld\n",
|
||||
ksmbd_counter_sum(KSMBD_COUNTER_WRITE_BYTES));
|
||||
|
||||
seq_puts(m, "\nSMB2\n");
|
||||
for (i = 0; i < KSMBD_COUNTER_MAX_REQS; i++)
|
||||
seq_printf(m, "%-20s:\t%lld\n", smb2_process_req[i].name,
|
||||
seq_printf(m, "%s:\t%lld\n", smb2_process_req[i].name,
|
||||
ksmbd_counter_sum(KSMBD_COUNTER_FIRST_REQ + i));
|
||||
|
||||
seq_puts(m, "\nSMB2 status\n");
|
||||
seq_printf(m, "success:\t%lld\n",
|
||||
ksmbd_counter_sum(KSMBD_COUNTER_STATUS_SUCCESS));
|
||||
seq_printf(m, "informational:\t%lld\n",
|
||||
ksmbd_counter_sum(KSMBD_COUNTER_STATUS_INFORMATIONAL));
|
||||
seq_printf(m, "warning:\t%lld\n",
|
||||
ksmbd_counter_sum(KSMBD_COUNTER_STATUS_WARNING));
|
||||
seq_printf(m, "error:\t%lld\n",
|
||||
ksmbd_counter_sum(KSMBD_COUNTER_STATUS_ERROR));
|
||||
seq_printf(m, "access_denied:\t%lld\n",
|
||||
ksmbd_counter_sum(KSMBD_COUNTER_ERROR_ACCESS_DENIED));
|
||||
seq_printf(m, "not_found:\t%lld\n",
|
||||
ksmbd_counter_sum(KSMBD_COUNTER_ERROR_NOT_FOUND));
|
||||
seq_printf(m, "invalid_parameter:\t%lld\n",
|
||||
ksmbd_counter_sum(KSMBD_COUNTER_ERROR_INVALID_PARAMETER));
|
||||
seq_printf(m, "sharing_violation:\t%lld\n",
|
||||
ksmbd_counter_sum(KSMBD_COUNTER_ERROR_SHARING_VIOLATION));
|
||||
seq_printf(m, "not_supported:\t%lld\n",
|
||||
ksmbd_counter_sum(KSMBD_COUNTER_ERROR_NOT_SUPPORTED));
|
||||
seq_printf(m, "other:\t%lld\n",
|
||||
ksmbd_counter_sum(KSMBD_COUNTER_ERROR_OTHER));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -156,8 +156,11 @@ static int __process_request(struct ksmbd_work *work, struct ksmbd_conn *conn,
|
|||
}
|
||||
|
||||
ret = cmds->proc(work);
|
||||
if (conn->ops->inc_reqs)
|
||||
conn->ops->inc_reqs(command);
|
||||
if (conn->ops->inc_reqs) {
|
||||
struct smb2_hdr *rsp = ksmbd_resp_buf_curr(work);
|
||||
|
||||
conn->ops->inc_reqs(command, rsp->Status);
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
ksmbd_debug(CONN, "Failed to process %u [%d]\n", command, ret);
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ struct file_id_both_directory_info {
|
|||
|
||||
struct smb_version_ops {
|
||||
u16 (*get_cmd_val)(struct ksmbd_work *swork);
|
||||
void (*inc_reqs)(unsigned int cmd);
|
||||
void (*inc_reqs)(unsigned int cmd, __le32 status);
|
||||
int (*init_rsp_hdr)(struct ksmbd_work *swork);
|
||||
void (*set_rsp_status)(struct ksmbd_work *swork, __le32 err);
|
||||
int (*allocate_rsp_buf)(struct ksmbd_work *work);
|
||||
|
|
|
|||
|
|
@ -9,12 +9,24 @@
|
|||
#ifndef __KSMBD_STATS_H__
|
||||
#define __KSMBD_STATS_H__
|
||||
|
||||
#include "../common/smb2status.h"
|
||||
|
||||
#define KSMBD_COUNTER_MAX_REQS 19
|
||||
|
||||
enum {
|
||||
KSMBD_COUNTER_SESSIONS = 0,
|
||||
KSMBD_COUNTER_TREE_CONNS,
|
||||
KSMBD_COUNTER_REQUESTS,
|
||||
KSMBD_COUNTER_STATUS_SUCCESS,
|
||||
KSMBD_COUNTER_STATUS_INFORMATIONAL,
|
||||
KSMBD_COUNTER_STATUS_WARNING,
|
||||
KSMBD_COUNTER_STATUS_ERROR,
|
||||
KSMBD_COUNTER_ERROR_ACCESS_DENIED,
|
||||
KSMBD_COUNTER_ERROR_NOT_FOUND,
|
||||
KSMBD_COUNTER_ERROR_INVALID_PARAMETER,
|
||||
KSMBD_COUNTER_ERROR_SHARING_VIOLATION,
|
||||
KSMBD_COUNTER_ERROR_NOT_SUPPORTED,
|
||||
KSMBD_COUNTER_ERROR_OTHER,
|
||||
KSMBD_COUNTER_READ_BYTES,
|
||||
KSMBD_COUNTER_WRITE_BYTES,
|
||||
KSMBD_COUNTER_FIRST_REQ,
|
||||
|
|
@ -50,8 +62,45 @@ static inline void ksmbd_counter_sub(int type, s64 value)
|
|||
percpu_counter_sub(&ksmbd_counters.counters[type], value);
|
||||
}
|
||||
|
||||
static inline void ksmbd_counter_inc_reqs(unsigned int cmd)
|
||||
static inline void ksmbd_counter_inc_reqs(unsigned int cmd, __le32 status)
|
||||
{
|
||||
unsigned int severity = le32_to_cpu(status) >> 30;
|
||||
int type;
|
||||
|
||||
switch (severity) {
|
||||
case 0:
|
||||
type = KSMBD_COUNTER_STATUS_SUCCESS;
|
||||
break;
|
||||
case 1:
|
||||
type = KSMBD_COUNTER_STATUS_INFORMATIONAL;
|
||||
break;
|
||||
case 2:
|
||||
type = KSMBD_COUNTER_STATUS_WARNING;
|
||||
break;
|
||||
default:
|
||||
type = KSMBD_COUNTER_STATUS_ERROR;
|
||||
break;
|
||||
}
|
||||
percpu_counter_inc(&ksmbd_counters.counters[type]);
|
||||
|
||||
if (severity == 3) {
|
||||
if (status == STATUS_ACCESS_DENIED)
|
||||
type = KSMBD_COUNTER_ERROR_ACCESS_DENIED;
|
||||
else if (status == STATUS_OBJECT_NAME_NOT_FOUND ||
|
||||
status == STATUS_NO_SUCH_FILE)
|
||||
type = KSMBD_COUNTER_ERROR_NOT_FOUND;
|
||||
else if (status == STATUS_INVALID_PARAMETER)
|
||||
type = KSMBD_COUNTER_ERROR_INVALID_PARAMETER;
|
||||
else if (status == STATUS_SHARING_VIOLATION)
|
||||
type = KSMBD_COUNTER_ERROR_SHARING_VIOLATION;
|
||||
else if (status == STATUS_NOT_SUPPORTED ||
|
||||
status == STATUS_NOT_IMPLEMENTED)
|
||||
type = KSMBD_COUNTER_ERROR_NOT_SUPPORTED;
|
||||
else
|
||||
type = KSMBD_COUNTER_ERROR_OTHER;
|
||||
percpu_counter_inc(&ksmbd_counters.counters[type]);
|
||||
}
|
||||
|
||||
if (cmd < KSMBD_COUNTER_MAX_REQS) {
|
||||
percpu_counter_inc(&ksmbd_counters.counters[KSMBD_COUNTER_REQUESTS]);
|
||||
percpu_counter_inc(&ksmbd_counters.counters[KSMBD_COUNTER_FIRST_REQ + cmd]);
|
||||
|
|
@ -68,7 +117,7 @@ static inline void ksmbd_counter_inc(int type) {}
|
|||
static inline void ksmbd_counter_dec(int type) {}
|
||||
static inline void ksmbd_counter_add(int type, s64 value) {}
|
||||
static inline void ksmbd_counter_sub(int type, s64 value) {}
|
||||
static inline void ksmbd_counter_inc_reqs(unsigned int cmd) {}
|
||||
static inline void ksmbd_counter_inc_reqs(unsigned int cmd, __le32 status) {}
|
||||
static inline s64 ksmbd_counter_sum(int type) { return 0; }
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -191,6 +191,16 @@ static bool durable_scavenger_running;
|
|||
static DEFINE_MUTEX(durable_scavenger_lock);
|
||||
static wait_queue_head_t dh_wq;
|
||||
|
||||
bool ksmbd_durable_scavenger_active(void)
|
||||
{
|
||||
bool active;
|
||||
|
||||
mutex_lock(&durable_scavenger_lock);
|
||||
active = durable_scavenger_running;
|
||||
mutex_unlock(&durable_scavenger_lock);
|
||||
return active;
|
||||
}
|
||||
|
||||
void ksmbd_set_fd_limit(unsigned long limit)
|
||||
{
|
||||
limit = min(limit, get_max_files());
|
||||
|
|
|
|||
|
|
@ -216,6 +216,7 @@ unsigned int ksmbd_open_durable_fd(struct ksmbd_file *fp);
|
|||
struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp);
|
||||
void ksmbd_launch_ksmbd_durable_scavenger(void);
|
||||
void ksmbd_stop_durable_scavenger(void);
|
||||
bool ksmbd_durable_scavenger_active(void);
|
||||
void ksmbd_close_tree_conn_fds(struct ksmbd_work *work);
|
||||
void ksmbd_close_session_fds(struct ksmbd_work *work);
|
||||
int ksmbd_close_inode_fds(struct ksmbd_work *work, struct inode *inode);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user