aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/export.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/btrfs/export.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'fs/btrfs/export.c')
-rw-r--r--fs/btrfs/export.c107
1 files changed, 92 insertions, 15 deletions
diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c
index 951ef09b82f4..1b8dc33778f9 100644
--- a/fs/btrfs/export.c
+++ b/fs/btrfs/export.c
@@ -21,14 +21,18 @@ static int btrfs_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
21 int len = *max_len; 21 int len = *max_len;
22 int type; 22 int type;
23 23
24 if ((len < BTRFS_FID_SIZE_NON_CONNECTABLE) || 24 if (connectable && (len < BTRFS_FID_SIZE_CONNECTABLE)) {
25 (connectable && len < BTRFS_FID_SIZE_CONNECTABLE)) 25 *max_len = BTRFS_FID_SIZE_CONNECTABLE;
26 return 255; 26 return 255;
27 } else if (len < BTRFS_FID_SIZE_NON_CONNECTABLE) {
28 *max_len = BTRFS_FID_SIZE_NON_CONNECTABLE;
29 return 255;
30 }
27 31
28 len = BTRFS_FID_SIZE_NON_CONNECTABLE; 32 len = BTRFS_FID_SIZE_NON_CONNECTABLE;
29 type = FILEID_BTRFS_WITHOUT_PARENT; 33 type = FILEID_BTRFS_WITHOUT_PARENT;
30 34
31 fid->objectid = inode->i_ino; 35 fid->objectid = btrfs_ino(inode);
32 fid->root_objectid = BTRFS_I(inode)->root->objectid; 36 fid->root_objectid = BTRFS_I(inode)->root->objectid;
33 fid->gen = inode->i_generation; 37 fid->gen = inode->i_generation;
34 38
@@ -65,7 +69,6 @@ static struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid,
65{ 69{
66 struct btrfs_fs_info *fs_info = btrfs_sb(sb)->fs_info; 70 struct btrfs_fs_info *fs_info = btrfs_sb(sb)->fs_info;
67 struct btrfs_root *root; 71 struct btrfs_root *root;
68 struct dentry *dentry;
69 struct inode *inode; 72 struct inode *inode;
70 struct btrfs_key key; 73 struct btrfs_key key;
71 int index; 74 int index;
@@ -108,10 +111,7 @@ static struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid,
108 return ERR_PTR(-ESTALE); 111 return ERR_PTR(-ESTALE);
109 } 112 }
110 113
111 dentry = d_obtain_alias(inode); 114 return d_obtain_alias(inode);
112 if (!IS_ERR(dentry))
113 dentry->d_op = &btrfs_dentry_operations;
114 return dentry;
115fail: 115fail:
116 srcu_read_unlock(&fs_info->subvol_srcu, index); 116 srcu_read_unlock(&fs_info->subvol_srcu, index);
117 return ERR_PTR(err); 117 return ERR_PTR(err);
@@ -166,7 +166,6 @@ static struct dentry *btrfs_fh_to_dentry(struct super_block *sb, struct fid *fh,
166static struct dentry *btrfs_get_parent(struct dentry *child) 166static struct dentry *btrfs_get_parent(struct dentry *child)
167{ 167{
168 struct inode *dir = child->d_inode; 168 struct inode *dir = child->d_inode;
169 static struct dentry *dentry;
170 struct btrfs_root *root = BTRFS_I(dir)->root; 169 struct btrfs_root *root = BTRFS_I(dir)->root;
171 struct btrfs_path *path; 170 struct btrfs_path *path;
172 struct extent_buffer *leaf; 171 struct extent_buffer *leaf;
@@ -176,14 +175,16 @@ static struct dentry *btrfs_get_parent(struct dentry *child)
176 int ret; 175 int ret;
177 176
178 path = btrfs_alloc_path(); 177 path = btrfs_alloc_path();
178 if (!path)
179 return ERR_PTR(-ENOMEM);
179 180
180 if (dir->i_ino == BTRFS_FIRST_FREE_OBJECTID) { 181 if (btrfs_ino(dir) == BTRFS_FIRST_FREE_OBJECTID) {
181 key.objectid = root->root_key.objectid; 182 key.objectid = root->root_key.objectid;
182 key.type = BTRFS_ROOT_BACKREF_KEY; 183 key.type = BTRFS_ROOT_BACKREF_KEY;
183 key.offset = (u64)-1; 184 key.offset = (u64)-1;
184 root = root->fs_info->tree_root; 185 root = root->fs_info->tree_root;
185 } else { 186 } else {
186 key.objectid = dir->i_ino; 187 key.objectid = btrfs_ino(dir);
187 key.type = BTRFS_INODE_REF_KEY; 188 key.type = BTRFS_INODE_REF_KEY;
188 key.offset = (u64)-1; 189 key.offset = (u64)-1;
189 } 190 }
@@ -223,18 +224,94 @@ static struct dentry *btrfs_get_parent(struct dentry *child)
223 224
224 key.type = BTRFS_INODE_ITEM_KEY; 225 key.type = BTRFS_INODE_ITEM_KEY;
225 key.offset = 0; 226 key.offset = 0;
226 dentry = d_obtain_alias(btrfs_iget(root->fs_info->sb, &key, root, NULL)); 227 return d_obtain_alias(btrfs_iget(root->fs_info->sb, &key, root, NULL));
227 if (!IS_ERR(dentry))
228 dentry->d_op = &btrfs_dentry_operations;
229 return dentry;
230fail: 228fail:
231 btrfs_free_path(path); 229 btrfs_free_path(path);
232 return ERR_PTR(ret); 230 return ERR_PTR(ret);
233} 231}
234 232
233static int btrfs_get_name(struct dentry *parent, char *name,
234 struct dentry *child)
235{
236 struct inode *inode = child->d_inode;
237 struct inode *dir = parent->d_inode;
238 struct btrfs_path *path;
239 struct btrfs_root *root = BTRFS_I(dir)->root;
240 struct btrfs_inode_ref *iref;
241 struct btrfs_root_ref *rref;
242 struct extent_buffer *leaf;
243 unsigned long name_ptr;
244 struct btrfs_key key;
245 int name_len;
246 int ret;
247 u64 ino;
248
249 if (!dir || !inode)
250 return -EINVAL;
251
252 if (!S_ISDIR(dir->i_mode))
253 return -EINVAL;
254
255 ino = btrfs_ino(inode);
256
257 path = btrfs_alloc_path();
258 if (!path)
259 return -ENOMEM;
260 path->leave_spinning = 1;
261
262 if (ino == BTRFS_FIRST_FREE_OBJECTID) {
263 key.objectid = BTRFS_I(inode)->root->root_key.objectid;
264 key.type = BTRFS_ROOT_BACKREF_KEY;
265 key.offset = (u64)-1;
266 root = root->fs_info->tree_root;
267 } else {
268 key.objectid = ino;
269 key.offset = btrfs_ino(dir);
270 key.type = BTRFS_INODE_REF_KEY;
271 }
272
273 ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
274 if (ret < 0) {
275 btrfs_free_path(path);
276 return ret;
277 } else if (ret > 0) {
278 if (ino == BTRFS_FIRST_FREE_OBJECTID) {
279 path->slots[0]--;
280 } else {
281 btrfs_free_path(path);
282 return -ENOENT;
283 }
284 }
285 leaf = path->nodes[0];
286
287 if (ino == BTRFS_FIRST_FREE_OBJECTID) {
288 rref = btrfs_item_ptr(leaf, path->slots[0],
289 struct btrfs_root_ref);
290 name_ptr = (unsigned long)(rref + 1);
291 name_len = btrfs_root_ref_name_len(leaf, rref);
292 } else {
293 iref = btrfs_item_ptr(leaf, path->slots[0],
294 struct btrfs_inode_ref);
295 name_ptr = (unsigned long)(iref + 1);
296 name_len = btrfs_inode_ref_name_len(leaf, iref);
297 }
298
299 read_extent_buffer(leaf, name, name_ptr, name_len);
300 btrfs_free_path(path);
301
302 /*
303 * have to add the null termination to make sure that reconnect_path
304 * gets the right len for strlen
305 */
306 name[name_len] = '\0';
307
308 return 0;
309}
310
235const struct export_operations btrfs_export_ops = { 311const struct export_operations btrfs_export_ops = {
236 .encode_fh = btrfs_encode_fh, 312 .encode_fh = btrfs_encode_fh,
237 .fh_to_dentry = btrfs_fh_to_dentry, 313 .fh_to_dentry = btrfs_fh_to_dentry,
238 .fh_to_parent = btrfs_fh_to_parent, 314 .fh_to_parent = btrfs_fh_to_parent,
239 .get_parent = btrfs_get_parent, 315 .get_parent = btrfs_get_parent,
316 .get_name = btrfs_get_name,
240}; 317};