#include "btree_update_interior.h"
#include "buckets.h"
#include "checksum.h"
+#include "counters.h"
#include "disk_groups.h"
#include "ec.h"
#include "error.h"
#include "journal_io.h"
#include "journal_sb.h"
#include "journal_seq_blacklist.h"
+#include "recovery.h"
#include "replicas.h"
#include "quota.h"
#include "super-io.h"
#include "super.h"
#include "trace.h"
#include "vstructs.h"
-#include "counters.h"
#include <linux/backing-dev.h>
#include <linux/sort.h>
-struct bch2_metadata_version_str {
+struct bch2_metadata_version {
u16 version;
const char *name;
+ u64 recovery_passes;
};
-static const struct bch2_metadata_version_str bch2_metadata_versions[] = {
-#define x(n, v) { .version = v, .name = #n },
+static const struct bch2_metadata_version bch2_metadata_versions[] = {
+#define x(n, v, _recovery_passes) { \
+ .version = v, \
+ .name = #n, \
+ .recovery_passes = _recovery_passes, \
+},
BCH_METADATA_VERSIONS()
#undef x
};
return v;
}
+u64 bch2_upgrade_recovery_passes(struct bch_fs *c,
+ unsigned old_version,
+ unsigned new_version)
+{
+ u64 ret = 0;
+
+ for (const struct bch2_metadata_version *i = bch2_metadata_versions;
+ i < bch2_metadata_versions + ARRAY_SIZE(bch2_metadata_versions);
+ i++)
+ if (i->version > old_version && i->version <= new_version) {
+ if (i->recovery_passes & RECOVERY_PASS_ALL_FSCK)
+ ret |= bch2_fsck_recovery_passes();
+ ret |= i->recovery_passes;
+ }
+
+ return ret &= ~RECOVERY_PASS_ALL_FSCK;
+}
+
const char * const bch2_sb_fields[] = {
#define x(name, nr) #name,
BCH_SB_FIELDS()
SET_BCH_SB_JOURNAL_FLUSH_DELAY(sb, 1000);
if (!BCH_SB_JOURNAL_RECLAIM_DELAY(sb))
SET_BCH_SB_JOURNAL_RECLAIM_DELAY(sb, 1000);
+
+ if (!BCH_SB_VERSION_UPGRADE_COMPLETE(sb))
+ SET_BCH_SB_VERSION_UPGRADE_COMPLETE(sb, le16_to_cpu(sb->version));
}
for (opt_id = 0; opt_id < bch2_opts_nr; opt_id++) {
c->sb.user_uuid = src->user_uuid;
c->sb.version = le16_to_cpu(src->version);
c->sb.version_min = le16_to_cpu(src->version_min);
- c->sb.version_upgrade_complete = BCH_SB_VERSION_UPGRADE_COMPLETE(src) ?: c->sb.version;
+ c->sb.version_upgrade_complete = BCH_SB_VERSION_UPGRADE_COMPLETE(src);
c->sb.nr_devices = src->nr_devices;
c->sb.clean = BCH_SB_CLEAN(src);
c->sb.encryption_type = BCH_SB_ENCRYPTION_TYPE(src);
struct printbuf err = PRINTBUF;
__le64 *i;
int ret;
-
+#ifndef __KERNEL__
+retry:
+#endif
memset(sb, 0, sizeof(*sb));
sb->mode = FMODE_READ;
sb->have_bio = true;
+#ifndef __KERNEL__
+ if (opt_get(*opts, direct_io) == false)
+ sb->mode |= FMODE_BUFFERED;
+#endif
+
if (!opt_get(*opts, noexcl))
sb->mode |= FMODE_EXCL;
got_super:
if (le16_to_cpu(sb->sb->block_size) << 9 <
- bdev_logical_block_size(sb->bdev)) {
+ bdev_logical_block_size(sb->bdev) &&
+ opt_get(*opts, direct_io)) {
+#ifndef __KERNEL__
+ opt_set(*opts, direct_io, false);
+ bch2_free_super(sb);
+ goto retry;
+#endif
prt_printf(&err, "block size (%u) smaller than device block size (%u)",
le16_to_cpu(sb->sb->block_size) << 9,
bdev_logical_block_size(sb->bdev));
#undef x
};
-static const struct bch_sb_field_ops bch2_sb_field_null_ops = {
- NULL
-};
+static const struct bch_sb_field_ops bch2_sb_field_null_ops;
static const struct bch_sb_field_ops *bch2_sb_field_type_ops(unsigned type)
{