Blame view

fs/ceph/export.c 5.78 KB
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
1
  #include <linux/ceph/ceph_debug.h>
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
2
3
  
  #include <linux/exportfs.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
4
  #include <linux/slab.h>
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
5
6
7
  #include <asm/unaligned.h>
  
  #include "super.h"
3d14c5d2b   Yehuda Sadeh   ceph: factor out ...
8
  #include "mds_client.h"
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
9
10
  
  /*
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
11
12
13
14
15
16
17
   * Basic fh
   */
  struct ceph_nfs_fh {
  	u64 ino;
  } __attribute__ ((packed));
  
  /*
4f32b42dc   Yan, Zheng   ceph: simplify ce...
18
   * Larger fh that includes parent ino.
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
19
20
21
   */
  struct ceph_nfs_confh {
  	u64 ino, parent_ino;
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
22
  } __attribute__ ((packed));
c862868bb   Sage Weil   ceph: move encode...
23
24
  static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,
  			  struct inode *parent_inode)
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
25
  {
92923dcbf   Aneesh Kumar K.V   ceph: Fix return ...
26
  	int type;
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
27
28
  	struct ceph_nfs_fh *fh = (void *)rawfh;
  	struct ceph_nfs_confh *cfh = (void *)rawfh;
92923dcbf   Aneesh Kumar K.V   ceph: Fix return ...
29
30
  	int connected_handle_length = sizeof(*cfh)/4;
  	int handle_length = sizeof(*fh)/4;
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
31
32
33
34
  
  	/* don't re-export snaps */
  	if (ceph_snap(inode) != CEPH_NOSNAP)
  		return -EINVAL;
4f32b42dc   Yan, Zheng   ceph: simplify ce...
35
36
37
38
39
40
41
  	if (parent_inode && (*max_len < connected_handle_length)) {
  		*max_len = connected_handle_length;
  		return FILEID_INVALID;
  	} else if (*max_len < handle_length) {
  		*max_len = handle_length;
  		return FILEID_INVALID;
  	}
f6af75dac   Cyril Roelandt   ceph: fix dentry ...
42

4f32b42dc   Yan, Zheng   ceph: simplify ce...
43
44
45
46
  	if (parent_inode) {
  		dout("encode_fh %llx with parent %llx
  ",
  		     ceph_ino(inode), ceph_ino(parent_inode));
c862868bb   Sage Weil   ceph: move encode...
47
  		cfh->ino = ceph_ino(inode);
4f32b42dc   Yan, Zheng   ceph: simplify ce...
48
  		cfh->parent_ino = ceph_ino(parent_inode);
92923dcbf   Aneesh Kumar K.V   ceph: Fix return ...
49
  		*max_len = connected_handle_length;
4f32b42dc   Yan, Zheng   ceph: simplify ce...
50
  		type = FILEID_INO32_GEN_PARENT;
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
51
  	} else {
4f32b42dc   Yan, Zheng   ceph: simplify ce...
52
53
54
  		dout("encode_fh %llx
  ", ceph_ino(inode));
  		fh->ino = ceph_ino(inode);
bba0cd0e3   Aneesh Kumar K.V   ceph: Update max_...
55
  		*max_len = handle_length;
4f32b42dc   Yan, Zheng   ceph: simplify ce...
56
  		type = FILEID_INO32_GEN;
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
57
58
59
  	}
  	return type;
  }
4f32b42dc   Yan, Zheng   ceph: simplify ce...
60
  static struct dentry *__fh_to_dentry(struct super_block *sb, u64 ino)
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
61
  {
3c454cf21   Sage Weil   ceph: use LOOKUPI...
62
  	struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc;
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
63
64
65
66
  	struct inode *inode;
  	struct dentry *dentry;
  	struct ceph_vino vino;
  	int err;
4f32b42dc   Yan, Zheng   ceph: simplify ce...
67
  	vino.ino = ino;
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
68
69
  	vino.snap = CEPH_NOSNAP;
  	inode = ceph_find_inode(sb, vino);
3c454cf21   Sage Weil   ceph: use LOOKUPI...
70
71
72
73
74
75
76
77
78
79
80
  	if (!inode) {
  		struct ceph_mds_request *req;
  
  		req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPINO,
  					       USE_ANY_MDS);
  		if (IS_ERR(req))
  			return ERR_CAST(req);
  
  		req->r_ino1 = vino;
  		req->r_num_caps = 1;
  		err = ceph_mdsc_do_request(mdsc, NULL, req);
45e3d3eeb   Sage Weil   ceph: avoid inode...
81
82
  		inode = req->r_target_inode;
  		if (inode)
70b666c3b   Sage Weil   ceph: use ihold w...
83
  			ihold(inode);
3c454cf21   Sage Weil   ceph: use LOOKUPI...
84
  		ceph_mdsc_put_request(req);
3c454cf21   Sage Weil   ceph: use LOOKUPI...
85
86
87
  		if (!inode)
  			return ERR_PTR(-ESTALE);
  	}
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
88
89
  
  	dentry = d_obtain_alias(inode);
0d509c949   Dan Carpenter   ceph: d_obtain_al...
90
  	if (IS_ERR(dentry)) {
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
91
  		iput(inode);
0d509c949   Dan Carpenter   ceph: d_obtain_al...
92
  		return dentry;
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
93
94
  	}
  	err = ceph_init_dentry(dentry);
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
95
  	if (err < 0) {
4f32b42dc   Yan, Zheng   ceph: simplify ce...
96
  		dput(dentry);
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
97
98
  		return ERR_PTR(err);
  	}
4f32b42dc   Yan, Zheng   ceph: simplify ce...
99
100
  	dout("__fh_to_dentry %llx %p dentry %p
  ", ino, inode, dentry);
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
101
102
103
104
  	return dentry;
  }
  
  /*
4f32b42dc   Yan, Zheng   ceph: simplify ce...
105
   * convert regular fh to dentry
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
106
   */
4f32b42dc   Yan, Zheng   ceph: simplify ce...
107
108
109
  static struct dentry *ceph_fh_to_dentry(struct super_block *sb,
  					struct fid *fid,
  					int fh_len, int fh_type)
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
110
  {
4f32b42dc   Yan, Zheng   ceph: simplify ce...
111
  	struct ceph_nfs_fh *fh = (void *)fid->raw;
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
112

4f32b42dc   Yan, Zheng   ceph: simplify ce...
113
114
115
116
117
  	if (fh_type != FILEID_INO32_GEN  &&
  	    fh_type != FILEID_INO32_GEN_PARENT)
  		return NULL;
  	if (fh_len < sizeof(*fh) / 4)
  		return NULL;
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
118

4f32b42dc   Yan, Zheng   ceph: simplify ce...
119
120
121
  	dout("fh_to_dentry %llx
  ", fh->ino);
  	return __fh_to_dentry(sb, fh->ino);
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
122
  }
9017c2ec7   Yan, Zheng   ceph: add get_par...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
  static struct dentry *__get_parent(struct super_block *sb,
  				   struct dentry *child, u64 ino)
  {
  	struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc;
  	struct ceph_mds_request *req;
  	struct inode *inode;
  	struct dentry *dentry;
  	int err;
  
  	req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPPARENT,
  				       USE_ANY_MDS);
  	if (IS_ERR(req))
  		return ERR_CAST(req);
  
  	if (child) {
2b0143b5c   David Howells   VFS: normal files...
138
139
  		req->r_inode = d_inode(child);
  		ihold(d_inode(child));
9017c2ec7   Yan, Zheng   ceph: add get_par...
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
  	} else {
  		req->r_ino1 = (struct ceph_vino) {
  			.ino = ino,
  			.snap = CEPH_NOSNAP,
  		};
  	}
  	req->r_num_caps = 1;
  	err = ceph_mdsc_do_request(mdsc, NULL, req);
  	inode = req->r_target_inode;
  	if (inode)
  		ihold(inode);
  	ceph_mdsc_put_request(req);
  	if (!inode)
  		return ERR_PTR(-ENOENT);
  
  	dentry = d_obtain_alias(inode);
  	if (IS_ERR(dentry)) {
  		iput(inode);
  		return dentry;
  	}
  	err = ceph_init_dentry(dentry);
  	if (err < 0) {
  		dput(dentry);
  		return ERR_PTR(err);
  	}
  	dout("__get_parent ino %llx parent %p ino %llx.%llx
  ",
2b0143b5c   David Howells   VFS: normal files...
167
  	     child ? ceph_ino(d_inode(child)) : ino,
9017c2ec7   Yan, Zheng   ceph: add get_par...
168
169
170
  	     dentry, ceph_vinop(inode));
  	return dentry;
  }
e84be11c5   Fengguang Wu   ceph: ceph_get_pa...
171
  static struct dentry *ceph_get_parent(struct dentry *child)
9017c2ec7   Yan, Zheng   ceph: add get_par...
172
173
  {
  	/* don't re-export snaps */
2b0143b5c   David Howells   VFS: normal files...
174
  	if (ceph_snap(d_inode(child)) != CEPH_NOSNAP)
9017c2ec7   Yan, Zheng   ceph: add get_par...
175
176
177
178
  		return ERR_PTR(-EINVAL);
  
  	dout("get_parent %p ino %llx.%llx
  ",
2b0143b5c   David Howells   VFS: normal files...
179
  	     child, ceph_vinop(d_inode(child)));
9017c2ec7   Yan, Zheng   ceph: add get_par...
180
181
  	return __get_parent(child->d_sb, child, 0);
  }
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
182
  /*
8996f4f23   Yan, Zheng   ceph: fix ceph_fh...
183
   * convert regular fh to parent
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
184
185
   */
  static struct dentry *ceph_fh_to_parent(struct super_block *sb,
8996f4f23   Yan, Zheng   ceph: fix ceph_fh...
186
  					struct fid *fid,
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
187
188
189
  					int fh_len, int fh_type)
  {
  	struct ceph_nfs_confh *cfh = (void *)fid->raw;
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
190
  	struct dentry *dentry;
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
191

8996f4f23   Yan, Zheng   ceph: fix ceph_fh...
192
193
  	if (fh_type != FILEID_INO32_GEN_PARENT)
  		return NULL;
35c2a7f49   Hugh Dickins   tmpfs,ceph,gfs2,i...
194
  	if (fh_len < sizeof(*cfh) / 4)
8996f4f23   Yan, Zheng   ceph: fix ceph_fh...
195
  		return NULL;
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
196

8996f4f23   Yan, Zheng   ceph: fix ceph_fh...
197
198
199
200
201
  	dout("fh_to_parent %llx
  ", cfh->parent_ino);
  	dentry = __get_parent(sb, NULL, cfh->ino);
  	if (IS_ERR(dentry) && PTR_ERR(dentry) == -ENOENT)
  		dentry = __fh_to_dentry(sb, cfh->parent_ino);
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
202
203
  	return dentry;
  }
19913b4ea   Yan, Zheng   ceph: add get_nam...
204
205
206
207
208
209
  static int ceph_get_name(struct dentry *parent, char *name,
  			 struct dentry *child)
  {
  	struct ceph_mds_client *mdsc;
  	struct ceph_mds_request *req;
  	int err;
2b0143b5c   David Howells   VFS: normal files...
210
  	mdsc = ceph_inode_to_client(d_inode(child))->mdsc;
19913b4ea   Yan, Zheng   ceph: add get_nam...
211
212
213
214
  	req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_LOOKUPNAME,
  				       USE_ANY_MDS);
  	if (IS_ERR(req))
  		return PTR_ERR(req);
5955102c9   Al Viro   wrappers for ->i_...
215
  	inode_lock(d_inode(parent));
19913b4ea   Yan, Zheng   ceph: add get_nam...
216

2b0143b5c   David Howells   VFS: normal files...
217
218
219
220
  	req->r_inode = d_inode(child);
  	ihold(d_inode(child));
  	req->r_ino2 = ceph_vino(d_inode(parent));
  	req->r_locked_dir = d_inode(parent);
19913b4ea   Yan, Zheng   ceph: add get_nam...
221
222
  	req->r_num_caps = 2;
  	err = ceph_mdsc_do_request(mdsc, NULL, req);
5955102c9   Al Viro   wrappers for ->i_...
223
  	inode_unlock(d_inode(parent));
19913b4ea   Yan, Zheng   ceph: add get_nam...
224
225
226
227
228
229
230
  
  	if (!err) {
  		struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info;
  		memcpy(name, rinfo->dname, rinfo->dname_len);
  		name[rinfo->dname_len] = 0;
  		dout("get_name %p ino %llx.%llx name %s
  ",
2b0143b5c   David Howells   VFS: normal files...
231
  		     child, ceph_vinop(d_inode(child)), name);
19913b4ea   Yan, Zheng   ceph: add get_nam...
232
233
234
  	} else {
  		dout("get_name %p ino %llx.%llx err %d
  ",
2b0143b5c   David Howells   VFS: normal files...
235
  		     child, ceph_vinop(d_inode(child)), err);
19913b4ea   Yan, Zheng   ceph: add get_nam...
236
237
238
239
240
  	}
  
  	ceph_mdsc_put_request(req);
  	return err;
  }
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
241
242
243
244
  const struct export_operations ceph_export_ops = {
  	.encode_fh = ceph_encode_fh,
  	.fh_to_dentry = ceph_fh_to_dentry,
  	.fh_to_parent = ceph_fh_to_parent,
9017c2ec7   Yan, Zheng   ceph: add get_par...
245
  	.get_parent = ceph_get_parent,
19913b4ea   Yan, Zheng   ceph: add get_nam...
246
  	.get_name = ceph_get_name,
a8e63b7d5   Sage Weil   ceph: nfs re-expo...
247
  };