xref: /openbmc/linux/fs/afs/file.c (revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2)
1*1da177e4SLinus Torvalds /* file.c: AFS filesystem file handling
2*1da177e4SLinus Torvalds  *
3*1da177e4SLinus Torvalds  * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4*1da177e4SLinus Torvalds  * Written by David Howells (dhowells@redhat.com)
5*1da177e4SLinus Torvalds  *
6*1da177e4SLinus Torvalds  * This program is free software; you can redistribute it and/or
7*1da177e4SLinus Torvalds  * modify it under the terms of the GNU General Public License
8*1da177e4SLinus Torvalds  * as published by the Free Software Foundation; either version
9*1da177e4SLinus Torvalds  * 2 of the License, or (at your option) any later version.
10*1da177e4SLinus Torvalds  */
11*1da177e4SLinus Torvalds 
12*1da177e4SLinus Torvalds #include <linux/kernel.h>
13*1da177e4SLinus Torvalds #include <linux/module.h>
14*1da177e4SLinus Torvalds #include <linux/init.h>
15*1da177e4SLinus Torvalds #include <linux/sched.h>
16*1da177e4SLinus Torvalds #include <linux/slab.h>
17*1da177e4SLinus Torvalds #include <linux/fs.h>
18*1da177e4SLinus Torvalds #include <linux/pagemap.h>
19*1da177e4SLinus Torvalds #include <linux/buffer_head.h>
20*1da177e4SLinus Torvalds #include "volume.h"
21*1da177e4SLinus Torvalds #include "vnode.h"
22*1da177e4SLinus Torvalds #include <rxrpc/call.h>
23*1da177e4SLinus Torvalds #include "internal.h"
24*1da177e4SLinus Torvalds 
25*1da177e4SLinus Torvalds #if 0
26*1da177e4SLinus Torvalds static int afs_file_open(struct inode *inode, struct file *file);
27*1da177e4SLinus Torvalds static int afs_file_release(struct inode *inode, struct file *file);
28*1da177e4SLinus Torvalds #endif
29*1da177e4SLinus Torvalds 
30*1da177e4SLinus Torvalds static int afs_file_readpage(struct file *file, struct page *page);
31*1da177e4SLinus Torvalds static int afs_file_invalidatepage(struct page *page, unsigned long offset);
32*1da177e4SLinus Torvalds static int afs_file_releasepage(struct page *page, int gfp_flags);
33*1da177e4SLinus Torvalds 
34*1da177e4SLinus Torvalds static ssize_t afs_file_write(struct file *file, const char __user *buf,
35*1da177e4SLinus Torvalds 			      size_t size, loff_t *off);
36*1da177e4SLinus Torvalds 
37*1da177e4SLinus Torvalds struct inode_operations afs_file_inode_operations = {
38*1da177e4SLinus Torvalds 	.getattr	= afs_inode_getattr,
39*1da177e4SLinus Torvalds };
40*1da177e4SLinus Torvalds 
41*1da177e4SLinus Torvalds struct file_operations afs_file_file_operations = {
42*1da177e4SLinus Torvalds 	.read		= generic_file_read,
43*1da177e4SLinus Torvalds 	.write		= afs_file_write,
44*1da177e4SLinus Torvalds 	.mmap		= generic_file_mmap,
45*1da177e4SLinus Torvalds #if 0
46*1da177e4SLinus Torvalds 	.open		= afs_file_open,
47*1da177e4SLinus Torvalds 	.release	= afs_file_release,
48*1da177e4SLinus Torvalds 	.fsync		= afs_file_fsync,
49*1da177e4SLinus Torvalds #endif
50*1da177e4SLinus Torvalds };
51*1da177e4SLinus Torvalds 
52*1da177e4SLinus Torvalds struct address_space_operations afs_fs_aops = {
53*1da177e4SLinus Torvalds 	.readpage	= afs_file_readpage,
54*1da177e4SLinus Torvalds 	.sync_page	= block_sync_page,
55*1da177e4SLinus Torvalds 	.set_page_dirty	= __set_page_dirty_nobuffers,
56*1da177e4SLinus Torvalds 	.releasepage	= afs_file_releasepage,
57*1da177e4SLinus Torvalds 	.invalidatepage	= afs_file_invalidatepage,
58*1da177e4SLinus Torvalds };
59*1da177e4SLinus Torvalds 
60*1da177e4SLinus Torvalds /*****************************************************************************/
61*1da177e4SLinus Torvalds /*
62*1da177e4SLinus Torvalds  * AFS file write
63*1da177e4SLinus Torvalds  */
64*1da177e4SLinus Torvalds static ssize_t afs_file_write(struct file *file, const char __user *buf,
65*1da177e4SLinus Torvalds 			      size_t size, loff_t *off)
66*1da177e4SLinus Torvalds {
67*1da177e4SLinus Torvalds 	struct afs_vnode *vnode;
68*1da177e4SLinus Torvalds 
69*1da177e4SLinus Torvalds 	vnode = AFS_FS_I(file->f_dentry->d_inode);
70*1da177e4SLinus Torvalds 	if (vnode->flags & AFS_VNODE_DELETED)
71*1da177e4SLinus Torvalds 		return -ESTALE;
72*1da177e4SLinus Torvalds 
73*1da177e4SLinus Torvalds 	return -EIO;
74*1da177e4SLinus Torvalds } /* end afs_file_write() */
75*1da177e4SLinus Torvalds 
76*1da177e4SLinus Torvalds /*****************************************************************************/
77*1da177e4SLinus Torvalds /*
78*1da177e4SLinus Torvalds  * deal with notification that a page was read from the cache
79*1da177e4SLinus Torvalds  */
80*1da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
81*1da177e4SLinus Torvalds static void afs_file_readpage_read_complete(void *cookie_data,
82*1da177e4SLinus Torvalds 					    struct page *page,
83*1da177e4SLinus Torvalds 					    void *data,
84*1da177e4SLinus Torvalds 					    int error)
85*1da177e4SLinus Torvalds {
86*1da177e4SLinus Torvalds 	_enter("%p,%p,%p,%d", cookie_data, page, data, error);
87*1da177e4SLinus Torvalds 
88*1da177e4SLinus Torvalds 	if (error)
89*1da177e4SLinus Torvalds 		SetPageError(page);
90*1da177e4SLinus Torvalds 	else
91*1da177e4SLinus Torvalds 		SetPageUptodate(page);
92*1da177e4SLinus Torvalds 	unlock_page(page);
93*1da177e4SLinus Torvalds 
94*1da177e4SLinus Torvalds } /* end afs_file_readpage_read_complete() */
95*1da177e4SLinus Torvalds #endif
96*1da177e4SLinus Torvalds 
97*1da177e4SLinus Torvalds /*****************************************************************************/
98*1da177e4SLinus Torvalds /*
99*1da177e4SLinus Torvalds  * deal with notification that a page was written to the cache
100*1da177e4SLinus Torvalds  */
101*1da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
102*1da177e4SLinus Torvalds static void afs_file_readpage_write_complete(void *cookie_data,
103*1da177e4SLinus Torvalds 					     struct page *page,
104*1da177e4SLinus Torvalds 					     void *data,
105*1da177e4SLinus Torvalds 					     int error)
106*1da177e4SLinus Torvalds {
107*1da177e4SLinus Torvalds 	_enter("%p,%p,%p,%d", cookie_data, page, data, error);
108*1da177e4SLinus Torvalds 
109*1da177e4SLinus Torvalds 	unlock_page(page);
110*1da177e4SLinus Torvalds 
111*1da177e4SLinus Torvalds } /* end afs_file_readpage_write_complete() */
112*1da177e4SLinus Torvalds #endif
113*1da177e4SLinus Torvalds 
114*1da177e4SLinus Torvalds /*****************************************************************************/
115*1da177e4SLinus Torvalds /*
116*1da177e4SLinus Torvalds  * AFS read page from file (or symlink)
117*1da177e4SLinus Torvalds  */
118*1da177e4SLinus Torvalds static int afs_file_readpage(struct file *file, struct page *page)
119*1da177e4SLinus Torvalds {
120*1da177e4SLinus Torvalds 	struct afs_rxfs_fetch_descriptor desc;
121*1da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
122*1da177e4SLinus Torvalds 	struct cachefs_page *pageio;
123*1da177e4SLinus Torvalds #endif
124*1da177e4SLinus Torvalds 	struct afs_vnode *vnode;
125*1da177e4SLinus Torvalds 	struct inode *inode;
126*1da177e4SLinus Torvalds 	int ret;
127*1da177e4SLinus Torvalds 
128*1da177e4SLinus Torvalds 	inode = page->mapping->host;
129*1da177e4SLinus Torvalds 
130*1da177e4SLinus Torvalds 	_enter("{%lu},{%lu}", inode->i_ino, page->index);
131*1da177e4SLinus Torvalds 
132*1da177e4SLinus Torvalds 	vnode = AFS_FS_I(inode);
133*1da177e4SLinus Torvalds 
134*1da177e4SLinus Torvalds 	if (!PageLocked(page))
135*1da177e4SLinus Torvalds 		PAGE_BUG(page);
136*1da177e4SLinus Torvalds 
137*1da177e4SLinus Torvalds 	ret = -ESTALE;
138*1da177e4SLinus Torvalds 	if (vnode->flags & AFS_VNODE_DELETED)
139*1da177e4SLinus Torvalds 		goto error;
140*1da177e4SLinus Torvalds 
141*1da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
142*1da177e4SLinus Torvalds 	ret = cachefs_page_get_private(page, &pageio, GFP_NOIO);
143*1da177e4SLinus Torvalds 	if (ret < 0)
144*1da177e4SLinus Torvalds 		goto error;
145*1da177e4SLinus Torvalds 
146*1da177e4SLinus Torvalds 	/* is it cached? */
147*1da177e4SLinus Torvalds 	ret = cachefs_read_or_alloc_page(vnode->cache,
148*1da177e4SLinus Torvalds 					 page,
149*1da177e4SLinus Torvalds 					 afs_file_readpage_read_complete,
150*1da177e4SLinus Torvalds 					 NULL,
151*1da177e4SLinus Torvalds 					 GFP_KERNEL);
152*1da177e4SLinus Torvalds #else
153*1da177e4SLinus Torvalds 	ret = -ENOBUFS;
154*1da177e4SLinus Torvalds #endif
155*1da177e4SLinus Torvalds 
156*1da177e4SLinus Torvalds 	switch (ret) {
157*1da177e4SLinus Torvalds 		/* read BIO submitted and wb-journal entry found */
158*1da177e4SLinus Torvalds 	case 1:
159*1da177e4SLinus Torvalds 		BUG(); // TODO - handle wb-journal match
160*1da177e4SLinus Torvalds 
161*1da177e4SLinus Torvalds 		/* read BIO submitted (page in cache) */
162*1da177e4SLinus Torvalds 	case 0:
163*1da177e4SLinus Torvalds 		break;
164*1da177e4SLinus Torvalds 
165*1da177e4SLinus Torvalds 		/* no page available in cache */
166*1da177e4SLinus Torvalds 	case -ENOBUFS:
167*1da177e4SLinus Torvalds 	case -ENODATA:
168*1da177e4SLinus Torvalds 	default:
169*1da177e4SLinus Torvalds 		desc.fid	= vnode->fid;
170*1da177e4SLinus Torvalds 		desc.offset	= page->index << PAGE_CACHE_SHIFT;
171*1da177e4SLinus Torvalds 		desc.size	= min((size_t) (inode->i_size - desc.offset),
172*1da177e4SLinus Torvalds 				      (size_t) PAGE_SIZE);
173*1da177e4SLinus Torvalds 		desc.buffer	= kmap(page);
174*1da177e4SLinus Torvalds 
175*1da177e4SLinus Torvalds 		clear_page(desc.buffer);
176*1da177e4SLinus Torvalds 
177*1da177e4SLinus Torvalds 		/* read the contents of the file from the server into the
178*1da177e4SLinus Torvalds 		 * page */
179*1da177e4SLinus Torvalds 		ret = afs_vnode_fetch_data(vnode, &desc);
180*1da177e4SLinus Torvalds 		kunmap(page);
181*1da177e4SLinus Torvalds 		if (ret < 0) {
182*1da177e4SLinus Torvalds 			if (ret==-ENOENT) {
183*1da177e4SLinus Torvalds 				_debug("got NOENT from server"
184*1da177e4SLinus Torvalds 				       " - marking file deleted and stale");
185*1da177e4SLinus Torvalds 				vnode->flags |= AFS_VNODE_DELETED;
186*1da177e4SLinus Torvalds 				ret = -ESTALE;
187*1da177e4SLinus Torvalds 			}
188*1da177e4SLinus Torvalds 
189*1da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
190*1da177e4SLinus Torvalds 			cachefs_uncache_page(vnode->cache, page);
191*1da177e4SLinus Torvalds #endif
192*1da177e4SLinus Torvalds 			goto error;
193*1da177e4SLinus Torvalds 		}
194*1da177e4SLinus Torvalds 
195*1da177e4SLinus Torvalds 		SetPageUptodate(page);
196*1da177e4SLinus Torvalds 
197*1da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
198*1da177e4SLinus Torvalds 		if (cachefs_write_page(vnode->cache,
199*1da177e4SLinus Torvalds 				       page,
200*1da177e4SLinus Torvalds 				       afs_file_readpage_write_complete,
201*1da177e4SLinus Torvalds 				       NULL,
202*1da177e4SLinus Torvalds 				       GFP_KERNEL) != 0
203*1da177e4SLinus Torvalds 		    ) {
204*1da177e4SLinus Torvalds 			cachefs_uncache_page(vnode->cache, page);
205*1da177e4SLinus Torvalds 			unlock_page(page);
206*1da177e4SLinus Torvalds 		}
207*1da177e4SLinus Torvalds #else
208*1da177e4SLinus Torvalds 		unlock_page(page);
209*1da177e4SLinus Torvalds #endif
210*1da177e4SLinus Torvalds 	}
211*1da177e4SLinus Torvalds 
212*1da177e4SLinus Torvalds 	_leave(" = 0");
213*1da177e4SLinus Torvalds 	return 0;
214*1da177e4SLinus Torvalds 
215*1da177e4SLinus Torvalds  error:
216*1da177e4SLinus Torvalds 	SetPageError(page);
217*1da177e4SLinus Torvalds 	unlock_page(page);
218*1da177e4SLinus Torvalds 
219*1da177e4SLinus Torvalds 	_leave(" = %d", ret);
220*1da177e4SLinus Torvalds 	return ret;
221*1da177e4SLinus Torvalds 
222*1da177e4SLinus Torvalds } /* end afs_file_readpage() */
223*1da177e4SLinus Torvalds 
224*1da177e4SLinus Torvalds /*****************************************************************************/
225*1da177e4SLinus Torvalds /*
226*1da177e4SLinus Torvalds  * get a page cookie for the specified page
227*1da177e4SLinus Torvalds  */
228*1da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
229*1da177e4SLinus Torvalds int afs_cache_get_page_cookie(struct page *page,
230*1da177e4SLinus Torvalds 			      struct cachefs_page **_page_cookie)
231*1da177e4SLinus Torvalds {
232*1da177e4SLinus Torvalds 	int ret;
233*1da177e4SLinus Torvalds 
234*1da177e4SLinus Torvalds 	_enter("");
235*1da177e4SLinus Torvalds 	ret = cachefs_page_get_private(page,_page_cookie, GFP_NOIO);
236*1da177e4SLinus Torvalds 
237*1da177e4SLinus Torvalds 	_leave(" = %d", ret);
238*1da177e4SLinus Torvalds 	return ret;
239*1da177e4SLinus Torvalds } /* end afs_cache_get_page_cookie() */
240*1da177e4SLinus Torvalds #endif
241*1da177e4SLinus Torvalds 
242*1da177e4SLinus Torvalds /*****************************************************************************/
243*1da177e4SLinus Torvalds /*
244*1da177e4SLinus Torvalds  * invalidate part or all of a page
245*1da177e4SLinus Torvalds  */
246*1da177e4SLinus Torvalds static int afs_file_invalidatepage(struct page *page, unsigned long offset)
247*1da177e4SLinus Torvalds {
248*1da177e4SLinus Torvalds 	int ret = 1;
249*1da177e4SLinus Torvalds 
250*1da177e4SLinus Torvalds 	_enter("{%lu},%lu", page->index, offset);
251*1da177e4SLinus Torvalds 
252*1da177e4SLinus Torvalds 	BUG_ON(!PageLocked(page));
253*1da177e4SLinus Torvalds 
254*1da177e4SLinus Torvalds 	if (PagePrivate(page)) {
255*1da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
256*1da177e4SLinus Torvalds 		struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
257*1da177e4SLinus Torvalds 		cachefs_uncache_page(vnode->cache,page);
258*1da177e4SLinus Torvalds #endif
259*1da177e4SLinus Torvalds 
260*1da177e4SLinus Torvalds 		/* We release buffers only if the entire page is being
261*1da177e4SLinus Torvalds 		 * invalidated.
262*1da177e4SLinus Torvalds 		 * The get_block cached value has been unconditionally
263*1da177e4SLinus Torvalds 		 * invalidated, so real IO is not possible anymore.
264*1da177e4SLinus Torvalds 		 */
265*1da177e4SLinus Torvalds 		if (offset == 0) {
266*1da177e4SLinus Torvalds 			BUG_ON(!PageLocked(page));
267*1da177e4SLinus Torvalds 
268*1da177e4SLinus Torvalds 			ret = 0;
269*1da177e4SLinus Torvalds 			if (!PageWriteback(page))
270*1da177e4SLinus Torvalds 				ret = page->mapping->a_ops->releasepage(page,
271*1da177e4SLinus Torvalds 									0);
272*1da177e4SLinus Torvalds 		}
273*1da177e4SLinus Torvalds 	}
274*1da177e4SLinus Torvalds 
275*1da177e4SLinus Torvalds 	_leave(" = %d", ret);
276*1da177e4SLinus Torvalds 	return ret;
277*1da177e4SLinus Torvalds } /* end afs_file_invalidatepage() */
278*1da177e4SLinus Torvalds 
279*1da177e4SLinus Torvalds /*****************************************************************************/
280*1da177e4SLinus Torvalds /*
281*1da177e4SLinus Torvalds  * release a page and cleanup its private data
282*1da177e4SLinus Torvalds  */
283*1da177e4SLinus Torvalds static int afs_file_releasepage(struct page *page, int gfp_flags)
284*1da177e4SLinus Torvalds {
285*1da177e4SLinus Torvalds 	struct cachefs_page *pageio;
286*1da177e4SLinus Torvalds 
287*1da177e4SLinus Torvalds 	_enter("{%lu},%x", page->index, gfp_flags);
288*1da177e4SLinus Torvalds 
289*1da177e4SLinus Torvalds 	if (PagePrivate(page)) {
290*1da177e4SLinus Torvalds #ifdef AFS_CACHING_SUPPORT
291*1da177e4SLinus Torvalds 		struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
292*1da177e4SLinus Torvalds 		cachefs_uncache_page(vnode->cache, page);
293*1da177e4SLinus Torvalds #endif
294*1da177e4SLinus Torvalds 
295*1da177e4SLinus Torvalds 		pageio = (struct cachefs_page *) page->private;
296*1da177e4SLinus Torvalds 		page->private = 0;
297*1da177e4SLinus Torvalds 		ClearPagePrivate(page);
298*1da177e4SLinus Torvalds 
299*1da177e4SLinus Torvalds 		if (pageio)
300*1da177e4SLinus Torvalds 			kfree(pageio);
301*1da177e4SLinus Torvalds 	}
302*1da177e4SLinus Torvalds 
303*1da177e4SLinus Torvalds 	_leave(" = 0");
304*1da177e4SLinus Torvalds 	return 0;
305*1da177e4SLinus Torvalds } /* end afs_file_releasepage() */
306