scoutfs: use single small key struct

Variable length keys lead to having a key struct point to the buffer
that contains the key.  With dirents and xattrs now using small keys we
can convert everyone to using a single key struct and significantly
simplify the system.

We no longer have a seperate generic key buf struct that points to
specific per-type key storage.  All items use the key struct and fill
out the appropriate fields.  All the code that paired a generic key buf
struct and a specific key type struct is collapsed down to a key struct.
There's no longer the difference between a key buf that shares a
read-only key, has it's own precise allocation, or has a max size
allocation for incrementing and decrementing.

Each key user now has an init function fills out its fields.  It looks a
lot like the old pattern but we no longer have seperate key storage that
the buf points to.

A bunch of code now takes the address of static key storage instead of
managing allocated keys.  Conversely, swapping now uses the full keys
instead of pointers to the keys.

We don't need all the functions that worked on the generic key buf
struct because they had different lengths.  Copy, clone, length init,
memcpy, all of that goes away.

The item API had some functions that tested the length of keys and
values.  The key length tests vanish, and that gets rid of the _same()
call.  The _same_min() call only had one user who didn't also test for
the value length being too large.  Let's leave caller key constraints in
callers instead of trying to hide them on the other side of a bunch of
item calls.

We no longer have to track the number of key bytes when calculating if
an item population will fit in segments.  This removes the key length
from reservations, transactions, and segment writing.

The item cache key querying ioctls no longer have to deal with variable
length keys.  The simply specify the start key, the ioctls return the
number of keys copied instead of bytes, and the caller is responsible
for incrementing the next search key.

The segment no longer has to store the key length.  It stores the key
struct in the item header.

The fancy variable length key formatting and printing can be removed.
We have a single format for the universal key struct.  The SK_ wrappers
that bracked calls to use preempt safe per cpu buffers can turn back
into their normal calls.

