Commit c30f4eb8 authored by Namjae Jeon's avatar Namjae Jeon
Browse files

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: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarNamjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent f5a544e3
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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

+0 −1
Original line number Diff line number Diff line
@@ -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

fs/cifsd/buffer_pool.c

deleted100644 → 0
+0 −265
Original line number Diff line number Diff line
// 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;
}

fs/cifsd/buffer_pool.h

deleted100644 → 0
+0 −17
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_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__ */
+0 −1
Original line number Diff line number Diff line
@@ -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"
Loading