mntpt.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 288 行

C
288
字号
/* 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 <linux/mount.h>#include <linux/namei.h>#include <linux/namespace.h>#include "super.h"#include "cell.h"#include "volume.h"#include "vnode.h"#include "internal.h"static struct dentry *afs_mntpt_lookup(struct inode *dir,				       struct dentry *dentry,				       struct nameidata *nd);static int afs_mntpt_open(struct inode *inode, struct file *file);static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd);struct file_operations afs_mntpt_file_operations = {	.open		= afs_mntpt_open,};struct inode_operations afs_mntpt_inode_operations = {	.lookup		= afs_mntpt_lookup,	.follow_link	= afs_mntpt_follow_link,	.readlink	= page_readlink,	.getattr	= afs_inode_getattr,};static LIST_HEAD(afs_vfsmounts);static void afs_mntpt_expiry_timed_out(struct afs_timer *timer);struct afs_timer_ops afs_mntpt_expiry_timer_ops = {	.timed_out	= afs_mntpt_expiry_timed_out,};struct afs_timer afs_mntpt_expiry_timer;unsigned long afs_mntpt_expiry_timeout = 20;/*****************************************************************************//* * 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(struct afs_vnode *vnode){	struct page *page;	filler_t *filler;	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 */	filler = (filler_t *) AFS_VNODE_TO_I(vnode)->i_mapping->a_ops->readpage;	page = read_cache_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0,			       filler, 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,				       struct nameidata *nd){	kenter("%p,%p{%p{%s},%s}",	       dir,	       dentry,	       dentry->d_parent,	       dentry->d_parent ?	       dentry->d_parent->d_name.name : (const unsigned char *) "",	       dentry->d_name.name);	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){	kenter("%p,%p{%p{%s},%s}",	       inode, file,	       file->f_dentry->d_parent,	       file->f_dentry->d_parent ?	       file->f_dentry->d_parent->d_name.name :	       (const unsigned char *) "",	       file->f_dentry->d_name.name);	return -EREMOTE;} /* end afs_mntpt_open() *//*****************************************************************************//* * create a vfsmount to be automounted */static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt){	struct afs_super_info *super;	struct vfsmount *mnt;	struct page *page = NULL;	size_t size;	char *buf, *devname = NULL, *options = NULL;	filler_t *filler;	int ret;	kenter("{%s}", mntpt->d_name.name);	BUG_ON(!mntpt->d_inode);	ret = -EINVAL;	size = mntpt->d_inode->i_size;	if (size > PAGE_SIZE - 1)		goto error;	ret = -ENOMEM;	devname = (char *) get_zeroed_page(GFP_KERNEL);	if (!devname)		goto error;	options = (char *) get_zeroed_page(GFP_KERNEL);	if (!options)		goto error;	/* read the contents of the AFS special symlink */	filler = (filler_t *)mntpt->d_inode->i_mapping->a_ops->readpage;	page = read_cache_page(mntpt->d_inode->i_mapping, 0, filler, NULL);	if (IS_ERR(page)) {		ret = PTR_ERR(page);		goto error;	}	ret = -EIO;	wait_on_page_locked(page);	if (!PageUptodate(page) || PageError(page))		goto error;	buf = kmap(page);	memcpy(devname, buf, size);	kunmap(page);	page_cache_release(page);	page = NULL;	/* work out what options we want */	super = AFS_FS_S(mntpt->d_sb);	memcpy(options, "cell=", 5);	strcpy(options + 5, super->volume->cell->name);	if (super->volume->type == AFSVL_RWVOL)		strcat(options, ",rwpath");	/* try and do the mount */	kdebug("--- attempting mount %s -o %s ---", devname, options);	mnt = do_kern_mount("afs", 0, devname, options);	kdebug("--- mount result %p ---", mnt);	free_page((unsigned long) devname);	free_page((unsigned long) options);	kleave(" = %p", mnt);	return mnt; error:	if (page)		page_cache_release(page);	if (devname)		free_page((unsigned long) devname);	if (options)		free_page((unsigned long) options);	kleave(" = %d", ret);	return ERR_PTR(ret);} /* end afs_mntpt_do_automount() *//*****************************************************************************//* * follow a link from a mountpoint directory, thus causing it to be mounted */static int afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd){	struct vfsmount *newmnt;	struct dentry *old_dentry;	int err;	kenter("%p{%s},{%s:%p{%s}}",	       dentry,	       dentry->d_name.name,	       nd->mnt->mnt_devname,	       dentry,	       nd->dentry->d_name.name);	newmnt = afs_mntpt_do_automount(dentry);	if (IS_ERR(newmnt)) {		path_release(nd);		return PTR_ERR(newmnt);	}	old_dentry = nd->dentry;	nd->dentry = dentry;	err = do_add_mount(newmnt, nd, 0, &afs_vfsmounts);	nd->dentry = old_dentry;	path_release(nd);	if (!err) {		mntget(newmnt);		nd->mnt = newmnt;		dget(newmnt->mnt_root);		nd->dentry = newmnt->mnt_root;	}	kleave(" = %d", err);	return err;} /* end afs_mntpt_follow_link() *//*****************************************************************************//* * handle mountpoint expiry timer going off */static void afs_mntpt_expiry_timed_out(struct afs_timer *timer){	kenter("");	mark_mounts_for_expiry(&afs_vfsmounts);	afs_kafstimod_add_timer(&afs_mntpt_expiry_timer,				afs_mntpt_expiry_timeout * HZ);	kleave("");} /* end afs_mntpt_expiry_timed_out() */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?