#
obj-$(CONFIG_SMB_SERVER) += ksmbd.o
-ksmbd-y := unicode.o auth.o vfs.o vfs_cache.o server.o buffer_pool.o \
+ksmbd-y := unicode.o auth.o vfs.o vfs_cache.o server.o ndr.o \
misc.o oplock.o connection.o ksmbd_work.o crypto_ctx.o \
mgmt/ksmbd_ida.o mgmt/user_config.o mgmt/share_config.o \
mgmt/tree_connect.o mgmt/user_session.o smb_common.o \
transport_tcp.o transport_ipc.o smbacl.o smb2pdu.o \
smb2ops.o smb2misc.o ksmbd_spnego_negtokeninit.asn1.o \
- ksmbd_spnego_negtokentarg.asn1.o asn1.o ndr.o
+ ksmbd_spnego_negtokentarg.asn1.o asn1.o
$(obj)/asn1.o: $(obj)/ksmbd_spnego_negtokeninit.asn1.h $(obj)/ksmbd_spnego_negtokentarg.asn1.h
#include "mgmt/user_config.h"
#include "crypto_ctx.h"
#include "transport_ipc.h"
-#include "buffer_pool.h"
/*
* Fixed format data defining GSS header and fixed string
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#include <linux/kernel.h>
-#include <linux/wait.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/rwlock.h>
-
-#include "glob.h"
-#include "buffer_pool.h"
-#include "connection.h"
-#include "mgmt/ksmbd_ida.h"
-
-static struct kmem_cache *filp_cache;
-
-struct wm {
- struct list_head list;
- unsigned int sz;
- char buffer[0];
-};
-
-struct wm_list {
- struct list_head list;
- unsigned int sz;
-
- spinlock_t wm_lock;
- int avail_wm;
- struct list_head idle_wm;
- wait_queue_head_t wm_wait;
-};
-
-static LIST_HEAD(wm_lists);
-static DEFINE_RWLOCK(wm_lists_lock);
-
-static struct wm *wm_alloc(size_t sz, gfp_t flags)
-{
- struct wm *wm;
- size_t alloc_sz = sz + sizeof(struct wm);
-
- if (sz > SIZE_MAX - sizeof(struct wm))
- return NULL;
-
- wm = kvmalloc(alloc_sz, flags);
- if (!wm)
- return NULL;
- wm->sz = sz;
- return wm;
-}
-
-static int register_wm_size_class(size_t sz)
-{
- struct wm_list *l, *nl;
-
- nl = kmalloc(sizeof(struct wm_list), GFP_KERNEL);
- if (!nl)
- return -ENOMEM;
-
- nl->sz = sz;
- spin_lock_init(&nl->wm_lock);
- INIT_LIST_HEAD(&nl->idle_wm);
- INIT_LIST_HEAD(&nl->list);
- init_waitqueue_head(&nl->wm_wait);
- nl->avail_wm = 0;
-
- write_lock(&wm_lists_lock);
- list_for_each_entry(l, &wm_lists, list) {
- if (l->sz == sz) {
- write_unlock(&wm_lists_lock);
- kfree(nl);
- return 0;
- }
- }
-
- list_add(&nl->list, &wm_lists);
- write_unlock(&wm_lists_lock);
- return 0;
-}
-
-static struct wm_list *match_wm_list(size_t size)
-{
- struct wm_list *l, *rl = NULL;
-
- read_lock(&wm_lists_lock);
- list_for_each_entry(l, &wm_lists, list) {
- if (l->sz == size) {
- rl = l;
- break;
- }
- }
- read_unlock(&wm_lists_lock);
- return rl;
-}
-
-static struct wm *find_wm(size_t size)
-{
- struct wm_list *wm_list;
- struct wm *wm;
-
- wm_list = match_wm_list(size);
- if (!wm_list) {
- if (register_wm_size_class(size))
- return NULL;
- wm_list = match_wm_list(size);
- }
-
- if (!wm_list)
- return NULL;
-
- while (1) {
- spin_lock(&wm_list->wm_lock);
- if (!list_empty(&wm_list->idle_wm)) {
- wm = list_entry(wm_list->idle_wm.next,
- struct wm,
- list);
- list_del(&wm->list);
- spin_unlock(&wm_list->wm_lock);
- return wm;
- }
-
- if (wm_list->avail_wm > num_online_cpus()) {
- spin_unlock(&wm_list->wm_lock);
- wait_event(wm_list->wm_wait,
- !list_empty(&wm_list->idle_wm));
- continue;
- }
-
- wm_list->avail_wm++;
- spin_unlock(&wm_list->wm_lock);
-
- wm = wm_alloc(size, GFP_KERNEL);
- if (!wm) {
- spin_lock(&wm_list->wm_lock);
- wm_list->avail_wm--;
- spin_unlock(&wm_list->wm_lock);
- wait_event(wm_list->wm_wait,
- !list_empty(&wm_list->idle_wm));
- continue;
- }
- break;
- }
-
- return wm;
-}
-
-static void release_wm(struct wm *wm, struct wm_list *wm_list)
-{
- if (!wm)
- return;
-
- spin_lock(&wm_list->wm_lock);
- if (wm_list->avail_wm <= num_online_cpus()) {
- list_add(&wm->list, &wm_list->idle_wm);
- spin_unlock(&wm_list->wm_lock);
- wake_up(&wm_list->wm_wait);
- return;
- }
-
- wm_list->avail_wm--;
- spin_unlock(&wm_list->wm_lock);
- kvfree(wm);
-}
-
-static void wm_list_free(struct wm_list *l)
-{
- struct wm *wm;
-
- while (!list_empty(&l->idle_wm)) {
- wm = list_entry(l->idle_wm.next, struct wm, list);
- list_del(&wm->list);
- kvfree(wm);
- }
- kfree(l);
-}
-
-static void wm_lists_destroy(void)
-{
- struct wm_list *l;
-
- while (!list_empty(&wm_lists)) {
- l = list_entry(wm_lists.next, struct wm_list, list);
- list_del(&l->list);
- wm_list_free(l);
- }
-}
-
-void *ksmbd_find_buffer(size_t size)
-{
- struct wm *wm;
-
- wm = find_wm(size);
-
- WARN_ON(!wm);
- if (wm)
- return wm->buffer;
- return NULL;
-}
-
-void ksmbd_release_buffer(void *buffer)
-{
- struct wm_list *wm_list;
- struct wm *wm;
-
- if (!buffer)
- return;
-
- wm = container_of(buffer, struct wm, buffer);
- wm_list = match_wm_list(wm->sz);
- WARN_ON(!wm_list);
- if (wm_list)
- release_wm(wm, wm_list);
-}
-
-void *ksmbd_realloc_response(void *ptr, size_t old_sz, size_t new_sz)
-{
- size_t sz = min(old_sz, new_sz);
- void *nptr;
-
- nptr = kvmalloc(new_sz, GFP_KERNEL | __GFP_ZERO);
- if (!nptr)
- return ptr;
- memcpy(nptr, ptr, sz);
- kvfree(ptr);
- return nptr;
-}
-
-void ksmbd_free_file_struct(void *filp)
-{
- kmem_cache_free(filp_cache, filp);
-}
-
-void *ksmbd_alloc_file_struct(void)
-{
- return kmem_cache_zalloc(filp_cache, GFP_KERNEL);
-}
-
-void ksmbd_destroy_buffer_pools(void)
-{
- wm_lists_destroy();
- ksmbd_work_pool_destroy();
- kmem_cache_destroy(filp_cache);
-}
-
-int ksmbd_init_buffer_pools(void)
-{
- if (ksmbd_work_pool_init())
- goto out;
-
- filp_cache = kmem_cache_create("ksmbd_file_cache",
- sizeof(struct ksmbd_file), 0,
- SLAB_HWCACHE_ALIGN, NULL);
- if (!filp_cache)
- goto out;
-
- return 0;
-
-out:
- ksmbd_err("failed to allocate memory\n");
- ksmbd_destroy_buffer_pools();
- return -ENOMEM;
-}
+++ /dev/null
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2018 Samsung Electronics Co., Ltd.
- */
-
-#ifndef __KSMBD_BUFFER_POOL_H__
-#define __KSMBD_BUFFER_POOL_H__
-
-void *ksmbd_find_buffer(size_t size);
-void ksmbd_release_buffer(void *buffer);
-void *ksmbd_realloc_response(void *ptr, size_t old_sz, size_t new_sz);
-void ksmbd_free_file_struct(void *filp);
-void *ksmbd_alloc_file_struct(void);
-void ksmbd_destroy_buffer_pools(void);
-int ksmbd_init_buffer_pools(void);
-
-#endif /* __KSMBD_BUFFER_POOL_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 "glob.h"
#include "crypto_ctx.h"
-#include "buffer_pool.h"
struct crypto_ctx_list {
spinlock_t ctx_lock;
*/
#define KSMBD_GLOBAL_FLAG_INVALID (0)
#define KSMBD_GLOBAL_FLAG_SMB2_LEASES BIT(0)
-#define KSMBD_GLOBAL_FLAG_CACHE_TBUF BIT(1)
-#define KSMBD_GLOBAL_FLAG_CACHE_RBUF BIT(2)
-#define KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION BIT(3)
-#define KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL BIT(4)
+#define KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION BIT(1)
+#define KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL BIT(2)
struct ksmbd_startup_request {
__u32 flags;
#include "server.h"
#include "connection.h"
#include "ksmbd_work.h"
-#include "buffer_pool.h"
#include "mgmt/ksmbd_ida.h"
/* @FIXME */
void ksmbd_free_work_struct(struct ksmbd_work *work)
{
WARN_ON(work->saved_cred != NULL);
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_CACHE_TBUF &&
- work->set_trans_buf)
- ksmbd_release_buffer(work->response_buf);
- else
- kvfree(work->response_buf);
-
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_CACHE_RBUF &&
- work->set_read_buf)
- ksmbd_release_buffer(work->aux_payload_buf);
- else
- kvfree(work->aux_payload_buf);
+ kvfree(work->response_buf);
+ kvfree(work->aux_payload_buf);
kfree(work->tr_buf);
kvfree(work->request_buf);
if (work->async_id)
/* Is this SYNC or ASYNC ksmbd_work */
bool syncronous:1;
bool need_invalidate_rkey:1;
- bool set_trans_buf:1;
- bool set_read_buf:1;
unsigned int remote_key;
/* cancel works */
#include "share_config.h"
#include "user_config.h"
#include "user_session.h"
-#include "../buffer_pool.h"
#include "../transport_ipc.h"
#define SHARE_HASH_BITS 3
#include <linux/slab.h>
#include <linux/xarray.h>
-#include "../buffer_pool.h"
#include "../transport_ipc.h"
#include "../connection.h"
#include <linux/mm.h>
#include "user_config.h"
-#include "../buffer_pool.h"
#include "../transport_ipc.h"
struct ksmbd_user *ksmbd_login_user(const char *account)
#include "tree_connect.h"
#include "../transport_ipc.h"
#include "../connection.h"
-#include "../buffer_pool.h"
#include "../vfs_cache.h"
static DEFINE_IDA(session_ida);
#include "smb_common.h"
#include "smbstatus.h"
-#include "buffer_pool.h"
#include "connection.h"
#include "mgmt/user_session.h"
#include "mgmt/share_config.h"
#include "server.h"
#include "smb_common.h"
#include "smbstatus.h"
-#include "buffer_pool.h"
#include "connection.h"
#include "transport_ipc.h"
#include "mgmt/user_session.h"
ksmbd_crypto_destroy();
ksmbd_free_global_file_table();
destroy_lease_table(NULL);
- ksmbd_destroy_buffer_pools();
+ ksmbd_work_pool_destroy();
+ ksmbd_exit_file_cache();
server_conf_free();
return 0;
}
if (ret)
goto err_unregister;
- ret = ksmbd_init_buffer_pools();
+ ret = ksmbd_work_pool_init();
if (ret)
goto err_unregister;
+ ret = ksmbd_init_file_cache();
+ if (ret)
+ goto err_destroy_work_pools;
+
ret = ksmbd_ipc_init();
if (ret)
- goto err_free_session_table;
+ goto err_exit_file_cache;
ret = ksmbd_init_global_file_table();
if (ret)
ksmbd_free_global_file_table();
err_ipc_release:
ksmbd_ipc_release();
-err_free_session_table:
- ksmbd_destroy_buffer_pools();
+err_exit_file_cache:
+ ksmbd_exit_file_cache();
+err_destroy_work_pools:
+ ksmbd_work_pool_destroy();
err_unregister:
class_unregister(&ksmbd_control_class);
#include "auth.h"
#include "asn1.h"
-#include "buffer_pool.h"
#include "connection.h"
#include "transport_ipc.h"
#include "vfs.h"
size_t sz = small_sz;
int cmd = le16_to_cpu(hdr->Command);
- if (cmd == SMB2_IOCTL_HE || cmd == SMB2_QUERY_DIRECTORY_HE) {
+ if (cmd == SMB2_IOCTL_HE || cmd == SMB2_QUERY_DIRECTORY_HE)
sz = large_sz;
- work->set_trans_buf = true;
- }
if (cmd == SMB2_QUERY_INFO_HE) {
struct smb2_query_info_req *req;
req = work->request_buf;
if (req->InfoType == SMB2_O_INFO_FILE &&
(req->FileInfoClass == FILE_FULL_EA_INFORMATION ||
- req->FileInfoClass == FILE_ALL_INFORMATION)) {
+ req->FileInfoClass == FILE_ALL_INFORMATION))
sz = large_sz;
- work->set_trans_buf = true;
- }
}
/* allocate large response buf for chained commands */
if (le32_to_cpu(hdr->NextCommand) > 0)
sz = large_sz;
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_CACHE_TBUF &&
- work->set_trans_buf)
- work->response_buf = ksmbd_find_buffer(sz);
- else
- work->response_buf = kvmalloc(sz, GFP_KERNEL | __GFP_ZERO);
-
+ work->response_buf = kvmalloc(sz, GFP_KERNEL | __GFP_ZERO);
if (!work->response_buf)
return -ENOMEM;
ksmbd_debug(SMB, "filename %s, offset %lld, len %zu\n", FP_FILENAME(fp),
offset, length);
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_CACHE_RBUF) {
- work->aux_payload_buf =
- ksmbd_find_buffer(conn->vals->max_read_size);
- work->set_read_buf = true;
- } else {
- work->aux_payload_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO);
- }
+ work->aux_payload_buf = kvmalloc(length, GFP_KERNEL | __GFP_ZERO);
if (!work->aux_payload_buf) {
err = -ENOMEM;
goto out;
}
if ((nbytes == 0 && length != 0) || nbytes < mincount) {
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_CACHE_RBUF)
- ksmbd_release_buffer(work->aux_payload_buf);
- else
- kvfree(work->aux_payload_buf);
+ kvfree(work->aux_payload_buf);
work->aux_payload_buf = NULL;
rsp->hdr.Status = STATUS_END_OF_FILE;
smb2_set_err_rsp(work);
remain_bytes = smb2_read_rdma_channel(work, req,
work->aux_payload_buf,
nbytes);
- if (server_conf.flags & KSMBD_GLOBAL_FLAG_CACHE_RBUF)
- ksmbd_release_buffer(work->aux_payload_buf);
- else
- kvfree(work->aux_payload_buf);
+ kvfree(work->aux_payload_buf);
work->aux_payload_buf = NULL;
nbytes = 0;
#include "vfs_cache.h"
#include "transport_ipc.h"
-#include "buffer_pool.h"
#include "server.h"
#include "smb_common.h"
#include "connection.h"
#include "smb_common.h"
#include "smbstatus.h"
-#include "buffer_pool.h"
#include "transport_rdma.h"
#define SMB_DIRECT_PORT 5445
#include "smb_common.h"
#include "server.h"
#include "auth.h"
-#include "buffer_pool.h"
#include "connection.h"
#include "transport_tcp.h"
#include "glob.h"
#include "oplock.h"
#include "connection.h"
-#include "buffer_pool.h"
#include "vfs.h"
#include "vfs_cache.h"
#include "smbacl.h"
#include "glob.h"
#include "vfs_cache.h"
-#include "buffer_pool.h"
#include "oplock.h"
#include "vfs.h"
#include "connection.h"
static struct ksmbd_file_table global_ft;
static atomic_long_t fd_limit;
+static struct kmem_cache *filp_cache;
void ksmbd_set_fd_limit(unsigned long limit)
{
kfree(fp->filename);
if (ksmbd_stream_fd(fp))
kfree(fp->stream.name);
- ksmbd_free_file_struct(fp);
+ kmem_cache_free(filp_cache, fp);
}
static struct ksmbd_file *ksmbd_fp_get(struct ksmbd_file *fp)
struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp)
{
- struct ksmbd_file *fp;
+ struct ksmbd_file *fp;
int ret;
- fp = ksmbd_alloc_file_struct();
+ fp = kmem_cache_zalloc(filp_cache, GFP_KERNEL);
if (!fp) {
ksmbd_err("Failed to allocate memory\n");
return ERR_PTR(-ENOMEM);
fp->f_ci = ksmbd_inode_get(fp);
if (!fp->f_ci) {
- ksmbd_free_file_struct(fp);
+ kmem_cache_free(filp_cache, fp);
return ERR_PTR(-ENOMEM);
}
ret = __open_id(&work->sess->file_table, fp, OPEN_ID_TYPE_VOLATILE_ID);
if (ret) {
ksmbd_inode_put(fp->f_ci);
- ksmbd_free_file_struct(fp);
+ kmem_cache_free(filp_cache, fp);
return ERR_PTR(ret);
}
idr_for_each_entry(global_ft.idr, fp, id) {
__ksmbd_remove_durable_fd(fp);
- ksmbd_free_file_struct(fp);
+ kmem_cache_free(filp_cache, fp);
}
ksmbd_destroy_file_table(&global_ft);
kfree(ft->idr);
ft->idr = NULL;
}
+
+int ksmbd_init_file_cache(void)
+{
+ filp_cache = kmem_cache_create("ksmbd_file_cache",
+ sizeof(struct ksmbd_file), 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+ if (!filp_cache)
+ goto out;
+
+ return 0;
+
+out:
+ ksmbd_err("failed to allocate file cache\n");
+ return -ENOMEM;
+}
+
+void ksmbd_exit_file_cache(void)
+{
+ kmem_cache_destroy(filp_cache);
+}
void ksmbd_clear_inode_pending_delete(struct ksmbd_file *fp);
void ksmbd_fd_set_delete_on_close(struct ksmbd_file *fp,
int file_info);
+int ksmbd_init_file_cache(void);
+void ksmbd_exit_file_cache(void);
#endif /* __VFS_CACHE_H__ */