Blame view

fs/9p/vfs_addr.c 8.2 KB
147b31cf0   Eric Van Hensbergen   [PATCH] v9fs: add...
1
2
3
4
5
6
7
8
9
  /*
   *  linux/fs/9p/vfs_addr.c
   *
   * This file contians vfs address (mmap) ops for 9P2000.
   *
   *  Copyright (C) 2005 by Eric Van Hensbergen <ericvh@gmail.com>
   *  Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov>
   *
   *  This program is free software; you can redistribute it and/or modify
42e8c509c   Eric Van Hensbergen   [PATCH] v9fs: upd...
10
11
   *  it under the terms of the GNU General Public License version 2
   *  as published by the Free Software Foundation.
147b31cf0   Eric Van Hensbergen   [PATCH] v9fs: add...
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
   *
   *  This program is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *  along with this program; if not, write to:
   *  Free Software Foundation
   *  51 Franklin Street, Fifth Floor
   *  Boston, MA  02111-1301  USA
   *
   */
  
  #include <linux/module.h>
  #include <linux/errno.h>
  #include <linux/fs.h>
  #include <linux/file.h>
  #include <linux/stat.h>
  #include <linux/string.h>
147b31cf0   Eric Van Hensbergen   [PATCH] v9fs: add...
32
  #include <linux/inet.h>
147b31cf0   Eric Van Hensbergen   [PATCH] v9fs: add...
33
34
  #include <linux/pagemap.h>
  #include <linux/idr.h>
e8edc6e03   Alexey Dobriyan   Detach sched.h fr...
35
  #include <linux/sched.h>
bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
36
37
  #include <net/9p/9p.h>
  #include <net/9p/client.h>
147b31cf0   Eric Van Hensbergen   [PATCH] v9fs: add...
38

147b31cf0   Eric Van Hensbergen   [PATCH] v9fs: add...
39
  #include "v9fs.h"
147b31cf0   Eric Van Hensbergen   [PATCH] v9fs: add...
40
  #include "v9fs_vfs.h"
60e78d2c9   Abhishek Kulkarni   9p: Add fscache s...
41
  #include "cache.h"
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
42
  #include "fid.h"
147b31cf0   Eric Van Hensbergen   [PATCH] v9fs: add...
43
44
  
  /**
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
45
   * v9fs_fid_readpage - read an entire page in from 9P
147b31cf0   Eric Van Hensbergen   [PATCH] v9fs: add...
46
   *
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
47
   * @fid: fid being read
147b31cf0   Eric Van Hensbergen   [PATCH] v9fs: add...
48
49
50
   * @page: structure to page
   *
   */
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
51
  static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page)
147b31cf0   Eric Van Hensbergen   [PATCH] v9fs: add...
52
  {
bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
53
54
55
  	int retval;
  	loff_t offset;
  	char *buffer;
60e78d2c9   Abhishek Kulkarni   9p: Add fscache s...
56
  	struct inode *inode;
e03abc0c9   Eric Van Hensbergen   9p: implement opt...
57

60e78d2c9   Abhishek Kulkarni   9p: Add fscache s...
58
  	inode = page->mapping->host;
5d3851530   Joe Perches   9p: Reduce object...
59
60
  	p9_debug(P9_DEBUG_VFS, "
  ");
60e78d2c9   Abhishek Kulkarni   9p: Add fscache s...
61
62
63
64
65
66
  
  	BUG_ON(!PageLocked(page));
  
  	retval = v9fs_readpage_from_fscache(inode, page);
  	if (retval == 0)
  		return retval;
147b31cf0   Eric Van Hensbergen   [PATCH] v9fs: add...
67
  	buffer = kmap(page);
bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
68
  	offset = page_offset(page);
147b31cf0   Eric Van Hensbergen   [PATCH] v9fs: add...
69

7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
70
  	retval = v9fs_fid_readn(fid, buffer, NULL, PAGE_CACHE_SIZE, offset);
60e78d2c9   Abhishek Kulkarni   9p: Add fscache s...
71
72
  	if (retval < 0) {
  		v9fs_uncache_page(inode, page);
bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
73
  		goto done;
60e78d2c9   Abhishek Kulkarni   9p: Add fscache s...
74
  	}
147b31cf0   Eric Van Hensbergen   [PATCH] v9fs: add...
75

bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
76
  	memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval);
147b31cf0   Eric Van Hensbergen   [PATCH] v9fs: add...
77
78
  	flush_dcache_page(page);
  	SetPageUptodate(page);
60e78d2c9   Abhishek Kulkarni   9p: Add fscache s...
79
80
  
  	v9fs_readpage_to_fscache(inode, page);
147b31cf0   Eric Van Hensbergen   [PATCH] v9fs: add...
81
  	retval = 0;
bd238fb43   Latchesar Ionkov   9p: Reorganizatio...
82
  done:
147b31cf0   Eric Van Hensbergen   [PATCH] v9fs: add...
83
84
85
86
  	kunmap(page);
  	unlock_page(page);
  	return retval;
  }
