Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,10 @@ struct btrfs_super_block {
__le64 cache_generation;
__le64 uuid_tree_generation;

/* r5log journal tail (where recovery starts) */
__le64 journal_tail;
/* future expansion */
__le64 reserved[30];
__le64 reserved[29];
u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE];
struct btrfs_root_backup super_roots[BTRFS_NUM_BACKUP_ROOTS];
} __attribute__ ((__packed__));
Expand Down Expand Up @@ -697,6 +699,7 @@ struct btrfs_stripe_hash_table {
void btrfs_init_async_reclaim_work(struct work_struct *work);

/* fs_info */
struct btrfs_r5l_log;
struct reloc_control;
struct btrfs_device;
struct btrfs_fs_devices;
Expand Down Expand Up @@ -1114,6 +1117,9 @@ struct btrfs_fs_info {
u32 nodesize;
u32 sectorsize;
u32 stripesize;

/* raid56 log */
struct btrfs_r5l_log *r5log;
};

static inline struct btrfs_fs_info *btrfs_sb(struct super_block *sb)
Expand Down Expand Up @@ -2287,6 +2293,8 @@ BTRFS_SETGET_STACK_FUNCS(super_log_root_transid, struct btrfs_super_block,
log_root_transid, 64);
BTRFS_SETGET_STACK_FUNCS(super_log_root_level, struct btrfs_super_block,
log_root_level, 8);
BTRFS_SETGET_STACK_FUNCS(super_journal_tail, struct btrfs_super_block,
journal_tail, 64);
BTRFS_SETGET_STACK_FUNCS(super_total_bytes, struct btrfs_super_block,
total_bytes, 64);
BTRFS_SETGET_STACK_FUNCS(super_bytes_used, struct btrfs_super_block,
Expand Down Expand Up @@ -2932,6 +2940,8 @@ static inline int btrfs_need_cleaner_sleep(struct btrfs_fs_info *fs_info)

static inline void free_fs_info(struct btrfs_fs_info *fs_info)
{
if (fs_info->r5log)
kfree(fs_info->r5log);
kfree(fs_info->balance_ctl);
kfree(fs_info->delayed_root);
kfree(fs_info->extent_root);
Expand Down Expand Up @@ -3278,6 +3288,10 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
unsigned long new_flags);
int btrfs_sync_fs(struct super_block *sb, int wait);

/* raid56.c */
void btrfs_r5l_write_journal_tail(struct btrfs_fs_info *fs_info);


static inline __printf(2, 3)
void btrfs_no_printk(const struct btrfs_fs_info *fs_info, const char *fmt, ...)
{
Expand Down
16 changes: 16 additions & 0 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -2987,6 +2987,22 @@ int open_ctree(struct super_block *sb,
fs_info->generation = generation;
fs_info->last_trans_committed = generation;

if (fs_info->r5log) {
u64 cp = btrfs_super_journal_tail(fs_info->super_copy);
#ifdef BTRFS_DEBUG_R5LOG
trace_printk("%s: get journal_tail %llu\n", __func__, cp);
#endif
/* if the data is not replayed, data and parity on
* disk are still consistent. So we can move on.
*
* About fsync, since fsync can make sure data is
* flushed onto disk and only metadata is kept into
* write-ahead log, the fsync'd data will never ends
* up with being replayed by raid56 log.
*/
btrfs_r5l_load_log(fs_info, NULL, cp);
}

ret = btrfs_recover_balance(fs_info);
if (ret) {
btrfs_err(fs_info, "failed to recover balance: %d", ret);
Expand Down
48 changes: 47 additions & 1 deletion fs/btrfs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -2653,6 +2653,50 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp)
return ret;
}

/* identical to btrfs_ioctl_add_dev, but this is with flags */
static long btrfs_ioctl_add_dev_v2(struct btrfs_fs_info *fs_info, void __user *arg)
{
struct btrfs_ioctl_vol_args_v2 *vol_args;
int ret;

if (!capable(CAP_SYS_ADMIN))
return -EPERM;

if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags))
return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;

mutex_lock(&fs_info->volume_mutex);
vol_args = memdup_user(arg, sizeof(*vol_args));
if (IS_ERR(vol_args)) {
ret = PTR_ERR(vol_args);
goto out;
}

if (vol_args->flags & BTRFS_DEVICE_RAID56_LOG &&
fs_info->r5log) {
ret = -EEXIST;
btrfs_info(fs_info, "r5log: attempting to add another log device!");
goto out_free;
}

vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
ret = btrfs_init_new_device(fs_info, vol_args->name, vol_args->flags);
if (!ret) {
if (vol_args->flags & BTRFS_DEVICE_RAID56_LOG) {
ASSERT(fs_info->r5log);
btrfs_info(fs_info, "disk added %s as raid56 log", vol_args->name);
} else {
btrfs_info(fs_info, "disk added %s", vol_args->name);
}
}
out_free:
kfree(vol_args);
out:
mutex_unlock(&fs_info->volume_mutex);
clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
return ret;
}

static long btrfs_ioctl_add_dev(struct btrfs_fs_info *fs_info, void __user *arg)
{
struct btrfs_ioctl_vol_args *vol_args;
Expand All @@ -2672,7 +2716,7 @@ static long btrfs_ioctl_add_dev(struct btrfs_fs_info *fs_info, void __user *arg)
}

vol_args->name[BTRFS_PATH_NAME_MAX] = '\0';
ret = btrfs_init_new_device(fs_info, vol_args->name);
ret = btrfs_init_new_device(fs_info, vol_args->name, 0);

if (!ret)
btrfs_info(fs_info, "disk added %s", vol_args->name);
Expand Down Expand Up @@ -5539,6 +5583,8 @@ long btrfs_ioctl(struct file *file, unsigned int
return btrfs_ioctl_resize(file, argp);
case BTRFS_IOC_ADD_DEV:
return btrfs_ioctl_add_dev(fs_info, argp);
case BTRFS_IOC_ADD_DEV_V2:
return btrfs_ioctl_add_dev_v2(fs_info, argp);
case BTRFS_IOC_RM_DEV:
return btrfs_ioctl_rm_dev(file, argp);
case BTRFS_IOC_RM_DEV_V2:
Expand Down
Loading