cregit-Linux how code gets into the kernel

Release 4.10 fs/ncpfs/inode.c

Directory: fs/ncpfs
/*
 *  inode.c
 *
 *  Copyright (C) 1995, 1996 by Volker Lendecke
 *  Modified for big endian by J.F. Chadima and David S. Miller
 *  Modified 1997 Peter Waltenberg, Bill Hawes, David Woodhouse for 2.1 dcache
 *  Modified 1998 Wolfram Pienkoss for NLS
 *  Modified 2000 Ben Harris, University of Cambridge for NFS NS meta-info
 *
 */


#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/module.h>

#include <linux/uaccess.h>
#include <asm/byteorder.h>

#include <linux/time.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/string.h>
#include <linux/stat.h>
#include <linux/errno.h>
#include <linux/file.h>
#include <linux/fcntl.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
#include <linux/vfs.h>
#include <linux/mount.h>
#include <linux/seq_file.h>
#include <linux/namei.h>

#include <net/sock.h>

#include "ncp_fs.h"
#include "getopt.h"


#define NCP_DEFAULT_FILE_MODE 0600

#define NCP_DEFAULT_DIR_MODE 0700

#define NCP_DEFAULT_TIME_OUT 10

#define NCP_DEFAULT_RETRY_COUNT 20

static void ncp_evict_inode(struct inode *);
static void ncp_put_super(struct super_block *);
static int  ncp_statfs(struct dentry *, struct kstatfs *);
static int  ncp_show_options(struct seq_file *, struct dentry *);


static struct kmem_cache * ncp_inode_cachep;


static struct inode *ncp_alloc_inode(struct super_block *sb) { struct ncp_inode_info *ei; ei = (struct ncp_inode_info *)kmem_cache_alloc(ncp_inode_cachep, GFP_KERNEL); if (!ei) return NULL; return &ei->vfs_inode; }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds4597.83%150.00%
christoph lameterchristoph lameter12.17%150.00%
Total46100.00%2100.00%


static void ncp_i_callback(struct rcu_head *head) { struct inode *inode = container_of(head, struct inode, i_rcu); kmem_cache_free(ncp_inode_cachep, NCP_FINFO(inode)); }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds1850.00%150.00%
nick pigginnick piggin1850.00%150.00%
Total36100.00%2100.00%


static void ncp_destroy_inode(struct inode *inode) { call_rcu(&inode->i_rcu, ncp_i_callback); }

Contributors

PersonTokensPropCommitsCommitProp
nick pigginnick piggin21100.00%1100.00%
Total21100.00%1100.00%


static void init_once(void *foo) { struct ncp_inode_info *ei = (struct ncp_inode_info *) foo; mutex_init(&ei->open_mutex); inode_init_once(&ei->vfs_inode); }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds3386.84%133.33%
christoph lameterchristoph lameter37.89%133.33%
ingo molnaringo molnar25.26%133.33%
Total38100.00%3100.00%


static int init_inodecache(void) { ncp_inode_cachep = kmem_cache_create("ncp_inode_cache", sizeof(struct ncp_inode_info), 0, (SLAB_RECLAIM_ACCOUNT| SLAB_MEM_SPREAD|SLAB_ACCOUNT), init_once); if (ncp_inode_cachep == NULL) return -ENOMEM; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds3984.78%120.00%
paul jacksonpaul jackson48.70%240.00%
vladimir davydovvladimir davydov24.35%120.00%
andrew mortonandrew morton12.17%120.00%
Total46100.00%5100.00%


static void destroy_inodecache(void) { /* * Make sure all delayed rcu free inodes are flushed before we * destroy cache. */ rcu_barrier(); kmem_cache_destroy(ncp_inode_cachep); }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds1376.47%150.00%
kirill a. shutemovkirill a. shutemov423.53%150.00%
Total17100.00%2100.00%


static int ncp_remount(struct super_block *sb, int *flags, char* data) { sync_filesystem(sb); *flags |= MS_NODIRATIME; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
al viroal viro2784.38%150.00%
theodore tsotheodore tso515.62%150.00%
Total32100.00%2100.00%

static const struct super_operations ncp_sops = { .alloc_inode = ncp_alloc_inode, .destroy_inode = ncp_destroy_inode, .drop_inode = generic_delete_inode, .evict_inode = ncp_evict_inode, .put_super = ncp_put_super, .statfs = ncp_statfs, .remount_fs = ncp_remount, .show_options = ncp_show_options, }; /* * Fill in the ncpfs-specific information in the inode. */
static void ncp_update_dirent(struct inode *inode, struct ncp_entry_info *nwinfo) { NCP_FINFO(inode)->DosDirNum = nwinfo->i.DosDirNum; NCP_FINFO(inode)->dirEntNum = nwinfo->i.dirEntNum; NCP_FINFO(inode)->volNumber = nwinfo->volume; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git4992.45%360.00%
petr vandrovec*petr vandrovec*47.55%240.00%
Total53100.00%5100.00%


void ncp_update_inode(struct inode *inode, struct ncp_entry_info *nwinfo) { ncp_update_dirent(inode, nwinfo); NCP_FINFO(inode)->nwattr = nwinfo->i.attributes; NCP_FINFO(inode)->access = nwinfo->access; memcpy(NCP_FINFO(inode)->file_handle, nwinfo->file_handle, sizeof(nwinfo->file_handle)); ncp_dbg(1, "updated %s, volnum=%d, dirent=%u\n", nwinfo->i.entryName, NCP_FINFO(inode)->volNumber, NCP_FINFO(inode)->dirEntNum); }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git6973.40%466.67%
petr vandrovec*petr vandrovec*2122.34%116.67%
joe perchesjoe perches44.26%116.67%
Total94100.00%6100.00%


static void ncp_update_dates(struct inode *inode, struct nw_info_struct *nwi) { /* NFS namespace mode overrides others if it's set. */ ncp_dbg(1, "(%s) nfs.mode=0%o\n", nwi->entryName, nwi->nfs.mode); if (nwi->nfs.mode) { /* XXX Security? */ inode->i_mode = nwi->nfs.mode; } inode->i_blocks = (i_size_read(inode) + NCP_BLOCK_SIZE - 1) >> NCP_BLOCK_SHIFT; inode->i_mtime.tv_sec = ncp_date_dos2unix(nwi->modifyTime, nwi->modifyDate); inode->i_ctime.tv_sec = ncp_date_dos2unix(nwi->creationTime, nwi->creationDate); inode->i_atime.tv_sec = ncp_date_dos2unix(0, nwi->lastAccessDate); inode->i_atime.tv_nsec = 0; inode->i_mtime.tv_nsec = 0; inode->i_ctime.tv_nsec = 0; }

Contributors

PersonTokensPropCommitsCommitProp
petr vandrovec*petr vandrovec*10773.79%233.33%
andi kleenandi kleen3020.69%116.67%
joe perchesjoe perches42.76%116.67%
petr vandrovecpetr vandrovec32.07%116.67%
pre-gitpre-git10.69%116.67%
Total145100.00%6100.00%


static void ncp_update_attrs(struct inode *inode, struct ncp_entry_info *nwinfo) { struct nw_info_struct *nwi = &nwinfo->i; struct ncp_server *server = NCP_SERVER(inode); if (nwi->attributes & aDIR) { inode->i_mode = server->m.dir_mode; /* for directories dataStreamSize seems to be some Object ID ??? */ i_size_write(inode, NCP_BLOCK_SIZE); } else { u32 size; inode->i_mode = server->m.file_mode; size = le32_to_cpu(nwi->dataStreamSize); i_size_write(inode, size); #ifdef CONFIG_NCPFS_EXTRAS if ((server->m.flags & (NCP_MOUNT_EXTRAS|NCP_MOUNT_SYMLINKS)) && (nwi->attributes & aSHARED)) { switch (nwi->attributes & (aHIDDEN|aSYSTEM)) { case aHIDDEN: if (server->m.flags & NCP_MOUNT_SYMLINKS) { if (/* (size >= NCP_MIN_SYMLINK_SIZE) && */ (size <= NCP_MAX_SYMLINK_SIZE)) { inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK; NCP_FINFO(inode)->flags |= NCPI_KLUDGE_SYMLINK; break; } } /* FALLTHROUGH */ case 0: if (server->m.flags & NCP_MOUNT_EXTRAS) inode->i_mode |= S_IRUGO; break; case aSYSTEM: if (server->m.flags & NCP_MOUNT_EXTRAS) inode->i_mode |= (inode->i_mode >> 2) & S_IXUGO; break; /* case aSYSTEM|aHIDDEN: */ default: /* reserved combination */ break; } } #endif } if (nwi->attributes & aRONLY) inode->i_mode &= ~S_IWUGO; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git22787.31%350.00%
petr vandrovecpetr vandrovec176.54%116.67%
petr vandrovec*petr vandrovec*166.15%233.33%
Total260100.00%6100.00%


void ncp_update_inode2(struct inode* inode, struct ncp_entry_info *nwinfo) { NCP_FINFO(inode)->flags = 0; if (!atomic_read(&NCP_FINFO(inode)->opened)) { NCP_FINFO(inode)->nwattr = nwinfo->i.attributes; ncp_update_attrs(inode, nwinfo); } ncp_update_dates(inode, &nwinfo->i); ncp_update_dirent(inode, nwinfo); }

Contributors

PersonTokensPropCommitsCommitProp
petr vandrovec*petr vandrovec*5368.83%250.00%
pre-gitpre-git2431.17%250.00%
Total77100.00%4100.00%

/* * Fill in the inode based on the ncp_entry_info structure. Used only for brand new inodes. */
static void ncp_set_attr(struct inode *inode, struct ncp_entry_info *nwinfo) { struct ncp_server *server = NCP_SERVER(inode); NCP_FINFO(inode)->flags = 0; ncp_update_attrs(inode, nwinfo); ncp_dbg(2, "inode->i_mode = %u\n", inode->i_mode); set_nlink(inode, 1); inode->i_uid = server->m.uid; inode->i_gid = server->m.gid; ncp_update_dates(inode, &nwinfo->i); ncp_update_inode(inode, nwinfo); }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git7274.23%660.00%
petr vandrovec*petr vandrovec*1717.53%220.00%
joe perchesjoe perches44.12%110.00%
miklos szeredimiklos szeredi44.12%110.00%
Total97100.00%10100.00%

#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) static const struct inode_operations ncp_symlink_inode_operations = { .get_link = page_get_link, .setattr = ncp_notify_change, }; #endif /* * Get a new inode. */
struct inode * ncp_iget(struct super_block *sb, struct ncp_entry_info *info) { struct inode *inode; if (info == NULL) { pr_err("%s: info is NULL\n", __func__); return NULL; } inode = new_inode(sb); if (inode) { atomic_set(&NCP_FINFO(inode)->opened, info->opened); inode->i_ino = info->ino; ncp_set_attr(inode, info); if (S_ISREG(inode->i_mode)) { inode->i_op = &ncp_file_inode_operations; inode->i_fop = &ncp_file_operations; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &ncp_dir_inode_operations; inode->i_fop = &ncp_dir_operations; #ifdef CONFIG_NCPFS_NFS_NS } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { init_special_inode(inode, inode->i_mode, new_decode_dev(info->i.nfs.rdev)); #endif #if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) } else if (S_ISLNK(inode->i_mode)) { inode->i_op = &ncp_symlink_inode_operations; inode_nohighmem(inode); inode->i_data.a_ops = &ncp_symlink_aops; #endif } else { make_bad_inode(inode); } insert_inode_hash(inode); } else pr_err("%s: iget failed!\n", __func__); return inode; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git17566.79%964.29%
petr vandrovec*petr vandrovec*7127.10%17.14%
joe perchesjoe perches83.05%17.14%
al viroal viro83.05%321.43%
Total262100.00%14100.00%


static void ncp_evict_inode(struct inode *inode) { truncate_inode_pages_final(&inode->i_data); clear_inode(inode); if (S_ISDIR(inode->i_mode)) { ncp_dbg(2, "put directory %ld\n", inode->i_ino); } if (ncp_make_closed(inode) != 0) { /* We can't do anything but complain. */ pr_err("%s: could not close\n", __func__); } }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git4366.15%333.33%
joe perchesjoe perches812.31%222.22%
mark fashehmark fasheh710.77%111.11%
al viroal viro57.69%111.11%
jan karajan kara11.54%111.11%
johannes weinerjohannes weiner11.54%111.11%
Total65100.00%9100.00%


static void ncp_stop_tasks(struct ncp_server *server) { struct sock* sk = server->ncp_sock->sk; lock_sock(sk); sk->sk_error_report = server->error_report; sk->sk_data_ready = server->data_ready; sk->sk_write_space = server->write_space; release_sock(sk); del_timer_sync(&server->timeout_tm); flush_work(&server->rcv.tq); if (sk->sk_socket->type == SOCK_STREAM) flush_work(&server->tx.tq); else flush_work(&server->timeout_tq); }

Contributors

PersonTokensPropCommitsCommitProp
petr vandrovec*petr vandrovec*5250.49%120.00%
tejun heotejun heo3836.89%240.00%
petr vandrovecpetr vandrovec109.71%120.00%
arnaldo carvalho de meloarnaldo carvalho de melo32.91%120.00%
Total103100.00%5100.00%


static int ncp_show_options(struct seq_file *seq, struct dentry *root) { struct ncp_server *server = NCP_SBP(root->d_sb); unsigned int tmp; if (!uid_eq(server->m.uid, GLOBAL_ROOT_UID)) seq_printf(seq, ",uid=%u", from_kuid_munged(&init_user_ns, server->m.uid)); if (!gid_eq(server->m.gid, GLOBAL_ROOT_GID)) seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, server->m.gid)); if (!uid_eq(server->m.mounted_uid, GLOBAL_ROOT_UID)) seq_printf(seq, ",owner=%u", from_kuid_munged(&init_user_ns, server->m.mounted_uid)); tmp = server->m.file_mode & S_IALLUGO; if (tmp != NCP_DEFAULT_FILE_MODE) seq_printf(seq, ",mode=0%o", tmp); tmp = server->m.dir_mode & S_IALLUGO; if (tmp != NCP_DEFAULT_DIR_MODE) seq_printf(seq, ",dirmode=0%o", tmp); if (server->m.time_out != NCP_DEFAULT_TIME_OUT * HZ / 100) { tmp = server->m.time_out * 100 / HZ; seq_printf(seq, ",timeout=%u", tmp); } if (server->m.retry_count != NCP_DEFAULT_RETRY_COUNT) seq_printf(seq, ",retry=%u", server->m.retry_count); if (server->m.flags != 0) seq_printf(seq, ",flags=%lu", server->m.flags); if (server->m.wdog_pid != NULL) seq_printf(seq, ",wdogpid=%u", pid_vnr(server->m.wdog_pid)); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
miklos szeredimiklos szeredi25386.35%133.33%
eric w. biedermaneric w. biederman3612.29%133.33%
al viroal viro41.37%133.33%
Total293100.00%3100.00%

static const struct ncp_option ncp_opts[] = { { "uid", OPT_INT, 'u' }, { "gid", OPT_INT, 'g' }, { "owner", OPT_INT, 'o' }, { "mode", OPT_INT, 'm' }, { "dirmode", OPT_INT, 'd' }, { "timeout", OPT_INT, 't' }, { "retry", OPT_INT, 'r' }, { "flags", OPT_INT, 'f' }, { "wdogpid", OPT_INT, 'w' }, { "ncpfd", OPT_INT, 'n' }, { "infofd", OPT_INT, 'i' }, /* v5 */ { "version", OPT_INT, 'v' }, { NULL, 0, 0 } };
static int ncp_parse_options(struct ncp_mount_data_kernel *data, char *options) { int optval; char *optarg; unsigned long optint; int version = 0; int ret; data->flags = 0; data->int_flags = 0; data->mounted_uid = GLOBAL_ROOT_UID; data->wdog_pid = NULL; data->ncp_fd = ~0; data->time_out = NCP_DEFAULT_TIME_OUT; data->retry_count = NCP_DEFAULT_RETRY_COUNT; data->uid = GLOBAL_ROOT_UID; data->gid = GLOBAL_ROOT_GID; data->file_mode = NCP_DEFAULT_FILE_MODE; data->dir_mode = NCP_DEFAULT_DIR_MODE; data->info_fd = -1; data->mounted_vol[0] = 0; while ((optval = ncp_getopt("ncpfs", &options, ncp_opts, NULL, &optarg, &optint)) != 0) { ret = optval; if (ret < 0) goto err; switch (optval) { case 'u': data->uid = make_kuid(current_user_ns(), optint); if (!uid_valid(data->uid)) { ret = -EINVAL; goto err; } break; case 'g': data->gid = make_kgid(current_user_ns(), optint); if (!gid_valid(data->gid)) { ret = -EINVAL; goto err; } break; case 'o': data->mounted_uid = make_kuid(current_user_ns(), optint); if (!uid_valid(data->mounted_uid)) { ret = -EINVAL; goto err; } break; case 'm': data->file_mode = optint; break; case 'd': data->dir_mode = optint; break; case 't': data->time_out = optint; break; case 'r': data->retry_count = optint; break; case 'f': data->flags = optint; break; case 'w': data->wdog_pid = find_get_pid(optint); break; case 'n': data->ncp_fd = optint; break; case 'i': data->info_fd = optint; break; case 'v': ret = -ECHRNG; if (optint < NCP_MOUNT_VERSION_V4) goto err; if (optint > NCP_MOUNT_VERSION_V5) goto err; version = optint; break; } } return 0; err: put_pid(data->wdog_pid); data->wdog_pid = NULL; return ret; }

Contributors

PersonTokensPropCommitsCommitProp
petr vandrovec*petr vandrovec*27868.30%228.57%
eric w. biedermaneric w. biederman10425.55%342.86%
wei yongjunwei yongjun215.16%114.29%
miklos szeredimiklos szeredi40.98%114.29%
Total407100.00%7100.00%


static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent) { struct ncp_mount_data_kernel data; struct ncp_server *server; struct inode *root_inode; struct socket *sock; int error; int default_bufsize; #ifdef CONFIG_NCPFS_PACKET_SIGNING int options; #endif struct ncp_entry_info finfo; memset(&data, 0, sizeof(data)); server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL); if (!server) return -ENOMEM; sb->s_fs_info = server; error = -EFAULT; if (raw_data == NULL) goto out; switch (*(int*)raw_data) { case NCP_MOUNT_VERSION: { struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data; data.flags = md->flags; data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE; data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid); data.wdog_pid = find_get_pid(md->wdog_pid); data.ncp_fd = md->ncp_fd; data.time_out = md->time_out; data.retry_count = md->retry_count; data.uid = make_kuid(current_user_ns(), md->uid); data.gid = make_kgid(current_user_ns(), md->gid); data.file_mode = md->file_mode; data.dir_mode = md->dir_mode; data.info_fd = -1; memcpy(data.mounted_vol, md->mounted_vol, NCP_VOLNAME_LEN+1); } break; case NCP_MOUNT_VERSION_V4: { struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data; data.flags = md->flags; data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid); data.wdog_pid = find_get_pid(md->wdog_pid); data.ncp_fd = md->ncp_fd; data.time_out = md->time_out; data.retry_count = md->retry_count; data.uid = make_kuid(current_user_ns(), md->uid); data.gid = make_kgid(current_user_ns(), md->gid); data.file_mode = md->file_mode; data.dir_mode = md->dir_mode; data.info_fd = -1; } break; default: error = -ECHRNG; if (memcmp(raw_data, "vers", 4) == 0) { error = ncp_parse_options(&data, raw_data); } if (error) goto out; break; } error = -EINVAL; if (!uid_valid(data.mounted_uid) || !uid_valid(data.uid) || !gid_valid(data.gid)) goto out; sock = sockfd_lookup(data.ncp_fd, &error); if (!sock) goto out; if (sock->type == SOCK_STREAM) default_bufsize = 0xF000; else default_bufsize = 1024; sb->s_flags |= MS_NODIRATIME; /* probably even noatime */ sb->s_maxbytes = 0xFFFFFFFFU; sb->s_blocksize = 1024; /* Eh... Is this correct? */ sb->s_blocksize_bits = 10; sb->s_magic = NCP_SUPER_MAGIC; sb->s_op = &ncp_sops; sb->s_d_op = &ncp_dentry_operations; sb->s_bdi = &server->bdi; server = NCP_SBP(sb); memset(server, 0, sizeof(*server)); error = bdi_setup_and_register(&server->bdi, "ncpfs"); if (error) goto out_fput; server->ncp_sock =