60e78d2c9   Abhishek Kulkarni   9p: Add fscache s...
87
  /**
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
88
89
90
91
92
93
94
95
96
97
98
99
100
   * v9fs_vfs_readpage - read an entire page in from 9P
   *
   * @filp: file being read
   * @page: structure to page
   *
   */
  
  static int v9fs_vfs_readpage(struct file *filp, struct page *page)
  {
  	return v9fs_fid_readpage(filp->private_data, page);
  }
  
  /**
60e78d2c9   Abhishek Kulkarni   9p: Add fscache s...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
   * v9fs_vfs_readpages - read a set of pages from 9P
   *
   * @filp: file being read
   * @mapping: the address space
   * @pages: list of pages to read
   * @nr_pages: count of pages to read
   *
   */
  
  static int v9fs_vfs_readpages(struct file *filp, struct address_space *mapping,
  			     struct list_head *pages, unsigned nr_pages)
  {
  	int ret = 0;
  	struct inode *inode;
  
  	inode = mapping->host;
5d3851530   Joe Perches   9p: Reduce object...
117
118
  	p9_debug(P9_DEBUG_VFS, "inode: %p file: %p
  ", inode, filp);
60e78d2c9   Abhishek Kulkarni   9p: Add fscache s...
119
120
121
122
123
124
  
  	ret = v9fs_readpages_from_fscache(inode, mapping, pages, &nr_pages);
  	if (ret == 0)
  		return ret;
  
  	ret = read_cache_pages(mapping, pages, (void *)v9fs_vfs_readpage, filp);
5d3851530   Joe Perches   9p: Reduce object...
125
126
  	p9_debug(P9_DEBUG_VFS, "  = %d
  ", ret);
60e78d2c9   Abhishek Kulkarni   9p: Add fscache s...
127
128
129
130
131
132
133
134
135
136
137
138
139
  	return ret;
  }
  
  /**
   * v9fs_release_page - release the private state associated with a page
   *
   * Returns 1 if the page can be released, false otherwise.
   */
  
  static int v9fs_release_page(struct page *page, gfp_t gfp)
  {
  	if (PagePrivate(page))
  		return 0;
60e78d2c9   Abhishek Kulkarni   9p: Add fscache s...
140
141
142
143
144
145
146
147
148
149
150
151
  	return v9fs_fscache_release_page(page, gfp);
  }
  
  /**
   * v9fs_invalidate_page - Invalidate a page completely or partially
   *
   * @page: structure to page
   * @offset: offset in the page
   */
  
  static void v9fs_invalidate_page(struct page *page, unsigned long offset)
  {
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
152
153
154
155
  	/*
  	 * If called with zero offset, we should release
  	 * the private state assocated with the page
  	 */
60e78d2c9   Abhishek Kulkarni   9p: Add fscache s...
156
157
158
  	if (offset == 0)
  		v9fs_fscache_invalidate_page(page);
  }
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
159
160
161
162
163
164
  static int v9fs_vfs_writepage_locked(struct page *page)
  {
  	char *buffer;
  	int retval, len;
  	loff_t offset, size;
  	mm_segment_t old_fs;
6b39f6d22   Aneesh Kumar K.V   fs/9p: Move write...
165
  	struct v9fs_inode *v9inode;
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
166
  	struct inode *inode = page->mapping->host;
6b39f6d22   Aneesh Kumar K.V   fs/9p: Move write...
167
  	v9inode = V9FS_I(inode);
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
168
169
170
171
172
173
174
175
176
177
178
179
180
  	size = i_size_read(inode);
  	if (page->index == size >> PAGE_CACHE_SHIFT)
  		len = size & ~PAGE_CACHE_MASK;
  	else
  		len = PAGE_CACHE_SIZE;
  
  	set_page_writeback(page);
  
  	buffer = kmap(page);
  	offset = page_offset(page);
  
  	old_fs = get_fs();
  	set_fs(get_ds());
6b39f6d22   Aneesh Kumar K.V   fs/9p: Move write...
181
182
  	/* We should have writeback_fid always set */
  	BUG_ON(!v9inode->writeback_fid);
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
183
184
  
  	retval = v9fs_file_write_internal(inode,
6b39f6d22   Aneesh Kumar K.V   fs/9p: Move write...
185
  					  v9inode->writeback_fid,
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
  					  (__force const char __user *)buffer,
  					  len, &offset, 0);
  	if (retval > 0)
  		retval = 0;
  
  	set_fs(old_fs);
  	kunmap(page);
  	end_page_writeback(page);
  	return retval;
  }
  
  static int v9fs_vfs_writepage(struct page *page, struct writeback_control *wbc)
  {
  	int retval;
  
  	retval = v9fs_vfs_writepage_locked(page);
  	if (retval < 0) {
  		if (retval == -EAGAIN) {
  			redirty_page_for_writepage(wbc, page);
  			retval = 0;
  		} else {
  			SetPageError(page);
  			mapping_set_error(page->mapping, retval);
  		}
  	} else
  		retval = 0;
  
  	unlock_page(page);
  	return retval;
  }
60e78d2c9   Abhishek Kulkarni   9p: Add fscache s...
216
217
  /**
   * v9fs_launder_page - Writeback a dirty page
60e78d2c9   Abhishek Kulkarni   9p: Add fscache s...
218
219
220
221
222
   * Returns 0 on success.
   */
  
  static int v9fs_launder_page(struct page *page)
  {
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
223
  	int retval;
2efda7998   Aneesh Kumar K.V   fs/9p: [fscache] ...
224
  	struct inode *inode = page->mapping->host;
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
225

2efda7998   Aneesh Kumar K.V   fs/9p: [fscache] ...
226
  	v9fs_fscache_wait_on_page_write(inode, page);
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
227
228
229
230
231
  	if (clear_page_dirty_for_io(page)) {
  		retval = v9fs_vfs_writepage_locked(page);
  		if (retval)
  			return retval;
  	}
60e78d2c9   Abhishek Kulkarni   9p: Add fscache s...
232
233
  	return 0;
  }
3e24ad2ff   jvrao   9p: Add a Direct ...
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
  /**
   * v9fs_direct_IO - 9P address space operation for direct I/O
   * @rw: direction (read or write)
   * @iocb: target I/O control block
   * @iov: array of vectors that define I/O buffer
   * @pos: offset in file to begin the operation
   * @nr_segs: size of iovec array
   *
   * The presence of v9fs_direct_IO() in the address space ops vector
   * allowes open() O_DIRECT flags which would have failed otherwise.
   *
   * In the non-cached mode, we shunt off direct read and write requests before
   * the VFS gets them, so this method should never be called.
   *
   * Direct IO is not 'yet' supported in the cached mode. Hence when
   * this routine is called through generic_file_aio_read(), the read/write fails
   * with an error.
   *
   */
e959b5490   Aneesh Kumar K.V   fs/9p: Add direct...
253
254
255
  static ssize_t
  v9fs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
  	       loff_t pos, unsigned long nr_segs)
3e24ad2ff   jvrao   9p: Add a Direct ...
256
  {
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
257
258
259
260
261
  	/*
  	 * FIXME
  	 * Now that we do caching with cache mode enabled, We need
  	 * to support direct IO
  	 */
5d3851530   Joe Perches   9p: Reduce object...
262
263
264
265
  	p9_debug(P9_DEBUG_VFS, "v9fs_direct_IO: v9fs_direct_IO (%s) off/no(%lld/%lu) EINVAL
  ",
  		 iocb->ki_filp->f_path.dentry->d_name.name,
  		 (long long)pos, nr_segs);
3e24ad2ff   jvrao   9p: Add a Direct ...
266
267
268
  
  	return -EINVAL;
  }
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
269
270
271
272
273
274
275
  
  static int v9fs_write_begin(struct file *filp, struct address_space *mapping,
  			    loff_t pos, unsigned len, unsigned flags,
  			    struct page **pagep, void **fsdata)
  {
  	int retval = 0;
  	struct page *page;
6b39f6d22   Aneesh Kumar K.V   fs/9p: Move write...
276
  	struct v9fs_inode *v9inode;
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
277
278
  	pgoff_t index = pos >> PAGE_CACHE_SHIFT;
  	struct inode *inode = mapping->host;
6b39f6d22   Aneesh Kumar K.V   fs/9p: Move write...
279
  	v9inode = V9FS_I(inode);
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
280
281
282
283
284
285
  start:
  	page = grab_cache_page_write_begin(mapping, index, flags);
  	if (!page) {
  		retval = -ENOMEM;
  		goto out;
  	}
6b39f6d22   Aneesh Kumar K.V   fs/9p: Move write...
286
  	BUG_ON(!v9inode->writeback_fid);
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
287
288
289
290
291
  	if (PageUptodate(page))
  		goto out;
  
  	if (len == PAGE_CACHE_SIZE)
  		goto out;
6b39f6d22   Aneesh Kumar K.V   fs/9p: Move write...
292
  	retval = v9fs_fid_readpage(v9inode->writeback_fid, page);
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
  	page_cache_release(page);
  	if (!retval)
  		goto start;
  out:
  	*pagep = page;
  	return retval;
  }
  
  static int v9fs_write_end(struct file *filp, struct address_space *mapping,
  			  loff_t pos, unsigned len, unsigned copied,
  			  struct page *page, void *fsdata)
  {
  	loff_t last_pos = pos + copied;
  	struct inode *inode = page->mapping->host;
  
  	if (unlikely(copied < len)) {
  		/*
  		 * zero out the rest of the area
  		 */
  		unsigned from = pos & (PAGE_CACHE_SIZE - 1);
  
  		zero_user(page, from + copied, len - copied);
  		flush_dcache_page(page);
  	}
  
  	if (!PageUptodate(page))
  		SetPageUptodate(page);
  	/*
  	 * No need to use i_size_read() here, the i_size
  	 * cannot change under us because we hold the i_mutex.
  	 */
  	if (last_pos > inode->i_size) {
  		inode_add_bytes(inode, last_pos - inode->i_size);
  		i_size_write(inode, last_pos);
  	}
  	set_page_dirty(page);
  	unlock_page(page);
  	page_cache_release(page);
  
  	return copied;
  }
f5e54d6e5   Christoph Hellwig   [PATCH] mark addr...
334
  const struct address_space_operations v9fs_addr_operations = {
7263cebed   Aneesh Kumar K.V   fs/9p: Add buffer...
335
336
337
338
339
340
341
342
343
344
  	.readpage = v9fs_vfs_readpage,
  	.readpages = v9fs_vfs_readpages,
  	.set_page_dirty = __set_page_dirty_nobuffers,
  	.writepage = v9fs_vfs_writepage,
  	.write_begin = v9fs_write_begin,
  	.write_end = v9fs_write_end,
  	.releasepage = v9fs_release_page,
  	.invalidatepage = v9fs_invalidate_page,
  	.launder_page = v9fs_launder_page,
  	.direct_IO = v9fs_direct_IO,
147b31cf0   Eric Van Hensbergen   [PATCH] v9fs: add...
345
  };