aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r--fs/btrfs/super.c107
1 files changed, 101 insertions, 6 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 487da5a213c0..fd3d9d616ff9 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -28,11 +28,15 @@ static void btrfs_read_locked_inode(struct inode *inode)
28 struct btrfs_inode_item *inode_item; 28 struct btrfs_inode_item *inode_item;
29 struct btrfs_root *root = btrfs_sb(inode->i_sb); 29 struct btrfs_root *root = btrfs_sb(inode->i_sb);
30 int ret; 30 int ret;
31
31 btrfs_init_path(&path); 32 btrfs_init_path(&path);
33 mutex_lock(&root->fs_info->fs_mutex);
34
32 ret = btrfs_lookup_inode(NULL, root, &path, inode->i_ino, 0); 35 ret = btrfs_lookup_inode(NULL, root, &path, inode->i_ino, 0);
33 if (ret) { 36 if (ret) {
34 make_bad_inode(inode);
35 btrfs_release_path(root, &path); 37 btrfs_release_path(root, &path);
38 mutex_unlock(&root->fs_info->fs_mutex);
39 make_bad_inode(inode);
36 return; 40 return;
37 } 41 }
38 inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), 42 inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]),
@@ -53,6 +57,7 @@ static void btrfs_read_locked_inode(struct inode *inode)
53 inode->i_blocks = btrfs_inode_nblocks(inode_item); 57 inode->i_blocks = btrfs_inode_nblocks(inode_item);
54 inode->i_generation = btrfs_inode_generation(inode_item); 58 inode->i_generation = btrfs_inode_generation(inode_item);
55 btrfs_release_path(root, &path); 59 btrfs_release_path(root, &path);
60 mutex_unlock(&root->fs_info->fs_mutex);
56 switch (inode->i_mode & S_IFMT) { 61 switch (inode->i_mode & S_IFMT) {
57#if 0 62#if 0
58 default: 63 default:
@@ -151,20 +156,85 @@ error:
151 return ret; 156 return ret;
152} 157}
153 158
159static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans,
160 struct btrfs_root *root,
161 struct inode *inode)
162{
163 int ret;
164 struct btrfs_path path;
165 struct btrfs_key key;
166 struct btrfs_disk_key *found_key;
167 struct btrfs_leaf *leaf;
168 struct btrfs_file_extent_item *fi;
169 u64 extent_start;
170 u64 extent_num_blocks;
171
172 /* FIXME, add redo link to tree so we don't leak on crash */
173 key.objectid = inode->i_ino;
174 key.offset = (u64)-1;
175 key.flags = 0;
176 btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY);
177 while(1) {
178 btrfs_init_path(&path);
179 ret = btrfs_search_slot(trans, root, &key, &path, -1, 1);
180 if (ret < 0) {
181 btrfs_release_path(root, &path);
182 goto error;
183 }
184 if (ret > 0) {
185 BUG_ON(path.slots[0] == 0);
186 path.slots[0]--;
187 }
188 leaf = btrfs_buffer_leaf(path.nodes[0]);
189 found_key = &leaf->items[path.slots[0]].key;
190 if (btrfs_disk_key_objectid(found_key) != inode->i_ino)
191 break;
192 if (btrfs_disk_key_type(found_key) != BTRFS_EXTENT_DATA_KEY)
193 break;
194 if (btrfs_disk_key_offset(found_key) < inode->i_size)
195 break;
196 /* FIXME: add extent truncation */
197 if (btrfs_disk_key_offset(found_key) < inode->i_size)
198 break;
199 fi = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]),
200 path.slots[0],
201 struct btrfs_file_extent_item);
202 extent_start = btrfs_file_extent_disk_blocknr(fi);
203 extent_num_blocks = btrfs_file_extent_disk_num_blocks(fi);
204 key.offset = btrfs_disk_key_offset(found_key) - 1;
205 ret = btrfs_del_item(trans, root, &path);
206 BUG_ON(ret);
207 inode->i_blocks -= btrfs_file_extent_num_blocks(fi) >> 9;
208 btrfs_release_path(root, &path);
209 ret = btrfs_free_extent(trans, root, extent_start,
210 extent_num_blocks, 0);
211 BUG_ON(ret);
212 if (btrfs_disk_key_offset(found_key) == 0)
213 break;
214 }
215 btrfs_release_path(root, &path);
216 ret = 0;
217error:
218 return ret;
219}
220
154static void btrfs_delete_inode(struct inode *inode) 221static void btrfs_delete_inode(struct inode *inode)
155{ 222{
156 struct btrfs_trans_handle *trans; 223 struct btrfs_trans_handle *trans;
157 struct btrfs_root *root = btrfs_sb(inode->i_sb); 224 struct btrfs_root *root = btrfs_sb(inode->i_sb);
225 int ret;
226
158 truncate_inode_pages(&inode->i_data, 0); 227 truncate_inode_pages(&inode->i_data, 0);
159 if (is_bad_inode(inode)) { 228 if (is_bad_inode(inode)) {
160 goto no_delete; 229 goto no_delete;
161 } 230 }
162 inode->i_size = 0; 231 inode->i_size = 0;
163 if (inode->i_blocks)
164 WARN_ON(1);
165
166 mutex_lock(&root->fs_info->fs_mutex); 232 mutex_lock(&root->fs_info->fs_mutex);
167 trans = btrfs_start_transaction(root, 1); 233 trans = btrfs_start_transaction(root, 1);
234 if (S_ISREG(inode->i_mode)) {
235 ret = btrfs_truncate_in_trans(trans, root, inode);
236 BUG_ON(ret);
237 }
168 btrfs_free_inode(trans, root, inode); 238 btrfs_free_inode(trans, root, inode);
169 btrfs_end_transaction(trans, root); 239 btrfs_end_transaction(trans, root);
170 mutex_unlock(&root->fs_info->fs_mutex); 240 mutex_unlock(&root->fs_info->fs_mutex);
@@ -173,7 +243,6 @@ no_delete:
173 clear_inode(inode); 243 clear_inode(inode);
174} 244}
175 245
176
177static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry, 246static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry,
178 ino_t *ino) 247 ino_t *ino)
179{ 248{
@@ -688,6 +757,8 @@ allocate:
688 err = ret; 757 err = ret;
689 goto out; 758 goto out;
690 } 759 }
760 inode->i_blocks += inode->i_sb->s_blocksize >> 9;
761 set_buffer_new(result);
691 map_bh(result, inode->i_sb, blocknr); 762 map_bh(result, inode->i_sb, blocknr);
692 763
693out: 764out:
@@ -724,6 +795,30 @@ static int btrfs_writepage(struct page *page, struct writeback_control *wbc)
724 return nobh_writepage(page, btrfs_get_block, wbc); 795 return nobh_writepage(page, btrfs_get_block, wbc);
725} 796}
726 797
798static void btrfs_truncate(struct inode *inode)
799{
800 struct btrfs_root *root = btrfs_sb(inode->i_sb);
801 int ret;
802 struct btrfs_trans_handle *trans;
803
804 if (!S_ISREG(inode->i_mode))
805 return;
806 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
807 return;
808
809 nobh_truncate_page(inode->i_mapping, inode->i_size);
810
811 /* FIXME, add redo link to tree so we don't leak on crash */
812 mutex_lock(&root->fs_info->fs_mutex);
813 trans = btrfs_start_transaction(root, 1);
814 ret = btrfs_truncate_in_trans(trans, root, inode);
815 BUG_ON(ret);
816 ret = btrfs_end_transaction(trans, root);
817 BUG_ON(ret);
818 mutex_unlock(&root->fs_info->fs_mutex);
819 mark_inode_dirty(inode);
820}
821
727static int btrfs_get_sb(struct file_system_type *fs_type, 822static int btrfs_get_sb(struct file_system_type *fs_type,
728 int flags, const char *dev_name, void *data, struct vfsmount *mnt) 823 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
729{ 824{
@@ -772,7 +867,7 @@ static struct address_space_operations btrfs_aops = {
772}; 867};
773 868
774static struct inode_operations btrfs_file_inode_operations = { 869static struct inode_operations btrfs_file_inode_operations = {
775 .truncate = NULL, 870 .truncate = btrfs_truncate,
776}; 871};
777 872
778static struct file_operations btrfs_file_operations = { 873static struct file_operations btrfs_file_operations = {