diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2018-06-27 13:36:20 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2018-06-27 13:38:43 -0400 |
commit | 080201178e609fa8ef827439801f728fba85188e (patch) | |
tree | ad83b809cae74c4a1fe0e0d9d4916f647e7911a7 | |
parent | d6fb71272ec66b8c934c9d337cff4d21317067c3 (diff) |
bcachefs: BCH_NAME_MAX
also fix some dirent bugs
-rw-r--r-- | fs/bcachefs/bcachefs_format.h | 5 | ||||
-rw-r--r-- | fs/bcachefs/btree_io.c | 4 | ||||
-rw-r--r-- | fs/bcachefs/dirent.c | 32 | ||||
-rw-r--r-- | fs/bcachefs/fs.c | 2 | ||||
-rw-r--r-- | fs/bcachefs/xattr.c | 2 |
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)); } |