scoutfs: add value length limit

Add a relatively small universal value size limit.  This will be needed
by more dense item packing to predict the worst case padding to avoid
full items crossing block boundaries.

We refactor the existing symlink and xattr item value limit to use this
new limit.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2017-06-21 13:56:53 -07:00
parent 1724bab8ea
commit 463a696575
4 changed files with 38 additions and 15 deletions

View File

@@ -54,7 +54,7 @@ static inline void scoutfs_count_dirents(struct scoutfs_item_count *cnt,
static inline void scoutfs_count_sym_target(struct scoutfs_item_count *cnt,
unsigned size)
{
unsigned nr = DIV_ROUND_UP(size, SCOUTFS_SYMLINK_MAX_VAL_SIZE);
unsigned nr = DIV_ROUND_UP(size, SCOUTFS_MAX_VAL_SIZE);
cnt->items += nr;
cnt->keys += nr * sizeof(struct scoutfs_symlink_key);

View File

@@ -661,7 +661,7 @@ enum {
SYM_DELETE,
};
static int symlink_item_ops(struct super_block *sb, int op, u64 ino,
const char *target, int size)
const char *target, size_t size)
{
struct scoutfs_symlink_key skey;
struct scoutfs_key_buf key;
@@ -671,15 +671,15 @@ static int symlink_item_ops(struct super_block *sb, int op, u64 ino,
int ret;
int i;
if (WARN_ON_ONCE(size <= 0 || size > SCOUTFS_SYMLINK_MAX_SIZE ||
if (WARN_ON_ONCE(size == 0 || size > SCOUTFS_SYMLINK_MAX_SIZE ||
op > SYM_DELETE))
return -EINVAL;
nr = DIV_ROUND_UP(size, SCOUTFS_SYMLINK_MAX_VAL_SIZE);
nr = DIV_ROUND_UP(size, SCOUTFS_MAX_VAL_SIZE);
for (i = 0; i < nr; i++) {
init_symlink_key(&key, &skey, ino, i);
bytes = min(size, SCOUTFS_SYMLINK_MAX_VAL_SIZE);
bytes = min(size, SCOUTFS_MAX_VAL_SIZE);
scoutfs_kvec_init(val, (void *)target, bytes);
if (op == SYM_CREATE)
@@ -691,7 +691,7 @@ static int symlink_item_ops(struct super_block *sb, int op, u64 ino,
if (ret)
break;
target += SCOUTFS_SYMLINK_MAX_VAL_SIZE;
target += SCOUTFS_MAX_VAL_SIZE;
size -= bytes;
}

View File

@@ -260,8 +260,6 @@ struct scoutfs_symlink_key {
__u8 nr;
} __packed;
#define SCOUTFS_SYMLINK_MAX_VAL_SIZE 200
struct scoutfs_betimespec {
__be64 sec;
__be32 nsec;
@@ -377,13 +375,6 @@ struct scoutfs_dirent {
/* S32_MAX avoids the (int) sign bit and might avoid sloppy bugs */
#define SCOUTFS_LINK_MAX S32_MAX
#define SCOUTFS_XATTR_MAX_NAME_LEN 255
#define SCOUTFS_XATTR_MAX_SIZE 65536
#define SCOUTFS_XATTR_PART_SIZE \
(SCOUTFS_BLOCK_SIZE - sizeof(struct scoutfs_xattr_val_header))
#define SCOUTFS_XATTR_MAX_PARTS \
DIV_ROUND_UP(SCOUTFS_XATTR_MAX_SIZE, SCOUTFS_XATTR_PART_SIZE)
/* entries begin after . and .. */
#define SCOUTFS_DIRENT_FIRST_POS 2
/* getdents returns next pos with an entry, no entry at (f_pos)~0 */
@@ -404,6 +395,18 @@ enum {
#define SCOUTFS_MAX_KEY_SIZE \
offsetof(struct scoutfs_link_backref_key, name[SCOUTFS_NAME_LEN + 1])
/* largest single val are dirents, larger broken up into units of this */
#define SCOUTFS_MAX_VAL_SIZE \
offsetof(struct scoutfs_dirent, name[SCOUTFS_NAME_LEN])
#define SCOUTFS_XATTR_MAX_NAME_LEN 255
#define SCOUTFS_XATTR_MAX_SIZE 65536
#define SCOUTFS_XATTR_PART_SIZE \
(SCOUTFS_MAX_VAL_SIZE - sizeof(struct scoutfs_xattr_val_header))
#define SCOUTFS_XATTR_MAX_PARTS \
DIV_ROUND_UP(SCOUTFS_XATTR_MAX_SIZE, SCOUTFS_XATTR_PART_SIZE)
/*
* messages over the wire.
*/

View File

@@ -41,6 +41,12 @@
* clobber them in creation and skip them in lookups.
*/
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)));
}
static bool invalid_flags(int sif)
{
return (sif & SIF_EXCLUSIVE) && (sif & SIF_REPLACE);
@@ -992,6 +998,9 @@ int scoutfs_item_create(struct super_block *sb, struct scoutfs_key_buf *key,
unsigned long flags;
int ret;
if (invalid_key_val(key, val))
return -EINVAL;
item = alloc_item(sb, key, val);
if (!item)
return -ENOMEM;
@@ -1021,6 +1030,9 @@ int scoutfs_item_add_batch(struct super_block *sb, struct list_head *list,
struct cached_item *item;
int ret;
if (invalid_key_val(key, val))
return -EINVAL;
item = alloc_item(sb, key, val);
if (item) {
list_add_tail(&item->entry, list);
@@ -1128,6 +1140,11 @@ int scoutfs_item_set_batch(struct super_block *sb, struct list_head *list,
if (WARN_ON_ONCE(invalid_flags(sif)))
return -EINVAL;
list_for_each_entry(item, list, entry) {
if (invalid_key_val(item->key, item->val))
return -EINVAL;
}
trace_scoutfs_item_set_batch(sb, start, end);
if (WARN_ON_ONCE(scoutfs_key_compare(start, end) > 0))
@@ -1283,6 +1300,9 @@ int scoutfs_item_update(struct super_block *sb, struct scoutfs_key_buf *key,
unsigned long flags;
int ret;
if (invalid_key_val(key, val))
return -EINVAL;
end = scoutfs_key_alloc(sb, SCOUTFS_MAX_KEY_SIZE);
if (!end) {
ret = -ENOMEM;