Skip to content

Commit

Permalink
fscache: convert object to use workqueue instead of slow-work
Browse files Browse the repository at this point in the history
Make fscache object state transition callbacks use workqueue instead
of slow-work.  New dedicated unbound CPU workqueue fscache_object_wq
is created.  get/put callbacks are renamed and modified to take
@object and called directly from the enqueue wrapper and the work
function.  While at it, make all open coded instances of get/put to
use fscache_get/put_object().

* Unbound workqueue is used.

* work_busy() output is printed instead of slow-work flags in object
  debugging outputs.  They mean basically the same thing bit-for-bit.

* sysctl fscache.object_max_active added to control concurrency.  The
  default value is nr_cpus clamped between 4 and
  WQ_UNBOUND_MAX_ACTIVE.

* slow_work_sleep_till_thread_needed() is replaced with fscache
  private implementation fscache_object_sleep_till_congested() which
  waits on fscache_object_wq congestion.

* debugfs support is dropped for now.  Tracing API based debug
  facility is planned to be added.

Signed-off-by: Tejun Heo <[email protected]>
Acked-by: David Howells <[email protected]>
  • Loading branch information
htejun committed Jul 22, 2010
1 parent e120153 commit 8b8edef
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 74 deletions.
10 changes: 5 additions & 5 deletions Documentation/filesystems/caching/fscache.txt
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,8 @@ This will look something like:
[root@andromeda ~]# head /proc/fs/fscache/objects
OBJECT PARENT STAT CHLDN OPS OOP IPR EX READS EM EV F S | NETFS_COOKIE_DEF TY FL NETFS_DATA OBJECT_KEY, AUX_DATA
======== ======== ==== ===== === === === == ===== == == = = | ================ == == ================ ================
17e4b 2 ACTV 0 0 0 0 0 0 7b 4 0 8 | NFS.fh DT 0 ffff88001dd82820 010006017edcf8bbc93b43298fdfbe71e50b57b13a172c0117f38472, e567634700000000000000000000000063f2404a000000000000000000000000c9030000000000000000000063f2404a
1693a 2 ACTV 0 0 0 0 0 0 7b 4 0 8 | NFS.fh DT 0 ffff88002db23380 010006017edcf8bbc93b43298fdfbe71e50b57b1e0162c01a2df0ea6, 420ebc4a000000000000000000000000420ebc4a0000000000000000000000000e1801000000000000000000420ebc4a
17e4b 2 ACTV 0 0 0 0 0 0 7b 4 0 0 | NFS.fh DT 0 ffff88001dd82820 010006017edcf8bbc93b43298fdfbe71e50b57b13a172c0117f38472, e567634700000000000000000000000063f2404a000000000000000000000000c9030000000000000000000063f2404a
1693a 2 ACTV 0 0 0 0 0 0 7b 4 0 0 | NFS.fh DT 0 ffff88002db23380 010006017edcf8bbc93b43298fdfbe71e50b57b1e0162c01a2df0ea6, 420ebc4a000000000000000000000000420ebc4a0000000000000000000000000e1801000000000000000000420ebc4a

where the first set of columns before the '|' describe the object:

Expand All @@ -362,7 +362,7 @@ where the first set of columns before the '|' describe the object:
EM Object's event mask
EV Events raised on this object
F Object flags
S Object slow-work work item flags
S Object work item busy state mask (1:pending 2:running)

and the second set of columns describe the object's cookie, if present:

Expand Down Expand Up @@ -395,8 +395,8 @@ and the following paired letters:
w Show objects that don't have pending writes
R Show objects that have outstanding reads
r Show objects that don't have outstanding reads
S Show objects that have slow work queued
s Show objects that don't have slow work queued
S Show objects that have work queued
s Show objects that don't have work queued

If neither side of a letter pair is given, then both are implied. For example:

Expand Down
13 changes: 6 additions & 7 deletions fs/cachefiles/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ void __cachefiles_printk_object(struct cachefiles_object *object,

printk(KERN_ERR "%sobject: OBJ%x\n",
prefix, object->fscache.debug_id);
printk(KERN_ERR "%sobjstate=%s fl=%lx swfl=%lx ev=%lx[%lx]\n",
printk(KERN_ERR "%sobjstate=%s fl=%lx wbusy=%x ev=%lx[%lx]\n",
prefix, fscache_object_states[object->fscache.state],
object->fscache.flags, object->fscache.work.flags,
object->fscache.flags, work_busy(&object->fscache.work),
object->fscache.events,
object->fscache.event_mask & FSCACHE_OBJECT_EVENTS_MASK);
printk(KERN_ERR "%sops=%u inp=%u exc=%u\n",
Expand Down Expand Up @@ -212,25 +212,24 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache,

/* if the object we're waiting for is queued for processing,
* then just put ourselves on the queue behind it */
if (slow_work_is_queued(&xobject->fscache.work)) {
if (work_pending(&xobject->fscache.work)) {
_debug("queue OBJ%x behind OBJ%x immediately",
object->fscache.debug_id,
xobject->fscache.debug_id);
goto requeue;
}

/* otherwise we sleep until either the object we're waiting for
* is done, or the slow-work facility wants the thread back to
* do other work */
* is done, or the fscache_object is congested */
wq = bit_waitqueue(&xobject->flags, CACHEFILES_OBJECT_ACTIVE);
init_wait(&wait);
requeue = false;
do {
prepare_to_wait(wq, &wait, TASK_UNINTERRUPTIBLE);
if (!test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags))
break;
requeue = slow_work_sleep_till_thread_needed(
&object->fscache.work, &timeout);

requeue = fscache_object_sleep_till_congested(&timeout);
} while (timeout > 0 && !requeue);
finish_wait(wq, &wait);

Expand Down
7 changes: 7 additions & 0 deletions fs/fscache/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ extern unsigned fscache_defer_lookup;
extern unsigned fscache_defer_create;
extern unsigned fscache_debug;
extern struct kobject *fscache_root;
extern struct workqueue_struct *fscache_object_wq;
DECLARE_PER_CPU(wait_queue_head_t, fscache_object_cong_wait);

static inline bool fscache_object_congested(void)
{
return workqueue_congested(WORK_CPU_UNBOUND, fscache_object_wq);
}

extern int fscache_wait_bit(void *);
extern int fscache_wait_bit_interruptible(void *);
Expand Down
76 changes: 76 additions & 0 deletions fs/fscache/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/sched.h>
#include <linux/completion.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
#include "internal.h"

MODULE_DESCRIPTION("FS Cache Manager");
Expand All @@ -40,22 +41,89 @@ MODULE_PARM_DESC(fscache_debug,
"FS-Cache debugging mask");

struct kobject *fscache_root;
struct workqueue_struct *fscache_object_wq;

DEFINE_PER_CPU(wait_queue_head_t, fscache_object_cong_wait);

/* these values serve as lower bounds, will be adjusted in fscache_init() */
static unsigned fscache_object_max_active = 4;

#ifdef CONFIG_SYSCTL
static struct ctl_table_header *fscache_sysctl_header;

static int fscache_max_active_sysctl(struct ctl_table *table, int write,
void __user *buffer,
size_t *lenp, loff_t *ppos)
{
struct workqueue_struct **wqp = table->extra1;
unsigned int *datap = table->data;
int ret;

ret = proc_dointvec(table, write, buffer, lenp, ppos);
if (ret == 0)
workqueue_set_max_active(*wqp, *datap);
return ret;
}

ctl_table fscache_sysctls[] = {
{
.procname = "object_max_active",
.data = &fscache_object_max_active,
.maxlen = sizeof(unsigned),
.mode = 0644,
.proc_handler = fscache_max_active_sysctl,
.extra1 = &fscache_object_wq,
},
{}
};

ctl_table fscache_sysctls_root[] = {
{
.procname = "fscache",
.mode = 0555,
.child = fscache_sysctls,
},
{}
};
#endif

/*
* initialise the fs caching module
*/
static int __init fscache_init(void)
{
unsigned int nr_cpus = num_possible_cpus();
unsigned int cpu;
int ret;

ret = slow_work_register_user(THIS_MODULE);
if (ret < 0)
goto error_slow_work;

fscache_object_max_active =
clamp_val(nr_cpus,
fscache_object_max_active, WQ_UNBOUND_MAX_ACTIVE);

ret = -ENOMEM;
fscache_object_wq = alloc_workqueue("fscache_object", WQ_UNBOUND,
fscache_object_max_active);
if (!fscache_object_wq)
goto error_object_wq;

for_each_possible_cpu(cpu)
init_waitqueue_head(&per_cpu(fscache_object_cong_wait, cpu));

ret = fscache_proc_init();
if (ret < 0)
goto error_proc;

#ifdef CONFIG_SYSCTL
ret = -ENOMEM;
fscache_sysctl_header = register_sysctl_table(fscache_sysctls_root);
if (!fscache_sysctl_header)
goto error_sysctl;
#endif

fscache_cookie_jar = kmem_cache_create("fscache_cookie_jar",
sizeof(struct fscache_cookie),
0,
Expand All @@ -78,8 +146,14 @@ static int __init fscache_init(void)
error_kobj:
kmem_cache_destroy(fscache_cookie_jar);
error_cookie_jar:
#ifdef CONFIG_SYSCTL
unregister_sysctl_table(fscache_sysctl_header);
error_sysctl:
#endif
fscache_proc_cleanup();
error_proc:
destroy_workqueue(fscache_object_wq);
error_object_wq:
slow_work_unregister_user(THIS_MODULE);
error_slow_work:
return ret;
Expand All @@ -96,7 +170,9 @@ static void __exit fscache_exit(void)

kobject_put(fscache_root);
kmem_cache_destroy(fscache_cookie_jar);
unregister_sysctl_table(fscache_sysctl_header);
fscache_proc_cleanup();
destroy_workqueue(fscache_object_wq);
slow_work_unregister_user(THIS_MODULE);
printk(KERN_NOTICE "FS-Cache: Unloaded\n");
}
Expand Down
11 changes: 5 additions & 6 deletions fs/fscache/object-list.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ struct fscache_objlist_data {
#define FSCACHE_OBJLIST_CONFIG_NOREADS 0x00000200 /* show objects without active reads */
#define FSCACHE_OBJLIST_CONFIG_EVENTS 0x00000400 /* show objects with events */
#define FSCACHE_OBJLIST_CONFIG_NOEVENTS 0x00000800 /* show objects without no events */
#define FSCACHE_OBJLIST_CONFIG_WORK 0x00001000 /* show objects with slow work */
#define FSCACHE_OBJLIST_CONFIG_NOWORK 0x00002000 /* show objects without slow work */
#define FSCACHE_OBJLIST_CONFIG_WORK 0x00001000 /* show objects with work */
#define FSCACHE_OBJLIST_CONFIG_NOWORK 0x00002000 /* show objects without work */

u8 buf[512]; /* key and aux data buffer */
};
Expand Down Expand Up @@ -231,12 +231,11 @@ static int fscache_objlist_show(struct seq_file *m, void *v)
READS, NOREADS);
FILTER(obj->events & obj->event_mask,
EVENTS, NOEVENTS);
FILTER(obj->work.flags & ~(1UL << SLOW_WORK_VERY_SLOW),
WORK, NOWORK);
FILTER(work_busy(&obj->work), WORK, NOWORK);
}

seq_printf(m,
"%8x %8x %s %5u %3u %3u %3u %2u %5u %2lx %2lx %1lx %1lx | ",
"%8x %8x %s %5u %3u %3u %3u %2u %5u %2lx %2lx %1lx %1x | ",
obj->debug_id,
obj->parent ? obj->parent->debug_id : -1,
fscache_object_states_short[obj->state],
Expand All @@ -249,7 +248,7 @@ static int fscache_objlist_show(struct seq_file *m, void *v)
obj->event_mask & FSCACHE_OBJECT_EVENTS_MASK,
obj->events,
obj->flags,
obj->work.flags);
work_busy(&obj->work));

no_cookie = true;
keylen = auxlen = 0;
Expand Down
Loading

0 comments on commit 8b8edef

Please sign in to comment.