scoutfs: remove the size index

We aren't using the size index. It has runtime and code maintenance
costs that aren't worth paying.  Let's remove it.

Removing it from the format and no longer maintaining it are straight
forward.

The bulk of this patch is actually the act of removing it from the index
locking functions.  We no longer have to predict the size that will be
stored during the transaction to lock the index items that will be
created during the transaction.  A bunch of code to predict the size and
then pass it into locking and transactions goes away.  Like other inode
fields we now update the size as it changes.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2018-01-30 15:03:35 -08:00
committed by Mark Fasheh
parent 9cc750c4ec
commit a49061a7d9
10 changed files with 45 additions and 138 deletions
+1 -11
View File
@@ -1147,7 +1147,6 @@ static int scoutfs_write_begin(struct file *file,
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
struct super_block *sb = inode->i_sb;
struct write_begin_data *wbd;
u64 new_size;
u64 ind_seq;
int ret;
@@ -1166,19 +1165,10 @@ static int scoutfs_write_begin(struct file *file,
goto out;
}
/*
* Lock a size update item assuming we perform the full write.
* If If the write is inside i_size then we don't lock and
* nothing will be updated. Lock granularity is larger than
* pages so any size update in this call will be covered by the
* lock. If there's an error and we don't change i_size then
* the item update won't happen and the lock will be unused.
*/
new_size = max(pos + len, i_size_read(inode));
do {
ret = scoutfs_inode_index_start(sb, &ind_seq) ?:
scoutfs_inode_index_prepare(sb, &wbd->ind_locks, inode,
new_size, true) ?:
true) ?:
scoutfs_inode_index_try_lock_hold(sb, &wbd->ind_locks,
ind_seq,
SIC_WRITE_BEGIN());
+18 -48
View File
@@ -531,7 +531,6 @@ out:
static struct inode *lock_hold_create(struct inode *dir, struct dentry *dentry,
umode_t mode, dev_t rdev,
const struct scoutfs_item_count cnt,
u64 dir_size, u64 inode_size,
struct scoutfs_lock **dir_lock,
struct scoutfs_lock **inode_lock,
struct list_head *ind_locks)
@@ -566,9 +565,8 @@ static struct inode *lock_hold_create(struct inode *dir, struct dentry *dentry,
retry:
ret = scoutfs_inode_index_start(sb, &ind_seq) ?:
scoutfs_inode_index_prepare(sb, ind_locks, dir, dir_size, true) ?:
scoutfs_inode_index_prepare_ino(sb, ind_locks, ino, mode,
inode_size) ?:
scoutfs_inode_index_prepare(sb, ind_locks, dir, true) ?:
scoutfs_inode_index_prepare_ino(sb, ind_locks, ino, mode) ?:
scoutfs_inode_index_try_lock_hold(sb, ind_locks, ind_seq, cnt);
if (ret > 0)
goto retry;
@@ -607,16 +605,14 @@ static int scoutfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
struct scoutfs_lock *dir_lock = NULL;
struct scoutfs_lock *inode_lock = NULL;
LIST_HEAD(ind_locks);
u64 dir_size;
u64 pos;
int ret;
if (dentry->d_name.len > SCOUTFS_NAME_LEN)
return -ENAMETOOLONG;
dir_size = i_size_read(dir) + dentry->d_name.len;
inode = lock_hold_create(dir, dentry, mode, rdev,
SIC_MKNOD(dentry->d_name.len), dir_size, 0,
SIC_MKNOD(dentry->d_name.len),
&dir_lock, &inode_lock, &ind_locks);
if (IS_ERR(inode))
return PTR_ERR(inode);
@@ -631,7 +627,7 @@ static int scoutfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
update_dentry_info(dentry, pos);
i_size_write(dir, dir_size);
i_size_write(dir, i_size_read(dir) + dentry->d_name.len);
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
inode->i_mtime = inode->i_atime = inode->i_ctime = dir->i_mtime;
@@ -704,10 +700,8 @@ static int scoutfs_link(struct dentry *old_dentry,
dir_size = i_size_read(dir) + dentry->d_name.len;
retry:
ret = scoutfs_inode_index_start(sb, &ind_seq) ?:
scoutfs_inode_index_prepare(sb, &ind_locks, dir,
dir_size, false) ?:
scoutfs_inode_index_prepare(sb, &ind_locks, inode,
i_size_read(inode), false) ?:
scoutfs_inode_index_prepare(sb, &ind_locks, dir, false) ?:
scoutfs_inode_index_prepare(sb, &ind_locks, inode, false) ?:
scoutfs_inode_index_try_lock_hold(sb, &ind_locks, ind_seq,
SIC_LINK(dentry->d_name.len));
if (ret > 0)
@@ -770,7 +764,6 @@ static int scoutfs_unlink(struct inode *dir, struct dentry *dentry)
struct scoutfs_lock *inode_lock = NULL;
struct scoutfs_lock *dir_lock = NULL;
LIST_HEAD(ind_locks);
u64 dir_size;
u64 ind_seq;
int ret = 0;
@@ -785,13 +778,10 @@ static int scoutfs_unlink(struct inode *dir, struct dentry *dentry)
goto unlock;
}
dir_size = i_size_read(dir) - dentry->d_name.len;
retry:
ret = scoutfs_inode_index_start(sb, &ind_seq) ?:
scoutfs_inode_index_prepare(sb, &ind_locks, dir,
dir_size, false) ?:
scoutfs_inode_index_prepare(sb, &ind_locks, inode,
i_size_read(inode), false) ?:
scoutfs_inode_index_prepare(sb, &ind_locks, dir, false) ?:
scoutfs_inode_index_prepare(sb, &ind_locks, inode, false) ?:
scoutfs_inode_index_try_lock_hold(sb, &ind_locks, ind_seq,
SIC_UNLINK(dentry->d_name.len));
if (ret > 0)
@@ -819,7 +809,7 @@ retry:
dir->i_ctime = ts;
dir->i_mtime = ts;
i_size_write(dir, dir_size);
i_size_write(dir, i_size_read(dir) - dentry->d_name.len);
inode->i_ctime = ts;
drop_nlink(inode);
@@ -1000,7 +990,6 @@ static int scoutfs_symlink(struct inode *dir, struct dentry *dentry,
struct scoutfs_lock *dir_lock = NULL;
struct scoutfs_lock *inode_lock = NULL;
LIST_HEAD(ind_locks);
u64 dir_size;
u64 pos;
int ret;
@@ -1013,10 +1002,8 @@ static int scoutfs_symlink(struct inode *dir, struct dentry *dentry,
if (ret)
return ret;
dir_size = i_size_read(dir) + dentry->d_name.len;
inode = lock_hold_create(dir, dentry, S_IFLNK|S_IRWXUGO, 0,
SIC_SYMLINK(dentry->d_name.len, name_len),
dir_size, name_len,
&dir_lock, &inode_lock, &ind_locks);
if (IS_ERR(inode))
return PTR_ERR(inode);
@@ -1036,7 +1023,7 @@ static int scoutfs_symlink(struct inode *dir, struct dentry *dentry,
update_dentry_info(dentry, pos);
i_size_write(dir, dir_size);
i_size_write(dir, i_size_read(dir) + dentry->d_name.len);
dir->i_mtime = dir->i_ctime = CURRENT_TIME;
inode->i_ctime = dir->i_mtime;
@@ -1397,8 +1384,6 @@ static int scoutfs_rename(struct inode *old_dir, struct dentry *old_dentry,
bool del_new = false;
bool ins_old = false;
LIST_HEAD(ind_locks);
u64 old_size;
u64 uninitialized_var(new_size);
u64 ind_seq;
u64 new_pos;
int ret;
@@ -1451,30 +1436,14 @@ static int scoutfs_rename(struct inode *old_dir, struct dentry *old_dentry,
if (ret)
goto out_unlock;
old_size = i_size_read(old_dir) - old_dentry->d_name.len;
if (!new_inode) {
if (old_dir != new_dir)
new_size = i_size_read(new_dir) +
new_dentry->d_name.len;
else
old_size += new_dentry->d_name.len;
} else {
if (old_dir != new_dir)
new_size = i_size_read(new_dir);
}
retry:
ret = scoutfs_inode_index_start(sb, &ind_seq) ?:
scoutfs_inode_index_prepare(sb, &ind_locks, old_dir,
old_size, false) ?:
scoutfs_inode_index_prepare(sb, &ind_locks, old_inode,
i_size_read(old_inode), false) ?:
scoutfs_inode_index_prepare(sb, &ind_locks, old_dir, false) ?:
scoutfs_inode_index_prepare(sb, &ind_locks, old_inode, false) ?:
(new_dir == old_dir ? 0 :
scoutfs_inode_index_prepare(sb, &ind_locks, new_dir,
new_size, false)) ?:
scoutfs_inode_index_prepare(sb, &ind_locks, new_dir, false)) ?:
(new_inode == NULL ? 0 :
scoutfs_inode_index_prepare(sb, &ind_locks, new_inode,
i_size_read(new_inode), false)) ?:
scoutfs_inode_index_prepare(sb, &ind_locks, new_inode, false)) ?:
scoutfs_inode_index_try_lock_hold(sb, &ind_locks, ind_seq,
SIC_RENAME(old_dentry->d_name.len,
new_dentry->d_name.len));
@@ -1540,9 +1509,10 @@ retry:
/* the caller will use d_move to move the old_dentry into place */
update_dentry_info(old_dentry, new_pos);
i_size_write(old_dir, old_size);
if (old_dir != new_dir)
i_size_write(new_dir, new_size);
i_size_write(old_dir, i_size_read(old_dir) - old_dentry->d_name.len);
if (!new_inode)
i_size_write(new_dir, i_size_read(new_dir) +
new_dentry->d_name.len);
if (new_inode) {
drop_nlink(new_inode);
+3 -4
View File
@@ -237,10 +237,9 @@ struct scoutfs_segment_block {
#define SCOUTFS_MAX_ZONE 4 /* power of 2 is efficient */
/* inode index zone */
#define SCOUTFS_INODE_INDEX_SIZE_TYPE 1
#define SCOUTFS_INODE_INDEX_META_SEQ_TYPE 2
#define SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE 3
#define SCOUTFS_INODE_INDEX_NR 4 /* don't forget to update */
#define SCOUTFS_INODE_INDEX_META_SEQ_TYPE 1
#define SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE 2
#define SCOUTFS_INODE_INDEX_NR 3 /* don't forget to update */
/* node zone */
#define SCOUTFS_FREE_BITS_SEGNO_TYPE 1
+13 -26
View File
@@ -214,8 +214,6 @@ static void set_item_info(struct scoutfs_inode_info *si,
memset(si->item_minors, 0, sizeof(si->item_minors));
si->have_item = true;
si->item_majors[SCOUTFS_INODE_INDEX_SIZE_TYPE] =
le64_to_cpu(sinode->size);
si->item_majors[SCOUTFS_INODE_INDEX_META_SEQ_TYPE] =
le64_to_cpu(sinode->meta_seq);
si->item_majors[SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE] =
@@ -340,7 +338,7 @@ static int set_inode_size(struct inode *inode, struct scoutfs_lock *lock,
if (!S_ISREG(inode->i_mode))
return 0;
ret = scoutfs_inode_index_lock_hold(inode, &ind_locks, new_size, true,
ret = scoutfs_inode_index_lock_hold(inode, &ind_locks, true,
SIC_DIRTY_INODE());
if (ret)
return ret;
@@ -365,8 +363,7 @@ static int clear_truncate_flag(struct inode *inode, struct scoutfs_lock *lock)
LIST_HEAD(ind_locks);
int ret;
ret = scoutfs_inode_index_lock_hold(inode, &ind_locks,
i_size_read(inode), false,
ret = scoutfs_inode_index_lock_hold(inode, &ind_locks, false,
SIC_DIRTY_INODE());
if (ret)
return ret;
@@ -445,8 +442,7 @@ int scoutfs_setattr(struct dentry *dentry, struct iattr *attr)
}
}
ret = scoutfs_inode_index_lock_hold(inode, &ind_locks,
i_size_read(inode), false,
ret = scoutfs_inode_index_lock_hold(inode, &ind_locks, false,
SIC_DIRTY_INODE());
if (ret)
goto out;
@@ -691,7 +687,6 @@ static bool will_ins_index(struct scoutfs_inode_info *si,
static bool inode_has_index(umode_t mode, u8 type)
{
switch(type) {
case SCOUTFS_INODE_INDEX_SIZE_TYPE:
case SCOUTFS_INODE_INDEX_META_SEQ_TYPE:
return true;
case SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE:
@@ -821,8 +816,6 @@ static int update_indices(struct super_block *sb,
u64 major;
u32 minor;
} *upd, upds[] = {
{ SCOUTFS_INODE_INDEX_SIZE_TYPE,
le64_to_cpu(sinode->size), 0 },
{ SCOUTFS_INODE_INDEX_META_SEQ_TYPE,
le64_to_cpu(sinode->meta_seq), 0 },
{ SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE,
@@ -900,8 +893,8 @@ void scoutfs_update_inode_item(struct inode *inode, struct scoutfs_lock *lock,
* We map the item to coarse locks here. This reduces the number of
* locks we track and means that when we later try to find the lock that
* covers an item we can deal with the item update changing a little
* (seq, size) while still being covered. It does mean we have to share
* some logic with lock naming.
* while still being covered. It does mean we have to share some logic
* with lock naming.
*/
static int add_index_lock(struct list_head *list, u64 ino, u8 type, u64 major,
u32 minor)
@@ -979,7 +972,7 @@ static u64 upd_data_seq(struct scoutfs_sb_info *sbi,
*/
static int prepare_indices(struct super_block *sb, struct list_head *list,
struct scoutfs_inode_info *si, u64 ino,
umode_t mode, u64 new_size, bool set_data_seq)
umode_t mode, bool set_data_seq)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct index_update {
@@ -987,7 +980,6 @@ static int prepare_indices(struct super_block *sb, struct list_head *list,
u64 major;
u32 minor;
} *upd, upds[] = {
{ SCOUTFS_INODE_INDEX_SIZE_TYPE, new_size, 0},
{ SCOUTFS_INODE_INDEX_META_SEQ_TYPE, sbi->trans_seq, 0},
{ SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE,
upd_data_seq(sbi, si, set_data_seq), 0},
@@ -1009,13 +1001,12 @@ static int prepare_indices(struct super_block *sb, struct list_head *list,
}
int scoutfs_inode_index_prepare(struct super_block *sb, struct list_head *list,
struct inode *inode, u64 new_size,
bool set_data_seq)
struct inode *inode, bool set_data_seq)
{
struct scoutfs_inode_info *si = SCOUTFS_I(inode);
return prepare_indices(sb, list, si, scoutfs_ino(inode),
inode->i_mode, new_size, set_data_seq);
inode->i_mode, set_data_seq);
}
/*
@@ -1026,9 +1017,9 @@ int scoutfs_inode_index_prepare(struct super_block *sb, struct list_head *list,
*/
int scoutfs_inode_index_prepare_ino(struct super_block *sb,
struct list_head *list, u64 ino,
umode_t mode, u64 new_size)
umode_t mode)
{
return prepare_indices(sb, list, NULL, ino, mode, new_size, true);
return prepare_indices(sb, list, NULL, ino, mode, true);
}
/*
@@ -1045,8 +1036,6 @@ static int prepare_index_deletion(struct super_block *sb,
u64 major;
u32 minor;
} *ind, inds[] = {
{ SCOUTFS_INODE_INDEX_SIZE_TYPE,
le64_to_cpu(sinode->size), 0 },
{ SCOUTFS_INODE_INDEX_META_SEQ_TYPE,
le64_to_cpu(sinode->meta_seq), 0 },
{ SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE,
@@ -1120,7 +1109,7 @@ out:
}
int scoutfs_inode_index_lock_hold(struct inode *inode, struct list_head *list,
u64 size, bool set_data_seq,
bool set_data_seq,
const struct scoutfs_item_count cnt)
{
struct super_block *sb = inode->i_sb;
@@ -1129,7 +1118,7 @@ int scoutfs_inode_index_lock_hold(struct inode *inode, struct list_head *list,
do {
ret = scoutfs_inode_index_start(sb, &seq) ?:
scoutfs_inode_index_prepare(sb, list, inode, size,
scoutfs_inode_index_prepare(sb, list, inode,
set_data_seq) ?:
scoutfs_inode_index_try_lock_hold(sb, list, seq, cnt);
} while (ret > 0);
@@ -1191,9 +1180,7 @@ static int remove_index_items(struct super_block *sb, u64 ino,
umode_t mode = le32_to_cpu(sinode->mode);
int ret;
ret = remove_index(sb, ino, SCOUTFS_INODE_INDEX_SIZE_TYPE,
le64_to_cpu(sinode->size), 0, ind_locks) ?:
remove_index(sb, ino, SCOUTFS_INODE_INDEX_META_SEQ_TYPE,
ret = remove_index(sb, ino, SCOUTFS_INODE_INDEX_META_SEQ_TYPE,
le64_to_cpu(sinode->meta_seq), 0, ind_locks);
if (ret == 0 && S_ISREG(mode))
ret = remove_index(sb, ino, SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE,
+3 -4
View File
@@ -64,16 +64,15 @@ struct inode *scoutfs_ilookup(struct super_block *sb, 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, u64 new_size,
bool set_data_seq);
struct inode *inode, bool set_data_seq);
int scoutfs_inode_index_prepare_ino(struct super_block *sb,
struct list_head *list, u64 ino,
umode_t mode, u64 new_size);
umode_t mode);
int scoutfs_inode_index_try_lock_hold(struct super_block *sb,
struct list_head *list, u64 seq,
const struct scoutfs_item_count cnt);
int scoutfs_inode_index_lock_hold(struct inode *inode, struct list_head *list,
u64 size, bool set_data_seq,
bool set_data_seq,
const struct scoutfs_item_count cnt);
void scoutfs_inode_index_unlock(struct super_block *sb, struct list_head *list);
+1 -3
View File
@@ -71,9 +71,7 @@ static long scoutfs_ioc_walk_inodes(struct file *file, unsigned long arg)
trace_scoutfs_ioc_walk_inodes(sb, &walk);
if (walk.index == SCOUTFS_IOC_WALK_INODES_SIZE)
type = SCOUTFS_INODE_INDEX_SIZE_TYPE;
else if (walk.index == SCOUTFS_IOC_WALK_INODES_META_SEQ)
if (walk.index == SCOUTFS_IOC_WALK_INODES_META_SEQ)
type = SCOUTFS_INODE_INDEX_META_SEQ_TYPE;
else if (walk.index == SCOUTFS_IOC_WALK_INODES_DATA_SEQ)
type = SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE;
+1 -2
View File
@@ -51,8 +51,7 @@ struct scoutfs_ioctl_walk_inodes {
} __packed;
enum {
SCOUTFS_IOC_WALK_INODES_SIZE = 0,
SCOUTFS_IOC_WALK_INODES_META_SEQ,
SCOUTFS_IOC_WALK_INODES_META_SEQ = 0,
SCOUTFS_IOC_WALK_INODES_DATA_SEQ,
SCOUTFS_IOC_WALK_INODES_UNKNOWN,
};
-3
View File
@@ -211,7 +211,6 @@ typedef int (*key_printer_t)(char *buf, struct scoutfs_key_buf *key,
static int pr_ino_idx(char *buf, struct scoutfs_key_buf *key, size_t size)
{
static char *type_strings[] = {
[SCOUTFS_INODE_INDEX_SIZE_TYPE] = "siz",
[SCOUTFS_INODE_INDEX_META_SEQ_TYPE] = "msq",
[SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE] = "dsq",
};
@@ -329,8 +328,6 @@ static int pr_block_mapping(char *buf, struct scoutfs_key_buf *key, size_t size)
}
const static key_printer_t key_printers[SCOUTFS_MAX_ZONE][SCOUTFS_MAX_TYPE] = {
[SCOUTFS_INODE_INDEX_ZONE][SCOUTFS_INODE_INDEX_SIZE_TYPE] =
pr_ino_idx,
[SCOUTFS_INODE_INDEX_ZONE][SCOUTFS_INODE_INDEX_META_SEQ_TYPE] =
pr_ino_idx,
[SCOUTFS_INODE_INDEX_ZONE][SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE] =
+4 -35
View File
@@ -947,16 +947,6 @@ int scoutfs_lock_global(struct super_block *sb, int mode, int flags, int type,
* The seq indexes have natural batching and limits on the number of
* keys per major value.
*
* The file size index is very different. We don't control the
* distribution of sizes amongst inodes. We map ranges of sizes to a
* small set of locks by rounding the size down to groups of sizes
* identified by their highest set bit and two next significant bits.
* This results in ranges that increase by quarters of powers of two.
* (small sizes don't have enough bits for this scheme, they're all
* mapped to a range from 0 to 15.) two (0 and 1 are mapped to 0). Each
* lock then covers all the sizes in their range and all the inodes with
* those sizes.
*
* This can also be used to find items that are covered by the same lock
* because their starting keys are the same.
*/
@@ -964,32 +954,11 @@ 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)
{
u64 start_major;
u64 end_major;
int bit;
u64 start_major = major & ~SCOUTFS_LOCK_SEQ_GROUP_MASK;
u64 end_major = major | SCOUTFS_LOCK_SEQ_GROUP_MASK;
switch(type) {
case SCOUTFS_INODE_INDEX_SIZE_TYPE:
bit = major ? fls64(major) : 0;
if (bit < 5) {
/* sizes [ 0 .. 15 ] are in their own lock */
start_major = 0;
end_major = 15;
} else {
/* last bit, 2 lesser bits, mask */
start_major = major & (7ULL << (bit - 3));
end_major = start_major + (1ULL << (bit - 3)) - 1;
}
break;
case SCOUTFS_INODE_INDEX_META_SEQ_TYPE:
case SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE:
start_major = major & ~SCOUTFS_LOCK_SEQ_GROUP_MASK;
end_major = major | SCOUTFS_LOCK_SEQ_GROUP_MASK;
break;
default:
BUG();
}
BUG_ON(type != SCOUTFS_INODE_INDEX_META_SEQ_TYPE &&
type != SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE);
if (start) {
start->zone = SCOUTFS_INODE_INDEX_ZONE;
+1 -2
View File
@@ -321,8 +321,7 @@ static int scoutfs_xattr_set(struct dentry *dentry, const char *name,
retry:
ret = scoutfs_inode_index_start(sb, &ind_seq) ?:
scoutfs_inode_index_prepare(sb, &ind_locks, inode,
i_size_read(inode), false) ?:
scoutfs_inode_index_prepare(sb, &ind_locks, inode, false) ?:
scoutfs_inode_index_try_lock_hold(sb, &ind_locks, ind_seq,
SIC_XATTR_SET(name_len, size));
if (ret > 0)