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