Skip to content

Commit

Permalink
Turn the insertion-region code into a function
Browse files Browse the repository at this point in the history
  • Loading branch information
dhowells committed Jun 9, 2022
1 parent ab4885d commit 8175808
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 105 deletions.
36 changes: 5 additions & 31 deletions fs/netfs/buffered_flush.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,47 +187,21 @@ int netfs_flush_conflicting_writes(struct netfs_inode *ctx,
* point indicates the last page in the front region. A pointer to the new
* front part is returned.
*/
static struct netfs_dirty_region *netfs_split_off_front(
static struct netfs_dirty_region *netfs_alloc_split_off_front(
struct netfs_inode *ctx,
struct netfs_dirty_region *back,
pgoff_t front_last,
enum netfs_dirty_trace why)
{
struct netfs_dirty_region *front;

BUG_ON(back->first > front_last);
BUG_ON(back->last < front_last);

front = netfs_alloc_dirty_region(GFP_ATOMIC);
if (!front) {
pr_err("OOM\n");
BUG();
}

front->debug_id = atomic_inc_return(&netfs_region_debug_ids);
front->type = back->type;
front->first = back->first;
front->last = front_last;
back->first = front->last + 1;
front->from = back->from;
back->from = back->first * PAGE_SIZE;
front->to = back->from;

_debug("front %04lx-%04lx %08llx-%08llx",
front->first, front->last, front->from, front->to);
_debug("back %04lx-%04lx %08llx-%08llx",
back->first, back->last, back->from, back->to);

_debug("split D=%x from D=%x", front->debug_id, back->debug_id);

if (ctx->ops->split_dirty_region)
ctx->ops->split_dirty_region(front, back);

list_move_tail(&front->dirty_link, &back->dirty_link);
list_add_tail (&front->proc_link, &back->proc_link);

trace_netfs_dirty(ctx, front, back, why);
trace_netfs_dirty(ctx, back, front, netfs_dirty_trace_split);
netfs_split_off_front(ctx, front, back, front_last, why);
return front;
}

Expand Down Expand Up @@ -301,8 +275,8 @@ static void netfs_split_out_regions(struct netfs_io_request *wreq,
if (wreq->first != region->first) {
BUG_ON(wreq->first < region->first);
BUG_ON(wreq->first == 0);
netfs_split_off_front(ctx, region, wreq->first - 1,
netfs_dirty_trace_split_off_front);
netfs_alloc_split_off_front(ctx, region, wreq->first - 1,
netfs_dirty_trace_split_off_front);
netfs_check_dirty_list('F', &ctx->dirty_regions, region);
}

Expand All @@ -311,7 +285,7 @@ static void netfs_split_out_regions(struct netfs_io_request *wreq,
if (wreq->last == region->last)
goto excise;
if (wreq->last < region->last) {
region = netfs_split_off_front(
region = netfs_alloc_split_off_front(
ctx, region, wreq->last,
netfs_dirty_trace_split_off_back);
if (region->dirty_link.next == &front->dirty_link)
Expand Down
166 changes: 100 additions & 66 deletions fs/netfs/buffered_write.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,15 +148,16 @@ static bool netfs_try_bridge_next(struct netfs_inode *ctx,
if (target->last >= next->last) {
/* Next entry is superseded in its entirety. */
list_move(&next->dirty_link, discards);
trace_netfs_dirty(ctx, target, next, netfs_dirty_trace_supersede);
trace_netfs_dirty(ctx, target, next,
netfs_dirty_trace_supersede_all);
if (target->last > next->last)
goto again;
goto out;
}

next->from = target->to;
next->first = target->last + 1;
trace_netfs_dirty(ctx, target, next, netfs_dirty_trace_supersede);
trace_netfs_dirty(ctx, target, next, netfs_dirty_trace_superseded);
out:
return true; /* Return true for tail-callers */
}
Expand Down Expand Up @@ -224,6 +225,74 @@ static bool netfs_merge_with_next(struct netfs_inode *ctx,
return true;
}

/*
* Insert a new region at the specified point, initialising it from the
* proposed region.
*/
static void netfs_insert_new(struct netfs_inode *ctx,
struct netfs_dirty_region *insertion,
const struct netfs_dirty_region *proposal,
struct file *file,
struct netfs_dirty_region *insert_point,
enum netfs_dirty_trace how)
{
insertion->first = proposal->first;
insertion->last = proposal->last;
insertion->from = proposal->from;
insertion->to = proposal->to;
insertion->type = proposal->type;
netfs_init_dirty_region(ctx, insertion, file);
switch (how) {
case netfs_dirty_trace_insert_only:
list_add_tail(&insertion->dirty_link, &ctx->dirty_regions);
break;
case netfs_dirty_trace_insert_before:
case netfs_dirty_trace_supersede_front:
list_add_tail(&insertion->dirty_link, &insert_point->dirty_link);
break;
case netfs_dirty_trace_insert_after:
case netfs_dirty_trace_supersede_back:
list_add(&insertion->dirty_link, &insert_point->dirty_link);
break;
default:
BUG_ON(1);
}
trace_netfs_dirty(ctx, insertion, insert_point, how);
}

/*
* Split the front off of the dirty region at the specified point into the new
* supplied front region, where the point indicates the last page in the front
* region.
*/
void netfs_split_off_front(struct netfs_inode *ctx,
struct netfs_dirty_region *front,
struct netfs_dirty_region *back,
pgoff_t front_last,
enum netfs_dirty_trace why)
{
BUG_ON(back->first > front_last);
BUG_ON(back->last < front_last);

front->debug_id = atomic_inc_return(&netfs_region_debug_ids);
front->type = back->type;
front->first = back->first;
front->last = front_last;
back->first = front->last + 1;
front->from = back->from;
back->from = back->first * PAGE_SIZE;
front->to = back->from;

if (front->type != NETFS_COPY_TO_CACHE &&
ctx->ops->split_dirty_region)
ctx->ops->split_dirty_region(front, back);

list_move_tail(&front->dirty_link, &back->dirty_link);
list_add(&front->proc_link, &back->proc_link);

trace_netfs_dirty(ctx, front, back, why);
}

/*
* Supersede some data that's marked copy-to-cache only. We may need to make
* up to two splits in the region and we may need to merge with the adjacent
Expand All @@ -237,7 +306,7 @@ static void netfs_supersede_cache_copy(struct netfs_inode *ctx,
{
struct netfs_dirty_region *prev = netfs_prev_region(ctx, target);
struct netfs_dirty_region *next = netfs_next_region(ctx, target);
struct netfs_dirty_region *tail, *insertion;
struct netfs_dirty_region *insertion, *front;

_enter("D=%u", target->debug_id);

Expand Down Expand Up @@ -286,23 +355,20 @@ static void netfs_supersede_cache_copy(struct netfs_inode *ctx,
prev->last = proposal->last;
target->first = proposal->last + 1;
target->from = target->first * PAGE_SIZE;
trace_netfs_dirty(ctx, prev, target, netfs_dirty_trace_merged_prev_super);
trace_netfs_dirty(ctx, prev, target,
netfs_dirty_trace_merged_prev_super);
} else {
insertion = netfs_alloc_dirty_region(GFP_ATOMIC);
if (!insertion) {
pr_err("OOM");
BUG();
}
insertion->first = proposal->first;
insertion->last = proposal->last;
insertion->from = proposal->from;
insertion->to = proposal->to;
insertion->type = proposal->type;
netfs_init_dirty_region(ctx, insertion, file);
list_move_tail(&insertion->dirty_link, &target->dirty_link);
netfs_insert_new(ctx, insertion, proposal, file, target,
netfs_dirty_trace_supersede_front);
target->first = insertion->last + 1;
target->to = target->first * PAGE_SIZE;
trace_netfs_dirty(ctx, insertion, target, netfs_dirty_trace_supersede);
trace_netfs_dirty(ctx, insertion, target,
netfs_dirty_trace_superseded);
}
return;
}
Expand All @@ -318,57 +384,43 @@ static void netfs_supersede_cache_copy(struct netfs_inode *ctx,
next->first = proposal->first;
target->last = proposal->first - 1;
target->to = proposal->first * PAGE_SIZE;
trace_netfs_dirty(ctx, next, target, netfs_dirty_trace_merged_next_super);
trace_netfs_dirty(ctx, next, target,
netfs_dirty_trace_merged_next_super);
} else {
insertion = netfs_alloc_dirty_region(GFP_ATOMIC);
if (!insertion) {
pr_err("OOM");
BUG();
}
insertion->first = proposal->first;
insertion->last = proposal->last;
insertion->from = proposal->from;
insertion->to = proposal->to;
insertion->type = proposal->type;
netfs_init_dirty_region(ctx, insertion, file);
list_move(&insertion->dirty_link, &target->dirty_link);
netfs_insert_new(ctx, insertion, proposal, file, target,
netfs_dirty_trace_supersede_back);
target->first = proposal->last + 1;
target->from = target->first * PAGE_SIZE;
trace_netfs_dirty(ctx, insertion, target, netfs_dirty_trace_supersede);
trace_netfs_dirty(ctx, target, insertion,
netfs_dirty_trace_superseded);
}
return;
}

/* Otherwise we have to split the copy-to-cache region and insert the
* proposed region between.
*/
tail = netfs_alloc_dirty_region(GFP_ATOMIC);
if (!tail) {
insertion = netfs_alloc_dirty_region(GFP_ATOMIC);
if (!insertion) {
pr_err("OOM");
BUG();
}
tail->first = proposal->last + 1;
tail->last = target->last;
tail->from = tail->first * PAGE_SIZE;
tail->to = target->to;
tail->type = NETFS_COPY_TO_CACHE;
netfs_init_dirty_region(ctx, tail, NULL);
list_move(&tail->dirty_link, &target->dirty_link);
trace_netfs_dirty(ctx, tail, target, netfs_dirty_trace_split_c2c);

insertion = netfs_alloc_dirty_region(GFP_ATOMIC);
if (!insertion) {
front = netfs_alloc_dirty_region(GFP_ATOMIC);
if (!front) {
pr_err("OOM");
BUG();
}
insertion->first = proposal->first;
insertion->last = proposal->last;
insertion->from = proposal->from;
insertion->to = proposal->to;
insertion->type = proposal->type;
netfs_init_dirty_region(ctx, insertion, file);
list_move(&insertion->dirty_link, &target->dirty_link);
trace_netfs_dirty(ctx, insertion, target, netfs_dirty_trace_supersede);

netfs_split_off_front(ctx, front, target, proposal->first - 1,
netfs_dirty_trace_split_c2c);

netfs_insert_new(ctx, insertion, proposal, file, target,
netfs_dirty_trace_supersede_front);

target->from = min(target->from, insertion->from);
target->first = min(target->first, insertion->first);
Expand Down Expand Up @@ -406,14 +458,8 @@ static void netfs_commit_region(struct netfs_inode *ctx, struct file *file,
pr_err("OOM\n");
BUG();
}
insertion->first = proposal->first;
insertion->last = proposal->last;
insertion->from = proposal->from;
insertion->to = proposal->to;
insertion->type = proposal->type;
netfs_init_dirty_region(ctx, insertion, file);
list_move_tail(&insertion->dirty_link, &ctx->dirty_regions);
trace_netfs_dirty(ctx, insertion, NULL, netfs_dirty_trace_insert);
netfs_insert_new(ctx, insertion, proposal, file, NULL,
netfs_dirty_trace_insert_only);
goto done;
}

Expand Down Expand Up @@ -448,14 +494,8 @@ static void netfs_commit_region(struct netfs_inode *ctx, struct file *file,
pr_err("OOM\n");
BUG();
}
insertion->first = proposal->first;
insertion->last = proposal->last;
insertion->from = proposal->from;
insertion->to = proposal->to;
insertion->type = proposal->type;
netfs_init_dirty_region(ctx, insertion, file);
list_move_tail(&insertion->dirty_link, &ctx->dirty_regions);
trace_netfs_dirty(ctx, insertion, NULL, netfs_dirty_trace_insert);
netfs_insert_new(ctx, insertion, proposal, file, target,
netfs_dirty_trace_insert_after);
goto done;
}
target = next;
Expand All @@ -471,14 +511,8 @@ static void netfs_commit_region(struct netfs_inode *ctx, struct file *file,
pr_err("OOM\n");
BUG();
}
insertion->first = proposal->first;
insertion->last = proposal->last;
insertion->from = proposal->from;
insertion->to = proposal->to;
insertion->type = proposal->type;
netfs_init_dirty_region(ctx, insertion, file);
list_move_tail(&insertion->dirty_link, &target->dirty_link);
trace_netfs_dirty(ctx, insertion, NULL, netfs_dirty_trace_insert);
netfs_insert_new(ctx, insertion, proposal, file, target,
netfs_dirty_trace_insert_before);

done:
spin_unlock(&ctx->dirty_lock);
Expand Down
7 changes: 5 additions & 2 deletions fs/netfs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ int netfs_prefetch_for_write(struct file *file, struct folio *folio, size_t len)
/*
* buffered_write.c
*/
int netfs_preallocate_regions(struct list_head *spare_regions);
void netfs_unpreallocate_regions(struct list_head *spare_regions);
void netfs_discard_regions(struct netfs_inode *ctx,
struct list_head *discards,
enum netfs_region_trace why);
Expand All @@ -42,6 +40,11 @@ bool netfs_are_regions_mergeable(struct netfs_inode *ctx,
const struct netfs_dirty_region *b);
struct netfs_dirty_region *netfs_find_region(struct netfs_inode *ctx,
pgoff_t first, pgoff_t last);
void netfs_split_off_front(struct netfs_inode *ctx,
struct netfs_dirty_region *front,
struct netfs_dirty_region *back,
pgoff_t front_last,
enum netfs_dirty_trace why);
void netfs_rreq_do_write_to_cache(struct netfs_io_request *rreq);

/*
Expand Down
8 changes: 4 additions & 4 deletions fs/netfs/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,12 @@ static void *netfs_requests_seq_start(struct seq_file *m, loff_t *_pos)
__acquires(rcu)
{
rcu_read_lock();
return seq_list_start_head(&netfs_io_requests, *_pos);
return seq_list_start_head_rcu(&netfs_io_requests, *_pos);
}

static void *netfs_requests_seq_next(struct seq_file *m, void *v, loff_t *_pos)
{
return seq_list_next(v, &netfs_io_requests, _pos);
return seq_list_next_rcu(v, &netfs_io_requests, _pos);
}

static void netfs_requests_seq_stop(struct seq_file *m, void *v)
Expand Down Expand Up @@ -122,12 +122,12 @@ static void *netfs_regions_seq_start(struct seq_file *m, loff_t *_pos)
__acquires(rcu)
{
rcu_read_lock();
return seq_list_start_head(&netfs_regions, *_pos);
return seq_list_start_head_rcu(&netfs_regions, *_pos);
}

static void *netfs_regions_seq_next(struct seq_file *m, void *v, loff_t *_pos)
{
return seq_list_next(v, &netfs_regions, _pos);
return seq_list_next_rcu(v, &netfs_regions, _pos);
}

static void netfs_regions_seq_stop(struct seq_file *m, void *v)
Expand Down

0 comments on commit 8175808

Please sign in to comment.