linux-2.6.33/do_generic_file_read()
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
|
ログイン
]
開始行:
*参照元 [#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 lo...
*
* This is really ugly. But the goto's actually try to c...
* of the logic when it comes to error handling etc.
*/
static void do_generic_file_read(struct file *filp, loff...
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 pag...
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) ...
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 Up...
*
* Checking i_size after the check allows us to calcul...
* the correct value for "nr", which means the zero-fi...
* part of the page is not copied back to userspace (u...
* another truncate extends the file - this is desired...
*/
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...
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 actua...
* NOTE! This may not be the same as how much of a use...
* we filled up (we may be padding etc), so we can onl...
* "pos" here (the actor routine has to update the use...
* 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;
-generic_file_aio_read() から呼ばれる場合、actor は file_...
--[[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 pag...
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]
終了行:
*参照元 [#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 lo...
*
* This is really ugly. But the goto's actually try to c...
* of the logic when it comes to error handling etc.
*/
static void do_generic_file_read(struct file *filp, loff...
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 pag...
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) ...
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 Up...
*
* Checking i_size after the check allows us to calcul...
* the correct value for "nr", which means the zero-fi...
* part of the page is not copied back to userspace (u...
* another truncate extends the file - this is desired...
*/
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...
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 actua...
* NOTE! This may not be the same as how much of a use...
* we filled up (we may be padding etc), so we can onl...
* "pos" here (the actor routine has to update the use...
* 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;
-generic_file_aio_read() から呼ばれる場合、actor は file_...
--[[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 pag...
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]
ページ名: