diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-03-27 13:42:32 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-03-27 13:42:32 -0400 |
commit | 5f443fd280c76a2170259cebaa4108c9daad6e1b (patch) | |
tree | 7c0f8747aaa8f8b7e18d6d8bdc18a4c58e3af536 /fs | |
parent | 9773a788681db1f5c2701b7433737fdca61a14ba (diff) |
btrfs_rmdir
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/super.c | 106 |
1 files changed, 93 insertions, 13 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index f2f08189903d..67659b6ce962 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -81,11 +81,12 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
81 | return; | 81 | return; |
82 | } | 82 | } |
83 | 83 | ||
84 | static int btrfs_unlink(struct inode *dir, struct dentry *dentry) | 84 | static int btrfs_unlink_trans(struct btrfs_trans_handle *trans, |
85 | struct btrfs_root *root, | ||
86 | struct inode *dir, | ||
87 | struct dentry *dentry) | ||
85 | { | 88 | { |
86 | struct btrfs_path path; | 89 | struct btrfs_path path; |
87 | struct btrfs_root *root; | ||
88 | struct btrfs_trans_handle *trans; | ||
89 | const char *name = dentry->d_name.name; | 90 | const char *name = dentry->d_name.name; |
90 | int name_len = dentry->d_name.len; | 91 | int name_len = dentry->d_name.len; |
91 | int ret; | 92 | int ret; |
@@ -93,10 +94,6 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry) | |||
93 | struct btrfs_dir_item *di; | 94 | struct btrfs_dir_item *di; |
94 | 95 | ||
95 | btrfs_init_path(&path); | 96 | btrfs_init_path(&path); |
96 | root = btrfs_sb(dir->i_sb); | ||
97 | mutex_lock(&root->fs_info->fs_mutex); | ||
98 | trans = btrfs_start_transaction(root, 1); | ||
99 | |||
100 | ret = btrfs_lookup_dir_item(trans, root, &path, dir->i_ino, | 97 | ret = btrfs_lookup_dir_item(trans, root, &path, dir->i_ino, |
101 | name, name_len, -1); | 98 | name, name_len, -1); |
102 | if (ret < 0) | 99 | if (ret < 0) |
@@ -114,13 +111,98 @@ static int btrfs_unlink(struct inode *dir, struct dentry *dentry) | |||
114 | dentry->d_inode->i_ctime = dir->i_ctime; | 111 | dentry->d_inode->i_ctime = dir->i_ctime; |
115 | err: | 112 | err: |
116 | btrfs_release_path(root, &path); | 113 | btrfs_release_path(root, &path); |
117 | btrfs_end_transaction(trans, root); | ||
118 | mutex_unlock(&root->fs_info->fs_mutex); | ||
119 | if (ret == 0) | 114 | if (ret == 0) |
120 | inode_dec_link_count(dentry->d_inode); | 115 | inode_dec_link_count(dentry->d_inode); |
121 | return ret; | 116 | return ret; |
122 | } | 117 | } |
123 | 118 | ||
119 | static int btrfs_unlink(struct inode *dir, struct dentry *dentry) | ||
120 | { | ||
121 | struct btrfs_root *root; | ||
122 | struct btrfs_trans_handle *trans; | ||
123 | int ret; | ||
124 | |||
125 | root = btrfs_sb(dir->i_sb); | ||
126 | mutex_lock(&root->fs_info->fs_mutex); | ||
127 | trans = btrfs_start_transaction(root, 1); | ||
128 | ret = btrfs_unlink_trans(trans, root, dir, dentry); | ||
129 | btrfs_end_transaction(trans, root); | ||
130 | mutex_unlock(&root->fs_info->fs_mutex); | ||
131 | return ret; | ||
132 | } | ||
133 | |||
134 | static int btrfs_rmdir(struct inode *dir, struct dentry *dentry) | ||
135 | { | ||
136 | struct inode *inode = dentry->d_inode; | ||
137 | int err; | ||
138 | int ret; | ||
139 | struct btrfs_root *root = btrfs_sb(dir->i_sb); | ||
140 | struct btrfs_path path; | ||
141 | struct btrfs_key key; | ||
142 | struct btrfs_trans_handle *trans; | ||
143 | struct btrfs_disk_key *found_key; | ||
144 | struct btrfs_leaf *leaf; | ||
145 | |||
146 | btrfs_init_path(&path); | ||
147 | mutex_lock(&root->fs_info->fs_mutex); | ||
148 | trans = btrfs_start_transaction(root, 1); | ||
149 | key.objectid = inode->i_ino; | ||
150 | key.offset = (u64)-1; | ||
151 | key.flags = 0; | ||
152 | btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY); | ||
153 | ret = btrfs_search_slot(trans, root, &key, &path, -1, 1); | ||
154 | if (ret < 0) { | ||
155 | err = ret; | ||
156 | goto out; | ||
157 | } | ||
158 | |||
159 | BUG_ON(ret == 0); | ||
160 | BUG_ON(path.slots[0] == 0); | ||
161 | path.slots[0]--; | ||
162 | leaf = btrfs_buffer_leaf(path.nodes[0]); | ||
163 | found_key = &leaf->items[path.slots[0]].key; | ||
164 | if (btrfs_disk_key_objectid(found_key) != inode->i_ino) { | ||
165 | err = -ENOENT; | ||
166 | goto out; | ||
167 | } | ||
168 | if (btrfs_disk_key_type(found_key) != BTRFS_DIR_ITEM_KEY || | ||
169 | btrfs_disk_key_offset(found_key) != 2) { | ||
170 | err = -ENOTEMPTY; | ||
171 | goto out; | ||
172 | } | ||
173 | ret = btrfs_del_item(trans, root, &path); | ||
174 | BUG_ON(ret); | ||
175 | btrfs_release_path(root, &path); | ||
176 | key.offset = 1; | ||
177 | ret = btrfs_search_slot(trans, root, &key, &path, -1, 1); | ||
178 | if (ret < 0) { | ||
179 | err = ret; | ||
180 | goto out; | ||
181 | } | ||
182 | if (ret > 0) { | ||
183 | err = -ENOTEMPTY; | ||
184 | goto out; | ||
185 | } | ||
186 | ret = btrfs_del_item(trans, root, &path); | ||
187 | if (ret) { | ||
188 | err = ret; | ||
189 | goto out; | ||
190 | } | ||
191 | btrfs_release_path(root, &path); | ||
192 | |||
193 | /* now the directory is empty */ | ||
194 | err = btrfs_unlink_trans(trans, root, dir, dentry); | ||
195 | if (!err) { | ||
196 | inode->i_size = 0; | ||
197 | } | ||
198 | out: | ||
199 | mutex_unlock(&root->fs_info->fs_mutex); | ||
200 | ret = btrfs_end_transaction(trans, root); | ||
201 | if (ret && !err) | ||
202 | err = ret; | ||
203 | return err; | ||
204 | } | ||
205 | |||
124 | static int btrfs_free_inode(struct btrfs_trans_handle *trans, | 206 | static int btrfs_free_inode(struct btrfs_trans_handle *trans, |
125 | struct btrfs_root *root, | 207 | struct btrfs_root *root, |
126 | struct inode *inode) | 208 | struct inode *inode) |
@@ -193,9 +275,6 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
193 | break; | 275 | break; |
194 | if (btrfs_disk_key_offset(found_key) < inode->i_size) | 276 | if (btrfs_disk_key_offset(found_key) < inode->i_size) |
195 | break; | 277 | 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]), | 278 | fi = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), |
200 | path.slots[0], | 279 | path.slots[0], |
201 | struct btrfs_file_extent_item); | 280 | struct btrfs_file_extent_item); |
@@ -209,7 +288,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
209 | ret = btrfs_free_extent(trans, root, extent_start, | 288 | ret = btrfs_free_extent(trans, root, extent_start, |
210 | extent_num_blocks, 0); | 289 | extent_num_blocks, 0); |
211 | BUG_ON(ret); | 290 | BUG_ON(ret); |
212 | if (btrfs_disk_key_offset(found_key) == 0) | 291 | if (key.offset + 1 == 0) |
213 | break; | 292 | break; |
214 | } | 293 | } |
215 | btrfs_release_path(root, &path); | 294 | btrfs_release_path(root, &path); |
@@ -852,6 +931,7 @@ static struct inode_operations btrfs_dir_inode_operations = { | |||
852 | .create = btrfs_create, | 931 | .create = btrfs_create, |
853 | .unlink = btrfs_unlink, | 932 | .unlink = btrfs_unlink, |
854 | .mkdir = btrfs_mkdir, | 933 | .mkdir = btrfs_mkdir, |
934 | .rmdir = btrfs_rmdir, | ||
855 | }; | 935 | }; |
856 | 936 | ||
857 | static struct file_operations btrfs_dir_file_operations = { | 937 | static struct file_operations btrfs_dir_file_operations = { |