cregit-Linux how code gets into the kernel

Release 4.10 fs/afs/mntpt.c

Directory: fs/afs
/* mountpoint management
 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (
 * 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/fs.h>
#include <linux/pagemap.h>
#include <linux/mount.h>
#include <linux/namei.h>
#include <linux/gfp.h>
#include "internal.h"

static struct dentry *afs_mntpt_lookup(struct inode *dir,
				       struct dentry *dentry,
				       unsigned int flags);
static int afs_mntpt_open(struct inode *inode, struct file *file);
static void afs_mntpt_expiry_timed_out(struct work_struct *work);

const struct file_operations afs_mntpt_file_operations = {
	.open		= afs_mntpt_open,
	.llseek		= noop_llseek,

const struct inode_operations afs_mntpt_inode_operations = {
	.lookup		= afs_mntpt_lookup,
	.readlink	= page_readlink,
	.getattr	= afs_getattr,

const struct inode_operations afs_autocell_inode_operations = {
	.getattr	= afs_getattr,

static LIST_HEAD(afs_vfsmounts);
static DECLARE_DELAYED_WORK(afs_mntpt_expiry_timer, afs_mntpt_expiry_timed_out);

static unsigned long afs_mntpt_expiry_timeout = 10 * 60;

 * 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 key *key) { struct page *page; size_t size; char *buf; int ret; _enter("{%x:%u,%u}", vnode->fid.vid, 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, afs_page_filler, key); if (IS_ERR(page)) { ret = PTR_ERR(page); goto out; } ret = -EIO; if (PageError(page)) goto out_free; buf = kmap(page); /* examine the symlink's contents */ size = vnode->status.size; _debug("symlink to %*.*s", (int) size, (int) size, buf); if (size > 2 && (buf[0] == '%' || buf[0] == '#') && buf[size - 1] == '.' ) { _debug("symlink is a mountpoint"); spin_lock(&vnode->lock); set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags); vnode->vfs_inode.i_flags |= S_AUTOMOUNT; spin_unlock(&vnode->lock); } ret = 0; kunmap(page); out_free: put_page(page); out: _leave(" = %d", ret); return ret; }


david howellsdavid howells21389.12%660.00%
andrew mortonandrew morton145.86%110.00%
nick pigginnick piggin72.93%110.00%
al viroal viro41.67%110.00%
kirill a. shutemovkirill a. shutemov10.42%110.00%

/* * no valid lookup procedure on this sort of dir */
static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) { _enter("%p,%p{%pd2}", dir, dentry, dentry); return ERR_PTR(-EREMOTE); }


david howellsdavid howells3587.50%350.00%
al viroal viro410.00%233.33%
trond myklebusttrond myklebust12.50%116.67%

/* * no valid open procedure on this sort of dir */
static int afs_mntpt_open(struct inode *inode, struct file *file) { _enter("%p,%p{%pD2}", inode, file, file); return -EREMOTE; }


david howellsdavid howells3096.77%375.00%
al viroal viro13.23%125.00%

