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 | |
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')
-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 ecf5f7d8166f..acb4f3517582 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 ab07627084f1..de1e2fd32080 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 5fa7d7d287a4..4d6e0b6f21ea 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 917bf10597c6..5b68330f8585 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 54dfd45cc591..926332a73cde 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: |