mirror of
https://github.com/versity/scoutfs.git
synced 2026-08-03 22:06:43 +00:00
scoutfs: remove support for multi-element kvecs
Originally the item interfaces were written with full support for vectored keys and values. Callers constructed keys and values made up of header structs and data buffers. Segments supported much larger values which could span pages when stored in memory. But over time we've pulled that support back. Keys are described by a key struct instead of a multi-element kvec. Values are now much smaller and don't span pages. The item interfaces still use the kvec arrays but everyone only uses a single element. So let's make the world a whole lot less awful but having the item interfaces only supporting a single value buffer specified by a kvec. A bunch of code disappears and the result is much easier to understand. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
+3
-4
@@ -6,10 +6,9 @@ CFLAGS_super.o = -DSCOUTFS_GIT_DESCRIBE=\"$(SCOUTFS_GIT_DESCRIBE)\" \
|
||||
CFLAGS_scoutfs_trace.o = -I$(src) # define_trace.h double include
|
||||
|
||||
scoutfs-y += alloc.o bio.o btree.o client.o compact.o counters.o data.o dir.o \
|
||||
export.o file.o kvec.o inode.o ioctl.o item.o key.o lock.o \
|
||||
manifest.o msg.o options.o per_task.o seg.o server.o \
|
||||
scoutfs_trace.o sock.o sort_priv.o super.o sysfs.o trans.o \
|
||||
triggers.o xattr.o
|
||||
export.o file.o inode.o ioctl.o item.o key.o lock.o manifest.o \
|
||||
msg.o options.o per_task.o seg.o server.o scoutfs_trace.o sock.o \
|
||||
sort_priv.o super.o sysfs.o trans.o triggers.o xattr.o
|
||||
|
||||
#
|
||||
# The raw types aren't available in userspace headers. Make sure all
|
||||
|
||||
+9
-9
@@ -16,7 +16,6 @@
|
||||
|
||||
#include "super.h"
|
||||
#include "format.h"
|
||||
#include "kvec.h"
|
||||
#include "seg.h"
|
||||
#include "bio.h"
|
||||
#include "cmp.h"
|
||||
@@ -186,7 +185,7 @@ static int next_item(struct super_block *sb, struct compact_cursor *curs,
|
||||
struct compact_seg *upper = curs->upper;
|
||||
struct compact_seg *lower = curs->lower;
|
||||
struct scoutfs_key_buf lower_key;
|
||||
SCOUTFS_DECLARE_KVEC(lower_val);
|
||||
struct kvec lower_val;
|
||||
u8 lower_flags;
|
||||
int cmp;
|
||||
int ret;
|
||||
@@ -205,7 +204,7 @@ retry:
|
||||
goto out;
|
||||
|
||||
ret = scoutfs_seg_item_ptrs(lower->seg, lower->off,
|
||||
&lower_key, lower_val,
|
||||
&lower_key, &lower_val,
|
||||
&lower_flags);
|
||||
if (ret == 0)
|
||||
break;
|
||||
@@ -232,7 +231,7 @@ retry:
|
||||
|
||||
if (cmp > 0) {
|
||||
scoutfs_key_clone(item_key, &lower_key);
|
||||
scoutfs_kvec_clone(item_val, lower_val);
|
||||
*item_val = lower_val;
|
||||
*item_flags = lower_flags;
|
||||
}
|
||||
|
||||
@@ -278,13 +277,13 @@ static int compact_segments(struct super_block *sb,
|
||||
struct list_head *results)
|
||||
{
|
||||
struct scoutfs_key_buf item_key;
|
||||
SCOUTFS_DECLARE_KVEC(item_val);
|
||||
struct scoutfs_segment *seg;
|
||||
struct compact_seg *cseg;
|
||||
struct compact_seg *upper;
|
||||
struct compact_seg *lower;
|
||||
unsigned next_segno = 0;
|
||||
bool append_filled = false;
|
||||
struct kvec item_val;
|
||||
int ret = 0;
|
||||
u8 flags;
|
||||
|
||||
@@ -363,7 +362,7 @@ static int compact_segments(struct super_block *sb,
|
||||
break;
|
||||
|
||||
if (!append_filled)
|
||||
ret = next_item(sb, curs, &item_key, item_val, &flags);
|
||||
ret = next_item(sb, curs, &item_key, &item_val, &flags);
|
||||
else
|
||||
ret = 1;
|
||||
if (ret <= 0)
|
||||
@@ -410,13 +409,14 @@ static int compact_segments(struct super_block *sb,
|
||||
list_add_tail(&cseg->entry, results);
|
||||
|
||||
for (;;) {
|
||||
if (!scoutfs_seg_append_item(sb, seg, &item_key, item_val,
|
||||
flags, curs->links)) {
|
||||
if (!scoutfs_seg_append_item(sb, seg, &item_key,
|
||||
&item_val, flags,
|
||||
curs->links)) {
|
||||
append_filled = true;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
ret = next_item(sb, curs, &item_key, item_val, &flags);
|
||||
ret = next_item(sb, curs, &item_key, &item_val, &flags);
|
||||
if (ret <= 0) {
|
||||
append_filled = false;
|
||||
break;
|
||||
|
||||
+46
-45
@@ -25,6 +25,7 @@
|
||||
#include "inode.h"
|
||||
#include "key.h"
|
||||
#include "data.h"
|
||||
#include "kvec.h"
|
||||
#include "trans.h"
|
||||
#include "counters.h"
|
||||
#include "scoutfs_trace.h"
|
||||
@@ -355,14 +356,14 @@ static int set_segno_free(struct super_block *sb, u64 segno)
|
||||
struct scoutfs_free_bits_key fbk = {0,};
|
||||
struct scoutfs_free_bits frb;
|
||||
struct scoutfs_key_buf key;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
struct kvec val;
|
||||
int bit = 0;
|
||||
int ret;
|
||||
|
||||
init_free_key(&key, &fbk, sbi->node_id, segno,
|
||||
SCOUTFS_FREE_BITS_SEGNO_TYPE);
|
||||
scoutfs_kvec_init(val, &frb, sizeof(struct scoutfs_free_bits));
|
||||
ret = scoutfs_item_lookup_exact(sb, &key, val, lock);
|
||||
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
|
||||
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
|
||||
if (ret && ret != -ENOENT)
|
||||
goto out;
|
||||
|
||||
@@ -371,7 +372,7 @@ static int set_segno_free(struct super_block *sb, u64 segno)
|
||||
if (ret == -ENOENT) {
|
||||
memset(&frb, 0, sizeof(frb));
|
||||
set_bit_le(bit, &frb);
|
||||
ret = scoutfs_item_create(sb, &key, val, lock);
|
||||
ret = scoutfs_item_create(sb, &key, &val, lock);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -380,7 +381,7 @@ static int set_segno_free(struct super_block *sb, u64 segno)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = scoutfs_item_update(sb, &key, val, lock);
|
||||
ret = scoutfs_item_update(sb, &key, &val, lock);
|
||||
out:
|
||||
trace_scoutfs_data_set_segno_free(sb, segno, be64_to_cpu(fbk.base),
|
||||
bit, ret);
|
||||
@@ -399,18 +400,18 @@ static int create_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 frb;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
struct kvec val;
|
||||
int bit;
|
||||
|
||||
init_free_key(key, fbk, sbi->node_id, blkno,
|
||||
SCOUTFS_FREE_BITS_BLKNO_TYPE);
|
||||
scoutfs_kvec_init(val, &frb, sizeof(struct scoutfs_free_bits));
|
||||
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
|
||||
|
||||
bit = blkno & SCOUTFS_FREE_BITS_MASK;
|
||||
memset(&frb, 0xff, sizeof(frb));
|
||||
clear_bit_le(bit, frb.bits);
|
||||
|
||||
return scoutfs_item_create(sb, key, val, lock);
|
||||
return scoutfs_item_create(sb, key, &val, lock);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -433,15 +434,15 @@ static int clear_segno_free(struct super_block *sb, u64 segno)
|
||||
struct scoutfs_free_bits frb;
|
||||
struct scoutfs_key_buf b_key;
|
||||
struct scoutfs_key_buf key;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
struct kvec val;
|
||||
u64 blkno;
|
||||
int bit;
|
||||
int ret;
|
||||
|
||||
init_free_key(&key, &fbk, sbi->node_id, segno,
|
||||
SCOUTFS_FREE_BITS_SEGNO_TYPE);
|
||||
scoutfs_kvec_init(val, &frb, sizeof(struct scoutfs_free_bits));
|
||||
ret = scoutfs_item_lookup_exact(sb, &key, val, lock);
|
||||
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
|
||||
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
|
||||
if (ret) {
|
||||
/* XXX corruption, caller saw item.. should still exist */
|
||||
if (ret == -ENOENT)
|
||||
@@ -465,7 +466,7 @@ static int clear_segno_free(struct super_block *sb, u64 segno)
|
||||
if (bitmap_empty((long *)frb.bits, SCOUTFS_FREE_BITS_BITS))
|
||||
ret = scoutfs_item_delete(sb, &key, lock);
|
||||
else
|
||||
ret = scoutfs_item_update(sb, &key, val, lock);
|
||||
ret = scoutfs_item_update(sb, &key, &val, lock);
|
||||
if (ret)
|
||||
scoutfs_item_delete_dirty(sb, &b_key);
|
||||
out:
|
||||
@@ -484,7 +485,7 @@ static int set_blkno_free(struct super_block *sb, u64 blkno)
|
||||
struct scoutfs_free_bits_key fbk;
|
||||
struct scoutfs_free_bits frb;
|
||||
struct scoutfs_key_buf key;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
struct kvec val;
|
||||
u64 segno;
|
||||
int bit;
|
||||
int ret;
|
||||
@@ -492,8 +493,8 @@ static int set_blkno_free(struct super_block *sb, u64 blkno)
|
||||
/* get the specified item */
|
||||
init_free_key(&key, &fbk, sbi->node_id, blkno,
|
||||
SCOUTFS_FREE_BITS_BLKNO_TYPE);
|
||||
scoutfs_kvec_init(val, &frb, sizeof(struct scoutfs_free_bits));
|
||||
ret = scoutfs_item_lookup_exact(sb, &key, val, lock);
|
||||
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
|
||||
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
|
||||
if (ret && ret != -ENOENT)
|
||||
goto out;
|
||||
|
||||
@@ -502,7 +503,7 @@ static int set_blkno_free(struct super_block *sb, u64 blkno)
|
||||
if (ret == -ENOENT) {
|
||||
memset(&frb, 0, sizeof(frb));
|
||||
set_bit_le(bit, &frb);
|
||||
ret = scoutfs_item_create(sb, &key, val, lock);
|
||||
ret = scoutfs_item_create(sb, &key, &val, lock);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -512,7 +513,7 @@ static int set_blkno_free(struct super_block *sb, u64 blkno)
|
||||
}
|
||||
|
||||
if (!bitmap_full((long *)frb.bits, SCOUTFS_FREE_BITS_BITS)) {
|
||||
ret = scoutfs_item_update(sb, &key, val, lock);
|
||||
ret = scoutfs_item_update(sb, &key, &val, lock);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -544,15 +545,15 @@ static int clear_blkno_free(struct super_block *sb, u64 blkno)
|
||||
struct scoutfs_free_bits_key fbk;
|
||||
struct scoutfs_free_bits frb;
|
||||
struct scoutfs_key_buf key;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
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);
|
||||
scoutfs_kvec_init(val, &frb, sizeof(struct scoutfs_free_bits));
|
||||
ret = scoutfs_item_lookup_exact(sb, &key, val, lock);
|
||||
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
|
||||
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
|
||||
if (ret) {
|
||||
/* XXX corruption, bits should have existed */
|
||||
if (ret == -ENOENT)
|
||||
@@ -570,7 +571,7 @@ static int clear_blkno_free(struct super_block *sb, u64 blkno)
|
||||
if (bitmap_empty((long *)frb.bits, SCOUTFS_FREE_BITS_BITS))
|
||||
ret = scoutfs_item_delete(sb, &key, lock);
|
||||
else
|
||||
ret = scoutfs_item_update(sb, &key, val, lock);
|
||||
ret = scoutfs_item_update(sb, &key, &val, lock);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@@ -611,7 +612,7 @@ int scoutfs_data_truncate_items(struct super_block *sb, struct inode *inode,
|
||||
struct scoutfs_block_mapping_key last_bmk;
|
||||
struct scoutfs_block_mapping_key bmk;
|
||||
struct block_mapping *map;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
struct kvec val;
|
||||
bool holding = false;
|
||||
bool dirtied;
|
||||
u64 blkno;
|
||||
@@ -633,7 +634,7 @@ int scoutfs_data_truncate_items(struct super_block *sb, struct inode *inode,
|
||||
while (iblock <= last) {
|
||||
/* find the mapping that could include iblock */
|
||||
init_mapping_key(&key, &bmk, ino, iblock);
|
||||
scoutfs_kvec_init(val, map->encoded, sizeof(map->encoded));
|
||||
kvec_init(&val, map->encoded, sizeof(map->encoded));
|
||||
|
||||
ret = scoutfs_hold_trans(sb, SIC_TRUNC_BLOCK());
|
||||
if (ret)
|
||||
@@ -642,7 +643,7 @@ int scoutfs_data_truncate_items(struct super_block *sb, struct inode *inode,
|
||||
|
||||
down_write(&datinf->alloc_rwsem);
|
||||
|
||||
ret = scoutfs_item_next(sb, &key, &last_key, val, lock);
|
||||
ret = scoutfs_item_next(sb, &key, &last_key, &val, lock);
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOENT)
|
||||
ret = 0;
|
||||
@@ -669,7 +670,7 @@ int scoutfs_data_truncate_items(struct super_block *sb, struct inode *inode,
|
||||
|
||||
if (!dirtied) {
|
||||
/* dirty item with full size encoded */
|
||||
ret = scoutfs_item_update(sb, &key, val, lock);
|
||||
ret = scoutfs_item_update(sb, &key, &val, lock);
|
||||
if (ret)
|
||||
break;
|
||||
dirtied = true;
|
||||
@@ -706,8 +707,8 @@ int scoutfs_data_truncate_items(struct super_block *sb, struct inode *inode,
|
||||
/* update how ever much of the item we finished */
|
||||
bytes = encode_mapping(map);
|
||||
if (bytes) {
|
||||
scoutfs_kvec_init(val, map->encoded, bytes);
|
||||
scoutfs_item_update_dirty(sb, &key, val);
|
||||
kvec_init(&val, map->encoded, bytes);
|
||||
scoutfs_item_update_dirty(sb, &key, &val);
|
||||
} else {
|
||||
scoutfs_item_delete_dirty(sb, &key);
|
||||
}
|
||||
@@ -840,15 +841,15 @@ static int find_free_blkno(struct super_block *sb, u64 blkno, u64 *blkno_ret)
|
||||
struct scoutfs_free_bits_key fbk;
|
||||
struct scoutfs_free_bits frb;
|
||||
struct scoutfs_key_buf key;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
struct kvec val;
|
||||
int ret;
|
||||
int bit;
|
||||
|
||||
init_free_key(&key, &fbk, sbi->node_id, blkno,
|
||||
SCOUTFS_FREE_BITS_BLKNO_TYPE);
|
||||
scoutfs_kvec_init(val, &frb, sizeof(struct scoutfs_free_bits));
|
||||
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
|
||||
|
||||
ret = scoutfs_item_lookup_exact(sb, &key, val, lock);
|
||||
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
@@ -878,7 +879,7 @@ static int find_free_segno(struct super_block *sb, u64 *segno)
|
||||
struct scoutfs_free_bits frb;
|
||||
struct scoutfs_key_buf last_key;
|
||||
struct scoutfs_key_buf key;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
struct kvec val;
|
||||
int bit;
|
||||
int ret;
|
||||
|
||||
@@ -886,9 +887,9 @@ static int find_free_segno(struct super_block *sb, u64 *segno)
|
||||
SCOUTFS_FREE_BITS_SEGNO_TYPE);
|
||||
init_free_key(&last_key, &last_fbk, sbi->node_id, ~0,
|
||||
SCOUTFS_FREE_BITS_SEGNO_TYPE);
|
||||
scoutfs_kvec_init(val, &frb, sizeof(struct scoutfs_free_bits));
|
||||
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
|
||||
|
||||
ret = scoutfs_item_next(sb, &key, &last_key, val, lock);
|
||||
ret = scoutfs_item_next(sb, &key, &last_key, &val, lock);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
@@ -921,7 +922,7 @@ static int find_alloc_block(struct super_block *sb, struct inode *inode,
|
||||
{
|
||||
DECLARE_DATA_INFO(sb, datinf);
|
||||
struct task_cursor *curs;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
struct kvec val;
|
||||
int bytes;
|
||||
u64 segno;
|
||||
u64 blkno;
|
||||
@@ -965,11 +966,11 @@ static int find_alloc_block(struct super_block *sb, struct inode *inode,
|
||||
trace_scoutfs_data_find_alloc_block_found_seg(sb, segno, blkno);
|
||||
|
||||
/* ensure that we can copy in encoded without failing */
|
||||
scoutfs_kvec_init(val, map->encoded, sizeof(map->encoded));
|
||||
kvec_init(&val, map->encoded, sizeof(map->encoded));
|
||||
if (map_exists)
|
||||
ret = scoutfs_item_update(sb, map_key, val, data_lock);
|
||||
ret = scoutfs_item_update(sb, map_key, &val, data_lock);
|
||||
else
|
||||
ret = scoutfs_item_create(sb, map_key, val, data_lock);
|
||||
ret = scoutfs_item_create(sb, map_key, &val, data_lock);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@@ -991,8 +992,8 @@ static int find_alloc_block(struct super_block *sb, struct inode *inode,
|
||||
inode->i_blocks += SCOUTFS_BLOCK_SECTORS;
|
||||
|
||||
bytes = encode_mapping(map);
|
||||
scoutfs_kvec_init(val, map->encoded, bytes);
|
||||
scoutfs_item_update_dirty(sb, map_key, val);
|
||||
kvec_init(&val, map->encoded, bytes);
|
||||
scoutfs_item_update_dirty(sb, map_key, &val);
|
||||
|
||||
/* set cursor to next block, clearing if we finish the segment */
|
||||
curs->blkno++;
|
||||
@@ -1016,7 +1017,7 @@ static int scoutfs_get_block(struct inode *inode, sector_t iblock,
|
||||
struct scoutfs_key_buf key;
|
||||
struct scoutfs_lock *lock;
|
||||
struct block_mapping *map;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
struct kvec val;
|
||||
bool exists;
|
||||
int ind;
|
||||
int ret;
|
||||
@@ -1031,10 +1032,10 @@ static int scoutfs_get_block(struct inode *inode, sector_t iblock,
|
||||
return -ENOMEM;
|
||||
|
||||
init_mapping_key(&key, &bmk, scoutfs_ino(inode), iblock);
|
||||
scoutfs_kvec_init(val, map->encoded, sizeof(map->encoded));
|
||||
kvec_init(&val, map->encoded, sizeof(map->encoded));
|
||||
|
||||
/* find the mapping item that covers the logical block */
|
||||
ret = scoutfs_item_lookup(sb, &key, val, lock);
|
||||
ret = scoutfs_item_lookup(sb, &key, &val, lock);
|
||||
if (ret < 0) {
|
||||
if (ret != -ENOENT)
|
||||
goto out;
|
||||
@@ -1316,7 +1317,7 @@ int scoutfs_data_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
||||
struct pending_fiemap pend;
|
||||
struct scoutfs_block_mapping_key last_bmk;
|
||||
struct scoutfs_block_mapping_key bmk;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
struct kvec val;
|
||||
loff_t i_size;
|
||||
bool offline;
|
||||
u64 blk_off;
|
||||
@@ -1358,9 +1359,9 @@ int scoutfs_data_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
|
||||
|
||||
while (blk_off <= final) {
|
||||
init_mapping_key(&key, &bmk, ino, blk_off);
|
||||
scoutfs_kvec_init(val, &map->encoded, sizeof(map->encoded));
|
||||
kvec_init(&val, &map->encoded, sizeof(map->encoded));
|
||||
|
||||
ret = scoutfs_item_next(sb, &key, &last_key, val, inode_lock);
|
||||
ret = scoutfs_item_next(sb, &key, &last_key, &val, inode_lock);
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOENT)
|
||||
ret = 0;
|
||||
|
||||
+18
-19
@@ -247,7 +247,7 @@ static int lookup_dirent(struct super_block *sb, struct inode *dir,
|
||||
struct scoutfs_lock *lock)
|
||||
{
|
||||
struct scoutfs_key_buf *key = NULL;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
struct kvec val;
|
||||
int ret;
|
||||
|
||||
key = alloc_dirent_key(sb, scoutfs_ino(dir), name, name_len);
|
||||
@@ -256,9 +256,9 @@ static int lookup_dirent(struct super_block *sb, struct inode *dir,
|
||||
goto out;
|
||||
}
|
||||
|
||||
scoutfs_kvec_init(val, dent, sizeof(struct scoutfs_dirent));
|
||||
kvec_init(&val, dent, sizeof(struct scoutfs_dirent));
|
||||
|
||||
ret = scoutfs_item_lookup_exact(sb, key, val, lock);
|
||||
ret = scoutfs_item_lookup_exact(sb, key, &val, lock);
|
||||
out:
|
||||
scoutfs_key_free(sb, key);
|
||||
return ret;
|
||||
@@ -457,9 +457,9 @@ static int scoutfs_readdir(struct file *file, void *dirent, filldir_t filldir)
|
||||
struct scoutfs_readdir_key rkey;
|
||||
struct scoutfs_readdir_key last_rkey;
|
||||
struct scoutfs_lock *dir_lock;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
unsigned int item_len;
|
||||
unsigned int name_len;
|
||||
struct kvec val;
|
||||
u64 pos;
|
||||
int ret;
|
||||
|
||||
@@ -483,8 +483,8 @@ static int scoutfs_readdir(struct file *file, void *dirent, filldir_t filldir)
|
||||
for (;;) {
|
||||
init_readdir_key(&key, &rkey, scoutfs_ino(inode), file->f_pos);
|
||||
|
||||
scoutfs_kvec_init(val, dent, item_len);
|
||||
ret = scoutfs_item_next_same_min(sb, &key, &last_key, val,
|
||||
kvec_init(&val, dent, item_len);
|
||||
ret = scoutfs_item_next_same_min(sb, &key, &last_key, &val,
|
||||
offsetof(struct scoutfs_dirent, name[1]),
|
||||
dir_lock);
|
||||
if (ret < 0) {
|
||||
@@ -529,9 +529,9 @@ static int add_entry_items(struct super_block *sb, u64 dir_ino, u64 pos,
|
||||
struct scoutfs_dirent *dent = NULL;
|
||||
struct scoutfs_key_buf rdir_key;
|
||||
struct scoutfs_readdir_key rkey;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
bool del_ent = false;
|
||||
bool del_rdir = false;
|
||||
struct kvec val;
|
||||
int ret;
|
||||
|
||||
ent_key = alloc_dirent_key(sb, dir_ino, name, name_len);
|
||||
@@ -549,18 +549,17 @@ static int add_entry_items(struct super_block *sb, u64 dir_ino, u64 pos,
|
||||
memcpy(dent->name, name, name_len);
|
||||
|
||||
/* dirent item for lookup */
|
||||
scoutfs_kvec_init(val, dent, sizeof(struct scoutfs_dirent));
|
||||
ret = scoutfs_item_create(sb, ent_key, val, dir_lock);
|
||||
kvec_init(&val, dent, sizeof(struct scoutfs_dirent));
|
||||
ret = scoutfs_item_create(sb, ent_key, &val, dir_lock);
|
||||
if (ret)
|
||||
goto out;
|
||||
del_ent = true;
|
||||
|
||||
/* readdir item for .. readdir */
|
||||
init_readdir_key(&rdir_key, &rkey, dir_ino, pos);
|
||||
scoutfs_kvec_init(val, dent, offsetof(struct scoutfs_dirent,
|
||||
name[name_len]));
|
||||
kvec_init(&val, dent, offsetof(struct scoutfs_dirent, name[name_len]));
|
||||
|
||||
ret = scoutfs_item_create(sb, &rdir_key, val, dir_lock);
|
||||
ret = scoutfs_item_create(sb, &rdir_key, &val, dir_lock);
|
||||
if (ret)
|
||||
goto out;
|
||||
del_rdir = true;
|
||||
@@ -984,7 +983,7 @@ static int symlink_item_ops(struct super_block *sb, int op, u64 ino,
|
||||
{
|
||||
struct scoutfs_symlink_key skey;
|
||||
struct scoutfs_key_buf key;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
struct kvec val;
|
||||
unsigned bytes;
|
||||
unsigned nr;
|
||||
int ret;
|
||||
@@ -999,12 +998,12 @@ static int symlink_item_ops(struct super_block *sb, int op, u64 ino,
|
||||
|
||||
init_symlink_key(&key, &skey, ino, i);
|
||||
bytes = min_t(u64, size, SCOUTFS_MAX_VAL_SIZE);
|
||||
scoutfs_kvec_init(val, (void *)target, bytes);
|
||||
kvec_init(&val, (void *)target, bytes);
|
||||
|
||||
if (op == SYM_CREATE)
|
||||
ret = scoutfs_item_create(sb, &key, val, lock);
|
||||
ret = scoutfs_item_create(sb, &key, &val, lock);
|
||||
else if (op == SYM_LOOKUP)
|
||||
ret = scoutfs_item_lookup_exact(sb, &key, val, lock);
|
||||
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
|
||||
else if (op == SYM_DELETE)
|
||||
ret = scoutfs_item_delete(sb, &key, lock);
|
||||
if (ret)
|
||||
@@ -1440,16 +1439,16 @@ static int verify_entry(struct super_block *sb, u64 dir_ino, const char *name,
|
||||
{
|
||||
struct scoutfs_key_buf *key = NULL;
|
||||
struct scoutfs_dirent dent;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
struct kvec val;
|
||||
int ret;
|
||||
|
||||
key = alloc_dirent_key(sb, dir_ino, name, name_len);
|
||||
if (!key)
|
||||
return -ENOMEM;
|
||||
|
||||
scoutfs_kvec_init(val, &dent, sizeof(dent));
|
||||
kvec_init(&val, &dent, sizeof(dent));
|
||||
|
||||
ret = scoutfs_item_lookup_exact(sb, key, val, lock);
|
||||
ret = scoutfs_item_lookup_exact(sb, key, &val, lock);
|
||||
if (ret == 0 && le64_to_cpu(dent.ino) != ino)
|
||||
ret = -ENOENT;
|
||||
else if (ret == -ENOENT && ino == 0)
|
||||
|
||||
+12
-12
@@ -266,7 +266,7 @@ int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock,
|
||||
struct scoutfs_key_buf key;
|
||||
struct scoutfs_inode_key ikey;
|
||||
struct scoutfs_inode sinode;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
struct kvec val;
|
||||
const u64 refresh_gen = lock->refresh_gen;
|
||||
int ret;
|
||||
|
||||
@@ -282,11 +282,11 @@ int scoutfs_inode_refresh(struct inode *inode, struct scoutfs_lock *lock,
|
||||
return 0;
|
||||
|
||||
scoutfs_inode_init_key(&key, &ikey, scoutfs_ino(inode));
|
||||
scoutfs_kvec_init(val, &sinode, sizeof(sinode));
|
||||
kvec_init(&val, &sinode, sizeof(sinode));
|
||||
|
||||
mutex_lock(&si->item_mutex);
|
||||
if (atomic64_read(&si->last_refreshed) < refresh_gen) {
|
||||
ret = scoutfs_item_lookup_exact(sb, &key, val, lock);
|
||||
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
|
||||
if (ret == 0) {
|
||||
load_inode(inode, &sinode);
|
||||
atomic64_set(&si->last_refreshed, refresh_gen);
|
||||
@@ -909,7 +909,7 @@ void scoutfs_update_inode_item(struct inode *inode, struct scoutfs_lock *lock,
|
||||
struct scoutfs_inode_key ikey;
|
||||
struct scoutfs_key_buf key;
|
||||
struct scoutfs_inode sinode;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
struct kvec val;
|
||||
int ret;
|
||||
int err;
|
||||
|
||||
@@ -925,9 +925,9 @@ void scoutfs_update_inode_item(struct inode *inode, struct scoutfs_lock *lock,
|
||||
BUG_ON(ret);
|
||||
|
||||
scoutfs_inode_init_key(&key, &ikey, ino);
|
||||
scoutfs_kvec_init(val, &sinode, sizeof(sinode));
|
||||
kvec_init(&val, &sinode, sizeof(sinode));
|
||||
|
||||
err = scoutfs_item_update(sb, &key, val, lock);
|
||||
err = scoutfs_item_update(sb, &key, &val, lock);
|
||||
if (err) {
|
||||
scoutfs_err(sb, "inode %llu update err %d", ino, err);
|
||||
BUG_ON(err);
|
||||
@@ -1314,8 +1314,8 @@ struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir,
|
||||
struct scoutfs_inode_key ikey;
|
||||
struct scoutfs_key_buf key;
|
||||
struct scoutfs_inode sinode;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
struct inode *inode;
|
||||
struct kvec val;
|
||||
int ret;
|
||||
|
||||
inode = new_inode(sb);
|
||||
@@ -1347,9 +1347,9 @@ struct inode *scoutfs_new_inode(struct super_block *sb, struct inode *dir,
|
||||
|
||||
store_inode(&sinode, inode);
|
||||
scoutfs_inode_init_key(&key, &ikey, scoutfs_ino(inode));
|
||||
scoutfs_kvec_init(val, &sinode, sizeof(sinode));
|
||||
kvec_init(&val, &sinode, sizeof(sinode));
|
||||
|
||||
ret = scoutfs_item_create(sb, &key, val, lock);
|
||||
ret = scoutfs_item_create(sb, &key, &val, lock);
|
||||
if (ret) {
|
||||
iput(inode);
|
||||
return ERR_PTR(ret);
|
||||
@@ -1400,9 +1400,9 @@ static int delete_inode_items(struct super_block *sb, u64 ino)
|
||||
struct scoutfs_inode_key ikey;
|
||||
struct scoutfs_inode sinode;
|
||||
struct scoutfs_key_buf key;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
LIST_HEAD(ind_locks);
|
||||
bool release = false;
|
||||
struct kvec val;
|
||||
umode_t mode;
|
||||
u64 ind_seq;
|
||||
int ret;
|
||||
@@ -1412,9 +1412,9 @@ static int delete_inode_items(struct super_block *sb, u64 ino)
|
||||
return ret;
|
||||
|
||||
scoutfs_inode_init_key(&key, &ikey, ino);
|
||||
scoutfs_kvec_init(val, &sinode, sizeof(sinode));
|
||||
kvec_init(&val, &sinode, sizeof(sinode));
|
||||
|
||||
ret = scoutfs_item_lookup_exact(sb, &key, val, lock);
|
||||
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOENT)
|
||||
ret = 0;
|
||||
|
||||
+70
-37
@@ -44,7 +44,7 @@
|
||||
static bool invalid_key_val(struct scoutfs_key_buf *key, struct kvec *val)
|
||||
{
|
||||
return WARN_ON_ONCE(key->key_len > SCOUTFS_MAX_KEY_SIZE ||
|
||||
(val && (scoutfs_kvec_length(val) > SCOUTFS_MAX_VAL_SIZE)));
|
||||
(val && (val->iov_len > SCOUTFS_MAX_VAL_SIZE)));
|
||||
}
|
||||
|
||||
struct item_cache {
|
||||
@@ -79,8 +79,8 @@ struct cached_item {
|
||||
unsigned deletion:1;
|
||||
|
||||
struct scoutfs_key_buf *key;
|
||||
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
void *val;
|
||||
unsigned int val_len;
|
||||
};
|
||||
|
||||
struct cached_range {
|
||||
@@ -105,11 +105,16 @@ static void free_item(struct super_block *sb, struct cached_item *item)
|
||||
WARN_ON_ONCE(!list_empty(&item->entry));
|
||||
WARN_ON_ONCE(!RB_EMPTY_NODE(&item->node));
|
||||
scoutfs_key_free(sb, item->key);
|
||||
scoutfs_kvec_kfree(item->val);
|
||||
kfree(item->val);
|
||||
kfree(item);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The value vec may be null if the item has no value. Values are
|
||||
* allocated separately so that we can free them when deleting or swap
|
||||
* them in place when updating items.
|
||||
*/
|
||||
static struct cached_item *alloc_item(struct super_block *sb,
|
||||
struct scoutfs_key_buf *key,
|
||||
struct kvec *val)
|
||||
@@ -121,12 +126,15 @@ static struct cached_item *alloc_item(struct super_block *sb,
|
||||
RB_CLEAR_NODE(&item->node);
|
||||
INIT_LIST_HEAD(&item->entry);
|
||||
|
||||
if (!val)
|
||||
scoutfs_kvec_init_null(item->val);
|
||||
|
||||
item->key = scoutfs_key_dup(sb, key);
|
||||
if (!item->key ||
|
||||
(val && scoutfs_kvec_dup_flatten(item->val, val))) {
|
||||
if (val) {
|
||||
item->val = kmalloc(val->iov_len, GFP_NOFS);
|
||||
item->val_len = val->iov_len;
|
||||
if (item->val)
|
||||
memcpy(item->val, val->iov_base, val->iov_len);
|
||||
}
|
||||
|
||||
if (!item->key || (val && !item->val)) {
|
||||
free_item(sb, item);
|
||||
item = NULL;
|
||||
}
|
||||
@@ -138,6 +146,25 @@ static struct cached_item *alloc_item(struct super_block *sb,
|
||||
return item;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the cached item's value into the caller's single value vector.
|
||||
* The number of bytes that fit in the vec and were copied is returned.
|
||||
* A null val returns 0.
|
||||
*/
|
||||
static int copy_item_val(struct kvec *val, struct cached_item *item)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (val) {
|
||||
ret = min_t(size_t, item->val_len, val->iov_len);
|
||||
memcpy(val->iov_base, item->val, ret);
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk the item rbtree and return the item found and the next and
|
||||
* prev items.
|
||||
@@ -340,9 +367,7 @@ static void mark_item_dirty(struct super_block *sb, struct item_cache *cac,
|
||||
list_del_init(&item->entry);
|
||||
cac->lru_nr--;
|
||||
|
||||
update_dirty_item_counts(sb, 1, item->key->key_len,
|
||||
scoutfs_kvec_length(item->val));
|
||||
|
||||
update_dirty_item_counts(sb, 1, item->key->key_len, item->val_len);
|
||||
update_dirty_parents(item);
|
||||
}
|
||||
|
||||
@@ -359,8 +384,7 @@ static void clear_item_dirty(struct super_block *sb, struct item_cache *cac,
|
||||
list_add_tail(&item->entry, &cac->lru_list);
|
||||
cac->lru_nr++;
|
||||
|
||||
update_dirty_item_counts(sb, -1, -item->key->key_len,
|
||||
-scoutfs_kvec_length(item->val));
|
||||
update_dirty_item_counts(sb, -1, -item->key->key_len, -item->val_len);
|
||||
|
||||
WARN_ON_ONCE(cac->nr_dirty_items < 0 || cac->dirty_key_bytes < 0 ||
|
||||
cac->dirty_val_bytes < 0);
|
||||
@@ -408,9 +432,13 @@ static void become_deletion_item(struct super_block *sb,
|
||||
struct item_cache *cac,
|
||||
struct cached_item *item)
|
||||
{
|
||||
/* uses val_len to update item accounting */
|
||||
clear_item_dirty(sb, cac, item);
|
||||
scoutfs_kvec_kfree(item->val);
|
||||
scoutfs_kvec_init_null(item->val);
|
||||
|
||||
kfree(item->val);
|
||||
item->val = NULL;
|
||||
item->val_len = 0;
|
||||
|
||||
item->deletion = 1;
|
||||
mark_item_dirty(sb, cac, item);
|
||||
scoutfs_inc_counter(sb, item_delete);
|
||||
@@ -788,7 +816,7 @@ int scoutfs_item_lookup(struct super_block *sb, struct scoutfs_key_buf *key,
|
||||
if (item) {
|
||||
item_referenced(cac, item);
|
||||
if (val)
|
||||
ret = scoutfs_kvec_memcpy(val, item->val);
|
||||
ret = copy_item_val(val, item);
|
||||
else
|
||||
ret = 0;
|
||||
} else if (check_range(sb, &cac->ranges, key, NULL)) {
|
||||
@@ -824,11 +852,10 @@ int scoutfs_item_lookup_exact(struct super_block *sb,
|
||||
struct scoutfs_key_buf *key, struct kvec *val,
|
||||
struct scoutfs_lock *lock)
|
||||
{
|
||||
int size = scoutfs_kvec_length(val);
|
||||
int ret;
|
||||
|
||||
ret = scoutfs_item_lookup(sb, key, val, lock);
|
||||
if (ret == size)
|
||||
if (ret == val->iov_len)
|
||||
ret = 0;
|
||||
else if (ret >= 0)
|
||||
ret = -EIO;
|
||||
@@ -994,7 +1021,7 @@ int scoutfs_item_next(struct super_block *sb, struct scoutfs_key_buf *key,
|
||||
scoutfs_key_copy(key, item->key);
|
||||
if (val) {
|
||||
item_referenced(cac, item);
|
||||
ret = scoutfs_kvec_memcpy(val, item->val);
|
||||
ret = copy_item_val(val, item);
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
@@ -1027,7 +1054,7 @@ int scoutfs_item_next_same_min(struct super_block *sb,
|
||||
|
||||
trace_scoutfs_item_next_same_min(sb, key_len, len);
|
||||
|
||||
if (WARN_ON_ONCE(!val || scoutfs_kvec_length(val) < len))
|
||||
if (WARN_ON_ONCE(!val || val->iov_len < len))
|
||||
return -EINVAL;
|
||||
|
||||
ret = scoutfs_item_next(sb, key, last, val, lock);
|
||||
@@ -1306,9 +1333,9 @@ int scoutfs_item_update(struct super_block *sb, struct scoutfs_key_buf *key,
|
||||
{
|
||||
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
|
||||
struct item_cache *cac = sbi->item_cache;
|
||||
SCOUTFS_DECLARE_KVEC(up_val);
|
||||
struct cached_item *item;
|
||||
unsigned long flags;
|
||||
void *up_val = NULL;
|
||||
int ret;
|
||||
|
||||
if (invalid_key_val(key, val))
|
||||
@@ -1318,11 +1345,12 @@ int scoutfs_item_update(struct super_block *sb, struct scoutfs_key_buf *key,
|
||||
return -EINVAL;
|
||||
|
||||
if (val) {
|
||||
ret = scoutfs_kvec_dup_flatten(up_val, val);
|
||||
if (ret)
|
||||
up_val = kmalloc(val->iov_len, GFP_NOFS);
|
||||
if (!up_val) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
} else {
|
||||
scoutfs_kvec_init_null(up_val);
|
||||
}
|
||||
memcpy(up_val, val->iov_base, val->iov_len);
|
||||
}
|
||||
|
||||
do {
|
||||
@@ -1331,7 +1359,8 @@ int scoutfs_item_update(struct super_block *sb, struct scoutfs_key_buf *key,
|
||||
item = find_item(sb, &cac->items, key);
|
||||
if (item) {
|
||||
clear_item_dirty(sb, cac, item);
|
||||
scoutfs_kvec_swap(up_val, item->val);
|
||||
swap(up_val, item->val);
|
||||
item->val_len = val ? val->iov_len : 0;
|
||||
mark_item_dirty(sb, cac, item);
|
||||
ret = 0;
|
||||
} else if (check_range(sb, &cac->ranges, key, NULL)) {
|
||||
@@ -1346,7 +1375,7 @@ int scoutfs_item_update(struct super_block *sb, struct scoutfs_key_buf *key,
|
||||
(ret = scoutfs_manifest_read_items(sb, key, lock->start,
|
||||
lock->end)) == 0);
|
||||
out:
|
||||
scoutfs_kvec_kfree(up_val);
|
||||
kfree(up_val);
|
||||
|
||||
trace_scoutfs_item_update_ret(sb, ret);
|
||||
return ret;
|
||||
@@ -1412,7 +1441,6 @@ int scoutfs_item_delete_force(struct super_block *sb,
|
||||
if (WARN_ON_ONCE(!lock_coverage(lock, key, DLM_LOCK_CW)))
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
item = alloc_item(sb, key, NULL);
|
||||
if (!item)
|
||||
return -ENOMEM;
|
||||
@@ -1568,7 +1596,6 @@ void scoutfs_item_delete_dirty(struct super_block *sb,
|
||||
struct cached_item *item;
|
||||
unsigned long flags;
|
||||
|
||||
|
||||
spin_lock_irqsave(&cac->lock, flags);
|
||||
|
||||
item = find_item(sb, &cac->items, key);
|
||||
@@ -1581,7 +1608,9 @@ void scoutfs_item_delete_dirty(struct super_block *sb,
|
||||
/*
|
||||
* Copy the callers value into the dirty item and truncate its value if
|
||||
* the existing value is longer. The caller must have ensured that the
|
||||
* item was dirty and had a large enough value.
|
||||
* item was dirty and had a large enough value. If the updated value is
|
||||
* smaller then it will sit in the larger item allocation until the
|
||||
* value is eventually freed along with the item.
|
||||
*/
|
||||
void scoutfs_item_update_dirty(struct super_block *sb,
|
||||
struct scoutfs_key_buf *key, struct kvec *val)
|
||||
@@ -1590,17 +1619,19 @@ void scoutfs_item_update_dirty(struct super_block *sb,
|
||||
struct item_cache *cac = sbi->item_cache;
|
||||
struct cached_item *item;
|
||||
unsigned long flags;
|
||||
unsigned int new_len = val ? val->iov_len : 0;
|
||||
signed delta;
|
||||
|
||||
spin_lock_irqsave(&cac->lock, flags);
|
||||
|
||||
item = find_item(sb, &cac->items, key);
|
||||
|
||||
BUG_ON(!item || !item_is_dirty(item) ||
|
||||
scoutfs_kvec_length(val) > scoutfs_kvec_length(item->val));
|
||||
BUG_ON(!item || !item_is_dirty(item) || new_len > item->val_len);
|
||||
|
||||
delta = scoutfs_kvec_length(val) - scoutfs_kvec_length(item->val);
|
||||
scoutfs_kvec_memcpy_truncate(item->val, val);
|
||||
delta = new_len - item->val_len;
|
||||
if (val)
|
||||
memcpy(item->val, val->iov_base, new_len);
|
||||
item->val_len = new_len;
|
||||
update_dirty_item_counts(sb, 0, 0, delta);
|
||||
|
||||
spin_unlock_irqrestore(&cac->lock, flags);
|
||||
@@ -1767,13 +1798,15 @@ int scoutfs_item_dirty_seg(struct super_block *sb, struct scoutfs_segment *seg)
|
||||
struct cached_item *item = NULL;
|
||||
struct cached_item *del;
|
||||
unsigned long flags;
|
||||
struct kvec val;
|
||||
bool appended;
|
||||
|
||||
spin_lock_irqsave(&cac->lock, flags);
|
||||
|
||||
item = first_dirty(cac->items.rb_node);
|
||||
while (item) {
|
||||
appended = scoutfs_seg_append_item(sb, seg, item->key, item->val,
|
||||
kvec_init(&val, item->val, item->val_len);
|
||||
appended = scoutfs_seg_append_item(sb, seg, item->key, &val,
|
||||
item_flags(item), links);
|
||||
/* trans reservation should have limited dirty */
|
||||
BUG_ON(!appended);
|
||||
@@ -2064,7 +2097,7 @@ static int shrink_around(struct super_block *sb, struct cached_range *rng,
|
||||
|
||||
unlink_item(sb, cac, item);
|
||||
key = item->key;
|
||||
scoutfs_kvec_kfree(item->val);
|
||||
kfree(item->val);
|
||||
nr++;
|
||||
|
||||
new_rng = (void *)item;
|
||||
|
||||
-292
@@ -1,292 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 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
|
||||
* License v2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/magic.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/statfs.h>
|
||||
#include <linux/ctype.h>
|
||||
|
||||
#include "super.h"
|
||||
#include "format.h"
|
||||
#include "inode.h"
|
||||
#include "dir.h"
|
||||
#include "xattr.h"
|
||||
#include "msg.h"
|
||||
#include "counters.h"
|
||||
#include "trans.h"
|
||||
#include "kvec.h"
|
||||
#include "scoutfs_trace.h"
|
||||
|
||||
struct iter {
|
||||
struct kvec *kvec;
|
||||
size_t count;
|
||||
size_t off;
|
||||
size_t i;
|
||||
};
|
||||
|
||||
static void iter_advance(struct iter *iter, size_t len)
|
||||
{
|
||||
iter->off += len;
|
||||
iter->count -= len;
|
||||
|
||||
while (iter->i < SCOUTFS_KVEC_NR && iter->off >= iter->kvec->iov_len) {
|
||||
iter->off -= iter->kvec->iov_len;
|
||||
iter->kvec++;
|
||||
iter->i++;
|
||||
}
|
||||
}
|
||||
|
||||
static void iter_init(struct iter *iter, struct kvec *kvec)
|
||||
{
|
||||
iter->kvec = kvec;
|
||||
iter->i = 0;
|
||||
iter->off = 0;
|
||||
iter->count = scoutfs_kvec_length(kvec);
|
||||
|
||||
iter_advance(iter, 0);
|
||||
}
|
||||
|
||||
static void *iter_ptr(struct iter *iter)
|
||||
{
|
||||
if (iter->i < SCOUTFS_KVEC_NR)
|
||||
return iter->kvec->iov_base + iter->off;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* count of contiguous bytes available at the next vector */
|
||||
static size_t iter_contig(struct iter *iter)
|
||||
{
|
||||
if (iter->i < SCOUTFS_KVEC_NR)
|
||||
return iter->kvec->iov_len - iter->off;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the result of memcmp between the min of the two total lengths.
|
||||
* If their shorter lengths are equal than the shorter length is considered
|
||||
* smaller than the longer.
|
||||
*/
|
||||
int scoutfs_kvec_memcmp(struct kvec *a, struct kvec *b)
|
||||
{
|
||||
struct iter a_iter;
|
||||
struct iter b_iter;
|
||||
size_t len;
|
||||
int ret;
|
||||
|
||||
iter_init(&a_iter, a);
|
||||
iter_init(&b_iter, b);
|
||||
|
||||
while ((len = min(iter_contig(&a_iter), iter_contig(&b_iter)))) {
|
||||
ret = memcmp(iter_ptr(&a_iter), iter_ptr(&b_iter), len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
iter_advance(&a_iter, len);
|
||||
iter_advance(&b_iter, len);
|
||||
}
|
||||
|
||||
return iter_contig(&a_iter) ? 1 : iter_contig(&b_iter) ? -1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return -1 if [a,b] doesn't overlap with and is to the left of [c,d],
|
||||
* 1 if it doesn't overlap and is to the right of, and 0 if they
|
||||
* overlap.
|
||||
*/
|
||||
int scoutfs_kvec_cmp_overlap(struct kvec *a, struct kvec *b,
|
||||
struct kvec *c, struct kvec *d)
|
||||
{
|
||||
return scoutfs_kvec_memcmp(b, c) < 0 ? -1 :
|
||||
scoutfs_kvec_memcmp(a, d) > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set just the pointers and length fields in the dst vector to point to
|
||||
* the source vector.
|
||||
*/
|
||||
void scoutfs_kvec_clone(struct kvec *dst, struct kvec *src)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SCOUTFS_KVEC_NR; i++)
|
||||
dst[i] = src[i];
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy as much of src as fits in dst. Null base pointers termintae the
|
||||
* copy. The number of bytes copied is returned. Only the buffers
|
||||
* pointed to by dst are changed, the kvec elements are not changed.
|
||||
*/
|
||||
int scoutfs_kvec_memcpy(struct kvec *dst, struct kvec *src)
|
||||
{
|
||||
struct iter dst_iter;
|
||||
struct iter src_iter;
|
||||
size_t copied = 0;
|
||||
size_t len;
|
||||
|
||||
iter_init(&dst_iter, dst);
|
||||
iter_init(&src_iter, src);
|
||||
|
||||
while ((len = min(iter_contig(&dst_iter), iter_contig(&src_iter)))) {
|
||||
memcpy(iter_ptr(&dst_iter), iter_ptr(&src_iter), len);
|
||||
|
||||
copied += len;
|
||||
iter_advance(&dst_iter, len);
|
||||
iter_advance(&src_iter, len);
|
||||
}
|
||||
|
||||
return copied;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy bytes in src into dst, stopping if dst is full. The number of copied
|
||||
* bytes is returned and the lengths of dst are updated if the size changes.
|
||||
* The pointers in dst are not changed.
|
||||
*/
|
||||
int scoutfs_kvec_memcpy_truncate(struct kvec *dst, struct kvec *src)
|
||||
{
|
||||
int copied = scoutfs_kvec_memcpy(dst, src);
|
||||
size_t bytes;
|
||||
int i;
|
||||
|
||||
if (copied < scoutfs_kvec_length(dst)) {
|
||||
bytes = copied;
|
||||
for (i = 0; i < SCOUTFS_KVEC_NR; i++) {
|
||||
dst[i].iov_len = min(dst[i].iov_len, bytes);
|
||||
bytes -= dst[i].iov_len;
|
||||
}
|
||||
}
|
||||
|
||||
return copied;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the src key vector into one new allocation in the dst. The existing
|
||||
* dst is clobbered. The source isn't changed.
|
||||
*/
|
||||
int scoutfs_kvec_dup_flatten(struct kvec *dst, struct kvec *src)
|
||||
{
|
||||
void *ptr;
|
||||
size_t len = scoutfs_kvec_length(src);
|
||||
|
||||
ptr = kmalloc(len, GFP_NOFS);
|
||||
if (!ptr) {
|
||||
scoutfs_kvec_init_null(dst);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
scoutfs_kvec_init(dst, ptr, len);
|
||||
scoutfs_kvec_memcpy(dst, src);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Free all the set pointers in the kvec.
|
||||
*/
|
||||
void scoutfs_kvec_kfree(struct kvec *kvec)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < SCOUTFS_KVEC_NR; i++) {
|
||||
kfree(kvec[i].iov_base);
|
||||
kvec[i].iov_base = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void scoutfs_kvec_init_null(struct kvec *kvec)
|
||||
{
|
||||
memset(kvec, 0, SCOUTFS_KVEC_BYTES);
|
||||
}
|
||||
|
||||
void scoutfs_kvec_swap(struct kvec *a, struct kvec *b)
|
||||
{
|
||||
SCOUTFS_DECLARE_KVEC(tmp);
|
||||
|
||||
memcpy(tmp, a, SCOUTFS_KVEC_BYTES);
|
||||
memcpy(a, b, SCOUTFS_KVEC_BYTES);
|
||||
memcpy(b, tmp, SCOUTFS_KVEC_BYTES);
|
||||
}
|
||||
|
||||
int scoutfs_kvec_alloc_key(struct kvec *kvec)
|
||||
{
|
||||
const size_t len = SCOUTFS_MAX_KEY_SIZE;
|
||||
void *ptr;
|
||||
|
||||
ptr = kzalloc(len, GFP_NOFS);
|
||||
if (!ptr) {
|
||||
scoutfs_kvec_init_null(kvec);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
scoutfs_kvec_init(kvec, ptr, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void scoutfs_kvec_init_key(struct kvec *kvec)
|
||||
{
|
||||
scoutfs_kvec_init(kvec, kvec[0].iov_base, SCOUTFS_MAX_KEY_SIZE);
|
||||
}
|
||||
|
||||
void scoutfs_kvec_set_max_key(struct kvec *kvec)
|
||||
{
|
||||
__u8 *type = kvec[0].iov_base;
|
||||
|
||||
*type = 255;
|
||||
scoutfs_kvec_init(kvec, type, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Increase the kvec as though it is a big endian value. Carry
|
||||
* increments of the least significant byte as long as it wraps.
|
||||
*/
|
||||
void scoutfs_kvec_be_inc(struct kvec *kvec)
|
||||
{
|
||||
int i;
|
||||
int b;
|
||||
|
||||
for (i = SCOUTFS_KVEC_NR - 1; i >= 0; i--) {
|
||||
for (b = (int)kvec[i].iov_len - 1; b >= 0; b--) {
|
||||
if (++((u8 *)kvec[i].iov_base)[b])
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void scoutfs_kvec_be_dec(struct kvec *kvec)
|
||||
{
|
||||
int i;
|
||||
int b;
|
||||
|
||||
for (i = SCOUTFS_KVEC_NR - 1; i >= 0; i--) {
|
||||
for (b = (int)kvec[i].iov_len - 1; b >= 0; b--) {
|
||||
if (--((u8 *)kvec[i].iov_base)[b] != 0xff)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Clone the source kvec into the dst if the dst is empty or if
|
||||
* the src kvec is less than the dst.
|
||||
*/
|
||||
void scoutfs_kvec_clone_less(struct kvec *dst, struct kvec *src)
|
||||
{
|
||||
if (scoutfs_kvec_length(dst) == 0 ||
|
||||
scoutfs_kvec_memcmp(src, dst) < 0)
|
||||
scoutfs_kvec_clone(dst, src);
|
||||
}
|
||||
+3
-63
@@ -3,70 +3,10 @@
|
||||
|
||||
#include <linux/uio.h>
|
||||
|
||||
/*
|
||||
* The item APIs use kvecs to represent variable size item keys and
|
||||
* values.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This ends up defining the max item size as nr - 1 * page _size.
|
||||
*/
|
||||
#define SCOUTFS_KVEC_NR 2
|
||||
#define SCOUTFS_KVEC_BYTES (SCOUTFS_KVEC_NR * sizeof(struct kvec))
|
||||
|
||||
#define SCOUTFS_DECLARE_KVEC(name) \
|
||||
struct kvec name[SCOUTFS_KVEC_NR]
|
||||
|
||||
static inline void scoutfs_kvec_init_all(struct kvec *kvec,
|
||||
void *ptr0, size_t len0,
|
||||
void *ptr1, size_t len1,
|
||||
void *ptr2, ...)
|
||||
static inline void kvec_init(struct kvec *kv, void *base, size_t len)
|
||||
{
|
||||
BUG_ON(ptr2 != NULL);
|
||||
|
||||
kvec[0].iov_base = ptr0;
|
||||
kvec[0].iov_len = len0;
|
||||
kvec[1].iov_base = ptr1;
|
||||
kvec[1].iov_len = len1;
|
||||
kv->iov_base = base;
|
||||
kv->iov_len = len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Provide a nice variadic initialization function without having to
|
||||
* iterate over the callers arg types. We play some macro games to pad
|
||||
* out the callers ptr/len pairs to the full possible number. This will
|
||||
* produce confusing errors if an odd number of arguments is given and
|
||||
* the padded ptr/length types aren't compatible with the fixed
|
||||
* arguments in the static inline.
|
||||
*/
|
||||
#define scoutfs_kvec_init(val, ...) \
|
||||
scoutfs_kvec_init_all(val, __VA_ARGS__, NULL, 0, NULL, 0)
|
||||
|
||||
static inline int scoutfs_kvec_length(struct kvec *kvec)
|
||||
{
|
||||
BUILD_BUG_ON(sizeof(struct kvec) != sizeof(struct iovec));
|
||||
BUILD_BUG_ON(offsetof(struct kvec, iov_len) !=
|
||||
offsetof(struct iovec, iov_len));
|
||||
BUILD_BUG_ON(member_sizeof(struct kvec, iov_len) !=
|
||||
member_sizeof(struct iovec, iov_len));
|
||||
|
||||
return iov_length((struct iovec *)kvec, SCOUTFS_KVEC_NR);
|
||||
}
|
||||
|
||||
void scoutfs_kvec_clone(struct kvec *dst, struct kvec *src);
|
||||
int scoutfs_kvec_memcmp(struct kvec *a, struct kvec *b);
|
||||
int scoutfs_kvec_cmp_overlap(struct kvec *a, struct kvec *b,
|
||||
struct kvec *c, struct kvec *d);
|
||||
int scoutfs_kvec_memcpy(struct kvec *dst, struct kvec *src);
|
||||
int scoutfs_kvec_memcpy_truncate(struct kvec *dst, struct kvec *src);
|
||||
int scoutfs_kvec_dup_flatten(struct kvec *dst, struct kvec *src);
|
||||
void scoutfs_kvec_kfree(struct kvec *kvec);
|
||||
void scoutfs_kvec_init_null(struct kvec *kvec);
|
||||
void scoutfs_kvec_swap(struct kvec *a, struct kvec *b);
|
||||
int scoutfs_kvec_alloc_key(struct kvec *kvec);
|
||||
void scoutfs_kvec_init_key(struct kvec *kvec);
|
||||
void scoutfs_kvec_set_max_key(struct kvec *kvec);
|
||||
void scoutfs_kvec_clone_less(struct kvec *dst, struct kvec *src);
|
||||
void scoutfs_kvec_be_inc(struct kvec *kvec);
|
||||
void scoutfs_kvec_be_dec(struct kvec *kvec);
|
||||
|
||||
#endif
|
||||
|
||||
+5
-5
@@ -640,12 +640,12 @@ int scoutfs_manifest_read_items(struct super_block *sb,
|
||||
struct scoutfs_key_buf seg_start;
|
||||
struct scoutfs_key_buf seg_end;
|
||||
struct scoutfs_btree_root root;
|
||||
SCOUTFS_DECLARE_KVEC(item_val);
|
||||
SCOUTFS_DECLARE_KVEC(found_val);
|
||||
struct scoutfs_segment *seg;
|
||||
struct manifest_ref *ref;
|
||||
struct manifest_ref *tmp;
|
||||
__le64 last_root_seq;
|
||||
struct kvec found_val;
|
||||
struct kvec item_val;
|
||||
LIST_HEAD(ref_list);
|
||||
LIST_HEAD(batch);
|
||||
u8 found_flags = 0;
|
||||
@@ -753,7 +753,7 @@ retry_stale:
|
||||
* that our segments can see.
|
||||
*/
|
||||
ret = scoutfs_seg_item_ptrs(ref->seg, ref->off,
|
||||
&item_key, item_val,
|
||||
&item_key, &item_val,
|
||||
&item_flags);
|
||||
if (ret < 0 ||
|
||||
scoutfs_key_compare(&item_key, &seg_end) > 0) {
|
||||
@@ -774,7 +774,7 @@ retry_stale:
|
||||
|
||||
/* remember new least key */
|
||||
scoutfs_key_clone(&found_key, &item_key);
|
||||
scoutfs_kvec_clone(found_val, item_val);
|
||||
found_val = item_val;
|
||||
found_flags = item_flags;
|
||||
ref->found_ctr = ++found_ctr;
|
||||
found = true;
|
||||
@@ -798,7 +798,7 @@ retry_stale:
|
||||
*/
|
||||
if (!(found_flags & SCOUTFS_ITEM_FLAG_DELETION)) {
|
||||
ret = scoutfs_item_add_batch(sb, &batch, &found_key,
|
||||
found_val);
|
||||
&found_val);
|
||||
if (ret) {
|
||||
if (added)
|
||||
ret = 0;
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
|
||||
#include "key.h"
|
||||
#include "format.h"
|
||||
#include "kvec.h"
|
||||
#include "lock.h"
|
||||
#include "seg.h"
|
||||
#include "super.h"
|
||||
|
||||
+9
-7
@@ -439,9 +439,10 @@ static void item_ptrs(struct scoutfs_segment *seg, int off,
|
||||
if (key)
|
||||
scoutfs_key_init(key, item_key_ptr(item),
|
||||
le16_to_cpu(item->key_len));
|
||||
if (val)
|
||||
scoutfs_kvec_init(val, item_val_ptr(item),
|
||||
le16_to_cpu(item->val_len));
|
||||
if (val) {
|
||||
val->iov_base = item_val_ptr(item);
|
||||
val->iov_len = le16_to_cpu(item->val_len);
|
||||
}
|
||||
}
|
||||
|
||||
static void first_last_keys(struct scoutfs_segment *seg,
|
||||
@@ -645,14 +646,14 @@ bool scoutfs_seg_append_item(struct super_block *sb, struct scoutfs_segment *seg
|
||||
struct scoutfs_segment_block *sblk = off_ptr(seg, 0);
|
||||
struct scoutfs_segment_item *item;
|
||||
struct scoutfs_key_buf item_key;
|
||||
SCOUTFS_DECLARE_KVEC(item_val);
|
||||
struct kvec item_val;
|
||||
u8 nr_links;
|
||||
u32 val_len;
|
||||
u32 bytes;
|
||||
u32 off;
|
||||
int i;
|
||||
|
||||
val_len = scoutfs_kvec_length(val);
|
||||
val_len = val ? val->iov_len : 0;
|
||||
|
||||
/* initialize the segment and skip links as the first item is appended */
|
||||
if (sblk->nr_items == 0) {
|
||||
@@ -701,9 +702,10 @@ 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);
|
||||
item_ptrs(seg, off, &item_key, &item_val);
|
||||
scoutfs_key_copy(&item_key, key);
|
||||
scoutfs_kvec_memcpy(item_val, val);
|
||||
if (val_len)
|
||||
memcpy(item_val.iov_base, val->iov_base, val_len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+6
-6
@@ -117,7 +117,7 @@ static int get_next_xattr(struct inode *inode, struct scoutfs_xattr_key *xak,
|
||||
struct scoutfs_xattr_key last_xak;
|
||||
struct scoutfs_key_buf last;
|
||||
struct scoutfs_key_buf key;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
struct kvec val;
|
||||
u8 last_part;
|
||||
int total;
|
||||
u8 part;
|
||||
@@ -140,8 +140,8 @@ static int get_next_xattr(struct inode *inode, struct scoutfs_xattr_key *xak,
|
||||
|
||||
for (;;) {
|
||||
xak->part = part;
|
||||
scoutfs_kvec_init(val, (void *)xat + total, bytes - total);
|
||||
ret = scoutfs_item_next(sb, &key, &last, val, lock);
|
||||
kvec_init(&val, (void *)xat + total, bytes - total);
|
||||
ret = scoutfs_item_next(sb, &key, &last, &val, lock);
|
||||
if (ret < 0) {
|
||||
/* XXX corruption, ran out of parts */
|
||||
if (ret == -ENOENT && part > 0)
|
||||
@@ -216,8 +216,8 @@ static int create_xattr_items(struct inode *inode, u64 id,
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct scoutfs_xattr_key xak;
|
||||
struct scoutfs_key_buf key;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
unsigned int part_bytes;
|
||||
struct kvec val;
|
||||
int total;
|
||||
int ret;
|
||||
|
||||
@@ -228,9 +228,9 @@ static int create_xattr_items(struct inode *inode, u64 id,
|
||||
ret = 0;
|
||||
while (total < bytes) {
|
||||
part_bytes = min(bytes - total, SCOUTFS_XATTR_MAX_PART_SIZE);
|
||||
scoutfs_kvec_init(val, (void *)xat + total, part_bytes);
|
||||
kvec_init(&val, (void *)xat + total, part_bytes);
|
||||
|
||||
ret = scoutfs_item_create(sb, &key, val, lock);
|
||||
ret = scoutfs_item_create(sb, &key, &val, lock);
|
||||
if (ret) {
|
||||
while (xak.part-- > 0)
|
||||
scoutfs_item_delete_dirty(sb, &key);
|
||||
|
||||
Reference in New Issue
Block a user