Re: [RFC PATCH 6/6] btrfs: add chattr support for send/receive
On Tue, May 08, 2018 at 10:06:51PM -0400, Howard McLauchlan wrote: > From: Howard McLauchlan > > Presently btrfs send/receive does not propagate inode attribute flags; > all chattr operations are effectively discarded upon transmission. > > This patch adds kernel support for inode attribute flags. Userspace > support can be found under the commit: > > btrfs-progs: add chattr support for send/receive > > An associated xfstest can be found at: > > btrfs: add verify chattr support for send/receive test > > These changes are only enabled for send stream version 2 > > Signed-off-by: Howard McLauchlan > --- > fs/btrfs/ctree.h | 2 + > fs/btrfs/ioctl.c | 2 +- > fs/btrfs/send.c | 181 --- > fs/btrfs/send.h | 4 +- > 4 files changed, 159 insertions(+), 30 deletions(-) > > diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h > index 2771cc56a622..0a2359144b18 100644 > --- a/fs/btrfs/ctree.h > +++ b/fs/btrfs/ctree.h > @@ -1461,6 +1461,8 @@ struct btrfs_map_token { > unsigned long offset; > }; > > +unsigned int btrfs_flags_to_ioctl(unsigned int flags); > + > #define BTRFS_BYTES_TO_BLKS(fs_info, bytes) \ > ((bytes) >> (fs_info)->sb->s_blocksize_bits) > > diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c > index 632e26d6f7ce..36ce1e589f9e 100644 > --- a/fs/btrfs/ioctl.c > +++ b/fs/btrfs/ioctl.c > @@ -106,7 +106,7 @@ static unsigned int btrfs_mask_flags(umode_t mode, > unsigned int flags) > /* > * Export inode flags to the format expected by the FS_IOC_GETFLAGS ioctl. > */ > -static unsigned int btrfs_flags_to_ioctl(unsigned int flags) > +unsigned int btrfs_flags_to_ioctl(unsigned int flags) > { > unsigned int iflags = 0; > > diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c > index c8ea1ccaa3d8..fa7db1474a7f 100644 > --- a/fs/btrfs/send.c > +++ b/fs/btrfs/send.c > @@ -108,6 +108,13 @@ struct send_ctx { > u64 cur_inode_last_extent; > u64 cur_inode_next_write_offset; > > + /* > + * state for chattr purposes > + */ > + u64 cur_inode_flip_flags; > + u64 cur_inode_receive_flags; > + int receive_flags_valid; I'd use bool here (and change the places that set it to use true or false). > + > u64 send_progress; > u64 total_data_size; > > @@ -815,7 +822,7 @@ static int send_rmdir(struct send_ctx *sctx, struct > fs_path *path) > */ > static int __get_inode_info(struct btrfs_root *root, struct btrfs_path *path, > u64 ino, u64 *size, u64 *gen, u64 *mode, u64 *uid, > - u64 *gid, u64 *rdev) > + u64 *gid, u64 *rdev, u64 *flags) > { > int ret; > struct btrfs_inode_item *ii; > @@ -845,6 +852,8 @@ static int __get_inode_info(struct btrfs_root *root, > struct btrfs_path *path, > *gid = btrfs_inode_gid(path->nodes[0], ii); > if (rdev) > *rdev = btrfs_inode_rdev(path->nodes[0], ii); > + if (flags) > + *flags = btrfs_inode_flags(path->nodes[0], ii); > > return ret; > } > @@ -852,7 +861,7 @@ static int __get_inode_info(struct btrfs_root *root, > struct btrfs_path *path, > static int get_inode_info(struct btrfs_root *root, > u64 ino, u64 *size, u64 *gen, > u64 *mode, u64 *uid, u64 *gid, > - u64 *rdev) > + u64 *rdev, u64 *flags) > { > struct btrfs_path *path; > int ret; > @@ -861,7 +870,7 @@ static int get_inode_info(struct btrfs_root *root, > if (!path) > return -ENOMEM; > ret = __get_inode_info(root, path, ino, size, gen, mode, uid, gid, > -rdev); > +rdev, flags); > btrfs_free_path(path); > return ret; > } > @@ -1250,7 +1259,7 @@ static int __iterate_backrefs(u64 ino, u64 offset, u64 > root, void *ctx_) >* accept clones from these extents. >*/ > ret = __get_inode_info(found->root, bctx->path, ino, &i_size, NULL, > NULL, > -NULL, NULL, NULL); > +NULL, NULL, NULL, NULL); > btrfs_release_path(bctx->path); > if (ret < 0) > return ret; > @@ -1610,7 +1619,7 @@ static int get_cur_inode_state(struct send_ctx *sctx, > u64 ino, u64 gen) > u64 right_gen; > > ret = get_inode_info(sctx->send_root, ino, NULL, &left_gen, NULL, NULL, > - NULL, NULL); > + NULL, NULL, NULL); > if (ret < 0 && ret != -ENOENT) > goto out; > left_ret = ret; > @@ -1619,7 +1628,7 @@ static int get_cur_inode_state(struct send_ctx *sctx, > u64 ino, u64 gen) > right_ret = -ENOENT; > } else { > ret = get_inode_info(sctx->parent_root, ino, NULL, &right_gen, > - NULL, NULL, NULL, NULL); > + NULL, NULL, N
[RFC PATCH 6/6] btrfs: add chattr support for send/receive
From: Howard McLauchlan Presently btrfs send/receive does not propagate inode attribute flags; all chattr operations are effectively discarded upon transmission. This patch adds kernel support for inode attribute flags. Userspace support can be found under the commit: btrfs-progs: add chattr support for send/receive An associated xfstest can be found at: btrfs: add verify chattr support for send/receive test These changes are only enabled for send stream version 2 Signed-off-by: Howard McLauchlan --- fs/btrfs/ctree.h | 2 + fs/btrfs/ioctl.c | 2 +- fs/btrfs/send.c | 181 --- fs/btrfs/send.h | 4 +- 4 files changed, 159 insertions(+), 30 deletions(-) diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 2771cc56a622..0a2359144b18 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -1461,6 +1461,8 @@ struct btrfs_map_token { unsigned long offset; }; +unsigned int btrfs_flags_to_ioctl(unsigned int flags); + #define BTRFS_BYTES_TO_BLKS(fs_info, bytes) \ ((bytes) >> (fs_info)->sb->s_blocksize_bits) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 632e26d6f7ce..36ce1e589f9e 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -106,7 +106,7 @@ static unsigned int btrfs_mask_flags(umode_t mode, unsigned int flags) /* * Export inode flags to the format expected by the FS_IOC_GETFLAGS ioctl. */ -static unsigned int btrfs_flags_to_ioctl(unsigned int flags) +unsigned int btrfs_flags_to_ioctl(unsigned int flags) { unsigned int iflags = 0; diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index c8ea1ccaa3d8..fa7db1474a7f 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -108,6 +108,13 @@ struct send_ctx { u64 cur_inode_last_extent; u64 cur_inode_next_write_offset; + /* +* state for chattr purposes +*/ + u64 cur_inode_flip_flags; + u64 cur_inode_receive_flags; + int receive_flags_valid; + u64 send_progress; u64 total_data_size; @@ -815,7 +822,7 @@ static int send_rmdir(struct send_ctx *sctx, struct fs_path *path) */ static int __get_inode_info(struct btrfs_root *root, struct btrfs_path *path, u64 ino, u64 *size, u64 *gen, u64 *mode, u64 *uid, - u64 *gid, u64 *rdev) + u64 *gid, u64 *rdev, u64 *flags) { int ret; struct btrfs_inode_item *ii; @@ -845,6 +852,8 @@ static int __get_inode_info(struct btrfs_root *root, struct btrfs_path *path, *gid = btrfs_inode_gid(path->nodes[0], ii); if (rdev) *rdev = btrfs_inode_rdev(path->nodes[0], ii); + if (flags) + *flags = btrfs_inode_flags(path->nodes[0], ii); return ret; } @@ -852,7 +861,7 @@ static int __get_inode_info(struct btrfs_root *root, struct btrfs_path *path, static int get_inode_info(struct btrfs_root *root, u64 ino, u64 *size, u64 *gen, u64 *mode, u64 *uid, u64 *gid, - u64 *rdev) + u64 *rdev, u64 *flags) { struct btrfs_path *path; int ret; @@ -861,7 +870,7 @@ static int get_inode_info(struct btrfs_root *root, if (!path) return -ENOMEM; ret = __get_inode_info(root, path, ino, size, gen, mode, uid, gid, - rdev); + rdev, flags); btrfs_free_path(path); return ret; } @@ -1250,7 +1259,7 @@ static int __iterate_backrefs(u64 ino, u64 offset, u64 root, void *ctx_) * accept clones from these extents. */ ret = __get_inode_info(found->root, bctx->path, ino, &i_size, NULL, NULL, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); btrfs_release_path(bctx->path); if (ret < 0) return ret; @@ -1610,7 +1619,7 @@ static int get_cur_inode_state(struct send_ctx *sctx, u64 ino, u64 gen) u64 right_gen; ret = get_inode_info(sctx->send_root, ino, NULL, &left_gen, NULL, NULL, - NULL, NULL); + NULL, NULL, NULL); if (ret < 0 && ret != -ENOENT) goto out; left_ret = ret; @@ -1619,7 +1628,7 @@ static int get_cur_inode_state(struct send_ctx *sctx, u64 ino, u64 gen) right_ret = -ENOENT; } else { ret = get_inode_info(sctx->parent_root, ino, NULL, &right_gen, - NULL, NULL, NULL, NULL); + NULL, NULL, NULL, NULL, NULL); if (ret < 0 && ret != -ENOENT) goto out; right_ret = ret; @@ -1788,7 +1797,7 @@ static int get_first_ref(struct btrfs_root *root, u64 ino, if (dir_gen) { ret = get_inode_info(root, parent_dir, NULL, dir_