Skip to content

Commit

Permalink
sched: Remove proliferation of wait_on_bit() action functions
Browse files Browse the repository at this point in the history
The current "wait_on_bit" interface requires an 'action'
function to be provided which does the actual waiting.
There are over 20 such functions, many of them identical.
Most cases can be satisfied by one of just two functions, one
which uses io_schedule() and one which just uses schedule().

So:
 Rename wait_on_bit and        wait_on_bit_lock to
        wait_on_bit_action and wait_on_bit_lock_action
 to make it explicit that they need an action function.

 Introduce new wait_on_bit{,_lock} and wait_on_bit{,_lock}_io
 which are *not* given an action function but implicitly use
 a standard one.
 The decision to error-out if a signal is pending is now made
 based on the 'mode' argument rather than being encoded in the action
 function.

 All instances of the old wait_on_bit and wait_on_bit_lock which
 can use the new version have been changed accordingly and their
 action functions have been discarded.
 wait_on_bit{_lock} does not return any specific error code in the
 event of a signal so the caller must check for non-zero and
 interpolate their own error code as appropriate.

The wait_on_bit() call in __fscache_wait_on_invalidate() was
ambiguous as it specified TASK_UNINTERRUPTIBLE but used
fscache_wait_bit_interruptible as an action function.
David Howells confirms this should be uniformly
"uninterruptible"

The main remaining user of wait_on_bit{,_lock}_action is NFS
which needs to use a freezer-aware schedule() call.

A comment in fs/gfs2/glock.c notes that having multiple 'action'
functions is useful as they display differently in the 'wchan'
field of 'ps'. (and /proc/$PID/wchan).
As the new bit_wait{,_io} functions are tagged "__sched", they
will not show up at all, but something higher in the stack.  So
the distinction will still be visible, only with different
function names (gds2_glock_wait versus gfs2_glock_dq_wait in the
gfs2/glock.c case).

Since first version of this patch (against 3.15) two new action
functions appeared, on in NFS and one in CIFS.  CIFS also now
uses an action function that makes the same freezer aware
schedule call as NFS.

Signed-off-by: NeilBrown <neilb@suse.de>
Acked-by: David Howells <dhowells@redhat.com> (fscache, keys)
Acked-by: Steven Whitehouse <swhiteho@redhat.com> (gfs2)
Acked-by: Peter Zijlstra <peterz@infradead.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Steve French <sfrench@samba.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: http://lkml.kernel.org/r/20140707051603.28027.72349.stgit@notabene.brown
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
neilbrown authored and Ingo Molnar committed Jul 16, 2014
1 parent d26fad5 commit 7431620
Show file tree
Hide file tree
Showing 38 changed files with 195 additions and 275 deletions.
2 changes: 1 addition & 1 deletion Documentation/filesystems/caching/operations.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ operations:
to be cleared before proceeding:

wait_on_bit(&op->flags, FSCACHE_OP_WAITING,
fscache_wait_bit, TASK_UNINTERRUPTIBLE);
TASK_UNINTERRUPTIBLE);


(2) The operation may be fast asynchronous (FSCACHE_OP_FAST), in which case it
Expand Down
41 changes: 14 additions & 27 deletions drivers/md/dm-bufio.c
Original file line number Diff line number Diff line change
Expand Up @@ -614,16 +614,6 @@ static void write_endio(struct bio *bio, int error)
wake_up_bit(&b->state, B_WRITING);
}

/*
* This function is called when wait_on_bit is actually waiting.
*/
static int do_io_schedule(void *word)
{
io_schedule();

return 0;
}

/*
* Initiate a write on a dirty buffer, but don't wait for it.
*
Expand All @@ -640,8 +630,7 @@ static void __write_dirty_buffer(struct dm_buffer *b,
return;

clear_bit(B_DIRTY, &b->state);
wait_on_bit_lock(&b->state, B_WRITING,
do_io_schedule, TASK_UNINTERRUPTIBLE);
wait_on_bit_lock_io(&b->state, B_WRITING, TASK_UNINTERRUPTIBLE);

if (!write_list)
submit_io(b, WRITE, b->block, write_endio);
Expand Down Expand Up @@ -675,9 +664,9 @@ static void __make_buffer_clean(struct dm_buffer *b)
if (!b->state) /* fast case */
return;

wait_on_bit(&b->state, B_READING, do_io_schedule, TASK_UNINTERRUPTIBLE);
wait_on_bit_io(&b->state, B_READING, TASK_UNINTERRUPTIBLE);
__write_dirty_buffer(b, NULL);
wait_on_bit(&b->state, B_WRITING, do_io_schedule, TASK_UNINTERRUPTIBLE);
wait_on_bit_io(&b->state, B_WRITING, TASK_UNINTERRUPTIBLE);
}

