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

📄 read.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		nfs_list_add_request(req, &data->pages);		ClearPageError(req->wb_page);		*pages++ = req->wb_page;	}	req = nfs_list_entry(data->pages.next);	nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0);	nfs_execute_read(data);	return 0;out_bad:	nfs_async_read_error(head);	return -ENOMEM;}/* * This is the callback from RPC telling us whether a reply was * received or some error occurred (timeout or socket shutdown). */int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data){	int status;	dprintk("NFS: %s: %5u, (status %d)\n", __FUNCTION__, task->tk_pid,			task->tk_status);	status = NFS_PROTO(data->inode)->read_done(task, data);	if (status != 0)		return status;	nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, data->res.count);	if (task->tk_status == -ESTALE) {		set_bit(NFS_INO_STALE, &NFS_FLAGS(data->inode));		nfs_mark_for_revalidate(data->inode);	}	return 0;}static int nfs_readpage_retry(struct rpc_task *task, struct nfs_read_data *data){	struct nfs_readargs *argp = &data->args;	struct nfs_readres *resp = &data->res;	if (resp->eof || resp->count == argp->count)		return 0;	/* This is a short read! */	nfs_inc_stats(data->inode, NFSIOS_SHORTREAD);	/* Has the server at least made some progress? */	if (resp->count == 0)		return 0;	/* Yes, so retry the read at the end of the data */	argp->offset += resp->count;	argp->pgbase += resp->count;	argp->count -= resp->count;	rpc_restart_call(task);	return -EAGAIN;}/* * Handle a read reply that fills part of a page. */static void nfs_readpage_result_partial(struct rpc_task *task, void *calldata){	struct nfs_read_data *data = calldata;	struct nfs_page *req = data->req;	struct page *page = req->wb_page; 	if (nfs_readpage_result(task, data) != 0)		return;	if (likely(task->tk_status >= 0)) {		nfs_readpage_truncate_uninitialised_page(data);		if (nfs_readpage_retry(task, data) != 0)			return;	}	if (unlikely(task->tk_status < 0))		SetPageError(page);	if (atomic_dec_and_test(&req->wb_complete)) {		if (!PageError(page))			SetPageUptodate(page);		nfs_readpage_release(req);	}}static const struct rpc_call_ops nfs_read_partial_ops = {	.rpc_call_done = nfs_readpage_result_partial,	.rpc_release = nfs_readdata_release,};static void nfs_readpage_set_pages_uptodate(struct nfs_read_data *data){	unsigned int count = data->res.count;	unsigned int base = data->args.pgbase;	struct page **pages;	if (data->res.eof)		count = data->args.count;	if (unlikely(count == 0))		return;	pages = &data->args.pages[base >> PAGE_CACHE_SHIFT];	base &= ~PAGE_CACHE_MASK;	count += base;	for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++)		SetPageUptodate(*pages);	if (count == 0)		return;	/* Was this a short read? */	if (data->res.eof || data->res.count == data->args.count)		SetPageUptodate(*pages);}/* * This is the callback from RPC telling us whether a reply was * received or some error occurred (timeout or socket shutdown). */static void nfs_readpage_result_full(struct rpc_task *task, void *calldata){	struct nfs_read_data *data = calldata;	if (nfs_readpage_result(task, data) != 0)		return;	/*	 * Note: nfs_readpage_retry may change the values of	 * data->args. In the multi-page case, we therefore need	 * to ensure that we call nfs_readpage_set_pages_uptodate()	 * first.	 */	if (likely(task->tk_status >= 0)) {		nfs_readpage_truncate_uninitialised_page(data);		nfs_readpage_set_pages_uptodate(data);		if (nfs_readpage_retry(task, data) != 0)			return;	}	while (!list_empty(&data->pages)) {		struct nfs_page *req = nfs_list_entry(data->pages.next);		nfs_list_remove_request(req);		nfs_readpage_release(req);	}}static const struct rpc_call_ops nfs_read_full_ops = {	.rpc_call_done = nfs_readpage_result_full,	.rpc_release = nfs_readdata_release,};/* * Read a page over NFS. * We read the page synchronously in the following case: *  -	The error flag is set for this page. This happens only when a *	previous async read operation failed. */int nfs_readpage(struct file *file, struct page *page){	struct nfs_open_context *ctx;	struct inode *inode = page->mapping->host;	int		error;	dprintk("NFS: nfs_readpage (%p %ld@%lu)\n",		page, PAGE_CACHE_SIZE, page->index);	nfs_inc_stats(inode, NFSIOS_VFSREADPAGE);	nfs_add_stats(inode, NFSIOS_READPAGES, 1);	/*	 * Try to flush any pending writes to the file..	 *	 * NOTE! Because we own the page lock, there cannot	 * be any new pending writes generated at this point	 * for this page (other pages can be written to).	 */	error = nfs_wb_page(inode, page);	if (error)		goto out_unlock;	if (PageUptodate(page))		goto out_unlock;	error = -ESTALE;	if (NFS_STALE(inode))		goto out_unlock;	if (file == NULL) {		error = -EBADF;		ctx = nfs_find_open_context(inode, NULL, FMODE_READ);		if (ctx == NULL)			goto out_unlock;	} else		ctx = get_nfs_open_context(nfs_file_open_context(file));	error = nfs_readpage_async(ctx, inode, page);	put_nfs_open_context(ctx);	return error;out_unlock:	unlock_page(page);	return error;}struct nfs_readdesc {	struct nfs_pageio_descriptor *pgio;	struct nfs_open_context *ctx;};static intreadpage_async_filler(void *data, struct page *page){	struct nfs_readdesc *desc = (struct nfs_readdesc *)data;	struct inode *inode = page->mapping->host;	struct nfs_page *new;	unsigned int len;	int error;	error = nfs_wb_page(inode, page);	if (error)		goto out_unlock;	if (PageUptodate(page))		goto out_unlock;	len = nfs_page_length(page);	if (len == 0)		return nfs_return_empty_page(page);	new = nfs_create_request(desc->ctx, inode, page, 0, len);	if (IS_ERR(new))		goto out_error;	if (len < PAGE_CACHE_SIZE)		zero_user_page(page, len, PAGE_CACHE_SIZE - len, KM_USER0);	nfs_pageio_add_request(desc->pgio, new);	return 0;out_error:	error = PTR_ERR(new);	SetPageError(page);out_unlock:	unlock_page(page);	return error;}int nfs_readpages(struct file *filp, struct address_space *mapping,		struct list_head *pages, unsigned nr_pages){	struct nfs_pageio_descriptor pgio;	struct nfs_readdesc desc = {		.pgio = &pgio,	};	struct inode *inode = mapping->host;	struct nfs_server *server = NFS_SERVER(inode);	size_t rsize = server->rsize;	unsigned long npages;	int ret = -ESTALE;	dprintk("NFS: nfs_readpages (%s/%Ld %d)\n",			inode->i_sb->s_id,			(long long)NFS_FILEID(inode),			nr_pages);	nfs_inc_stats(inode, NFSIOS_VFSREADPAGES);	if (NFS_STALE(inode))		goto out;	if (filp == NULL) {		desc.ctx = nfs_find_open_context(inode, NULL, FMODE_READ);		if (desc.ctx == NULL)			return -EBADF;	} else		desc.ctx = get_nfs_open_context(nfs_file_open_context(filp));	if (rsize < PAGE_CACHE_SIZE)		nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0);	else		nfs_pageio_init(&pgio, inode, nfs_pagein_one, rsize, 0);	ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc);	nfs_pageio_complete(&pgio);	npages = (pgio.pg_bytes_written + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;	nfs_add_stats(inode, NFSIOS_READPAGES, npages);	put_nfs_open_context(desc.ctx);out:	return ret;}int __init nfs_init_readpagecache(void){	nfs_rdata_cachep = kmem_cache_create("nfs_read_data",					     sizeof(struct nfs_read_data),					     0, SLAB_HWCACHE_ALIGN,					     NULL);	if (nfs_rdata_cachep == NULL)		return -ENOMEM;	nfs_rdata_mempool = mempool_create_slab_pool(MIN_POOL_READ,						     nfs_rdata_cachep);	if (nfs_rdata_mempool == NULL)		return -ENOMEM;	return 0;}void nfs_destroy_readpagecache(void){	mempool_destroy(nfs_rdata_mempool);	kmem_cache_destroy(nfs_rdata_cachep);}

⌨️ 快捷键说明

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