aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-03-27 13:42:32 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-03-27 13:42:32 -0400
commit5f443fd280c76a2170259cebaa4108c9daad6e1b (patch)
tree7c0f8747aaa8f8b7e18d6d8bdc18a4c58e3af536 /fs
parent9773a788681db1f5c2701b7433737fdca61a14ba (diff)
btrfs_rmdir
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/super.c106
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
84static int btrfs_unlink(struct inode *dir, struct dentry *dentry) 84static 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;
115err: 112err:
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
119static 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
134static 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 }
198out:
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
124static int btrfs_free_inode(struct btrfs_trans_handle *trans, 206static 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
857static struct file_operations btrfs_dir_file_operations = { 937static struct file_operations btrfs_dir_file_operations = {