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