/*
Expand Down Expand Up @@ -1030,7 +1019,7 @@ static void *new_read(struct dm_bufio_client *c, sector_t block,
if (need_submit)
submit_io(b, READ, b->block, read_endio);

wait_on_bit(&b->state, B_READING, do_io_schedule, TASK_UNINTERRUPTIBLE);
wait_on_bit_io(&b->state, B_READING, TASK_UNINTERRUPTIBLE);

if (b->read_error) {
int error = b->read_error;
Expand Down Expand Up @@ -1209,15 +1198,13 @@ int dm_bufio_write_dirty_buffers(struct dm_bufio_client *c)
dropped_lock = 1;
b->hold_count++;
dm_bufio_unlock(c);
wait_on_bit(&b->state, B_WRITING,
do_io_schedule,
TASK_UNINTERRUPTIBLE);
wait_on_bit_io(&b->state, B_WRITING,
TASK_UNINTERRUPTIBLE);
dm_bufio_lock(c);
b->hold_count--;
} else
wait_on_bit(&b->state, B_WRITING,
do_io_schedule,
TASK_UNINTERRUPTIBLE);
wait_on_bit_io(&b->state, B_WRITING,
TASK_UNINTERRUPTIBLE);
}

if (!test_bit(B_DIRTY, &b->state) &&
Expand Down Expand Up @@ -1321,15 +1308,15 @@ void dm_bufio_release_move(struct dm_buffer *b, sector_t new_block)

__write_dirty_buffer(b, NULL);
if (b->hold_count == 1) {
wait_on_bit(&b->state, B_WRITING,
do_io_schedule, TASK_UNINTERRUPTIBLE);
wait_on_bit_io(&b->state, B_WRITING,
TASK_UNINTERRUPTIBLE);
set_bit(B_DIRTY, &b->state);
__unlink_buffer(b);
__link_buffer(b, new_block, LIST_DIRTY);
} else {
sector_t old_block;
wait_on_bit_lock(&b->state, B_WRITING,
do_io_schedule, TASK_UNINTERRUPTIBLE);
wait_on_bit_lock_io(&b->state, B_WRITING,
TASK_UNINTERRUPTIBLE);
/*
* Relink buffer to "new_block" so that write_callback
* sees "new_block" as a block number.
Expand All @@ -1341,8 +1328,8 @@ void dm_bufio_release_move(struct dm_buffer *b, sector_t new_block)
__unlink_buffer(b);
__link_buffer(b, new_block, b->list_mode);
submit_io(b, WRITE, new_block, write_endio);
wait_on_bit(&b->state, B_WRITING,
do_io_schedule, TASK_UNINTERRUPTIBLE);
wait_on_bit_io(&b->state, B_WRITING,
TASK_UNINTERRUPTIBLE);
__unlink_buffer(b);
__link_buffer(b, old_block, b->list_mode);
}
Expand Down
10 changes: 1 addition & 9 deletions drivers/md/dm-snap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1032,21 +1032,13 @@ static void start_merge(struct dm_snapshot *s)
snapshot_merge_next_chunks(s);
}

static int wait_schedule(void *ptr)
{
schedule();

return 0;
}

/*
* Stop the merging process and wait until it finishes.
*/
static void stop_merge(struct dm_snapshot *s)
{
set_bit(SHUTDOWN_MERGE, &s->state_bits);
wait_on_bit(&s->state_bits, RUNNING_MERGE, wait_schedule,
TASK_UNINTERRUPTIBLE);
wait_on_bit(&s->state_bits, RUNNING_MERGE, TASK_UNINTERRUPTIBLE);
clear_bit(SHUTDOWN_MERGE, &s->state_bits);
}

Expand Down
12 changes: 2 additions & 10 deletions drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,13 +253,6 @@ static int dvb_usbv2_adapter_stream_exit(struct dvb_usb_adapter *adap)
return usb_urb_exitv2(&adap->stream);
}

static int wait_schedule(void *ptr)
{
schedule();

return 0;
}

static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
{
struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv;
Expand All @@ -273,8 +266,7 @@ static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
dvbdmxfeed->pid, dvbdmxfeed->index);

/* wait init is done */
wait_on_bit(&adap->state_bits, ADAP_INIT, wait_schedule,
TASK_UNINTERRUPTIBLE);
wait_on_bit(&adap->state_bits, ADAP_INIT, TASK_UNINTERRUPTIBLE);

if (adap->active_fe == -1)
return -EINVAL;
Expand Down Expand Up @@ -568,7 +560,7 @@ static int dvb_usb_fe_sleep(struct dvb_frontend *fe)

