Commit 0626e664 authored by Namjae Jeon's avatar Namjae Jeon Committed by Steve French
Browse files

cifsd: add server handler for central processing and tranport layers



This adds server handler for central processing,
transport layers(tcp, rdma, ipc) and a document describing cifsd
architecture.

Signed-off-by: default avatarNamjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: default avatarSergey Senozhatsky <sergey.senozhatsky@gmail.com>
Signed-off-by: default avatarHyunchul Lee <hyc.lee@gmail.com>
Acked-by: default avatarRonnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 6efb943b
Loading
Loading
Loading
Loading
+136 −0
Original line number Diff line number Diff line
.. SPDX-License-Identifier: GPL-2.0

=========================
CIFSD - SMB3 Kernel Server
=========================

CIFSD is a linux kernel server which implements SMB3 protocol in kernel space
for sharing files over network.

CIFSD architecture
==================

The subset of performance related operations belong in kernelspace and
the other subset which belong to operations which are not really related with
performance in userspace. So, DCE/RPC management that has historically resulted
into number of buffer overflow issues and dangerous security bugs and user
account management are implemented in user space as ksmbd.mountd.
File operations that are related with performance (open/read/write/close etc.)
in kernel space (ksmbd). This also allows for easier integration with VFS
interface for all file operations.

ksmbd (kernel daemon)
---------------------

When the server daemon is started, It starts up a forker thread
(ksmbd/interface name) at initialization time and open a dedicated port 445
for listening to SMB requests. Whenever new clients make request, Forker
thread will accept the client connection and fork a new thread for dedicated
communication channel between the client and the server. It allows for parallel
processing of SMB requests(commands) from clients as well as allowing for new
clients to make new connections. Each instance is named ksmbd/1~n(port number)
to indicate connected clients. Depending on the SMB request types, each new
thread can decide to pass through the commands to the user space (ksmbd.mountd),
currently DCE/RPC commands are identified to be handled through the user space.
To further utilize the linux kernel, it has been chosen to process the commands
as workitems and to be executed in the handlers of the ksmbd-io kworker threads.
It allows for multiplexing of the handlers as the kernel take care of initiating
extra worker threads if the load is increased and vice versa, if the load is
decreased it destroys the extra worker threads. So, after connection is
established with client. Dedicated ksmbd/1..n(port number) takes complete
ownership of receiving/parsing of SMB commands. Each received command is worked
in parallel i.e., There can be multiple clients commands which are worked in
parallel. After receiving each command a separated kernel workitem is prepared
for each command which is further queued to be handled by ksmbd-io kworkers.
So, each SMB workitem is queued to the kworkers. This allows the benefit of load
sharing to be managed optimally by the default kernel and optimizing client
performance by handling client commands in parallel.

ksmbd.mountd (user space daemon)
--------------------------------

ksmbd.mountd is userspace process to, transfer user account and password that
are registered using ksmbd.adduser(part of utils for user space). Further it
allows sharing information parameters that parsed from smb.conf to ksmbd in
kernel. For the execution part it has a daemon which is continuously running
and connected to the kernel interface using netlink socket, it waits for the
requests(dcerpc and share/user info). It handles RPC calls (at a minimum few
dozen) that are most important for file server from NetShareEnum and
NetServerGetInfo. Complete DCE/RPC response is prepared from the user space
and passed over to the associated kernel thread for the client.

Key Features
============

The supported features are:
 * SMB3 protocols for basic file sharing
 * Auto negotiation
 * Compound requests
 * Oplock/Lease
 * Large MTU
 * NTLM/NTLMv2
 * HMAC-SHA256 Signing
 * Secure negotiate
 * Signing Update
 * Pre-authentication integrity(SMB 3.1.1)
 * SMB3 encryption(CCM, GCM)
 * SMB direct(RDMA)
 * SMB3.1.1 POSIX extension support
 * ACLs
 * Kerberos

