*参照元 [#oad4fb2b]
#backlinks

*説明 [#o630f803]
-パス: [[linux-2.6.33/mm/filemap.c]]

-FIXME: これは何?
--説明


**引数 [#ceaa3d7e]
-struct file *filp
--
--[[linux-2.6.33/file]]
-loff_t *ppos
--
-read_descriptor_t *desc
--
--[[linux-2.6.33/read_descriptor_t]]
-read_actor_t actor
--
--[[linux-2.6.33/read_actor_t]]


**返り値 [#d77e6268]
-なし


**参考 [#c3c0ff91]


*実装 [#k88b590e]
 /**
  * do_generic_file_read - generic file read routine
  * @filp:	the file to read
  * @ppos:	current file position
  * @desc:	read_descriptor
  * @actor:	read method
  *
  * This is a generic file read routine, and uses the
  * mapping->a_ops->readpage() function for the actual low-level stuff.
  *
  * This is really ugly. But the goto's actually try to clarify some
  * of the logic when it comes to error handling etc.
  */
 static void do_generic_file_read(struct file *filp, loff_t *ppos,
 		read_descriptor_t *desc, read_actor_t actor)
 {
 	struct address_space *mapping = filp->f_mapping;
 	struct inode *inode = mapping->host;
 	struct file_ra_state *ra = &filp->f_ra;
-
--[[linux-2.6.33/address_space]]
-
--[[linux-2.6.33/inode]]
-
--[[linux-2.6.33/file_ra_state]]

 	pgoff_t index;
 	pgoff_t last_index;
 	pgoff_t prev_index;
 	unsigned long offset;      /* offset into pagecache page */
 	unsigned int prev_offset;
 	int error;
 
 	index = *ppos >> PAGE_CACHE_SHIFT;
 	prev_index = ra->prev_pos >> PAGE_CACHE_SHIFT;
 	prev_offset = ra->prev_pos & (PAGE_CACHE_SIZE-1);
 	last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
 	offset = *ppos & ~PAGE_CACHE_MASK;
 
 	for (;;) {
 		struct page *page;
 		pgoff_t end_index;
 		loff_t isize;
 		unsigned long nr, ret;
 
-
--[[linux-2.6.33/page]]

 		cond_resched();
-
--[[linux-2.6.33/cond_resched()]]

 find_page:
 		page = find_get_page(mapping, index);
-
--[[linux-2.6.33/find_get_page()]]

 		if (!page) {
 			page_cache_sync_readahead(mapping,
 					ra, filp,
 					index, last_index - index);
-
--[[linux-2.6.33/page_cache_sync_readahead()]]

 			page = find_get_page(mapping, index);
 			if (unlikely(page == NULL))
 				goto no_cached_page;
-
--[[linux-2.6.33/unlikely()]]

 		}
 		if (PageReadahead(page)) {
-
--[[linux-2.6.33/PageReadahead()]]

 			page_cache_async_readahead(mapping,
 					ra, filp, page,
 					index, last_index - index);
-
--[[linux-2.6.33/page_cache_async_readahead()]]

 		}
 		if (!PageUptodate(page)) {
-
--[[linux-2.6.33/PageUptodate()]]

 			if (inode->i_blkbits == PAGE_CACHE_SHIFT ||
 					!mapping->a_ops->is_partially_uptodate)
 				goto page_not_up_to_date;
 			if (!trylock_page(page))
 				goto page_not_up_to_date;
-mapping->a_ops は address_space_operations 型
--[[linux-2.6.33/address_space_operations]]
-
--[[linux-2.6.33/trylock_page()]]

 			if (!mapping->a_ops->is_partially_uptodate(page,
 								desc, offset))
 				goto page_not_up_to_date_locked;
 			unlock_page(page);
-
--[[linux-2.6.33/unlock_page()]]

 		}
 page_ok:
 		/*
 		 * i_size must be checked after we know the page is Uptodate.
 		 *
 		 * Checking i_size after the check allows us to calculate
 		 * the correct value for "nr", which means the zero-filled
 		 * part of the page is not copied back to userspace (unless
 		 * another truncate extends the file - this is desired though).
 		 */
 
 		isize = i_size_read(inode);
-
--[[linux-2.6.33/i_size_read()]]

 		end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
 		if (unlikely(!isize || index > end_index)) {
 			page_cache_release(page);
 			goto out;
 		}
 
-
--[[linux-2.6.33/page_cache_release()]]

 		/* nr is the maximum number of bytes to copy from this page */
 		nr = PAGE_CACHE_SIZE;
 		if (index == end_index) {
 			nr = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
 			if (nr <= offset) {
 				page_cache_release(page);
 				goto out;
 			}
 		}
 		nr = nr - offset;
 
 		/* If users can be writing to this page using arbitrary
 		 * virtual addresses, take care about potential aliasing
 		 * before reading the page on the kernel side.
 		 */
 		if (mapping_writably_mapped(mapping))
 			flush_dcache_page(page);
 
-
--[[linux-2.6.33/mapping_writably_mapped()]]
-
--[[linux-2.6.33/flush_dcache_page()]]

 		/*
 		 * When a sequential read accesses a page several times,
 		 * only mark it as accessed the first time.
 		 */
 		if (prev_index != index || offset != prev_offset)
 			mark_page_accessed(page);
 		prev_index = index;
 
-
--[[linux-2.6.33/mark_page_accessed()]]

 		/*
 		 * Ok, we have the page, and it's up-to-date, so
 		 * now we can copy it to user space...
 		 *
 		 * The actor routine returns how many bytes were actually used..
 		 * NOTE! This may not be the same as how much of a user buffer
 		 * we filled up (we may be padding etc), so we can only update
 		 * "pos" here (the actor routine has to update the user buffer
 		 * pointers and the remaining count).
 		 */
 		ret = actor(desc, page, offset, nr);
 		offset += ret;
 		index += offset >> PAGE_CACHE_SHIFT;
 		offset &= ~PAGE_CACHE_MASK;
 		prev_offset = offset;
 
-
--[[linux-2.6.33/actor()]]
-generic_file_aio_read() から呼ばれる場合、actor は file_read_actor() が指定されている。
--[[linux-2.6.33/read_actor_t]]
--[[linux-2.6.33/file_read_actor()]]

 		page_cache_release(page);
 		if (ret == nr && desc->count)
 			continue;
 		goto out;
 
 page_not_up_to_date:
 		/* Get exclusive access to the page ... */
 		error = lock_page_killable(page);
 		if (unlikely(error))
 			goto readpage_error;
 
-
--[[linux-2.6.33/lock_page_killable()]]

 page_not_up_to_date_locked:
 		/* Did it get truncated before we got the lock? */
 		if (!page->mapping) {
 			unlock_page(page);
 			page_cache_release(page);
 			continue;
 		}
 
-
--[[linux-2.6.33/unlock_page()]]
-
--[[linux-2.6.33/page_cache_release()]]

 		/* Did somebody else fill it already? */
 		if (PageUptodate(page)) {
 			unlock_page(page);
 			goto page_ok;
 		}
 
-
--[[linux-2.6.33/PageUptodate()]]

 readpage:
 		/* Start the actual read. The read will unlock the page. */
 		error = mapping->a_ops->readpage(filp, page);
 
-mapping->a_ops は address_space_operations 型
--[[linux-2.6.33/address_space_operations]]

 		if (unlikely(error)) {
 			if (error == AOP_TRUNCATED_PAGE) {
 				page_cache_release(page);
 				goto find_page;
 			}
 			goto readpage_error;
 		}
 
 		if (!PageUptodate(page)) {
 			error = lock_page_killable(page);
 			if (unlikely(error))
 				goto readpage_error;
-
--[[linux-2.6.33/lock_page_killable()]]

 			if (!PageUptodate(page)) {
 				if (page->mapping == NULL) {
 					/*
 					 * invalidate_inode_pages got it
 					 */
 					unlock_page(page);
 					page_cache_release(page);
 					goto find_page;
 				}
 				unlock_page(page);
 				shrink_readahead_size_eio(filp, ra);
 				error = -EIO;
 				goto readpage_error;
-
--[[linux-2.6.33/shrink_readahead_size_eio()]]

 			}
 			unlock_page(page);
 		}
 
 		goto page_ok;
 
 readpage_error:
 		/* UHHUH! A synchronous read error occurred. Report it */
 		desc->error = error;
 		page_cache_release(page);
 		goto out;
 
 no_cached_page:
 		/*
 		 * Ok, it wasn't cached, so we need to create a new
 		 * page..
 		 */
 		page = page_cache_alloc_cold(mapping);
 		if (!page) {
 			desc->error = -ENOMEM;
 			goto out;
 		}
-
--[[linux-2.6.33/page_cache_alloc_cold()]]

 		error = add_to_page_cache_lru(page, mapping,
 						index, GFP_KERNEL);
 		if (error) {
 			page_cache_release(page);
 			if (error == -EEXIST)
 				goto find_page;
 			desc->error = error;
 			goto out;
 		}
-
--[[linux-2.6.33/add_to_page_cache_lru()]]
-
--[[linux-2.6.33/page_cache_release()]]

 		goto readpage;
 	}
 
 out:
 	ra->prev_pos = prev_index;
 	ra->prev_pos <<= PAGE_CACHE_SHIFT;
 	ra->prev_pos |= prev_offset;
 
 	*ppos = ((loff_t)index << PAGE_CACHE_SHIFT) + offset;
 	file_accessed(filp);
-
--[[linux-2.6.33/file_accessed()]]

 }


*コメント [#f994dde1]

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS