aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/afs/file.c')
-rw-r--r--fs/afs/file.c124
1 files changed, 76 insertions, 48 deletions
diff --git a/fs/afs/file.c b/fs/afs/file.c
index b17634541f67..ae256498f4f7 100644
--- a/fs/afs/file.c
+++ b/fs/afs/file.c
@@ -1,6 +1,6 @@
1/* file.c: AFS filesystem file handling 1/* AFS filesystem file handling
2 * 2 *
3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -15,22 +15,25 @@
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/fs.h> 16#include <linux/fs.h>
17#include <linux/pagemap.h> 17#include <linux/pagemap.h>
18#include "volume.h"
19#include "vnode.h"
20#include <rxrpc/call.h>
21#include "internal.h" 18#include "internal.h"
22 19
23#if 0
24static int afs_file_open(struct inode *inode, struct file *file);
25static int afs_file_release(struct inode *inode, struct file *file);
26#endif
27
28static int afs_file_readpage(struct file *file, struct page *page); 20static int afs_file_readpage(struct file *file, struct page *page);
29static void afs_file_invalidatepage(struct page *page, unsigned long offset); 21static void afs_file_invalidatepage(struct page *page, unsigned long offset);
30static int afs_file_releasepage(struct page *page, gfp_t gfp_flags); 22static int afs_file_releasepage(struct page *page, gfp_t gfp_flags);
31 23
24const struct file_operations afs_file_operations = {
25 .open = afs_open,
26 .release = afs_release,
27 .llseek = generic_file_llseek,
28 .read = do_sync_read,
29 .aio_read = generic_file_aio_read,
30 .mmap = generic_file_readonly_mmap,
31 .sendfile = generic_file_sendfile,
32};
33
32const struct inode_operations afs_file_inode_operations = { 34const struct inode_operations afs_file_inode_operations = {
33 .getattr = afs_inode_getattr, 35 .getattr = afs_inode_getattr,
36 .permission = afs_permission,
34}; 37};
35 38
36const struct address_space_operations afs_fs_aops = { 39const struct address_space_operations afs_fs_aops = {
@@ -40,7 +43,48 @@ const struct address_space_operations afs_fs_aops = {
40 .invalidatepage = afs_file_invalidatepage, 43 .invalidatepage = afs_file_invalidatepage,
41}; 44};
42 45
43/*****************************************************************************/ 46/*
47 * open an AFS file or directory and attach a key to it
48 */
49int afs_open(struct inode *inode, struct file *file)
50{
51 struct afs_vnode *vnode = AFS_FS_I(inode);
52 struct key *key;
53 int ret;
54
55 _enter("{%x:%x},", vnode->fid.vid, vnode->fid.vnode);
56
57 key = afs_request_key(vnode->volume->cell);
58 if (IS_ERR(key)) {
59 _leave(" = %ld [key]", PTR_ERR(key));
60 return PTR_ERR(key);
61 }
62
63 ret = afs_validate(vnode, key);
64 if (ret < 0) {
65 _leave(" = %d [val]", ret);
66 return ret;
67 }
68
69 file->private_data = key;
70 _leave(" = 0");
71 return 0;
72}
73
74/*
75 * release an AFS file or directory and discard its key
76 */
77int afs_release(struct inode *inode, struct file *file)
78{
79 struct afs_vnode *vnode = AFS_FS_I(inode);
80
81 _enter("{%x:%x},", vnode->fid.vid, vnode->fid.vnode);
82
83 key_put(file->private_data);
84 _leave(" = 0");
85 return 0;
86}
87
44/* 88/*
45 * deal with notification that a page was read from the cache 89 * deal with notification that a page was read from the cache
46 */ 90 */
@@ -58,10 +102,9 @@ static void afs_file_readpage_read_complete(void *cookie_data,
58 SetPageUptodate(page); 102 SetPageUptodate(page);
59 unlock_page(page); 103 unlock_page(page);
60 104
61} /* end afs_file_readpage_read_complete() */ 105}
62#endif 106#endif
63 107
64/*****************************************************************************/
65/* 108/*
66 * deal with notification that a page was written to the cache 109 * deal with notification that a page was written to the cache
67 */ 110 */
@@ -74,41 +117,38 @@ static void afs_file_readpage_write_complete(void *cookie_data,
74 _enter("%p,%p,%p,%d", cookie_data, page, data, error); 117 _enter("%p,%p,%p,%d", cookie_data, page, data, error);
75 118
76 unlock_page(page); 119 unlock_page(page);
77 120}
78} /* end afs_file_readpage_write_complete() */
79#endif 121#endif
80 122
81/*****************************************************************************/
82/* 123/*
83 * AFS read page from file (or symlink) 124 * AFS read page from file (or symlink)
84 */ 125 */
85static int afs_file_readpage(struct file *file, struct page *page) 126static int afs_file_readpage(struct file *file, struct page *page)
86{ 127{
87 struct afs_rxfs_fetch_descriptor desc;
88#ifdef AFS_CACHING_SUPPORT
89 struct cachefs_page *pageio;
90#endif
91 struct afs_vnode *vnode; 128 struct afs_vnode *vnode;
92 struct inode *inode; 129 struct inode *inode;
130 struct key *key;
131 size_t len;
132 off_t offset;
93 int ret; 133 int ret;
94 134
95 inode = page->mapping->host; 135 inode = page->mapping->host;
96 136
97 _enter("{%lu},{%lu}", inode->i_ino, page->index); 137 ASSERT(file != NULL);
138 key = file->private_data;
139 ASSERT(key != NULL);
140
141 _enter("{%x},{%lu},{%lu}", key_serial(key), inode->i_ino, page->index);
98 142
99 vnode = AFS_FS_I(inode); 143 vnode = AFS_FS_I(inode);
100 144
101 BUG_ON(!PageLocked(page)); 145 BUG_ON(!PageLocked(page));
102 146
103 ret = -ESTALE; 147 ret = -ESTALE;
104 if (vnode->flags & AFS_VNODE_DELETED) 148 if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
105 goto error; 149 goto error;
106 150
107#ifdef AFS_CACHING_SUPPORT 151#ifdef AFS_CACHING_SUPPORT
108 ret = cachefs_page_get_private(page, &pageio, GFP_NOIO);
109 if (ret < 0)
110 goto error;
111
112 /* is it cached? */ 152 /* is it cached? */
113 ret = cachefs_read_or_alloc_page(vnode->cache, 153 ret = cachefs_read_or_alloc_page(vnode->cache,
114 page, 154 page,
@@ -132,26 +172,19 @@ static int afs_file_readpage(struct file *file, struct page *page)
132 case -ENOBUFS: 172 case -ENOBUFS:
133 case -ENODATA: 173 case -ENODATA:
134 default: 174 default:
135 desc.fid = vnode->fid; 175 offset = page->index << PAGE_CACHE_SHIFT;
136 desc.offset = page->index << PAGE_CACHE_SHIFT; 176 len = min_t(size_t, i_size_read(inode) - offset, PAGE_SIZE);
137 desc.size = min((size_t) (inode->i_size - desc.offset),
138 (size_t) PAGE_SIZE);
139 desc.buffer = kmap(page);
140
141 clear_page(desc.buffer);
142 177
143 /* read the contents of the file from the server into the 178 /* read the contents of the file from the server into the
144 * page */ 179 * page */
145 ret = afs_vnode_fetch_data(vnode, &desc); 180 ret = afs_vnode_fetch_data(vnode, key, offset, len, page);
146 kunmap(page);
147 if (ret < 0) { 181 if (ret < 0) {
148 if (ret==-ENOENT) { 182 if (ret == -ENOENT) {
149 _debug("got NOENT from server" 183 _debug("got NOENT from server"
150 " - marking file deleted and stale"); 184 " - marking file deleted and stale");
151 vnode->flags |= AFS_VNODE_DELETED; 185 set_bit(AFS_VNODE_DELETED, &vnode->flags);
152 ret = -ESTALE; 186 ret = -ESTALE;
153 } 187 }
154
155#ifdef AFS_CACHING_SUPPORT 188#ifdef AFS_CACHING_SUPPORT
156 cachefs_uncache_page(vnode->cache, page); 189 cachefs_uncache_page(vnode->cache, page);
157#endif 190#endif
@@ -178,16 +211,13 @@ static int afs_file_readpage(struct file *file, struct page *page)
178 _leave(" = 0"); 211 _leave(" = 0");
179 return 0; 212 return 0;
180 213
181 error: 214error:
182 SetPageError(page); 215 SetPageError(page);
183 unlock_page(page); 216 unlock_page(page);
184
185 _leave(" = %d", ret); 217 _leave(" = %d", ret);
186 return ret; 218 return ret;
219}
187 220
188} /* end afs_file_readpage() */
189
190/*****************************************************************************/
191/* 221/*
192 * get a page cookie for the specified page 222 * get a page cookie for the specified page
193 */ 223 */
@@ -202,10 +232,9 @@ int afs_cache_get_page_cookie(struct page *page,
202 232
203 _leave(" = %d", ret); 233 _leave(" = %d", ret);
204 return ret; 234 return ret;
205} /* end afs_cache_get_page_cookie() */ 235}
206#endif 236#endif
207 237
208/*****************************************************************************/
209/* 238/*
210 * invalidate part or all of a page 239 * invalidate part or all of a page
211 */ 240 */
@@ -240,9 +269,8 @@ static void afs_file_invalidatepage(struct page *page, unsigned long offset)
240 } 269 }
241 270
242 _leave(" = %d", ret); 271 _leave(" = %d", ret);
243} /* end afs_file_invalidatepage() */ 272}
244 273
245/*****************************************************************************/
246/* 274/*
247 * release a page and cleanup its private data 275 * release a page and cleanup its private data
248 */ 276 */
@@ -267,4 +295,4 @@ static int afs_file_releasepage(struct page *page, gfp_t gfp_flags)
267 295
268 _leave(" = 0"); 296 _leave(" = 0");
269 return 0; 297 return 0;
270} /* end afs_file_releasepage() */ 298}