xref: /openbmc/linux/fs/exportfs/expfs.c (revision 64c70b1c)
1 
2 #include <linux/fs.h>
3 #include <linux/file.h>
4 #include <linux/module.h>
5 #include <linux/namei.h>
6 
7 struct export_operations export_op_default;
8 
9 #define	CALL(ops,fun) ((ops->fun)?(ops->fun):export_op_default.fun)
10 
11 #define dprintk(fmt, args...) do{}while(0)
12 
13 static struct dentry *
14 find_acceptable_alias(struct dentry *result,
15 		int (*acceptable)(void *context, struct dentry *dentry),
16 		void *context)
17 {
18 	struct dentry *dentry, *toput = NULL;
19 
20 	spin_lock(&dcache_lock);
21 	list_for_each_entry(dentry, &result->d_inode->i_dentry, d_alias) {
22 		dget_locked(dentry);
23 		spin_unlock(&dcache_lock);
24 		if (toput)
25 			dput(toput);
26 		if (dentry != result && acceptable(context, dentry)) {
27 			dput(result);
28 			return dentry;
29 		}
30 		spin_lock(&dcache_lock);
31 		toput = dentry;
32 	}
33 	spin_unlock(&dcache_lock);
34 
35 	if (toput)
36 		dput(toput);
37 	return NULL;
38 }
39 
40 /**
41  * find_exported_dentry - helper routine to implement export_operations->decode_fh
42  * @sb:		The &super_block identifying the filesystem
43  * @obj:	An opaque identifier of the object to be found - passed to
44  *		get_inode
45  * @parent:	An optional opqaue identifier of the parent of the object.
46  * @acceptable:	A function used to test possible &dentries to see if they are
47  *		acceptable
48  * @context:	A parameter to @acceptable so that it knows on what basis to
49  *		judge.
50  *
51  * find_exported_dentry is the central helper routine to enable file systems
52  * to provide the decode_fh() export_operation.  It's main task is to take
53  * an &inode, find or create an appropriate &dentry structure, and possibly
54  * splice this into the dcache in the correct place.
55  *
56  * The decode_fh() operation provided by the filesystem should call
57  * find_exported_dentry() with the same parameters that it received except
58  * that instead of the file handle fragment, pointers to opaque identifiers
59  * for the object and optionally its parent are passed.  The default decode_fh
60  * routine passes one pointer to the start of the filehandle fragment, and
61  * one 8 bytes into the fragment.  It is expected that most filesystems will
62  * take this approach, though the offset to the parent identifier may well be
63  * different.
64  *
65  * find_exported_dentry() will call get_dentry to get an dentry pointer from
66  * the file system.  If any &dentry in the d_alias list is acceptable, it will
67  * be returned.  Otherwise find_exported_dentry() will attempt to splice a new
68  * &dentry into the dcache using get_name() and get_parent() to find the
69  * appropriate place.
70  */
71 
72 struct dentry *
73 find_exported_dentry(struct super_block *sb, void *obj, void *parent,
74 		     int (*acceptable)(void *context, struct dentry *de),
75 		     void *context)
76 {
77 	struct dentry *result = NULL;
78 	struct dentry *target_dir;
79 	int err;
80 	struct export_operations *nops = sb->s_export_op;
81 	struct dentry *alias;
82 	int noprogress;
83 	char nbuf[NAME_MAX+1];
84 
85 	/*
86 	 * Attempt to find the inode.
87 	 */
88 	result = CALL(sb->s_export_op,get_dentry)(sb,obj);
89 	err = -ESTALE;
90 	if (result == NULL)
91 		goto err_out;
92 	if (IS_ERR(result)) {
93 		err = PTR_ERR(result);
94 		goto err_out;
95 	}
96 	if (S_ISDIR(result->d_inode->i_mode) &&
97 	    (result->d_flags & DCACHE_DISCONNECTED)) {
98 		/* it is an unconnected directory, we must connect it */
99 		;
100 	} else {
101 		if (acceptable(context, result))
102 			return result;
103 		if (S_ISDIR(result->d_inode->i_mode)) {
104 			err = -EACCES;
105 			goto err_result;
106 		}
107 
108 		alias = find_acceptable_alias(result, acceptable, context);
109 		if (alias)
110 			return alias;
111 	}
112 
113 	/* It's a directory, or we are required to confirm the file's
114 	 * location in the tree based on the parent information
115  	 */
116 	dprintk("find_exported_dentry: need to look harder for %s/%d\n",sb->s_id,*(int*)obj);
117 	if (S_ISDIR(result->d_inode->i_mode))
118 		target_dir = dget(result);
119 	else {
120 		if (parent == NULL)
121 			goto err_result;
122 
123 		target_dir = CALL(sb->s_export_op,get_dentry)(sb,parent);
124 		if (IS_ERR(target_dir))
125 			err = PTR_ERR(target_dir);
126 		if (target_dir == NULL || IS_ERR(target_dir))
127 			goto err_result;
128 	}
129 	/*
130 	 * Now we need to make sure that target_dir is properly connected.
131 	 * It may already be, as the flag isn't always updated when connection
132 	 * happens.
133 	 * So, we walk up parent links until we find a connected directory,
134 	 * or we run out of directories.  Then we find the parent, find
135 	 * the name of the child in that parent, and do a lookup.
136 	 * This should connect the child into the parent
137 	 * We then repeat.
138 	 */
139 
140 	/* it is possible that a confused file system might not let us complete
141 	 * the path to the root.  For example, if get_parent returns a directory
142 	 * in which we cannot find a name for the child.  While this implies a
143 	 * very sick filesystem we don't want it to cause knfsd to spin.  Hence
144 	 * the noprogress counter.  If we go through the loop 10 times (2 is
145 	 * probably enough) without getting anywhere, we just give up
146 	 */
147 	noprogress= 0;
148 	while (target_dir->d_flags & DCACHE_DISCONNECTED && noprogress++ < 10) {
149 		struct dentry *pd = target_dir;
150 
151 		dget(pd);
152 		spin_lock(&pd->d_lock);
153 		while (!IS_ROOT(pd) &&
154 				(pd->d_parent->d_flags&DCACHE_DISCONNECTED)) {
155 			struct dentry *parent = pd->d_parent;
156 
157 			dget(parent);
158 			spin_unlock(&pd->d_lock);
159 			dput(pd);
160 			pd = parent;
161 			spin_lock(&pd->d_lock);
162 		}
163 		spin_unlock(&pd->d_lock);
164 
165 		if (!IS_ROOT(pd)) {
166 			/* must have found a connected parent - great */
167 			spin_lock(&pd->d_lock);
168 			pd->d_flags &= ~DCACHE_DISCONNECTED;
169 			spin_unlock(&pd->d_lock);
170 			noprogress = 0;
171 		} else if (pd == sb->s_root) {
172 			printk(KERN_ERR "export: Eeek filesystem root is not connected, impossible\n");
173 			spin_lock(&pd->d_lock);
174 			pd->d_flags &= ~DCACHE_DISCONNECTED;
175 			spin_unlock(&pd->d_lock);
176 			noprogress = 0;
177 		} else {
178 			/* we have hit the top of a disconnected path.  Try
179 			 * to find parent and connect
180 			 * note: racing with some other process renaming a
181 			 * directory isn't much of a problem here.  If someone
182 			 * renames the directory, it will end up properly
183 			 * connected, which is what we want
184 			 */
185 			struct dentry *ppd;
186 			struct dentry *npd;
187 
188 			mutex_lock(&pd->d_inode->i_mutex);
189 			ppd = CALL(nops,get_parent)(pd);
190 			mutex_unlock(&pd->d_inode->i_mutex);
191 
192 			if (IS_ERR(ppd)) {
193 				err = PTR_ERR(ppd);
194 				dprintk("find_exported_dentry: get_parent of %ld failed, err %d\n",
195 					pd->d_inode->i_ino, err);
196 				dput(pd);
197 				break;
198 			}
199 			dprintk("find_exported_dentry: find name of %lu in %lu\n", pd->d_inode->i_ino, ppd->d_inode->i_ino);
200 			err = CALL(nops,get_name)(ppd, nbuf, pd);
201 			if (err) {
202 				dput(ppd);
203 				dput(pd);
204 				if (err == -ENOENT)
205 					/* some race between get_parent and
206 					 * get_name?  just try again
207 					 */
208 					continue;
209 				break;
210 			}
211 			dprintk("find_exported_dentry: found name: %s\n", nbuf);
212 			mutex_lock(&ppd->d_inode->i_mutex);
213 			npd = lookup_one_len(nbuf, ppd, strlen(nbuf));
214 			mutex_unlock(&ppd->d_inode->i_mutex);
215 			if (IS_ERR(npd)) {
216 				err = PTR_ERR(npd);
217 				dprintk("find_exported_dentry: lookup failed: %d\n", err);
218 				dput(ppd);
219 				dput(pd);
220 				break;
221 			}
222 			/* we didn't really want npd, we really wanted
223 			 * a side-effect of the lookup.
224 			 * hopefully, npd == pd, though it isn't really
225 			 * a problem if it isn't
226 			 */
227 			if (npd == pd)
228 				noprogress = 0;
229 			else
230 				printk("find_exported_dentry: npd != pd\n");
231 			dput(npd);
232 			dput(ppd);
233 			if (IS_ROOT(pd)) {
234 				/* something went wrong, we have to give up */
235 				dput(pd);
236 				break;
237 			}
238 		}
239 		dput(pd);
240 	}
241 
242 	if (target_dir->d_flags & DCACHE_DISCONNECTED) {
243 		/* something went wrong - oh-well */
244 		if (!err)
245 			err = -ESTALE;
246 		goto err_target;
247 	}
248 	/* if we weren't after a directory, have one more step to go */
249 	if (result != target_dir) {
250 		struct dentry *nresult;
251 		err = CALL(nops,get_name)(target_dir, nbuf, result);
252 		if (!err) {
253 			mutex_lock(&target_dir->d_inode->i_mutex);
254 			nresult = lookup_one_len(nbuf, target_dir, strlen(nbuf));
255 			mutex_unlock(&target_dir->d_inode->i_mutex);
256 			if (!IS_ERR(nresult)) {
257 				if (nresult->d_inode) {
258 					dput(result);
259 					result = nresult;
260 				} else
261 					dput(nresult);
262 			}
263 		}
264 	}
265 	dput(target_dir);
266 	/* now result is properly connected, it is our best bet */
267 	if (acceptable(context, result))
268 		return result;
269 
270 	alias = find_acceptable_alias(result, acceptable, context);
271 	if (alias)
272 		return alias;
273 
274 	/* drat - I just cannot find anything acceptable */
275 	dput(result);
276 	/* It might be justifiable to return ESTALE here,
277 	 * but the filehandle at-least looks reasonable good
278 	 * and it just be a permission problem, so returning
279 	 * -EACCESS is safer
280 	 */
281 	return ERR_PTR(-EACCES);
282 
283  err_target:
284 	dput(target_dir);
285  err_result:
286 	dput(result);
287  err_out:
288 	return ERR_PTR(err);
289 }
290 
291 
292 
293 static struct dentry *get_parent(struct dentry *child)
294 {
295 	/* get_parent cannot be supported generically, the locking
296 	 * is too icky.
297 	 * instead, we just return EACCES.  If server reboots or inodes
298 	 * get flushed, you lose
299 	 */
300 	return ERR_PTR(-EACCES);
301 }
302 
303 
304 struct getdents_callback {
305 	char *name;		/* name that was found. It already points to a
306 				   buffer NAME_MAX+1 is size */
307 	unsigned long ino;	/* the inum we are looking for */
308 	int found;		/* inode matched? */
309 	int sequence;		/* sequence counter */
310 };
311 
312 /*
313  * A rather strange filldir function to capture
314  * the name matching the specified inode number.
315  */
316 static int filldir_one(void * __buf, const char * name, int len,
317 			loff_t pos, u64 ino, unsigned int d_type)
318 {
319 	struct getdents_callback *buf = __buf;
320 	int result = 0;
321 
322 	buf->sequence++;
323 	if (buf->ino == ino) {
324 		memcpy(buf->name, name, len);
325 		buf->name[len] = '\0';
326 		buf->found = 1;
327 		result = -1;
328 	}
329 	return result;
330 }
331 
332 /**
333  * get_name - default export_operations->get_name function
334  * @dentry: the directory in which to find a name
335  * @name:   a pointer to a %NAME_MAX+1 char buffer to store the name
336  * @child:  the dentry for the child directory.
337  *
338  * calls readdir on the parent until it finds an entry with
339  * the same inode number as the child, and returns that.
340  */
341 static int get_name(struct dentry *dentry, char *name,
342 			struct dentry *child)
343 {
344 	struct inode *dir = dentry->d_inode;
345 	int error;
346 	struct file *file;
347 	struct getdents_callback buffer;
348 
349 	error = -ENOTDIR;
350 	if (!dir || !S_ISDIR(dir->i_mode))
351 		goto out;
352 	error = -EINVAL;
353 	if (!dir->i_fop)
354 		goto out;
355 	/*
356 	 * Open the directory ...
357 	 */
358 	file = dentry_open(dget(dentry), NULL, O_RDONLY);
359 	error = PTR_ERR(file);
360 	if (IS_ERR(file))
361 		goto out;
362 
363 	error = -EINVAL;
364 	if (!file->f_op->readdir)
365 		goto out_close;
366 
367 	buffer.name = name;
368 	buffer.ino = child->d_inode->i_ino;
369 	buffer.found = 0;
370 	buffer.sequence = 0;
371 	while (1) {
372 		int old_seq = buffer.sequence;
373 
374 		error = vfs_readdir(file, filldir_one, &buffer);
375 
376 		if (error < 0)
377 			break;
378 
379 		error = 0;
380 		if (buffer.found)
381 			break;
382 		error = -ENOENT;
383 		if (old_seq == buffer.sequence)
384 			break;
385 	}
386 
387 out_close:
388 	fput(file);
389 out:
390 	return error;
391 }
392 
393 
394 static struct dentry *export_iget(struct super_block *sb, unsigned long ino, __u32 generation)
395 {
396 
397 	/* iget isn't really right if the inode is currently unallocated!!
398 	 * This should really all be done inside each filesystem
399 	 *
400 	 * ext2fs' read_inode has been strengthed to return a bad_inode if
401 	 * the inode had been deleted.
402 	 *
403 	 * Currently we don't know the generation for parent directory, so
404 	 * a generation of 0 means "accept any"
405 	 */
406 	struct inode *inode;
407 	struct dentry *result;
408 	if (ino == 0)
409 		return ERR_PTR(-ESTALE);
410 	inode = iget(sb, ino);
411 	if (inode == NULL)
412 		return ERR_PTR(-ENOMEM);
413 	if (is_bad_inode(inode)
414 	    || (generation && inode->i_generation != generation)
415 		) {
416 		/* we didn't find the right inode.. */
417 		dprintk("fh_verify: Inode %lu, Bad count: %d %d or version  %u %u\n",
418 			inode->i_ino,
419 			inode->i_nlink, atomic_read(&inode->i_count),
420 			inode->i_generation,
421 			generation);
422 
423 		iput(inode);
424 		return ERR_PTR(-ESTALE);
425 	}
426 	/* now to find a dentry.
427 	 * If possible, get a well-connected one
428 	 */
429 	result = d_alloc_anon(inode);
430 	if (!result) {
431 		iput(inode);
432 		return ERR_PTR(-ENOMEM);
433 	}
434 	return result;
435 }
436 
437 
438 static struct dentry *get_object(struct super_block *sb, void *vobjp)
439 {
440 	__u32 *objp = vobjp;
441 	unsigned long ino = objp[0];
442 	__u32 generation = objp[1];
443 
444 	return export_iget(sb, ino, generation);
445 }
446 
447 
448 /**
449  * export_encode_fh - default export_operations->encode_fh function
450  * @dentry:  the dentry to encode
451  * @fh:      where to store the file handle fragment
452  * @max_len: maximum length to store there
453  * @connectable: whether to store parent information
454  *
455  * This default encode_fh function assumes that the 32 inode number
456  * is suitable for locating an inode, and that the generation number
457  * can be used to check that it is still valid.  It places them in the
458  * filehandle fragment where export_decode_fh expects to find them.
459  */
460 static int export_encode_fh(struct dentry *dentry, __u32 *fh, int *max_len,
461 		   int connectable)
462 {
463 	struct inode * inode = dentry->d_inode;
464 	int len = *max_len;
465 	int type = 1;
466 
467 	if (len < 2 || (connectable && len < 4))
468 		return 255;
469 
470 	len = 2;
471 	fh[0] = inode->i_ino;
472 	fh[1] = inode->i_generation;
473 	if (connectable && !S_ISDIR(inode->i_mode)) {
474 		struct inode *parent;
475 
476 		spin_lock(&dentry->d_lock);
477 		parent = dentry->d_parent->d_inode;
478 		fh[2] = parent->i_ino;
479 		fh[3] = parent->i_generation;
480 		spin_unlock(&dentry->d_lock);
481 		len = 4;
482 		type = 2;
483 	}
484 	*max_len = len;
485 	return type;
486 }
487 
488 
489 /**
490  * export_decode_fh - default export_operations->decode_fh function
491  * @sb:  The superblock
492  * @fh:  pointer to the file handle fragment
493  * @fh_len: length of file handle fragment
494  * @acceptable: function for testing acceptability of dentrys
495  * @context:   context for @acceptable
496  *
497  * This is the default decode_fh() function.
498  * a fileid_type of 1 indicates that the filehandlefragment
499  * just contains an object identifier understood by  get_dentry.
500  * a fileid_type of 2 says that there is also a directory
501  * identifier 8 bytes in to the filehandlefragement.
502  */
503 static struct dentry *export_decode_fh(struct super_block *sb, __u32 *fh, int fh_len,
504 			      int fileid_type,
505 			 int (*acceptable)(void *context, struct dentry *de),
506 			 void *context)
507 {
508 	__u32 parent[2];
509 	parent[0] = parent[1] = 0;
510 	if (fh_len < 2 || fileid_type > 2)
511 		return NULL;
512 	if (fileid_type == 2) {
513 		if (fh_len > 2) parent[0] = fh[2];
514 		if (fh_len > 3) parent[1] = fh[3];
515 	}
516 	return find_exported_dentry(sb, fh, parent,
517 				   acceptable, context);
518 }
519 
520 struct export_operations export_op_default = {
521 	.decode_fh	= export_decode_fh,
522 	.encode_fh	= export_encode_fh,
523 
524 	.get_name	= get_name,
525 	.get_parent	= get_parent,
526 	.get_dentry	= get_object,
527 };
528 
529 EXPORT_SYMBOL(export_op_default);
530 EXPORT_SYMBOL(find_exported_dentry);
531 
532 MODULE_LICENSE("GPL");
533