The features that are planned or not supported:
 * SMB3 Multi-channel
 * Durable handle v1,v2
 * Persistent handles
 * Directory lease
 * SMB2 notify

How to run
==========

1. Download ksmbd-tools and compile them.
	- https://github.com/cifsd-team/ksmbd-tools

2. Create user/password for SMB share.

	# mkdir /etc/ksmbd/
	# ksmbd.adduser -a <Enter USERNAME for SMB share access>

3. Create /etc/ksmbd/smb.conf file, add SMB share in smb.conf file
	- Refer smb.conf.example and Documentation/configuration.txt
	  in ksmbd-tools

4. Insert ksmbd.ko module

	# insmod ksmbd.ko

5. Start ksmbd user space daemon
	# ksmbd.mountd

6. Access share from Windows or Linux using CIFS

Shutdown CIFSD
==============

1. kill user and kernel space daemon
	# sudo ksmbd.control -s

How to turn debug print on
==========================

Each layer
/sys/class/ksmbd-control/debug

1. Enable all component prints
	# sudo ksmbd.control -d "all"

2. Enable one of components(smb, auth, vfs, oplock, ipc, conn, rdma)
	# sudo ksmbd.control -d "smb"

3. Show what prints are enable.
	# cat/sys/class/ksmbd-control/debug
	  [smb] auth vfs oplock ipc conn [rdma]

4. Disable prints:
	If you try the selected component once more, It is disabled without brackets.

fs/cifsd/connection.c

0 → 100644
+416 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 *   Copyright (C) 2016 Namjae Jeon <namjae.jeon@protocolfreedom.org>
 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 */

#include <linux/mutex.h>
#include <linux/freezer.h>
#include <linux/module.h>

#include "server.h"
#include "buffer_pool.h"
#include "smb_common.h"
#include "mgmt/ksmbd_ida.h"
#include "connection.h"
#include "transport_tcp.h"
#include "transport_rdma.h"

static DEFINE_MUTEX(init_lock);

static struct ksmbd_conn_ops default_conn_ops;

static LIST_HEAD(conn_list);
static DEFINE_RWLOCK(conn_list_lock);

/**
 * ksmbd_conn_free() - free resources of the connection instance
 *
 * @conn:	connection instance to be cleand up
 *
 * During the thread termination, the corresponding conn instance
 * resources(sock/memory) are released and finally the conn object is freed.
 */
void ksmbd_conn_free(struct ksmbd_conn *conn)
{
	write_lock(&conn_list_lock);
	list_del(&conn->conns_list);
	write_unlock(&conn_list_lock);

	ksmbd_free_request(conn->request_buf);
	ksmbd_ida_free(conn->async_ida);
	kfree(conn->preauth_info);
	kfree(conn);
}

/**
 * ksmbd_conn_alloc() - initialize a new connection instance
 *
 * Return:	ksmbd_conn struct on success, otherwise NULL
 */
struct ksmbd_conn *ksmbd_conn_alloc(void)
{
	struct ksmbd_conn *conn;

	conn = kzalloc(sizeof(struct ksmbd_conn), GFP_KERNEL);
	if (!conn)
		return NULL;

	conn->need_neg = true;
	conn->status = KSMBD_SESS_NEW;
	conn->local_nls = load_nls("utf8");
	if (!conn->local_nls)
		conn->local_nls = load_nls_default();
	atomic_set(&conn->req_running, 0);
	atomic_set(&conn->r_count, 0);
	init_waitqueue_head(&conn->req_running_q);
	INIT_LIST_HEAD(&conn->conns_list);
	INIT_LIST_HEAD(&conn->sessions);
	INIT_LIST_HEAD(&conn->requests);
	INIT_LIST_HEAD(&conn->async_requests);
	spin_lock_init(&conn->request_lock);
	spin_lock_init(&conn->credits_lock);
	conn->async_ida = ksmbd_ida_alloc();

	write_lock(&conn_list_lock);
	list_add(&conn->conns_list, &conn_list);
	write_unlock(&conn_list_lock);
	return conn;
}

bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c)
{
	struct ksmbd_conn *t;
	bool ret = false;

	read_lock(&conn_list_lock);
	list_for_each_entry(t, &conn_list, conns_list) {
		if (memcmp(t->ClientGUID, c->ClientGUID, SMB2_CLIENT_GUID_SIZE))
			continue;

		ret = true;
		break;
	}
	read_unlock(&conn_list_lock);
	return ret;
}

void ksmbd_conn_enqueue_request(struct ksmbd_work *work)
{
	struct ksmbd_conn *conn = work->conn;
	struct list_head *requests_queue = NULL;

	if (conn->ops->get_cmd_val(work) != SMB2_CANCEL_HE) {
		requests_queue = &conn->requests;
		work->syncronous = true;
	}

	if (requests_queue) {
		atomic_inc(&conn->req_running);
		spin_lock(&conn->request_lock);
		list_add_tail(&work->request_entry, requests_queue);
		spin_unlock(&conn->request_lock);
	}
}

int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
{
	struct ksmbd_conn *conn = work->conn;
	int ret = 1;

	if (list_empty(&work->request_entry) &&
		list_empty(&work->async_request_entry))
		return 0;

	atomic_dec(&conn->req_running);
	spin_lock(&conn->request_lock);
	if (!work->multiRsp) {
		list_del_init(&work->request_entry);
		if (work->syncronous == false)
			list_del_init(&work->async_request_entry);
		ret = 0;
	}
	spin_unlock(&conn->request_lock);

	wake_up_all(&conn->req_running_q);
	return ret;
}

static void ksmbd_conn_lock(struct ksmbd_conn *conn)
{
	mutex_lock(&conn->srv_mutex);
}

static void ksmbd_conn_unlock(struct ksmbd_conn *conn)
{
	mutex_unlock(&conn->srv_mutex);
}

void ksmbd_conn_wait_idle(struct ksmbd_conn *conn)
{
	wait_event(conn->req_running_q, atomic_read(&conn->req_running) < 2);
}

int ksmbd_conn_write(struct ksmbd_work *work)
{
	struct ksmbd_conn *conn = work->conn;
	struct smb_hdr *rsp_hdr = RESPONSE_BUF(work);
	size_t len = 0;
	int sent;
	struct kvec iov[3];
	int iov_idx = 0;

	ksmbd_conn_try_dequeue_request(work);
	if (!rsp_hdr) {
		ksmbd_err("NULL response header\n");
		return -EINVAL;
	}

	if (HAS_TRANSFORM_BUF(work)) {
		iov[iov_idx] = (struct kvec) { work->tr_buf,
				sizeof(struct smb2_transform_hdr) };
		len += iov[iov_idx++].iov_len;
	}

	if (HAS_AUX_PAYLOAD(work)) {
		iov[iov_idx] = (struct kvec) { rsp_hdr, RESP_HDR_SIZE(work) };
		len += iov[iov_idx++].iov_len;
		iov[iov_idx] = (struct kvec) { AUX_PAYLOAD(work),
			AUX_PAYLOAD_SIZE(work) };
		len += iov[iov_idx++].iov_len;
	} else {
		if (HAS_TRANSFORM_BUF(work))
			iov[iov_idx].iov_len = RESP_HDR_SIZE(work);
		else
			iov[iov_idx].iov_len = get_rfc1002_len(rsp_hdr) + 4;
		iov[iov_idx].iov_base = rsp_hdr;
		len += iov[iov_idx++].iov_len;
	}

	ksmbd_conn_lock(conn);
	sent = conn->transport->ops->writev(conn->transport, &iov[0],
					iov_idx, len,
					work->need_invalidate_rkey,
					work->remote_key);
	ksmbd_conn_unlock(conn);

	if (sent < 0) {
		ksmbd_err("Failed to send message: %d\n", sent);
		return sent;
	}

	return 0;
}

