Skip to content

Commit

Permalink
Create a dynamically sized pool of threads for doing very slow work i…
Browse files Browse the repository at this point in the history
…tems

Create a dynamically sized pool of threads for doing very slow work items, such
as invoking mkdir() or rmdir() - things that may take a long time and may
sleep, holding mutexes/semaphores and hogging a thread, and are thus unsuitable
for workqueues.

The number of threads is always at least a settable minimum, but more are
started when there's more work to do, up to a limit.  Because of the nature of
the load, it's not suitable for a 1-thread-per-CPU type pool.  A system with
one CPU may well want several threads.

This is used by FS-Cache to do slow caching operations in the background, such
as looking up, creating or deleting cache objects.

Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Acked-by: Steve Dickson <steved@redhat.com>
Acked-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Acked-by: Al Viro <viro@zeniv.linux.org.uk>
Tested-by: Daire Byrne <Daire.Byrne@framestore.com>
  • Loading branch information
dhowells committed Apr 3, 2009
1 parent 8fe74cf commit 07fe7cb
Show file tree
Hide file tree
Showing 4 changed files with 489 additions and 0 deletions.
88 changes: 88 additions & 0 deletions include/linux/slow-work.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/* Worker thread pool for slow items, such as filesystem lookups or mkdirs
*
* Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*/

#ifndef _LINUX_SLOW_WORK_H
#define _LINUX_SLOW_WORK_H

#ifdef CONFIG_SLOW_WORK

struct slow_work;

/*
* The operations used to support slow work items
*/
struct slow_work_ops {
/* get a ref on a work item
* - return 0 if successful, -ve if not
*/
int (*get_ref)(struct slow_work *work);

/* discard a ref to a work item */
void (*put_ref)(struct slow_work *work);

/* execute a work item */
void (*execute)(struct slow_work *work);
};

/*
* A slow work item
* - A reference is held on the parent object by the thread pool when it is
* queued
*/
struct slow_work {
unsigned long flags;
#define SLOW_WORK_PENDING 0 /* item pending (further) execution */
#define SLOW_WORK_EXECUTING 1 /* item currently executing */
#define SLOW_WORK_ENQ_DEFERRED 2 /* item enqueue deferred */
#define SLOW_WORK_VERY_SLOW 3 /* item is very slow */
const struct slow_work_ops *ops; /* operations table for this item */
struct list_head link; /* link in queue */
};

/**
* slow_work_init - Initialise a slow work item
* @work: The work item to initialise
* @ops: The operations to use to handle the slow work item
*
* Initialise a slow work item.
*/
static inline void slow_work_init(struct slow_work *work,
const struct slow_work_ops *ops)
{
work->flags = 0;
work->ops = ops;
INIT_LIST_HEAD(&work->link);
}

/**
* slow_work_init - Initialise a very slow work item
* @work: The work item to initialise
* @ops: The operations to use to handle the slow work item
*
* Initialise a very slow work item. This item will be restricted such that
* only a certain number of the pool threads will be able to execute items of
* this type.
*/
static inline void vslow_work_init(struct slow_work *work,
const struct slow_work_ops *ops)
{
work->flags = 1 << SLOW_WORK_VERY_SLOW;
work->ops = ops;
INIT_LIST_HEAD(&work->link);
}

extern int slow_work_enqueue(struct slow_work *work);
extern int slow_work_register_user(void);
extern void slow_work_unregister_user(void);


#endif /* CONFIG_SLOW_WORK */
#endif /* _LINUX_SLOW_WORK_H */
12 changes: 12 additions & 0 deletions init/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,18 @@ config MARKERS

source "arch/Kconfig"

config SLOW_WORK
default n
bool "Enable slow work thread pool"
help
The slow work thread pool provides a number of dynamically allocated
threads that can be used by the kernel to perform operations that
take a relatively long time.

An example of this would be CacheFiles doing a path lookup followed
by a series of mkdirs and a create call, all of which have to touch
disk.

endmenu # General setup

config HAVE_GENERIC_DMA_COHERENT
Expand Down
1 change: 1 addition & 0 deletions kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
obj-$(CONFIG_FUNCTION_TRACER) += trace/
obj-$(CONFIG_TRACING) += trace/
obj-$(CONFIG_SMP) += sched_cpupri.o
obj-$(CONFIG_SLOW_WORK) += slow-work.o

ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y)
# According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
Expand Down
Loading

0 comments on commit 07fe7cb

Please sign in to comment.