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

📄 inode.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  inode.c * *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke *  Copyright (C) 1997 by Volker Lendecke * *  Please add a note about your changes to smbfs in the ChangeLog file. */#include <linux/module.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/slab.h>#include <linux/init.h>#include <linux/file.h>#include <linux/dcache.h>#include <linux/smp_lock.h>#include <linux/nls.h>#include <linux/seq_file.h>#include <linux/mount.h>#include <linux/net.h>#include <linux/vfs.h>#include <linux/highuid.h>#include <linux/sched.h>#include <linux/smb_fs.h>#include <linux/smbno.h>#include <linux/smb_mount.h>#include <asm/system.h>#include <asm/uaccess.h>#include "smb_debug.h"#include "getopt.h"#include "proto.h"/* Always pick a default string */#ifdef CONFIG_SMB_NLS_REMOTE#define SMB_NLS_REMOTE CONFIG_SMB_NLS_REMOTE#else#define SMB_NLS_REMOTE ""#endif#define SMB_TTL_DEFAULT 1000static void smb_delete_inode(struct inode *);static void smb_put_super(struct super_block *);static int  smb_statfs(struct dentry *, struct kstatfs *);static int  smb_show_options(struct seq_file *, struct vfsmount *);static struct kmem_cache *smb_inode_cachep;static struct inode *smb_alloc_inode(struct super_block *sb){	struct smb_inode_info *ei;	ei = (struct smb_inode_info *)kmem_cache_alloc(smb_inode_cachep, GFP_KERNEL);	if (!ei)		return NULL;	return &ei->vfs_inode;}static void smb_destroy_inode(struct inode *inode){	kmem_cache_free(smb_inode_cachep, SMB_I(inode));}static void init_once(struct kmem_cache *cachep, void *foo){	struct smb_inode_info *ei = (struct smb_inode_info *) foo;	inode_init_once(&ei->vfs_inode);}static int init_inodecache(void){	smb_inode_cachep = kmem_cache_create("smb_inode_cache",					     sizeof(struct smb_inode_info),					     0, (SLAB_RECLAIM_ACCOUNT|						SLAB_MEM_SPREAD),					     init_once);	if (smb_inode_cachep == NULL)		return -ENOMEM;	return 0;}static void destroy_inodecache(void){	kmem_cache_destroy(smb_inode_cachep);}static int smb_remount(struct super_block *sb, int *flags, char *data){	*flags |= MS_NODIRATIME;	return 0;}static const struct super_operations smb_sops ={	.alloc_inode	= smb_alloc_inode,	.destroy_inode	= smb_destroy_inode,	.drop_inode	= generic_delete_inode,	.delete_inode	= smb_delete_inode,	.put_super	= smb_put_super,	.statfs		= smb_statfs,	.show_options	= smb_show_options,	.remount_fs	= smb_remount,};/* We are always generating a new inode here */struct inode *smb_iget(struct super_block *sb, struct smb_fattr *fattr){	struct smb_sb_info *server = SMB_SB(sb);	struct inode *result;	DEBUG1("smb_iget: %p\n", fattr);	result = new_inode(sb);	if (!result)		return result;	result->i_ino = fattr->f_ino;	SMB_I(result)->open = 0;	SMB_I(result)->fileid = 0;	SMB_I(result)->access = 0;	SMB_I(result)->flags = 0;	SMB_I(result)->closed = 0;	SMB_I(result)->openers = 0;	smb_set_inode_attr(result, fattr);	if (S_ISREG(result->i_mode)) {		result->i_op = &smb_file_inode_operations;		result->i_fop = &smb_file_operations;		result->i_data.a_ops = &smb_file_aops;	} else if (S_ISDIR(result->i_mode)) {		if (server->opt.capabilities & SMB_CAP_UNIX)			result->i_op = &smb_dir_inode_operations_unix;		else			result->i_op = &smb_dir_inode_operations;		result->i_fop = &smb_dir_operations;	} else if (S_ISLNK(result->i_mode)) {		result->i_op = &smb_link_inode_operations;	} else {		init_special_inode(result, result->i_mode, fattr->f_rdev);	}	insert_inode_hash(result);	return result;}/* * Copy the inode data to a smb_fattr structure. */voidsmb_get_inode_attr(struct inode *inode, struct smb_fattr *fattr){	memset(fattr, 0, sizeof(struct smb_fattr));	fattr->f_mode	= inode->i_mode;	fattr->f_nlink	= inode->i_nlink;	fattr->f_ino	= inode->i_ino;	fattr->f_uid	= inode->i_uid;	fattr->f_gid	= inode->i_gid;	fattr->f_size	= inode->i_size;	fattr->f_mtime	= inode->i_mtime;	fattr->f_ctime	= inode->i_ctime;	fattr->f_atime	= inode->i_atime;	fattr->f_blocks	= inode->i_blocks;	fattr->attr	= SMB_I(inode)->attr;	/*	 * Keep the attributes in sync with the inode permissions.	 */	if (fattr->f_mode & S_IWUSR)		fattr->attr &= ~aRONLY;	else		fattr->attr |= aRONLY;}/* * Update the inode, possibly causing it to invalidate its pages if mtime/size * is different from last time. */voidsmb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr){	struct smb_inode_info *ei = SMB_I(inode);	/*	 * A size change should have a different mtime, or same mtime	 * but different size.	 */	time_t last_time = inode->i_mtime.tv_sec;	loff_t last_sz = inode->i_size;	inode->i_mode	= fattr->f_mode;	inode->i_nlink	= fattr->f_nlink;	inode->i_uid	= fattr->f_uid;	inode->i_gid	= fattr->f_gid;	inode->i_ctime	= fattr->f_ctime;	inode->i_blocks = fattr->f_blocks;	inode->i_size	= fattr->f_size;	inode->i_mtime	= fattr->f_mtime;	inode->i_atime	= fattr->f_atime;	ei->attr = fattr->attr;	/*	 * Update the "last time refreshed" field for revalidation.	 */	ei->oldmtime = jiffies;	if (inode->i_mtime.tv_sec != last_time || inode->i_size != last_sz) {		VERBOSE("%ld changed, old=%ld, new=%ld, oz=%ld, nz=%ld\n",			inode->i_ino,			(long) last_time, (long) inode->i_mtime.tv_sec,			(long) last_sz, (long) inode->i_size);		if (!S_ISDIR(inode->i_mode))			invalidate_remote_inode(inode);	}}/* * This is called if the connection has gone bad ... * try to kill off all the current inodes. */voidsmb_invalidate_inodes(struct smb_sb_info *server){	VERBOSE("\n");	shrink_dcache_sb(SB_of(server));	invalidate_inodes(SB_of(server));}/* * This is called to update the inode attributes after * we've made changes to a file or directory. */static intsmb_refresh_inode(struct dentry *dentry){	struct inode *inode = dentry->d_inode;	int error;	struct smb_fattr fattr;	error = smb_proc_getattr(dentry, &fattr);	if (!error) {		smb_renew_times(dentry);		/*		 * Check whether the type part of the mode changed,		 * and don't update the attributes if it did.		 *		 * And don't dick with the root inode		 */		if (inode->i_ino == 2)			return error;		if (S_ISLNK(inode->i_mode))			return error;	/* VFS will deal with it */		if ((inode->i_mode & S_IFMT) == (fattr.f_mode & S_IFMT)) {			smb_set_inode_attr(inode, &fattr);		} else {			/*			 * Big trouble! The inode has become a new object,			 * so any operations attempted on it are invalid.			 *			 * To limit damage, mark the inode as bad so that			 * subsequent lookup validations will fail.			 */			PARANOIA("%s/%s changed mode, %07o to %07o\n",				 DENTRY_PATH(dentry),				 inode->i_mode, fattr.f_mode);			fattr.f_mode = inode->i_mode; /* save mode */			make_bad_inode(inode);			inode->i_mode = fattr.f_mode; /* restore mode */			/*			 * No need to worry about unhashing the dentry: the			 * lookup validation will see that the inode is bad.			 * But we do want to invalidate the caches ...			 */			if (!S_ISDIR(inode->i_mode))				invalidate_remote_inode(inode);			else				smb_invalid_dir_cache(inode);			error = -EIO;		}	}	return error;}/* * This is called when we want to check whether the inode * has changed on the server.  If it has changed, we must * invalidate our local caches. */intsmb_revalidate_inode(struct dentry *dentry){	struct smb_sb_info *s = server_from_dentry(dentry);	struct inode *inode = dentry->d_inode;	int error = 0;	DEBUG1("smb_revalidate_inode\n");	lock_kernel();	/*	 * Check whether we've recently refreshed the inode.	 */	if (time_before(jiffies, SMB_I(inode)->oldmtime + SMB_MAX_AGE(s))) {		VERBOSE("up-to-date, ino=%ld, jiffies=%lu, oldtime=%lu\n",			inode->i_ino, jiffies, SMB_I(inode)->oldmtime);		goto out;	}	error = smb_refresh_inode(dentry);out:	unlock_kernel();	return error;}/* * This routine is called when i_nlink == 0 and i_count goes to 0. * All blocking cleanup operations need to go here to avoid races. */static voidsmb_delete_inode(struct inode *ino){	DEBUG1("ino=%ld\n", ino->i_ino);	truncate_inode_pages(&ino->i_data, 0);	lock_kernel();	if (smb_close(ino))		PARANOIA("could not close inode %ld\n", ino->i_ino);	unlock_kernel();	clear_inode(ino);}static struct option opts[] = {	{ "version",	0, 'v' },	{ "win95",	SMB_MOUNT_WIN95, 1 },	{ "oldattr",	SMB_MOUNT_OLDATTR, 1 },	{ "dirattr",	SMB_MOUNT_DIRATTR, 1 },	{ "case",	SMB_MOUNT_CASE, 1 },	{ "uid",	0, 'u' },	{ "gid",	0, 'g' },	{ "file_mode",	0, 'f' },	{ "dir_mode",	0, 'd' },	{ "iocharset",	0, 'i' },	{ "codepage",	0, 'c' },	{ "ttl",	0, 't' },	{ NULL,		0, 0}};static intparse_options(struct smb_mount_data_kernel *mnt, char *options){	int c;	unsigned long flags;	unsigned long value;	char *optarg;	char *optopt;	flags = 0;	while ( (c = smb_getopt("smbfs", &options, opts,				&optopt, &optarg, &flags, &value)) > 0) {		VERBOSE("'%s' -> '%s'\n", optopt, optarg ? optarg : "<none>");		switch (c) {		case 1:			/* got a "flag" option */			break;		case 'v':			if (value != SMB_MOUNT_VERSION) {			printk ("smbfs: Bad mount version %ld, expected %d\n",				value, SMB_MOUNT_VERSION);				return 0;			}			mnt->version = value;			break;		case 'u':			mnt->uid = value;			flags |= SMB_MOUNT_UID;			break;		case 'g':			mnt->gid = value;			flags |= SMB_MOUNT_GID;			break;		case 'f':			mnt->file_mode = (value & S_IRWXUGO) | S_IFREG;			flags |= SMB_MOUNT_FMODE;			break;		case 'd':			mnt->dir_mode = (value & S_IRWXUGO) | S_IFDIR;			flags |= SMB_MOUNT_DMODE;			break;		case 'i':			strlcpy(mnt->codepage.local_name, optarg, 				SMB_NLS_MAXNAMELEN);			break;		case 'c':			strlcpy(mnt->codepage.remote_name, optarg,				SMB_NLS_MAXNAMELEN);			break;		case 't':			mnt->ttl = value;			break;		default:			printk ("smbfs: Unrecognized mount option %s\n",				optopt);			return -1;		}	}	mnt->flags = flags;	return c;}

⌨️ 快捷键说明

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