📄 file.c
字号:
/* AFS filesystem file handling * * Copyright (C) 2002, 2007 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/slab.h>#include <linux/fs.h>#include <linux/pagemap.h>#include <linux/writeback.h>#include "internal.h"static int afs_readpage(struct file *file, struct page *page);static void afs_invalidatepage(struct page *page, unsigned long offset);static int afs_releasepage(struct page *page, gfp_t gfp_flags);static int afs_launder_page(struct page *page);const struct file_operations afs_file_operations = { .open = afs_open, .release = afs_release, .llseek = generic_file_llseek, .read = do_sync_read, .write = do_sync_write, .aio_read = generic_file_aio_read, .aio_write = afs_file_write, .mmap = generic_file_readonly_mmap, .splice_read = generic_file_splice_read, .fsync = afs_fsync, .lock = afs_lock, .flock = afs_flock,};const struct inode_operations afs_file_inode_operations = { .getattr = afs_getattr, .setattr = afs_setattr, .permission = afs_permission,};const struct address_space_operations afs_fs_aops = { .readpage = afs_readpage, .set_page_dirty = afs_set_page_dirty, .launder_page = afs_launder_page, .releasepage = afs_releasepage, .invalidatepage = afs_invalidatepage, .prepare_write = afs_prepare_write, .commit_write = afs_commit_write, .writepage = afs_writepage, .writepages = afs_writepages,};/* * open an AFS file or directory and attach a key to it */int afs_open(struct inode *inode, struct file *file){ struct afs_vnode *vnode = AFS_FS_I(inode); struct key *key; int ret; _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode); key = afs_request_key(vnode->volume->cell); if (IS_ERR(key)) { _leave(" = %ld [key]", PTR_ERR(key)); return PTR_ERR(key); } ret = afs_validate(vnode, key); if (ret < 0) { _leave(" = %d [val]", ret); return ret; } file->private_data = key; _leave(" = 0"); return 0;}/* * release an AFS file or directory and discard its key */int afs_release(struct inode *inode, struct file *file){ struct afs_vnode *vnode = AFS_FS_I(inode); _enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode); key_put(file->private_data); _leave(" = 0"); return 0;}/* * deal with notification that a page was read from the cache */#ifdef AFS_CACHING_SUPPORTstatic void afs_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);}#endif/* * deal with notification that a page was written to the cache */#ifdef AFS_CACHING_SUPPORTstatic void afs_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);}#endif/* * AFS read page from file, directory or symlink */static int afs_readpage(struct file *file, struct page *page){ struct afs_vnode *vnode; struct inode *inode; struct key *key; size_t len; off_t offset; int ret; inode = page->mapping->host; ASSERT(file != NULL); key = file->private_data; ASSERT(key != NULL); _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index); vnode = AFS_FS_I(inode); BUG_ON(!PageLocked(page)); ret = -ESTALE; if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) goto error;#ifdef AFS_CACHING_SUPPORT /* 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: offset = page->index << PAGE_CACHE_SHIFT; len = min_t(size_t, i_size_read(inode) - offset, PAGE_SIZE); /* read the contents of the file from the server into the * page */ ret = afs_vnode_fetch_data(vnode, key, offset, len, page); if (ret < 0) { if (ret == -ENOENT) { _debug("got NOENT from server" " - marking file deleted and stale"); set_bit(AFS_VNODE_DELETED, &vnode->flags); 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;}/* * invalidate part or all of a page */static void afs_invalidatepage(struct page *page, unsigned long offset){ int ret = 1; _enter("{%lu},%lu", page->index, offset); BUG_ON(!PageLocked(page)); if (PagePrivate(page)) { /* 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); /* possibly should BUG_ON(!ret); - neilb */ } } _leave(" = %d", ret);}/* * write back a dirty page */static int afs_launder_page(struct page *page){ _enter("{%lu}", page->index); return 0;}/* * release a page and cleanup its private data */static int afs_releasepage(struct page *page, gfp_t gfp_flags){ struct afs_vnode *vnode = AFS_FS_I(page->mapping->host); struct afs_writeback *wb; _enter("{{%x:%u}[%lu],%lx},%x", vnode->fid.vid, vnode->fid.vnode, page->index, page->flags, gfp_flags); if (PagePrivate(page)) { wb = (struct afs_writeback *) page_private(page); ASSERT(wb != NULL); set_page_private(page, 0); ClearPagePrivate(page); afs_put_writeback(wb); } _leave(" = 0"); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -