1/* Worker thread pool for slow items, such as filesystem lookups or mkdirs 2 * 3 * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public Licence 8 * as published by the Free Software Foundation; either version 9 * 2 of the Licence, or (at your option) any later version. 10 * 11 * See Documentation/slow-work.txt 12 */ 13 14#ifndef _LINUX_SLOW_WORK_H 15#define _LINUX_SLOW_WORK_H 16 17#ifdef CONFIG_SLOW_WORK 18 19#include <linux/sysctl.h> 20#include <linux/timer.h> 21 22struct slow_work; 23#ifdef CONFIG_SLOW_WORK_DEBUG 24struct seq_file; 25#endif 26 27/* 28 * The operations used to support slow work items 29 */ 30struct slow_work_ops { 31 /* owner */ 32 struct module *owner; 33 34 /* get a ref on a work item 35 * - return 0 if successful, -ve if not 36 */ 37 int (*get_ref)(struct slow_work *work); 38 39 /* discard a ref to a work item */ 40 void (*put_ref)(struct slow_work *work); 41 42 /* execute a work item */ 43 void (*execute)(struct slow_work *work); 44 45#ifdef CONFIG_SLOW_WORK_DEBUG 46 /* describe a work item for debugfs */ 47 void (*desc)(struct slow_work *work, struct seq_file *m); 48#endif 49}; 50 51/* 52 * A slow work item 53 * - A reference is held on the parent object by the thread pool when it is 54 * queued 55 */ 56struct slow_work { 57 struct module *owner; /* the owning module */ 58 unsigned long flags; 59#define SLOW_WORK_PENDING 0 /* item pending (further) execution */ 60#define SLOW_WORK_EXECUTING 1 /* item currently executing */ 61#define SLOW_WORK_ENQ_DEFERRED 2 /* item enqueue deferred */ 62#define SLOW_WORK_VERY_SLOW 3 /* item is very slow */ 63#define SLOW_WORK_CANCELLING 4 /* item is being cancelled, don't enqueue */ 64#define SLOW_WORK_DELAYED 5 /* item is struct delayed_slow_work with active timer */ 65 const struct slow_work_ops *ops; /* operations table for this item */ 66 struct list_head link; /* link in queue */ 67#ifdef CONFIG_SLOW_WORK_DEBUG 68 struct timespec mark; /* jiffies at which queued or exec begun */ 69#endif 70}; 71 72struct delayed_slow_work { 73 struct slow_work work; 74 struct timer_list timer; 75}; 76 77/** 78 * slow_work_init - Initialise a slow work item 79 * @work: The work item to initialise 80 * @ops: The operations to use to handle the slow work item 81 * 82 * Initialise a slow work item. 83 */ 84static inline void slow_work_init(struct slow_work *work, 85 const struct slow_work_ops *ops) 86{ 87 work->flags = 0; 88 work->ops = ops; 89 INIT_LIST_HEAD(&work->link); 90} 91 92/** 93 * slow_work_init - Initialise a delayed slow work item 94 * @work: The work item to initialise 95 * @ops: The operations to use to handle the slow work item 96 * 97 * Initialise a delayed slow work item. 98 */ 99static inline void delayed_slow_work_init(struct delayed_slow_work *dwork, 100 const struct slow_work_ops *ops) 101{ 102 init_timer(&dwork->timer); 103 slow_work_init(&dwork->work, ops); 104} 105 106/** 107 * vslow_work_init - Initialise a very slow work item 108 * @work: The work item to initialise 109 * @ops: The operations to use to handle the slow work item 110 * 111 * Initialise a very slow work item. This item will be restricted such that 112 * only a certain number of the pool threads will be able to execute items of 113 * this type. 114 */ 115static inline void vslow_work_init(struct slow_work *work, 116 const struct slow_work_ops *ops) 117{ 118 work->flags = 1 << SLOW_WORK_VERY_SLOW; 119 work->ops = ops; 120 INIT_LIST_HEAD(&work->link); 121} 122 123/** 124 * slow_work_is_queued - Determine if a slow work item is on the work queue 125 * work: The work item to test 126 * 127 * Determine if the specified slow-work item is on the work queue. This 128 * returns true if it is actually on the queue. 129 * 130 * If the item is executing and has been marked for requeue when execution 131 * finishes, then false will be returned. 132 * 133 * Anyone wishing to wait for completion of execution can wait on the 134 * SLOW_WORK_EXECUTING bit. 135 */ 136static inline bool slow_work_is_queued(struct slow_work *work) 137{ 138 unsigned long flags = work->flags; 139 return flags & SLOW_WORK_PENDING && !(flags & SLOW_WORK_EXECUTING); 140} 141 142extern int slow_work_enqueue(struct slow_work *work); 143extern void slow_work_cancel(struct slow_work *work); 144extern int slow_work_register_user(struct module *owner); 145extern void slow_work_unregister_user(struct module *owner); 146 147extern int delayed_slow_work_enqueue(struct delayed_slow_work *dwork, 148 unsigned long delay); 149 150static inline void delayed_slow_work_cancel(struct delayed_slow_work *dwork) 151{ 152 slow_work_cancel(&dwork->work); 153} 154 155extern bool slow_work_sleep_till_thread_needed(struct slow_work *work, 156 signed long *_timeout); 157 158#ifdef CONFIG_SYSCTL 159extern ctl_table slow_work_sysctls[]; 160#endif 161 162#endif /* CONFIG_SLOW_WORK */ 163#endif /* _LINUX_SLOW_WORK_H */ 164