Merge with 2.5.75.
[linux-2.6/linux-mips.git] / fs / afs / mntpt.c
blobd22887d47f38879e4e2c121667c5bac3286df348
1 /* mntpt.c: mountpoint management
3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/sched.h>
16 #include <linux/slab.h>
17 #include <linux/fs.h>
18 #include <linux/pagemap.h>
19 #include "volume.h"
20 #include "vnode.h"
21 #include "internal.h"
24 static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *);
25 static int afs_mntpt_open(struct inode *inode, struct file *file);
27 struct file_operations afs_mntpt_file_operations = {
28 .open = afs_mntpt_open,
31 struct inode_operations afs_mntpt_inode_operations = {
32 .lookup = afs_mntpt_lookup,
33 .readlink = page_readlink,
34 .getattr = afs_inode_getattr,
37 /*****************************************************************************/
39 * check a symbolic link to see whether it actually encodes a mountpoint
40 * - sets the AFS_VNODE_MOUNTPOINT flag on the vnode appropriately
42 int afs_mntpt_check_symlink(afs_vnode_t *vnode)
44 struct page *page;
45 size_t size;
46 char *buf;
47 int ret;
49 _enter("{%u,%u}",vnode->fid.vnode,vnode->fid.unique);
51 /* read the contents of the symlink into the pagecache */
52 page = read_cache_page(AFS_VNODE_TO_I(vnode)->i_mapping,0,
53 (filler_t*)AFS_VNODE_TO_I(vnode)->i_mapping->a_ops->readpage,NULL);
54 if (IS_ERR(page)) {
55 ret = PTR_ERR(page);
56 goto out;
59 ret = -EIO;
60 wait_on_page_locked(page);
61 buf = kmap(page);
62 if (!PageUptodate(page))
63 goto out_free;
64 if (PageError(page))
65 goto out_free;
67 /* examine the symlink's contents */
68 size = vnode->status.size;
69 _debug("symlink to %*.*s",size,(int)size,buf);
71 if (size>2 &&
72 (buf[0]=='%' || buf[0]=='#') &&
73 buf[size-1]=='.'
74 ) {
75 _debug("symlink is a mountpoint");
76 spin_lock(&vnode->lock);
77 vnode->flags |= AFS_VNODE_MOUNTPOINT;
78 spin_unlock(&vnode->lock);
81 ret = 0;
83 out_free:
84 kunmap(page);
85 page_cache_release(page);
86 out:
87 _leave(" = %d",ret);
88 return ret;
90 } /* end afs_mntpt_check_symlink() */
92 /*****************************************************************************/
94 * no valid lookup procedure on this sort of dir
96 static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
98 return ERR_PTR(-EREMOTE);
99 } /* end afs_mntpt_lookup() */
101 /*****************************************************************************/
103 * no valid open procedure on this sort of dir
105 static int afs_mntpt_open(struct inode *inode, struct file *file)
107 return -EREMOTE;
108 } /* end afs_mntpt_open() */