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

📄 inode.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Wait for the inode to get unlocked. */static int nfs_wait_on_inode(struct inode *inode){	struct rpc_clnt	*clnt = NFS_CLIENT(inode);	struct nfs_inode *nfsi = NFS_I(inode);	sigset_t oldmask;	int error;	rpc_clnt_sigmask(clnt, &oldmask);	error = wait_on_bit_lock(&nfsi->flags, NFS_INO_REVALIDATING,					nfs_wait_schedule, TASK_INTERRUPTIBLE);	rpc_clnt_sigunmask(clnt, &oldmask);	return error;}static void nfs_wake_up_inode(struct inode *inode){	struct nfs_inode *nfsi = NFS_I(inode);	clear_bit(NFS_INO_REVALIDATING, &nfsi->flags);	smp_mb__after_clear_bit();	wake_up_bit(&nfsi->flags, NFS_INO_REVALIDATING);}int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat){	struct inode *inode = dentry->d_inode;	int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME;	int err;	/* Flush out writes to the server in order to update c/mtime */	if (S_ISREG(inode->i_mode))		nfs_wb_nocommit(inode);	/*	 * We may force a getattr if the user cares about atime.	 *	 * Note that we only have to check the vfsmount flags here:	 *  - NFS always sets S_NOATIME by so checking it would give a	 *    bogus result	 *  - NFS never sets MS_NOATIME or MS_NODIRATIME so there is	 *    no point in checking those.	 */ 	if ((mnt->mnt_flags & MNT_NOATIME) || 	    ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode)))		need_atime = 0;	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);		stat->ino = nfs_compat_user_ino64(NFS_FILEID(inode));	}	return err;}static struct nfs_open_context *alloc_nfs_open_context(struct vfsmount *mnt, struct dentry *dentry, struct rpc_cred *cred){	struct nfs_open_context *ctx;	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);	if (ctx != NULL) {		ctx->path.dentry = dget(dentry);		ctx->path.mnt = mntget(mnt);		ctx->cred = get_rpccred(cred);		ctx->state = NULL;		ctx->lockowner = current->files;		ctx->error = 0;		ctx->dir_cookie = 0;		atomic_set(&ctx->count, 1);	}	return ctx;}struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx){	if (ctx != NULL)		atomic_inc(&ctx->count);	return ctx;}static void __put_nfs_open_context(struct nfs_open_context *ctx, int wait){	struct inode *inode = ctx->path.dentry->d_inode;	if (!atomic_dec_and_lock(&ctx->count, &inode->i_lock))		return;	list_del(&ctx->list);	spin_unlock(&inode->i_lock);	if (ctx->state != NULL) {		if (wait)			nfs4_close_sync(&ctx->path, ctx->state, ctx->mode);		else			nfs4_close_state(&ctx->path, ctx->state, ctx->mode);	}	if (ctx->cred != NULL)		put_rpccred(ctx->cred);	dput(ctx->path.dentry);	mntput(ctx->path.mnt);	kfree(ctx);}void put_nfs_open_context(struct nfs_open_context *ctx){	__put_nfs_open_context(ctx, 0);}static void put_nfs_open_context_sync(struct nfs_open_context *ctx){	__put_nfs_open_context(ctx, 1);}/* * Ensure that mmap has a recent RPC credential for use when writing out * shared pages */static void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx){	struct inode *inode = filp->f_path.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);}/* * Given an inode, search for an open context with the desired characteristics */struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, 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 (cred != NULL && pos->cred != cred)			continue;		if ((pos->mode & mode) == mode) {			ctx = get_nfs_open_context(pos);			break;		}	}	spin_unlock(&inode->i_lock);	return ctx;}static void nfs_file_clear_open_context(struct file *filp){	struct inode *inode = filp->f_path.dentry->d_inode;	struct nfs_open_context *ctx = nfs_file_open_context(filp);	if (ctx) {		filp->private_data = NULL;		spin_lock(&inode->i_lock);		list_move_tail(&ctx->list, &NFS_I(inode)->open_files);		spin_unlock(&inode->i_lock);		put_nfs_open_context_sync(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;	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);	if (IS_ERR(cred))		return PTR_ERR(cred);	ctx = alloc_nfs_open_context(filp->f_path.mnt, filp->f_path.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);	return 0;}int nfs_release(struct inode *inode, struct file *filp){	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);	dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n",		inode->i_sb->s_id, (long long)NFS_FILEID(inode));	nfs_inc_stats(inode, NFSIOS_INODEREVALIDATE);	lock_kernel();	if (is_bad_inode(inode)) 		goto out_nowait;	if (NFS_STALE(inode)) 		goto out_nowait;	status = nfs_wait_on_inode(inode);	if (status < 0)		goto out;	status = -ESTALE;	if (NFS_STALE(inode))		goto out;	status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr);	if (status != 0) {		dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n",			 inode->i_sb->s_id,			 (long long)NFS_FILEID(inode), status);		if (status == -ESTALE) {			nfs_zap_caches(inode);			if (!S_ISDIR(inode->i_mode))				set_bit(NFS_INO_STALE, &NFS_FLAGS(inode));		}		goto out;	}	spin_lock(&inode->i_lock);	status = nfs_update_inode(inode, &fattr);	if (status) {		spin_unlock(&inode->i_lock);		dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n",			 inode->i_sb->s_id,			 (long long)NFS_FILEID(inode), status);		goto out;	}	spin_unlock(&inode->i_lock);	if (nfsi->cache_validity & NFS_INO_INVALID_ACL)		nfs_zap_acl_cache(inode);	dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n",		inode->i_sb->s_id,		(long long)NFS_FILEID(inode)); out:	nfs_wake_up_inode(inode); out_nowait:	unlock_kernel();	return status;}int nfs_attribute_timeout(struct inode *inode){	struct nfs_inode *nfsi = NFS_I(inode);	if (nfs_have_delegation(inode, FMODE_READ))		return 0;	return !time_in_range(jiffies, nfsi->read_cache_jiffies, nfsi->read_cache_jiffies + nfsi->attrtimeo);}/** * nfs_revalidate_inode - Revalidate the inode attributes * @server - pointer to nfs_server struct * @inode - pointer to inode struct * * Updates inode attribute information by retrieving the data from the server. */int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode){	if (!(NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATTR)			&& !nfs_attribute_timeout(inode))		return NFS_STALE(inode) ? -ESTALE : 0;	return __nfs_revalidate_inode(server, inode);}static int nfs_invalidate_mapping_nolock(struct inode *inode, struct address_space *mapping){	struct nfs_inode *nfsi = NFS_I(inode);		if (mapping->nrpages != 0) {		int ret = invalidate_inode_pages2(mapping);		if (ret < 0)			return ret;	}	spin_lock(&inode->i_lock);	nfsi->cache_validity &= ~NFS_INO_INVALID_DATA;	if (S_ISDIR(inode->i_mode))		memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf));	spin_unlock(&inode->i_lock);	nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE);	dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n",			inode->i_sb->s_id, (long long)NFS_FILEID(inode));	return 0;}static int nfs_invalidate_mapping(struct inode *inode, struct address_space *mapping){	int ret = 0;	mutex_lock(&inode->i_mutex);	if (NFS_I(inode)->cache_validity & NFS_INO_INVALID_DATA) {		ret = nfs_sync_mapping(mapping);		if (ret == 0)			ret = nfs_invalidate_mapping_nolock(inode, mapping);	}	mutex_unlock(&inode->i_mutex);	return ret;}/** * nfs_revalidate_mapping_nolock - Revalidate the pagecache * @inode - pointer to host inode * @mapping - pointer to mapping */int nfs_revalidate_mapping_nolock(struct inode *inode, struct address_space *mapping){	struct nfs_inode *nfsi = NFS_I(inode);	int ret = 0;	if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)			|| nfs_attribute_timeout(inode) || NFS_STALE(inode)) {		ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode);		if (ret < 0)			goto out;	}	if (nfsi->cache_validity & NFS_INO_INVALID_DATA)		ret = nfs_invalidate_mapping_nolock(inode, mapping);out:	return ret;}/** * nfs_revalidate_mapping - Revalidate the pagecache * @inode - pointer to host inode * @mapping - pointer to mapping * * This version of the function will take the inode->i_mutex and attempt to * flush out all dirty data if it needs to invalidate the page cache. */int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping){	struct nfs_inode *nfsi = NFS_I(inode);	int ret = 0;	if ((nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)			|| nfs_attribute_timeout(inode) || NFS_STALE(inode)) {		ret = __nfs_revalidate_inode(NFS_SERVER(inode), inode);		if (ret < 0)			goto out;	}	if (nfsi->cache_validity & NFS_INO_INVALID_DATA)		ret = nfs_invalidate_mapping(inode, mapping);out:	return ret;}static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr){	struct nfs_inode *nfsi = NFS_I(inode);	if ((fattr->valid & NFS_ATTR_WCC_V4) != 0 &&			nfsi->change_attr == fattr->pre_change_attr) {		nfsi->change_attr = fattr->change_attr;		if (S_ISDIR(inode->i_mode))			nfsi->cache_validity |= NFS_INO_INVALID_DATA;	}	/* If we have atomic WCC data, we may update some attributes */	if ((fattr->valid & NFS_ATTR_WCC) != 0) {		if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime))			memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));		if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) {			memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));			if (S_ISDIR(inode->i_mode))				nfsi->cache_validity |= NFS_INO_INVALID_DATA;		}		if (inode->i_size == fattr->pre_size && nfsi->npages == 0)			inode->i_size = fattr->size;	}}/** * nfs_check_inode_attributes - verify consistency of the inode attribute cache * @inode - pointer to inode * @fattr - updated attributes * * Verifies the attribute cache. If we have just changed the attributes, * so that fattr carries weak cache consistency data, then it may * also update the ctime/mtime/change_attribute. */static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fattr){	struct nfs_inode *nfsi = NFS_I(inode);	loff_t cur_size, new_isize;	unsigned long invalid = 0;	/* Has the inode gone and changed behind our back? */	if (nfsi->fileid != fattr->fileid			|| (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) {		return -EIO;	}	/* Do atomic weak cache consistency updates */	nfs_wcc_update_inode(inode, fattr);	if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 &&			nfsi->change_attr != fattr->change_attr)		invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE;	/* Verify a few of the more important attributes */	if (!timespec_equal(&inode->i_mtime, &fattr->mtime))		invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE;	cur_size = i_size_read(inode); 	new_isize = nfs_size_to_loff_t(fattr->size);	if (cur_size != new_isize && nfsi->npages == 0)		invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE;

⌨️ 快捷键说明

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