if (!adap->suspend_resume_active) {
set_bit(ADAP_SLEEP, &adap->state_bits);
wait_on_bit(&adap->state_bits, ADAP_STREAMING, wait_schedule,
wait_on_bit(&adap->state_bits, ADAP_STREAMING,
TASK_UNINTERRUPTIBLE);
}

Expand Down
10 changes: 2 additions & 8 deletions fs/btrfs/extent_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -3437,16 +3437,10 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc,
return 0;
}

static int eb_wait(void *word)
{
io_schedule();
return 0;
}

void wait_on_extent_buffer_writeback(struct extent_buffer *eb)
{
wait_on_bit(&eb->bflags, EXTENT_BUFFER_WRITEBACK, eb_wait,
TASK_UNINTERRUPTIBLE);
wait_on_bit_io(&eb->bflags, EXTENT_BUFFER_WRITEBACK,
TASK_UNINTERRUPTIBLE);
}

static noinline_for_stack int
Expand Down
11 changes: 2 additions & 9 deletions fs/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,9 @@ inline void touch_buffer(struct buffer_head *bh)
}
EXPORT_SYMBOL(touch_buffer);

static int sleep_on_buffer(void *word)
{
io_schedule();
return 0;
}

void __lock_buffer(struct buffer_head *bh)
{
wait_on_bit_lock(&bh->b_state, BH_Lock, sleep_on_buffer,
TASK_UNINTERRUPTIBLE);
wait_on_bit_lock_io(&bh->b_state, BH_Lock, TASK_UNINTERRUPTIBLE);
}
EXPORT_SYMBOL(__lock_buffer);

Expand Down Expand Up @@ -123,7 +116,7 @@ EXPORT_SYMBOL(buffer_check_dirty_writeback);
*/
void __wait_on_buffer(struct buffer_head * bh)
{
wait_on_bit(&bh->b_state, BH_Lock, sleep_on_buffer, TASK_UNINTERRUPTIBLE);
wait_on_bit_io(&bh->b_state, BH_Lock, TASK_UNINTERRUPTIBLE);
}
EXPORT_SYMBOL(__wait_on_buffer);

Expand Down
10 changes: 1 addition & 9 deletions fs/cifs/connect.c
Original file line number Diff line number Diff line change
Expand Up @@ -3934,13 +3934,6 @@ cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
return tlink_tcon(cifs_sb_master_tlink(cifs_sb));
}

static int
cifs_sb_tcon_pending_wait(void *unused)
{
schedule();
return signal_pending(current) ? -ERESTARTSYS : 0;
}

/* find and return a tlink with given uid */
static struct tcon_link *
tlink_rb_search(struct rb_root *root, kuid_t uid)
Expand Down Expand Up @@ -4039,11 +4032,10 @@ cifs_sb_tlink(struct cifs_sb_info *cifs_sb)
} else {
wait_for_construction:
ret = wait_on_bit(&tlink->tl_flags, TCON_LINK_PENDING,
cifs_sb_tcon_pending_wait,
TASK_INTERRUPTIBLE);
if (ret) {
cifs_put_tlink(tlink);
return ERR_PTR(ret);
return ERR_PTR(-ERESTARTSYS);
}

/* if it's good, return it */
Expand Down
9 changes: 1 addition & 8 deletions fs/cifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -3618,13 +3618,6 @@ static int cifs_launder_page(struct page *page)
return rc;
}

static int
cifs_pending_writers_wait(void *unused)
{
schedule();
return 0;
}

void cifs_oplock_break(struct work_struct *work)
{
struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo,
Expand All @@ -3636,7 +3629,7 @@ void cifs_oplock_break(struct work_struct *work)
int rc = 0;

wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS,
cifs_pending_writers_wait, TASK_UNINTERRUPTIBLE);
TASK_UNINTERRUPTIBLE);

server->ops->downgrade_oplock(server, cinode,
test_bit(CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, &cinode->flags));
Expand Down
4 changes: 2 additions & 2 deletions fs/cifs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1794,8 +1794,8 @@ cifs_revalidate_mapping(struct inode *inode)
int rc;
unsigned long *flags = &CIFS_I(inode)->flags;

rc = wait_on_bit_lock(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
TASK_KILLABLE);
rc = wait_on_bit_lock_action(flags, CIFS_INO_LOCK, cifs_wait_bit_killable,
TASK_KILLABLE);
if (rc)
return rc;

Expand Down
2 changes: 1 addition & 1 deletion fs/cifs/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ int cifs_get_writer(struct cifsInodeInfo *cinode)

start:
rc = wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK,
cifs_oplock_break_wait, TASK_KILLABLE);
TASK_KILLABLE);
if (rc)
return rc;

Expand Down
3 changes: 2 additions & 1 deletion fs/fs-writeback.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,8 @@ static void __inode_wait_for_writeback(struct inode *inode)
wqh = bit_waitqueue(&inode->i_state, __I_SYNC);
while (inode->i_state & I_SYNC) {
spin_unlock(&inode->i_lock);
__wait_on_bit(wqh, &wq, inode_wait, TASK_UNINTERRUPTIBLE);
__wait_on_bit(wqh, &wq, bit_wait,
TASK_UNINTERRUPTIBLE);
spin_lock(&inode->i_lock);
}
}
Expand Down
7 changes: 3 additions & 4 deletions fs/fscache/cookie.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ void __fscache_enable_cookie(struct fscache_cookie *cookie,
_enter("%p", cookie);

wait_on_bit_lock(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK,
fscache_wait_bit, TASK_UNINTERRUPTIBLE);
TASK_UNINTERRUPTIBLE);

if (test_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags))
goto out_unlock;
Expand Down Expand Up @@ -255,7 +255,7 @@ static int fscache_acquire_non_index_cookie(struct fscache_cookie *cookie)
if (!fscache_defer_lookup) {
_debug("non-deferred lookup %p", &cookie->flags);
wait_on_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP,
fscache_wait_bit, TASK_UNINTERRUPTIBLE);
TASK_UNINTERRUPTIBLE);
_debug("complete");
if (test_bit(FSCACHE_COOKIE_UNAVAILABLE, &cookie->flags))
goto unavailable;
Expand Down Expand Up @@ -463,7 +463,6 @@ void __fscache_wait_on_invalidate(struct fscache_cookie *cookie)
_enter("%p", cookie);

wait_on_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING,
fscache_wait_bit_interruptible,
TASK_UNINTERRUPTIBLE);

_leave("");
Expand Down Expand Up @@ -525,7 +524,7 @@ void __fscache_disable_cookie(struct fscache_cookie *cookie, bool invalidate)
}

wait_on_bit_lock(&cookie->flags, FSCACHE_COOKIE_ENABLEMENT_LOCK,
fscache_wait_bit, TASK_UNINTERRUPTIBLE);
TASK_UNINTERRUPTIBLE);
if (!test_and_clear_bit(FSCACHE_COOKIE_ENABLED, &cookie->flags))
goto out_unlock_enable;

Expand Down
2 changes: 0 additions & 2 deletions fs/fscache/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,6 @@ 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 *);
extern int fscache_wait_atomic_t(atomic_t *);

/*
Expand Down
18 changes: 0 additions & 18 deletions fs/fscache/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,24 +196,6 @@ static void __exit fscache_exit(void)

module_exit(fscache_exit);

/*
* wait_on_bit() sleep function for uninterruptible waiting
*/
int fscache_wait_bit(void *flags)
{
schedule();
return 0;
}

/*
* wait_on_bit() sleep function for interruptible waiting
*/
int fscache_wait_bit_interruptible(void *flags)
{
schedule();
return signal_pending(current);
}

/*
* wait_on_atomic_t() sleep function for uninterruptible waiting
*/
Expand Down
4 changes: 1 addition & 3 deletions fs/fscache/page.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,6 @@ int fscache_wait_for_deferred_lookup(struct fscache_cookie *cookie)

jif = jiffies;
if (wait_on_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP,
fscache_wait_bit_interruptible,
TASK_INTERRUPTIBLE) != 0) {
fscache_stat(&fscache_n_retrievals_intr);
_leave(" = -ERESTARTSYS");
Expand Down Expand Up @@ -342,7 +341,6 @@ int fscache_wait_for_operation_activation(struct fscache_object *object,
if (stat_op_waits)
fscache_stat(stat_op_waits);
if (wait_on_bit(&op->flags, FSCACHE_OP_WAITING,
fscache_wait_bit_interruptible,
TASK_INTERRUPTIBLE) != 0) {
ret = fscache_cancel_op(op, do_cancel);
if (ret == 0)
Expand All @@ -351,7 +349,7 @@ int fscache_wait_for_operation_activation(struct fscache_object *object,
/* it's been removed from the pending queue by another party,
* so we should get to run shortly */
wait_on_bit(&op->flags, FSCACHE_OP_WAITING,
fscache_wait_bit, TASK_UNINTERRUPTIBLE);
TASK_UNINTERRUPTIBLE);
}
_debug("<<< GO");

Expand Down
Loading

0 comments on commit 7431620

Please sign in to comment.