diff --git a/kmod/src/counters.h b/kmod/src/counters.h index b8432d56..6d26c4f7 100644 --- a/kmod/src/counters.h +++ b/kmod/src/counters.h @@ -56,6 +56,7 @@ EXPAND_COUNTER(extent_delete) \ EXPAND_COUNTER(extent_insert) \ EXPAND_COUNTER(extent_next) \ + EXPAND_COUNTER(extent_prev) \ EXPAND_COUNTER(extent_remove) \ EXPAND_COUNTER(item_alloc) \ EXPAND_COUNTER(item_batch_duplicate) \ diff --git a/kmod/src/data.c b/kmod/src/data.c index d2600cbe..50196f37 100644 --- a/kmod/src/data.c +++ b/kmod/src/data.c @@ -139,6 +139,7 @@ static int data_extent_io(struct super_block *sb, int op, { struct scoutfs_lock *lock = data; struct scoutfs_file_extent fex; + struct scoutfs_key first; struct scoutfs_key last; struct scoutfs_key key; struct kvec val; @@ -164,6 +165,7 @@ static int data_extent_io(struct super_block *sb, int op, if (ext->type == SCOUTFS_FILE_EXTENT_TYPE) { init_file_extent_key(&key, ext->owner, ext->start + ext->len - 1); + init_file_extent_key(&first, ext->owner, 0); init_file_extent_key(&last, ext->owner, U64_MAX); fex.blkno = cpu_to_le64(ext->map); fex.len = cpu_to_le64(ext->len); @@ -174,14 +176,20 @@ static int data_extent_io(struct super_block *sb, int op, ext->start + ext->len - 1, ext->len); if (ext->type == SCOUTFS_FREE_EXTENT_BLOCKS_TYPE) swap(key.sknf_major, key.sknf_minor); + init_free_extent_key(&first, ext->type, ext->owner, + 0, 0); init_free_extent_key(&last, ext->type, ext->owner, U64_MAX, U64_MAX); kvec_init(&val, NULL, 0); } - if (op == SEI_NEXT) { + if (op == SEI_NEXT || op == SEI_PREV) { expected = val.iov_len; - ret = scoutfs_item_next(sb, &key, &last, &val, lock); + + if (op == SEI_NEXT) + ret = scoutfs_item_next(sb, &key, &last, &val, lock); + else + ret = scoutfs_item_prev(sb, &key, &first, &val, lock); if (ret >= 0 && ret != expected) ret = -EIO; if (ret == expected) diff --git a/kmod/src/extents.c b/kmod/src/extents.c index bbb18c71..c5bacdfd 100644 --- a/kmod/src/extents.c +++ b/kmod/src/extents.c @@ -153,6 +153,19 @@ int scoutfs_extent_next(struct super_block *sb, scoutfs_extent_io_t iof, return ret; } +int scoutfs_extent_prev(struct super_block *sb, scoutfs_extent_io_t iof, + struct scoutfs_extent *ext, void *data) +{ + int ret; + + scoutfs_inc_counter(sb, extent_prev); + trace_scoutfs_extent_prev_input(sb, ext); + ret = iof(sb, SEI_PREV, ext, data); + if (ret == 0) + trace_scoutfs_extent_prev_output(sb, ext); + return ret; +} + /* * Search for a next extent and see if we can merge it with the caller's * extent. The caller has initialized next for us to search from. If diff --git a/kmod/src/extents.h b/kmod/src/extents.h index d97f1f32..2cba23ab 100644 --- a/kmod/src/extents.h +++ b/kmod/src/extents.h @@ -20,6 +20,7 @@ struct scoutfs_extent { enum { SEI_NEXT, + SEI_PREV, SEI_INSERT, SEI_DELETE, }; @@ -33,6 +34,8 @@ bool scoutfs_extent_intersection(struct scoutfs_extent *a, int scoutfs_extent_next(struct super_block *sb, scoutfs_extent_io_t iof, struct scoutfs_extent *ext, void *data); +int scoutfs_extent_prev(struct super_block *sb, scoutfs_extent_io_t iof, + struct scoutfs_extent *ext, void *data); int scoutfs_extent_add(struct super_block *sb, scoutfs_extent_io_t iof, struct scoutfs_extent *add, void *data); int scoutfs_extent_remove(struct super_block *sb, scoutfs_extent_io_t iof, diff --git a/kmod/src/scoutfs_trace.h b/kmod/src/scoutfs_trace.h index b665dbab..87495177 100644 --- a/kmod/src/scoutfs_trace.h +++ b/kmod/src/scoutfs_trace.h @@ -2222,6 +2222,14 @@ DEFINE_EVENT(scoutfs_extent_class, scoutfs_extent_next_output, TP_PROTO(struct super_block *sb, struct scoutfs_extent *ext), TP_ARGS(sb, ext) ); +DEFINE_EVENT(scoutfs_extent_class, scoutfs_extent_prev_input, + TP_PROTO(struct super_block *sb, struct scoutfs_extent *ext), + TP_ARGS(sb, ext) +); +DEFINE_EVENT(scoutfs_extent_class, scoutfs_extent_prev_output, + TP_PROTO(struct super_block *sb, struct scoutfs_extent *ext), + TP_ARGS(sb, ext) +); DEFINE_EVENT(scoutfs_extent_class, scoutfs_extent_add, TP_PROTO(struct super_block *sb, struct scoutfs_extent *ext), TP_ARGS(sb, ext) diff --git a/kmod/src/server.c b/kmod/src/server.c index 1290f75b..d830d53e 100644 --- a/kmod/src/server.c +++ b/kmod/src/server.c @@ -164,9 +164,13 @@ static int server_extent_io(struct super_block *sb, int op, if (ext->type == SCOUTFS_FREE_EXTENT_BLOCKS_TYPE) swap(ebk.major, ebk.minor); - if (op == SEI_NEXT) { - ret = scoutfs_btree_next(sb, &super->alloc_root, - &ebk, sizeof(ebk), &iref); + if (op == SEI_NEXT || op == SEI_PREV) { + if (op == SEI_NEXT) + ret = scoutfs_btree_next(sb, &super->alloc_root, + &ebk, sizeof(ebk), &iref); + else + ret = scoutfs_btree_prev(sb, &super->alloc_root, + &ebk, sizeof(ebk), &iref); if (ret == 0) { ret = init_extent_from_btree_key(ext, ext->type, iref.key,