/* * 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 afs_vnode *vnode; struct page *page; char *devname, *options; bool rwpath = false; int ret; _enter("{%pd}", mntpt); BUG_ON(!d_inode(mntpt)); ret = -ENOMEM; devname = (char *) get_zeroed_page(GFP_KERNEL); if (!devname) goto error_no_devname; options = (char *) get_zeroed_page(GFP_KERNEL); if (!options) goto error_no_options; vnode = AFS_FS_I(d_inode(mntpt)); if (test_bit(AFS_VNODE_PSEUDODIR, &vnode->flags)) { /* if the directory is a pseudo directory, use the d_name */ static const char afs_root_cell[] = ":root.cell."; unsigned size = mntpt->d_name.len; ret = -ENOENT; if (size < 2 || size > AFS_MAXCELLNAME) goto error_no_page; if (mntpt->[0] == '.') { devname[0] = '#'; memcpy(devname + 1, mntpt->, size - 1); memcpy(devname + size, afs_root_cell, sizeof(afs_root_cell)); rwpath = true; } else { devname[0] = '%'; memcpy(devname + 1, mntpt->, size); memcpy(devname + size + 1, afs_root_cell, sizeof(afs_root_cell)); } } else { /* read the contents of the AFS special symlink */ loff_t size = i_size_read(d_inode(mntpt)); char *buf; ret = -EINVAL; if (size > PAGE_SIZE - 1) goto error_no_page; page = read_mapping_page(d_inode(mntpt)->i_mapping, 0, NULL); if (IS_ERR(page)) { ret = PTR_ERR(page); goto error_no_page; } ret = -EIO; if (PageError(page)) goto error; buf = kmap_atomic(page); memcpy(devname, buf, size); kunmap_atomic(buf); put_page(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 || rwpath) strcat(options, ",rwpath"); /* try and do the mount */ _debug("--- attempting mount %s -o %s ---", devname, options); mnt = vfs_kern_mount(&afs_fs_type, 0, devname, options); _debug("--- mount result %p ---", mnt); free_page((unsigned long) devname); free_page((unsigned long) options); _leave(" = %p", mnt); return mnt; error: put_page(page); error_no_page: free_page((unsigned long) options); error_no_options: free_page((unsigned long) devname); error_no_devname: _leave(" = %d", ret); return ERR_PTR(ret); }


david howellsdavid howells33161.75%550.00%
wang leiwang lei19836.94%110.00%
trond myklebusttrond myklebust30.56%110.00%
kirill a. shutemovkirill a. shutemov20.37%110.00%
pekka j enbergpekka j enberg10.19%110.00%
al viroal viro10.19%110.00%

/* * handle an automount point */
struct vfsmount *afs_d_automount(struct path *path) { struct vfsmount *newmnt; _enter("{%pd}", path->dentry); newmnt = afs_mntpt_do_automount(path->dentry); if (IS_ERR(newmnt)) return newmnt; mntget(newmnt); /* prevent immediate expiration */ mnt_set_expiry(newmnt, &afs_vfsmounts); queue_delayed_work(afs_wq, &afs_mntpt_expiry_timer, afs_mntpt_expiry_timeout * HZ); _leave(" = %p", newmnt); return newmnt; }


david howellsdavid howells7491.36%450.00%
tejun heotejun heo33.70%112.50%
jan blunckjan blunck22.47%112.50%
al viroal viro22.47%225.00%

/* * handle mountpoint expiry timer going off */
static void afs_mntpt_expiry_timed_out(struct work_struct *work) { _enter(""); if (!list_empty(&afs_vfsmounts)) { mark_mounts_for_expiry(&afs_vfsmounts); queue_delayed_work(afs_wq, &afs_mntpt_expiry_timer, afs_mntpt_expiry_timeout * HZ); } _leave(""); }


david howellsdavid howells4794.00%266.67%
tejun heotejun heo36.00%133.33%

/* * kill the AFS mountpoint timer if it's still running */
void afs_mntpt_kill_timer(void) { _enter(""); ASSERT(list_empty(&afs_vfsmounts)); cancel_delayed_work_sync(&afs_mntpt_expiry_timer); }


david howellsdavid howells2696.30%266.67%
tejun heotejun heo13.70%133.33%

Overall Contributors

david howellsdavid howells88376.19%1238.71%
wang leiwang lei21018.12%13.23%
al viroal viro161.38%516.13%
andrew mortonandrew morton141.21%13.23%
tejun heotejun heo100.86%26.45%
nick pigginnick piggin70.60%13.23%
trond myklebusttrond myklebust50.43%26.45%
arnd bergmannarnd bergmann50.43%13.23%
kirill a. shutemovkirill a. shutemov30.26%13.23%
arjan van de venarjan van de ven20.17%26.45%
jan blunckjan blunck20.17%13.23%
pekka j enbergpekka j enberg10.09%13.23%
adrian bunkadrian bunk10.09%13.23%
Directory: fs/afs
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.