int ksmbd_conn_rdma_read(struct ksmbd_conn *conn,
				void *buf, unsigned int buflen,
				u32 remote_key, u64 remote_offset,
				u32 remote_len)
{
	int ret = -EINVAL;

	if (conn->transport->ops->rdma_read)
		ret = conn->transport->ops->rdma_read(conn->transport,
						buf, buflen,
						remote_key, remote_offset,
						remote_len);
	return ret;
}

int ksmbd_conn_rdma_write(struct ksmbd_conn *conn,
				void *buf, unsigned int buflen,
				u32 remote_key, u64 remote_offset,
				u32 remote_len)
{
	int ret = -EINVAL;

	if (conn->transport->ops->rdma_write)
		ret = conn->transport->ops->rdma_write(conn->transport,
						buf, buflen,
						remote_key, remote_offset,
						remote_len);
	return ret;
}

bool ksmbd_conn_alive(struct ksmbd_conn *conn)
{
	if (!ksmbd_server_running())
		return false;

	if (conn->status == KSMBD_SESS_EXITING)
		return false;

	if (kthread_should_stop())
		return false;

	if (atomic_read(&conn->stats.open_files_count) > 0)
		return true;

	/*
	 * Stop current session if the time that get last request from client
	 * is bigger than deadtime user configured and openning file count is
	 * zero.
	 */
	if (server_conf.deadtime > 0 &&
		time_after(jiffies, conn->last_active + server_conf.deadtime)) {
		ksmbd_debug(CONN, "No response from client in %lu minutes\n",
			server_conf.deadtime / SMB_ECHO_INTERVAL);
		return false;
	}
	return true;
}

/**
 * ksmbd_conn_handler_loop() - session thread to listen on new smb requests
 * @p:		connection instance
 *
 * One thread each per connection
 *
 * Return:	0 on success
 */
int ksmbd_conn_handler_loop(void *p)
{
	struct ksmbd_conn *conn = (struct ksmbd_conn *)p;
	struct ksmbd_transport *t = conn->transport;
	unsigned int pdu_size;
	char hdr_buf[4] = {0,};
	int size;

	mutex_init(&conn->srv_mutex);
	__module_get(THIS_MODULE);

	if (t->ops->prepare && t->ops->prepare(t))
		goto out;

	conn->last_active = jiffies;
	while (ksmbd_conn_alive(conn)) {
		if (try_to_freeze())
			continue;

		ksmbd_free_request(conn->request_buf);
		conn->request_buf = NULL;

		size = t->ops->read(t, hdr_buf, sizeof(hdr_buf));
		if (size != sizeof(hdr_buf))
			break;

		pdu_size = get_rfc1002_len(hdr_buf);
		ksmbd_debug(CONN, "RFC1002 header %u bytes\n", pdu_size);

		/* make sure we have enough to get to SMB header end */
		if (!ksmbd_pdu_size_has_room(pdu_size)) {
			ksmbd_debug(CONN, "SMB request too short (%u bytes)\n",
				    pdu_size);
			continue;
		}

		/* 4 for rfc1002 length field */
		size = pdu_size + 4;
		conn->request_buf = ksmbd_alloc_request(size);
		if (!conn->request_buf)
			continue;

		memcpy(conn->request_buf, hdr_buf, sizeof(hdr_buf));
		if (!ksmbd_smb_request(conn))
			break;

		/*
		 * We already read 4 bytes to find out PDU size, now
		 * read in PDU
		 */
		size = t->ops->read(t, conn->request_buf + 4, pdu_size);
		if (size < 0) {
			ksmbd_err("sock_read failed: %d\n", size);
			break;
		}

		if (size != pdu_size) {
			ksmbd_err("PDU error. Read: %d, Expected: %d\n",
				  size,
				  pdu_size);
			continue;
		}

		if (!default_conn_ops.process_fn) {
			ksmbd_err("No connection request callback\n");
			break;
		}

		if (default_conn_ops.process_fn(conn)) {
			ksmbd_err("Cannot handle request\n");
			break;
		}
	}

out:
	/* Wait till all reference dropped to the Server object*/
	while (atomic_read(&conn->r_count) > 0)
		schedule_timeout(HZ);

	unload_nls(conn->local_nls);
	if (default_conn_ops.terminate_fn)
		default_conn_ops.terminate_fn(conn);
	t->ops->disconnect(t);
	module_put(THIS_MODULE);
	return 0;
}