Manifest entries are now a fixed size.  We can simply split them between
btree keys and values and initialize them instead of allocating them.
This means that level 0 entries don't have their own format that sorts
by the seq.  They're sorted by the key like all the other levels.
Compaction needs to sweep all of them looking for the oldest and read
can stop sweeping once it can no longer overlap.  This makes rare
compaction more expensive and common reading less expensive, which is
the right tradeoff.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2018-04-04 09:15:27 -05:00
committed by Mark Swan
parent df6a8af71f
commit 9148f24aa2
29 changed files with 1221 additions and 2129 deletions
+4 -12
View File
@@ -589,22 +589,14 @@ int scoutfs_client_record_segment(struct super_block *sb,
struct scoutfs_segment *seg, u8 level)
{
struct client_info *client = SCOUTFS_SB(sb)->client_info;
struct scoutfs_net_manifest_entry *net_ment;
struct scoutfs_net_manifest_entry net_ment;
struct scoutfs_manifest_entry ment;
int ret;
scoutfs_seg_init_ment(&ment, level, seg);
net_ment = scoutfs_alloc_net_ment(&ment);
if (net_ment) {
ret = client_request(client, SCOUTFS_NET_RECORD_SEGMENT,
net_ment, scoutfs_net_ment_bytes(net_ment),
NULL, 0);
kfree(net_ment);
} else {
ret = -ENOMEM;
}
scoutfs_init_ment_to_net(&net_ment, &ment);
return ret;
return client_request(client, SCOUTFS_NET_RECORD_SEGMENT, &net_ment,
sizeof(net_ment), NULL, 0);
}
static int sort_cmp_u64s(const void *A, const void *B)
+13 -1
View File
@@ -1,7 +1,19 @@
#ifndef _SCOUTFS_CMP_H_
#define _SCOUTFS_CMP_H_
#include <linux/kernel.h>
/*
* A generic ternary comparison macro with strict type checking.
*/
#define scoutfs_cmp(a, b) \
({ \
__typeof__(a) _a = (a); \
__typeof__(b) _b = (b); \
int _ret; \
\
(void) (&_a == &_b); \
_ret = _a < _b ? -1 : _a > _b ? 1 : 0; \
_ret; \
})
static inline int scoutfs_cmp_u64s(u64 a, u64 b)
{
+21 -27
View File
@@ -66,8 +66,8 @@ struct compact_seg {
u64 segno;
u64 seq;
u8 level;
struct scoutfs_key_buf *first;
struct scoutfs_key_buf *last;
struct scoutfs_key first;
struct scoutfs_key last;
struct scoutfs_segment *seg;
int off;
bool part_of_move;
@@ -101,27 +101,20 @@ static void free_cseg(struct super_block *sb, struct compact_seg *cseg)
WARN_ON_ONCE(!list_empty(&cseg->entry));
scoutfs_seg_put(cseg->seg);
scoutfs_key_free(sb, cseg->first);
scoutfs_key_free(sb, cseg->last);
kfree(cseg);
}
static struct compact_seg *alloc_cseg(struct super_block *sb,
struct scoutfs_key_buf *first,
struct scoutfs_key_buf *last)
struct scoutfs_key *first,
struct scoutfs_key *last)
{
struct compact_seg *cseg;
cseg = kzalloc(sizeof(struct compact_seg), GFP_NOFS);
if (cseg) {
INIT_LIST_HEAD(&cseg->entry);
cseg->first = scoutfs_key_dup(sb, first);
cseg->last = scoutfs_key_dup(sb, last);
if (!cseg->first || !cseg->last) {
free_cseg(sb, cseg);
cseg = NULL;
}
cseg->first = *first;
cseg->last = *last;
}
return cseg;
@@ -179,12 +172,12 @@ static struct compact_seg *next_spos(struct compact_cursor *curs,
* incremental update items.
*/
static int next_item(struct super_block *sb, struct compact_cursor *curs,
struct scoutfs_key_buf *item_key, struct kvec *item_val,
struct scoutfs_key *item_key, struct kvec *item_val,
u8 *item_flags)
{
struct compact_seg *upper = curs->upper;
struct compact_seg *lower = curs->lower;
struct scoutfs_key_buf lower_key;
struct scoutfs_key lower_key;
struct kvec lower_val;
u8 lower_flags;
int cmp;
@@ -192,8 +185,8 @@ static int next_item(struct super_block *sb, struct compact_cursor *curs,
retry:
if (upper) {
ret = scoutfs_seg_item_ptrs(upper->seg, upper->off,
item_key, item_val, item_flags);
ret = scoutfs_seg_get_item(upper->seg, upper->off,
item_key, item_val, item_flags);
if (ret < 0)
upper = NULL;
}
@@ -203,9 +196,9 @@ retry:
if (ret)
goto out;
ret = scoutfs_seg_item_ptrs(lower->seg, lower->off,
&lower_key, &lower_val,
&lower_flags);
ret = scoutfs_seg_get_item(lower->seg, lower->off,
&lower_key, &lower_val,
&lower_flags);
if (ret == 0)
break;
lower = next_spos(curs, lower);
@@ -230,7 +223,7 @@ retry:
cmp = 1;
if (cmp > 0) {
scoutfs_key_clone(item_key, &lower_key);
*item_key = lower_key;
*item_val = lower_val;
*item_flags = lower_flags;
}
@@ -243,7 +236,7 @@ retry:
*/
if (curs->sticky && curs->lower &&
(!lower || lower == curs->last_lower) &&
scoutfs_key_compare(item_key, curs->last_lower->last) > 0) {
scoutfs_key_compare(item_key, &curs->last_lower->last) > 0) {
ret = 0;
goto out;
}
@@ -276,7 +269,7 @@ static int compact_segments(struct super_block *sb,
struct scoutfs_bio_completion *comp,
struct list_head *results)
{
struct scoutfs_key_buf item_key;
struct scoutfs_key item_key;
struct scoutfs_segment *seg;
struct compact_seg *cseg;
struct compact_seg *upper;
@@ -315,7 +308,7 @@ static int compact_segments(struct super_block *sb,
* entry iterator that reading and compacting
* can use.
*/
cseg = alloc_cseg(sb, upper->first, upper->last);
cseg = alloc_cseg(sb, &upper->first, &upper->last);
if (!cseg) {
ret = -ENOMEM;
break;
@@ -535,7 +528,7 @@ int scoutfs_compact_commit(struct super_block *sb, void *c, void *r)
}
scoutfs_manifest_init_entry(&ment, cseg->level, 0, cseg->seq,
cseg->first, NULL);
&cseg->first, NULL);
ret = scoutfs_manifest_del(sb, &ment);
BUG_ON(ret);
}
@@ -548,7 +541,7 @@ int scoutfs_compact_commit(struct super_block *sb, void *c, void *r)
else
scoutfs_manifest_init_entry(&ment, cseg->level,
cseg->segno, cseg->seq,
cseg->first, cseg->last);
&cseg->first, &cseg->last);
ret = scoutfs_manifest_add(sb, &ment);
BUG_ON(ret);
}
@@ -590,7 +583,8 @@ static void scoutfs_compact_func(struct work_struct *work)
/* trace compaction ranges */
list_for_each_entry(cseg, &curs.csegs, entry) {
trace_scoutfs_compact_input(sb, cseg->level, cseg->segno,
cseg->seq, cseg->first, cseg->last);
cseg->seq, &cseg->first,
&cseg->last);
}
if (ret == 0 && !list_empty(&curs.csegs)) {
+3 -20
View File
@@ -2,10 +2,8 @@
#define _SCOUTFS_COUNT_H_
/*
* Our estimate of the space consumed while dirtying items isn't a
* single value. We're packing items into segments which have different
* overheads for items (header overhead), keys (block aligned), and
* values (can span blocks, not aligned).
* Our estimate of the space consumed while dirtying items is based on
* the number of items and the size of their values.
*
* The estimate is still a read-only input to entering the transaction.
* We'd like to use it as a clean rhs arg to hold_trans. We define SIC_
@@ -21,7 +19,6 @@
struct scoutfs_item_count {
signed items;
signed keys;
signed vals;
};
@@ -33,8 +30,6 @@ static inline void __count_alloc_inode(struct scoutfs_item_count *cnt)
const int nr_indices = SCOUTFS_INODE_INDEX_NR;
cnt->items += 1 + nr_indices;
cnt->keys += sizeof(struct scoutfs_inode_key) +
(nr_indices * sizeof(struct scoutfs_inode_index_key));
cnt->vals += sizeof(struct scoutfs_inode);
}
@@ -47,8 +42,6 @@ static inline void __count_dirty_inode(struct scoutfs_item_count *cnt)
const int nr_indices = 2 * SCOUTFS_INODE_INDEX_NR;
cnt->items += 1 + nr_indices;
cnt->keys += sizeof(struct scoutfs_inode_key) +
(nr_indices * sizeof(struct scoutfs_inode_index_key));
cnt->vals += sizeof(struct scoutfs_inode);
}
@@ -77,7 +70,6 @@ static inline void __count_dirents(struct scoutfs_item_count *cnt,
unsigned name_len)
{
cnt->items += 3;
cnt->keys += 3 * sizeof(struct scoutfs_dirent_key);
cnt->vals += 3 * offsetof(struct scoutfs_dirent, name[name_len]);
}
@@ -87,7 +79,6 @@ static inline void __count_sym_target(struct scoutfs_item_count *cnt,
unsigned nr = DIV_ROUND_UP(size, SCOUTFS_MAX_VAL_SIZE);
cnt->items += nr;
cnt->keys += nr * sizeof(struct scoutfs_symlink_key);
cnt->vals += size;
}
@@ -95,7 +86,6 @@ static inline void __count_orphan(struct scoutfs_item_count *cnt)
{
cnt->items += 1;
cnt->keys += sizeof(struct scoutfs_orphan_key);
}
static inline void __count_mknod(struct scoutfs_item_count *cnt,
@@ -197,16 +187,13 @@ static inline const struct scoutfs_item_count SIC_XATTR_SET(unsigned old_parts,
__count_dirty_inode(&cnt);
if (old_parts) {
if (old_parts)
cnt.items += old_parts;
cnt.keys += old_parts * sizeof(struct scoutfs_xattr_key);
}
if (creating) {
new_parts = SCOUTFS_XATTR_NR_PARTS(name_len, size)
cnt.items += new_parts;
cnt.keys += new_parts * sizeof(struct scoutfs_xattr_key);
cnt.vals += sizeof(struct scoutfs_xattr) + name_len + size;
}
@@ -225,8 +212,6 @@ static inline const struct scoutfs_item_count SIC_WRITE_BEGIN(void)
__count_dirty_inode(&cnt);
cnt.items += 1 + nr_free;
cnt.keys += sizeof(struct scoutfs_block_mapping_key) +
(nr_free * sizeof(struct scoutfs_free_bits_key));
cnt.vals += SCOUTFS_BLOCK_MAPPING_MAX_BYTES +
(nr_free * sizeof(struct scoutfs_free_bits));
@@ -244,8 +229,6 @@ static inline const struct scoutfs_item_count SIC_TRUNC_BLOCK(void)
unsigned nr_free = (2 * SCOUTFS_BLOCK_MAPPING_BLOCKS);
cnt.items += 1 + nr_free;
cnt.keys += sizeof(struct scoutfs_block_mapping_key) +
(nr_free * sizeof(struct scoutfs_free_bits_key));
cnt.vals += SCOUTFS_BLOCK_MAPPING_MAX_BYTES +
(nr_free * sizeof(struct scoutfs_free_bits));
+50 -75
View File
@@ -319,30 +319,25 @@ static int decode_mapping(struct block_mapping *map, int size)
return 0;
}
static void init_mapping_key(struct scoutfs_key_buf *key,
struct scoutfs_block_mapping_key *bmk,
u64 ino, u64 iblock)
static void init_mapping_key(struct scoutfs_key *key, u64 ino, u64 iblock)
{
bmk->zone = SCOUTFS_FS_ZONE;
bmk->ino = cpu_to_be64(ino);
bmk->type = SCOUTFS_BLOCK_MAPPING_TYPE;
bmk->base = cpu_to_be64(iblock >> SCOUTFS_BLOCK_MAPPING_SHIFT);
scoutfs_key_init(key, bmk, sizeof(struct scoutfs_block_mapping_key));
*key = (struct scoutfs_key) {
.sk_zone = SCOUTFS_FS_ZONE,
.skm_ino = cpu_to_le64(ino),
.sk_type = SCOUTFS_BLOCK_MAPPING_TYPE,
.skm_base = cpu_to_le64(iblock >> SCOUTFS_BLOCK_MAPPING_SHIFT),
};
}
static void init_free_key(struct scoutfs_key_buf *key,
struct scoutfs_free_bits_key *fbk, u64 node_id,
u64 full_bit, u8 type)
static void init_free_key(struct scoutfs_key *key, u64 node_id, u64 full_bit,
u8 type)
{
fbk->zone = SCOUTFS_NODE_ZONE;
fbk->node_id = cpu_to_be64(node_id);
fbk->type = type;
fbk->base = cpu_to_be64(full_bit >> SCOUTFS_FREE_BITS_SHIFT);
scoutfs_key_init(key, fbk, sizeof(struct scoutfs_free_bits_key));
*key = (struct scoutfs_key) {
.sk_zone = SCOUTFS_NODE_ZONE,
.skf_node_id = cpu_to_le64(node_id),
.sk_type = type,
.skf_base = cpu_to_le64(full_bit >> SCOUTFS_FREE_BITS_SHIFT),
};
}
/*
@@ -353,15 +348,13 @@ static int set_segno_free(struct super_block *sb, u64 segno)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
struct scoutfs_free_bits_key fbk = {0,};
struct scoutfs_free_bits frb;
struct scoutfs_key_buf key;
struct scoutfs_key key;
struct kvec val;
int bit = 0;
int ret;
init_free_key(&key, &fbk, sbi->node_id, segno,
SCOUTFS_FREE_BITS_SEGNO_TYPE);
init_free_key(&key, sbi->node_id, segno, SCOUTFS_FREE_BITS_SEGNO_TYPE);
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
if (ret && ret != -ENOENT)
@@ -383,7 +376,7 @@ static int set_segno_free(struct super_block *sb, u64 segno)
ret = scoutfs_item_update(sb, &key, &val, lock);
out:
trace_scoutfs_data_set_segno_free(sb, segno, be64_to_cpu(fbk.base),
trace_scoutfs_data_set_segno_free(sb, segno, le64_to_cpu(key.skf_base),
bit, ret);
return ret;
}
@@ -394,8 +387,7 @@ out:
* need to.
*/
static int create_blkno_free(struct super_block *sb, u64 blkno,
struct scoutfs_key_buf *key,
struct scoutfs_free_bits_key *fbk)
struct scoutfs_key *key)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
@@ -403,8 +395,7 @@ static int create_blkno_free(struct super_block *sb, u64 blkno,
struct kvec val;
int bit;
init_free_key(key, fbk, sbi->node_id, blkno,
SCOUTFS_FREE_BITS_BLKNO_TYPE);
init_free_key(key, sbi->node_id, blkno, SCOUTFS_FREE_BITS_BLKNO_TYPE);
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
bit = blkno & SCOUTFS_FREE_BITS_MASK;
@@ -429,18 +420,15 @@ static int clear_segno_free(struct super_block *sb, u64 segno)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
struct scoutfs_free_bits_key b_fbk;
struct scoutfs_free_bits_key fbk;
struct scoutfs_free_bits frb;
struct scoutfs_key_buf b_key;
struct scoutfs_key_buf key;
struct scoutfs_key b_key;
struct scoutfs_key key;
struct kvec val;
u64 blkno;
int bit;
int ret;
init_free_key(&key, &fbk, sbi->node_id, segno,
SCOUTFS_FREE_BITS_SEGNO_TYPE);
init_free_key(&key, sbi->node_id, segno, SCOUTFS_FREE_BITS_SEGNO_TYPE);
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
if (ret) {
@@ -459,7 +447,7 @@ static int clear_segno_free(struct super_block *sb, u64 segno)
/* create the new blkno item, we can safely delete it */
blkno = segno << SCOUTFS_SEGMENT_BLOCK_SHIFT;
ret = create_blkno_free(sb, blkno, &b_key, &b_fbk);
ret = create_blkno_free(sb, blkno, &b_key);
if (ret)
goto out;
@@ -482,17 +470,15 @@ static int set_blkno_free(struct super_block *sb, u64 blkno)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
struct scoutfs_free_bits_key fbk;
struct scoutfs_free_bits frb;
struct scoutfs_key_buf key;
struct scoutfs_key key;
struct kvec val;
u64 segno;
int bit;
int ret;
/* get the specified item */
init_free_key(&key, &fbk, sbi->node_id, blkno,
SCOUTFS_FREE_BITS_BLKNO_TYPE);
init_free_key(&key, sbi->node_id, blkno, SCOUTFS_FREE_BITS_BLKNO_TYPE);
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
if (ret && ret != -ENOENT)
@@ -542,16 +528,14 @@ static int clear_blkno_free(struct super_block *sb, u64 blkno)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
struct scoutfs_free_bits_key fbk;
struct scoutfs_free_bits frb;
struct scoutfs_key_buf key;
struct scoutfs_key key;
struct kvec val;
int bit;
int ret;
/* get the specified item */
init_free_key(&key, &fbk, sbi->node_id, blkno,
SCOUTFS_FREE_BITS_BLKNO_TYPE);
init_free_key(&key, sbi->node_id, blkno, SCOUTFS_FREE_BITS_BLKNO_TYPE);
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
if (ret) {
@@ -607,10 +591,8 @@ int scoutfs_data_truncate_items(struct super_block *sb, struct inode *inode,
struct scoutfs_lock *lock)
{
DECLARE_DATA_INFO(sb, datinf);
struct scoutfs_key_buf last_key;
struct scoutfs_key_buf key;
struct scoutfs_block_mapping_key last_bmk;
struct scoutfs_block_mapping_key bmk;
struct scoutfs_key last_key;
struct scoutfs_key key;
struct block_mapping *map;
struct kvec val;
bool holding = false;
@@ -629,11 +611,11 @@ int scoutfs_data_truncate_items(struct super_block *sb, struct inode *inode,
if (!map)
return -ENOMEM;
init_mapping_key(&last_key, &last_bmk, ino, last);
init_mapping_key(&last_key, ino, last);
while (iblock <= last) {
/* find the mapping that could include iblock */
init_mapping_key(&key, &bmk, ino, iblock);
init_mapping_key(&key, ino, iblock);
kvec_init(&val, map->encoded, sizeof(map->encoded));
ret = scoutfs_hold_trans(sb, SIC_TRUNC_BLOCK());
@@ -655,7 +637,7 @@ int scoutfs_data_truncate_items(struct super_block *sb, struct inode *inode,
break;
/* set iblock to the first in the next item inside last */
iblock = max(iblock, be64_to_cpu(bmk.base) <<
iblock = max(iblock, le64_to_cpu(key.skm_base) <<
SCOUTFS_BLOCK_MAPPING_SHIFT);
dirtied = false;
@@ -838,15 +820,13 @@ static int find_free_blkno(struct super_block *sb, u64 blkno, u64 *blkno_ret)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
struct scoutfs_free_bits_key fbk;
struct scoutfs_free_bits frb;
struct scoutfs_key_buf key;
struct scoutfs_key key;
struct kvec val;
int ret;
int bit;
init_free_key(&key, &fbk, sbi->node_id, blkno,
SCOUTFS_FREE_BITS_BLKNO_TYPE);
init_free_key(&key, sbi->node_id, blkno, SCOUTFS_FREE_BITS_BLKNO_TYPE);
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
@@ -860,7 +840,8 @@ static int find_free_blkno(struct super_block *sb, u64 blkno, u64 *blkno_ret)
goto out;
}
*blkno_ret = (be64_to_cpu(fbk.base) << SCOUTFS_FREE_BITS_SHIFT) + bit;
*blkno_ret = (le64_to_cpu(key.skf_base) << SCOUTFS_FREE_BITS_SHIFT) +
bit;
ret = 0;
out:
return ret;
@@ -874,18 +855,15 @@ static int find_free_segno(struct super_block *sb, u64 *segno)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
struct scoutfs_free_bits_key last_fbk;
struct scoutfs_free_bits_key fbk;
struct scoutfs_free_bits frb;
struct scoutfs_key_buf last_key;
struct scoutfs_key_buf key;
struct scoutfs_key last_key;
struct scoutfs_key key;
struct kvec val;
int bit;
int ret;
init_free_key(&key, &fbk, sbi->node_id, 0,
SCOUTFS_FREE_BITS_SEGNO_TYPE);
init_free_key(&last_key, &last_fbk, sbi->node_id, ~0,
init_free_key(&key, sbi->node_id, 0, SCOUTFS_FREE_BITS_SEGNO_TYPE);
init_free_key(&last_key, sbi->node_id, U64_MAX,
SCOUTFS_FREE_BITS_SEGNO_TYPE);
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
@@ -900,7 +878,7 @@ static int find_free_segno(struct super_block *sb, u64 *segno)
goto out;
}
*segno = (be64_to_cpu(fbk.base) << SCOUTFS_FREE_BITS_SHIFT) + bit;
*segno = (le64_to_cpu(key.skf_base) << SCOUTFS_FREE_BITS_SHIFT) + bit;
ret = 0;
out:
return ret;
@@ -916,7 +894,7 @@ out:
*/
static int find_alloc_block(struct super_block *sb, struct inode *inode,
struct block_mapping *map,
struct scoutfs_key_buf *map_key,
struct scoutfs_key *map_key,
unsigned map_ind, bool map_exists,
struct scoutfs_lock *data_lock)
{
@@ -1013,8 +991,7 @@ static int scoutfs_get_block(struct inode *inode, sector_t iblock,
{
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
struct super_block *sb = inode->i_sb;
struct scoutfs_block_mapping_key bmk;
struct scoutfs_key_buf key;
struct scoutfs_key key;
struct scoutfs_lock *lock;
struct block_mapping *map;
struct kvec val;
@@ -1031,7 +1008,7 @@ static int scoutfs_get_block(struct inode *inode, sector_t iblock,
if (!map)
return -ENOMEM;
init_mapping_key(&key, &bmk, scoutfs_ino(inode), iblock);
init_mapping_key(&key, scoutfs_ino(inode), iblock);
kvec_init(&val, map->encoded, sizeof(map->encoded));
/* find the mapping item that covers the logical block */
@@ -1310,13 +1287,11 @@ int scoutfs_data_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
{
struct super_block *sb = inode->i_sb;
const u64 ino = scoutfs_ino(inode);
struct scoutfs_key_buf last_key;
struct scoutfs_key_buf key;
struct scoutfs_key last_key;
struct scoutfs_key key;
struct scoutfs_lock *inode_lock = NULL;
struct block_mapping *map;
struct pending_fiemap pend;
struct scoutfs_block_mapping_key last_bmk;
struct scoutfs_block_mapping_key bmk;
struct kvec val;
loff_t i_size;
bool offline;
@@ -1351,14 +1326,14 @@ int scoutfs_data_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
blk_off = start >> SCOUTFS_BLOCK_SHIFT;
final = min_t(loff_t, i_size - 1, start + len - 1) >>
SCOUTFS_BLOCK_SHIFT;
init_mapping_key(&last_key, &last_bmk, ino, final);
init_mapping_key(&last_key, ino, final);
ret = scoutfs_lock_inode(sb, DLM_LOCK_PR, 0, inode, &inode_lock);
if (ret)
goto out;
while (blk_off <= final) {
init_mapping_key(&key, &bmk, ino, blk_off);
init_mapping_key(&key, ino, blk_off);
kvec_init(&val, &map->encoded, sizeof(map->encoded));
ret = scoutfs_item_next(sb, &key, &last_key, &val, inode_lock);
@@ -1373,7 +1348,7 @@ int scoutfs_data_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
break;
/* set blk_off to the first in the next item inside last */
blk_off = max(blk_off, be64_to_cpu(bmk.base) <<
blk_off = max(blk_off, le64_to_cpu(key.skm_base) <<
SCOUTFS_BLOCK_MAPPING_SHIFT);
for_each_block(i, blk_off, final) {
+59 -78
View File
@@ -191,17 +191,16 @@ static u64 dentry_info_pos(struct dentry *dentry)
return di->pos;
}
static void init_dirent_key(struct scoutfs_key_buf *key,
struct scoutfs_dirent_key *dkey, u8 type,
u64 ino, u64 major, u64 minor)
static void init_dirent_key(struct scoutfs_key *key, u8 type, u64 ino,
u64 major, u64 minor)
{
dkey->zone = SCOUTFS_FS_ZONE;
dkey->ino = cpu_to_be64(ino);
dkey->type = type;
dkey->major = cpu_to_be64(major);
dkey->minor = cpu_to_be64(minor);
scoutfs_key_init(key, dkey, sizeof(struct scoutfs_dirent_key));
*key = (struct scoutfs_key) {
.sk_zone = SCOUTFS_FS_ZONE,
.skd_ino = cpu_to_le64(ino),
.sk_type = type,
.skd_major = cpu_to_le64(major),
.skd_minor = cpu_to_le64(minor),
};
}
static unsigned int dirent_bytes(unsigned int name_len)
@@ -237,10 +236,8 @@ static int lookup_dirent(struct super_block *sb, u64 dir_ino, const char *name,
struct scoutfs_dirent *dent_ret,
struct scoutfs_lock *lock)
{
struct scoutfs_dirent_key last_dkey;
struct scoutfs_dirent_key dkey;
struct scoutfs_key_buf last_key;
struct scoutfs_key_buf key;
struct scoutfs_key last_key;
struct scoutfs_key key;
struct scoutfs_dirent *dent = NULL;
struct kvec val;
int ret;
@@ -251,10 +248,8 @@ static int lookup_dirent(struct super_block *sb, u64 dir_ino, const char *name,
goto out;
}
init_dirent_key(&key, &dkey, SCOUTFS_DIRENT_TYPE,
dir_ino, hash, 0);
init_dirent_key(&last_key, &last_dkey, SCOUTFS_DIRENT_TYPE,
dir_ino, hash, U64_MAX);
init_dirent_key(&key, SCOUTFS_DIRENT_TYPE, dir_ino, hash, 0);
init_dirent_key(&last_key, SCOUTFS_DIRENT_TYPE, dir_ino, hash, U64_MAX);
kvec_init(&val, dent, dirent_bytes(SCOUTFS_NAME_LEN));
for (;;) {
@@ -275,11 +270,11 @@ static int lookup_dirent(struct super_block *sb, u64 dir_ino, const char *name,
break;
}
if (be64_to_cpu(dkey.minor) == U64_MAX) {
if (le64_to_cpu(key.skd_minor) == U64_MAX) {
ret = -ENOENT;
break;
}
be64_add_cpu(&dkey.minor, 1);
le64_add_cpu(&key.skd_minor, 1);
}
out:
@@ -472,13 +467,11 @@ static int scoutfs_readdir(struct file *file, void *dirent, filldir_t filldir)
struct inode *inode = file_inode(file);
struct super_block *sb = inode->i_sb;
struct scoutfs_dirent *dent;
struct scoutfs_key_buf key;
struct scoutfs_key_buf last_key;
struct scoutfs_dirent_key dkey;
struct scoutfs_dirent_key last_dkey;
struct scoutfs_key key;
struct scoutfs_key last_key;
struct scoutfs_lock *dir_lock;
unsigned int name_len;
struct kvec val;
int name_len;
u64 pos;
int ret;
@@ -491,8 +484,8 @@ static int scoutfs_readdir(struct file *file, void *dirent, filldir_t filldir)
goto out;
}
init_dirent_key(&last_key, &last_dkey, SCOUTFS_READDIR_TYPE,
scoutfs_ino(inode), SCOUTFS_DIRENT_LAST_POS, 0);
init_dirent_key(&last_key, SCOUTFS_READDIR_TYPE, scoutfs_ino(inode),
SCOUTFS_DIRENT_LAST_POS, 0);
kvec_init(&val, dent, dirent_bytes(SCOUTFS_NAME_LEN));
ret = scoutfs_lock_inode(sb, DLM_LOCK_PR, 0, inode, &dir_lock);
@@ -500,11 +493,10 @@ static int scoutfs_readdir(struct file *file, void *dirent, filldir_t filldir)
goto out;
for (;;) {
init_dirent_key(&key, &dkey, SCOUTFS_READDIR_TYPE,
scoutfs_ino(inode), file->f_pos, 0);
init_dirent_key(&key, SCOUTFS_READDIR_TYPE, scoutfs_ino(inode),
file->f_pos, 0);
ret = scoutfs_item_next_same_min(sb, &key, &last_key, &val,
dirent_bytes(1), dir_lock);
ret = scoutfs_item_next(sb, &key, &last_key, &val, dir_lock);
if (ret < 0) {
if (ret == -ENOENT)
ret = 0;
@@ -512,7 +504,13 @@ static int scoutfs_readdir(struct file *file, void *dirent, filldir_t filldir)
}
name_len = ret - sizeof(struct scoutfs_dirent);
pos = be64_to_cpu(dkey.major);
/* XXX corruption */
if (name_len < 1 || name_len > SCOUTFS_NAME_LEN) {
ret = -EIO;
goto out;
}
pos = le64_to_cpu(key.skd_major);
if (filldir(dirent, dent->name, name_len, pos,
le64_to_cpu(dent->ino), dentry_type(dent->type))) {
@@ -542,12 +540,9 @@ static int add_entry_items(struct super_block *sb, u64 dir_ino, u64 hash,
u64 ino, umode_t mode, struct scoutfs_lock *dir_lock,
struct scoutfs_lock *inode_lock)
{
struct scoutfs_dirent_key rdir_dkey;
struct scoutfs_dirent_key ent_dkey;
struct scoutfs_dirent_key lb_dkey;
struct scoutfs_key_buf rdir_key;
struct scoutfs_key_buf ent_key;
struct scoutfs_key_buf lb_key;
struct scoutfs_key rdir_key;
struct scoutfs_key ent_key;
struct scoutfs_key lb_key;
struct scoutfs_dirent *dent;
bool del_ent = false;
bool del_rdir = false;
@@ -567,12 +562,9 @@ static int add_entry_items(struct super_block *sb, u64 dir_ino, u64 hash,
dent->type = mode_to_type(mode);
memcpy(dent->name, name, name_len);
init_dirent_key(&ent_key, &ent_dkey, SCOUTFS_DIRENT_TYPE,
dir_ino, hash, pos);
init_dirent_key(&rdir_key, &rdir_dkey, SCOUTFS_READDIR_TYPE,
dir_ino, pos, 0);
init_dirent_key(&lb_key, &lb_dkey, SCOUTFS_LINK_BACKREF_TYPE,
ino, dir_ino, pos);
init_dirent_key(&ent_key, SCOUTFS_DIRENT_TYPE, dir_ino, hash, pos);
init_dirent_key(&rdir_key, SCOUTFS_READDIR_TYPE, dir_ino, pos, 0);
init_dirent_key(&lb_key, SCOUTFS_LINK_BACKREF_TYPE, ino, dir_ino, pos);
kvec_init(&val, dent, dirent_bytes(name_len));
ret = scoutfs_item_create(sb, &ent_key, &val, dir_lock);
@@ -610,22 +602,16 @@ static int del_entry_items(struct super_block *sb, u64 dir_ino, u64 hash,
u64 pos, u64 ino, struct scoutfs_lock *dir_lock,
struct scoutfs_lock *inode_lock)
{
struct scoutfs_dirent_key rdir_dkey;
struct scoutfs_dirent_key ent_dkey;
struct scoutfs_dirent_key lb_dkey;
struct scoutfs_key_buf rdir_key;
struct scoutfs_key_buf ent_key;
struct scoutfs_key_buf lb_key;
struct scoutfs_key rdir_key;
struct scoutfs_key ent_key;
struct scoutfs_key lb_key;
LIST_HEAD(dir_saved);
LIST_HEAD(inode_saved);
int ret;
init_dirent_key(&ent_key, &ent_dkey, SCOUTFS_DIRENT_TYPE,
dir_ino, hash, pos);
init_dirent_key(&rdir_key, &rdir_dkey, SCOUTFS_READDIR_TYPE,
dir_ino, pos, 0);
init_dirent_key(&lb_key, &lb_dkey, SCOUTFS_LINK_BACKREF_TYPE,
ino, dir_ino, pos);
init_dirent_key(&ent_key, SCOUTFS_DIRENT_TYPE, dir_ino, hash, pos);
init_dirent_key(&rdir_key, SCOUTFS_READDIR_TYPE, dir_ino, pos, 0);
init_dirent_key(&lb_key, SCOUTFS_LINK_BACKREF_TYPE, ino, dir_ino, pos);
ret = scoutfs_item_delete_save(sb, &ent_key, &dir_saved, dir_lock) ?:
scoutfs_item_delete_save(sb, &rdir_key, &dir_saved, dir_lock) ?:
@@ -959,15 +945,14 @@ unlock:
return ret;
}
static void init_symlink_key(struct scoutfs_key_buf *key,
struct scoutfs_symlink_key *skey, u64 ino, u8 nr)
static void init_symlink_key(struct scoutfs_key *key, u64 ino, u8 nr)
{
skey->zone = SCOUTFS_FS_ZONE;
skey->ino = cpu_to_be64(ino);
skey->type = SCOUTFS_SYMLINK_TYPE;
skey->nr = nr;
scoutfs_key_init(key, skey, sizeof(struct scoutfs_symlink_key));
*key = (struct scoutfs_key) {
.sk_zone = SCOUTFS_FS_ZONE,
.sks_ino = cpu_to_le64(ino),
.sk_type = SCOUTFS_SYMLINK_TYPE,
.sks_nr = cpu_to_le64(nr),
};
}
/*
@@ -991,8 +976,7 @@ static int symlink_item_ops(struct super_block *sb, int op, u64 ino,
struct scoutfs_lock *lock, const char *target,
size_t size)
{
struct scoutfs_symlink_key skey;
struct scoutfs_key_buf key;
struct scoutfs_key key;
struct kvec val;
unsigned bytes;
unsigned nr;
@@ -1006,7 +990,7 @@ static int symlink_item_ops(struct super_block *sb, int op, u64 ino,
nr = DIV_ROUND_UP(size, SCOUTFS_MAX_VAL_SIZE);
for (i = 0; i < nr; i++) {
init_symlink_key(&key, &skey, ino, i);
init_symlink_key(&key, ino, i);
bytes = min_t(u64, size, SCOUTFS_MAX_VAL_SIZE);
kvec_init(&val, (void *)target, bytes);
@@ -1213,10 +1197,8 @@ int scoutfs_dir_add_next_linkref(struct super_block *sb, u64 ino,
struct list_head *list)
{
struct scoutfs_link_backref_entry *ent;
struct scoutfs_dirent_key last_dkey;
struct scoutfs_dirent_key dkey;
struct scoutfs_key_buf last_key;
struct scoutfs_key_buf key;
struct scoutfs_key last_key;
struct scoutfs_key key;
struct scoutfs_lock *lock = NULL;
struct kvec val;
int len;
@@ -1229,10 +1211,9 @@ int scoutfs_dir_add_next_linkref(struct super_block *sb, u64 ino,
INIT_LIST_HEAD(&ent->head);
init_dirent_key(&key, &dkey, SCOUTFS_LINK_BACKREF_TYPE,
ino, dir_ino, dir_pos);
init_dirent_key(&last_key, &last_dkey, SCOUTFS_LINK_BACKREF_TYPE,
ino, U64_MAX, U64_MAX);
init_dirent_key(&key, SCOUTFS_LINK_BACKREF_TYPE, ino, dir_ino, dir_pos);
init_dirent_key(&last_key, SCOUTFS_LINK_BACKREF_TYPE, ino, U64_MAX,
U64_MAX);
kvec_init(&val, &ent->dent, dirent_bytes(SCOUTFS_NAME_LEN));
ret = scoutfs_lock_ino(sb, DLM_LOCK_PR, 0, ino, &lock);
@@ -1243,7 +1224,7 @@ int scoutfs_dir_add_next_linkref(struct super_block *sb, u64 ino,
scoutfs_unlock(sb, lock, DLM_LOCK_PR);
lock = NULL;
trace_scoutfs_dir_add_next_linkref(sb, ino, dir_ino, ret, key.key_len);
trace_scoutfs_dir_add_next_linkref(sb, ino, dir_ino, dir_pos, ret);
if (ret < 0)
goto out;
@@ -1255,8 +1236,8 @@ int scoutfs_dir_add_next_linkref(struct super_block *sb, u64 ino,
}
list_add(&ent->head, list);
ent->dir_ino = be64_to_cpu(dkey.major);
ent->dir_pos = be64_to_cpu(dkey.minor);
ent->dir_ino = le64_to_cpu(key.skd_major);
ent->dir_pos = le64_to_cpu(key.skd_minor);
ent->name_len = len;
ret = 0;
out:
+83 -93
View File
@@ -52,6 +52,75 @@ struct scoutfs_block_header {
__le64 blkno;
} __packed;
/*
* scoutfs identifies all file system metadata items by a small key
* struct.
*
* Each item type maps their logical structures to the fixed fields in
* sort order. This lets us print keys without needing per-type
* formats.
*
* The keys are compared by considering the fields in struct order from
* most to least significant. They are considered a multi precision
* value when navigating the keys in ordered key space. We can
* increment them, subtract them from each other, etc.
*/
struct scoutfs_key {
__u8 sk_zone;
__le64 _sk_first;
__u8 sk_type;
__le64 _sk_second;
__le64 _sk_third;
__u8 _sk_fourth;
}__packed;
/* inode index */
#define skii_major _sk_second
#define skii_ino _sk_third
/* node free bit map */
#define skf_node_id _sk_first
#define skf_base _sk_second
/* node orphan inode */
#define sko_node_id _sk_first
#define sko_ino _sk_second
/* inode */
#define ski_ino _sk_first
/* xattr parts */
#define skx_ino _sk_first
#define skx_name_hash _sk_second
#define skx_id _sk_third
#define skx_part _sk_fourth
/* directory entries */
#define skd_ino _sk_first
#define skd_major _sk_second
#define skd_minor _sk_third
/* symlink target */
#define sks_ino _sk_first
#define sks_nr _sk_second
/* file data mapping */
#define skm_ino _sk_first
#define skm_base _sk_second
/*
* The btree still uses memcmp() to compare keys. We should fix that
* before too long.
*/
struct scoutfs_key_be {
__u8 sk_zone;
__be64 _sk_first;
__u8 sk_type;
__be64 _sk_second;
__be64 _sk_third;
__u8 _sk_fourth;
}__packed;
/*
* Assert that we'll be able to represent all possible keys with 8 64bit
* primary sort values.
@@ -143,34 +212,24 @@ struct scoutfs_manifest {
} __packed;
/*
* Manifest entries are packed into btree keys and values in a very
* fiddly way so that we can sort them with memcmp first by level then
* by their position in the level. First comes the level.
* Manifest entries are split across btree keys and values. Putting
* some entry fields in the value keeps the key smaller and increases
* the fanout of the btree which keeps the tree smaller and reduces
* block IO.
*
* Level 0 segments are sorted by their seq so they don't have the first
* segment key in the manifest btree key. Both of their keys are in the
* value.
*
* Level 1 segments are sorted by their first key so their last key is
* in the value.
*
* We go to all this trouble so that we can communicate a version of the
* manifest with one btree root, have dense btree keys which are used as
* seperators in parent blocks, and don't duplicate the large keys in
* the manifest btree key and value.
* The key is made up of the level, first key, and seq. At level 0
* segments can completely overlap and have identical key ranges but we
* avoid duplicate btree keys by including the unique seq.
*/
struct scoutfs_manifest_btree_key {
__u8 level;
__u8 bkey[0];
struct scoutfs_key_be first_key;
__be64 seq;
} __packed;
struct scoutfs_manifest_btree_val {
__le64 segno;
__le64 seq;
__le16 first_key_len;
__le16 last_key_len;
__u8 keys[0];
struct scoutfs_key last_key;
} __packed;
#define SCOUTFS_ALLOC_REGION_SHIFT 8
@@ -201,15 +260,12 @@ struct scoutfs_alloc_region_btree_val {
* They're not allowed to cross a block boundary.
*/
struct scoutfs_segment_item {
__le16 key_len;
struct scoutfs_key key;
__le16 val_len;
__u8 flags;
__u8 nr_links;
__le32 skip_links[0];
/*
* __u8 key_bytes[key_len]
* __u8 val_bytes[val_len]
*/
/* __u8 val_bytes[val_len] */
} __packed;
#define SCOUTFS_ITEM_FLAG_DELETION (1 << 0)
@@ -259,30 +315,6 @@ struct scoutfs_segment_block {
#define SCOUTFS_MAX_TYPE 16 /* power of 2 is efficient */
/* value is struct scoutfs_inode */
struct scoutfs_inode_key {
__u8 zone;
__be64 ino;
__u8 type;
} __packed;
/* value is struct scoutfs_dirent with the name */
struct scoutfs_dirent_key {
__u8 zone;
__be64 ino;
__u8 type;
__be64 major;
__be64 minor;
} __packed;
/* key is bytes of encoded block mapping */
struct scoutfs_block_mapping_key {
__u8 zone;
__be64 ino;
__u8 type;
__be64 base;
} __packed;
/* each mapping item describes a fixed number of blocks */
#define SCOUTFS_BLOCK_MAPPING_SHIFT 6
#define SCOUTFS_BLOCK_MAPPING_BLOCKS (1 << SCOUTFS_BLOCK_MAPPING_SHIFT)
@@ -328,33 +360,10 @@ struct scoutfs_block_mapping_key {
#define SCOUTFS_FREE_BITS_U64S \
DIV_ROUND_UP(SCOUTFS_FREE_BITS_BITS, 64)
struct scoutfs_free_bits_key {
__u8 zone;
__be64 node_id;
__u8 type;
__be64 base;
} __packed;
struct scoutfs_free_bits {
__le64 bits[SCOUTFS_FREE_BITS_U64S];
} __packed;
struct scoutfs_orphan_key {
__u8 zone;
__be64 node_id;
__u8 type;
__be64 ino;
} __packed;
struct scoutfs_xattr_key {
__u8 zone;
__be64 ino;
__u8 type;
__be32 name_hash;
__be64 id;
__u8 part;
} __packed;
/*
* The first xattr part item has a header that describes the xattr. The
* name and value are then packed into the following bytes in the first
@@ -366,27 +375,11 @@ struct scoutfs_xattr {
__u8 name[0];
} __packed;
/* size determines nr needed to store full target path in their values */
struct scoutfs_symlink_key {
__u8 zone;
__be64 ino;
__u8 type;
__u8 nr;
} __packed;
struct scoutfs_betimespec {
__be64 sec;
__be32 nsec;
} __packed;
struct scoutfs_inode_index_key {
__u8 zone;
__u8 type;
__be64 major;
__be32 minor;
__be64 ino;
} __packed;
/* XXX does this exist upstream somewhere? */
#define member_sizeof(TYPE, MEMBER) (sizeof(((TYPE *)0)->MEMBER))
@@ -514,9 +507,6 @@ enum {
SCOUTFS_DT_WHT,
};
#define SCOUTFS_MAX_KEY_SIZE \
sizeof(struct scoutfs_dirent_key)
#define SCOUTFS_MAX_VAL_SIZE SCOUTFS_BLOCK_MAPPING_MAX_BYTES
#define SCOUTFS_XATTR_MAX_NAME_LEN 255
@@ -591,8 +581,8 @@ struct scoutfs_net_key_range {
struct scoutfs_net_manifest_entry {
__le64 segno;
__le64 seq;
__le16 first_key_len;
__le16 last_key_len;
struct scoutfs_key first;
struct scoutfs_key last;
__u8 level;
__u8 keys[0];
} __packed;
+63 -76
View File
@@ -247,6 +247,15 @@ static void load_inode(struct inode *inode, struct scoutfs_inode *cinode)
set_item_info(ci, cinode);
}
static void init_inode_key(struct scoutfs_key *key, u64 ino)
{
*key = (struct scoutfs_key) {
.sk_zone = SCOUTFS_FS_ZONE,
.ski_ino = cpu_to_le64(ino),
.sk_type = SCOUTFS_INODE_TYPE,
};
}
/*
* Refresh the vfs inode fields if the lock indicates that the current
* contents could be stale.
@@ -263,8 +272,7 @@ int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock,
{
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
struct super_block *sb = inode->i_sb;
struct scoutfs_key_buf key;
struct scoutfs_inode_key ikey;
struct scoutfs_key key;
struct scoutfs_inode sinode;
struct kvec val;
const u64 refresh_gen = lock->refresh_gen;
@@ -281,7 +289,7 @@ int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock,
if (atomic64_read(&si->last_refreshed) == refresh_gen)
return 0;
scoutfs_inode_init_key(&key, &ikey, scoutfs_ino(inode));
init_inode_key(&key, scoutfs_ino(inode));
kvec_init(&val, &sinode, sizeof(sinode));
mutex_lock(&si->item_mutex);
@@ -299,16 +307,6 @@ int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock,
return ret;
}
void scoutfs_inode_init_key(struct scoutfs_key_buf *key,
struct scoutfs_inode_key *ikey, u64 ino)
{
ikey->zone = SCOUTFS_FS_ZONE;
ikey->ino = cpu_to_be64(ino);
ikey->type = SCOUTFS_INODE_TYPE;
scoutfs_key_init(key, ikey, sizeof(struct scoutfs_inode_key));
}
int scoutfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
struct kstat *stat)
{
@@ -694,14 +692,13 @@ static void store_inode(struct scoutfs_inode *cinode, struct inode *inode)
int scoutfs_dirty_inode_item(struct inode *inode, struct scoutfs_lock *lock)
{
struct super_block *sb = inode->i_sb;
struct scoutfs_inode_key ikey;
struct scoutfs_key_buf key;
struct scoutfs_key key;
struct scoutfs_inode sinode;
int ret;
store_inode(&sinode, inode);
scoutfs_inode_init_key(&key, &ikey, scoutfs_ino(inode));
init_inode_key(&key, scoutfs_ino(inode));
ret = scoutfs_item_dirty(sb, &key, lock);
if (!ret)
@@ -759,13 +756,13 @@ static int cmp_index_lock(void *priv, struct list_head *A, struct list_head *B)
static void clamp_inode_index(u8 type, u64 *major, u32 *minor, u64 *ino)
{
struct scoutfs_inode_index_key start;
struct scoutfs_key start;
scoutfs_lock_get_index_item_range(type, *major, *ino, &start, NULL);
*major = be64_to_cpu(start.major);
*minor = be32_to_cpu(start.minor);
*ino = be64_to_cpu(start.ino);
*major = le64_to_cpu(start.skii_major);
*minor = 0;
*ino = le64_to_cpu(start.skii_ino);
}
/*
@@ -799,6 +796,17 @@ static struct scoutfs_lock *find_index_lock(struct list_head *lock_list,
return NULL;
}
void scoutfs_inode_init_index_key(struct scoutfs_key *key, u8 type, u64 major,
u32 minor, u64 ino)
{
*key = (struct scoutfs_key) {
.sk_zone = SCOUTFS_INODE_INDEX_ZONE,
.sk_type = type,
.skii_major = cpu_to_le64(major),
.skii_ino = cpu_to_le64(ino),
};
}
/*
* The inode info reflects the current inode index items. Create or delete
* index items to bring the index in line with the caller's item. The list
@@ -809,12 +817,10 @@ static int update_index_items(struct super_block *sb,
u64 major, u32 minor,
struct list_head *lock_list)
{
struct scoutfs_inode_index_key ins_ikey;
struct scoutfs_inode_index_key del_ikey;
struct scoutfs_lock *ins_lock;
struct scoutfs_lock *del_lock;
struct scoutfs_key_buf ins;
struct scoutfs_key_buf del;
struct scoutfs_key ins;
struct scoutfs_key del;
int ret;
int err;
@@ -823,12 +829,7 @@ static int update_index_items(struct super_block *sb,
trace_scoutfs_create_index_item(sb, type, major, minor, ino);
ins_ikey.zone = SCOUTFS_INODE_INDEX_ZONE;
ins_ikey.type = type;
ins_ikey.major = cpu_to_be64(major);
ins_ikey.minor = cpu_to_be32(minor);
ins_ikey.ino = cpu_to_be64(ino);
scoutfs_key_init(&ins, &ins_ikey, sizeof(ins_ikey));
scoutfs_inode_init_index_key(&ins, type, major, minor, ino);
ins_lock = find_index_lock(lock_list, type, major, minor, ino);
ret = scoutfs_item_create_force(sb, &ins, NULL, ins_lock);
@@ -838,12 +839,8 @@ static int update_index_items(struct super_block *sb,
trace_scoutfs_delete_index_item(sb, type, si->item_majors[type],
si->item_minors[type], ino);
del_ikey.zone = SCOUTFS_INODE_INDEX_ZONE;
del_ikey.type = type;
del_ikey.major = cpu_to_be64(si->item_majors[type]);
del_ikey.minor = cpu_to_be32(si->item_minors[type]);
del_ikey.ino = cpu_to_be64(ino);
scoutfs_key_init(&del, &del_ikey, sizeof(del_ikey));
scoutfs_inode_init_index_key(&del, type, si->item_majors[type],
si->item_minors[type], ino);
del_lock = find_index_lock(lock_list, type, si->item_majors[type],
si->item_minors[type], ino);
@@ -906,8 +903,7 @@ void scoutfs_update_inode_item(struct inode *inode, struct scoutfs_lock *lock,
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
struct super_block *sb = inode->i_sb;
const u64 ino = scoutfs_ino(inode);
struct scoutfs_inode_key ikey;
struct scoutfs_key_buf key;
struct scoutfs_key key;
struct scoutfs_inode sinode;
struct kvec val;
int ret;
@@ -924,7 +920,7 @@ void scoutfs_update_inode_item(struct inode *inode, struct scoutfs_lock *lock,
ret = update_indices(sb, si, ino, inode->i_mode, &sinode, lock_list);
BUG_ON(ret);
scoutfs_inode_init_key(&key, &ikey, ino);
init_inode_key(&key, ino);
kvec_init(&val, &sinode, sizeof(sinode));
err = scoutfs_item_update(sb, &key, &val, lock);
@@ -1195,17 +1191,11 @@ void scoutfs_inode_index_unlock(struct super_block *sb, struct list_head *list)
static int remove_index(struct super_block *sb, u64 ino, u8 type, u64 major,
u32 minor, struct list_head *ind_locks)
{
struct scoutfs_inode_index_key ikey;
struct scoutfs_key_buf key;
struct scoutfs_key key;
struct scoutfs_lock *lock;
int ret;
ikey.zone = SCOUTFS_INODE_INDEX_ZONE;
ikey.type = type;
ikey.major = cpu_to_be64(major);
ikey.minor = cpu_to_be32(minor);
ikey.ino = cpu_to_be64(ino);
scoutfs_key_init(&key, &ikey, sizeof(ikey));
scoutfs_inode_init_index_key(&key, type, major, minor, ino);
lock = find_index_lock(ind_locks, type, major, minor, ino);
ret = scoutfs_item_delete_force(sb, &key, lock);
@@ -1311,8 +1301,7 @@ struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir,
struct scoutfs_lock *lock)
{
struct scoutfs_inode_info *ci;
struct scoutfs_inode_key ikey;
struct scoutfs_key_buf key;
struct scoutfs_key key;
struct scoutfs_inode sinode;
struct inode *inode;
struct kvec val;
@@ -1346,7 +1335,7 @@ struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir,
set_inode_ops(inode);
store_inode(&sinode, inode);
scoutfs_inode_init_key(&key, &ikey, scoutfs_ino(inode));
init_inode_key(&key, scoutfs_ino(inode));
kvec_init(&val, &sinode, sizeof(sinode));
ret = scoutfs_item_create(sb, &key, &val, lock);
@@ -1358,26 +1347,24 @@ struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir,
return inode;
}
static void init_orphan_key(struct scoutfs_key_buf *key,
struct scoutfs_orphan_key *okey, u64 node_id, u64 ino)
static void init_orphan_key(struct scoutfs_key *key, u64 node_id, u64 ino)
{
okey->zone = SCOUTFS_NODE_ZONE;
okey->node_id = cpu_to_be64(node_id);
okey->type = SCOUTFS_ORPHAN_TYPE;
okey->ino = cpu_to_be64(ino);
scoutfs_key_init(key, okey, sizeof(struct scoutfs_orphan_key));
*key = (struct scoutfs_key) {
.sk_zone = SCOUTFS_NODE_ZONE,
.sko_node_id = cpu_to_le64(node_id),
.sk_type = SCOUTFS_ORPHAN_TYPE,
.sko_ino = cpu_to_le64(ino),
};
}
static int remove_orphan_item(struct super_block *sb, u64 ino)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
struct scoutfs_orphan_key okey;
struct scoutfs_key_buf key;
struct scoutfs_key key;
int ret;
init_orphan_key(&key, &okey, sbi->node_id, ino);
init_orphan_key(&key, sbi->node_id, ino);
ret = scoutfs_item_delete(sb, &key, lock);
if (ret == -ENOENT)
@@ -1397,9 +1384,8 @@ static int remove_orphan_item(struct super_block *sb, u64 ino)
static int delete_inode_items(struct super_block *sb, u64 ino)
{
struct scoutfs_lock *lock = NULL;
struct scoutfs_inode_key ikey;
struct scoutfs_inode sinode;
struct scoutfs_key_buf key;
struct scoutfs_key key;
LIST_HEAD(ind_locks);
bool release = false;
struct kvec val;
@@ -1411,7 +1397,7 @@ static int delete_inode_items(struct super_block *sb, u64 ino)
if (ret)
return ret;
scoutfs_inode_init_key(&key, &ikey, ino);
init_inode_key(&key, ino);
kvec_init(&val, &sinode, sizeof(sinode));
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
@@ -1520,30 +1506,32 @@ int scoutfs_scan_orphans(struct super_block *sb)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
struct scoutfs_orphan_key okey;
struct scoutfs_orphan_key last_okey;
struct scoutfs_key_buf key;
struct scoutfs_key_buf last;
struct scoutfs_key key;
struct scoutfs_key last;
int err = 0;
int ret;
trace_scoutfs_scan_orphans(sb);
init_orphan_key(&key, &okey, sbi->node_id, 0);
init_orphan_key(&last, &last_okey, sbi->node_id, ~0ULL);
init_orphan_key(&key, sbi->node_id, 0);
init_orphan_key(&last, sbi->node_id, ~0ULL);
while (1) {
ret = scoutfs_item_next_same(sb, &key, &last, NULL, lock);
ret = scoutfs_item_next(sb, &key, &last, NULL, lock);
if (ret == -ENOENT) /* No more orphan items */
break;
if (ret < 0)
goto out;
ret = delete_inode_items(sb, be64_to_cpu(okey.ino));
ret = delete_inode_items(sb, le64_to_cpu(key.sko_ino));
if (ret && ret != -ENOENT && !err)
err = ret;
scoutfs_key_inc_cur_len(&key);
if (le64_to_cpu(key.sko_ino) == U64_MAX) {
ret = -ENOENT;
break;
}
le64_add_cpu(&key.sko_ino, 1);
}
ret = 0;
@@ -1556,13 +1544,12 @@ int scoutfs_orphan_inode(struct inode *inode)
struct super_block *sb = inode->i_sb;
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
struct scoutfs_orphan_key okey;
struct scoutfs_key_buf key;
struct scoutfs_key key;
int ret;
trace_scoutfs_orphan_inode(sb, inode);
init_orphan_key(&key, &okey, sbi->node_id, scoutfs_ino(inode));
init_orphan_key(&key, sbi->node_id, scoutfs_ino(inode));
ret = scoutfs_item_create(sb, &key, NULL, lock);
+3 -3
View File
@@ -5,6 +5,7 @@
#include "lock.h"
#include "per_task.h"
#include "count.h"
#include "format.h"
struct scoutfs_lock;
@@ -62,9 +63,6 @@ static inline u64 scoutfs_ino(struct inode *inode)
return SCOUTFS_I(inode)->ino;
}
void scoutfs_inode_init_key(struct scoutfs_key_buf *key,
struct scoutfs_inode_key *ikey, u64 ino);
struct inode *scoutfs_alloc_inode(struct super_block *sb);
void scoutfs_destroy_inode(struct inode *inode);
int scoutfs_drop_inode(struct inode *inode);
@@ -74,6 +72,8 @@ int scoutfs_orphan_inode(struct inode *inode);
struct inode *scoutfs_iget(struct super_block *sb, u64 ino);
struct inode *scoutfs_ilookup(struct super_block *sb, u64 ino);
void scoutfs_inode_init_index_key(struct scoutfs_key *key, u8 type, u64 major,
u32 minor, u64 ino);
int scoutfs_inode_index_start(struct super_block *sb, u64 *seq);
int scoutfs_inode_index_prepare(struct super_block *sb, struct list_head *list,
struct inode *inode, bool set_data_seq);
+44 -85
View File
@@ -55,11 +55,9 @@ static long scoutfs_ioc_walk_inodes(struct file *file, unsigned long arg)
struct scoutfs_ioctl_walk_inodes __user *uwalk = (void __user *)arg;
struct scoutfs_ioctl_walk_inodes walk;
struct scoutfs_ioctl_walk_inodes_entry ent;
struct scoutfs_inode_index_key last_ikey;
struct scoutfs_inode_index_key ikey;
struct scoutfs_key_buf *next_key;
struct scoutfs_key_buf last_key;
struct scoutfs_key_buf key;
struct scoutfs_key next_key;
struct scoutfs_key last_key;
struct scoutfs_key key;
struct scoutfs_lock *lock;
u64 last_seq;
int ret = 0;
@@ -93,23 +91,10 @@ static long scoutfs_ioc_walk_inodes(struct file *file, unsigned long arg)
}
}
next_key = scoutfs_key_alloc(sb, SCOUTFS_MAX_KEY_SIZE);
if (!next_key)
return -ENOMEM;
ikey.zone = SCOUTFS_INODE_INDEX_ZONE;
ikey.type = type;
ikey.major = cpu_to_be64(walk.first.major);
ikey.minor = cpu_to_be32(walk.first.minor);
ikey.ino = cpu_to_be64(walk.first.ino);
scoutfs_key_init(&key, &ikey, sizeof(ikey));
last_ikey.zone = ikey.zone;
last_ikey.type = ikey.type;
last_ikey.major = cpu_to_be64(walk.last.major);
last_ikey.minor = cpu_to_be32(walk.last.minor);
last_ikey.ino = cpu_to_be64(walk.last.ino);
scoutfs_key_init(&last_key, &last_ikey, sizeof(last_ikey));
scoutfs_inode_init_index_key(&key, type, walk.first.major,
walk.first.minor, walk.first.ino);
scoutfs_inode_init_index_key(&last_key, type, walk.last.major,
walk.last.minor, walk.last.ino);
/* cap nr to the max the ioctl can return to a compat task */
walk.nr_entries = min_t(u64, walk.nr_entries, INT_MAX);
@@ -121,21 +106,21 @@ static long scoutfs_ioc_walk_inodes(struct file *file, unsigned long arg)
for (nr = 0; nr < walk.nr_entries; ) {
ret = scoutfs_item_next_same(sb, &key, &last_key, NULL, lock);
ret = scoutfs_item_next(sb, &key, &last_key, NULL, lock);
if (ret < 0 && ret != -ENOENT)
break;
if (ret == -ENOENT) {
/* done if lock covers last iteration key */
if (scoutfs_key_compare(&last_key, lock->end) <= 0) {
if (scoutfs_key_compare(&last_key, &lock->end) <= 0) {
ret = 0;
break;
}
/* continue iterating after locked empty region */
scoutfs_key_copy(&key, lock->end);
scoutfs_key_inc_cur_len(&key);
key = lock->end;
scoutfs_key_inc(&key);
scoutfs_unlock(sb, lock, DLM_LOCK_PR);
@@ -146,37 +131,32 @@ static long scoutfs_ioc_walk_inodes(struct file *file, unsigned long arg)
* It'd mean adding a lock to the inode index
* items which isn't quite there yet.
*/
ret = scoutfs_manifest_next_key(sb, &key, next_key);
ret = scoutfs_manifest_next_key(sb, &key, &next_key);
if (ret < 0 && ret != -ENOENT)
goto out;
if (ret == -ENOENT ||
scoutfs_key_compare(next_key, &last_key) > 0) {
scoutfs_key_compare(&next_key, &last_key) > 0) {
ret = 0;
goto out;
}
/* if it's within last it should be same size */
if (next_key->key_len != key.key_len) {
ret = -EIO;
goto out;
}
key = next_key;
scoutfs_key_copy(&key, next_key);
ret = scoutfs_lock_inode_index(sb, DLM_LOCK_PR, ikey.type,
be64_to_cpu(ikey.major),
be64_to_cpu(ikey.ino),
&lock);
ret = scoutfs_lock_inode_index(sb, DLM_LOCK_PR,
key.sk_type,
le64_to_cpu(key.skii_major),
le64_to_cpu(key.skii_ino),
&lock);
if (ret < 0)
goto out;
continue;
}
ent.major = be64_to_cpu(ikey.major);
ent.minor = be32_to_cpu(ikey.minor);
ent.ino = be64_to_cpu(ikey.ino);
ent.major = le64_to_cpu(key.skii_major);
ent.minor = 0;
ent.ino = le64_to_cpu(key.skii_ino);
if (copy_to_user((void __user *)walk.entries_ptr, &ent,
sizeof(ent))) {
@@ -187,14 +167,12 @@ static long scoutfs_ioc_walk_inodes(struct file *file, unsigned long arg)
nr++;
walk.entries_ptr += sizeof(ent);
scoutfs_key_inc_cur_len(&key);
scoutfs_key_inc(&key);
}
scoutfs_unlock(sb, lock, DLM_LOCK_PR);
out:
scoutfs_key_free(sb, next_key);
if (nr > 0)
ret = nr;
@@ -499,66 +477,47 @@ static long scoutfs_ioc_item_cache_keys(struct file *file, unsigned long arg)
{
struct super_block *sb = file_inode(file)->i_sb;
struct scoutfs_ioctl_item_cache_keys ick;
struct scoutfs_key_buf *key;
struct page *page;
unsigned bytes;
void *buf;
struct scoutfs_key __user *ukeys;
struct scoutfs_key keys[16];
unsigned int nr;
int total;
int ret;
if (copy_from_user(&ick, (void __user *)arg, sizeof(ick)))
return -EFAULT;
if ((!!ick.key_ptr != !!ick.key_len) ||
ick.key_len > SCOUTFS_MAX_KEY_SIZE ||
ick.which > SCOUTFS_IOC_ITEM_CACHE_KEYS_RANGES)
if (ick.which > SCOUTFS_IOC_ITEM_CACHE_KEYS_RANGES)
return -EINVAL;
/* don't overflow signed 32bit syscall return longs */
ick.buf_len = min_t(u64, ick.buf_len, S32_MAX);
key = scoutfs_key_alloc(sb, SCOUTFS_MAX_KEY_SIZE);
page = alloc_page(GFP_KERNEL);
if (!key || !page) {
ret = -ENOMEM;
goto out;
}
if (copy_from_user(key->data, (void __user *)ick.key_ptr, ick.key_len)) {
ret = -EFAULT;
goto out;
}
scoutfs_key_init_buf_len(key, key->data, ick.key_len,
SCOUTFS_MAX_KEY_SIZE);
scoutfs_key_inc(key);
buf = page_address(page);
ukeys = (void __user *)(long)ick.buf_ptr;
total = 0;
ret = 0;
while (ick.buf_len) {
bytes = min_t(u64, ick.buf_len, PAGE_SIZE);
while (ick.buf_nr) {
nr = min_t(size_t, ick.buf_nr, ARRAY_SIZE(keys));
if (ick.which == SCOUTFS_IOC_ITEM_CACHE_KEYS_ITEMS)
ret = scoutfs_item_copy_keys(sb, key, buf, bytes);
ret = scoutfs_item_copy_keys(sb, &ick.key, keys, nr);
else
ret = scoutfs_item_copy_range_keys(sb, key, buf, bytes);
if (ret > 0 && copy_to_user((void __user *)ick.buf_ptr, buf, ret))
ret = -EFAULT;
ret = scoutfs_item_copy_range_keys(sb, &ick.key, keys,
nr);
BUG_ON(ret > nr); /* stack overflow \o/ */
if (ret <= 0)
break;
ick.buf_len -= ret;
ick.buf_ptr += ret;
if (copy_to_user(ukeys, keys, ret * sizeof(keys[0]))) {
ret = -EFAULT;
break;
}
ick.key = keys[ret - 1];
scoutfs_key_inc(&ick.key);
ukeys += ret;
ick.buf_nr -= ret;
total += ret;
ret = 0;
}
out:
scoutfs_key_free(sb, key);
if (page)
__free_page(page);
return ret ?: total;
}
+8 -3
View File
@@ -208,11 +208,16 @@ struct scoutfs_ioctl_stat_more {
#define SCOUTFS_IOC_STAT_MORE _IOW(SCOUTFS_IOCTL_MAGIC, 7, \
struct scoutfs_ioctl_stat_more)
/*
* Fills the buffer with either the keys for the cached items or the
* keys for the cached ranges found starting with the given key. The
* number of keys filled in the buffer is returned. When filling range
* keys the returned number will always be a multiple of two.
*/
struct scoutfs_ioctl_item_cache_keys {
__u64 key_ptr;
__u64 key_len;
struct scoutfs_key key;
__u64 buf_ptr;
__u64 buf_len;
__u16 buf_nr;
__u8 which;
} __packed;
+181 -306
View File
File diff suppressed because it is too large Load Diff
+28 -36
View File
@@ -4,75 +4,67 @@
#include <linux/uio.h>
struct scoutfs_segment;
struct scoutfs_key_buf;
struct scoutfs_key;
int scoutfs_item_lookup(struct super_block *sb, struct scoutfs_key_buf *key,
int scoutfs_item_lookup(struct super_block *sb, struct scoutfs_key *key,
struct kvec *val, struct scoutfs_lock *lock);
int scoutfs_item_lookup_exact(struct super_block *sb,
struct scoutfs_key_buf *key, struct kvec *val,
struct scoutfs_key *key, struct kvec *val,
struct scoutfs_lock *lock);
int scoutfs_item_next(struct super_block *sb, struct scoutfs_key_buf *key,
struct scoutfs_key_buf *last, struct kvec *val,
int scoutfs_item_next(struct super_block *sb, struct scoutfs_key *key,
struct scoutfs_key *last, struct kvec *val,
struct scoutfs_lock *lock);
int scoutfs_item_next_same_min(struct super_block *sb,
struct scoutfs_key_buf *key,
struct scoutfs_key_buf *last,
struct kvec *val, int len,
struct scoutfs_lock *lock);
int scoutfs_item_next_same(struct super_block *sb, struct scoutfs_key_buf *key,
struct scoutfs_key_buf *last, struct kvec *val,
struct scoutfs_lock *lock);
int scoutfs_item_create(struct super_block *sb, struct scoutfs_key_buf *key,
int scoutfs_item_create(struct super_block *sb, struct scoutfs_key *key,
struct kvec *val, struct scoutfs_lock *lock);
int scoutfs_item_create_force(struct super_block *sb,
struct scoutfs_key_buf *key,
struct scoutfs_key *key,
struct kvec *val, struct scoutfs_lock *lock);
int scoutfs_item_dirty(struct super_block *sb, struct scoutfs_key_buf *key,
int scoutfs_item_dirty(struct super_block *sb, struct scoutfs_key *key,
struct scoutfs_lock *lock);
int scoutfs_item_update(struct super_block *sb, struct scoutfs_key_buf *key,
int scoutfs_item_update(struct super_block *sb, struct scoutfs_key *key,
struct kvec *val, struct scoutfs_lock *lock);
void scoutfs_item_delete_dirty(struct super_block *sb,
struct scoutfs_key_buf *key);
struct scoutfs_key *key);
void scoutfs_item_update_dirty(struct super_block *sb,
struct scoutfs_key_buf *key, struct kvec *val);
int scoutfs_item_delete(struct super_block *sb, struct scoutfs_key_buf *key,
struct scoutfs_key *key, struct kvec *val);
int scoutfs_item_delete(struct super_block *sb, struct scoutfs_key *key,
struct scoutfs_lock *lock);
int scoutfs_item_delete_force(struct super_block *sb,
struct scoutfs_key_buf *key,
struct scoutfs_key *key,
struct scoutfs_lock *lock);
int scoutfs_item_delete_save(struct super_block *sb,
struct scoutfs_key_buf *key,
struct scoutfs_key *key,
struct list_head *list,
struct scoutfs_lock *lock);
int scoutfs_item_restore(struct super_block *sb, struct list_head *list,
struct scoutfs_lock *lock);
int scoutfs_item_add_batch(struct super_block *sb, struct list_head *list,
struct scoutfs_key_buf *key, struct kvec *val);
struct scoutfs_key *key, struct kvec *val);
int scoutfs_item_insert_batch(struct super_block *sb, struct list_head *list,
struct scoutfs_key_buf *start,
struct scoutfs_key_buf *end);
struct scoutfs_key *start,
struct scoutfs_key *end);
void scoutfs_item_free_batch(struct super_block *sb, struct list_head *list);
bool scoutfs_item_has_dirty(struct super_block *sb);
bool scoutfs_item_range_cached(struct super_block *sb,
struct scoutfs_key_buf *start,
struct scoutfs_key_buf *end, bool dirty);
struct scoutfs_key *start,
struct scoutfs_key *end, bool dirty);
bool scoutfs_item_dirty_fits_single(struct super_block *sb, u32 nr_items,
u32 key_bytes, u32 val_bytes);
u32 val_bytes);
int scoutfs_item_dirty_seg(struct super_block *sb, struct scoutfs_segment *seg);
int scoutfs_item_writeback(struct super_block *sb,
struct scoutfs_key_buf *start,
struct scoutfs_key_buf *end);
struct scoutfs_key *start,
struct scoutfs_key *end);
int scoutfs_item_invalidate(struct super_block *sb,
struct scoutfs_key_buf *start,
struct scoutfs_key_buf *end);
struct scoutfs_key *start,
struct scoutfs_key *end);
int scoutfs_item_copy_range_keys(struct super_block *sb,
struct scoutfs_key_buf *key, void *data,
unsigned len);
int scoutfs_item_copy_keys(struct super_block *sb, struct scoutfs_key_buf *key,
void *data, unsigned len);
struct scoutfs_key *key,
struct scoutfs_key *keys, unsigned nr);
int scoutfs_item_copy_keys(struct super_block *sb, struct scoutfs_key *key,
struct scoutfs_key *keys, unsigned nr);
int scoutfs_item_setup(struct super_block *sb);
void scoutfs_item_destroy(struct super_block *sb);
+37 -411
View File
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 Versity Software, Inc. All rights reserved.
* Copyright (C) 2018 Versity Software, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
@@ -11,422 +11,48 @@
* General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/bug.h>
#include <linux/errno.h>
#include "format.h"
#include "key.h"
struct scoutfs_key_buf *scoutfs_key_alloc(struct super_block *sb, u16 len)
char *scoutfs_zone_strings[SCOUTFS_MAX_ZONE] = {
[SCOUTFS_INODE_INDEX_ZONE] = "ind",
[SCOUTFS_NODE_ZONE] = "nod",
[SCOUTFS_FS_ZONE] = "fs",
};
char *scoutfs_type_strings[SCOUTFS_MAX_ZONE][SCOUTFS_MAX_TYPE] = {
[SCOUTFS_INODE_INDEX_ZONE][SCOUTFS_INODE_INDEX_META_SEQ_TYPE] = "msq",
[SCOUTFS_INODE_INDEX_ZONE][SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE] = "dsq",
[SCOUTFS_NODE_ZONE][SCOUTFS_FREE_BITS_SEGNO_TYPE] = "fsg",
[SCOUTFS_NODE_ZONE][SCOUTFS_FREE_BITS_BLKNO_TYPE] = "fbk",
[SCOUTFS_NODE_ZONE][SCOUTFS_ORPHAN_TYPE] = "orp",
[SCOUTFS_FS_ZONE][SCOUTFS_INODE_TYPE] = "ino",
[SCOUTFS_FS_ZONE][SCOUTFS_XATTR_TYPE] = "xat",
[SCOUTFS_FS_ZONE][SCOUTFS_DIRENT_TYPE] = "dnt",
[SCOUTFS_FS_ZONE][SCOUTFS_READDIR_TYPE] = "rdr",
[SCOUTFS_FS_ZONE][SCOUTFS_LINK_BACKREF_TYPE] = "lbr",
[SCOUTFS_FS_ZONE][SCOUTFS_SYMLINK_TYPE] = "sym",
[SCOUTFS_FS_ZONE][SCOUTFS_BLOCK_MAPPING_TYPE] = "bmp",
};
char scoutfs_unknown_u8_strings[U8_MAX][U8_STR_MAX];
int __init scoutfs_key_init(void)
{
struct scoutfs_key_buf *key;
if (WARN_ON_ONCE(len > SCOUTFS_MAX_KEY_SIZE))
return NULL;
key = kmalloc(sizeof(struct scoutfs_key_buf) + len, GFP_NOFS);
if (key) {
key->data = key + 1;
key->key_len = len;
key->buf_len = len;
}
return key;
}
struct scoutfs_key_buf *scoutfs_key_dup(struct super_block *sb,
struct scoutfs_key_buf *key)
{
struct scoutfs_key_buf *dup;
dup = scoutfs_key_alloc(sb, key->key_len);
if (dup)
memcpy(dup->data, key->data, dup->key_len);
return dup;
}
void scoutfs_key_free(struct super_block *sb, struct scoutfs_key_buf *key)
{
kfree(key);
}
/*
* Keys are large multi-byte big-endian values. To correctly increase
* or decrease keys we need to start by extending the key to the full
* precision using the max key size, setting the least significant bytes
* to 0.
*/
static void extend_zeros(struct scoutfs_key_buf *key)
{
if (key->key_len < SCOUTFS_MAX_KEY_SIZE &&
!WARN_ON_ONCE(key->buf_len != SCOUTFS_MAX_KEY_SIZE)) {
memset(key->data + key->key_len, 0,
key->buf_len - key->key_len);
key->key_len = key->buf_len;
}
}
/*
* There are callers that work with a range of keys of a uniform length
* who know that it's safe to increment their keys that aren't full
* precision. These are exceptional so a specific function variant
* marks them.
*/
void scoutfs_key_inc_cur_len(struct scoutfs_key_buf *key)
{
u8 *bytes = key->data;
int i;
for (i = key->key_len - 1; i >= 0; i--) {
if (++bytes[i] != 0)
break;
}
}
void scoutfs_key_inc(struct scoutfs_key_buf *key)
{
extend_zeros(key);
scoutfs_key_inc_cur_len(key);
}
void scoutfs_key_dec_cur_len(struct scoutfs_key_buf *key)
{
u8 *bytes = key->data;
int i;
for (i = key->key_len - 1; i >= 0; i--) {
if (--bytes[i] != 255)
break;
}
}
void scoutfs_key_dec(struct scoutfs_key_buf *key)
{
extend_zeros(key);
scoutfs_key_dec_cur_len(key);
}
/* return the bytes of the string including the null term */
#define snprintf_null(buf, size, fmt, args...) \
(snprintf((buf), (size), fmt, ##args) + 1)
/*
* Store a formatted string representing the key in the buffer. The key
* must be at least min_len to store the data needed by the format at
* all. fmt_len is the length of data that's used by the format. These
* are different because we have badly designed keys with variable
* length data that isn't described by the key. It's assumed from the
* length of the key. Take dirents -- they need to at least have a
* dirent struct, but the name length is the rest of the key.
*
* (XXX And this goes horribly wrong when we pad out dirent keys to max
* len to increment at high precision. We'll never see these items used
* by real fs code, but temporary keys and range endpoints can be full
* precision and we can try and print them and get very confused. We
* need to rev the format to include explicit lengths.)
*
* If the format doesn't cover the entire key then we append more
* formatting to represent the trailing bytes: runs of zeros compresesd
* to _ and then hex output of non-zero bytes.
*/
static int __printf(6, 7) snprintf_key(char *buf, size_t size,
struct scoutfs_key_buf *key,
unsigned min_len, unsigned fmt_len,
const char *fmt, ...)
{
va_list args;
char *data;
char *end;
int left;
int part;
int ret;
int nr;
int i;
if (key->key_len < min_len)
return snprintf_null(buf, size, "[trunc len %u < min %u]",
key->key_len, min_len);
if (fmt_len == 0)
fmt_len = min_len;
va_start(args, fmt);
ret = vsnprintf(buf, size, fmt, args);
va_end(args);
/* next formatting overwrites null */
if (buf) {
buf += ret;
size -= min_t(int, size, ret);
for (i = 0; i <= U8_MAX; i++) {
ret = snprintf(scoutfs_unknown_u8_strings[i], U8_STR_MAX,
"u%u", i);
if (WARN_ONCE(ret <= 0 || ret >= U8_STR_MAX,
"snprintf("__stringify(U8_STR_MAX)") ret %d\n",
ret))
return -EINVAL;
}
data = key->data + fmt_len;
left = key->key_len - fmt_len;
while (left && (!buf || size > 1)) {
/* compress runs of zero bytes to _ */
end = memchr_inv(data, 0, left);
nr = end ? end - data : left;
if (nr) {
if (buf) {
*(buf++) = '_';
size--;
}
ret++;
data += nr;
left -= nr;
continue;
}
/*
* hex print non-zero bytes. %ph is limited to 64 bytes
* and is buggy in that it still tries to print to buf
* past size. (so buf = null, size = 0 crashes instead
* of printing the length of the formatted string.)
*/
end = memchr(data, 0, left);
nr = end ? end - data : left;
nr = min(nr, 64);
if (buf)
part = snprintf(buf, size, "%*phN", nr, data);
else
part = nr * 2;
if (buf) {
buf += part;
size -= min_t(int, size, part);
}
ret += part;
data += nr;
left -= nr;
}
/* always store and include null */
if (buf)
*buf = '\0';
return ret + 1;
}
typedef int (*key_printer_t)(char *buf, struct scoutfs_key_buf *key,
size_t size);
static int pr_ino_idx(char *buf, struct scoutfs_key_buf *key, size_t size)
{
static char *type_strings[] = {
[SCOUTFS_INODE_INDEX_META_SEQ_TYPE] = "msq",
[SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE] = "dsq",
};
struct scoutfs_inode_index_key *ikey = key->data;
return snprintf_key(buf, size, key,
sizeof(struct scoutfs_inode_index_key), 0,
"iin.%s.%llu.%u.%llu",
type_strings[ikey->type], be64_to_cpu(ikey->major),
be32_to_cpu(ikey->minor), be64_to_cpu(ikey->ino));
}
static int pr_free_bits(char *buf, struct scoutfs_key_buf *key, size_t size)
{
static char *type_strings[] = {
[SCOUTFS_FREE_BITS_SEGNO_TYPE] = "fsg",
[SCOUTFS_FREE_BITS_BLKNO_TYPE] = "fbk",
};
struct scoutfs_free_bits_key *frk = key->data;
return snprintf_key(buf, size, key,
sizeof(struct scoutfs_block_mapping_key), 0,
"nod.%llu.%s.%llu",
be64_to_cpu(frk->node_id),
type_strings[frk->type],
be64_to_cpu(frk->base));
}
static int pr_orphan(char *buf, struct scoutfs_key_buf *key, size_t size)
{
struct scoutfs_orphan_key *okey = key->data;
return snprintf_key(buf, size, key,
sizeof(struct scoutfs_orphan_key), 0,
"nod.%llu.orp.%llu",
be64_to_cpu(okey->node_id),
be64_to_cpu(okey->ino));
}
static int pr_inode(char *buf, struct scoutfs_key_buf *key, size_t size)
{
struct scoutfs_inode_key *ikey = key->data;
return snprintf_key(buf, size, key,
sizeof(struct scoutfs_inode_key), 0,
"fs.%llu.ino",
be64_to_cpu(ikey->ino));
}
static int pr_xattr(char *buf, struct scoutfs_key_buf *key, size_t size)
{
struct scoutfs_xattr_key *xkey = key->data;
return snprintf_key(buf, size, key,
sizeof(struct scoutfs_xattr_key), key->key_len,
"fs.%llu.xat.%08x.%llu.%u",
be64_to_cpu(xkey->ino),
be32_to_cpu(xkey->name_hash),
be64_to_cpu(xkey->id), xkey->part);
}
static int pr_dirent(char *buf, struct scoutfs_key_buf *key, size_t size)
{
struct scoutfs_dirent_key *dkey = key->data;
char *which = dkey->type == SCOUTFS_DIRENT_TYPE ? "dnt" :
dkey->type == SCOUTFS_READDIR_TYPE ? "rdr" :
dkey->type == SCOUTFS_LINK_BACKREF_TYPE ? "lbr" :
"unk";
return snprintf_key(buf, size, key,
sizeof(struct scoutfs_dirent_key), key->key_len,
"fs.%llu.%s.%llu.%llu",
be64_to_cpu(dkey->ino), which,
be64_to_cpu(dkey->major),
be64_to_cpu(dkey->minor));
}
static int pr_symlink(char *buf, struct scoutfs_key_buf *key, size_t size)
{
struct scoutfs_symlink_key *skey = key->data;
return snprintf_key(buf, size, key,
sizeof(struct scoutfs_symlink_key), 0,
"fs.%llu.sym",
be64_to_cpu(skey->ino));
}
static int pr_block_mapping(char *buf, struct scoutfs_key_buf *key, size_t size)
{
struct scoutfs_block_mapping_key *bmk = key->data;
return snprintf_key(buf, size, key,
sizeof(struct scoutfs_block_mapping_key), 0,
"fs.%llu.bmp.%llu",
be64_to_cpu(bmk->ino),
be64_to_cpu(bmk->base));
}
const static key_printer_t key_printers[SCOUTFS_MAX_ZONE][SCOUTFS_MAX_TYPE] = {
[SCOUTFS_INODE_INDEX_ZONE][SCOUTFS_INODE_INDEX_META_SEQ_TYPE] =
pr_ino_idx,
[SCOUTFS_INODE_INDEX_ZONE][SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE] =
pr_ino_idx,
[SCOUTFS_NODE_ZONE][SCOUTFS_FREE_BITS_SEGNO_TYPE] = pr_free_bits,
[SCOUTFS_NODE_ZONE][SCOUTFS_FREE_BITS_BLKNO_TYPE] = pr_free_bits,
[SCOUTFS_NODE_ZONE][SCOUTFS_ORPHAN_TYPE] = pr_orphan,
[SCOUTFS_FS_ZONE][SCOUTFS_INODE_TYPE] = pr_inode,
[SCOUTFS_FS_ZONE][SCOUTFS_XATTR_TYPE] = pr_xattr,
[SCOUTFS_FS_ZONE][SCOUTFS_DIRENT_TYPE] = pr_dirent,
[SCOUTFS_FS_ZONE][SCOUTFS_READDIR_TYPE] = pr_dirent,
[SCOUTFS_FS_ZONE][SCOUTFS_LINK_BACKREF_TYPE] = pr_dirent,
[SCOUTFS_FS_ZONE][SCOUTFS_SYMLINK_TYPE] = pr_symlink,
[SCOUTFS_FS_ZONE][SCOUTFS_BLOCK_MAPPING_TYPE] = pr_block_mapping,
};
/*
* Write the null-terminated string that describes the key to the
* buffer. The bytes copied (including the null) is returned. A null
* buffer can be used to find the string size without writing anything.
*
* XXX nonprintable characters in the trace?
*/
int scoutfs_key_str_size(char *buf, struct scoutfs_key_buf *key, size_t size)
{
u8 zone;
u8 type;
if (key == NULL || key->data == NULL)
return snprintf_null(buf, size, "[NULL]");
/* always at least zone, some id, and type */
if (key->key_len < (1 + 8 + 1))
return snprintf_null(buf, size, "[trunc len %u]", key->key_len);
zone = *(u8 *)key->data;
/*
* each zone's keys always start with the same fields that let
* us deref any key to get the type. We chose a few representative
* keys from each zone to get the type.
*/
if (zone == SCOUTFS_INODE_INDEX_ZONE) {
struct scoutfs_inode_index_key *ikey = key->data;
type = ikey->type;
} else if (zone == SCOUTFS_NODE_ZONE) {
struct scoutfs_free_bits_key *fkey = key->data;
type = fkey->type;
} else if (zone == SCOUTFS_FS_ZONE) {
struct scoutfs_inode_key *ikey = key->data;
type = ikey->type;
} else {
type = 255;
}
if (zone > SCOUTFS_MAX_ZONE || type > SCOUTFS_MAX_TYPE ||
key_printers[zone][type] == NULL) {
return snprintf_null(buf, size, "[unk zone %u type %u]",
zone, type);
}
return key_printers[zone][type](buf, key, size);
}
/*
* Callers never have a pre-existing buffer whose size they need to be
* careful for. For a given static string they're first calling with a
* null buf to find out the formatted length without storing anything.
* Then they're called again with a buffer of that allocation size. As
* long as the formatting is consistent this pattern won't overflow.
*/
int scoutfs_key_str(char *buf, struct scoutfs_key_buf *key)
{
return scoutfs_key_str_size(buf, key, buf ? INT_MAX : 0);
}
#define MAX_STR_COUNT 10
struct key_strings {
bool started;
int next_str;
char strings[MAX_STR_COUNT][SK_STR_BYTES];
};
static DEFINE_PER_CPU(struct key_strings, percpu_key_strings);
void scoutfs_key_start_percpu(void)
{
struct key_strings *ks = this_cpu_ptr(&percpu_key_strings);
BUG_ON(ks->started);
ks->started = true;
get_cpu();
}
char *scoutfs_key_percpu_string(void)
{
struct key_strings *ks = this_cpu_ptr(&percpu_key_strings);
char *str;
BUG_ON(!ks->started);
str = ks->strings[ks->next_str++];
BUG_ON(ks->next_str >= MAX_STR_COUNT);
return str;
}
void scoutfs_key_finish_percpu(void)
{
struct key_strings *ks = this_cpu_ptr(&percpu_key_strings);
BUG_ON(!ks->started);
ks->next_str = 0;
ks->started = false;
put_cpu();
return 0;
}
+135 -119
View File
@@ -3,88 +3,87 @@
#include <linux/types.h>
#include "format.h"
#include "cmp.h"
#include "endian_swap.h"
struct scoutfs_key_buf {
void *data;
u16 key_len;
u16 buf_len;
};
extern char *scoutfs_zone_strings[SCOUTFS_MAX_ZONE];
extern char *scoutfs_type_strings[SCOUTFS_MAX_ZONE][SCOUTFS_MAX_TYPE];
#define U8_STR_MAX 5 /* u%3u'\0' */
extern char scoutfs_unknown_u8_strings[U8_MAX][U8_STR_MAX];
struct scoutfs_key_buf *scoutfs_key_alloc(struct super_block *sb, u16 len);
struct scoutfs_key_buf *scoutfs_key_dup(struct super_block *sb,
struct scoutfs_key_buf *key);
void scoutfs_key_free(struct super_block *sb, struct scoutfs_key_buf *key);
void scoutfs_key_inc(struct scoutfs_key_buf *key);
void scoutfs_key_inc_cur_len(struct scoutfs_key_buf *key);
void scoutfs_key_dec(struct scoutfs_key_buf *key);
void scoutfs_key_dec_cur_len(struct scoutfs_key_buf *key);
int __init scoutfs_key_init(void);
int scoutfs_key_str_size(char *buf, struct scoutfs_key_buf *key, size_t size);
int scoutfs_key_str(char *buf, struct scoutfs_key_buf *key);
void scoutfs_key_start_percpu(void);
char *scoutfs_key_percpu_string(void);
void scoutfs_key_finish_percpu(void);
#define SK_PCPU(statements) do { \
scoutfs_key_start_percpu(); \
{ statements; } \
scoutfs_key_finish_percpu(); \
} while (0)
/*
* The biggest keys are typically a little struct then a large name. The
* string representation will tend to be mostly the name, but some of the
* strict fields can blow up from say 8 bytes to 20 bytes. So we give
* a lot of padding for that.
*/
#define SK_STR_BYTES (100 + SCOUTFS_MAX_KEY_SIZE)
#define SK_FMT "%s"
#define SK_ARG(k) \
({ \
char *__str = scoutfs_key_percpu_string(); \
scoutfs_key_str_size(__str, k, SK_STR_BYTES); \
__str; \
})
#define SK_TRACE_PRINTK(args...) SK_PCPU(trace_printk(args))
#define SK_PRINTK(args...) SK_PCPU(printk(args))
/*
* Initialize a small key in a larger allocated buffer. This lets
* callers, for example, search for a small key and get a larger key
* copied in.
*/
static inline void scoutfs_key_init_buf_len(struct scoutfs_key_buf *key,
void *data, u16 key_len,
u16 buf_len)
static inline char *sk_zone_str(u8 zone)
{
WARN_ON_ONCE(buf_len > SCOUTFS_MAX_KEY_SIZE);
WARN_ON_ONCE(key_len > buf_len);
if (zone >= SCOUTFS_MAX_ZONE || scoutfs_zone_strings[zone] == NULL)
return scoutfs_unknown_u8_strings[zone];
key->data = data;
key->key_len = key_len;
key->buf_len = buf_len;
return scoutfs_zone_strings[zone];
}
static inline char *sk_type_str(u8 zone, u8 type)
{
if (zone >= SCOUTFS_MAX_ZONE || type >= SCOUTFS_MAX_TYPE ||
scoutfs_type_strings[zone][type] == NULL)
return scoutfs_unknown_u8_strings[type];
return scoutfs_type_strings[zone][type];
}
#define SK_FMT "%s.%llu.%s.%llu.%llu.%u"
/* This does not support null keys */
#define SK_ARG(key) sk_zone_str((key)->sk_zone), \
le64_to_cpu((key)->_sk_first), \
sk_type_str((key)->sk_zone, (key)->sk_type), \
le64_to_cpu((key)->_sk_second), \
le64_to_cpu((key)->_sk_third), \
(key)->_sk_fourth
static inline void scoutfs_key_set_zeros(struct scoutfs_key *key)
{
key->sk_zone = 0;
key->_sk_first = 0;
key->sk_type = 0;
key->_sk_second = 0;
key->_sk_third = 0;
key->_sk_fourth = 0;
}
static inline void scoutfs_key_copy_or_zeros(struct scoutfs_key *dst,
struct scoutfs_key *src)
{
if (src)
*dst = *src;
else
scoutfs_key_set_zeros(dst);
}
static inline void scoutfs_key_set_ones(struct scoutfs_key *key)
{
key->sk_zone = U8_MAX;
key->_sk_first = cpu_to_le64(U64_MAX);
key->sk_type = U8_MAX;
key->_sk_second = cpu_to_le64(U64_MAX);
key->_sk_third = cpu_to_le64(U64_MAX);
key->_sk_fourth = U8_MAX;
}
/*
* Point the key buf, usually statically allocated, at an existing
* contiguous key stored elsewhere.
* Return a -1/0/1 comparison of keys.
*
* It turns out that these ternary chains are consistently cheaper than
* other alternatives across keys that first differ in any of the
* values. Say maybe 20% faster than memcmp.
*/
static inline void scoutfs_key_init(struct scoutfs_key_buf *key,
void *data, u16 len)
static inline int scoutfs_key_compare(struct scoutfs_key *a,
struct scoutfs_key *b)
{
scoutfs_key_init_buf_len(key, data, len, len);
}
/*
* Compare the fs keys in segment sort order.
*/
static inline int scoutfs_key_compare(struct scoutfs_key_buf *a,
struct scoutfs_key_buf *b)
{
return memcmp(a->data, b->data, min(a->key_len, b->key_len)) ?:
a->key_len < b->key_len ? -1 : a->key_len > b->key_len ? 1 : 0;
return scoutfs_cmp(a->sk_zone, b->sk_zone) ?:
scoutfs_cmp(le64_to_cpu(a->_sk_first), le64_to_cpu(b->_sk_first)) ?:
scoutfs_cmp(a->sk_type, b->sk_type) ?:
scoutfs_cmp(le64_to_cpu(a->_sk_second), le64_to_cpu(b->_sk_second)) ?:
scoutfs_cmp(le64_to_cpu(a->_sk_third), le64_to_cpu(b->_sk_third)) ?:
scoutfs_cmp(a->_sk_fourth, b->_sk_fourth);
}
/*
@@ -93,68 +92,85 @@ static inline int scoutfs_key_compare(struct scoutfs_key_buf *a,
* 1: a_start > b_end
* else 0: ranges overlap
*/
static inline int scoutfs_key_compare_ranges(struct scoutfs_key_buf *a_start,
struct scoutfs_key_buf *a_end,
struct scoutfs_key_buf *b_start,
struct scoutfs_key_buf *b_end)
static inline int scoutfs_key_compare_ranges(struct scoutfs_key *a_start,
struct scoutfs_key *a_end,
struct scoutfs_key *b_start,
struct scoutfs_key *b_end)
{
return scoutfs_key_compare(a_end, b_start) < 0 ? -1 :
scoutfs_key_compare(a_start, b_end) > 0 ? 1 :
0;
}
/*
* Copy as much of the contents of the source buffer that fits into the
* dest buffer.
*/
static inline void scoutfs_key_copy(struct scoutfs_key_buf *dst,
struct scoutfs_key_buf *src)
static inline void scoutfs_key_inc(struct scoutfs_key *key)
{
dst->key_len = min(dst->buf_len, src->key_len);
memcpy(dst->data, src->data, dst->key_len);
}
/*
* Initialize the dst buffer to point to the source buffer in all ways,
* including the buf len. The contents of the buffer are shared by the
* fields describing the buffers are not.
*/
static inline void scoutfs_key_clone(struct scoutfs_key_buf *dst,
struct scoutfs_key_buf *src)
{
*dst = *src;
}
/*
* Memset as much of the length as fits in the buffer and set that to
* the new key length.
*/
static inline void scoutfs_key_memset(struct scoutfs_key_buf *key, int c,
u16 len)
{
if (WARN_ON_ONCE(len > SCOUTFS_MAX_KEY_SIZE))
if (++key->_sk_fourth != 0)
return;
key->key_len = min(key->buf_len, len);
memset(key->data, c, key->key_len);
le64_add_cpu(&key->_sk_third, 1);
if (key->_sk_third != 0)
return;
le64_add_cpu(&key->_sk_second, 1);
if (key->_sk_second != 0)
return;
if (++key->sk_type != 0)
return;
le64_add_cpu(&key->_sk_first, 1);
if (key->_sk_first != 0)
return;
key->sk_zone++;
}
/*
* Set the contents of the buffer to the smallest possible key by sort
* order. It might be truncated if the buffer isn't large enough.
*/
static inline void scoutfs_key_set_min(struct scoutfs_key_buf *key)
static inline void scoutfs_key_dec(struct scoutfs_key *key)
{
scoutfs_key_memset(key, 0, sizeof(struct scoutfs_inode_key));
if (--key->_sk_fourth != U8_MAX)
return;
le64_add_cpu(&key->_sk_third, -1);
if (key->_sk_third != cpu_to_le64(U64_MAX))
return;
le64_add_cpu(&key->_sk_second, -1);
if (key->_sk_second != cpu_to_le64(U64_MAX))
return;
if (--key->sk_type != U8_MAX)
return;
le64_add_cpu(&key->_sk_first, -1);
if (key->_sk_first != cpu_to_le64(U64_MAX))
return;
key->sk_zone--;
}
/*
* Set the contents of the buffer to the largest possible key by sort
* order. It might be truncated if the buffer isn't large enough.
*/
static inline void scoutfs_key_set_max(struct scoutfs_key_buf *key)
static inline void scoutfs_key_to_be(struct scoutfs_key_be *be,
struct scoutfs_key *key)
{
scoutfs_key_memset(key, 0xff, sizeof(struct scoutfs_inode_key));
BUILD_BUG_ON(sizeof(struct scoutfs_key_be) !=
sizeof(struct scoutfs_key));
be->sk_zone = key->sk_zone;
be->_sk_first = le64_to_be64(key->_sk_first);
be->sk_type = key->sk_type;
be->_sk_second = le64_to_be64(key->_sk_second);
be->_sk_third = le64_to_be64(key->_sk_third);
be->_sk_fourth = key->_sk_fourth;
}
static inline void scoutfs_key_from_be(struct scoutfs_key *key,
struct scoutfs_key_be *be)
{
key->sk_zone = be->sk_zone;
key->_sk_first = be64_to_le64(be->_sk_first);
key->sk_type = be->sk_type;
key->_sk_second = be64_to_le64(be->_sk_second);
key->_sk_third = be64_to_le64(be->_sk_third);
key->_sk_fourth = be->_sk_fourth;
}
#endif
+72 -93
View File
@@ -112,8 +112,8 @@ static void invalidate_inode(struct super_block *sb, u64 ino)
static int lock_invalidate(struct super_block *sb, struct scoutfs_lock *lock,
int prev, int mode)
{
struct scoutfs_key_buf *start = lock->start;
struct scoutfs_key_buf *end = lock->end;
struct scoutfs_key *start = &lock->start;
struct scoutfs_key *end = &lock->end;
struct scoutfs_lock_coverage *cov;
struct scoutfs_lock_coverage *tmp;
u64 ino, last;
@@ -191,15 +191,13 @@ static void lock_free(struct lock_info *linfo, struct scoutfs_lock *lock)
list_del(&lock->lru_head);
linfo->lru_nr--;
}
scoutfs_key_free(sb, lock->start);
scoutfs_key_free(sb, lock->end);
kfree(lock);
}
static struct scoutfs_lock *lock_alloc(struct super_block *sb,
struct scoutfs_lock_name *name,
struct scoutfs_key_buf *start,
struct scoutfs_key_buf *end)
struct scoutfs_key *start,
struct scoutfs_key *end)
{
DECLARE_LOCK_INFO(sb, linfo);
@@ -235,12 +233,8 @@ static struct scoutfs_lock *lock_alloc(struct super_block *sb,
INIT_LIST_HEAD(&lock->cov_list);
if (start) {
lock->start = scoutfs_key_dup(sb, start);
lock->end = scoutfs_key_dup(sb, end);
if (!lock->start || !lock->end) {
lock_free(linfo, lock);
return NULL;
}
lock->start = *start;
lock->end = *end;
}
lock->sb = sb;
@@ -465,14 +459,14 @@ static bool insert_range_node(struct super_block *sb, struct scoutfs_lock *ins)
parent = *node;
lock = container_of(*node, struct scoutfs_lock, range_node);
cmp = scoutfs_key_compare_ranges(ins->start, ins->end,
lock->start, lock->end);
cmp = scoutfs_key_compare_ranges(&ins->start, &ins->end,
&lock->start, &lock->end);
if (WARN_ON_ONCE(cmp == 0)) {
scoutfs_warn_sk(sb, "inserting lock %p name "LN_FMT" start "SK_FMT" end "SK_FMT" overlaps with existing lock %p name "LN_FMT" start "SK_FMT" end "SK_FMT"\n",
ins, LN_ARG(&ins->name),
SK_ARG(ins->start), SK_ARG(ins->end),
lock, LN_ARG(&lock->name),
SK_ARG(lock->start), SK_ARG(lock->end));
scoutfs_warn(sb, "inserting lock %p name "LN_FMT" start "SK_FMT" end "SK_FMT" overlaps with existing lock %p name "LN_FMT" start "SK_FMT" end "SK_FMT"\n",
ins, LN_ARG(&ins->name),
SK_ARG(&ins->start), SK_ARG(&ins->end),
lock, LN_ARG(&lock->name),
SK_ARG(&lock->start), SK_ARG(&lock->end));
return false;
}
@@ -544,8 +538,8 @@ static void scoutfs_lock_ast(void *arg)
struct super_block *sb = lock->sb;
DECLARE_LOCK_INFO(sb, linfo);
int status = lock->lksb.sb_status;
bool cached;
bool dirty;
bool cached = false;
bool dirty = false;
scoutfs_inc_counter(sb, lock_ast);
@@ -584,17 +578,20 @@ static void scoutfs_lock_ast(void *arg)
* changing lock modes. We can't have cached items if we're not
* in the two modes that allow caching.
*/
cached = lock->start && scoutfs_item_range_cached(sb, lock->start,
lock->end, false);
dirty = lock->start && scoutfs_item_range_cached(sb, lock->start,
lock->end, true);
if (!RB_EMPTY_NODE(&lock->range_node)) {
cached = scoutfs_item_range_cached(sb, &lock->start,
&lock->end, false);
dirty = scoutfs_item_range_cached(sb, &lock->start, &lock->end,
true);
}
if (WARN_ON_ONCE(dirty ||
(cached && lock->granted_mode != DLM_LOCK_PR &&
lock->granted_mode != DLM_LOCK_EX))) {
scoutfs_err_sk(sb, "lock item cache consistency violation, cached %u dirty %u: name "LN_FMT" start "SK_FMT" end "SK_FMT" refresh_gen %llu error %d granted %d bast %d prev %d work %d waiters: pr %u ex %u cw %u users: pr %u ex %u cw %u dlmlksb: status %d lkid 0x%x flags 0x%x\n",
scoutfs_err(sb, "lock item cache consistency violation, cached %u dirty %u: name "LN_FMT" start "SK_FMT" end "SK_FMT" refresh_gen %llu error %d granted %d bast %d prev %d work %d waiters: pr %u ex %u cw %u users: pr %u ex %u cw %u dlmlksb: status %d lkid 0x%x flags 0x%x\n",
cached, dirty,
LN_ARG(&lock->name), SK_ARG(lock->start),
SK_ARG(lock->end), lock->refresh_gen, lock->error,
LN_ARG(&lock->name), SK_ARG(&lock->start),
SK_ARG(&lock->end), lock->refresh_gen, lock->error,
lock->granted_mode, lock->bast_mode,
lock->work_prev_mode, lock->work_mode,
lock->waiters[DLM_LOCK_PR],
@@ -674,7 +671,7 @@ static void scoutfs_lock_work(struct work_struct *work)
spin_unlock(&linfo->lock);
if (lock->start) {
if (!RB_EMPTY_NODE(&lock->range_node)) {
ret = lock_invalidate(sb, lock, prev, mode);
BUG_ON(ret);
}
@@ -793,8 +790,7 @@ static bool lock_wait(struct lock_info *linfo, struct scoutfs_lock *lock,
*/
static int lock_name_keys(struct super_block *sb, int mode, int flags,
struct scoutfs_lock_name *name,
struct scoutfs_key_buf *start,
struct scoutfs_key_buf *end,
struct scoutfs_key *start, struct scoutfs_key *end,
struct scoutfs_lock **ret_lock)
{
DECLARE_LOCK_INFO(sb, linfo);
@@ -873,10 +869,8 @@ int scoutfs_lock_ino(struct super_block *sb, int mode, int flags, u64 ino,
struct scoutfs_lock **ret_lock)
{
struct scoutfs_lock_name name;
struct scoutfs_inode_key start_ikey;
struct scoutfs_inode_key end_ikey;
struct scoutfs_key_buf start;
struct scoutfs_key_buf end;
struct scoutfs_key start;
struct scoutfs_key end;
ino &= ~(u64)SCOUTFS_LOCK_INODE_GROUP_MASK;
@@ -886,15 +880,17 @@ int scoutfs_lock_ino(struct super_block *sb, int mode, int flags, u64 ino,
name.first = cpu_to_le64(ino);
name.second = 0;
start_ikey.zone = SCOUTFS_FS_ZONE;
start_ikey.ino = cpu_to_be64(ino);
start_ikey.type = 0;
scoutfs_key_init(&start, &start_ikey, sizeof(start_ikey));
start = (struct scoutfs_key) {
.sk_zone = SCOUTFS_FS_ZONE,
.ski_ino = cpu_to_le64(ino),
.sk_type = 0,
};
end_ikey.zone = SCOUTFS_FS_ZONE;
end_ikey.ino = cpu_to_be64(ino + SCOUTFS_LOCK_INODE_GROUP_NR - 1);
end_ikey.type = ~0;
scoutfs_key_init(&end, &end_ikey, sizeof(end_ikey));
end = (struct scoutfs_key) {
.sk_zone = SCOUTFS_FS_ZONE,
.ski_ino = cpu_to_le64(ino + SCOUTFS_LOCK_INODE_GROUP_NR - 1),
.sk_type = U8_MAX,
};
return lock_name_keys(sb, mode, flags, &name, &start, &end, ret_lock);
}
@@ -1045,8 +1041,8 @@ int scoutfs_lock_global(struct super_block *sb, int mode, int flags, int type,
* because their starting keys are the same.
*/
void scoutfs_lock_get_index_item_range(u8 type, u64 major, u64 ino,
struct scoutfs_inode_index_key *start,
struct scoutfs_inode_index_key *end)
struct scoutfs_key *start,
struct scoutfs_key *end)
{
u64 start_major = major & ~SCOUTFS_LOCK_SEQ_GROUP_MASK;
u64 end_major = major | SCOUTFS_LOCK_SEQ_GROUP_MASK;
@@ -1054,21 +1050,12 @@ void scoutfs_lock_get_index_item_range(u8 type, u64 major, u64 ino,
BUG_ON(type != SCOUTFS_INODE_INDEX_META_SEQ_TYPE &&
type != SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE);
if (start) {
start->zone = SCOUTFS_INODE_INDEX_ZONE;
start->type = type;
start->major = cpu_to_be64(start_major);
start->minor = 0;
start->ino = 0;
}
if (start)
scoutfs_inode_init_index_key(start, type, start_major, 0, 0);
if (end) {
end->zone = SCOUTFS_INODE_INDEX_ZONE;
end->type = type;
end->major = cpu_to_be64(end_major);
end->minor = 0;
end->ino = cpu_to_be64(~0ULL);
}
if (end)
scoutfs_inode_init_index_key(end, type, end_major, U32_MAX,
U64_MAX);
}
/*
@@ -1082,22 +1069,16 @@ int scoutfs_lock_inode_index(struct super_block *sb, int mode,
struct scoutfs_lock **ret_lock)
{
struct scoutfs_lock_name name;
struct scoutfs_inode_index_key start_ikey;
struct scoutfs_inode_index_key end_ikey;
struct scoutfs_key_buf start;
struct scoutfs_key_buf end;
struct scoutfs_key start;
struct scoutfs_key end;
scoutfs_lock_get_index_item_range(type, major, ino,
&start_ikey, &end_ikey);
scoutfs_lock_get_index_item_range(type, major, ino, &start, &end);
name.scope = SCOUTFS_LOCK_SCOPE_FS_ITEMS;
name.zone = start_ikey.zone;
name.type = start_ikey.type;
name.first = be64_to_le64(start_ikey.major);
name.second = be64_to_le64(start_ikey.ino);
scoutfs_key_init(&start, &start_ikey, sizeof(start_ikey));
scoutfs_key_init(&end, &end_ikey, sizeof(end_ikey));
name.zone = start.sk_zone;
name.type = start.sk_type;
name.first = start.skii_major;
name.second = start.skii_ino;
return lock_name_keys(sb, mode, 0, &name, &start, &end, ret_lock);
}
@@ -1117,10 +1098,8 @@ int scoutfs_lock_node_id(struct super_block *sb, int mode, int flags,
u64 node_id, struct scoutfs_lock **lock)
{
struct scoutfs_lock_name name;
struct scoutfs_orphan_key start_okey;
struct scoutfs_orphan_key end_okey;
struct scoutfs_key_buf start;
struct scoutfs_key_buf end;
struct scoutfs_key start;
struct scoutfs_key end;
name.scope = SCOUTFS_LOCK_SCOPE_FS_ITEMS;
name.zone = SCOUTFS_NODE_ZONE;
@@ -1128,17 +1107,17 @@ int scoutfs_lock_node_id(struct super_block *sb, int mode, int flags,
name.first = cpu_to_le64(node_id);
name.second = 0;
start_okey.zone = SCOUTFS_NODE_ZONE;
start_okey.node_id = cpu_to_be64(node_id);
start_okey.type = 0;
start_okey.ino = 0;
scoutfs_key_init(&start, &start_okey, sizeof(start_okey));
start = (struct scoutfs_key) {
.sk_zone = SCOUTFS_NODE_ZONE,
.sko_node_id = cpu_to_le64(node_id),
.sk_type = 0,
};
end_okey.zone = SCOUTFS_NODE_ZONE;
end_okey.node_id = cpu_to_be64(node_id);
end_okey.type = ~0;
end_okey.ino = cpu_to_be64(~0ULL);
scoutfs_key_init(&end, &end_okey, sizeof(end_okey));
end = (struct scoutfs_key) {
.sk_zone = SCOUTFS_NODE_ZONE,
.sko_node_id = cpu_to_le64(node_id),
.sk_type = U8_MAX,
};
return lock_name_keys(sb, mode, flags, &name, &start, &end, lock);
}
@@ -1330,9 +1309,9 @@ static int scoutfs_debug_locks_seq_show(struct seq_file *m, void *v)
{
struct scoutfs_lock *lock = v;
SK_PCPU(seq_printf(m, "name "LN_FMT" start "SK_FMT" end "SK_FMT" refresh_gen %llu error %d granted %d bast %d prev %d work %d waiters: pr %u ex %u cw %u users: pr %u ex %u cw %u dlmlksb: status %d lkid 0x%x flags 0x%x\n",
LN_ARG(&lock->name), SK_ARG(lock->start),
SK_ARG(lock->end), lock->refresh_gen, lock->error,
seq_printf(m, "name "LN_FMT" start "SK_FMT" end "SK_FMT" refresh_gen %llu error %d granted %d bast %d prev %d work %d waiters: pr %u ex %u cw %u users: pr %u ex %u cw %u dlmlksb: status %d lkid 0x%x flags 0x%x\n",
LN_ARG(&lock->name), SK_ARG(&lock->start),
SK_ARG(&lock->end), lock->refresh_gen, lock->error,
lock->granted_mode, lock->bast_mode,
lock->work_prev_mode, lock->work_mode,
lock->waiters[DLM_LOCK_PR],
@@ -1343,7 +1322,7 @@ static int scoutfs_debug_locks_seq_show(struct seq_file *m, void *v)
lock->users[DLM_LOCK_CW],
lock->lksb.sb_status,
lock->lksb.sb_lkid,
lock->lksb.sb_flags));
lock->lksb.sb_flags);
return 0;
}
@@ -1437,10 +1416,10 @@ void scoutfs_lock_destroy(struct super_block *sb)
for (mode = 0; mode < SCOUTFS_LOCK_NR_MODES; mode++) {
if (lock->waiters[mode] || lock->users[mode]) {
scoutfs_warn_sk(sb, "lock name "LN_FMT" start "SK_FMT" end "SK_FMT" has mode %d user after shutdown",
scoutfs_warn(sb, "lock name "LN_FMT" start "SK_FMT" end "SK_FMT" has mode %d user after shutdown",
LN_ARG(&lock->name),
SK_ARG(lock->start),
SK_ARG(lock->end), mode);
SK_ARG(&lock->start),
SK_ARG(&lock->end), mode);
break;
}
}
+4 -4
View File
@@ -16,8 +16,8 @@
struct scoutfs_lock {
struct super_block *sb;
struct scoutfs_lock_name name;
struct scoutfs_key_buf *start;
struct scoutfs_key_buf *end;
struct scoutfs_key start;
struct scoutfs_key end;
struct rb_node node;
struct rb_node range_node;
unsigned int debug_locks_id;
@@ -53,8 +53,8 @@ int scoutfs_lock_inode(struct super_block *sb, int mode, int flags,
int scoutfs_lock_ino(struct super_block *sb, int mode, int flags, u64 ino,
struct scoutfs_lock **ret_lock);
void scoutfs_lock_get_index_item_range(u8 type, u64 major, u64 ino,
struct scoutfs_inode_index_key *start,
struct scoutfs_inode_index_key *end);
struct scoutfs_key *start,
struct scoutfs_key *end);
int scoutfs_lock_inode_index(struct super_block *sb, int mode,
u8 type, u64 major, u64 ino,
struct scoutfs_lock **ret_lock);
+169 -287
View File
@@ -50,7 +50,7 @@ struct manifest {
unsigned long flags;
struct scoutfs_key_buf *compact_keys[SCOUTFS_MANIFEST_MAX_LEVEL + 1];
struct scoutfs_key compact_keys[SCOUTFS_MANIFEST_MAX_LEVEL + 1];
};
#define MANI_FLAG_LEVEL0_FULL (1 << 0)
@@ -77,8 +77,8 @@ struct manifest_ref {
int off;
u8 level;
struct scoutfs_key_buf *first;
struct scoutfs_key_buf *last;
struct scoutfs_key first;
struct scoutfs_key last;
};
/*
@@ -123,95 +123,29 @@ bool scoutfs_manifest_level0_full(struct super_block *sb)
void scoutfs_manifest_init_entry(struct scoutfs_manifest_entry *ment,
u64 level, u64 segno, u64 seq,
struct scoutfs_key_buf *first,
struct scoutfs_key_buf *last)
struct scoutfs_key *first,
struct scoutfs_key *last)
{
ment->level = level;
ment->segno = segno;
ment->seq = seq;
if (first)
scoutfs_key_clone(&ment->first, first);
else
scoutfs_key_init(&ment->first, NULL, 0);
if (last)
scoutfs_key_clone(&ment->last, last);
else
scoutfs_key_init(&ment->last, NULL, 0);
scoutfs_key_copy_or_zeros(&ment->first, first);
scoutfs_key_copy_or_zeros(&ment->last, last);
}
/*
* level 0 segments have the extra seq up in the btree key.
*/
static struct scoutfs_manifest_btree_key *
alloc_btree_key_val_lens(unsigned first_len, unsigned last_len)
static void init_btree_key(struct scoutfs_manifest_btree_key *mkey,
u8 level, u64 seq, struct scoutfs_key *first)
{
return kmalloc(sizeof(struct scoutfs_manifest_btree_key) +
sizeof(u64) +
sizeof(struct scoutfs_manifest_btree_val) +
first_len + last_len, GFP_NOFS);
mkey->level = level;
scoutfs_key_to_be(&mkey->first_key, first);
mkey->seq = cpu_to_be64(seq);
}
/*
* Initialize the btree key and value for a manifest entry in one contiguous
* allocation.
*/
static struct scoutfs_manifest_btree_key *
alloc_btree_key_val(struct scoutfs_manifest_entry *ment, unsigned *mkey_len,
struct scoutfs_manifest_btree_val **mval_ret,
unsigned *mval_len_ret)
static void init_btree_val(struct scoutfs_manifest_btree_val *mval,
u64 segno, struct scoutfs_key *last)
{
struct scoutfs_manifest_btree_key *mkey;
struct scoutfs_manifest_btree_val *mval;
struct scoutfs_key_buf b_first;
struct scoutfs_key_buf b_last;
unsigned bkey_len;
unsigned mval_len;
__be64 seq;
mkey = alloc_btree_key_val_lens(ment->first.key_len, ment->last.key_len);
if (!mkey)
return NULL;
if (ment->level == 0) {
seq = cpu_to_be64(ment->seq);
bkey_len = sizeof(seq);
memcpy(mkey->bkey, &seq, bkey_len);
} else {
bkey_len = ment->first.key_len;
}
*mkey_len = offsetof(struct scoutfs_manifest_btree_key, bkey[bkey_len]);
mval = (void *)mkey + *mkey_len;
if (ment->level == 0) {
scoutfs_key_init(&b_first, mval->keys, ment->first.key_len);
scoutfs_key_init(&b_last, mval->keys + ment->first.key_len,
ment->last.key_len);
mval_len = sizeof(struct scoutfs_manifest_btree_val) +
ment->first.key_len + ment->last.key_len;
} else {
scoutfs_key_init(&b_first, mkey->bkey, ment->first.key_len);
scoutfs_key_init(&b_last, mval->keys, ment->last.key_len);
mval_len = sizeof(struct scoutfs_manifest_btree_val) +
ment->last.key_len;
}
mkey->level = ment->level;
mval->segno = cpu_to_le64(ment->segno);
mval->seq = cpu_to_le64(ment->seq);
mval->first_key_len = cpu_to_le16(ment->first.key_len);
mval->last_key_len = cpu_to_le16(ment->last.key_len);
scoutfs_key_copy(&b_first, &ment->first);
scoutfs_key_copy(&b_last, &ment->last);
if (mval_ret) {
*mval_ret = mval;
*mval_len_ret = mval_len;
}
return mkey;
mval->segno = cpu_to_le64(segno);
mval->last_key = *last;
}
/* initialize a native manifest entry to point to the btree key and value */
@@ -222,50 +156,12 @@ static void init_ment_iref(struct scoutfs_manifest_entry *ment,
struct scoutfs_manifest_btree_val *mval = iref->val;
ment->level = mkey->level;
scoutfs_key_from_be(&ment->first, &mkey->first_key);
ment->seq = be64_to_cpu(mkey->seq);
ment->segno = le64_to_cpu(mval->segno);
ment->seq = le64_to_cpu(mval->seq);
if (ment->level == 0) {
scoutfs_key_init(&ment->first, mval->keys,
le16_to_cpu(mval->first_key_len));
scoutfs_key_init(&ment->last, mval->keys +
le16_to_cpu(mval->first_key_len),
le16_to_cpu(mval->last_key_len));
} else {
scoutfs_key_init(&ment->first, mkey->bkey,
le16_to_cpu(mval->first_key_len));
scoutfs_key_init(&ment->last, mval->keys,
le16_to_cpu(mval->last_key_len));
}
ment->last = mval->last_key;
}
/*
* Fill the callers max-size btree key with the given values and return
* its length.
*/
static unsigned init_btree_key(struct scoutfs_manifest_btree_key *mkey,
u8 level, u64 seq, struct scoutfs_key_buf *first)
{
struct scoutfs_key_buf b_first;
unsigned bkey_len;
__be64 bseq;
mkey->level = level;
if (level == 0) {
bseq = cpu_to_be64(seq);
bkey_len = sizeof(bseq);
memcpy(mkey->bkey, &bseq, bkey_len);
} else if (first) {
scoutfs_key_init(&b_first, mkey->bkey, first->key_len);
scoutfs_key_copy(&b_first, first);
bkey_len = first->key_len;
} else {
bkey_len = 0;
}
return offsetof(struct scoutfs_manifest_btree_key, bkey[bkey_len]);
}
/*
* Insert a new manifest entry in the ring. The ring allocates a new
@@ -279,29 +175,25 @@ int scoutfs_manifest_add(struct super_block *sb,
DECLARE_MANIFEST(sb, mani);
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_super_block *super = &sbi->super;
struct scoutfs_manifest_btree_key *mkey;
struct scoutfs_manifest_btree_val *mval;
unsigned mkey_len;
unsigned mval_len;
struct scoutfs_manifest_btree_key mkey;
struct scoutfs_manifest_btree_val mval;
int ret;
lockdep_assert_held(&mani->rwsem);
mkey = alloc_btree_key_val(ment, &mkey_len, &mval, &mval_len);
if (!mkey)
return -ENOMEM;
init_btree_key(&mkey, ment->level, ment->seq, &ment->first);
init_btree_val(&mval, ment->segno, &ment->last);
trace_scoutfs_manifest_add(sb, ment->level, ment->segno, ment->seq,
&ment->first, &ment->last);
ret = scoutfs_btree_insert(sb, &super->manifest.root, mkey, mkey_len,
mval, mval_len);
ret = scoutfs_btree_insert(sb, &super->manifest.root,
&mkey, sizeof(mkey), &mval, sizeof(mval));
if (ret == 0) {
mani->nr_levels = max_t(u8, mani->nr_levels, ment->level + 1);
add_level_count(sb, ment->level, 1);
}
kfree(mkey);
return ret;
}
@@ -317,8 +209,7 @@ int scoutfs_manifest_del(struct super_block *sb,
DECLARE_MANIFEST(sb, mani);
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_super_block *super = &sbi->super;
struct scoutfs_manifest_btree_key *mkey;
unsigned mkey_len;
struct scoutfs_manifest_btree_key mkey;
int ret;
trace_scoutfs_manifest_delete(sb, ment->level, ment->segno, ment->seq,
@@ -326,15 +217,13 @@ int scoutfs_manifest_del(struct super_block *sb,
lockdep_assert_held(&mani->rwsem);
mkey = alloc_btree_key_val(ment, &mkey_len, NULL, NULL);
if (!mkey)
return -ENOMEM;
init_btree_key(&mkey, ment->level, ment->seq, &ment->first);
ret = scoutfs_btree_delete(sb, &super->manifest.root, mkey, mkey_len);
ret = scoutfs_btree_delete(sb, &super->manifest.root,
&mkey, sizeof(mkey));
if (ret == 0)
add_level_count(sb, ment->level, -1ULL);
kfree(mkey);
return ret;
}
@@ -367,8 +256,6 @@ static void free_ref(struct super_block *sb, struct manifest_ref *ref)
if (!IS_ERR_OR_NULL(ref)) {
WARN_ON_ONCE(!list_empty(&ref->entry));
scoutfs_seg_put(ref->seg);
scoutfs_key_free(sb, ref->first);
scoutfs_key_free(sb, ref->last);
kfree(ref);
}
}
@@ -383,15 +270,11 @@ static int alloc_manifest_ref(struct super_block *sb, struct list_head *ref_list
struct manifest_ref *ref;
ref = kzalloc(sizeof(struct manifest_ref), GFP_NOFS);
if (ref) {
ref->first = scoutfs_key_dup(sb, &ment->first);
ref->last = scoutfs_key_dup(sb, &ment->last);
}
if (!ref || !ref->first || !ref->last) {
free_ref(sb, ref);
if (!ref)
return -ENOMEM;
}
ref->first = ment->first;
ref->last = ment->last;
ref->level = ment->level;
ref->segno = ment->segno;
ref->seq = ment->seq;
@@ -410,7 +293,7 @@ static int alloc_manifest_ref(struct super_block *sb, struct list_head *ref_list
static int btree_prev_overlap_or_next(struct super_block *sb,
struct scoutfs_btree_root *root,
void *key, unsigned key_len,
struct scoutfs_key_buf *start, u8 level,
struct scoutfs_key *start, u8 level,
struct scoutfs_btree_item_ref *iref)
{
struct scoutfs_manifest_entry ment;
@@ -436,55 +319,63 @@ static int btree_prev_overlap_or_next(struct super_block *sb,
/*
* Get references to all the level 0 segments whose item ranges
* intersect with the callers range. We walk the manifest backwards so
* that we end up adding refs to the caller's list reverse sorted by
* sequence, which is what they want to be able to use the segment with
* the newest item.
* intersect with the callers range. The entries are sorted by their
* first key so we can stop searching once our end key can only keep
* being less than the increasing start key.
*
* This can return -ESTALE if it reads through stale btree blocks.
*/
static int get_zero_refs(struct super_block *sb,
struct scoutfs_btree_root *root,
struct scoutfs_key_buf *start,
struct scoutfs_key_buf *end,
struct scoutfs_key *start,
struct scoutfs_key *end,
struct list_head *ref_list)
{
struct scoutfs_manifest_btree_key *mkey;
struct scoutfs_manifest_btree_key mkey;
struct scoutfs_manifest_entry ment;
SCOUTFS_BTREE_ITEM_REF(iref);
SCOUTFS_BTREE_ITEM_REF(prev);
unsigned mkey_len;
struct scoutfs_key zeros;
int cmp;
int ret;
scoutfs_manifest_init_entry(&ment, 0, 0, 0, start, NULL);
mkey = alloc_btree_key_val(&ment, &mkey_len, NULL, NULL);
if (!mkey)
return -ENOMEM;
scoutfs_key_set_zeros(&zeros);
init_btree_key(&mkey, 0, 0, &zeros);
for (;;) {
ret = scoutfs_btree_next(sb, root, &mkey, sizeof(mkey), &iref);
if (ret < 0) {
if (ret == -ENOENT)
ret = 0;
break;
}
/* get level 0 segments that overlap with the missing range */
mkey_len = init_btree_key(mkey, 0, ~0ULL, NULL);
ret = scoutfs_btree_prev(sb, root, mkey, mkey_len, &iref);
while (ret == 0) {
init_ment_iref(&ment, &iref);
scoutfs_btree_put_iref(&iref);
if (scoutfs_key_compare_ranges(start, end, &ment.first,
&ment.last) == 0) {
/* done if we went past level 0 */
if (ment.level > 0) {
ret = 0;
break;
}
cmp = scoutfs_key_compare_ranges(start, end, &ment.first,
&ment.last);
/* done if all the ments will be greater */
if (cmp < 0) {
ret = 0;
break;
}
if (cmp == 0) {
ret = alloc_manifest_ref(sb, ref_list, &ment);
if (ret)
break;
}
swap(prev, iref);
ret = scoutfs_btree_before(sb, root, prev.key, prev.key_len,
&iref);
scoutfs_btree_put_iref(&prev);
scoutfs_key_inc(&ment.first);
init_btree_key(&mkey, ment.level, ment.seq, &ment.first);
}
if (ret == -ENOENT)
ret = 0;
scoutfs_btree_put_iref(&iref);
scoutfs_btree_put_iref(&prev);
kfree(mkey);
return ret;
}
@@ -502,37 +393,29 @@ static int get_zero_refs(struct super_block *sb,
*/
static int get_nonzero_refs(struct super_block *sb,
struct scoutfs_btree_root *root,
struct scoutfs_key_buf *key,
struct scoutfs_key_buf *end,
struct scoutfs_key *key,
struct scoutfs_key *end,
struct list_head *ref_list)
{
struct scoutfs_manifest_btree_key *mkey;
struct scoutfs_manifest_btree_key mkey;
struct scoutfs_manifest_entry ment;
SCOUTFS_BTREE_ITEM_REF(iref);
SCOUTFS_BTREE_ITEM_REF(prev);
unsigned mkey_len;
int ret;
int i;
scoutfs_manifest_init_entry(&ment, 0, 0, 0, key, NULL);
mkey = alloc_btree_key_val(&ment, &mkey_len, NULL, NULL);
if (!mkey)
return -ENOMEM;
mkey_len = init_btree_key(mkey, 1, 0, key);
for (i = 1; ; i++) {
mkey->level = i;
init_btree_key(&mkey, i, 0, key);
scoutfs_btree_put_iref(&iref);
ret = btree_prev_overlap_or_next(sb, root, mkey, mkey_len, key,
i, &iref);
ret = btree_prev_overlap_or_next(sb, root, &mkey, sizeof(mkey),
key, i, &iref);
if (ret < 0) {
if (ret == -ENOENT)
ret = 0;
goto out;
break;
}
init_ment_iref(&ment, &iref);
scoutfs_btree_put_iref(&iref);
if (ment.level != i ||
scoutfs_key_compare(&ment.first, end) > 0)
@@ -540,14 +423,9 @@ static int get_nonzero_refs(struct super_block *sb,
ret = alloc_manifest_ref(sb, ref_list, &ment);
if (ret)
goto out;
break;
}
ret = 0;
out:
scoutfs_btree_put_iref(&iref);
scoutfs_btree_put_iref(&prev);
kfree(mkey);
return ret;
}
@@ -630,15 +508,15 @@ static int cmp_ment_ref_level_seq(void *priv, struct list_head *A,
* as long as we hold refs.
*/
int scoutfs_manifest_read_items(struct super_block *sb,
struct scoutfs_key_buf *key,
struct scoutfs_key_buf *start,
struct scoutfs_key_buf *end)
struct scoutfs_key *key,
struct scoutfs_key *start,
struct scoutfs_key *end)
{
struct scoutfs_key_buf item_key;
struct scoutfs_key_buf found_key;
struct scoutfs_key_buf batch_end;
struct scoutfs_key_buf seg_start;
struct scoutfs_key_buf seg_end;
struct scoutfs_key item_key;
struct scoutfs_key found_key;
struct scoutfs_key batch_end;
struct scoutfs_key seg_start;
struct scoutfs_key seg_end;
struct scoutfs_btree_root root;
struct scoutfs_segment *seg;
struct manifest_ref *ref;
@@ -666,8 +544,8 @@ int scoutfs_manifest_read_items(struct super_block *sb,
last_root_seq = 0;
retry_stale:
scoutfs_key_clone(&seg_start, start);
scoutfs_key_clone(&seg_end, end);
seg_start = *start;
seg_end = *end;
ret = scoutfs_client_get_manifest_root(sb, &root);
if (ret)
@@ -681,13 +559,13 @@ retry_stale:
/* clamp start and end to the segment boundaries, including key */
list_for_each_entry(ref, &ref_list, entry) {
if (scoutfs_key_compare(ref->first, &seg_start) > 0 &&
scoutfs_key_compare(ref->first, key) <= 0)
scoutfs_key_clone(&seg_start, ref->first);
if (scoutfs_key_compare(&ref->first, &seg_start) > 0 &&
scoutfs_key_compare(&ref->first, key) <= 0)
seg_start = ref->first;
if (scoutfs_key_compare(ref->last, &seg_end) < 0 &&
scoutfs_key_compare(ref->last, key) >= 0)
scoutfs_key_clone(&seg_end, ref->last);
if (scoutfs_key_compare(&ref->last, &seg_end) < 0 &&
scoutfs_key_compare(&ref->last, key) >= 0)
seg_end = ref->last;
}
trace_scoutfs_read_item_keys(sb, key, start, end, &seg_start, &seg_end);
@@ -703,8 +581,9 @@ retry_stale:
/* submit reads for all the segments */
list_for_each_entry(ref, &ref_list, entry) {
trace_scoutfs_read_item_segment(sb, ref->level, ref->segno,
ref->seq, ref->first, ref->last);
trace_scoutfs_read_item_segment(sb, ref->level, ref->segno,
ref->seq, &ref->first,
&ref->last);
seg = scoutfs_seg_submit_read(sb, ref->segno);
if (IS_ERR(seg)) {
@@ -752,9 +631,9 @@ retry_stale:
* items or if the next item is past the keys
* that our segments can see.
*/
ret = scoutfs_seg_item_ptrs(ref->seg, ref->off,
&item_key, &item_val,
&item_flags);
ret = scoutfs_seg_get_item(ref->seg, ref->off,
&item_key, &item_val,
&item_flags);
if (ret < 0 ||
scoutfs_key_compare(&item_key, &seg_end) > 0) {
ref->off = -1;
@@ -773,7 +652,7 @@ retry_stale:
}
/* remember new least key */
scoutfs_key_clone(&found_key, &item_key);
found_key = item_key;
found_val = item_val;
found_flags = item_flags;
ref->found_ctr = ++found_ctr;
@@ -782,7 +661,7 @@ retry_stale:
/* ran out of keys in segs, range extends to seg end */
if (!found) {
scoutfs_key_clone(&batch_end, &seg_end);
batch_end = seg_end;
ret = 0;
break;
}
@@ -808,7 +687,7 @@ retry_stale:
}
/* the last successful key determines range end until run out */
scoutfs_key_clone(&batch_end, &found_key);
batch_end = found_key;
/* if we just saw the end key then we're done */
if (scoutfs_key_compare(&found_key, &seg_end) == 0) {
@@ -864,14 +743,12 @@ out:
* Returns 0 if it set next_key and -ENOENT if the key was after all the
* segments in the manifest.
*/
int scoutfs_manifest_next_key(struct super_block *sb,
struct scoutfs_key_buf *key,
struct scoutfs_key_buf *next_key)
int scoutfs_manifest_next_key(struct super_block *sb, struct scoutfs_key *key,
struct scoutfs_key *next_key)
{
struct scoutfs_key_buf item_key;
struct scoutfs_key_buf end;
struct scoutfs_key item_key;
struct scoutfs_key end;
struct scoutfs_btree_root root;
struct scoutfs_inode_key end_key;
struct scoutfs_segment *seg;
struct manifest_ref *ref;
struct manifest_ref *tmp;
@@ -887,8 +764,7 @@ retry_stale:
if (ret)
goto out;
scoutfs_key_init(&end, &end_key, sizeof(end_key));
scoutfs_key_set_max(&end);
scoutfs_key_set_ones(&end);
ret = get_zero_refs(sb, &root, key, &end, &ref_list) ?:
get_nonzero_refs(sb, &root, key, &end, &ref_list);
@@ -929,8 +805,9 @@ retry_stale:
found = false;
list_for_each_entry(ref, &ref_list, entry) {
if (ref->level > 0 &&
(!found || scoutfs_key_compare(ref->last, next_key) < 0)) {
scoutfs_key_copy(next_key, ref->last);
(!found ||
scoutfs_key_compare(&ref->last, next_key) < 0)) {
*next_key = ref->last;
found = true;
}
@@ -942,13 +819,13 @@ retry_stale:
if (ref->off < 0)
continue;
ret = scoutfs_seg_item_ptrs(ref->seg, ref->off, &item_key,
NULL, NULL);
ret = scoutfs_seg_get_item(ref->seg, ref->off, &item_key,
NULL, NULL);
if (ret < 0)
continue;
if (!found || scoutfs_key_compare(&item_key, next_key) < 0) {
scoutfs_key_copy(next_key, &item_key);
*next_key = item_key;
found = true;
}
}
@@ -996,19 +873,23 @@ int scoutfs_manifest_next_compact(struct super_block *sb, void *data)
DECLARE_MANIFEST(sb, mani);
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_super_block *super = &sbi->super;
struct scoutfs_manifest_btree_key mkey;
struct scoutfs_manifest_entry next;
struct scoutfs_manifest_entry ment;
struct scoutfs_manifest_entry over;
struct scoutfs_manifest_btree_key *mkey = NULL;
SCOUTFS_BTREE_ITEM_REF(iref);
SCOUTFS_BTREE_ITEM_REF(over_iref);
SCOUTFS_BTREE_ITEM_REF(prev);
unsigned mkey_len;
struct scoutfs_key zeros;
bool wrapped;
bool sticky;
int level;
int ret;
int nr = 0;
int i;
scoutfs_key_set_zeros(&zeros);
down_write(&mani->rwsem);
for (level = mani->nr_levels - 1; level >= 0; level--) {
@@ -1024,45 +905,60 @@ int scoutfs_manifest_next_compact(struct super_block *sb, void *data)
goto out;
}
/* alloc a full size mkey, fill it with whatever search key */
mkey = alloc_btree_key_val_lens(SCOUTFS_MAX_KEY_SIZE, 0);
if (!mkey) {
ret = -ENOMEM;
goto out;
}
/* find the oldest level 0 or the next higher order level by key */
/* fill ment and ret == 0 if we find an entry at the level */
if (level == 0) {
/* find the oldest level 0 */
mkey_len = init_btree_key(mkey, 0, 0, NULL);
ret = scoutfs_btree_next(sb, &super->manifest.root,
mkey, mkey_len, &iref);
init_btree_key(&mkey, 0, 0, &zeros);
ment.seq = U64_MAX;
for (;;) {
ret = scoutfs_btree_next(sb, &super->manifest.root,
&mkey, sizeof(mkey), &iref);
if (ret < 0) {
if (ret == -ENOENT && ment.seq != U64_MAX)
ret = 0;
break;
}
init_ment_iref(&next, &iref);
scoutfs_btree_put_iref(&iref);
if (next.level > 0) {
if (ment.seq == U64_MAX)
ret = -ENOENT;
break;
}
if (next.seq < ment.seq)
ment = next;
scoutfs_key_inc(&next.first);
init_btree_key(&mkey, next.level, next.seq,
&next.first);
}
} else {
/* find the next segment after the compaction at this level */
mkey_len = init_btree_key(mkey, level, 0,
mani->compact_keys[level]);
init_btree_key(&mkey, level, 0, &mani->compact_keys[level]);
wrapped = false;
again:
ret = scoutfs_btree_next(sb, &super->manifest.root,
mkey, mkey_len, &iref);
&mkey, sizeof(mkey), &iref);
if (ret == 0) {
init_ment_iref(&ment, &iref);
scoutfs_btree_put_iref(&iref);
if (ment.level != level)
ret = -ENOENT;
}
if (ret == -ENOENT) {
/* .. possibly wrapping to the first key in level */
mkey_len = init_btree_key(mkey, level, 0, NULL);
scoutfs_btree_put_iref(&iref);
ret = scoutfs_btree_next(sb, &super->manifest.root,
mkey, mkey_len, &iref);
/* try again if we wrapped */
if (ret == -ENOENT && !wrapped) {
init_btree_key(&mkey, level, 0, &zeros);
wrapped = true;
goto again;
}
}
if (ret == 0) {
init_ment_iref(&ment, &iref);
if (ment.level != level)
goto out;
}
if (ret < 0) {
if (ret == -ENOENT)
ret = 0;
@@ -1076,10 +972,10 @@ int scoutfs_manifest_next_compact(struct super_block *sb, void *data)
nr++;
/* and add a fanout's worth of lower overlapping segments */
mkey_len = init_btree_key(mkey, level + 1, 0, &ment.first);
init_btree_key(&mkey, level + 1, 0, &ment.first);
ret = btree_prev_overlap_or_next(sb, &super->manifest.root,
mkey, mkey_len,
&ment.first, level + 1, &over_iref);
&mkey, sizeof(mkey), &ment.first,
level + 1, &over_iref);
sticky = false;
for (i = 0; ret == 0 && i < SCOUTFS_MANIFEST_FANOUT + 1; i++) {
init_ment_iref(&over, &over_iref);
@@ -1112,14 +1008,13 @@ int scoutfs_manifest_next_compact(struct super_block *sb, void *data)
scoutfs_compact_describe(sb, data, level, mani->nr_levels - 1, sticky);
/* record the next key to start from */
scoutfs_key_copy(mani->compact_keys[level], &ment.last);
scoutfs_key_inc(mani->compact_keys[level]);
mani->compact_keys[level] = ment.last;
scoutfs_key_inc(&mani->compact_keys[level]);
ret = 0;
out:
up_write(&mani->rwsem);
kfree(mkey);
scoutfs_btree_put_iref(&iref);
scoutfs_btree_put_iref(&over_iref);
scoutfs_btree_put_iref(&prev);
@@ -1140,18 +1035,8 @@ int scoutfs_manifest_setup(struct super_block *sb)
init_rwsem(&mani->rwsem);
for (i = 0; i < ARRAY_SIZE(mani->compact_keys); i++) {
mani->compact_keys[i] = scoutfs_key_alloc(sb,
SCOUTFS_MAX_KEY_SIZE);
if (!mani->compact_keys[i]) {
while (--i >= 0)
scoutfs_key_free(sb, mani->compact_keys[i]);
kfree(mani);
return -ENOMEM;
}
scoutfs_key_set_min(mani->compact_keys[i]);
}
for (i = 0; i < ARRAY_SIZE(mani->compact_keys); i++)
scoutfs_key_set_zeros(&mani->compact_keys[i]);
for (i = ARRAY_SIZE(super->manifest.level_counts) - 1; i >= 0; i--) {
if (super->manifest.level_counts[i]) {
@@ -1177,11 +1062,8 @@ void scoutfs_manifest_destroy(struct super_block *sb)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct manifest *mani = sbi->manifest;
int i;
if (mani) {
for (i = 0; i < ARRAY_SIZE(mani->compact_keys); i++)
scoutfs_key_free(sb, mani->compact_keys[i]);
kfree(mani);
sbi->manifest = NULL;
}
+9 -10
View File
@@ -15,14 +15,14 @@ struct scoutfs_manifest_entry {
u8 level;
u64 segno;
u64 seq;
struct scoutfs_key_buf first;
struct scoutfs_key_buf last;
struct scoutfs_key first;
struct scoutfs_key last;
};
void scoutfs_manifest_init_entry(struct scoutfs_manifest_entry *ment,
u64 level, u64 segno, u64 seq,
struct scoutfs_key_buf *first,
struct scoutfs_key_buf *last);
struct scoutfs_key *first,
struct scoutfs_key *last);
int scoutfs_manifest_add(struct super_block *sb,
struct scoutfs_manifest_entry *ment);
int scoutfs_manifest_del(struct super_block *sb,
@@ -32,12 +32,11 @@ int scoutfs_manifest_lock(struct super_block *sb);
int scoutfs_manifest_unlock(struct super_block *sb);
int scoutfs_manifest_read_items(struct super_block *sb,
struct scoutfs_key_buf *key,
struct scoutfs_key_buf *start,
struct scoutfs_key_buf *end);
int scoutfs_manifest_next_key(struct super_block *sb,
struct scoutfs_key_buf *key,
struct scoutfs_key_buf *next_key);
struct scoutfs_key *key,
struct scoutfs_key *start,
struct scoutfs_key *end);
int scoutfs_manifest_next_key(struct super_block *sb, struct scoutfs_key *key,
struct scoutfs_key *next_key);
int scoutfs_manifest_next_compact(struct super_block *sb, void *data);
-14
View File
@@ -6,27 +6,13 @@
void __printf(4, 5) scoutfs_msg(struct super_block *sb, const char *prefix,
const char *str, const char *fmt, ...);
/*
* The _sk variants wrap the message in the SK_PCPU calls which safely
* manage the use of per-cpu key buffers in the arguments.
*/
#define scoutfs_err(sb, fmt, args...) \
scoutfs_msg(sb, KERN_ERR, " error", fmt, ##args)
#define scoutfs_err_sk(sb, fmt, args...) \
SK_PCPU(scoutfs_err(sb, fmt, ##args))
#define scoutfs_warn(sb, fmt, args...) \
scoutfs_msg(sb, KERN_WARNING, " warning", fmt, ##args)
#define scoutfs_warn_sk(sb, fmt, args...) \
SK_PCPU(scoutfs_warn(sb, fmt, ##args))
#define scoutfs_info(sb, fmt, args...) \
scoutfs_msg(sb, KERN_INFO, "", fmt, ##args)
#define scoutfs_info_sk(sb, fmt, args...) \
SK_PCPU(scoutfs_info(sb, fmt, ##args))
#endif
+133 -188
View File
@@ -317,45 +317,6 @@ TRACE_EVENT(scoutfs_item_next_same_ret,
TP_printk(FSID_FMT" ret %d", __entry->fsid, __entry->ret)
);
TRACE_EVENT(scoutfs_item_next_same_min,
TP_PROTO(struct super_block *sb, int key_len, int len),
TP_ARGS(sb, key_len, len),
TP_STRUCT__entry(
__field(__u64, fsid)
__field(int, key_len)
__field(int, len)
),
TP_fast_assign(
__entry->fsid = FSID_ARG(sb);
__entry->key_len = key_len;
__entry->len = len;
),
TP_printk(FSID_FMT" key len %u min val len %d", __entry->fsid,
__entry->key_len, __entry->len)
);
TRACE_EVENT(scoutfs_item_next_same_min_ret,
TP_PROTO(struct super_block *sb, int ret),
TP_ARGS(sb, ret),
TP_STRUCT__entry(
__field(__u64, fsid)
__field(int, ret)
),
TP_fast_assign(
__entry->fsid = FSID_ARG(sb);
__entry->ret = ret;
),
TP_printk(FSID_FMT" ret %d", __entry->fsid, __entry->ret)
);
TRACE_EVENT(scoutfs_item_next_ret,
TP_PROTO(struct super_block *sb, int ret),
@@ -619,25 +580,22 @@ TRACE_EVENT(scoutfs_release_trans,
struct scoutfs_item_count *res,
struct scoutfs_item_count *act, unsigned int tri_holders,
unsigned int tri_writing, unsigned int tri_items,
unsigned int tri_keys, unsigned int tri_vals),
unsigned int tri_vals),
TP_ARGS(sb, rsv, rsv_holders, res, act, tri_holders, tri_writing,
tri_items, tri_keys, tri_vals),
tri_items, tri_vals),
TP_STRUCT__entry(
__field(__u64, fsid)
__field(void *, rsv)
__field(unsigned int, rsv_holders)
__field(int, res_items)
__field(int, res_keys)
__field(int, res_vals)
__field(int, act_items)
__field(int, act_keys)
__field(int, act_vals)
__field(unsigned int, tri_holders)
__field(unsigned int, tri_writing)
__field(unsigned int, tri_items)
__field(unsigned int, tri_keys)
__field(unsigned int, tri_vals)
),
@@ -646,25 +604,21 @@ TRACE_EVENT(scoutfs_release_trans,
__entry->rsv = rsv;
__entry->rsv_holders = rsv_holders;
__entry->res_items = res->items;
__entry->res_keys = res->keys;
__entry->res_vals = res->vals;
__entry->act_items = act->items;
__entry->act_keys = act->keys;
__entry->act_vals = act->vals;
__entry->tri_holders = tri_holders;
__entry->tri_writing = tri_writing;
__entry->tri_items = tri_items;
__entry->tri_keys = tri_keys;
__entry->tri_vals = tri_vals;
),
TP_printk(FSID_FMT" rsv %p holders %u reserved %u.%u.%u actual "
"%d.%d.%d, trans holders %u writing %u reserved "
"%u.%u.%u", __entry->fsid, __entry->rsv,
__entry->rsv_holders, __entry->res_items, __entry->res_keys,
__entry->res_vals, __entry->act_items, __entry->act_keys,
TP_printk(FSID_FMT" rsv %p holders %u reserved %u.%u actual "
"%d.%d, trans holders %u writing %u reserved "
"%u.%u", __entry->fsid, __entry->rsv, __entry->rsv_holders,
__entry->res_items, __entry->res_vals, __entry->act_items,
__entry->act_vals, __entry->tri_holders, __entry->tri_writing,
__entry->tri_items, __entry->tri_keys, __entry->tri_vals)
__entry->tri_items, __entry->tri_vals)
);
TRACE_EVENT(scoutfs_trans_acquired_hold,
@@ -673,59 +627,50 @@ TRACE_EVENT(scoutfs_trans_acquired_hold,
struct scoutfs_item_count *res,
struct scoutfs_item_count *act, unsigned int tri_holders,
unsigned int tri_writing, unsigned int tri_items,
unsigned int tri_keys, unsigned int tri_vals),
unsigned int tri_vals),
TP_ARGS(sb, cnt, rsv, rsv_holders, res, act, tri_holders, tri_writing,
tri_items, tri_keys, tri_vals),
tri_items, tri_vals),
TP_STRUCT__entry(
__field(__u64, fsid)
__field(int, cnt_items)
__field(int, cnt_keys)
__field(int, cnt_vals)
__field(void *, rsv)
__field(unsigned int, rsv_holders)
__field(int, res_items)
__field(int, res_keys)
__field(int, res_vals)
__field(int, act_items)
__field(int, act_keys)
__field(int, act_vals)
__field(unsigned int, tri_holders)
__field(unsigned int, tri_writing)
__field(unsigned int, tri_items)
__field(unsigned int, tri_keys)
__field(unsigned int, tri_vals)
),
TP_fast_assign(
__entry->fsid = FSID_ARG(sb);
__entry->cnt_items = cnt->items;
__entry->cnt_keys = cnt->keys;
__entry->cnt_vals = cnt->vals;
__entry->rsv = rsv;
__entry->rsv_holders = rsv_holders;
__entry->res_items = res->items;
__entry->res_keys = res->keys;
__entry->res_vals = res->vals;
__entry->act_items = act->items;
__entry->act_keys = act->keys;
__entry->act_vals = act->vals;
__entry->tri_holders = tri_holders;
__entry->tri_writing = tri_writing;
__entry->tri_items = tri_items;
__entry->tri_keys = tri_keys;
__entry->tri_vals = tri_vals;
),
TP_printk(FSID_FMT" cnt %u.%u.%u, rsv %p holders %u reserved %u.%u.%u "
"actual %d.%d.%d, trans holders %u writing %u reserved "
"%u.%u.%u", __entry->fsid, __entry->cnt_items,
__entry->cnt_keys, __entry->cnt_vals, __entry->rsv,
__entry->rsv_holders, __entry->res_items, __entry->res_keys,
__entry->res_vals, __entry->act_items, __entry->act_keys,
TP_printk(FSID_FMT" cnt %u.%u, rsv %p holders %u reserved %u.%u "
"actual %d.%d, trans holders %u writing %u reserved "
"%u.%u", __entry->fsid, __entry->cnt_items,
__entry->cnt_vals, __entry->rsv, __entry->rsv_holders,
__entry->res_items, __entry->res_vals, __entry->act_items,
__entry->act_vals, __entry->tri_holders, __entry->tri_writing,
__entry->tri_items, __entry->tri_keys, __entry->tri_vals)
__entry->tri_items, __entry->tri_vals)
);
TRACE_EVENT(scoutfs_ioc_release_ret,
@@ -1102,30 +1047,30 @@ TRACE_EVENT(scoutfs_advance_dirty_super,
);
TRACE_EVENT(scoutfs_dir_add_next_linkref,
TP_PROTO(struct super_block *sb, __u64 ino, __u64 dir_ino, int ret,
unsigned int key_len),
TP_PROTO(struct super_block *sb, __u64 ino, __u64 dir_ino,
__u64 dir_pos, int ret),
TP_ARGS(sb, ino, dir_ino, ret, key_len),
TP_ARGS(sb, ino, dir_ino, dir_pos, ret),
TP_STRUCT__entry(
__field(__u64, fsid)
__field(__u64, ino)
__field(__u64, dir_ino)
__field(__u64, dir_pos)
__field(int, ret)
__field(unsigned int, key_len)
),
TP_fast_assign(
__entry->fsid = FSID_ARG(sb);
__entry->ino = ino;
__entry->dir_ino = dir_ino;
__entry->dir_pos = dir_pos;
__entry->ret = ret;
__entry->key_len = key_len;
),
TP_printk(FSID_FMT" ino %llu dir_ino %llu ret %d key_len %u",
__entry->fsid, __entry->ino, __entry->dir_ino, __entry->ret,
__entry->key_len)
TP_printk(FSID_FMT" ino %llu dir_ino %llu dis_pos %llu ret %d",
__entry->fsid, __entry->ino, __entry->dir_ino,
__entry->dir_ino, __entry->ret)
);
TRACE_EVENT(scoutfs_compact_func,
@@ -1342,98 +1287,97 @@ TRACE_EVENT(scoutfs_scan_orphans,
DECLARE_EVENT_CLASS(scoutfs_manifest_class,
TP_PROTO(struct super_block *sb, u8 level, u64 segno, u64 seq,
struct scoutfs_key_buf *first, struct scoutfs_key_buf *last),
struct scoutfs_key *first, struct scoutfs_key *last),
TP_ARGS(sb, level, segno, seq, first, last),
TP_STRUCT__entry(
__field(u8, level)
__field(u64, segno)
__field(u64, seq)
__dynamic_array(char, first, scoutfs_key_str(NULL, first))
__dynamic_array(char, last, scoutfs_key_str(NULL, last))
__field_struct(struct scoutfs_key, first)
__field_struct(struct scoutfs_key, last)
),
TP_fast_assign(
__entry->level = level;
__entry->segno = segno;
__entry->seq = seq;
scoutfs_key_str(__get_dynamic_array(first), first);
scoutfs_key_str(__get_dynamic_array(last), last);
scoutfs_key_copy_or_zeros(&__entry->first, first);
scoutfs_key_copy_or_zeros(&__entry->last, last);
),
TP_printk("level %u segno %llu seq %llu first %s last %s",
TP_printk("level %u segno %llu seq %llu first "SK_FMT" last "SK_FMT,
__entry->level, __entry->segno, __entry->seq,
__get_str(first), __get_str(last))
SK_ARG(&__entry->first), SK_ARG(&__entry->last))
);
DEFINE_EVENT(scoutfs_manifest_class, scoutfs_manifest_add,
TP_PROTO(struct super_block *sb, u8 level, u64 segno, u64 seq,
struct scoutfs_key_buf *first, struct scoutfs_key_buf *last),
struct scoutfs_key *first, struct scoutfs_key *last),
TP_ARGS(sb, level, segno, seq, first, last)
);
DEFINE_EVENT(scoutfs_manifest_class, scoutfs_manifest_delete,
TP_PROTO(struct super_block *sb, u8 level, u64 segno, u64 seq,
struct scoutfs_key_buf *first, struct scoutfs_key_buf *last),
struct scoutfs_key *first, struct scoutfs_key *last),
TP_ARGS(sb, level, segno, seq, first, last)
);
DEFINE_EVENT(scoutfs_manifest_class, scoutfs_compact_input,
TP_PROTO(struct super_block *sb, u8 level, u64 segno, u64 seq,
struct scoutfs_key_buf *first, struct scoutfs_key_buf *last),
struct scoutfs_key *first, struct scoutfs_key *last),
TP_ARGS(sb, level, segno, seq, first, last)
);
DEFINE_EVENT(scoutfs_manifest_class, scoutfs_read_item_segment,
TP_PROTO(struct super_block *sb, u8 level, u64 segno, u64 seq,
struct scoutfs_key_buf *first, struct scoutfs_key_buf *last),
struct scoutfs_key *first, struct scoutfs_key *last),
TP_ARGS(sb, level, segno, seq, first, last)
);
TRACE_EVENT(scoutfs_read_item_keys,
TP_PROTO(struct super_block *sb,
struct scoutfs_key_buf *key,
struct scoutfs_key_buf *start,
struct scoutfs_key_buf *end,
struct scoutfs_key_buf *seg_start,
struct scoutfs_key_buf *seg_end),
struct scoutfs_key *key,
struct scoutfs_key *start,
struct scoutfs_key *end,
struct scoutfs_key *seg_start,
struct scoutfs_key *seg_end),
TP_ARGS(sb, key, start, end, seg_start, seg_end),
TP_STRUCT__entry(
__field(__u64, fsid)
__dynamic_array(char, key, scoutfs_key_str(NULL, key))
__dynamic_array(char, start, scoutfs_key_str(NULL, start))
__dynamic_array(char, end, scoutfs_key_str(NULL, end))
__dynamic_array(char, seg_start,
scoutfs_key_str(NULL, seg_start))
__dynamic_array(char, seg_end,
scoutfs_key_str(NULL, seg_end))
__field_struct(struct scoutfs_key, key)
__field_struct(struct scoutfs_key, start)
__field_struct(struct scoutfs_key, end)
__field_struct(struct scoutfs_key, seg_start)
__field_struct(struct scoutfs_key, seg_end)
),
TP_fast_assign(
__entry->fsid = FSID_ARG(sb);
scoutfs_key_str(__get_dynamic_array(key), key);
scoutfs_key_str(__get_dynamic_array(start), start);
scoutfs_key_str(__get_dynamic_array(end), end);
scoutfs_key_str(__get_dynamic_array(seg_start), seg_start);
scoutfs_key_str(__get_dynamic_array(seg_end), seg_end);
scoutfs_key_copy_or_zeros(&__entry->key, key);
scoutfs_key_copy_or_zeros(&__entry->start, start);
scoutfs_key_copy_or_zeros(&__entry->end, end);
scoutfs_key_copy_or_zeros(&__entry->seg_start, seg_start);
scoutfs_key_copy_or_zeros(&__entry->seg_end, seg_end);
),
TP_printk("fsid "FSID_FMT" key %s start %s end %s seg_start %s seg_end %s",
__entry->fsid, __get_str(key), __get_str(start),
__get_str(end), __get_str(seg_start), __get_str(seg_end))
TP_printk("fsid "FSID_FMT" key "SK_FMT" start "SK_FMT" end "SK_FMT" seg_start "SK_FMT" seg_end "SK_FMT"",
__entry->fsid, SK_ARG(&__entry->key), SK_ARG(&__entry->start),
SK_ARG(&__entry->end), SK_ARG(&__entry->seg_start),
SK_ARG(&__entry->seg_end))
);
DECLARE_EVENT_CLASS(scoutfs_key_class,
TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *key),
TP_PROTO(struct super_block *sb, struct scoutfs_key *key),
TP_ARGS(sb, key),
TP_STRUCT__entry(
__field(__u64, fsid)
__dynamic_array(char, key, scoutfs_key_str(NULL, key))
__field_struct(struct scoutfs_key, key)
),
TP_fast_assign(
__entry->fsid = FSID_ARG(sb);
scoutfs_key_str(__get_dynamic_array(key), key);
scoutfs_key_copy_or_zeros(&__entry->key, key);
),
TP_printk(FSID_FMT" key %s", __entry->fsid, __get_str(key))
TP_printk(FSID_FMT" key "SK_FMT, __entry->fsid, SK_ARG(&__entry->key))
);
DEFINE_EVENT(scoutfs_key_class, scoutfs_item_lookup,
TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *key),
TP_PROTO(struct super_block *sb, struct scoutfs_key *key),
TP_ARGS(sb, key)
);
@@ -1456,127 +1400,129 @@ TRACE_EVENT(scoutfs_item_lookup_ret,
);
DEFINE_EVENT(scoutfs_key_class, scoutfs_item_insertion,
TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *key),
TP_PROTO(struct super_block *sb, struct scoutfs_key *key),
TP_ARGS(sb, key)
);
DEFINE_EVENT(scoutfs_key_class, scoutfs_item_shrink,
TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *key),
TP_PROTO(struct super_block *sb, struct scoutfs_key *key),
TP_ARGS(sb, key)
);
DEFINE_EVENT(scoutfs_key_class, scoutfs_xattr_get_next_key,
TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *key),
TP_PROTO(struct super_block *sb, struct scoutfs_key *key),
TP_ARGS(sb, key)
);
DECLARE_EVENT_CLASS(scoutfs_range_class,
TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *start,
struct scoutfs_key_buf *end),
TP_PROTO(struct super_block *sb, struct scoutfs_key *start,
struct scoutfs_key *end),
TP_ARGS(sb, start, end),
TP_STRUCT__entry(
__field(__u64, fsid)
__dynamic_array(char, start, scoutfs_key_str(NULL, start))
__dynamic_array(char, end, scoutfs_key_str(NULL, end))
__field_struct(struct scoutfs_key, start)
__field_struct(struct scoutfs_key, end)
),
TP_fast_assign(
__entry->fsid = FSID_ARG(sb);
scoutfs_key_str(__get_dynamic_array(start), start);
scoutfs_key_str(__get_dynamic_array(end), end);
scoutfs_key_copy_or_zeros(&__entry->start, start);
scoutfs_key_copy_or_zeros(&__entry->end, end);
),
TP_printk("fsid "FSID_FMT" start %s end %s",
__entry->fsid, __get_str(start), __get_str(end))
TP_printk("fsid "FSID_FMT" start "SK_FMT" end "SK_FMT,
__entry->fsid, SK_ARG(&__entry->start),
SK_ARG(&__entry->end))
);
DEFINE_EVENT(scoutfs_range_class, scoutfs_item_insert_batch,
TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *start,
struct scoutfs_key_buf *end),
TP_PROTO(struct super_block *sb, struct scoutfs_key *start,
struct scoutfs_key *end),
TP_ARGS(sb, start, end)
);
DEFINE_EVENT(scoutfs_range_class, scoutfs_item_invalidate_range,
TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *start,
struct scoutfs_key_buf *end),
TP_PROTO(struct super_block *sb, struct scoutfs_key *start,
struct scoutfs_key *end),
TP_ARGS(sb, start, end)
);
DEFINE_EVENT(scoutfs_range_class, scoutfs_item_shrink_range,
TP_PROTO(struct super_block *sb, struct scoutfs_key_buf *start,
struct scoutfs_key_buf *end),
TP_PROTO(struct super_block *sb, struct scoutfs_key *start,
struct scoutfs_key *end),
TP_ARGS(sb, start, end)
);
DECLARE_EVENT_CLASS(scoutfs_cached_range_class,
TP_PROTO(struct super_block *sb, void *rng,
struct scoutfs_key_buf *start, struct scoutfs_key_buf *end),
struct scoutfs_key *start, struct scoutfs_key *end),
TP_ARGS(sb, rng, start, end),
TP_STRUCT__entry(
__field(__u64, fsid)
__field(void *, rng)
__dynamic_array(char, start, scoutfs_key_str(NULL, start))
__dynamic_array(char, end, scoutfs_key_str(NULL, end))
__field_struct(struct scoutfs_key, start)
__field_struct(struct scoutfs_key, end)
),
TP_fast_assign(
__entry->fsid = FSID_ARG(sb);
__entry->rng = rng;
scoutfs_key_str(__get_dynamic_array(start), start);
scoutfs_key_str(__get_dynamic_array(end), end);
scoutfs_key_copy_or_zeros(&__entry->start, start);
scoutfs_key_copy_or_zeros(&__entry->end, end);
),
TP_printk("fsid "FSID_FMT" rng %p start %s end %s",
__entry->fsid, __entry->rng, __get_str(start), __get_str(end))
TP_printk("fsid "FSID_FMT" rng %p start "SK_FMT" end "SK_FMT,
__entry->fsid, __entry->rng, SK_ARG(&__entry->start),
SK_ARG(&__entry->end))
);
DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_free,
TP_PROTO(struct super_block *sb, void *rng,
struct scoutfs_key_buf *start, struct scoutfs_key_buf *end),
struct scoutfs_key *start, struct scoutfs_key *end),
TP_ARGS(sb, rng, start, end)
);
DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_ins_rb_insert,
TP_PROTO(struct super_block *sb, void *rng,
struct scoutfs_key_buf *start, struct scoutfs_key_buf *end),
struct scoutfs_key *start, struct scoutfs_key *end),
TP_ARGS(sb, rng, start, end)
);
DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_remove_mid_left,
TP_PROTO(struct super_block *sb, void *rng,
struct scoutfs_key_buf *start, struct scoutfs_key_buf *end),
struct scoutfs_key *start, struct scoutfs_key *end),
TP_ARGS(sb, rng, start, end)
);
DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_remove_start,
TP_PROTO(struct super_block *sb, void *rng,
struct scoutfs_key_buf *start, struct scoutfs_key_buf *end),
struct scoutfs_key *start, struct scoutfs_key *end),
TP_ARGS(sb, rng, start, end)
);
DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_remove_end,
TP_PROTO(struct super_block *sb, void *rng,
struct scoutfs_key_buf *start, struct scoutfs_key_buf *end),
struct scoutfs_key *start, struct scoutfs_key *end),
TP_ARGS(sb, rng, start, end)
);
DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_rem_rb_insert,
TP_PROTO(struct super_block *sb, void *rng,
struct scoutfs_key_buf *start, struct scoutfs_key_buf *end),
struct scoutfs_key *start, struct scoutfs_key *end),
TP_ARGS(sb, rng, start, end)
);
DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_delete_enoent,
TP_PROTO(struct super_block *sb, void *rng,
struct scoutfs_key_buf *start, struct scoutfs_key_buf *end),
struct scoutfs_key *start, struct scoutfs_key *end),
TP_ARGS(sb, rng, start, end)
);
DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_shrink_start,
TP_PROTO(struct super_block *sb, void *rng,
struct scoutfs_key_buf *start, struct scoutfs_key_buf *end),
struct scoutfs_key *start, struct scoutfs_key *end),
TP_ARGS(sb, rng, start, end)
);
DEFINE_EVENT(scoutfs_cached_range_class, scoutfs_item_range_shrink_end,
TP_PROTO(struct super_block *sb, void *rng,
struct scoutfs_key_buf *start, struct scoutfs_key_buf *end),
struct scoutfs_key *start, struct scoutfs_key *end),
TP_ARGS(sb, rng, start, end)
);
@@ -1784,32 +1730,32 @@ DEFINE_EVENT(scoutfs_net_class, scoutfs_client_recv_reply,
TRACE_EVENT(scoutfs_item_next_range_check,
TP_PROTO(struct super_block *sb, int cached,
struct scoutfs_key_buf *key, struct scoutfs_key_buf *pos,
struct scoutfs_key_buf *last, struct scoutfs_key_buf *end,
struct scoutfs_key_buf *range_end),
struct scoutfs_key *key, struct scoutfs_key *pos,
struct scoutfs_key *last, struct scoutfs_key *end,
struct scoutfs_key *range_end),
TP_ARGS(sb, cached, key, pos, last, end, range_end),
TP_STRUCT__entry(
__field(void *, sb)
__field(int, cached)
__dynamic_array(char, key, scoutfs_key_str(NULL, key))
__dynamic_array(char, pos, scoutfs_key_str(NULL, pos))
__dynamic_array(char, last, scoutfs_key_str(NULL, last))
__dynamic_array(char, end, scoutfs_key_str(NULL, end))
__dynamic_array(char, range_end,
scoutfs_key_str(NULL, range_end))
__field_struct(struct scoutfs_key, key)
__field_struct(struct scoutfs_key, pos)
__field_struct(struct scoutfs_key, last)
__field_struct(struct scoutfs_key, end)
__field_struct(struct scoutfs_key, range_end)
),
TP_fast_assign(
__entry->sb = sb;
__entry->cached = cached;
scoutfs_key_str(__get_dynamic_array(key), key);
scoutfs_key_str(__get_dynamic_array(pos), pos);
scoutfs_key_str(__get_dynamic_array(last), last);
scoutfs_key_str(__get_dynamic_array(end), end);
scoutfs_key_str(__get_dynamic_array(range_end), range_end);
scoutfs_key_copy_or_zeros(&__entry->key, key);
scoutfs_key_copy_or_zeros(&__entry->pos, pos);
scoutfs_key_copy_or_zeros(&__entry->last, last);
scoutfs_key_copy_or_zeros(&__entry->end, end);
scoutfs_key_copy_or_zeros(&__entry->range_end, range_end);
),
TP_printk("sb %p cached %d key %s pos %s last %s end %s range_end %s",
__entry->sb, __entry->cached, __get_str(key), __get_str(pos),
__get_str(last), __get_str(end), __get_str(range_end))
TP_printk("sb %p cached %d key "SK_FMT" pos "SK_FMT" last "SK_FMT" end "SK_FMT" range_end "SK_FMT,
__entry->sb, __entry->cached, SK_ARG(&__entry->key),
SK_ARG(&__entry->pos), SK_ARG(&__entry->last),
SK_ARG(&__entry->end), SK_ARG(&__entry->range_end))
);
DECLARE_EVENT_CLASS(scoutfs_shrink_exit_class,
@@ -1846,37 +1792,36 @@ DEFINE_EVENT(scoutfs_shrink_exit_class, scoutfs_item_shrink_exit,
TRACE_EVENT(scoutfs_item_shrink_around,
TP_PROTO(struct super_block *sb,
struct scoutfs_key_buf *rng_start,
struct scoutfs_key_buf *rng_end, struct scoutfs_key_buf *item,
struct scoutfs_key_buf *prev, struct scoutfs_key_buf *first,
struct scoutfs_key_buf *last, struct scoutfs_key_buf *next),
struct scoutfs_key *rng_start,
struct scoutfs_key *rng_end, struct scoutfs_key *item,
struct scoutfs_key *prev, struct scoutfs_key *first,
struct scoutfs_key *last, struct scoutfs_key *next),
TP_ARGS(sb, rng_start, rng_end, item, prev, first, last, next),
TP_STRUCT__entry(
__field(void *, sb)
__dynamic_array(char, rng_start,
scoutfs_key_str(NULL, rng_start))
__dynamic_array(char, rng_end,
scoutfs_key_str(NULL, rng_end))
__dynamic_array(char, item, scoutfs_key_str(NULL, item))
__dynamic_array(char, prev, scoutfs_key_str(NULL, prev))
__dynamic_array(char, first, scoutfs_key_str(NULL, first))
__dynamic_array(char, last, scoutfs_key_str(NULL, last))
__dynamic_array(char, next, scoutfs_key_str(NULL, next))
__field_struct(struct scoutfs_key, rng_start)
__field_struct(struct scoutfs_key, rng_end)
__field_struct(struct scoutfs_key, item)
__field_struct(struct scoutfs_key, prev)
__field_struct(struct scoutfs_key, first)
__field_struct(struct scoutfs_key, last)
__field_struct(struct scoutfs_key, next)
),
TP_fast_assign(
__entry->sb = sb;
scoutfs_key_str(__get_dynamic_array(rng_start), rng_start);
scoutfs_key_str(__get_dynamic_array(rng_end), rng_end);
scoutfs_key_str(__get_dynamic_array(item), item);
scoutfs_key_str(__get_dynamic_array(prev), prev);
scoutfs_key_str(__get_dynamic_array(first), first);
scoutfs_key_str(__get_dynamic_array(last), last);
scoutfs_key_str(__get_dynamic_array(next), next);
scoutfs_key_copy_or_zeros(&__entry->rng_start, rng_start);
scoutfs_key_copy_or_zeros(&__entry->rng_end, rng_end);
scoutfs_key_copy_or_zeros(&__entry->item, item);
scoutfs_key_copy_or_zeros(&__entry->prev, prev);
scoutfs_key_copy_or_zeros(&__entry->first, first);
scoutfs_key_copy_or_zeros(&__entry->last, last);
scoutfs_key_copy_or_zeros(&__entry->next, next);
),
TP_printk("sb %p rng_start %s rng_end %s item %s prev %s first %s last %s next %s",
__entry->sb, __get_str(rng_start), __get_str(rng_end),
__get_str(item), __get_str(prev), __get_str(first),
__get_str(last), __get_str(next))
TP_printk("sb %p rng_start "SK_FMT" rng_end "SK_FMT" item "SK_FMT" prev "SK_FMT" first "SK_FMT" last "SK_FMT" next "SK_FMT,
__entry->sb, SK_ARG(&__entry->rng_start),
SK_ARG(&__entry->rng_end), SK_ARG(&__entry->item),
SK_ARG(&__entry->prev), SK_ARG(&__entry->first),
SK_ARG(&__entry->last), SK_ARG(&__entry->next))
);
TRACE_EVENT(scoutfs_rename,
+32 -50
View File
@@ -410,49 +410,39 @@ out:
return ret;
}
static u32 item_bytes(u8 nr_links, u16 key_len, u16 val_len)
static u32 item_bytes(u8 nr_links, u16 val_len)
{
return offsetof(struct scoutfs_segment_item, skip_links[nr_links]) +
key_len + val_len;
}
static inline int item_key_off(struct scoutfs_segment_item *item, int item_off)
{
return item_off + item_bytes(item->nr_links, 0, 0);
}
static inline void *item_key_ptr(struct scoutfs_segment_item *item)
{
return (void *)item + item_bytes(item->nr_links, 0, 0);
val_len;
}
static inline void *item_val_ptr(struct scoutfs_segment_item *item)
{
return item_key_ptr(item) + le16_to_cpu(item->key_len);
return (void *)item + item_bytes(item->nr_links, 0);
}
static void item_ptrs(struct scoutfs_segment *seg, int off,
struct scoutfs_key_buf *key, struct kvec *val)
/* copy the item key into the caller's key and init their val to ref the val */
static void get_item_key_val(struct scoutfs_segment *seg, int off,
struct scoutfs_key *key, struct kvec *val)
{
struct scoutfs_segment_item *item = off_ptr(seg, off);
if (key)
scoutfs_key_init(key, item_key_ptr(item),
le16_to_cpu(item->key_len));
if (val) {
val->iov_base = item_val_ptr(item);
val->iov_len = le16_to_cpu(item->val_len);
}
*key = item->key;
if (val)
kvec_init(val, item_val_ptr(item), le16_to_cpu(item->val_len));
}
static void first_last_keys(struct scoutfs_segment *seg,
struct scoutfs_key_buf *first,
struct scoutfs_key_buf *last)
struct scoutfs_key *first,
struct scoutfs_key *last)
{
struct scoutfs_segment_block *sblk = off_ptr(seg, 0);
item_ptrs(seg, sizeof(struct scoutfs_segment_block), first, NULL);
item_ptrs(seg, le32_to_cpu(sblk->last_item_off), last, NULL);
get_item_key_val(seg, sizeof(struct scoutfs_segment_block),
first, NULL);
get_item_key_val(seg, le32_to_cpu(sblk->last_item_off), last, NULL);
}
static int check_caller_off(struct scoutfs_segment_block *sblk, int off)
@@ -475,9 +465,8 @@ static int check_caller_off(struct scoutfs_segment_block *sblk, int off)
* All other offsets must be initial values less than the segment header
* size, notably including 0, or returned from _next_off().
*/
int scoutfs_seg_item_ptrs(struct scoutfs_segment *seg, int off,
struct scoutfs_key_buf *key, struct kvec *val,
u8 *flags)
int scoutfs_seg_get_item(struct scoutfs_segment *seg, int off,
struct scoutfs_key *key, struct kvec *val,u8 *flags)
{
struct scoutfs_segment_block *sblk = off_ptr(seg, 0);
struct scoutfs_segment_item *item;
@@ -486,7 +475,7 @@ int scoutfs_seg_item_ptrs(struct scoutfs_segment *seg, int off,
if (off < 0)
return off;
item_ptrs(seg, off, key, val);
get_item_key_val(seg, off, key, val);
if (flags) {
item = off_ptr(seg, off);
@@ -524,12 +513,10 @@ static u8 skip_most_nr(u32 nr_items)
* than the items and descend down to lower more frequent links when the
* search key is less.
*/
int scoutfs_seg_find_off(struct scoutfs_segment *seg,
struct scoutfs_key_buf *key)
int scoutfs_seg_find_off(struct scoutfs_segment *seg, struct scoutfs_key *key)
{
struct scoutfs_segment_block *sblk = off_ptr(seg, 0);
struct scoutfs_segment_item *item;
struct scoutfs_key_buf item_key;
__le32 *links;
int cmp;
int ret;
@@ -544,10 +531,8 @@ int scoutfs_seg_find_off(struct scoutfs_segment *seg,
off = le32_to_cpu(links[i]);
item = off_ptr(seg, off);
scoutfs_key_init(&item_key, item_key_ptr(item),
le16_to_cpu(item->key_len));
cmp = scoutfs_key_compare(key, &item_key);
cmp = scoutfs_key_compare(key, &item->key);
if (cmp == 0) {
ret = off;
break;
@@ -607,16 +592,15 @@ u32 scoutfs_seg_total_bytes(struct scoutfs_segment *seg)
* than two links per item. We assume the worst case items have the
* max number of links.
*/
bool scoutfs_seg_fits_single(u32 nr_items, u32 key_bytes, u32 val_bytes)
bool scoutfs_seg_fits_single(u32 nr_items, u32 val_bytes)
{
u32 header = sizeof(struct scoutfs_segment_block);
u32 items = nr_items * item_bytes(2, 0, 0);
u32 item_pad = item_bytes(skip_most_nr(nr_items), SCOUTFS_MAX_KEY_SIZE,
u32 items = nr_items * item_bytes(2, 0);
u32 item_pad = item_bytes(skip_most_nr(nr_items),
SCOUTFS_MAX_VAL_SIZE) - 1;
u32 padding = (SCOUTFS_SEGMENT_SIZE / SCOUTFS_BLOCK_SIZE) * item_pad;
return (header + items + key_bytes + val_bytes + padding)
<= SCOUTFS_SEGMENT_SIZE;
return (header + items + val_bytes + padding) <= SCOUTFS_SEGMENT_SIZE;
}
static u32 align_item_off(struct scoutfs_segment *seg, u32 item_off, u32 bytes)
@@ -638,14 +622,13 @@ static u32 align_item_off(struct scoutfs_segment *seg, u32 item_off, u32 bytes)
* We return true if we appended and false if the segment was full.
*/
bool scoutfs_seg_append_item(struct super_block *sb, struct scoutfs_segment *seg,
struct scoutfs_key_buf *key, struct kvec *val,
struct scoutfs_key *key, struct kvec *val,
u8 flags, __le32 **links)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_super_block *super = &sbi->super;
struct scoutfs_segment_block *sblk = off_ptr(seg, 0);
struct scoutfs_segment_item *item;
struct scoutfs_key_buf item_key;
struct kvec item_val;
u8 nr_links;
u32 val_len;
@@ -674,12 +657,12 @@ bool scoutfs_seg_append_item(struct super_block *sb, struct scoutfs_segment *seg
*/
off = le32_to_cpu(sblk->last_item_off);
if (off) {
item_ptrs(seg, off, &item_key, NULL);
BUG_ON(scoutfs_key_compare(key, &item_key) <= 0);
item = off_ptr(seg, off);
BUG_ON(scoutfs_key_compare(key, &item->key) <= 0);
}
nr_links = skip_next_nr(le32_to_cpu(sblk->nr_items));
bytes = item_bytes(nr_links, key->key_len, val_len);
bytes = item_bytes(nr_links, val_len);
off = align_item_off(seg, le32_to_cpu(sblk->total_bytes), bytes);
if ((off + bytes) > SCOUTFS_SEGMENT_SIZE)
@@ -690,7 +673,7 @@ bool scoutfs_seg_append_item(struct super_block *sb, struct scoutfs_segment *seg
le32_add_cpu(&sblk->nr_items, 1);
item = off_ptr(seg, off);
item->key_len = cpu_to_le16(key->key_len);
item->key = *key;
item->val_len = cpu_to_le16(val_len);
item->flags = flags;
@@ -702,8 +685,7 @@ bool scoutfs_seg_append_item(struct super_block *sb, struct scoutfs_segment *seg
links[i] = &item->skip_links[i];
}
item_ptrs(seg, off, &item_key, &item_val);
scoutfs_key_copy(&item_key, key);
get_item_key_val(seg, off, NULL, &item_val);
if (val_len)
memcpy(item_val.iov_base, val->iov_base, val_len);
@@ -714,8 +696,8 @@ void scoutfs_seg_init_ment(struct scoutfs_manifest_entry *ment, int level,
struct scoutfs_segment *seg)
{
struct scoutfs_segment_block *sblk = off_ptr(seg, 0);
struct scoutfs_key_buf first;
struct scoutfs_key_buf last;
struct scoutfs_key first;
struct scoutfs_key last;
first_last_keys(seg, &first, &last);
+7 -10
View File
@@ -2,7 +2,7 @@
#define _SCOUTFS_SEG_H_
struct scoutfs_bio_completion;
struct scoutfs_key_buf;
struct scoutfs_key;
struct scoutfs_manifest_entry;
struct kvec;
@@ -23,24 +23,21 @@ struct scoutfs_segment *scoutfs_seg_submit_read(struct super_block *sb,
int scoutfs_seg_wait(struct super_block *sb, struct scoutfs_segment *seg,
u64 segno, u64 seq);
int scoutfs_seg_find_off(struct scoutfs_segment *seg,
struct scoutfs_key_buf *key);
int scoutfs_seg_find_off(struct scoutfs_segment *seg, struct scoutfs_key *key);
int scoutfs_seg_next_off(struct scoutfs_segment *seg, int off);
u32 scoutfs_seg_total_bytes(struct scoutfs_segment *seg);
int scoutfs_seg_item_ptrs(struct scoutfs_segment *seg, int off,
struct scoutfs_key_buf *key, struct kvec *val,
u8 *flags);
int scoutfs_seg_get_item(struct scoutfs_segment *seg, int off,
struct scoutfs_key *key, struct kvec *val, u8 *flags);
void scoutfs_seg_get(struct scoutfs_segment *seg);
void scoutfs_seg_put(struct scoutfs_segment *seg);
int scoutfs_seg_alloc(struct super_block *sb, u64 segno,
struct scoutfs_segment **seg_ret);
int scoutfs_seg_free_segno(struct super_block *sb,
struct scoutfs_segment *seg);
bool scoutfs_seg_fits_single(u32 nr_items, u32 key_bytes, u32 val_bytes);
int scoutfs_seg_free_segno(struct super_block *sb, struct scoutfs_segment *seg);
bool scoutfs_seg_fits_single(u32 nr_items, u32 val_bytes);
bool scoutfs_seg_append_item(struct super_block *sb, struct scoutfs_segment *seg,
struct scoutfs_key_buf *key, struct kvec *val,
struct scoutfs_key *key, struct kvec *val,
u8 flags, __le32 **links);
void scoutfs_seg_init_ment(struct scoutfs_manifest_entry *ment, int level,
struct scoutfs_segment *seg);
+9 -52
View File
@@ -232,67 +232,24 @@ static int send_reply(struct server_connection *conn, u64 id,
return ret;
}
void scoutfs_init_net_ment_keys(struct scoutfs_net_manifest_entry *net_ment,
struct scoutfs_key_buf *first,
struct scoutfs_key_buf *last)
void scoutfs_init_ment_to_net(struct scoutfs_net_manifest_entry *net_ment,
struct scoutfs_manifest_entry *ment)
{
scoutfs_key_init(first, net_ment->keys,
le16_to_cpu(net_ment->first_key_len));
scoutfs_key_init(last, net_ment->keys +
le16_to_cpu(net_ment->first_key_len),
le16_to_cpu(net_ment->last_key_len));
}
/*
* Allocate a contiguous manifest entry for communication over the network.
*/
struct scoutfs_net_manifest_entry *
scoutfs_alloc_net_ment(struct scoutfs_manifest_entry *ment)
{
struct scoutfs_net_manifest_entry *net_ment;
struct scoutfs_key_buf first;
struct scoutfs_key_buf last;
net_ment = kmalloc(offsetof(struct scoutfs_net_manifest_entry,
keys[ment->first.key_len +
ment->last.key_len]), GFP_NOFS);
if (!net_ment)
return NULL;
net_ment->segno = cpu_to_le64(ment->segno);
net_ment->seq = cpu_to_le64(ment->seq);
net_ment->first_key_len = cpu_to_le16(ment->first.key_len);
net_ment->last_key_len = cpu_to_le16(ment->last.key_len);
net_ment->first = ment->first;
net_ment->last = ment->last;
net_ment->level = ment->level;
scoutfs_init_net_ment_keys(net_ment, &first, &last);
scoutfs_key_copy(&first, &ment->first);
scoutfs_key_copy(&last, &ment->last);
return net_ment;
}
/* point a native manifest entry at a contiguous net manifest */
void scoutfs_init_ment_net_ment(struct scoutfs_manifest_entry *ment,
void scoutfs_init_ment_from_net(struct scoutfs_manifest_entry *ment,
struct scoutfs_net_manifest_entry *net_ment)
{
struct scoutfs_key_buf first;
struct scoutfs_key_buf last;
scoutfs_init_net_ment_keys(net_ment, &first, &last);
scoutfs_key_clone(&ment->first, &first);
scoutfs_key_clone(&ment->last, &last);
ment->segno = le64_to_cpu(net_ment->segno);
ment->seq = le64_to_cpu(net_ment->seq);
ment->level = net_ment->level;
}
unsigned scoutfs_net_ment_bytes(struct scoutfs_net_manifest_entry *net_ment)
{
return offsetof(struct scoutfs_net_manifest_entry,
keys[le16_to_cpu(net_ment->first_key_len) +
le16_to_cpu(net_ment->last_key_len)]);
ment->first = net_ment->first;
ment->last = net_ment->last;
}
static int process_alloc_inodes(struct server_connection *conn,
@@ -381,7 +338,7 @@ static int process_record_segment(struct server_connection *conn, u64 id,
net_ment = data;
if (data_len != scoutfs_net_ment_bytes(net_ment)) {
if (data_len != sizeof(*net_ment)) {
ret = -EINVAL;
goto out;
}
@@ -399,7 +356,7 @@ retry:
goto retry;
}
scoutfs_init_ment_net_ment(&ment, net_ment);
scoutfs_init_ment_from_net(&ment, net_ment);
ret = scoutfs_manifest_add(sb, &ment);
scoutfs_manifest_unlock(sb);
+3 -7
View File
@@ -1,14 +1,10 @@
#ifndef _SCOUTFS_SERVER_H_
#define _SCOUTFS_SERVER_H_
void scoutfs_init_net_ment_keys(struct scoutfs_net_manifest_entry *net_ment,
struct scoutfs_key_buf *first,
struct scoutfs_key_buf *last);
struct scoutfs_net_manifest_entry *
scoutfs_alloc_net_ment(struct scoutfs_manifest_entry *ment);
void scoutfs_init_ment_net_ment(struct scoutfs_manifest_entry *ment,
void scoutfs_init_ment_to_net(struct scoutfs_net_manifest_entry *net_ment,
struct scoutfs_manifest_entry *ment);
void scoutfs_init_ment_from_net(struct scoutfs_manifest_entry *ment,
struct scoutfs_net_manifest_entry *net_ment);
unsigned scoutfs_net_ment_bytes(struct scoutfs_net_manifest_entry *net_ment);
int scoutfs_client_get_compaction(struct super_block *sb, void *curs);
int scoutfs_client_finish_compaction(struct super_block *sb, void *curs,
+1
View File
@@ -419,6 +419,7 @@ static int __init scoutfs_module_init(void)
".string \""SCOUTFS_GIT_DESCRIBE"\\n\"\n"
".previous\n");
scoutfs_key_init();
scoutfs_init_counters();
ret = scoutfs_data_test();
+5 -16
View File
@@ -60,7 +60,6 @@
struct trans_info {
spinlock_t lock;
unsigned reserved_items;
unsigned reserved_keys;
unsigned reserved_vals;
unsigned holders;
bool writing;
@@ -295,7 +294,6 @@ static bool acquired_hold(struct super_block *sb,
DECLARE_TRANS_INFO(sb, tri);
bool acquired = false;
unsigned items;
unsigned keys;
unsigned vals;
bool fits;
@@ -305,7 +303,6 @@ static bool acquired_hold(struct super_block *sb,
&rsv->reserved, &rsv->actual,
tri->holders, tri->writing,
tri->reserved_items,
tri->reserved_keys,
tri->reserved_vals);
/* use a caller's existing reservation */
@@ -318,9 +315,8 @@ static bool acquired_hold(struct super_block *sb,
/* see if we can reserve space for our item count */
items = tri->reserved_items + cnt->items;
keys = tri->reserved_keys + cnt->keys;
vals = tri->reserved_vals + cnt->vals;
fits = scoutfs_item_dirty_fits_single(sb, items, keys, vals);
fits = scoutfs_item_dirty_fits_single(sb, items, vals);
if (!fits) {
scoutfs_inc_counter(sb, trans_commit_full);
queue_trans_work(sbi);
@@ -328,11 +324,9 @@ static bool acquired_hold(struct super_block *sb,
}
tri->reserved_items = items;
tri->reserved_keys = keys;
tri->reserved_vals = vals;
rsv->reserved.items = cnt->items;
rsv->reserved.keys = cnt->keys;
rsv->reserved.vals = cnt->vals;
hold:
@@ -358,9 +352,8 @@ int scoutfs_hold_trans(struct super_block *sb,
* Caller shouldn't provide garbage counts, nor counts that
* can't fit in segments by themselves.
*/
if (WARN_ON_ONCE(cnt.items <= 0 || cnt.keys < 0 || cnt.vals < 0) ||
WARN_ON_ONCE(!scoutfs_seg_fits_single(cnt.items, cnt.keys,
cnt.vals)))
if (WARN_ON_ONCE(cnt.items <= 0 || cnt.vals < 0) ||
WARN_ON_ONCE(!scoutfs_seg_fits_single(cnt.items, cnt.vals)))
return -EINVAL;
if (current == sbi->trans_task)
@@ -400,7 +393,7 @@ bool scoutfs_trans_held(void)
}
void scoutfs_trans_track_item(struct super_block *sb, signed items,
signed keys, signed vals)
signed vals)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_reservation *rsv = current->journal_info;
@@ -411,11 +404,9 @@ void scoutfs_trans_track_item(struct super_block *sb, signed items,
BUG_ON(!rsv || rsv->magic != SCOUTFS_RESERVATION_MAGIC);
rsv->actual.items += items;
rsv->actual.keys += keys;
rsv->actual.vals += vals;
WARN_ON_ONCE(rsv->actual.items > rsv->reserved.items);
WARN_ON_ONCE(rsv->actual.keys > rsv->reserved.keys);
WARN_ON_ONCE(rsv->actual.vals > rsv->reserved.vals);
}
@@ -442,15 +433,13 @@ void scoutfs_release_trans(struct super_block *sb)
trace_scoutfs_release_trans(sb, rsv, rsv->holders, &rsv->reserved,
&rsv->actual, tri->holders, tri->writing,
tri->reserved_items, tri->reserved_keys,
tri->reserved_vals);
tri->reserved_items, tri->reserved_vals);
BUG_ON(rsv->holders <= 0);
BUG_ON(tri->holders <= 0);
if (--rsv->holders == 0) {
tri->reserved_items -= rsv->reserved.items;
tri->reserved_keys -= rsv->reserved.keys;
tri->reserved_vals -= rsv->reserved.vals;
current->journal_info = NULL;
kfree(rsv);
+1 -1
View File
@@ -14,7 +14,7 @@ int scoutfs_hold_trans(struct super_block *sb,
bool scoutfs_trans_held(void);
void scoutfs_release_trans(struct super_block *sb);
void scoutfs_trans_track_item(struct super_block *sb, signed items,
signed keys, signed vals);
signed vals);
int scoutfs_setup_trans(struct super_block *sb);
void scoutfs_shutdown_trans(struct super_block *sb);
+44 -52
View File
@@ -68,19 +68,17 @@ static unsigned int xattr_nr_parts(struct scoutfs_xattr *xat)
le16_to_cpu(xat->val_len));
}
/* If no name is provided then the hash arg is used, caller can modify part */
static void init_xattr_key(struct scoutfs_key_buf *key,
struct scoutfs_xattr_key *xak, u64 ino,
u32 name_hash, u64 id)
static void init_xattr_key(struct scoutfs_key *key, u64 ino, u32 name_hash,
u64 id)
{
xak->zone = SCOUTFS_FS_ZONE;
xak->ino = cpu_to_be64(ino);
xak->type = SCOUTFS_XATTR_TYPE;
xak->name_hash = cpu_to_be32(name_hash);
xak->id = cpu_to_be64(id);
xak->part = 0;
scoutfs_key_init(key, xak, sizeof(struct scoutfs_xattr_key));
*key = (struct scoutfs_key) {
.sk_zone = SCOUTFS_FS_ZONE,
.skx_ino = cpu_to_le64(ino),
.sk_type = SCOUTFS_XATTR_TYPE,
.skx_name_hash = cpu_to_le64(name_hash),
.skx_id = cpu_to_le64(id),
.skx_part = 0,
};
}
static int unknown_prefix(const char *name)
@@ -108,15 +106,13 @@ static int unknown_prefix(const char *name)
*
* Returns -ENOENT if it didn't find a next item.
*/
static int get_next_xattr(struct inode *inode, struct scoutfs_xattr_key *xak,
static int get_next_xattr(struct inode *inode, struct scoutfs_key *key,
struct scoutfs_xattr *xat, unsigned int bytes,
const char *name, unsigned int name_len,
u64 name_hash, u64 id, struct scoutfs_lock *lock)
{
struct super_block *sb = inode->i_sb;
struct scoutfs_xattr_key last_xak;
struct scoutfs_key_buf last;
struct scoutfs_key_buf key;
struct scoutfs_key last;
struct kvec val;
u8 last_part;
int total;
@@ -131,17 +127,17 @@ static int get_next_xattr(struct inode *inode, struct scoutfs_xattr_key *xak,
if (name_len)
name_hash = xattr_name_hash(name, name_len);
init_xattr_key(&key, xak, scoutfs_ino(inode), name_hash, id);
init_xattr_key(&last, &last_xak, scoutfs_ino(inode), U32_MAX, U64_MAX);
init_xattr_key(key, scoutfs_ino(inode), name_hash, id);
init_xattr_key(&last, scoutfs_ino(inode), U32_MAX, U64_MAX);
last_part = 0;
part = 0;
total = 0;
for (;;) {
xak->part = part;
key->skx_part = part;
kvec_init(&val, (void *)xat + total, bytes - total);
ret = scoutfs_item_next(sb, &key, &last, &val, lock);
ret = scoutfs_item_next(sb, key, &last, &val, lock);
if (ret < 0) {
/* XXX corruption, ran out of parts */
if (ret == -ENOENT && part > 0)
@@ -149,10 +145,10 @@ static int get_next_xattr(struct inode *inode, struct scoutfs_xattr_key *xak,
break;
}
trace_scoutfs_xattr_get_next_key(sb, &key);
trace_scoutfs_xattr_get_next_key(sb, key);
/* XXX corruption */
if (xak->part != part) {
if (key->skx_part != part) {
ret = -EIO;
break;
}
@@ -175,7 +171,7 @@ static int get_next_xattr(struct inode *inode, struct scoutfs_xattr_key *xak,
if (part == 0 && name_len) {
/* ran out of names that could match */
if (be32_to_cpu(xak->name_hash) != name_hash) {
if (le64_to_cpu(key->skx_name_hash) != name_hash) {
ret = -ENOENT;
break;
}
@@ -184,7 +180,7 @@ static int get_next_xattr(struct inode *inode, struct scoutfs_xattr_key *xak,
if (!xattr_names_equal(name, name_len,
xat->name, xat->name_len)) {
part = 0;
be64_add_cpu(&xak->id, 1);
le64_add_cpu(&key->skx_id, 1);
continue;
}
@@ -214,14 +210,13 @@ static int create_xattr_items(struct inode *inode, u64 id,
struct scoutfs_lock *lock)
{
struct super_block *sb = inode->i_sb;
struct scoutfs_xattr_key xak;
struct scoutfs_key_buf key;
struct scoutfs_key key;
unsigned int part_bytes;
struct kvec val;
int total;
int ret;
init_xattr_key(&key, &xak, scoutfs_ino(inode),
init_xattr_key(&key, scoutfs_ino(inode),
xattr_name_hash(xat->name, xat->name_len), id);
total = 0;
@@ -232,13 +227,13 @@ static int create_xattr_items(struct inode *inode, u64 id,
ret = scoutfs_item_create(sb, &key, &val, lock);
if (ret) {
while (xak.part-- > 0)
while (key.skx_part-- > 0)
scoutfs_item_delete_dirty(sb, &key);
break;
}
total += part_bytes;
xak.part++;
key.skx_part++;
}
return ret;
@@ -249,20 +244,19 @@ static int create_xattr_items(struct inode *inode, u64 id,
* returns an error then the deleted and saved items are left on the
* list for the caller to restore.
*/
static int delete_xattr_items(struct inode *inode, u64 name_hash, u64 id,
static int delete_xattr_items(struct inode *inode, u32 name_hash, u64 id,
u8 nr_parts, struct list_head *list,
struct scoutfs_lock *lock)
{
struct super_block *sb = inode->i_sb;
struct scoutfs_xattr_key xak;
struct scoutfs_key_buf key;
struct scoutfs_key key;
int ret;
init_xattr_key(&key, &xak, scoutfs_ino(inode), name_hash, id);
init_xattr_key(&key, scoutfs_ino(inode), name_hash, id);
do {
ret = scoutfs_item_delete_save(sb, &key, list, lock);
} while (ret == 0 && ++xak.part < nr_parts);
} while (ret == 0 && ++key.skx_part < nr_parts);
return ret;
}
@@ -279,7 +273,7 @@ ssize_t scoutfs_getxattr(struct dentry *dentry, const char *name, void *buffer,
struct super_block *sb = inode->i_sb;
struct scoutfs_xattr *xat = NULL;
struct scoutfs_lock *lck = NULL;
struct scoutfs_xattr_key xak;
struct scoutfs_key key;
unsigned int bytes;
size_t name_len;
int ret;
@@ -303,7 +297,7 @@ ssize_t scoutfs_getxattr(struct dentry *dentry, const char *name, void *buffer,
down_read(&si->xattr_rwsem);
ret = get_next_xattr(inode, &xak, xat, bytes,
ret = get_next_xattr(inode, &key, xat, bytes,
name, name_len, 0, 0, lck);
up_read(&si->xattr_rwsem);
@@ -360,7 +354,7 @@ static int scoutfs_xattr_set(struct dentry *dentry, const char *name,
struct scoutfs_xattr *xat = NULL;
struct scoutfs_lock *lck = NULL;
size_t name_len = strlen(name);
struct scoutfs_xattr_key xak;
struct scoutfs_key key;
LIST_HEAD(ind_locks);
LIST_HEAD(saved);
u8 found_parts;
@@ -399,7 +393,7 @@ static int scoutfs_xattr_set(struct dentry *dentry, const char *name,
down_write(&si->xattr_rwsem);
/* find an existing xattr to delete */
ret = get_next_xattr(inode, &xak, xat,
ret = get_next_xattr(inode, &key, xat,
sizeof(struct scoutfs_xattr) + name_len,
name, name_len, 0, 0, lck);
if (ret < 0 && ret != -ENOENT)
@@ -420,7 +414,7 @@ static int scoutfs_xattr_set(struct dentry *dentry, const char *name,
goto unlock;
}
/* found fields in xak will also be used */
/* found fields in key will also be used */
found_parts = ret >= 0 ? xattr_nr_parts(xat) : 0;
/* prepare our xattr */
@@ -450,8 +444,8 @@ retry:
ret = 0;
if (found_parts)
ret = delete_xattr_items(inode, be32_to_cpu(xak.name_hash),
be64_to_cpu(xak.id), found_parts,
ret = delete_xattr_items(inode, le64_to_cpu(key.skx_name_hash),
le64_to_cpu(key.skx_id), found_parts,
&saved, lck);
if (value && ret == 0)
ret = create_xattr_items(inode, id, xat, bytes, lck);
@@ -500,7 +494,7 @@ ssize_t scoutfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
struct super_block *sb = inode->i_sb;
struct scoutfs_xattr *xat = NULL;
struct scoutfs_lock *lck = NULL;
struct scoutfs_xattr_key xak;
struct scoutfs_key key;
unsigned int bytes;
ssize_t total;
u32 name_hash;
@@ -526,7 +520,7 @@ ssize_t scoutfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
total = 0;
for (;;) {
ret = get_next_xattr(inode, &xak, xat, bytes,
ret = get_next_xattr(inode, &key, xat, bytes,
NULL, 0, name_hash, id, lck);
if (ret < 0) {
if (ret == -ENOENT)
@@ -547,8 +541,8 @@ ssize_t scoutfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
*(buffer++) = '\0';
}
name_hash = be32_to_cpu(xak.name_hash);
id = be64_to_cpu(xak.id) + 1;
name_hash = le64_to_cpu(key.skx_name_hash);
id = le64_to_cpu(key.skx_id) + 1;
}
up_read(&si->xattr_rwsem);
@@ -571,15 +565,13 @@ out:
*/
int scoutfs_xattr_drop(struct super_block *sb, u64 ino)
{
struct scoutfs_xattr_key last_xak;
struct scoutfs_xattr_key xak;
struct scoutfs_key_buf last;
struct scoutfs_key_buf key;
struct scoutfs_key last;
struct scoutfs_key key;
struct scoutfs_lock *lck;
int ret;
init_xattr_key(&key, &xak, ino, 0, 0);
init_xattr_key(&last, &last_xak, ino, U32_MAX, U64_MAX);
init_xattr_key(&key, ino, 0, 0);
init_xattr_key(&last, ino, U32_MAX, U64_MAX);
/* while we read to delete we need to writeback others */
ret = scoutfs_lock_ino(sb, DLM_LOCK_EX, 0, ino, &lck);
@@ -598,7 +590,7 @@ int scoutfs_xattr_drop(struct super_block *sb, u64 ino)
if (ret)
break;
xak.part++;
key.skx_part++;
}
scoutfs_unlock(sb, lck, DLM_LOCK_EX);