Blame view

fs/btrfs/export.c 7.17 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
c1d7c514f   David Sterba   btrfs: replace GP...
2

be6e8dc0b   Balaji Rao   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   Balaji Rao   NFS support for b...
10

d397712bc   Chris Mason   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   Balaji Rao   NFS support for b...
16

b0b0382bb   Al Viro   ->encode_fh() API...
17
18
  static int btrfs_encode_fh(struct inode *inode, u32 *fh, int *max_len,
  			   struct inode *parent)
be6e8dc0b   Balaji Rao   NFS support for b...
19
20
  {
  	struct btrfs_fid *fid = (struct btrfs_fid *)fh;
be6e8dc0b   Balaji Rao   NFS support for b...
21
22
  	int len = *max_len;
  	int type;
b0b0382bb   Al Viro   ->encode_fh() API...
23
  	if (parent && (len < BTRFS_FID_SIZE_CONNECTABLE)) {
5fe0c2378   Aneesh Kumar K.V   exportfs: Return ...
24
  		*max_len = BTRFS_FID_SIZE_CONNECTABLE;
94e07a759   Namjae Jeon   fs: encode_fh: re...
25
  		return FILEID_INVALID;
5fe0c2378   Aneesh Kumar K.V   exportfs: Return ...
26
27
  	} else if (len < BTRFS_FID_SIZE_NON_CONNECTABLE) {
  		*max_len = BTRFS_FID_SIZE_NON_CONNECTABLE;
94e07a759   Namjae Jeon   fs: encode_fh: re...
28
  		return FILEID_INVALID;
5fe0c2378   Aneesh Kumar K.V   exportfs: Return ...
29
  	}
be6e8dc0b   Balaji Rao   NFS support for b...
30
31
32
  
  	len  = BTRFS_FID_SIZE_NON_CONNECTABLE;
  	type = FILEID_BTRFS_WITHOUT_PARENT;
4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
33
  	fid->objectid = btrfs_ino(BTRFS_I(inode));
4fd786e6c   Misono Tomohiro   btrfs: Remove 'ob...
34
  	fid->root_objectid = BTRFS_I(inode)->root->root_key.objectid;
be6e8dc0b   Balaji Rao   NFS support for b...
35
  	fid->gen = inode->i_generation;
b0b0382bb   Al Viro   ->encode_fh() API...
36
  	if (parent) {
be6e8dc0b   Balaji Rao   NFS support for b...
37
  		u64 parent_root_id;
be6e8dc0b   Balaji Rao   NFS support for b...
38
39
  		fid->parent_objectid = BTRFS_I(parent)->location.objectid;
  		fid->parent_gen = parent->i_generation;
4fd786e6c   Misono Tomohiro   btrfs: Remove 'ob...
40
  		parent_root_id = BTRFS_I(parent)->root->root_key.objectid;
be6e8dc0b   Balaji Rao   NFS support for b...
41

be6e8dc0b   Balaji Rao   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   Marcos Paulo de Souza   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   Balaji Rao   NFS support for b...
58
  {
815745cf3   Al Viro   btrfs: let ->s_fs...
59
  	struct btrfs_fs_info *fs_info = btrfs_sb(sb);
be6e8dc0b   Balaji Rao   NFS support for b...
60
61
  	struct btrfs_root *root;
  	struct inode *inode;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
62
63
64
  
  	if (objectid < BTRFS_FIRST_FREE_OBJECTID)
  		return ERR_PTR(-ESTALE);
be6e8dc0b   Balaji Rao   NFS support for b...
65

56e9357a1   David Sterba   btrfs: simplify r...
66
  	root = btrfs_get_fs_root(fs_info, root_objectid, true);
c75e83941   Josef Bacik   btrfs: kill the s...
67
68
  	if (IS_ERR(root))
  		return ERR_CAST(root);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
69

0202e83fd   David Sterba   btrfs: simplify i...
70
  	inode = btrfs_iget(sb, objectid, root);
002465289   Josef Bacik   btrfs: rename btr...
71
  	btrfs_put_root(root);
c75e83941   Josef Bacik   btrfs: kill the s...
72
73
  	if (IS_ERR(inode))
  		return ERR_CAST(inode);
be6e8dc0b   Balaji Rao   NFS support for b...
74

76dda93c6   Yan, Zheng   Btrfs: add snapsh...
75
  	if (check_generation && generation != inode->i_generation) {
be6e8dc0b   Balaji Rao   NFS support for b...
76
77
78
  		iput(inode);
  		return ERR_PTR(-ESTALE);
  	}
af53d29ac   Al Viro   switch btrfs, clo...
79
  	return d_obtain_alias(inode);
be6e8dc0b   Balaji Rao   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   NeilBrown   BTRFS: support NF...
90
  		if (fh_len <  BTRFS_FID_SIZE_CONNECTABLE)
be6e8dc0b   Balaji Rao   NFS support for b...
91
92
93
  			return NULL;
  		root_objectid = fid->root_objectid;
  	} else if (fh_type == FILEID_BTRFS_WITH_PARENT_ROOT) {
7d35199e1   NeilBrown   BTRFS: support NF...
94
  		if (fh_len < BTRFS_FID_SIZE_CONNECTABLE_ROOT)
be6e8dc0b   Balaji Rao   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   Yan, Zheng   Btrfs: add snapsh...
102
  	return btrfs_get_dentry(sb, objectid, root_objectid, generation, 1);
be6e8dc0b   Balaji Rao   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   NeilBrown   BTRFS: support NF...
113
  	     fh_len < BTRFS_FID_SIZE_CONNECTABLE) &&
be6e8dc0b   Balaji Rao   NFS support for b...
114
  	    (fh_type != FILEID_BTRFS_WITH_PARENT_ROOT ||
7d35199e1   NeilBrown   BTRFS: support NF...
115
  	     fh_len < BTRFS_FID_SIZE_CONNECTABLE_ROOT) &&
be6e8dc0b   Balaji Rao   NFS support for b...
116
  	    (fh_type != FILEID_BTRFS_WITHOUT_PARENT ||
7d35199e1   NeilBrown   BTRFS: support NF...
117
  	     fh_len < BTRFS_FID_SIZE_NON_CONNECTABLE))
be6e8dc0b   Balaji Rao   NFS support for b...
118
119
120
121
122
  		return NULL;
  
  	objectid = fid->objectid;
  	root_objectid = fid->root_objectid;
  	generation = fid->gen;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
123
  	return btrfs_get_dentry(sb, objectid, root_objectid, generation, 1);
be6e8dc0b   Balaji Rao   NFS support for b...
124
  }
c0c907a47   Marcos Paulo de Souza   btrfs: export hel...
125
  struct dentry *btrfs_get_parent(struct dentry *child)
be6e8dc0b   Balaji Rao   NFS support for b...
126
  {
2b0143b5c   David Howells   VFS: normal files...
127
  	struct inode *dir = d_inode(child);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
128
  	struct btrfs_fs_info *fs_info = btrfs_sb(dir->i_sb);
be6e8dc0b   Balaji Rao   NFS support for b...
129
  	struct btrfs_root *root = BTRFS_I(dir)->root;
be6e8dc0b   Balaji Rao   NFS support for b...
130
131
  	struct btrfs_path *path;
  	struct extent_buffer *leaf;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
132
133
134
  	struct btrfs_root_ref *ref;
  	struct btrfs_key key;
  	struct btrfs_key found_key;
be6e8dc0b   Balaji Rao   NFS support for b...
135
136
137
  	int ret;
  
  	path = btrfs_alloc_path();
2a29edc6b   liubo   btrfs: fix severa...
138
139
  	if (!path)
  		return ERR_PTR(-ENOMEM);
be6e8dc0b   Balaji Rao   NFS support for b...
140

4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
141
  	if (btrfs_ino(BTRFS_I(dir)) == BTRFS_FIRST_FREE_OBJECTID) {
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
142
143
144
  		key.objectid = root->root_key.objectid;
  		key.type = BTRFS_ROOT_BACKREF_KEY;
  		key.offset = (u64)-1;
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
145
  		root = fs_info->tree_root;
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
146
  	} else {
4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
147
  		key.objectid = btrfs_ino(BTRFS_I(dir));
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
148
149
150
  		key.type = BTRFS_INODE_REF_KEY;
  		key.offset = (u64)-1;
  	}
be6e8dc0b   Balaji Rao   NFS support for b...
151

87acb4ef9   David Woodhouse   Simplify btrfs_ge...
152
  	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
153
154
  	if (ret < 0)
  		goto fail;
79787eaab   Jeff Mahoney   btrfs: replace ma...
155
  	BUG_ON(ret == 0); /* Key with offset of -1 found */
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
156
157
158
  	if (path->slots[0] == 0) {
  		ret = -ENOENT;
  		goto fail;
d54a83901   David Woodhouse   Clean up btrfs_ge...
159
  	}
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
160
161
  
  	path->slots[0]--;
be6e8dc0b   Balaji Rao   NFS support for b...
162
  	leaf = path->nodes[0];
76dda93c6   Yan, Zheng   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   Balaji Rao   NFS support for b...
168
  	}
