file.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 306 行

C
306
字号
/* file.c: AFS filesystem file handling * * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/slab.h>#include <linux/fs.h>#include <linux/pagemap.h>#include <linux/buffer_head.h>#include "volume.h"#include "vnode.h"#include <rxrpc/call.h>#include "internal.h"#if 0static int afs_file_open(struct inode *inode, struct file *file);static int afs_file_release(struct inode *inode, struct file *file);#endifstatic int afs_file_readpage(struct file *file, struct page *page);static int afs_file_invalidatepage(struct page *page, unsigned long offset);static int afs_file_releasepage(struct page *page, int gfp_flags);static ssize_t afs_file_write(struct file *file, const char __user *buf,			      size_t size, loff_t *off);struct inode_operations afs_file_inode_operations = {	.getattr	= afs_inode_getattr,};struct file_operations afs_file_file_operations = {	.read		= generic_file_read,	.write		= afs_file_write,	.mmap		= generic_file_mmap,#if 0	.open		= afs_file_open,	.release	= afs_file_release,	.fsync		= afs_file_fsync,#endif};struct address_space_operations afs_fs_aops = {	.readpage	= afs_file_readpage,	.sync_page	= block_sync_page,	.set_page_dirty	= __set_page_dirty_nobuffers,	.releasepage	= afs_file_releasepage,	.invalidatepage	= afs_file_invalidatepage,};/*****************************************************************************//* * AFS file write */static ssize_t afs_file_write(struct file *file, const char __user *buf,			      size_t size, loff_t *off){	struct afs_vnode *vnode;	vnode = AFS_FS_I(file->f_dentry->d_inode);	if (vnode->flags & AFS_VNODE_DELETED)		return -ESTALE;	return -EIO;} /* end afs_file_write() *//*****************************************************************************//* * deal with notification that a page was read from the cache */#ifdef AFS_CACHING_SUPPORTstatic void afs_file_readpage_read_complete(void *cookie_data,					    struct page *page,					    void *data,					    int error){	_enter("%p,%p,%p,%d", cookie_data, page, data, error);	if (error)		SetPageError(page);	else		SetPageUptodate(page);	unlock_page(page);} /* end afs_file_readpage_read_complete() */#endif/*****************************************************************************//* * deal with notification that a page was written to the cache */#ifdef AFS_CACHING_SUPPORTstatic void afs_file_readpage_write_complete(void *cookie_data,					     struct page *page,					     void *data,					     int error){	_enter("%p,%p,%p,%d", cookie_data, page, data, error);	unlock_page(page);} /* end afs_file_readpage_write_complete() */#endif/*****************************************************************************//* * AFS read page from file (or symlink) */static int afs_file_readpage(struct file *file, struct page *page){	struct afs_rxfs_fetch_descriptor desc;#ifdef AFS_CACHING_SUPPORT	struct cachefs_page *pageio;#endif	struct afs_vnode *vnode;	struct inode *inode;	int ret;	inode = page->mapping->host;	_enter("{%lu},{%lu}", inode->i_ino, page->index);	vnode = AFS_FS_I(inode);	if (!PageLocked(page))		PAGE_BUG(page);	ret = -ESTALE;	if (vnode->flags & AFS_VNODE_DELETED)		goto error;#ifdef AFS_CACHING_SUPPORT	ret = cachefs_page_get_private(page, &pageio, GFP_NOIO);	if (ret < 0)		goto error;	/* is it cached? */	ret = cachefs_read_or_alloc_page(vnode->cache,					 page,					 afs_file_readpage_read_complete,					 NULL,					 GFP_KERNEL);#else	ret = -ENOBUFS;#endif	switch (ret) {		/* read BIO submitted and wb-journal entry found */	case 1:		BUG(); // TODO - handle wb-journal match		/* read BIO submitted (page in cache) */	case 0:		break;		/* no page available in cache */	case -ENOBUFS:	case -ENODATA:	default:		desc.fid	= vnode->fid;		desc.offset	= page->index << PAGE_CACHE_SHIFT;		desc.size	= min((size_t) (inode->i_size - desc.offset),				      (size_t) PAGE_SIZE);		desc.buffer	= kmap(page);		clear_page(desc.buffer);		/* read the contents of the file from the server into the		 * page */		ret = afs_vnode_fetch_data(vnode, &desc);		kunmap(page);		if (ret < 0) {			if (ret==-ENOENT) {				_debug("got NOENT from server"				       " - marking file deleted and stale");				vnode->flags |= AFS_VNODE_DELETED;				ret = -ESTALE;			}#ifdef AFS_CACHING_SUPPORT			cachefs_uncache_page(vnode->cache, page);#endif			goto error;		}		SetPageUptodate(page);#ifdef AFS_CACHING_SUPPORT		if (cachefs_write_page(vnode->cache,				       page,				       afs_file_readpage_write_complete,				       NULL,				       GFP_KERNEL) != 0		    ) {			cachefs_uncache_page(vnode->cache, page);			unlock_page(page);		}#else		unlock_page(page);#endif	}	_leave(" = 0");	return 0; error:	SetPageError(page);	unlock_page(page);	_leave(" = %d", ret);	return ret;} /* end afs_file_readpage() *//*****************************************************************************//* * get a page cookie for the specified page */#ifdef AFS_CACHING_SUPPORTint afs_cache_get_page_cookie(struct page *page,			      struct cachefs_page **_page_cookie){	int ret;	_enter("");	ret = cachefs_page_get_private(page,_page_cookie, GFP_NOIO);	_leave(" = %d", ret);	return ret;} /* end afs_cache_get_page_cookie() */#endif/*****************************************************************************//* * invalidate part or all of a page */static int afs_file_invalidatepage(struct page *page, unsigned long offset){	int ret = 1;	_enter("{%lu},%lu", page->index, offset);	BUG_ON(!PageLocked(page));	if (PagePrivate(page)) {#ifdef AFS_CACHING_SUPPORT		struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);		cachefs_uncache_page(vnode->cache,page);#endif		/* We release buffers only if the entire page is being		 * invalidated.		 * The get_block cached value has been unconditionally		 * invalidated, so real IO is not possible anymore.		 */		if (offset == 0) {			BUG_ON(!PageLocked(page));			ret = 0;			if (!PageWriteback(page))				ret = page->mapping->a_ops->releasepage(page,									0);		}	}	_leave(" = %d", ret);	return ret;} /* end afs_file_invalidatepage() *//*****************************************************************************//* * release a page and cleanup its private data */static int afs_file_releasepage(struct page *page, int gfp_flags){	struct cachefs_page *pageio;	_enter("{%lu},%x", page->index, gfp_flags);	if (PagePrivate(page)) {#ifdef AFS_CACHING_SUPPORT		struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);		cachefs_uncache_page(vnode->cache, page);#endif		pageio = (struct cachefs_page *) page->private;		page->private = 0;		ClearPagePrivate(page);		if (pageio)			kfree(pageio);	}	_leave(" = 0");	return 0;} /* end afs_file_releasepage() */

⌨️ 快捷键说明

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