author | Alberto Bertogli
<albertito@blitiri.com.ar> 2009-09-26 18:14:01 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2009-09-26 18:42:39 UTC |
parent | 1ee54b0c2e244ddcba943208bb19ddb66ece2b60 |
libjio/Makefile | +2 | -2 |
libjio/btrfs-ioctl.h | +75 | -0 |
libjio/btrfs.c | +55 | -0 |
libjio/btrfs.h | +16 | -0 |
libjio/journal.c | +17 | -5 |
libjio/journal.h | +2 | -0 |
libjio/trans.c | +15 | -0 |
libjio/trans.h | +2 | -0 |
diff --git a/libjio/Makefile b/libjio/Makefile index a32828f..54343db 100644 --- a/libjio/Makefile +++ b/libjio/Makefile @@ -64,8 +64,8 @@ LIB_VER=1.00 LIB_SO_VER=1 -OBJS = $(addprefix $O/,autosync.o checksum.o common.o compat.o trans.o \ - check.o journal.o unix.o ansi.o) +OBJS = $(addprefix $O/,autosync.o btrfs.o checksum.o common.o compat.o \ + trans.o check.o journal.o unix.o ansi.o) # targets diff --git a/libjio/btrfs-ioctl.h b/libjio/btrfs-ioctl.h new file mode 100644 index 0000000..7c42513 --- /dev/null +++ b/libjio/btrfs-ioctl.h @@ -0,0 +1,75 @@ + +/* The following was copied from Linux 2.6.31's kernel source, and the + * #include <asm/types.h> line was added to permit inclusion from userspace + * applications. */ + +/* + * Copyright (C) 2007 Oracle. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License v2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 021110-1307, USA. + */ + +#ifndef __IOCTL_ +#define __IOCTL_ +#include <asm/types.h> +#include <linux/ioctl.h> + +#define BTRFS_IOCTL_MAGIC 0x94 +#define BTRFS_VOL_NAME_MAX 255 +#define BTRFS_PATH_NAME_MAX 4087 + +/* this should be 4k */ +struct btrfs_ioctl_vol_args { + __s64 fd; + char name[BTRFS_PATH_NAME_MAX + 1]; +}; + +struct btrfs_ioctl_clone_range_args { + __s64 src_fd; + __u64 src_offset, src_length; + __u64 dest_offset; +}; + +#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \ + struct btrfs_ioctl_vol_args) +#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ + struct btrfs_ioctl_vol_args) +#define BTRFS_IOC_RESIZE _IOW(BTRFS_IOCTL_MAGIC, 3, \ + struct btrfs_ioctl_vol_args) +#define BTRFS_IOC_SCAN_DEV _IOW(BTRFS_IOCTL_MAGIC, 4, \ + struct btrfs_ioctl_vol_args) +/* trans start and trans end are dangerous, and only for + * use by applications that know how to avoid the + * resulting deadlocks + */ +#define BTRFS_IOC_TRANS_START _IO(BTRFS_IOCTL_MAGIC, 6) +#define BTRFS_IOC_TRANS_END _IO(BTRFS_IOCTL_MAGIC, 7) +#define BTRFS_IOC_SYNC _IO(BTRFS_IOCTL_MAGIC, 8) + +#define BTRFS_IOC_CLONE _IOW(BTRFS_IOCTL_MAGIC, 9, int) +#define BTRFS_IOC_ADD_DEV _IOW(BTRFS_IOCTL_MAGIC, 10, \ + struct btrfs_ioctl_vol_args) +#define BTRFS_IOC_RM_DEV _IOW(BTRFS_IOCTL_MAGIC, 11, \ + struct btrfs_ioctl_vol_args) +#define BTRFS_IOC_BALANCE _IOW(BTRFS_IOCTL_MAGIC, 12, \ + struct btrfs_ioctl_vol_args) + +#define BTRFS_IOC_CLONE_RANGE _IOW(BTRFS_IOCTL_MAGIC, 13, \ + struct btrfs_ioctl_clone_range_args) + +#define BTRFS_IOC_SUBVOL_CREATE _IOW(BTRFS_IOCTL_MAGIC, 14, \ + struct btrfs_ioctl_vol_args) + +#endif diff --git a/libjio/btrfs.c b/libjio/btrfs.c new file mode 100644 index 0000000..2647df5 --- /dev/null +++ b/libjio/btrfs.c @@ -0,0 +1,55 @@ + +#include <sys/types.h> /* off_t, size_t */ +#include <sys/ioctl.h> /* ioctl() */ +#include "btrfs-ioctl.h" +#include "btrfs.h" +#include "trans.h" +#include "journal.h" + + +/* Wrapper around btrfs' clone_range ioctl() */ +int btrfs_clone_range(int src_fd, off_t src_off, size_t src_len, + int dst_fd, off_t dst_off) +{ + int res; + struct btrfs_ioctl_clone_range_args args; + + args.src_fd = src_fd; + args.src_offset = src_off; + args.src_length = src_len; + args.dest_offset = dst_off; + printf("%d %llu %zu -> %d %llu\n", src_fd, src_off, src_len, dst_fd, + dst_off); + + res = ioctl(dst_fd, BTRFS_IOC_CLONE_RANGE, &args); + return res; +} +ssize_t attempt_btrfs_clone_ranges(int fd, struct operation *head_op, + struct journal_op *jop) +{ + ssize_t r, written; + struct operation *op; + off_t journal_off; + + written = 0; + journal_off = BSZ; + for (op = head_op; op != NULL; op = op->next) { + /* skip the header + padding */ + journal_off += BSZ; + + r = btrfs_clone_range(jop->fd, journal_off, op->len, fd, + op->offset); + if (r != 0) { + perror("btrfs_clone_range"); + return -1; + } + written += op->len; + + /* skip the data + padding */ + journal_off += op->len; + journal_off += (BSZ - (journal_off % BSZ)) % BSZ; + } + + return written; +} + diff --git a/libjio/btrfs.h b/libjio/btrfs.h new file mode 100644 index 0000000..d351914 --- /dev/null +++ b/libjio/btrfs.h @@ -0,0 +1,16 @@ + +#ifndef _LJ_BTRFS_H +#define _LJ_BTRFS_H + +#include <sys/types.h> +#include "trans.h" +#include "journal.h" + +int btrfs_clone_range(int src_fd, off_t src_off, size_t src_len, + int dst_fd, off_t dst_off); + +/* TODO: better name for this, maybe put it inside trans.c */ +ssize_t attempt_btrfs_clone_ranges(int fd, struct operation *head_op, + struct journal_op *jop); + +#endif diff --git a/libjio/journal.c b/libjio/journal.c index fc34ffc..e2a4889 100644 --- a/libjio/journal.c +++ b/libjio/journal.c @@ -330,13 +330,20 @@ error: return NULL; } + +static unsigned char empty_blk[BSZ]; + /** Save a single operation in the journal file */ int journal_add_op(struct journal_op *jop, unsigned char *buf, size_t len, off_t offset) { ssize_t rv; struct on_disk_ophdr ophdr; - struct iovec iov[2]; + struct iovec iov[3]; + + /* start at 4k boundary */ + off_t curpos = lseek(jop->fd, 0, SEEK_CUR); + lseek(jop->fd, (BSZ - (curpos % BSZ)) % BSZ, SEEK_CUR); ophdr.len = len; ophdr.offset = offset; @@ -347,14 +354,19 @@ int journal_add_op(struct journal_op *jop, unsigned char *buf, size_t len, jop->csum = checksum_buf(jop->csum, (unsigned char *) &ophdr, sizeof(ophdr)); - iov[1].iov_base = (void *) buf; - iov[1].iov_len = len; + iov[1].iov_base = (void *) empty_blk; + iov[1].iov_len = BSZ - sizeof(ophdr); + jop->csum = checksum_buf(jop->csum, empty_blk, iov[1].iov_len); + + /* this will be BSZ-aligned */ + iov[2].iov_base = (void *) buf; + iov[2].iov_len = len; jop->csum = checksum_buf(jop->csum, buf, len); fiu_exit_on("jio/commit/tf_pre_addop"); - rv = swritev(jop->fd, iov, 2); - if (rv != sizeof(ophdr) + len) + rv = swritev(jop->fd, iov, 3); + if (rv != iov[0].iov_len + iov[1].iov_len + iov[2].iov_len) goto error; fiu_exit_on("jio/commit/tf_addop"); diff --git a/libjio/journal.h b/libjio/journal.h index bdc1445..57eff46 100644 --- a/libjio/journal.h +++ b/libjio/journal.h @@ -5,6 +5,8 @@ #include <stdint.h> #include "libjio.h" +/* filesystem block size */ +#define BSZ 4096 struct journal_op { int id; diff --git a/libjio/trans.c b/libjio/trans.c index 1f7b66f..e1d3899 100644 --- a/libjio/trans.c +++ b/libjio/trans.c @@ -21,6 +21,7 @@ #include "compat.h" #include "journal.h" #include "trans.h" +#include "btrfs.h" /* @@ -329,6 +330,18 @@ ssize_t jtrans_commit(struct jtrans *ts) goto unlink_exit; } + /* Attempt to write to the real file using btrfs' clone_range ioctl, + * and only resort to the normal write procedure if it fails. + * We should also isolate the normal write procedure, and clean this + * code up. */ + r = attempt_btrfs_clone_ranges(ts->fs->fd, ts->op, jop); + if (r >= 0) { + printf("btrfs ok\n"); + written = r; + goto write_success; + } + printf("btrfs fail\n"); + /* now that we have a safe transaction file, let's apply it */ written = 0; for (op = ts->op; op != NULL; op = op->next) { @@ -358,6 +371,8 @@ ssize_t jtrans_commit(struct jtrans *ts) fiu_exit_on("jio/commit/wrote_op"); } +write_success: + fiu_exit_on("jio/commit/wrote_all_ops"); if (jop && (ts->flags & J_LINGER)) { diff --git a/libjio/trans.h b/libjio/trans.h index 466c2d9..b033db8 100644 --- a/libjio/trans.h +++ b/libjio/trans.h @@ -2,6 +2,8 @@ #ifndef _TRANS_H #define _TRANS_H +#include <stdint.h> /* uint32_t and friends */ + struct operation; /** A transaction */