void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops)
{
	default_conn_ops.process_fn = ops->process_fn;
	default_conn_ops.terminate_fn = ops->terminate_fn;
}

int ksmbd_conn_transport_init(void)
{
	int ret;

	mutex_lock(&init_lock);
	ret = ksmbd_tcp_init();
	if (ret) {
		pr_err("Failed to init TCP subsystem: %d\n", ret);
		goto out;
	}

	ret = ksmbd_rdma_init();
	if (ret) {
		pr_err("Failed to init KSMBD subsystem: %d\n", ret);
		goto out;
	}
out:
	mutex_unlock(&init_lock);
	return ret;
}

static void stop_sessions(void)
{
	struct ksmbd_conn *conn;

again:
	read_lock(&conn_list_lock);
	list_for_each_entry(conn, &conn_list, conns_list) {
		struct task_struct *task;

		task = conn->transport->handler;
		if (task)
			ksmbd_debug(CONN, "Stop session handler %s/%d\n",
				  task->comm,
				  task_pid_nr(task));
		conn->status = KSMBD_SESS_EXITING;
	}
	read_unlock(&conn_list_lock);

	if (!list_empty(&conn_list)) {
		schedule_timeout_interruptible(HZ/10); /* 100ms */
		goto again;
	}
}

void ksmbd_conn_transport_destroy(void)
{
	mutex_lock(&init_lock);
	ksmbd_tcp_destroy();
	ksmbd_rdma_destroy();
	stop_sessions();
	mutex_unlock(&init_lock);
}

fs/cifsd/connection.h

0 → 100644
+212 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 */

#ifndef __KSMBD_CONNECTION_H__
#define __KSMBD_CONNECTION_H__

#include <linux/list.h>
#include <linux/ip.h>
#include <net/sock.h>
#include <net/tcp.h>
#include <net/inet_connection_sock.h>
#include <net/request_sock.h>
#include <linux/kthread.h>
#include <linux/nls.h>

#include "smb_common.h"
#include "ksmbd_work.h"

#define KSMBD_SOCKET_BACKLOG		16

/*
 * WARNING
 *
 * This is nothing but a HACK. Session status should move to channel
 * or to session. As of now we have 1 tcp_conn : 1 ksmbd_session, but
 * we need to change it to 1 tcp_conn : N ksmbd_sessions.
 */
enum {
	KSMBD_SESS_NEW = 0,
	KSMBD_SESS_GOOD,
	KSMBD_SESS_EXITING,
	KSMBD_SESS_NEED_RECONNECT,
	KSMBD_SESS_NEED_NEGOTIATE
};

struct ksmbd_stats {
	atomic_t			open_files_count;
	atomic64_t			request_served;
};

struct ksmbd_transport;

struct ksmbd_conn {
	struct smb_version_values	*vals;
	struct smb_version_ops		*ops;
	struct smb_version_cmds		*cmds;
	unsigned int			max_cmds;
	struct mutex			srv_mutex;
	int				status;
	unsigned int			cli_cap;
	char				*request_buf;
	struct ksmbd_transport		*transport;
	struct nls_table		*local_nls;
	struct list_head		conns_list;
	/* smb session 1 per user */
	struct list_head		sessions;
	unsigned long			last_active;
	/* How many request are running currently */
	atomic_t			req_running;
	/* References which are made for this Server object*/
	atomic_t			r_count;
	unsigned short			total_credits;
	unsigned short			max_credits;
	spinlock_t			credits_lock;
	wait_queue_head_t		req_running_q;
	/* Lock to protect requests list*/
	spinlock_t			request_lock;
	struct list_head		requests;
	struct list_head		async_requests;
	int				connection_type;
	struct ksmbd_stats		stats;
	char				ClientGUID[SMB2_CLIENT_GUID_SIZE];
	union {
		/* pending trans request table */
		struct trans_state	*recent_trans;
		/* Used by ntlmssp */
		char			*ntlmssp_cryptkey;
	};

