Blame view
fs/btrfs/export.c
7.17 KB
b24413180 License cleanup: ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
c1d7c514f btrfs: replace GP... |
2 |
|
be6e8dc0b NFS support for b... |
3 4 5 6 7 8 9 |
#include <linux/fs.h> #include <linux/types.h> #include "ctree.h" #include "disk-io.h" #include "btrfs_inode.h" #include "print-tree.h" #include "export.h" |
be6e8dc0b NFS support for b... |
10 |
|
d397712bc Btrfs: Fix checkp... |
11 12 13 14 15 |
#define BTRFS_FID_SIZE_NON_CONNECTABLE (offsetof(struct btrfs_fid, \ parent_objectid) / 4) #define BTRFS_FID_SIZE_CONNECTABLE (offsetof(struct btrfs_fid, \ parent_root_objectid) / 4) #define BTRFS_FID_SIZE_CONNECTABLE_ROOT (sizeof(struct btrfs_fid) / 4) |
be6e8dc0b NFS support for b... |
16 |
|
b0b0382bb ->encode_fh() API... |
17 18 |
static int btrfs_encode_fh(struct inode *inode, u32 *fh, int *max_len, struct inode *parent) |
be6e8dc0b NFS support for b... |
19 20 |
{ struct btrfs_fid *fid = (struct btrfs_fid *)fh; |
be6e8dc0b NFS support for b... |
21 22 |
int len = *max_len; int type; |
b0b0382bb ->encode_fh() API... |
23 |
if (parent && (len < BTRFS_FID_SIZE_CONNECTABLE)) { |
5fe0c2378 exportfs: Return ... |
24 |
*max_len = BTRFS_FID_SIZE_CONNECTABLE; |
94e07a759 fs: encode_fh: re... |
25 |
return FILEID_INVALID; |
5fe0c2378 exportfs: Return ... |
26 27 |
} else if (len < BTRFS_FID_SIZE_NON_CONNECTABLE) { *max_len = BTRFS_FID_SIZE_NON_CONNECTABLE; |
94e07a759 fs: encode_fh: re... |
28 |
return FILEID_INVALID; |
5fe0c2378 exportfs: Return ... |
29 |
} |
be6e8dc0b NFS support for b... |
30 31 32 |
len = BTRFS_FID_SIZE_NON_CONNECTABLE; type = FILEID_BTRFS_WITHOUT_PARENT; |
4a0cc7ca6 btrfs: Make btrfs... |
33 |
fid->objectid = btrfs_ino(BTRFS_I(inode)); |
4fd786e6c btrfs: Remove 'ob... |
34 |
fid->root_objectid = BTRFS_I(inode)->root->root_key.objectid; |
be6e8dc0b NFS support for b... |
35 |
fid->gen = inode->i_generation; |
b0b0382bb ->encode_fh() API... |
36 |
if (parent) { |
be6e8dc0b NFS support for b... |
37 |
u64 parent_root_id; |
be6e8dc0b NFS support for b... |
38 39 |
fid->parent_objectid = BTRFS_I(parent)->location.objectid; fid->parent_gen = parent->i_generation; |
4fd786e6c btrfs: Remove 'ob... |
40 |
parent_root_id = BTRFS_I(parent)->root->root_key.objectid; |
be6e8dc0b NFS support for b... |
41 |
|
be6e8dc0b NFS support for b... |
42 43 44 45 46 47 48 49 50 51 52 53 54 |
if (parent_root_id != fid->root_objectid) { fid->parent_root_objectid = parent_root_id; len = BTRFS_FID_SIZE_CONNECTABLE_ROOT; type = FILEID_BTRFS_WITH_PARENT_ROOT; } else { len = BTRFS_FID_SIZE_CONNECTABLE; type = FILEID_BTRFS_WITH_PARENT; } } *max_len = len; return type; } |
c0c907a47 btrfs: export hel... |
55 56 57 |
struct dentry *btrfs_get_dentry(struct super_block *sb, u64 objectid, u64 root_objectid, u32 generation, int check_generation) |
be6e8dc0b NFS support for b... |
58 |
{ |
815745cf3 btrfs: let ->s_fs... |
59 |
struct btrfs_fs_info *fs_info = btrfs_sb(sb); |
be6e8dc0b NFS support for b... |
60 61 |
struct btrfs_root *root; struct inode *inode; |
76dda93c6 Btrfs: add snapsh... |
62 63 64 |
if (objectid < BTRFS_FIRST_FREE_OBJECTID) return ERR_PTR(-ESTALE); |
be6e8dc0b NFS support for b... |
65 |
|
56e9357a1 btrfs: simplify r... |
66 |
root = btrfs_get_fs_root(fs_info, root_objectid, true); |
c75e83941 btrfs: kill the s... |
67 68 |
if (IS_ERR(root)) return ERR_CAST(root); |
76dda93c6 Btrfs: add snapsh... |
69 |
|
0202e83fd btrfs: simplify i... |
70 |
inode = btrfs_iget(sb, objectid, root); |
002465289 btrfs: rename btr... |
71 |
btrfs_put_root(root); |
c75e83941 btrfs: kill the s... |
72 73 |
if (IS_ERR(inode)) return ERR_CAST(inode); |
be6e8dc0b NFS support for b... |
74 |
|
76dda93c6 Btrfs: add snapsh... |
75 |
if (check_generation && generation != inode->i_generation) { |
be6e8dc0b NFS support for b... |
76 77 78 |
iput(inode); return ERR_PTR(-ESTALE); } |
af53d29ac switch btrfs, clo... |
79 |
return d_obtain_alias(inode); |
be6e8dc0b NFS support for b... |
80 81 82 83 84 85 86 87 88 89 |
} static struct dentry *btrfs_fh_to_parent(struct super_block *sb, struct fid *fh, int fh_len, int fh_type) { struct btrfs_fid *fid = (struct btrfs_fid *) fh; u64 objectid, root_objectid; u32 generation; if (fh_type == FILEID_BTRFS_WITH_PARENT) { |
7d35199e1 BTRFS: support NF... |
90 |
if (fh_len < BTRFS_FID_SIZE_CONNECTABLE) |
be6e8dc0b NFS support for b... |
91 92 93 |
return NULL; root_objectid = fid->root_objectid; } else if (fh_type == FILEID_BTRFS_WITH_PARENT_ROOT) { |
7d35199e1 BTRFS: support NF... |
94 |
if (fh_len < BTRFS_FID_SIZE_CONNECTABLE_ROOT) |
be6e8dc0b NFS support for b... |
95 96 97 98 99 100 101 |
return NULL; root_objectid = fid->parent_root_objectid; } else return NULL; objectid = fid->parent_objectid; generation = fid->parent_gen; |
76dda93c6 Btrfs: add snapsh... |
102 |
return btrfs_get_dentry(sb, objectid, root_objectid, generation, 1); |
be6e8dc0b NFS support for b... |
103 104 105 106 107 108 109 110 111 112 |
} static struct dentry *btrfs_fh_to_dentry(struct super_block *sb, struct fid *fh, int fh_len, int fh_type) { struct btrfs_fid *fid = (struct btrfs_fid *) fh; u64 objectid, root_objectid; u32 generation; if ((fh_type != FILEID_BTRFS_WITH_PARENT || |
7d35199e1 BTRFS: support NF... |
113 |
fh_len < BTRFS_FID_SIZE_CONNECTABLE) && |
be6e8dc0b NFS support for b... |
114 |
(fh_type != FILEID_BTRFS_WITH_PARENT_ROOT || |
7d35199e1 BTRFS: support NF... |
115 |
fh_len < BTRFS_FID_SIZE_CONNECTABLE_ROOT) && |
be6e8dc0b NFS support for b... |
116 |
(fh_type != FILEID_BTRFS_WITHOUT_PARENT || |
7d35199e1 BTRFS: support NF... |
117 |
fh_len < BTRFS_FID_SIZE_NON_CONNECTABLE)) |
be6e8dc0b NFS support for b... |
118 119 120 121 122 |
return NULL; objectid = fid->objectid; root_objectid = fid->root_objectid; generation = fid->gen; |
76dda93c6 Btrfs: add snapsh... |
123 |
return btrfs_get_dentry(sb, objectid, root_objectid, generation, 1); |
be6e8dc0b NFS support for b... |
124 |
} |
c0c907a47 btrfs: export hel... |
125 |
struct dentry *btrfs_get_parent(struct dentry *child) |
be6e8dc0b NFS support for b... |
126 |
{ |
2b0143b5c VFS: normal files... |
127 |
struct inode *dir = d_inode(child); |
0b246afa6 btrfs: root->fs_i... |
128 |
struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb); |
be6e8dc0b NFS support for b... |
129 |
struct btrfs_root *root = BTRFS_I(dir)->root; |
be6e8dc0b NFS support for b... |
130 131 |
struct btrfs_path *path; struct extent_buffer *leaf; |
76dda93c6 Btrfs: add snapsh... |
132 133 134 |
struct btrfs_root_ref *ref; struct btrfs_key key; struct btrfs_key found_key; |
be6e8dc0b NFS support for b... |
135 136 137 |
int ret; path = btrfs_alloc_path(); |
2a29edc6b btrfs: fix severa... |
138 139 |
if (!path) return ERR_PTR(-ENOMEM); |
be6e8dc0b NFS support for b... |
140 |
|
4a0cc7ca6 btrfs: Make btrfs... |
141 |
if (btrfs_ino(BTRFS_I(dir)) == BTRFS_FIRST_FREE_OBJECTID) { |
76dda93c6 Btrfs: add snapsh... |
142 143 144 |
key.objectid = root->root_key.objectid; key.type = BTRFS_ROOT_BACKREF_KEY; key.offset = (u64)-1; |
0b246afa6 btrfs: root->fs_i... |
145 |
root = fs_info->tree_root; |
76dda93c6 Btrfs: add snapsh... |
146 |
} else { |
4a0cc7ca6 btrfs: Make btrfs... |
147 |
key.objectid = btrfs_ino(BTRFS_I(dir)); |
76dda93c6 Btrfs: add snapsh... |
148 149 150 |
key.type = BTRFS_INODE_REF_KEY; key.offset = (u64)-1; } |
be6e8dc0b NFS support for b... |
151 |
|
87acb4ef9 Simplify btrfs_ge... |
152 |
ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
76dda93c6 Btrfs: add snapsh... |
153 154 |
if (ret < 0) goto fail; |
79787eaab btrfs: replace ma... |
155 |
BUG_ON(ret == 0); /* Key with offset of -1 found */ |
76dda93c6 Btrfs: add snapsh... |
156 157 158 |
if (path->slots[0] == 0) { ret = -ENOENT; goto fail; |
d54a83901 Clean up btrfs_ge... |
159 |
} |
76dda93c6 Btrfs: add snapsh... |
160 161 |
path->slots[0]--; |
be6e8dc0b NFS support for b... |
162 |
leaf = path->nodes[0]; |
76dda93c6 Btrfs: add snapsh... |
163 164 165 166 167 |
btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); if (found_key.objectid != key.objectid || found_key.type != key.type) { ret = -ENOENT; goto fail; |
be6e8dc0b NFS support for b... |
168 |
} |
76dda93c6 Btrfs: add snapsh... |
169 170 171 172 173 174 175 |
if (found_key.type == BTRFS_ROOT_BACKREF_KEY) { ref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_root_ref); key.objectid = btrfs_root_ref_dirid(leaf, ref); } else { key.objectid = found_key.offset; } |
be6e8dc0b NFS support for b... |
176 |
btrfs_free_path(path); |
76dda93c6 Btrfs: add snapsh... |
177 |
if (found_key.type == BTRFS_ROOT_BACKREF_KEY) { |
0b246afa6 btrfs: root->fs_i... |
178 |
return btrfs_get_dentry(fs_info->sb, key.objectid, |
76dda93c6 Btrfs: add snapsh... |
179 180 |
found_key.offset, 0, 0); } |
2d4d9fbd6 Btrfs: Fix NFS ex... |
181 |
|
0202e83fd btrfs: simplify i... |
182 |
return d_obtain_alias(btrfs_iget(fs_info->sb, key.objectid, root)); |
76dda93c6 Btrfs: add snapsh... |
183 184 185 |
fail: btrfs_free_path(path); return ERR_PTR(ret); |
be6e8dc0b NFS support for b... |
186 |
} |
2ede0daf0 Btrfs: handle NFS... |
187 188 189 |
static int btrfs_get_name(struct dentry *parent, char *name, struct dentry *child) { |
2b0143b5c VFS: normal files... |
190 191 |
struct inode *inode = d_inode(child); struct inode *dir = d_inode(parent); |
0b246afa6 btrfs: root->fs_i... |
192 |
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb); |
2ede0daf0 Btrfs: handle NFS... |
193 194 195 196 197 198 199 200 201 |
struct btrfs_path *path; struct btrfs_root *root = BTRFS_I(dir)->root; struct btrfs_inode_ref *iref; struct btrfs_root_ref *rref; struct extent_buffer *leaf; unsigned long name_ptr; struct btrfs_key key; int name_len; int ret; |
33345d015 Btrfs: Always use... |
202 |
u64 ino; |
2ede0daf0 Btrfs: handle NFS... |
203 |
|
2ede0daf0 Btrfs: handle NFS... |
204 205 |
if (!S_ISDIR(dir->i_mode)) return -EINVAL; |
4a0cc7ca6 btrfs: Make btrfs... |
206 |
ino = btrfs_ino(BTRFS_I(inode)); |
33345d015 Btrfs: Always use... |
207 |
|
2ede0daf0 Btrfs: handle NFS... |
208 209 210 211 |
path = btrfs_alloc_path(); if (!path) return -ENOMEM; path->leave_spinning = 1; |
33345d015 Btrfs: Always use... |
212 |
if (ino == BTRFS_FIRST_FREE_OBJECTID) { |
2ede0daf0 Btrfs: handle NFS... |
213 214 215 |
key.objectid = BTRFS_I(inode)->root->root_key.objectid; key.type = BTRFS_ROOT_BACKREF_KEY; key.offset = (u64)-1; |
0b246afa6 btrfs: root->fs_i... |
216 |
root = fs_info->tree_root; |
2ede0daf0 Btrfs: handle NFS... |
217 |
} else { |
33345d015 Btrfs: Always use... |
218 |
key.objectid = ino; |
4a0cc7ca6 btrfs: Make btrfs... |
219 |
key.offset = btrfs_ino(BTRFS_I(dir)); |
2ede0daf0 Btrfs: handle NFS... |
220 221 222 223 224 225 226 227 |
key.type = BTRFS_INODE_REF_KEY; } ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); if (ret < 0) { btrfs_free_path(path); return ret; } else if (ret > 0) { |
33345d015 Btrfs: Always use... |
228 |
if (ino == BTRFS_FIRST_FREE_OBJECTID) { |
2ede0daf0 Btrfs: handle NFS... |
229 230 231 232 233 234 235 |
path->slots[0]--; } else { btrfs_free_path(path); return -ENOENT; } } leaf = path->nodes[0]; |
33345d015 Btrfs: Always use... |
236 237 |
if (ino == BTRFS_FIRST_FREE_OBJECTID) { rref = btrfs_item_ptr(leaf, path->slots[0], |
2ede0daf0 Btrfs: handle NFS... |
238 |
struct btrfs_root_ref); |
33345d015 Btrfs: Always use... |
239 240 |
name_ptr = (unsigned long)(rref + 1); name_len = btrfs_root_ref_name_len(leaf, rref); |
2ede0daf0 Btrfs: handle NFS... |
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
} else { iref = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_inode_ref); name_ptr = (unsigned long)(iref + 1); name_len = btrfs_inode_ref_name_len(leaf, iref); } read_extent_buffer(leaf, name, name_ptr, name_len); btrfs_free_path(path); /* * have to add the null termination to make sure that reconnect_path * gets the right len for strlen */ name[name_len] = '\0'; return 0; } |
be6e8dc0b NFS support for b... |
259 260 261 262 263 |
const struct export_operations btrfs_export_ops = { .encode_fh = btrfs_encode_fh, .fh_to_dentry = btrfs_fh_to_dentry, .fh_to_parent = btrfs_fh_to_parent, .get_parent = btrfs_get_parent, |
2ede0daf0 Btrfs: handle NFS... |
264 |
.get_name = btrfs_get_name, |
be6e8dc0b NFS support for b... |
265 |
}; |