X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=fs%2Fafs%2Ffile.c;fp=fs%2Fafs%2Ffile.c;h=150b192279228a3dfee74846a6f8f48d38e933fd;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=e8e3680df9ffd03aafae577ca2514c6d452da98a;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/fs/afs/file.c b/fs/afs/file.c index e8e3680df..150b19227 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -16,91 +16,48 @@ #include #include #include -#include #include #include "volume.h" #include "vnode.h" #include #include "internal.h" -#define list_to_page(head) (list_entry((head)->prev, struct page, lru)) - #if 0 static int afs_file_open(struct inode *inode, struct file *file); static int afs_file_release(struct inode *inode, struct file *file); #endif static int afs_file_readpage(struct file *file, struct page *page); -static void afs_file_invalidatepage(struct page *page, unsigned long offset); +static int afs_file_invalidatepage(struct page *page, unsigned long offset); static int afs_file_releasepage(struct page *page, gfp_t gfp_flags); -static int afs_file_mmap(struct file * file, struct vm_area_struct * vma); - -#ifdef CONFIG_AFS_FSCACHE -static int afs_file_readpages(struct file *filp, struct address_space *mapping, - struct list_head *pages, unsigned nr_pages); -static int afs_file_page_mkwrite(struct vm_area_struct *vma, struct page *page); -#endif struct inode_operations afs_file_inode_operations = { .getattr = afs_inode_getattr, }; -const struct file_operations afs_file_file_operations = { - .llseek = generic_file_llseek, - .read = generic_file_read, - .mmap = afs_file_mmap, - .sendfile = generic_file_sendfile, -}; - -const struct address_space_operations afs_fs_aops = { +struct address_space_operations afs_fs_aops = { .readpage = afs_file_readpage, -#ifdef CONFIG_AFS_FSCACHE - .readpages = afs_file_readpages, -#endif .sync_page = block_sync_page, .set_page_dirty = __set_page_dirty_nobuffers, .releasepage = afs_file_releasepage, .invalidatepage = afs_file_invalidatepage, }; -static struct vm_operations_struct afs_fs_vm_operations = { - .nopage = filemap_nopage, - .populate = filemap_populate, -#ifdef CONFIG_AFS_FSCACHE - .page_mkwrite = afs_file_page_mkwrite, -#endif -}; - -/*****************************************************************************/ -/* - * set up a memory mapping on an AFS file - * - we set our own VMA ops so that we can catch the page becoming writable for - * userspace for shared-writable mmap - */ -static int afs_file_mmap(struct file *file, struct vm_area_struct *vma) -{ - _enter(""); - - file_accessed(file); - vma->vm_ops = &afs_fs_vm_operations; - return 0; - -} /* end afs_file_mmap() */ - /*****************************************************************************/ /* * deal with notification that a page was read from the cache */ -#ifdef CONFIG_AFS_FSCACHE -static void afs_file_readpage_read_complete(struct page *page, +#ifdef AFS_CACHING_SUPPORT +static void afs_file_readpage_read_complete(void *cookie_data, + struct page *page, void *data, int error) { - _enter("%p,%p,%d", page, data, error); + _enter("%p,%p,%p,%d", cookie_data, page, data, error); - /* if the read completes with an error, we just unlock the page and let - * the VM reissue the readpage */ - if (!error) + if (error) + SetPageError(page); + else SetPageUptodate(page); unlock_page(page); @@ -111,16 +68,15 @@ static void afs_file_readpage_read_complete(struct page *page, /* * deal with notification that a page was written to the cache */ -#ifdef CONFIG_AFS_FSCACHE -static void afs_file_readpage_write_complete(struct page *page, +#ifdef AFS_CACHING_SUPPORT +static void afs_file_readpage_write_complete(void *cookie_data, + struct page *page, void *data, int error) { - _enter("%p,%p,%d", page, data, error); + _enter("%p,%p,%p,%d", cookie_data, page, data, error); - /* note that the page has been written to the cache and can now be - * modified */ - end_page_fs_misc(page); + unlock_page(page); } /* end afs_file_readpage_write_complete() */ #endif @@ -132,13 +88,16 @@ static void afs_file_readpage_write_complete(struct page *page, 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},%p{%lu}", inode->i_ino, page, page->index); + _enter("{%lu},{%lu}", inode->i_ino, page->index); vnode = AFS_FS_I(inode); @@ -148,9 +107,13 @@ static int afs_file_readpage(struct file *file, struct page *page) if (vnode->flags & AFS_VNODE_DELETED) goto error; -#ifdef CONFIG_AFS_FSCACHE +#ifdef AFS_CACHING_SUPPORT + ret = cachefs_page_get_private(page, &pageio, GFP_NOIO); + if (ret < 0) + goto error; + /* is it cached? */ - ret = fscache_read_or_alloc_page(vnode->cache, + ret = cachefs_read_or_alloc_page(vnode->cache, page, afs_file_readpage_read_complete, NULL, @@ -160,20 +123,18 @@ static int afs_file_readpage(struct file *file, struct page *page) #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; - /* page not yet cached */ - case -ENODATA: - _debug("cache said ENODATA"); - goto go_on; - - /* page will not be cached */ + /* no page available in cache */ case -ENOBUFS: - _debug("cache said ENOBUFS"); + case -ENODATA: default: - go_on: desc.fid = vnode->fid; desc.offset = page->index << PAGE_CACHE_SHIFT; desc.size = min((size_t) (inode->i_size - desc.offset), @@ -187,40 +148,34 @@ static int afs_file_readpage(struct file *file, struct page *page) ret = afs_vnode_fetch_data(vnode, &desc); kunmap(page); if (ret < 0) { - if (ret == -ENOENT) { - kdebug("got NOENT from server" + if (ret==-ENOENT) { + _debug("got NOENT from server" " - marking file deleted and stale"); vnode->flags |= AFS_VNODE_DELETED; ret = -ESTALE; } -#ifdef CONFIG_AFS_FSCACHE - fscache_uncache_page(vnode->cache, page); - ClearPagePrivate(page); +#ifdef AFS_CACHING_SUPPORT + cachefs_uncache_page(vnode->cache, page); #endif goto error; } SetPageUptodate(page); - /* send the page to the cache */ -#ifdef CONFIG_AFS_FSCACHE - if (PagePrivate(page)) { - if (TestSetPageFsMisc(page)) - BUG(); - if (fscache_write_page(vnode->cache, - page, - afs_file_readpage_write_complete, - NULL, - GFP_KERNEL) != 0 - ) { - fscache_uncache_page(vnode->cache, page); - ClearPagePrivate(page); - end_page_fs_misc(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); } -#endif +#else unlock_page(page); +#endif } _leave(" = 0"); @@ -237,87 +192,57 @@ static int afs_file_readpage(struct file *file, struct page *page) /*****************************************************************************/ /* - * read a set of pages + * get a page cookie for the specified page */ -#ifdef CONFIG_AFS_FSCACHE -static int afs_file_readpages(struct file *filp, struct address_space *mapping, - struct list_head *pages, unsigned nr_pages) +#ifdef AFS_CACHING_SUPPORT +int afs_cache_get_page_cookie(struct page *page, + struct cachefs_page **_page_cookie) { - struct afs_vnode *vnode; -#if 0 - struct pagevec lru_pvec; - unsigned page_idx; -#endif - int ret = 0; - - _enter(",{%lu},,%d", mapping->host->i_ino, nr_pages); - - vnode = AFS_FS_I(mapping->host); - if (vnode->flags & AFS_VNODE_DELETED) { - _leave(" = -ESTALE"); - return -ESTALE; - } - - /* attempt to read as many of the pages as possible */ - ret = fscache_read_or_alloc_pages(vnode->cache, - mapping, - pages, - &nr_pages, - afs_file_readpage_read_complete, - NULL, - mapping_gfp_mask(mapping)); - - switch (ret) { - /* all pages are being read from the cache */ - case 0: - BUG_ON(!list_empty(pages)); - BUG_ON(nr_pages != 0); - _leave(" = 0 [reading all]"); - return 0; - - /* there were pages that couldn't be read from the cache */ - case -ENODATA: - case -ENOBUFS: - break; - - /* other error */ - default: - _leave(" = %d", ret); - return ret; - } + int ret; - /* load the missing pages from the network */ - ret = read_cache_pages(mapping, pages, - (void *) afs_file_readpage, NULL); + _enter(""); + ret = cachefs_page_get_private(page,_page_cookie, GFP_NOIO); - _leave(" = %d [netting]", ret); + _leave(" = %d", ret); return ret; - -} /* end afs_file_readpages() */ +} /* end afs_cache_get_page_cookie() */ #endif /*****************************************************************************/ /* * invalidate part or all of a page */ -static void afs_file_invalidatepage(struct page *page, unsigned long offset) +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 && !PageWriteback(page)) - page->mapping->a_ops->releasepage(page, 0); - } + if (offset == 0) { + BUG_ON(!PageLocked(page)); - _leave(""); + ret = 0; + if (!PageWriteback(page)) + ret = page->mapping->a_ops->releasepage(page, + 0); + } + } + _leave(" = %d", ret); + return ret; } /* end afs_file_invalidatepage() */ /*****************************************************************************/ @@ -326,30 +251,23 @@ static void afs_file_invalidatepage(struct page *page, unsigned long offset) */ static int afs_file_releasepage(struct page *page, gfp_t gfp_flags) { + struct cachefs_page *pageio; + _enter("{%lu},%x", page->index, gfp_flags); -#ifdef CONFIG_AFS_FSCACHE - wait_on_page_fs_misc(page); - fscache_uncache_page(AFS_FS_I(page->mapping->host)->cache, page); - ClearPagePrivate(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 - /* indicate that the page can be released */ - _leave(" = 1"); - return 1; + pageio = (struct cachefs_page *) page_private(page); + set_page_private(page, 0); + ClearPagePrivate(page); -} /* end afs_file_releasepage() */ + kfree(pageio); + } -/*****************************************************************************/ -/* - * wait for the disc cache to finish writing before permitting modification of - * our page in the page cache - */ -#ifdef CONFIG_AFS_FSCACHE -static int afs_file_page_mkwrite(struct vm_area_struct *vma, struct page *page) -{ - wait_on_page_fs_misc(page); + _leave(" = 0"); return 0; - -} /* end afs_file_page_mkwrite() */ -#endif +} /* end afs_file_releasepage() */