	struct preauth_integrity_info	*preauth_info;

	bool				need_neg;
	unsigned int			auth_mechs;
	unsigned int			preferred_auth_mech;
	bool				sign;
	bool				use_spnego:1;
	__u16				cli_sec_mode;
	__u16				srv_sec_mode;
	/* dialect index that server chose */
	__u16				dialect;

	char				*mechToken;

	struct ksmbd_conn_ops	*conn_ops;

	/* Preauth Session Table */
	struct list_head		preauth_sess_table;

	struct sockaddr_storage		peer_addr;

	/* Identifier for async message */
	struct ksmbd_ida		*async_ida;

	__le16				cipher_type;
	__le16				compress_algorithm;
	bool				posix_ext_supported;
};

struct ksmbd_conn_ops {
	int	(*process_fn)(struct ksmbd_conn *conn);
	int	(*terminate_fn)(struct ksmbd_conn *conn);
};

struct ksmbd_transport_ops {
	int (*prepare)(struct ksmbd_transport *t);
	void (*disconnect)(struct ksmbd_transport *t);
	int (*read)(struct ksmbd_transport *t,
			char *buf, unsigned int size);
	int (*writev)(struct ksmbd_transport *t,
			struct kvec *iovs, int niov, int size,
			bool need_invalidate_rkey, unsigned int remote_key);
	int (*rdma_read)(struct ksmbd_transport *t,
				void *buf, unsigned int len, u32 remote_key,
				u64 remote_offset, u32 remote_len);
	int (*rdma_write)(struct ksmbd_transport *t,
				void *buf, unsigned int len, u32 remote_key,
				u64 remote_offset, u32 remote_len);
};

struct ksmbd_transport {
	struct ksmbd_conn		*conn;
	struct ksmbd_transport_ops	*ops;
	struct task_struct		*handler;
};

#define KSMBD_TCP_RECV_TIMEOUT	(7 * HZ)
#define KSMBD_TCP_SEND_TIMEOUT	(5 * HZ)
#define KSMBD_TCP_PEER_SOCKADDR(c)	((struct sockaddr *)&((c)->peer_addr))

bool ksmbd_conn_alive(struct ksmbd_conn *conn);
void ksmbd_conn_wait_idle(struct ksmbd_conn *conn);

struct ksmbd_conn *ksmbd_conn_alloc(void);
void ksmbd_conn_free(struct ksmbd_conn *conn);
bool ksmbd_conn_lookup_dialect(struct ksmbd_conn *c);
int ksmbd_conn_write(struct ksmbd_work *work);
int ksmbd_conn_rdma_read(struct ksmbd_conn *conn,
				void *buf, unsigned int buflen,
				u32 remote_key, u64 remote_offset,
				u32 remote_len);
int ksmbd_conn_rdma_write(struct ksmbd_conn *conn,
				void *buf, unsigned int buflen,
				u32 remote_key, u64 remote_offset,
				u32 remote_len);

void ksmbd_conn_enqueue_request(struct ksmbd_work *work);
int ksmbd_conn_try_dequeue_request(struct ksmbd_work *work);
void ksmbd_conn_init_server_callbacks(struct ksmbd_conn_ops *ops);

int ksmbd_conn_handler_loop(void *p);

int ksmbd_conn_transport_init(void);
void ksmbd_conn_transport_destroy(void);

/*
 * WARNING
 *
 * This is a hack. We will move status to a proper place once we land
 * a multi-sessions support.
 */
static inline bool ksmbd_conn_good(struct ksmbd_work *work)
{
	return work->conn->status == KSMBD_SESS_GOOD;
}

static inline bool ksmbd_conn_need_negotiate(struct ksmbd_work *work)
{
	return work->conn->status == KSMBD_SESS_NEED_NEGOTIATE;
}

static inline bool ksmbd_conn_need_reconnect(struct ksmbd_work *work)
{
	return work->conn->status == KSMBD_SESS_NEED_RECONNECT;
}

static inline bool ksmbd_conn_exiting(struct ksmbd_work *work)
{
	return work->conn->status == KSMBD_SESS_EXITING;
}

static inline void ksmbd_conn_set_good(struct ksmbd_work *work)
{
	work->conn->status = KSMBD_SESS_GOOD;
}

static inline void ksmbd_conn_set_need_negotiate(struct ksmbd_work *work)
{
	work->conn->status = KSMBD_SESS_NEED_NEGOTIATE;
}

static inline void ksmbd_conn_set_need_reconnect(struct ksmbd_work *work)
{
	work->conn->status = KSMBD_SESS_NEED_RECONNECT;
}

static inline void ksmbd_conn_set_exiting(struct ksmbd_work *work)
{
	work->conn->status = KSMBD_SESS_EXITING;
}
#endif /* __CONNECTION_H__ */

fs/cifsd/glob.h

0 → 100644
+67 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 *   Copyright (C) 2016 Namjae Jeon <linkinjeon@kernel.org>
 *   Copyright (C) 2018 Samsung Electronics Co., Ltd.
 */

#ifndef __KSMBD_GLOB_H
#define __KSMBD_GLOB_H

#include <linux/ctype.h>
#include <linux/version.h>

#include "unicode.h"
#include "vfs_cache.h"
#include "smberr.h"

#define KSMBD_VERSION	"3.1.9"

/* @FIXME clean up this code */

extern int ksmbd_debug_types;
extern int ksmbd_caseless_search;

#define DATA_STREAM	1
#define DIR_STREAM	2

#define KSMBD_DEBUG_SMB         (1 << 0)
#define KSMBD_DEBUG_AUTH        (1 << 1)
#define KSMBD_DEBUG_VFS         (1 << 2)
#define KSMBD_DEBUG_OPLOCK      (1 << 3)
#define KSMBD_DEBUG_IPC         (1 << 4)
#define KSMBD_DEBUG_CONN        (1 << 5)
#define KSMBD_DEBUG_RDMA        (1 << 6)
#define KSMBD_DEBUG_ALL         (KSMBD_DEBUG_SMB | KSMBD_DEBUG_AUTH |	\
				KSMBD_DEBUG_VFS | KSMBD_DEBUG_OPLOCK |	\
				KSMBD_DEBUG_IPC | KSMBD_DEBUG_CONN |	\
				KSMBD_DEBUG_RDMA)

#ifndef ksmbd_pr_fmt
#ifdef SUBMOD_NAME
#define ksmbd_pr_fmt(fmt)	"ksmbd: " SUBMOD_NAME ": " fmt
#else
#define ksmbd_pr_fmt(fmt)	"ksmbd: " fmt
#endif
#endif

#define ksmbd_debug(type, fmt, ...)				\
	do {							\
		if (ksmbd_debug_types & KSMBD_DEBUG_##type)	\
			pr_info(ksmbd_pr_fmt("%s:%d: " fmt),	\
				__func__,			\
				__LINE__,			\
				##__VA_ARGS__);			\
	} while (0)

#define ksmbd_info(fmt, ...)					\
			pr_info(ksmbd_pr_fmt(fmt), ##__VA_ARGS__)

#define ksmbd_err(fmt, ...)					\
			pr_err(ksmbd_pr_fmt("%s:%d: " fmt),	\
				__func__,			\
				__LINE__,			\
				##__VA_ARGS__)

#define UNICODE_LEN(x)		((x) * 2)

#endif /* __KSMBD_GLOB_H */
+285 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading