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

📄 inode.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 4 页
字号:
	buf->f_frsize = server->wtmult;	buf->f_bsize = sb->s_blocksize;	blockbits = sb->s_blocksize_bits;	blockres = (1 << blockbits) - 1;	buf->f_blocks = (res.tbytes + blockres) >> blockbits;	buf->f_bfree = (res.fbytes + blockres) >> blockbits;	buf->f_bavail = (res.abytes + blockres) >> blockbits;	buf->f_files = res.tfiles;	buf->f_ffree = res.afiles;	buf->f_namelen = server->namelen; out:	unlock_kernel();	return 0; out_err:	printk(KERN_WARNING "nfs_statfs: statfs error = %d\n", -error);	buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1;	goto out;}static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt){	static struct proc_nfs_info {		int flag;		char *str;		char *nostr;	} nfs_info[] = {		{ NFS_MOUNT_SOFT, ",soft", ",hard" },		{ NFS_MOUNT_INTR, ",intr", "" },		{ NFS_MOUNT_POSIX, ",posix", "" },		{ NFS_MOUNT_TCP, ",tcp", ",udp" },		{ NFS_MOUNT_NOCTO, ",nocto", "" },		{ NFS_MOUNT_NOAC, ",noac", "" },		{ NFS_MOUNT_NONLM, ",nolock", ",lock" },		{ NFS_MOUNT_BROKEN_SUID, ",broken_suid", "" },		{ 0, NULL, NULL }	};	struct proc_nfs_info *nfs_infop;	struct nfs_server *nfss = NFS_SB(mnt->mnt_sb);	seq_printf(m, ",v%d", nfss->rpc_ops->version);	seq_printf(m, ",rsize=%d", nfss->rsize);	seq_printf(m, ",wsize=%d", nfss->wsize);	if (nfss->acregmin != 3*HZ)		seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ);	if (nfss->acregmax != 60*HZ)		seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ);	if (nfss->acdirmin != 30*HZ)		seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ);	if (nfss->acdirmax != 60*HZ)		seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ);	for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) {		if (nfss->flags & nfs_infop->flag)			seq_puts(m, nfs_infop->str);		else			seq_puts(m, nfs_infop->nostr);	}	seq_puts(m, ",addr=");	seq_escape(m, nfss->hostname, " \t\n\\");	return 0;}/* * Invalidate the local caches */voidnfs_zap_caches(struct inode *inode){	struct nfs_inode *nfsi = NFS_I(inode);	int mode = inode->i_mode;	NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);	NFS_ATTRTIMEO_UPDATE(inode) = jiffies;	memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));	if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))		nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;	else		nfsi->flags |= NFS_INO_INVALID_ATTR;}/* * Invalidate, but do not unhash, the inode */static voidnfs_invalidate_inode(struct inode *inode){	umode_t save_mode = inode->i_mode;	make_bad_inode(inode);	inode->i_mode = save_mode;	nfs_zap_caches(inode);}struct nfs_find_desc {	struct nfs_fh		*fh;	struct nfs_fattr	*fattr;};/* * In NFSv3 we can have 64bit inode numbers. In order to support * this, and re-exported directories (also seen in NFSv2) * we are forced to allow 2 different inodes to have the same * i_ino. */static intnfs_find_actor(struct inode *inode, void *opaque){	struct nfs_find_desc	*desc = (struct nfs_find_desc *)opaque;	struct nfs_fh		*fh = desc->fh;	struct nfs_fattr	*fattr = desc->fattr;	if (NFS_FILEID(inode) != fattr->fileid)		return 0;	if (nfs_compare_fh(NFS_FH(inode), fh))		return 0;	if (is_bad_inode(inode))		return 0;	return 1;}static intnfs_init_locked(struct inode *inode, void *opaque){	struct nfs_find_desc	*desc = (struct nfs_find_desc *)opaque;	struct nfs_fattr	*fattr = desc->fattr;	NFS_FILEID(inode) = fattr->fileid;	nfs_copy_fh(NFS_FH(inode), desc->fh);	return 0;}/* Don't use READDIRPLUS on directories that we believe are too large */#define NFS_LIMIT_READDIRPLUS (8*PAGE_SIZE)/* * This is our front-end to iget that looks up inodes by file handle * instead of inode number. */struct inode *nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr){	struct nfs_find_desc desc = {		.fh	= fh,		.fattr	= fattr	};	struct inode *inode = NULL;	unsigned long hash;	if ((fattr->valid & NFS_ATTR_FATTR) == 0)		goto out_no_inode;	if (!fattr->nlink) {		printk("NFS: Buggy server - nlink == 0!\n");		goto out_no_inode;	}	hash = nfs_fattr_to_ino_t(fattr);	if (!(inode = iget5_locked(sb, hash, nfs_find_actor, nfs_init_locked, &desc)))		goto out_no_inode;	if (inode->i_state & I_NEW) {		struct nfs_inode *nfsi = NFS_I(inode);		/* We set i_ino for the few things that still rely on it,		 * such as stat(2) */		inode->i_ino = hash;		/* We can't support update_atime(), since the server will reset it */		inode->i_flags |= S_NOATIME|S_NOCMTIME;		inode->i_mode = fattr->mode;		/* Why so? Because we want revalidate for devices/FIFOs, and		 * that's precisely what we have in nfs_file_inode_operations.		 */		inode->i_op = &nfs_file_inode_operations;		if (S_ISREG(inode->i_mode)) {			inode->i_fop = &nfs_file_operations;			inode->i_data.a_ops = &nfs_file_aops;			inode->i_data.backing_dev_info = &NFS_SB(sb)->backing_dev_info;		} else if (S_ISDIR(inode->i_mode)) {			inode->i_op = NFS_SB(sb)->rpc_ops->dir_inode_ops;			inode->i_fop = &nfs_dir_operations;			if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS)			    && fattr->size <= NFS_LIMIT_READDIRPLUS)				NFS_FLAGS(inode) |= NFS_INO_ADVISE_RDPLUS;		} else if (S_ISLNK(inode->i_mode))			inode->i_op = &nfs_symlink_inode_operations;		else			init_special_inode(inode, inode->i_mode, fattr->rdev);		nfsi->read_cache_jiffies = fattr->timestamp;		inode->i_atime = fattr->atime;		inode->i_mtime = fattr->mtime;		inode->i_ctime = fattr->ctime;		if (fattr->valid & NFS_ATTR_FATTR_V4)			nfsi->change_attr = fattr->change_attr;		inode->i_size = nfs_size_to_loff_t(fattr->size);		inode->i_nlink = fattr->nlink;		inode->i_uid = fattr->uid;		inode->i_gid = fattr->gid;		if (fattr->valid & (NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4)) {			/*			 * report the blocks in 512byte units			 */			inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);			inode->i_blksize = inode->i_sb->s_blocksize;		} else {			inode->i_blocks = fattr->du.nfs2.blocks;			inode->i_blksize = fattr->du.nfs2.blocksize;		}		nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);		nfsi->attrtimeo_timestamp = jiffies;		memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));		nfsi->cache_access.cred = NULL;		unlock_new_inode(inode);	} else		nfs_refresh_inode(inode, fattr);	dprintk("NFS: nfs_fhget(%s/%Ld ct=%d)\n",		inode->i_sb->s_id,		(long long)NFS_FILEID(inode),		atomic_read(&inode->i_count));out:	return inode;out_no_inode:	printk("nfs_fhget: iget failed\n");	goto out;}#define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET)intnfs_setattr(struct dentry *dentry, struct iattr *attr){	struct inode *inode = dentry->d_inode;	struct nfs_fattr fattr;	int error;	if (attr->ia_valid & ATTR_SIZE) {		if (!S_ISREG(inode->i_mode) || attr->ia_size == i_size_read(inode))			attr->ia_valid &= ~ATTR_SIZE;	}	/* Optimization: if the end result is no change, don't RPC */	attr->ia_valid &= NFS_VALID_ATTRS;	if (attr->ia_valid == 0)		return 0;	lock_kernel();	nfs_begin_data_update(inode);	/* Write all dirty data if we're changing file permissions or size */	if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE)) != 0) {		if (filemap_fdatawrite(inode->i_mapping) == 0)			filemap_fdatawait(inode->i_mapping);		nfs_wb_all(inode);	}	error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr);	if (error == 0) {		nfs_refresh_inode(inode, &fattr);		if ((attr->ia_valid & ATTR_MODE) != 0) {			int mode;			mode = inode->i_mode & ~S_IALLUGO;			mode |= attr->ia_mode & S_IALLUGO;			inode->i_mode = mode;		}		if ((attr->ia_valid & ATTR_UID) != 0)			inode->i_uid = attr->ia_uid;		if ((attr->ia_valid & ATTR_GID) != 0)			inode->i_gid = attr->ia_gid;		if ((attr->ia_valid & ATTR_SIZE) != 0) {			inode->i_size = attr->ia_size;			vmtruncate(inode, attr->ia_size);		}	}	if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) {		struct rpc_cred **cred = &NFS_I(inode)->cache_access.cred;		if (*cred) {			put_rpccred(*cred);			*cred = NULL;		}	}	nfs_end_data_update(inode);	unlock_kernel();	return error;}/* * Wait for the inode to get unlocked. * (Used for NFS_INO_LOCKED and NFS_INO_REVALIDATING). */intnfs_wait_on_inode(struct inode *inode, int flag){	struct rpc_clnt	*clnt = NFS_CLIENT(inode);	struct nfs_inode *nfsi = NFS_I(inode);	int error;	if (!(NFS_FLAGS(inode) & flag))		return 0;	atomic_inc(&inode->i_count);	error = nfs_wait_event(clnt, nfsi->nfs_i_wait,				!(NFS_FLAGS(inode) & flag));	iput(inode);	return error;}int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat){	struct inode *inode = dentry->d_inode;	struct nfs_inode *nfsi = NFS_I(inode);	int need_atime = nfsi->flags & NFS_INO_INVALID_ATIME;	int err;	if (__IS_FLG(inode, MS_NOATIME))		need_atime = 0;	else if (__IS_FLG(inode, MS_NODIRATIME) && S_ISDIR(inode->i_mode))		need_atime = 0;	/* We may force a getattr if the user cares about atime */	if (need_atime)		err = __nfs_revalidate_inode(NFS_SERVER(inode), inode);	else		err = nfs_revalidate_inode(NFS_SERVER(inode), inode);	if (!err)		generic_fillattr(inode, stat);	return err;}struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred){	struct nfs_open_context *ctx;	ctx = (struct nfs_open_context *)kmalloc(sizeof(*ctx), GFP_KERNEL);	if (ctx != NULL) {		atomic_set(&ctx->count, 1);		ctx->dentry = dget(dentry);		ctx->cred = get_rpccred(cred);		ctx->state = NULL;		ctx->lockowner = current->files;		ctx->error = 0;		init_waitqueue_head(&ctx->waitq);	}	return ctx;}struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx){	if (ctx != NULL)		atomic_inc(&ctx->count);	return ctx;}void put_nfs_open_context(struct nfs_open_context *ctx){	if (atomic_dec_and_test(&ctx->count)) {		if (ctx->state != NULL)			nfs4_close_state(ctx->state, ctx->mode);		if (ctx->cred != NULL)			put_rpccred(ctx->cred);		dput(ctx->dentry);		kfree(ctx);	}}/* * Ensure that mmap has a recent RPC credential for use when writing out * shared pages */void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx){	struct inode *inode = filp->f_dentry->d_inode;	struct nfs_inode *nfsi = NFS_I(inode);	filp->private_data = get_nfs_open_context(ctx);	spin_lock(&inode->i_lock);	list_add(&ctx->list, &nfsi->open_files);	spin_unlock(&inode->i_lock);}struct nfs_open_context *nfs_find_open_context(struct inode *inode, int mode){	struct nfs_inode *nfsi = NFS_I(inode);	struct nfs_open_context *pos, *ctx = NULL;	spin_lock(&inode->i_lock);	list_for_each_entry(pos, &nfsi->open_files, list) {		if ((pos->mode & mode) == mode) {			ctx = get_nfs_open_context(pos);			break;		}	}	spin_unlock(&inode->i_lock);	return ctx;}void nfs_file_clear_open_context(struct file *filp){	struct inode *inode = filp->f_dentry->d_inode;	struct nfs_open_context *ctx = (struct nfs_open_context *)filp->private_data;	if (ctx) {		filp->private_data = NULL;		spin_lock(&inode->i_lock);		list_del(&ctx->list);		spin_unlock(&inode->i_lock);		put_nfs_open_context(ctx);	}}/* * These allocate and release file read/write context information. */int nfs_open(struct inode *inode, struct file *filp){	struct nfs_open_context *ctx;	struct rpc_cred *cred;	if ((cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0)) == NULL)		return -ENOMEM;	ctx = alloc_nfs_open_context(filp->f_dentry, cred);	put_rpccred(cred);	if (ctx == NULL)		return -ENOMEM;	ctx->mode = filp->f_mode;	nfs_file_set_open_context(filp, ctx);	put_nfs_open_context(ctx);	if ((filp->f_mode & FMODE_WRITE) != 0)		nfs_begin_data_update(inode);	return 0;}int nfs_release(struct inode *inode, struct file *filp){	if ((filp->f_mode & FMODE_WRITE) != 0)		nfs_end_data_update(inode);	nfs_file_clear_open_context(filp);	return 0;}/* * This function is called whenever some part of NFS notices that * the cached attributes have to be refreshed. */int__nfs_revalidate_inode(struct nfs_server *server, struct inode *inode){	int		 status = -ESTALE;	struct nfs_fattr fattr;	struct nfs_inode *nfsi = NFS_I(inode);	unsigned long verifier;	unsigned int flags;	dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n",		inode->i_sb->s_id, (long long)NFS_FILEID(inode));	lock_kernel();	if (!inode || is_bad_inode(inode)) 		goto out_nowait;	if (NFS_STALE(inode) && inode != inode->i_sb->s_root->d_inode) 		goto out_nowait;	while (NFS_REVALIDATING(inode)) {		status = nfs_wait_on_inode(inode, NFS_INO_REVALIDATING);		if (status < 0)			goto out_nowait;		if (NFS_SERVER(inode)->flags & NFS_MOUNT_NOAC)			continue;		if (NFS_FLAGS(inode) & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ATIME))			continue;		status = NFS_STALE(inode) ? -ESTALE : 0;		goto out_nowait;	}	NFS_FLAGS(inode) |= NFS_INO_REVALIDATING;	/* Protect against RPC races by saving the change attribute */	verifier = nfs_save_change_attribute(inode);	status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr);	if (status) {		dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n",			 inode->i_sb->s_id,			 (long long)NFS_FILEID(inode), status);

⌨️ 快捷键说明

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