Skip to content

Commit

Permalink
Flush queue multidevice support.
Browse files Browse the repository at this point in the history
Sort all jnodes by subvolume IDs in the list before its submitting.
Check subvolume ID when recovering extents to make sure that jnodes
of the same extent belong to the same subvolume.

Signed-off-by: Edward Shishkin <edward.shishkin@gmail.com>
  • Loading branch information
edward6 committed Aug 14, 2017
1 parent de89f3c commit 3bb5938
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 22 deletions.
34 changes: 23 additions & 11 deletions flush_queue.c
Expand Up @@ -16,6 +16,7 @@
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/blkdev.h>
#include <linux/list_sort.h>
#include <linux/writeback.h>

/* A flush queue object is an accumulator for keeping jnodes prepared
Expand Down Expand Up @@ -522,6 +523,26 @@ static void release_prepped_list(flush_queue_t *fq)
spin_unlock_atom(atom);
}

static int fq_compare_jnode(void* priv UNUSED_ARG,
struct list_head *a, struct list_head *b)
{
jnode *ja, *jb;

assert("edward-1873", a != NULL);
assert("edward-1874", b != NULL);

ja = jnode_by_link(a);
jb = jnode_by_link(b);

if (jnode_get_subvol(ja)->id < jnode_get_subvol(jb)->id)
return -1;
if (jnode_get_subvol(ja)->id > jnode_get_subvol(jb)->id)
return 1;
if (jnode_get_block(ja) < jnode_get_block(jb))
return -1;
return 1;
}

/**
* Submit write requests for nodes on the already filled flush queue @fq.
*
Expand All @@ -533,8 +554,6 @@ int reiser4_write_fq(flush_queue_t *fq, long *nr_submitted, int flags)
{
int ret;
txn_atom *atom;
u32 mirr_id;
const u32 meta_id = current_volume()->vol_plug->meta_subvol_id();

while (1) {
atom = atom_locked_by_fq(fq);
Expand All @@ -547,18 +566,11 @@ int reiser4_write_fq(flush_queue_t *fq, long *nr_submitted, int flags)
break;
reiser4_atom_wait_event(atom);
}

atom->nr_running_queues++;
spin_unlock_atom(atom);

for_each_mirror(meta_id, mirr_id) {
reiser4_subvol *mirror = current_mirror(meta_id, mirr_id);

ret = write_jnode_list(ATOM_FQ_LIST(fq),
fq, nr_submitted, flags, mirror);
if (ret)
break;
}
list_sort(NULL, ATOM_FQ_LIST(fq), fq_compare_jnode);
ret = write_jnode_list(ATOM_FQ_LIST(fq), fq, nr_submitted, flags);
release_prepped_list(fq);
return ret;
}
Expand Down
4 changes: 2 additions & 2 deletions jnode.h
Expand Up @@ -370,8 +370,8 @@ extern struct address_space *jnode_get_mapping(const jnode * node) NONNULL;

static inline reiser4_subvol *jnode_get_subvol(const jnode *node)
{
assert("edard-1871", node != NULL);
assert("edard-1872", node->subvol != NULL);
assert("edward-1871", node != NULL);
assert("edward-1872", node->subvol != NULL);

return node->subvol;
}
Expand Down
81 changes: 74 additions & 7 deletions wander.c
Expand Up @@ -1005,14 +1005,16 @@ static int write_jnodes_contig(jnode *first, int nr,
}

/**
* Submit a list of jnodes against specified subvolume @subv (it can be
* original subvolume, or replica).
* This procedure recovers extents (contiguous sequences of disk block
* numbers) in a given list of jnodes and submits write requests on this
* per-extent basis.
*
* @head: the list of jnodes to write
* @head: the list of jnodes to submit
*/
int write_jnode_list(struct list_head *head, flush_queue_t *fq,
long *nr_submitted, int flags, reiser4_subvol *subv)
int write_jnode_list_subv(struct list_head *head, flush_queue_t *fq,
long *nr_submitted, int flags, reiser4_subvol *subv)
{
int ret;
struct list_head *beg = head->next;
Expand All @@ -1022,6 +1024,9 @@ int write_jnode_list(struct list_head *head, flush_queue_t *fq,
struct list_head *cur = beg->next;

while (head != cur) {
assert("edward-1876",
jnode_by_link(beg)->subvol ==
subv);
assert("edward-1707",
jnode_by_link(beg)->subvol ==
jnode_by_link(cur)->subvol);
Expand All @@ -1044,6 +1049,67 @@ int write_jnode_list(struct list_head *head, flush_queue_t *fq,
return 0;
}

/**
* Submit a list of jnodes.
* Every jnode is submitted against an origimal subvolume and all its
* replicas.
* This procedure recovers extents (contiguous sequences of disk block
* numbers) in a given list of jnodes and submits write requests on this
* per-extent basis.
*
* @head: list of jnodes to submit.
*/
int write_jnode_list(struct list_head *head, flush_queue_t *fq,
long *nr_submitted, int flags)
{
int ret;
struct list_head *beg = head->next;

while (head != beg) {
int nr = 1;
u32 mirr_id;
struct list_head *cur = beg->next;
reiser4_subvol *subv = jnode_get_subvol(jnode_by_link(beg));

while (head != cur) {
if (jnode_get_subvol(jnode_by_link(cur)) !=
jnode_get_subvol(jnode_by_link(beg)))
break;
if (*jnode_get_block(jnode_by_link(cur)) !=
*jnode_get_block(jnode_by_link(beg)) + nr)
break;
++nr;
cur = cur->next;
}
/*
* submit recovered extent against original subvolume
* and all its replicas
*/
for_each_mirror(subv->id, mirr_id) {
reiser4_subvol *mirror;

mirror = current_mirror(subv->id, mirr_id);

ret = write_jnodes_contig(jnode_by_link(beg), nr,
jnode_get_block(jnode_by_link(beg)),
fq, flags, mirror);
if (ret)
return ret;
}
#if 0
notice("edward-1875",
"subvol %llu: written extent (%llu, %llu)",
(unsigned long long)subv->id,
(unsigned long long)*jnode_get_block(jnode_by_link(beg)),
(unsigned long long)nr);
#endif
if (nr_submitted)
*nr_submitted += nr;
beg = cur;
}
return 0;
}

/*
* add given wandered mapping to atom's wandered map
*/
Expand Down Expand Up @@ -1256,7 +1322,7 @@ static int alloc_submit_wander_records(struct commit_handle *ch,
/*
* submit wander records
*/
ret = write_jnode_list(tx_list, fq, NULL, 0, subv);
ret = write_jnode_list_subv(tx_list, fq, NULL, 0, subv);

return ret;

Expand Down Expand Up @@ -1339,8 +1405,8 @@ static int play_tx_mirror(struct commit_handle *ch, reiser4_subvol *mirror)
return PTR_ERR(fq);
spin_unlock_atom(fq->atom);

ret = write_jnode_list(&ch_sub->overwrite_set,
fq, NULL, WRITEOUT_FOR_PAGE_RECLAIM, mirror);
ret = write_jnode_list_subv(&ch_sub->overwrite_set, fq,
NULL, WRITEOUT_FOR_PAGE_RECLAIM, mirror);
reiser4_fq_put(fq);
return ret;
}
Expand Down Expand Up @@ -1610,7 +1676,8 @@ static int replay_tx_subv(reiser4_subvol *subv)
subv = super_mirror(subv->super, orig_id, mirr_id);
assert("edward-1711", subvol_is_set(subv, SUBVOL_ACTIVATED));

write_jnode_list(&ch_sub->overwrite_set, NULL, NULL, 0, subv);
write_jnode_list_subv(&ch_sub->overwrite_set,
NULL, NULL, 0, subv);
ret = wait_on_jnode_list(&ch_sub->overwrite_set);
if (ret)
goto error;
Expand Down
5 changes: 3 additions & 2 deletions wander.h
Expand Up @@ -120,8 +120,9 @@ extern int reiser4_journal_recover_sb_data(struct super_block *,
extern int reiser4_init_journal_info(reiser4_subvol *subv);
extern void reiser4_done_journal_info(reiser4_subvol *subv);

extern int write_jnode_list(struct list_head *, flush_queue_t *, long *, int,
reiser4_subvol *);
extern int write_jnode_list_subv(struct list_head *, flush_queue_t *,
long *, int, reiser4_subvol *);
extern int write_jnode_list(struct list_head *, flush_queue_t *, long *, int);

#endif /* __FS_REISER4_WANDER_H__ */

Expand Down

0 comments on commit 3bb5938

Please sign in to comment.