ksmbd: remove cache read/trans buffer support

As vmalloc performance improvement patch for big allocation is merged into
linux kernel, This feature is no longer not needed.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
Namjae Jeon 2021-06-18 10:17:37 +09:00
parent f5a544e3ba
commit c30f4eb84b
22 changed files with 53 additions and 355 deletions

View File

@ -4,13 +4,13 @@
#
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

View File

@ -29,7 +29,6 @@
#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

View File

@ -1,265 +0,0 @@
// 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;
}

View File

@ -1,17 +0,0 @@
/* 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__ */

View File

@ -9,7 +9,6 @@
#include <linux/module.h>
#include "server.h"
#include "buffer_pool.h"
#include "smb_common.h"
#include "mgmt/ksmbd_ida.h"
#include "connection.h"

View File

@ -12,7 +12,6 @@
#include "glob.h"
#include "crypto_ctx.h"
#include "buffer_pool.h"
struct crypto_ctx_list {
spinlock_t ctx_lock;

View File

@ -30,10 +30,8 @@ struct ksmbd_heartbeat {
*/
#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;

View File

@ -11,7 +11,6 @@
#include "server.h"
#include "connection.h"
#include "ksmbd_work.h"
#include "buffer_pool.h"
#include "mgmt/ksmbd_ida.h"
/* @FIXME */
@ -38,18 +37,9 @@ struct ksmbd_work *ksmbd_alloc_work_struct(void)
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)

View File

@ -70,8 +70,6 @@ struct ksmbd_work {
/* 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 */

View File

@ -15,7 +15,6 @@
#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

View File

@ -7,7 +7,6 @@
#include <linux/slab.h>
#include <linux/xarray.h>
#include "../buffer_pool.h"
#include "../transport_ipc.h"
#include "../connection.h"

View File

@ -7,7 +7,6 @@
#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)

View File

@ -14,7 +14,6 @@
#include "tree_connect.h"
#include "../transport_ipc.h"
#include "../connection.h"
#include "../buffer_pool.h"
#include "../vfs_cache.h"
static DEFINE_IDA(session_ida);

View File

@ -11,7 +11,6 @@
#include "smb_common.h"
#include "smbstatus.h"
#include "buffer_pool.h"
#include "connection.h"
#include "mgmt/user_session.h"
#include "mgmt/share_config.h"

View File

@ -16,7 +16,6 @@
#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"
@ -536,7 +535,8 @@ static int ksmbd_server_shutdown(void)
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;
}
@ -557,13 +557,17 @@ static int __init ksmbd_server_init(void)
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)
@ -590,8 +594,10 @@ err_destroy_file_table:
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);

View File

@ -19,7 +19,6 @@
#include "auth.h"
#include "asn1.h"
#include "buffer_pool.h"
#include "connection.h"
#include "transport_ipc.h"
#include "vfs.h"
@ -538,10 +537,8 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
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;
@ -549,22 +546,15 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
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;
@ -5950,13 +5940,7 @@ int smb2_read(struct ksmbd_work *work)
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;
@ -5969,10 +5953,7 @@ int smb2_read(struct ksmbd_work *work)
}
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);
@ -5989,10 +5970,7 @@ int smb2_read(struct ksmbd_work *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;

View File

@ -16,7 +16,6 @@
#include "vfs_cache.h"
#include "transport_ipc.h"
#include "buffer_pool.h"
#include "server.h"
#include "smb_common.h"

View File

@ -33,7 +33,6 @@
#include "connection.h"
#include "smb_common.h"
#include "smbstatus.h"
#include "buffer_pool.h"
#include "transport_rdma.h"
#define SMB_DIRECT_PORT 5445

View File

@ -9,7 +9,6 @@
#include "smb_common.h"
#include "server.h"
#include "auth.h"
#include "buffer_pool.h"
#include "connection.h"
#include "transport_tcp.h"

View File

@ -23,7 +23,6 @@
#include "glob.h"
#include "oplock.h"
#include "connection.h"
#include "buffer_pool.h"
#include "vfs.h"
#include "vfs_cache.h"
#include "smbacl.h"

View File

@ -10,7 +10,6 @@
#include "glob.h"
#include "vfs_cache.h"
#include "buffer_pool.h"
#include "oplock.h"
#include "vfs.h"
#include "connection.h"
@ -29,6 +28,7 @@ static DEFINE_RWLOCK(inode_hash_lock);
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)
{
@ -315,7 +315,7 @@ static void __ksmbd_close_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp)
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)
@ -539,10 +539,10 @@ unsigned int ksmbd_open_durable_fd(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);
@ -561,14 +561,14 @@ struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp)
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);
}
@ -640,7 +640,7 @@ void ksmbd_free_global_file_table(void)
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);
@ -683,3 +683,23 @@ void ksmbd_destroy_file_table(struct ksmbd_file_table *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);
}

View File

@ -182,4 +182,6 @@ void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp);
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__ */