76dda93c6   Yan, Zheng   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   Balaji Rao   NFS support for b...
176
  	btrfs_free_path(path);
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
177
  	if (found_key.type == BTRFS_ROOT_BACKREF_KEY) {
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
178
  		return btrfs_get_dentry(fs_info->sb, key.objectid,
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
179
180
  					found_key.offset, 0, 0);
  	}
2d4d9fbd6   David Woodhouse   Btrfs: Fix NFS ex...
181

0202e83fd   David Sterba   btrfs: simplify i...
182
  	return d_obtain_alias(btrfs_iget(fs_info->sb, key.objectid, root));
76dda93c6   Yan, Zheng   Btrfs: add snapsh...
183
184
185
  fail:
  	btrfs_free_path(path);
  	return ERR_PTR(ret);
be6e8dc0b   Balaji Rao   NFS support for b...
186
  }
2ede0daf0   Josef Bacik   Btrfs: handle NFS...
187
188
189
  static int btrfs_get_name(struct dentry *parent, char *name,
  			  struct dentry *child)
  {
2b0143b5c   David Howells   VFS: normal files...
190
191
  	struct inode *inode = d_inode(child);
  	struct inode *dir = d_inode(parent);
0b246afa6   Jeff Mahoney   btrfs: root->fs_i...
192
  	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
2ede0daf0   Josef Bacik   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   Li Zefan   Btrfs: Always use...
202
  	u64 ino;
2ede0daf0   Josef Bacik   Btrfs: handle NFS...
203

2ede0daf0   Josef Bacik   Btrfs: handle NFS...
204
205
  	if (!S_ISDIR(dir->i_mode))
  		return -EINVAL;
4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
206
  	ino = btrfs_ino(BTRFS_I(inode));
33345d015   Li Zefan   Btrfs: Always use...
207

2ede0daf0   Josef Bacik   Btrfs: handle NFS...
208
209
210
211
  	path = btrfs_alloc_path();
  	if (!path)
  		return -ENOMEM;
  	path->leave_spinning = 1;
33345d015   Li Zefan   Btrfs: Always use...
212
  	if (ino == BTRFS_FIRST_FREE_OBJECTID) {
2ede0daf0   Josef Bacik   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   Jeff Mahoney   btrfs: root->fs_i...
216
  		root = fs_info->tree_root;
2ede0daf0   Josef Bacik   Btrfs: handle NFS...
217
  	} else {
33345d015   Li Zefan   Btrfs: Always use...
218
  		key.objectid = ino;
4a0cc7ca6   Nikolay Borisov   btrfs: Make btrfs...
219
  		key.offset = btrfs_ino(BTRFS_I(dir));
2ede0daf0   Josef Bacik   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   Li Zefan   Btrfs: Always use...
228
  		if (ino == BTRFS_FIRST_FREE_OBJECTID) {
2ede0daf0   Josef Bacik   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   Li Zefan   Btrfs: Always use...
236
237
  	if (ino == BTRFS_FIRST_FREE_OBJECTID) {
  		rref = btrfs_item_ptr(leaf, path->slots[0],
2ede0daf0   Josef Bacik   Btrfs: handle NFS...
238
  				     struct btrfs_root_ref);
33345d015   Li Zefan   Btrfs: Always use...
239
240
  		name_ptr = (unsigned long)(rref + 1);
  		name_len = btrfs_root_ref_name_len(leaf, rref);
2ede0daf0   Josef Bacik   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   Balaji Rao   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   Josef Bacik   Btrfs: handle NFS...
264
  	.get_name	= btrfs_get_name,
be6e8dc0b   Balaji Rao   NFS support for b...
265
  };