summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2018-06-27 13:36:20 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2018-06-27 13:38:43 -0400
commit080201178e609fa8ef827439801f728fba85188e (patch)
treead83b809cae74c4a1fe0e0d9d4916f647e7911a7
parentd6fb71272ec66b8c934c9d337cff4d21317067c3 (diff)
bcachefs: BCH_NAME_MAX
also fix some dirent bugs
-rw-r--r--fs/bcachefs/bcachefs_format.h5
-rw-r--r--fs/bcachefs/btree_io.c4
-rw-r--r--fs/bcachefs/dirent.c32
-rw-r--r--fs/bcachefs/fs.c2
-rw-r--r--fs/bcachefs/xattr.c2
5 files changed, 31 insertions, 14 deletions
diff --git a/fs/bcachefs/bcachefs_format.h b/fs/bcachefs/bcachefs_format.h
index 8e74de4f8c32..b6e7b983bc5b 100644
--- a/fs/bcachefs/bcachefs_format.h
+++ b/fs/bcachefs/bcachefs_format.h
@@ -793,6 +793,11 @@ struct bch_dirent {
} __attribute__((packed, aligned(8)));
BKEY_VAL_TYPE(dirent, BCH_DIRENT);
+#define BCH_NAME_MAX (U8_MAX * sizeof(u64) - \
+ sizeof(struct bkey) - \
+ offsetof(struct bch_dirent, d_name))
+
+
/* Xattrs */
enum {
diff --git a/fs/bcachefs/btree_io.c b/fs/bcachefs/btree_io.c
index 74ffad4c38f3..0c825bcbc45c 100644
--- a/fs/bcachefs/btree_io.c
+++ b/fs/bcachefs/btree_io.c
@@ -920,7 +920,7 @@ static int btree_err_msg(struct bch_fs *c, struct btree *b, struct bset *i,
char *out = buf, *end = buf + len;
out += scnprintf(out, end - out,
- "error validating btree node %s "
+ "error validating btree node %s"
"at btree %u level %u/%u\n"
"pos %llu:%llu node offset %u",
write ? "before write " : "",
@@ -1120,7 +1120,7 @@ static int validate_bset(struct bch_fs *c, struct btree *b,
bch2_bkey_val_to_text(c, type, buf, sizeof(buf), u);
btree_err(BTREE_ERR_FIXABLE, c, b, i,
- "invalid bkey:\n%s\n%s", buf, invalid);
+ "invalid bkey:\n%s\n%s", invalid, buf);
i->u64s = cpu_to_le16(le16_to_cpu(i->u64s) - k->u64s);
memmove_u64s_down(k, bkey_next(k),
diff --git a/fs/bcachefs/dirent.c b/fs/bcachefs/dirent.c
index df9913f8967b..36dca6b22a91 100644
--- a/fs/bcachefs/dirent.c
+++ b/fs/bcachefs/dirent.c
@@ -12,7 +12,8 @@
unsigned bch2_dirent_name_bytes(struct bkey_s_c_dirent d)
{
- unsigned len = bkey_val_bytes(d.k) - sizeof(struct bch_dirent);
+ unsigned len = bkey_val_bytes(d.k) -
+ offsetof(struct bch_dirent, d_name);
while (len && !d.v->d_name[len - 1])
--len;
@@ -22,7 +23,8 @@ unsigned bch2_dirent_name_bytes(struct bkey_s_c_dirent d)
static unsigned dirent_val_u64s(unsigned len)
{
- return DIV_ROUND_UP(sizeof(struct bch_dirent) + len, sizeof(u64));
+ return DIV_ROUND_UP(offsetof(struct bch_dirent, d_name) + len,
+ sizeof(u64));
}
static u64 bch2_dirent_hash(const struct bch_hash_info *info,
@@ -98,7 +100,7 @@ const char *bch2_dirent_invalid(const struct bch_fs *c, struct bkey_s_c k)
if (bkey_val_u64s(k.k) > dirent_val_u64s(len))
return "value too big";
- if (len > NAME_MAX)
+ if (len > BCH_NAME_MAX)
return "dirent name too big";
if (memchr(d.v->d_name, '/', len))
@@ -141,9 +143,14 @@ static struct bkey_i_dirent *dirent_create_key(u8 type,
struct bkey_i_dirent *dirent;
unsigned u64s = BKEY_U64s + dirent_val_u64s(name->len);
+ if (name->len > BCH_NAME_MAX)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ BUG_ON(u64s > U8_MAX);
+
dirent = kmalloc(u64s * sizeof(u64), GFP_NOFS);
if (!dirent)
- return NULL;
+ return ERR_PTR(-ENOMEM);
bkey_dirent_init(&dirent->k_i);
dirent->k.u64s = u64s;
@@ -153,7 +160,8 @@ static struct bkey_i_dirent *dirent_create_key(u8 type,
memcpy(dirent->v.d_name, name->name, name->len);
memset(dirent->v.d_name + name->len, 0,
bkey_val_bytes(&dirent->k) -
- (sizeof(struct bch_dirent) + name->len));
+ offsetof(struct bch_dirent, d_name) -
+ name->len);
EBUG_ON(bch2_dirent_name_bytes(dirent_i_to_s_c(dirent)) != name->len);
@@ -169,8 +177,8 @@ int bch2_dirent_create(struct bch_fs *c, u64 dir_inum,
int ret;
dirent = dirent_create_key(type, name, dst_inum);
- if (!dirent)
- return -ENOMEM;
+ if (IS_ERR(dirent))
+ return PTR_ERR(dirent);
ret = bch2_hash_set(bch2_dirent_hash_desc, hash_info, c, dir_inum,
journal_seq, &dirent->k_i, flags);
@@ -204,7 +212,7 @@ int bch2_dirent_rename(struct bch_fs *c,
struct bpos src_pos = bch2_dirent_pos(src_dir, src_name);
struct bpos dst_pos = bch2_dirent_pos(dst_dir, dst_name);
bool need_whiteout;
- int ret = -ENOMEM;
+ int ret;
bch2_btree_iter_init(&src_iter, c, BTREE_ID_DIRENTS, src_pos,
BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
@@ -218,15 +226,19 @@ int bch2_dirent_rename(struct bch_fs *c,
if (mode == BCH_RENAME_EXCHANGE) {
new_src = dirent_create_key(0, src_name, 0);
- if (!new_src)
+ if (IS_ERR(new_src)) {
+ ret = PTR_ERR(new_src);
goto err;
+ }
} else {
new_src = (void *) &delete;
}
new_dst = dirent_create_key(0, dst_name, 0);
- if (!new_dst)
+ if (IS_ERR(new_dst)) {
+ ret = PTR_ERR(new_dst);
goto err;
+ }
retry:
/*
* Note that on -EINTR/dropped locks we're not restarting the lookup
diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
index 19f3ba007e64..3b7f78e731b8 100644
--- a/fs/bcachefs/fs.c
+++ b/fs/bcachefs/fs.c
@@ -1119,7 +1119,7 @@ static int bch2_statfs(struct dentry *dentry, struct kstatfs *buf)
le64_to_cpup((void *) c->sb.user_uuid.b + sizeof(u64));
buf->f_fsid.val[0] = fsid & 0xFFFFFFFFUL;
buf->f_fsid.val[1] = (fsid >> 32) & 0xFFFFFFFFUL;
- buf->f_namelen = NAME_MAX;
+ buf->f_namelen = BCH_NAME_MAX;
return 0;
}
diff --git a/fs/bcachefs/xattr.c b/fs/bcachefs/xattr.c
index c89c7200a1b4..de95480c8b08 100644
--- a/fs/bcachefs/xattr.c
+++ b/fs/bcachefs/xattr.c
@@ -15,7 +15,7 @@
static unsigned xattr_val_u64s(unsigned name_len, unsigned val_len)
{
- return DIV_ROUND_UP(sizeof(struct bch_xattr) +
+ return DIV_ROUND_UP(offsetof(struct bch_xattr, x_name) +
name_len + val_len, sizeof(u64));
}