#include <fcntl.h>
#include <getopt.h>
#include <string.h>
+#include <sys/xattr.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <sys/vfs.h>
#include <unistd.h>
-#include <attr/xattr.h>
#include <linux/fiemap.h>
#include <linux/fs.h>
#include <linux/generic-radix-tree.h>
#include <linux/xattr.h>
#include "libbcachefs/bcachefs.h"
+#include "libbcachefs/alloc_background.h"
+#include "libbcachefs/alloc_foreground.h"
#include "libbcachefs/btree_update.h"
#include "libbcachefs/buckets.h"
#include "libbcachefs/dirent.h"
-#include "libbcachefs/fs.h"
+#include "libbcachefs/fs-common.h"
#include "libbcachefs/inode.h"
#include "libbcachefs/io.h"
+#include "libbcachefs/replicas.h"
#include "libbcachefs/str_hash.h"
#include "libbcachefs/super.h"
#include "libbcachefs/xattr.h"
+/* XXX cut and pasted from fsck.c */
+#define QSTR(n) { { { .len = strlen(n) } }, .name = n }
+
static char *dev_t_to_path(dev_t dev)
{
char link[PATH_MAX], *p;
struct range i;
for_each_hole(iter, extents, bucket_to_sector(ca, ca->mi.nbuckets) << 9, i) {
- struct bucket_mark new;
u64 b;
if (i.start == i.end)
b = sector_to_bucket(ca, i.start >> 9);
do {
- struct bucket *g = bucket(ca, b);
- bucket_cmpxchg(g, new, new.nouse = 1);
+ set_bit(b, ca->buckets_nouse);
b++;
} while (bucket_to_sector(ca, b) << 9 < i.end);
}
struct bkey_inode_buf packed;
int ret;
- bch2_inode_pack(&packed, inode);
- ret = bch2_btree_insert(c, BTREE_ID_INODES, &packed.inode.k_i,
- NULL, NULL, NULL, 0);
- if (ret)
- die("error creating file: %s", strerror(-ret));
-}
-
-static void create_dirent(struct bch_fs *c,
- struct bch_inode_unpacked *parent,
- const char *name, u64 inum, mode_t mode)
-{
- struct bch_hash_info parent_hash_info = bch2_hash_info_init(c, parent);
- struct qstr qname = { { { .len = strlen(name), } }, .name = name };
-
- int ret = bch2_dirent_create(c, parent->bi_inum, &parent_hash_info,
- mode_to_type(mode), &qname,
- inum, NULL, BCH_HASH_SET_MUST_CREATE);
+ bch2_inode_pack(c, &packed, inode);
+ ret = bch2_btree_insert(c, BTREE_ID_inodes, &packed.inode.k_i,
+ NULL, NULL, 0);
if (ret)
- die("error creating file: %s", strerror(-ret));
-
- if (S_ISDIR(mode))
- parent->bi_nlink++;
+ die("error updating inode: %s", strerror(-ret));
}
static void create_link(struct bch_fs *c,
struct bch_inode_unpacked *parent,
const char *name, u64 inum, mode_t mode)
{
+ struct qstr qstr = QSTR(name);
+ struct bch_inode_unpacked parent_u;
struct bch_inode_unpacked inode;
- int ret = bch2_inode_find_by_inum(c, inum, &inode);
- if (ret)
- die("error looking up hardlink: %s", strerror(-ret));
- inode.bi_nlink++;
- update_inode(c, &inode);
-
- create_dirent(c, parent, name, inum, mode);
+ int ret = bch2_trans_do(c, NULL, NULL, 0,
+ bch2_link_trans(&trans, parent->bi_inum, inum,
+ &parent_u, &inode, &qstr));
+ if (ret)
+ die("error creating hardlink: %s", strerror(-ret));
}
static struct bch_inode_unpacked create_file(struct bch_fs *c,
uid_t uid, gid_t gid,
mode_t mode, dev_t rdev)
{
+ struct qstr qstr = QSTR(name);
struct bch_inode_unpacked new_inode;
- int ret;
- bch2_inode_init(c, &new_inode, uid, gid, mode, rdev, parent);
-
- ret = bch2_inode_create(c, &new_inode, BLOCKDEV_INODE_MAX, 0,
- &c->unused_inode_hint);
+ int ret = bch2_trans_do(c, NULL, NULL, 0,
+ bch2_create_trans(&trans,
+ parent->bi_inum, parent,
+ &new_inode, &qstr,
+ uid, gid, mode, rdev, NULL, NULL));
if (ret)
die("error creating file: %s", strerror(-ret));
- create_dirent(c, parent, name, new_inode.bi_inum, mode);
-
return new_inode;
}
(handler) != NULL; \
(handler) = *(handlers)++)
-static const struct xattr_handler *xattr_resolve_name(const char **name)
+static const struct xattr_handler *xattr_resolve_name(char **name)
{
const struct xattr_handler **handlers = bch2_xattr_handlers;
const struct xattr_handler *handler;
for_each_xattr_handler(handlers, handler) {
- const char *n;
+ char *n;
n = strcmp_prefix(*name, xattr_prefix(handler));
if (n) {
if (attrs_size < 0)
die("listxattr error: %m");
- const char *next, *attr;
+ char *next, *attr;
for (attr = attrs;
attr < attrs + attrs_size;
attr = next) {
const struct xattr_handler *h = xattr_resolve_name(&attr);
- int ret = __bch2_xattr_set(c, dst->bi_inum, &hash_info, attr,
- val, val_size, 0, h->flags, NULL);
+ int ret = bch2_trans_do(c, NULL, NULL, 0,
+ bch2_xattr_set(&trans, dst->bi_inum, &hash_info, attr,
+ val, val_size, h->flags, 0));
if (ret < 0)
die("error creating xattr: %s", strerror(-ret));
}
}
static char buf[1 << 20] __aligned(PAGE_SIZE);
-static const size_t buf_pages = sizeof(buf) / PAGE_SIZE;
static void write_data(struct bch_fs *c,
struct bch_inode_unpacked *dst_inode,
{
struct {
struct bch_write_op op;
- struct bio_vec bv[buf_pages];
+ struct bio_vec bv[sizeof(buf) / PAGE_SIZE];
} o;
struct closure cl;
closure_init_stack(&cl);
- bio_init(&o.op.wbio.bio, o.bv, buf_pages);
- o.op.wbio.bio.bi_iter.bi_size = len;
- bch2_bio_map(&o.op.wbio.bio, buf);
+ bio_init(&o.op.wbio.bio, o.bv, ARRAY_SIZE(o.bv));
+ bch2_bio_map(&o.op.wbio.bio, buf, len);
- bch2_write_op_init(&o.op, c);
+ bch2_write_op_init(&o.op, c, bch2_opts_to_inode_opts(c->opts));
o.op.write_point = writepoint_hashed(0);
o.op.nr_replicas = 1;
o.op.pos = POS(dst_inode->bi_inum, dst_offset >> 9);
while (length) {
struct bkey_i_extent *e;
- BKEY_PADDED(k) k;
+ __BKEY_PADDED(k, BKEY_EXTENT_VAL_U64s_MAX) k;
u64 b = sector_to_bucket(ca, physical);
struct disk_reservation res;
unsigned sectors;
e->k.p.inode = dst->bi_inum;
e->k.p.offset = logical + sectors;
e->k.size = sectors;
- extent_ptr_append(e, (struct bch_extent_ptr) {
+ bch2_bkey_append_ptr(&e->k_i, (struct bch_extent_ptr) {
.offset = physical,
.dev = 0,
.gen = bucket(ca, b)->mark.gen,
});
- set_bit(b, ca->buckets_dirty);
-
ret = bch2_disk_reservation_get(c, &res, sectors, 1,
BCH_DISK_RESERVATION_NOFAIL);
if (ret)
die("error reserving space in new filesystem: %s",
strerror(-ret));
- bch2_check_mark_super(c, BCH_DATA_USER,
- bch2_bkey_devs(extent_i_to_s_c(e).s_c));
+ bch2_mark_bkey_replicas(c, extent_i_to_s_c(e).s_c);
- ret = bch2_btree_insert(c, BTREE_ID_EXTENTS, &e->k_i,
- &res, NULL, NULL, 0);
+ ret = bch2_btree_insert(c, BTREE_ID_extents, &e->k_i,
+ &res, NULL, 0);
if (ret)
die("btree insert error %s", strerror(-ret));
darray_free(s.extents);
genradix_free(&s.hardlinks);
- bch2_alloc_write(c);
+ bch2_alloc_write(c, false);
}
-static void find_superblock_space(ranges extents, struct dev_opts *dev)
+static void find_superblock_space(ranges extents,
+ struct format_opts opts,
+ struct dev_opts *dev)
{
struct range *i;
u64 end = round_down(i->end,
dev->bucket_size << 9);
- if (start + (128 << 10) <= end) {
+ /* Need space for two superblocks: */
+ if (start + (opts.superblock_size << 9) * 2 <= end) {
dev->sb_offset = start >> 9;
- dev->sb_end = dev->sb_offset + 256;
+ dev->sb_end = dev->sb_offset + opts.superblock_size * 2;
return;
}
}
{ NULL }
};
-static int migrate_fs(const char *fs_path,
- struct format_opts format_opts,
+static int migrate_fs(const char *fs_path,
+ struct bch_opt_strs fs_opt_strs,
+ struct bch_opts fs_opts,
+ struct format_opts format_opts,
bool force)
{
if (!path_is_fs_root(fs_path))
dev.path = dev_t_to_path(stat.st_dev);
dev.fd = xopen(dev.path, O_RDWR);
- unsigned block_size = get_blocksize(dev.path, dev.fd) << 9;
- BUG_ON(!is_power_of_2(block_size) || block_size < 512);
- format_opts.block_size = block_size >> 9;
+ opt_set(fs_opts, block_size, get_blocksize(dev.path, dev.fd));
char *file_path = mprintf("%s/bcachefs", fs_path);
printf("Creating new filesystem on %s in space reserved at %s\n",
dev.path, file_path);
- bch2_pick_bucket_size(format_opts, &dev);
+ bch2_pick_bucket_size(fs_opts, &dev);
u64 bcachefs_inum;
ranges extents = reserve_new_fs_space(file_path,
- format_opts.block_size << 9,
+ fs_opts.block_size << 9,
get_size(dev.path, dev.fd) / 5,
&bcachefs_inum, stat.st_dev, force);
- find_superblock_space(extents, &dev);
+ find_superblock_space(extents, format_opts, &dev);
- struct bch_sb *sb = bch2_format(format_opts, &dev, 1);
+ struct bch_sb *sb = bch2_format(fs_opt_strs,
+ fs_opts,format_opts, &dev, 1);
u64 sb_offset = le64_to_cpu(sb->layout.sb_offset[0]);
if (format_opts.passphrase)
mark_unreserved_space(c, extents);
- const char *err = bch2_fs_start(c);
- if (err)
- die("Error starting new filesystem: %s", err);
+ int ret = bch2_fs_start(c);
+ if (ret)
+ die("Error starting new filesystem: %s", strerror(-ret));
copy_fs(c, fs_fd, fs_path, bcachefs_inum, &extents);
bool no_passphrase = false, force = false;
int opt;
+ struct bch_opt_strs fs_opt_strs =
+ bch2_cmdline_opts_get(&argc, argv, OPT_FORMAT);
+ struct bch_opts fs_opts = bch2_parse_opts(fs_opt_strs);
+
while ((opt = getopt_long(argc, argv, "f:Fh",
migrate_opts, NULL)) != -1)
switch (opt) {
}
if (!fs_path)
- die("Please specify a filesytem to migrate");
+ die("Please specify a filesystem to migrate");
if (format_opts.encrypted && !no_passphrase)
format_opts.passphrase = read_passphrase_twice("Enter passphrase: ");
- return migrate_fs(fs_path, format_opts, force);
+ int ret = migrate_fs(fs_path,
+ fs_opt_strs,
+ fs_opts,
+ format_opts, force);
+ bch2_opt_strs_free(&fs_opt_strs);
+ return ret;
}
static void migrate_superblock_usage(void)
{
- puts("bcachefs migrate_superblock - create default superblock after migrating\n"
- "Usage: bcachefs migrate_superblock [OPTION]...\n"
+ puts("bcachefs migrate-superblock - create default superblock after migrating\n"
+ "Usage: bcachefs migrate-superblock [OPTION]...\n"
"\n"
"Options:\n"
" -d device Device to create superblock for\n"