diff options
| author | Christoph Hellwig <hch@lst.de> | 2009-04-17 04:37:41 -0400 |
|---|---|---|
| committer | Chris Mason <chris.mason@oracle.com> | 2009-06-10 11:29:52 -0400 |
| commit | 6cbff00f4632c8060b06bfc9585805217f11e12e (patch) | |
| tree | 1886c4c855662172b84be2bfbd2aa5ac6a5c429d /fs/btrfs | |
| parent | c289811cc096c57ff35550ee8132793a4f9b5b59 (diff) | |
Btrfs: implement FS_IOC_GETFLAGS/SETFLAGS/GETVERSION
Add support for the standard attributes set via chattr and read via
lsattr. Currently we store the attributes in the flags value in
the btrfs inode, but I wonder whether we should split it into two so
that we don't have to keep converting between the two formats.
Remove the btrfs_clear_flag/btrfs_set_flag/btrfs_test_flag macros
as they were confusing the existing code and got in the way of the
new additions.
Also add the FS_IOC_GETVERSION ioctl for getting i_generation as it's
trivial.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
| -rw-r--r-- | fs/btrfs/btrfs_inode.h | 1 | ||||
| -rw-r--r-- | fs/btrfs/compression.c | 6 | ||||
| -rw-r--r-- | fs/btrfs/ctree.h | 16 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 27 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 171 |
5 files changed, 200 insertions, 21 deletions
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index ecf5f7d8166..acb4f351758 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h | |||
| @@ -157,5 +157,4 @@ static inline void btrfs_i_size_write(struct inode *inode, u64 size) | |||
| 157 | BTRFS_I(inode)->disk_i_size = size; | 157 | BTRFS_I(inode)->disk_i_size = size; |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | |||
| 161 | #endif | 160 | #endif |
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index ab07627084f..de1e2fd3208 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c | |||
| @@ -123,7 +123,7 @@ static int check_compressed_csum(struct inode *inode, | |||
| 123 | u32 csum; | 123 | u32 csum; |
| 124 | u32 *cb_sum = &cb->sums; | 124 | u32 *cb_sum = &cb->sums; |
| 125 | 125 | ||
| 126 | if (btrfs_test_flag(inode, NODATASUM)) | 126 | if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM) |
| 127 | return 0; | 127 | return 0; |
| 128 | 128 | ||
| 129 | for (i = 0; i < cb->nr_pages; i++) { | 129 | for (i = 0; i < cb->nr_pages; i++) { |
| @@ -670,7 +670,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, | |||
| 670 | */ | 670 | */ |
| 671 | atomic_inc(&cb->pending_bios); | 671 | atomic_inc(&cb->pending_bios); |
| 672 | 672 | ||
| 673 | if (!btrfs_test_flag(inode, NODATASUM)) { | 673 | if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) { |
| 674 | btrfs_lookup_bio_sums(root, inode, comp_bio, | 674 | btrfs_lookup_bio_sums(root, inode, comp_bio, |
| 675 | sums); | 675 | sums); |
| 676 | } | 676 | } |
| @@ -697,7 +697,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, | |||
| 697 | ret = btrfs_bio_wq_end_io(root->fs_info, comp_bio, 0); | 697 | ret = btrfs_bio_wq_end_io(root->fs_info, comp_bio, 0); |
| 698 | BUG_ON(ret); | 698 | BUG_ON(ret); |
| 699 | 699 | ||
| 700 | if (!btrfs_test_flag(inode, NODATASUM)) | 700 | if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) |
| 701 | btrfs_lookup_bio_sums(root, inode, comp_bio, sums); | 701 | btrfs_lookup_bio_sums(root, inode, comp_bio, sums); |
| 702 | 702 | ||
| 703 | ret = btrfs_map_bio(root, READ, comp_bio, mirror_num, 0); | 703 | ret = btrfs_map_bio(root, READ, comp_bio, mirror_num, 0); |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 5fa7d7d287a..4d6e0b6f21e 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -1115,12 +1115,14 @@ struct btrfs_root { | |||
| 1115 | #define BTRFS_INODE_READONLY (1 << 2) | 1115 | #define BTRFS_INODE_READONLY (1 << 2) |
| 1116 | #define BTRFS_INODE_NOCOMPRESS (1 << 3) | 1116 | #define BTRFS_INODE_NOCOMPRESS (1 << 3) |
| 1117 | #define BTRFS_INODE_PREALLOC (1 << 4) | 1117 | #define BTRFS_INODE_PREALLOC (1 << 4) |
| 1118 | #define btrfs_clear_flag(inode, flag) (BTRFS_I(inode)->flags &= \ | 1118 | #define BTRFS_INODE_SYNC (1 << 5) |
| 1119 | ~BTRFS_INODE_##flag) | 1119 | #define BTRFS_INODE_IMMUTABLE (1 << 6) |
| 1120 | #define btrfs_set_flag(inode, flag) (BTRFS_I(inode)->flags |= \ | 1120 | #define BTRFS_INODE_APPEND (1 << 7) |
| 1121 | BTRFS_INODE_##flag) | 1121 | #define BTRFS_INODE_NODUMP (1 << 8) |
| 1122 | #define btrfs_test_flag(inode, flag) (BTRFS_I(inode)->flags & \ | 1122 | #define BTRFS_INODE_NOATIME (1 << 9) |
| 1123 | BTRFS_INODE_##flag) | 1123 | #define BTRFS_INODE_DIRSYNC (1 << 10) |
| 1124 | |||
| 1125 | |||
| 1124 | /* some macros to generate set/get funcs for the struct fields. This | 1126 | /* some macros to generate set/get funcs for the struct fields. This |
| 1125 | * assumes there is a lefoo_to_cpu for every type, so lets make a simple | 1127 | * assumes there is a lefoo_to_cpu for every type, so lets make a simple |
| 1126 | * one for u8: | 1128 | * one for u8: |
| @@ -2260,6 +2262,8 @@ int btrfs_cont_expand(struct inode *inode, loff_t size); | |||
| 2260 | 2262 | ||
| 2261 | /* ioctl.c */ | 2263 | /* ioctl.c */ |
| 2262 | long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg); | 2264 | long btrfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg); |
| 2265 | void btrfs_update_iflags(struct inode *inode); | ||
| 2266 | void btrfs_inherit_iflags(struct inode *inode, struct inode *dir); | ||
| 2263 | 2267 | ||
| 2264 | /* file.c */ | 2268 | /* file.c */ |
| 2265 | int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync); | 2269 | int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 917bf10597c..5b68330f858 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -368,7 +368,7 @@ again: | |||
| 368 | * inode has not been flagged as nocompress. This flag can | 368 | * inode has not been flagged as nocompress. This flag can |
| 369 | * change at any time if we discover bad compression ratios. | 369 | * change at any time if we discover bad compression ratios. |
| 370 | */ | 370 | */ |
| 371 | if (!btrfs_test_flag(inode, NOCOMPRESS) && | 371 | if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NOCOMPRESS) && |
| 372 | btrfs_test_opt(root, COMPRESS)) { | 372 | btrfs_test_opt(root, COMPRESS)) { |
| 373 | WARN_ON(pages); | 373 | WARN_ON(pages); |
| 374 | pages = kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS); | 374 | pages = kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS); |
| @@ -469,7 +469,7 @@ again: | |||
| 469 | nr_pages_ret = 0; | 469 | nr_pages_ret = 0; |
| 470 | 470 | ||
| 471 | /* flag the file so we don't compress in the future */ | 471 | /* flag the file so we don't compress in the future */ |
| 472 | btrfs_set_flag(inode, NOCOMPRESS); | 472 | BTRFS_I(inode)->flags |= BTRFS_INODE_NOCOMPRESS; |
| 473 | } | 473 | } |
| 474 | if (will_compress) { | 474 | if (will_compress) { |
| 475 | *num_added += 1; | 475 | *num_added += 1; |
| @@ -862,7 +862,7 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page, | |||
| 862 | async_cow->locked_page = locked_page; | 862 | async_cow->locked_page = locked_page; |
| 863 | async_cow->start = start; | 863 | async_cow->start = start; |
| 864 | 864 | ||
| 865 | if (btrfs_test_flag(inode, NOCOMPRESS)) | 865 | if (BTRFS_I(inode)->flags & BTRFS_INODE_NOCOMPRESS) |
| 866 | cur_end = end; | 866 | cur_end = end; |
| 867 | else | 867 | else |
| 868 | cur_end = min(end, start + 512 * 1024 - 1); | 868 | cur_end = min(end, start + 512 * 1024 - 1); |
| @@ -1133,10 +1133,10 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page, | |||
| 1133 | int ret; | 1133 | int ret; |
| 1134 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1134 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 1135 | 1135 | ||
| 1136 | if (btrfs_test_flag(inode, NODATACOW)) | 1136 | if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW) |
| 1137 | ret = run_delalloc_nocow(inode, locked_page, start, end, | 1137 | ret = run_delalloc_nocow(inode, locked_page, start, end, |
| 1138 | page_started, 1, nr_written); | 1138 | page_started, 1, nr_written); |
| 1139 | else if (btrfs_test_flag(inode, PREALLOC)) | 1139 | else if (BTRFS_I(inode)->flags & BTRFS_INODE_PREALLOC) |
| 1140 | ret = run_delalloc_nocow(inode, locked_page, start, end, | 1140 | ret = run_delalloc_nocow(inode, locked_page, start, end, |
| 1141 | page_started, 0, nr_written); | 1141 | page_started, 0, nr_written); |
| 1142 | else if (!btrfs_test_opt(root, COMPRESS)) | 1142 | else if (!btrfs_test_opt(root, COMPRESS)) |
| @@ -1290,7 +1290,7 @@ static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
| 1290 | int ret = 0; | 1290 | int ret = 0; |
| 1291 | int skip_sum; | 1291 | int skip_sum; |
| 1292 | 1292 | ||
| 1293 | skip_sum = btrfs_test_flag(inode, NODATASUM); | 1293 | skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; |
| 1294 | 1294 | ||
| 1295 | ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0); | 1295 | ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0); |
| 1296 | BUG_ON(ret); | 1296 | BUG_ON(ret); |
| @@ -1790,7 +1790,8 @@ static int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end, | |||
| 1790 | ClearPageChecked(page); | 1790 | ClearPageChecked(page); |
| 1791 | goto good; | 1791 | goto good; |
| 1792 | } | 1792 | } |
| 1793 | if (btrfs_test_flag(inode, NODATASUM)) | 1793 | |
| 1794 | if (BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM) | ||
| 1794 | return 0; | 1795 | return 0; |
| 1795 | 1796 | ||
| 1796 | if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID && | 1797 | if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID && |
| @@ -2156,6 +2157,8 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
| 2156 | init_special_inode(inode, inode->i_mode, rdev); | 2157 | init_special_inode(inode, inode->i_mode, rdev); |
| 2157 | break; | 2158 | break; |
| 2158 | } | 2159 | } |
| 2160 | |||
| 2161 | btrfs_update_iflags(inode); | ||
| 2159 | return; | 2162 | return; |
| 2160 | 2163 | ||
| 2161 | make_bad: | 2164 | make_bad: |
| @@ -3586,9 +3589,9 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
| 3586 | btrfs_find_block_group(root, 0, alloc_hint, owner); | 3589 | btrfs_find_block_group(root, 0, alloc_hint, owner); |
| 3587 | if ((mode & S_IFREG)) { | 3590 | if ((mode & S_IFREG)) { |
| 3588 | if (btrfs_test_opt(root, NODATASUM)) | 3591 | if (btrfs_test_opt(root, NODATASUM)) |
| 3589 | btrfs_set_flag(inode, NODATASUM); | 3592 | BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM; |
| 3590 | if (btrfs_test_opt(root, NODATACOW)) | 3593 | if (btrfs_test_opt(root, NODATACOW)) |
| 3591 | btrfs_set_flag(inode, NODATACOW); | 3594 | BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW; |
| 3592 | } | 3595 | } |
| 3593 | 3596 | ||
| 3594 | key[0].objectid = objectid; | 3597 | key[0].objectid = objectid; |
| @@ -3642,6 +3645,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
| 3642 | location->offset = 0; | 3645 | location->offset = 0; |
| 3643 | btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY); | 3646 | btrfs_set_key_type(location, BTRFS_INODE_ITEM_KEY); |
| 3644 | 3647 | ||
| 3648 | btrfs_inherit_iflags(inode, dir); | ||
| 3649 | |||
| 3645 | insert_inode_hash(inode); | 3650 | insert_inode_hash(inode); |
| 3646 | inode_tree_add(inode); | 3651 | inode_tree_add(inode); |
| 3647 | return inode; | 3652 | return inode; |
| @@ -5075,7 +5080,7 @@ static int prealloc_file_range(struct btrfs_trans_handle *trans, | |||
| 5075 | out: | 5080 | out: |
| 5076 | if (cur_offset > start) { | 5081 | if (cur_offset > start) { |
| 5077 | inode->i_ctime = CURRENT_TIME; | 5082 | inode->i_ctime = CURRENT_TIME; |
| 5078 | btrfs_set_flag(inode, PREALLOC); | 5083 | BTRFS_I(inode)->flags |= BTRFS_INODE_PREALLOC; |
| 5079 | if (!(mode & FALLOC_FL_KEEP_SIZE) && | 5084 | if (!(mode & FALLOC_FL_KEEP_SIZE) && |
| 5080 | cur_offset > i_size_read(inode)) | 5085 | cur_offset > i_size_read(inode)) |
| 5081 | btrfs_i_size_write(inode, cur_offset); | 5086 | btrfs_i_size_write(inode, cur_offset); |
| @@ -5196,7 +5201,7 @@ static int btrfs_set_page_dirty(struct page *page) | |||
| 5196 | 5201 | ||
| 5197 | static int btrfs_permission(struct inode *inode, int mask) | 5202 | static int btrfs_permission(struct inode *inode, int mask) |
| 5198 | { | 5203 | { |
| 5199 | if (btrfs_test_flag(inode, READONLY) && (mask & MAY_WRITE)) | 5204 | if ((BTRFS_I(inode)->flags & BTRFS_INODE_READONLY) && (mask & MAY_WRITE)) |
| 5200 | return -EACCES; | 5205 | return -EACCES; |
| 5201 | return generic_permission(inode, mask, btrfs_check_acl); | 5206 | return generic_permission(inode, mask, btrfs_check_acl); |
| 5202 | } | 5207 | } |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 54dfd45cc59..926332a73cd 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -50,7 +50,172 @@ | |||
| 50 | #include "volumes.h" | 50 | #include "volumes.h" |
| 51 | #include "locking.h" | 51 | #include "locking.h" |
| 52 | 52 | ||
| 53 | /* Mask out flags that are inappropriate for the given type of inode. */ | ||
| 54 | static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) | ||
| 55 | { | ||
| 56 | if (S_ISDIR(mode)) | ||
| 57 | return flags; | ||
| 58 | else if (S_ISREG(mode)) | ||
| 59 | return flags & ~FS_DIRSYNC_FL; | ||
| 60 | else | ||
| 61 | return flags & (FS_NODUMP_FL | FS_NOATIME_FL); | ||
| 62 | } | ||
| 63 | |||
| 64 | /* | ||
| 65 | * Export inode flags to the format expected by the FS_IOC_GETFLAGS ioctl. | ||
| 66 | */ | ||
| 67 | static unsigned int btrfs_flags_to_ioctl(unsigned int flags) | ||
| 68 | { | ||
| 69 | unsigned int iflags = 0; | ||
| 70 | |||
| 71 | if (flags & BTRFS_INODE_SYNC) | ||
| 72 | iflags |= FS_SYNC_FL; | ||
| 73 | if (flags & BTRFS_INODE_IMMUTABLE) | ||
| 74 | iflags |= FS_IMMUTABLE_FL; | ||
| 75 | if (flags & BTRFS_INODE_APPEND) | ||
| 76 | iflags |= FS_APPEND_FL; | ||
| 77 | if (flags & BTRFS_INODE_NODUMP) | ||
| 78 | iflags |= FS_NODUMP_FL; | ||
| 79 | if (flags & BTRFS_INODE_NOATIME) | ||
| 80 | iflags |= FS_NOATIME_FL; | ||
| 81 | if (flags & BTRFS_INODE_DIRSYNC) | ||
| 82 | iflags |= FS_DIRSYNC_FL; | ||
| 83 | |||
| 84 | return iflags; | ||
| 85 | } | ||
| 86 | |||
| 87 | /* | ||
| 88 | * Update inode->i_flags based on the btrfs internal flags. | ||
| 89 | */ | ||
| 90 | void btrfs_update_iflags(struct inode *inode) | ||
| 91 | { | ||
| 92 | struct btrfs_inode *ip = BTRFS_I(inode); | ||
| 93 | |||
| 94 | inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC); | ||
| 95 | |||
| 96 | if (ip->flags & BTRFS_INODE_SYNC) | ||
| 97 | inode->i_flags |= S_SYNC; | ||
| 98 | if (ip->flags & BTRFS_INODE_IMMUTABLE) | ||
| 99 | inode->i_flags |= S_IMMUTABLE; | ||
| 100 | if (ip->flags & BTRFS_INODE_APPEND) | ||
| 101 | inode->i_flags |= S_APPEND; | ||
| 102 | if (ip->flags & BTRFS_INODE_NOATIME) | ||
| 103 | inode->i_flags |= S_NOATIME; | ||
| 104 | if (ip->flags & BTRFS_INODE_DIRSYNC) | ||
| 105 | inode->i_flags |= S_DIRSYNC; | ||
| 106 | } | ||
| 107 | |||
| 108 | /* | ||
| 109 | * Inherit flags from the parent inode. | ||
| 110 | * | ||
| 111 | * Unlike extN we don't have any flags we don't want to inherit currently. | ||
| 112 | */ | ||
| 113 | void btrfs_inherit_iflags(struct inode *inode, struct inode *dir) | ||
| 114 | { | ||
| 115 | unsigned int flags = BTRFS_I(dir)->flags; | ||
| 116 | |||
| 117 | if (S_ISREG(inode->i_mode)) | ||
| 118 | flags &= ~BTRFS_INODE_DIRSYNC; | ||
| 119 | else if (!S_ISDIR(inode->i_mode)) | ||
| 120 | flags &= (BTRFS_INODE_NODUMP | BTRFS_INODE_NOATIME); | ||
| 121 | |||
| 122 | BTRFS_I(inode)->flags = flags; | ||
| 123 | btrfs_update_iflags(inode); | ||
| 124 | } | ||
| 125 | |||
| 126 | static int btrfs_ioctl_getflags(struct file *file, void __user *arg) | ||
| 127 | { | ||
| 128 | struct btrfs_inode *ip = BTRFS_I(file->f_path.dentry->d_inode); | ||
| 129 | unsigned int flags = btrfs_flags_to_ioctl(ip->flags); | ||
| 130 | |||
| 131 | if (copy_to_user(arg, &flags, sizeof(flags))) | ||
| 132 | return -EFAULT; | ||
| 133 | return 0; | ||
| 134 | } | ||
| 135 | |||
| 136 | static int btrfs_ioctl_setflags(struct file *file, void __user *arg) | ||
| 137 | { | ||
| 138 | struct inode *inode = file->f_path.dentry->d_inode; | ||
| 139 | struct btrfs_inode *ip = BTRFS_I(inode); | ||
| 140 | struct btrfs_root *root = ip->root; | ||
| 141 | struct btrfs_trans_handle *trans; | ||
| 142 | unsigned int flags, oldflags; | ||
| 143 | int ret; | ||
| 144 | |||
| 145 | if (copy_from_user(&flags, arg, sizeof(flags))) | ||
| 146 | return -EFAULT; | ||
| 147 | |||
| 148 | if (flags & ~(FS_IMMUTABLE_FL | FS_APPEND_FL | \ | ||
| 149 | FS_NOATIME_FL | FS_NODUMP_FL | \ | ||
| 150 | FS_SYNC_FL | FS_DIRSYNC_FL)) | ||
| 151 | return -EOPNOTSUPP; | ||
| 53 | 152 | ||
| 153 | if (!is_owner_or_cap(inode)) | ||
| 154 | return -EACCES; | ||
| 155 | |||
| 156 | mutex_lock(&inode->i_mutex); | ||
| 157 | |||
| 158 | flags = btrfs_mask_flags(inode->i_mode, flags); | ||
| 159 | oldflags = btrfs_flags_to_ioctl(ip->flags); | ||
| 160 | if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) { | ||
| 161 | if (!capable(CAP_LINUX_IMMUTABLE)) { | ||
| 162 | ret = -EPERM; | ||
| 163 | goto out_unlock; | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | ret = mnt_want_write(file->f_path.mnt); | ||
| 168 | if (ret) | ||
| 169 | goto out_unlock; | ||
| 170 | |||
| 171 | if (flags & FS_SYNC_FL) | ||
| 172 | ip->flags |= BTRFS_INODE_SYNC; | ||
| 173 | else | ||
| 174 | ip->flags &= ~BTRFS_INODE_SYNC; | ||
| 175 | if (flags & FS_IMMUTABLE_FL) | ||
| 176 | ip->flags |= BTRFS_INODE_IMMUTABLE; | ||
| 177 | else | ||
| 178 | ip->flags &= ~BTRFS_INODE_IMMUTABLE; | ||
| 179 | if (flags & FS_APPEND_FL) | ||
| 180 | ip->flags |= BTRFS_INODE_APPEND; | ||
| 181 | else | ||
| 182 | ip->flags &= ~BTRFS_INODE_APPEND; | ||
| 183 | if (flags & FS_NODUMP_FL) | ||
| 184 | ip->flags |= BTRFS_INODE_NODUMP; | ||
| 185 | else | ||
| 186 | ip->flags &= ~BTRFS_INODE_NODUMP; | ||
| 187 | if (flags & FS_NOATIME_FL) | ||
| 188 | ip->flags |= BTRFS_INODE_NOATIME; | ||
| 189 | else | ||
| 190 | ip->flags &= ~BTRFS_INODE_NOATIME; | ||
| 191 | if (flags & FS_DIRSYNC_FL) | ||
| 192 | ip->flags |= BTRFS_INODE_DIRSYNC; | ||
| 193 | else | ||
| 194 | ip->flags &= ~BTRFS_INODE_DIRSYNC; | ||
| 195 | |||
| 196 | |||
| 197 | trans = btrfs_join_transaction(root, 1); | ||
| 198 | BUG_ON(!trans); | ||
| 199 | |||
| 200 | ret = btrfs_update_inode(trans, root, inode); | ||
| 201 | BUG_ON(ret); | ||
| 202 | |||
| 203 | btrfs_update_iflags(inode); | ||
| 204 | inode->i_ctime = CURRENT_TIME; | ||
| 205 | btrfs_end_transaction(trans, root); | ||
| 206 | |||
| 207 | mnt_drop_write(file->f_path.mnt); | ||
| 208 | out_unlock: | ||
| 209 | mutex_unlock(&inode->i_mutex); | ||
| 210 | return 0; | ||
| 211 | } | ||
| 212 | |||
| 213 | static int btrfs_ioctl_getversion(struct file *file, int __user *arg) | ||
| 214 | { | ||
| 215 | struct inode *inode = file->f_path.dentry->d_inode; | ||
| 216 | |||
| 217 | return put_user(inode->i_generation, arg); | ||
| 218 | } | ||
| 54 | 219 | ||
| 55 | static noinline int create_subvol(struct btrfs_root *root, | 220 | static noinline int create_subvol(struct btrfs_root *root, |
| 56 | struct dentry *dentry, | 221 | struct dentry *dentry, |
| @@ -1077,6 +1242,12 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
| 1077 | void __user *argp = (void __user *)arg; | 1242 | void __user *argp = (void __user *)arg; |
| 1078 | 1243 | ||
| 1079 | switch (cmd) { | 1244 | switch (cmd) { |
| 1245 | case FS_IOC_GETFLAGS: | ||
| 1246 | return btrfs_ioctl_getflags(file, argp); | ||
| 1247 | case FS_IOC_SETFLAGS: | ||
| 1248 | return btrfs_ioctl_setflags(file, argp); | ||
| 1249 | case FS_IOC_GETVERSION: | ||
| 1250 | return btrfs_ioctl_getversion(file, argp); | ||
| 1080 | case BTRFS_IOC_SNAP_CREATE: | 1251 | case BTRFS_IOC_SNAP_CREATE: |
| 1081 | return btrfs_ioctl_snap_create(file, argp, 0); | 1252 | return btrfs_ioctl_snap_create(file, argp, 0); |
| 1082 | case BTRFS_IOC_SUBVOL_CREATE: | 1253 | case BTRFS_IOC_SUBVOL_CREATE: |
