⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 base.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	unsigned fd = *(unsigned *)ptr; 	struct inode *inode; 	struct proc_inode *ei;	struct dentry *error = ERR_PTR(-ENOENT);	inode = proc_pid_make_inode(dir->i_sb, task);	if (!inode)		goto out;	ei = PROC_I(inode);	ei->fd = fd;	inode->i_mode = S_IFREG | S_IRUSR;	inode->i_fop = &proc_fdinfo_file_operations;	dentry->d_op = &tid_fd_dentry_operations;	d_add(dentry, inode);	/* Close the race of the process dying before we return the dentry */	if (tid_fd_revalidate(dentry, NULL))		error = NULL; out:	return error;}static struct dentry *proc_lookupfdinfo(struct inode *dir,					struct dentry *dentry,					struct nameidata *nd){	return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);}static int proc_readfdinfo(struct file *filp, void *dirent, filldir_t filldir){	return proc_readfd_common(filp, dirent, filldir,				  proc_fdinfo_instantiate);}static const struct file_operations proc_fdinfo_operations = {	.read		= generic_read_dir,	.readdir	= proc_readfdinfo,};/* * proc directories can do almost nothing.. */static const struct inode_operations proc_fdinfo_inode_operations = {	.lookup		= proc_lookupfdinfo,	.setattr	= proc_setattr,};static struct dentry *proc_pident_instantiate(struct inode *dir,	struct dentry *dentry, struct task_struct *task, const void *ptr){	const struct pid_entry *p = ptr;	struct inode *inode;	struct proc_inode *ei;	struct dentry *error = ERR_PTR(-EINVAL);	inode = proc_pid_make_inode(dir->i_sb, task);	if (!inode)		goto out;	ei = PROC_I(inode);	inode->i_mode = p->mode;	if (S_ISDIR(inode->i_mode))		inode->i_nlink = 2;	/* Use getattr to fix if necessary */	if (p->iop)		inode->i_op = p->iop;	if (p->fop)		inode->i_fop = p->fop;	ei->op = p->op;	dentry->d_op = &pid_dentry_operations;	d_add(dentry, inode);	/* Close the race of the process dying before we return the dentry */	if (pid_revalidate(dentry, NULL))		error = NULL;out:	return error;}static struct dentry *proc_pident_lookup(struct inode *dir, 					 struct dentry *dentry,					 const struct pid_entry *ents,					 unsigned int nents){	struct inode *inode;	struct dentry *error;	struct task_struct *task = get_proc_task(dir);	const struct pid_entry *p, *last;	error = ERR_PTR(-ENOENT);	inode = NULL;	if (!task)		goto out_no_task;	/*	 * Yes, it does not scale. And it should not. Don't add	 * new entries into /proc/<tgid>/ without very good reasons.	 */	last = &ents[nents - 1];	for (p = ents; p <= last; p++) {		if (p->len != dentry->d_name.len)			continue;		if (!memcmp(dentry->d_name.name, p->name, p->len))			break;	}	if (p > last)		goto out;	error = proc_pident_instantiate(dir, dentry, task, p);out:	put_task_struct(task);out_no_task:	return error;}static int proc_pident_fill_cache(struct file *filp, void *dirent,	filldir_t filldir, struct task_struct *task, const struct pid_entry *p){	return proc_fill_cache(filp, dirent, filldir, p->name, p->len,				proc_pident_instantiate, task, p);}static int proc_pident_readdir(struct file *filp,		void *dirent, filldir_t filldir,		const struct pid_entry *ents, unsigned int nents){	int i;	struct dentry *dentry = filp->f_path.dentry;	struct inode *inode = dentry->d_inode;	struct task_struct *task = get_proc_task(inode);	const struct pid_entry *p, *last;	ino_t ino;	int ret;	ret = -ENOENT;	if (!task)		goto out_no_task;	ret = 0;	i = filp->f_pos;	switch (i) {	case 0:		ino = inode->i_ino;		if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)			goto out;		i++;		filp->f_pos++;		/* fall through */	case 1:		ino = parent_ino(dentry);		if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)			goto out;		i++;		filp->f_pos++;		/* fall through */	default:		i -= 2;		if (i >= nents) {			ret = 1;			goto out;		}		p = ents + i;		last = &ents[nents - 1];		while (p <= last) {			if (proc_pident_fill_cache(filp, dirent, filldir, task, p) < 0)				goto out;			filp->f_pos++;			p++;		}	}	ret = 1;out:	put_task_struct(task);out_no_task:	return ret;}#ifdef CONFIG_SECURITYstatic ssize_t proc_pid_attr_read(struct file * file, char __user * buf,				  size_t count, loff_t *ppos){	struct inode * inode = file->f_path.dentry->d_inode;	char *p = NULL;	ssize_t length;	struct task_struct *task = get_proc_task(inode);	if (!task)		return -ESRCH;	length = security_getprocattr(task,				      (char*)file->f_path.dentry->d_name.name,				      &p);	put_task_struct(task);	if (length > 0)		length = simple_read_from_buffer(buf, count, ppos, p, length);	kfree(p);	return length;}static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,				   size_t count, loff_t *ppos){	struct inode * inode = file->f_path.dentry->d_inode;	char *page;	ssize_t length;	struct task_struct *task = get_proc_task(inode);	length = -ESRCH;	if (!task)		goto out_no_task;	if (count > PAGE_SIZE)		count = PAGE_SIZE;	/* No partial writes. */	length = -EINVAL;	if (*ppos != 0)		goto out;	length = -ENOMEM;	page = (char*)__get_free_page(GFP_TEMPORARY);	if (!page)		goto out;	length = -EFAULT;	if (copy_from_user(page, buf, count))		goto out_free;	length = security_setprocattr(task,				      (char*)file->f_path.dentry->d_name.name,				      (void*)page, count);out_free:	free_page((unsigned long) page);out:	put_task_struct(task);out_no_task:	return length;}static const struct file_operations proc_pid_attr_operations = {	.read		= proc_pid_attr_read,	.write		= proc_pid_attr_write,};static const struct pid_entry attr_dir_stuff[] = {	REG("current",    S_IRUGO|S_IWUGO, pid_attr),	REG("prev",       S_IRUGO,	   pid_attr),	REG("exec",       S_IRUGO|S_IWUGO, pid_attr),	REG("fscreate",   S_IRUGO|S_IWUGO, pid_attr),	REG("keycreate",  S_IRUGO|S_IWUGO, pid_attr),	REG("sockcreate", S_IRUGO|S_IWUGO, pid_attr),};static int proc_attr_dir_readdir(struct file * filp,			     void * dirent, filldir_t filldir){	return proc_pident_readdir(filp,dirent,filldir,				   attr_dir_stuff,ARRAY_SIZE(attr_dir_stuff));}static const struct file_operations proc_attr_dir_operations = {	.read		= generic_read_dir,	.readdir	= proc_attr_dir_readdir,};static struct dentry *proc_attr_dir_lookup(struct inode *dir,				struct dentry *dentry, struct nameidata *nd){	return proc_pident_lookup(dir, dentry,				  attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff));}static const struct inode_operations proc_attr_dir_inode_operations = {	.lookup		= proc_attr_dir_lookup,	.getattr	= pid_getattr,	.setattr	= proc_setattr,};#endif#if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE)static ssize_t proc_coredump_filter_read(struct file *file, char __user *buf,					 size_t count, loff_t *ppos){	struct task_struct *task = get_proc_task(file->f_dentry->d_inode);	struct mm_struct *mm;	char buffer[PROC_NUMBUF];	size_t len;	int ret;	if (!task)		return -ESRCH;	ret = 0;	mm = get_task_mm(task);	if (mm) {		len = snprintf(buffer, sizeof(buffer), "%08lx\n",			       ((mm->flags & MMF_DUMP_FILTER_MASK) >>				MMF_DUMP_FILTER_SHIFT));		mmput(mm);		ret = simple_read_from_buffer(buf, count, ppos, buffer, len);	}	put_task_struct(task);	return ret;}static ssize_t proc_coredump_filter_write(struct file *file,					  const char __user *buf,					  size_t count,					  loff_t *ppos){	struct task_struct *task;	struct mm_struct *mm;	char buffer[PROC_NUMBUF], *end;	unsigned int val;	int ret;	int i;	unsigned long mask;	ret = -EFAULT;	memset(buffer, 0, sizeof(buffer));	if (count > sizeof(buffer) - 1)		count = sizeof(buffer) - 1;	if (copy_from_user(buffer, buf, count))		goto out_no_task;	ret = -EINVAL;	val = (unsigned int)simple_strtoul(buffer, &end, 0);	if (*end == '\n')		end++;	if (end - buffer == 0)		goto out_no_task;	ret = -ESRCH;	task = get_proc_task(file->f_dentry->d_inode);	if (!task)		goto out_no_task;	ret = end - buffer;	mm = get_task_mm(task);	if (!mm)		goto out_no_mm;	for (i = 0, mask = 1; i < MMF_DUMP_FILTER_BITS; i++, mask <<= 1) {		if (val & mask)			set_bit(i + MMF_DUMP_FILTER_SHIFT, &mm->flags);		else			clear_bit(i + MMF_DUMP_FILTER_SHIFT, &mm->flags);	}	mmput(mm); out_no_mm:	put_task_struct(task); out_no_task:	return ret;}static const struct file_operations proc_coredump_filter_operations = {	.read		= proc_coredump_filter_read,	.write		= proc_coredump_filter_write,};#endif/* * /proc/self: */static int proc_self_readlink(struct dentry *dentry, char __user *buffer,			      int buflen){	char tmp[PROC_NUMBUF];	sprintf(tmp, "%d", task_tgid_vnr(current));	return vfs_readlink(dentry,buffer,buflen,tmp);}static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd){	char tmp[PROC_NUMBUF];	sprintf(tmp, "%d", task_tgid_vnr(current));	return ERR_PTR(vfs_follow_link(nd,tmp));}static const struct inode_operations proc_self_inode_operations = {	.readlink	= proc_self_readlink,	.follow_link	= proc_self_follow_link,};/* * proc base * * These are the directory entries in the root directory of /proc * that properly belong to the /proc filesystem, as they describe * describe something that is process related. */static const struct pid_entry proc_base_stuff[] = {	NOD("self", S_IFLNK|S_IRWXUGO,		&proc_self_inode_operations, NULL, {}),};/* *	Exceptional case: normally we are not allowed to unhash a busy * directory. In this case, however, we can do it - no aliasing problems * due to the way we treat inodes. */static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd){	struct inode *inode = dentry->d_inode;	struct task_struct *task = get_proc_task(inode);	if (task) {		put_task_struct(task);		return 1;	}	d_drop(dentry);	return 0;}static struct dentry_operations proc_base_dentry_operations ={	.d_revalidate	= proc_base_revalidate,	.d_delete	= pid_delete_dentry,};static struct dentry *proc_base_instantiate(struct inode *dir,	struct dentry *dentry, struct task_struct *task, const void *ptr){	const struct pid_entry *p = ptr;	struct inode *inode;	struct proc_inode *ei;	struct dentry *error = ERR_PTR(-EINVAL);	/* Allocate the inode */	error = ERR_PTR(-ENOMEM);	inode = new_inode(dir->i_sb);	if (!inode)		goto out;	/* Initialize the inode */	ei = PROC_I(inode);	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;	/*	 * grab the reference to the task.	 */	ei->pid = get_task_pid(task, PIDTYPE_PID);	if (!ei->pid)		goto out_iput;	inode->i_uid = 0;	inode->i_gid = 0;	inode->i_mode = p->mode;	if (S_ISDIR(inode->i_mode))		inode->i_nlink = 2;	if (S_ISLNK(inode->i_mode))		inode->i_size = 64;	if (p->iop)		inode->i_op = p->iop;	if (p->fop)		inode->i_fop = p->fop;	ei->op = p->op;	dentry->d_op = &proc_base_dentry_operations;	d_add(dentry, inode);	error = NULL;out:	return error;out_iput:	iput(inode);	goto out;}static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry){	struct dentry *error;	struct task_struct *task = get_proc_task(dir);	const struct pid_entry *p, *last;	error = ERR_PTR(-ENOENT);	if (!task)		goto out_no_task;	/* Lookup the directory entry */	last = &proc_base_stuff[ARRAY_SIZE(proc_base_stuff) - 1];	for (p = proc_base_stuff; p <= last; p++) {		if (p->len != dentry->d_name.len)			continue;		if (!memcmp(dentry->d_name.name, p->name, p->len))			break;	}	if (p > last)		goto out;	error = proc_base_instantiate(dir, dentry, task, p);out:	put_task_struct(task);out_no_task:	return error;}static int proc_base_fill_cache(struct file *filp, void *dirent,	filldir_t filldir, struct task_struct *task, const struct pid_entry *p){	return proc_fill_cache(filp, dirent, filldir, p->name, p->len,				proc_base_instantiate, task, p);}#ifdef CONFIG_TASK_IO_ACCOUNTINGstatic int proc_pid_io_accounting(struct task_struct *task, char *buffer){	return sprintf(buffer,#ifdef CONFIG_TASK_XACCT			"rchar: %llu\n"			"wchar: %llu\n"			"syscr: %llu\n"			"syscw: %llu\n"#endif			"read_bytes: %llu\n"			"write_bytes: %llu\n"			"cancelled_write_bytes: %llu\n",#ifdef CONFIG_TASK_XACCT			(unsigned long long)task->rchar,			(unsigned long long)task->wchar,			(unsigned long long)task->syscr,			(unsigned long long)task->syscw,#endif			(unsigned long long)task->ioac.read_bytes,			(unsigned long long)task->ioac.write_bytes,			(unsigned long long)task->ioac.cancelled_write_bytes);}#endif/* * Thread groups */static const struct file_operations proc_task_operations;static const struct inode_operations proc_task_inode_operations;static const struct pid_entry tgid_base_stuff[] = {	DIR("task",       S_IRUGO|S_IXUGO, task),	DIR("fd",         S_IRUSR|S_IXUSR, fd),	DIR("fdinfo",     S_IRUSR|S_IXUSR, fdinfo),	REG("environ",    S_IRUSR, environ),	INF("auxv",       S_IRUSR, pid_auxv),	INF("status",     S_IRUGO, pid_status),	INF("limits",	  S_IRUSR, pid_limits),#ifdef CONFIG_SCHED_DEBUG	REG("sched",      S_IRUGO|S_IWUSR, pid_sched),#endif	INF("cmdline",    S_IRUGO, pid_cmdline),	INF("stat",       S_IRUGO, tgid_stat),

⌨️ 快捷键说明

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