Blame view
fs/nfs/file.c
23.7 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
/* * linux/fs/nfs/file.c * * Copyright (C) 1992 Rick Sladkey * * Changes Copyright (C) 1994 by Florian La Roche * - Do not copy data too often around in the kernel. * - In nfs_file_read the return value of kmalloc wasn't checked. * - Put in a better version of read look-ahead buffering. Original idea * and implementation by Wai S Kok elekokws@ee.nus.sg. * * Expire cache on write to a file by Wai S Kok (Oct 1994). * * Total rewrite of read side for new NFS buffer cache.. Linus. * * nfs regular file handling functions */ #include <linux/time.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/fcntl.h> #include <linux/stat.h> #include <linux/nfs_fs.h> #include <linux/nfs_mount.h> #include <linux/mm.h> |
1da177e4c Linux-2.6.12-rc2 |
27 |
#include <linux/pagemap.h> |
e8edc6e03 Detach sched.h fr... |
28 |
#include <linux/aio.h> |
5a0e3ad6a include cleanup: ... |
29 |
#include <linux/gfp.h> |
b608b283a NFS: kswapd must ... |
30 |
#include <linux/swap.h> |
1da177e4c Linux-2.6.12-rc2 |
31 32 33 34 35 |
#include <asm/uaccess.h> #include <asm/system.h> #include "delegation.h" |
94387fb1a NFS: Add the help... |
36 |
#include "internal.h" |
91d5b4702 NFS: add I/O perf... |
37 |
#include "iostat.h" |
545db45f0 NFS: FS-Cache pag... |
38 |
#include "fscache.h" |
e5e940170 NFS: create and d... |
39 |
#include "pnfs.h" |
1da177e4c Linux-2.6.12-rc2 |
40 41 |
#define NFSDBG_FACILITY NFSDBG_FILE |
f0f37e2f7 const: mark struc... |
42 |
static const struct vm_operations_struct nfs_file_vm_ops; |
94387fb1a NFS: Add the help... |
43 |
|
92e1d5be9 [PATCH] mark stru... |
44 |
const struct inode_operations nfs_file_inode_operations = { |
1da177e4c Linux-2.6.12-rc2 |
45 46 47 48 |
.permission = nfs_permission, .getattr = nfs_getattr, .setattr = nfs_setattr, }; |
b7fa0554c [PATCH] NFS: Add ... |
49 |
#ifdef CONFIG_NFS_V3 |
92e1d5be9 [PATCH] mark stru... |
50 |
const struct inode_operations nfs3_file_inode_operations = { |
b7fa0554c [PATCH] NFS: Add ... |
51 52 53 54 55 56 57 58 59 |
.permission = nfs_permission, .getattr = nfs_getattr, .setattr = nfs_setattr, .listxattr = nfs3_listxattr, .getxattr = nfs3_getxattr, .setxattr = nfs3_setxattr, .removexattr = nfs3_removexattr, }; #endif /* CONFIG_NFS_v3 */ |
1da177e4c Linux-2.6.12-rc2 |
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
/* Hack for future NFS swap support */ #ifndef IS_SWAPFILE # define IS_SWAPFILE(inode) (0) #endif static int nfs_check_flags(int flags) { if ((flags & (O_APPEND | O_DIRECT)) == (O_APPEND | O_DIRECT)) return -EINVAL; return 0; } /* * Open file */ static int nfs_file_open(struct inode *inode, struct file *filp) { |
1da177e4c Linux-2.6.12-rc2 |
79 |
int res; |
6da24bc9c NFS: Use NFSDBG_F... |
80 81 |
dprintk("NFS: open file(%s/%s) ", |
cc0dd2d10 NFS: Make nfs_ope... |
82 83 |
filp->f_path.dentry->d_parent->d_name.name, filp->f_path.dentry->d_name.name); |
c2459dc46 NFS: Proper accou... |
84 |
nfs_inc_stats(inode, NFSIOS_VFSOPEN); |
1da177e4c Linux-2.6.12-rc2 |
85 86 87 |
res = nfs_check_flags(filp->f_flags); if (res) return res; |
46cb650c2 NFS: Remove the r... |
88 |
res = nfs_open(inode, filp); |
1da177e4c Linux-2.6.12-rc2 |
89 90 91 92 93 94 |
return res; } static int nfs_file_release(struct inode *inode, struct file *filp) { |
6da24bc9c NFS: Use NFSDBG_F... |
95 96 |
dprintk("NFS: release(%s/%s) ", |
6f276e49f nfs: Fix unused v... |
97 98 |
filp->f_path.dentry->d_parent->d_name.name, filp->f_path.dentry->d_name.name); |
6da24bc9c NFS: Use NFSDBG_F... |
99 |
|
91d5b4702 NFS: add I/O perf... |
100 |
nfs_inc_stats(inode, NFSIOS_VFSRELEASE); |
46cb650c2 NFS: Remove the r... |
101 |
return nfs_release(inode, filp); |
1da177e4c Linux-2.6.12-rc2 |
102 |
} |
980802e31 [PATCH] NFS: Ensu... |
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
/** * nfs_revalidate_size - Revalidate the file size * @inode - pointer to inode struct * @file - pointer to struct file * * Revalidates the file length. This is basically a wrapper around * nfs_revalidate_inode() that takes into account the fact that we may * have cached writes (in which case we don't care about the server's * idea of what the file length is), or O_DIRECT (in which case we * shouldn't trust the cache). */ static int nfs_revalidate_file_size(struct inode *inode, struct file *filp) { struct nfs_server *server = NFS_SERVER(inode); struct nfs_inode *nfsi = NFS_I(inode); |
d7cf8dd01 NFSv4: Allow attr... |
118 119 |
if (nfs_have_delegated_attributes(inode)) goto out_noreval; |
980802e31 [PATCH] NFS: Ensu... |
120 121 |
if (filp->f_flags & O_DIRECT) goto force_reval; |
d7cf8dd01 NFSv4: Allow attr... |
122 123 124 125 126 127 |
if (nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE) goto force_reval; if (nfs_attribute_timeout(inode)) goto force_reval; out_noreval: return 0; |
980802e31 [PATCH] NFS: Ensu... |
128 129 130 131 132 133 |
force_reval: return __nfs_revalidate_inode(server, inode); } static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) { |
6da24bc9c NFS: Use NFSDBG_F... |
134 135 |
dprintk("NFS: llseek file(%s/%s, %lld, %d) ", |
b84e06c58 NFS: Make nfs_lls... |
136 137 138 |
filp->f_path.dentry->d_parent->d_name.name, filp->f_path.dentry->d_name.name, offset, origin); |
06222e491 fs: handle SEEK_H... |
139 140 141 142 |
/* * origin == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate * the cached file length */ |
6c5296174 NFS: Fix a regres... |
143 |
if (origin != SEEK_SET && origin != SEEK_CUR) { |
980802e31 [PATCH] NFS: Ensu... |
144 |
struct inode *inode = filp->f_mapping->host; |
d5e66348b NFS: Fix nfs_file... |
145 |
|
980802e31 [PATCH] NFS: Ensu... |
146 147 148 |
int retval = nfs_revalidate_file_size(inode, filp); if (retval < 0) return (loff_t)retval; |
79835a710 nfs: drop unneces... |
149 |
} |
d5e66348b NFS: Fix nfs_file... |
150 |
|
79835a710 nfs: drop unneces... |
151 |
return generic_file_llseek(filp, offset, origin); |
980802e31 [PATCH] NFS: Ensu... |
152 |
} |
1da177e4c Linux-2.6.12-rc2 |
153 154 |
/* * Flush all dirty pages, and check for write errors. |
1da177e4c Linux-2.6.12-rc2 |
155 156 |
*/ static int |
75e1fcc0b [PATCH] vfs: add ... |
157 |
nfs_file_flush(struct file *file, fl_owner_t id) |
1da177e4c Linux-2.6.12-rc2 |
158 |
{ |
6da24bc9c NFS: Use NFSDBG_F... |
159 160 |
struct dentry *dentry = file->f_path.dentry; struct inode *inode = dentry->d_inode; |
1da177e4c Linux-2.6.12-rc2 |
161 |
|
6da24bc9c NFS: Use NFSDBG_F... |
162 163 164 165 |
dprintk("NFS: flush(%s/%s) ", dentry->d_parent->d_name.name, dentry->d_name.name); |
1da177e4c Linux-2.6.12-rc2 |
166 |
|
c2459dc46 NFS: Proper accou... |
167 |
nfs_inc_stats(inode, NFSIOS_VFSFLUSH); |
1da177e4c Linux-2.6.12-rc2 |
168 169 |
if ((file->f_mode & FMODE_WRITE) == 0) return 0; |
7b159fc18 NFS: Fall back to... |
170 |
|
7fe5c398f NFS: Optimise NFS... |
171 |
/* Flush writes to the server and return any errors */ |
af7fa1650 NFS: Fix up the f... |
172 |
return vfs_fsync(file, 0); |
1da177e4c Linux-2.6.12-rc2 |
173 174 175 |
} static ssize_t |
027445c37 [PATCH] Vectorize... |
176 177 |
nfs_file_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) |
1da177e4c Linux-2.6.12-rc2 |
178 |
{ |
01cce933d [PATCH] nfs: chan... |
179 |
struct dentry * dentry = iocb->ki_filp->f_path.dentry; |
1da177e4c Linux-2.6.12-rc2 |
180 181 |
struct inode * inode = dentry->d_inode; ssize_t result; |
1da177e4c Linux-2.6.12-rc2 |
182 |
if (iocb->ki_filp->f_flags & O_DIRECT) |
027445c37 [PATCH] Vectorize... |
183 |
return nfs_file_direct_read(iocb, iov, nr_segs, pos); |
1da177e4c Linux-2.6.12-rc2 |
184 |
|
6da24bc9c NFS: Use NFSDBG_F... |
185 186 |
dprintk("NFS: read(%s/%s, %lu@%lu) ", |
1da177e4c Linux-2.6.12-rc2 |
187 |
dentry->d_parent->d_name.name, dentry->d_name.name, |
6f276e49f nfs: Fix unused v... |
188 |
(unsigned long) iov_length(iov, nr_segs), (unsigned long) pos); |
1da177e4c Linux-2.6.12-rc2 |
189 |
|
44b11874f NFS: Separate met... |
190 |
result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping); |
4184dcf2d NFS: Fix byte acc... |
191 |
if (!result) { |
027445c37 [PATCH] Vectorize... |
192 |
result = generic_file_aio_read(iocb, iov, nr_segs, pos); |
4184dcf2d NFS: Fix byte acc... |
193 194 195 |
if (result > 0) nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, result); } |
1da177e4c Linux-2.6.12-rc2 |
196 197 198 199 |
return result; } static ssize_t |
f0930fffa sendfile: convert... |
200 201 202 |
nfs_file_splice_read(struct file *filp, loff_t *ppos, struct pipe_inode_info *pipe, size_t count, unsigned int flags) |
1da177e4c Linux-2.6.12-rc2 |
203 |
{ |
01cce933d [PATCH] nfs: chan... |
204 |
struct dentry *dentry = filp->f_path.dentry; |
1da177e4c Linux-2.6.12-rc2 |
205 206 |
struct inode *inode = dentry->d_inode; ssize_t res; |
6da24bc9c NFS: Use NFSDBG_F... |
207 208 |
dprintk("NFS: splice_read(%s/%s, %lu@%Lu) ", |
1da177e4c Linux-2.6.12-rc2 |
209 210 |
dentry->d_parent->d_name.name, dentry->d_name.name, (unsigned long) count, (unsigned long long) *ppos); |
44b11874f NFS: Separate met... |
211 |
res = nfs_revalidate_mapping(inode, filp->f_mapping); |
aa2f1ef10 NFS: Account for ... |
212 |
if (!res) { |
f0930fffa sendfile: convert... |
213 |
res = generic_file_splice_read(filp, ppos, pipe, count, flags); |
aa2f1ef10 NFS: Account for ... |
214 215 216 |
if (res > 0) nfs_add_stats(inode, NFSIOS_NORMALREADBYTES, res); } |
1da177e4c Linux-2.6.12-rc2 |
217 218 219 220 221 222 |
return res; } static int nfs_file_mmap(struct file * file, struct vm_area_struct * vma) { |
01cce933d [PATCH] nfs: chan... |
223 |
struct dentry *dentry = file->f_path.dentry; |
1da177e4c Linux-2.6.12-rc2 |
224 225 |
struct inode *inode = dentry->d_inode; int status; |
6da24bc9c NFS: Use NFSDBG_F... |
226 227 |
dprintk("NFS: mmap(%s/%s) ", |
1da177e4c Linux-2.6.12-rc2 |
228 |
dentry->d_parent->d_name.name, dentry->d_name.name); |
e1ebfd33b NFS: Kill the "de... |
229 230 231 232 |
/* Note: generic_file_mmap() returns ENOSYS on nommu systems * so we call that before revalidating the mapping */ status = generic_file_mmap(file, vma); |
94387fb1a NFS: Add the help... |
233 234 |
if (!status) { vma->vm_ops = &nfs_file_vm_ops; |
e1ebfd33b NFS: Kill the "de... |
235 |
status = nfs_revalidate_mapping(inode, file->f_mapping); |
94387fb1a NFS: Add the help... |
236 |
} |
1da177e4c Linux-2.6.12-rc2 |
237 238 239 240 241 242 243 |
return status; } /* * Flush any dirty pages for this process, and check for write errors. * The return status from this call provides a reliable indication of * whether any write errors occurred for this process. |
af7fa1650 NFS: Fix up the f... |
244 245 246 247 248 |
* * Notice that it clears the NFS_CONTEXT_ERROR_WRITE before synching to * disk, but it retrieves and clears ctx->error after synching, despite * the two being set at the same time in nfs_context_set_write_error(). * This is because the former is used to notify the _next_ call to |
25985edce Fix common misspe... |
249 |
* nfs_file_write() that a write error occurred, and hence cause it to |
af7fa1650 NFS: Fix up the f... |
250 |
* fall back to doing a synchronous write. |
1da177e4c Linux-2.6.12-rc2 |
251 252 |
*/ static int |
02c24a821 fs: push i_mutex ... |
253 |
nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync) |
1da177e4c Linux-2.6.12-rc2 |
254 |
{ |
7ea808591 drop unused dentr... |
255 |
struct dentry *dentry = file->f_path.dentry; |
cd3758e37 NFS: Replace file... |
256 |
struct nfs_open_context *ctx = nfs_file_open_context(file); |
1da177e4c Linux-2.6.12-rc2 |
257 |
struct inode *inode = dentry->d_inode; |
af7fa1650 NFS: Fix up the f... |
258 259 |
int have_error, status; int ret = 0; |
6da24bc9c NFS: Use NFSDBG_F... |
260 261 |
dprintk("NFS: fsync file(%s/%s) datasync %d ", |
549177863 NFS: Make nfs_fsy... |
262 263 |
dentry->d_parent->d_name.name, dentry->d_name.name, datasync); |
1da177e4c Linux-2.6.12-rc2 |
264 |
|
02c24a821 fs: push i_mutex ... |
265 |
ret = filemap_write_and_wait_range(inode->i_mapping, start, end); |
02c24a821 fs: push i_mutex ... |
266 |
mutex_lock(&inode->i_mutex); |
91d5b4702 NFS: add I/O perf... |
267 |
nfs_inc_stats(inode, NFSIOS_VFSFSYNC); |
af7fa1650 NFS: Fix up the f... |
268 269 |
have_error = test_and_clear_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); status = nfs_commit_inode(inode, FLUSH_SYNC); |
2edb6bc38 NFS - fix recent ... |
270 271 |
if (status >= 0 && ret < 0) status = ret; |
af7fa1650 NFS: Fix up the f... |
272 273 274 |
have_error |= test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags); if (have_error) ret = xchg(&ctx->error, 0); |
0702099bd NFS: fix the retu... |
275 |
if (!ret && status < 0) |
af7fa1650 NFS: Fix up the f... |
276 |
ret = status; |
863a3c6c6 NFSv4.1: layoutco... |
277 278 |
if (!ret && !datasync) /* application has asked for meta-data sync */ |
ef3115378 NFSv4.1 convert l... |
279 |
ret = pnfs_layoutcommit_inode(inode, true); |
02c24a821 fs: push i_mutex ... |
280 |
mutex_unlock(&inode->i_mutex); |
af7fa1650 NFS: Fix up the f... |
281 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
282 283 284 |
} /* |
38c73044f NFS: read-modify-... |
285 286 287 288 289 290 291 292 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 |
* Decide whether a read/modify/write cycle may be more efficient * then a modify/write/read cycle when writing to a page in the * page cache. * * The modify/write/read cycle may occur if a page is read before * being completely filled by the writer. In this situation, the * page must be completely written to stable storage on the server * before it can be refilled by reading in the page from the server. * This can lead to expensive, small, FILE_SYNC mode writes being * done. * * It may be more efficient to read the page first if the file is * open for reading in addition to writing, the page is not marked * as Uptodate, it is not dirty or waiting to be committed, * indicating that it was previously allocated and then modified, * that there were valid bytes of data in that range of the file, * and that the new data won't completely replace the old data in * that range of the file. */ static int nfs_want_read_modify_write(struct file *file, struct page *page, loff_t pos, unsigned len) { unsigned int pglen = nfs_page_length(page); unsigned int offset = pos & (PAGE_CACHE_SIZE - 1); unsigned int end = offset + len; if ((file->f_mode & FMODE_READ) && /* open for read? */ !PageUptodate(page) && /* Uptodate? */ !PagePrivate(page) && /* i/o request already? */ pglen && /* valid bytes of file? */ (end < pglen || offset)) /* replace all valid bytes? */ return 1; return 0; } /* |
4899f9c85 nfs: convert to n... |
321 322 323 |
* This does the "real" work of the write. We must allocate and lock the * page to be sent back to the generic routine, which then copies the * data from user space. |
1da177e4c Linux-2.6.12-rc2 |
324 325 326 327 |
* * If the writer ends up delaying the write, the writer needs to * increment the page use counts until he is done with the page. */ |
4899f9c85 nfs: convert to n... |
328 329 330 |
static int nfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) |
1da177e4c Linux-2.6.12-rc2 |
331 |
{ |
4899f9c85 nfs: convert to n... |
332 |
int ret; |
38c73044f NFS: read-modify-... |
333 |
pgoff_t index = pos >> PAGE_CACHE_SHIFT; |
4899f9c85 nfs: convert to n... |
334 |
struct page *page; |
38c73044f NFS: read-modify-... |
335 |
int once_thru = 0; |
4899f9c85 nfs: convert to n... |
336 |
|
b7eaefaa8 NFS: Add debuggin... |
337 338 339 340 341 |
dfprintk(PAGECACHE, "NFS: write_begin(%s/%s(%ld), %u@%lld) ", file->f_path.dentry->d_parent->d_name.name, file->f_path.dentry->d_name.name, mapping->host->i_ino, len, (long long) pos); |
38c73044f NFS: read-modify-... |
342 |
start: |
72cb77f4a NFS: Throttle pag... |
343 344 345 346 347 348 349 350 |
/* * Prevent starvation issues if someone is doing a consistency * sync-to-disk */ ret = wait_on_bit(&NFS_I(mapping->host)->flags, NFS_INO_FLUSHING, nfs_wait_bit_killable, TASK_KILLABLE); if (ret) return ret; |
54566b2c1 fs: symlink write... |
351 |
page = grab_cache_page_write_begin(mapping, index, flags); |
4899f9c85 nfs: convert to n... |
352 353 354 355 356 357 358 359 |
if (!page) return -ENOMEM; *pagep = page; ret = nfs_flush_incompatible(file, page); if (ret) { unlock_page(page); page_cache_release(page); |
38c73044f NFS: read-modify-... |
360 361 362 363 364 365 366 |
} else if (!once_thru && nfs_want_read_modify_write(file, page, pos, len)) { once_thru = 1; ret = nfs_readpage(file, page); page_cache_release(page); if (!ret) goto start; |
4899f9c85 nfs: convert to n... |
367 368 |
} return ret; |
1da177e4c Linux-2.6.12-rc2 |
369 |
} |
4899f9c85 nfs: convert to n... |
370 371 372 |
static int nfs_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata) |
1da177e4c Linux-2.6.12-rc2 |
373 |
{ |
4899f9c85 nfs: convert to n... |
374 375 |
unsigned offset = pos & (PAGE_CACHE_SIZE - 1); int status; |
1da177e4c Linux-2.6.12-rc2 |
376 |
|
b7eaefaa8 NFS: Add debuggin... |
377 378 379 380 381 |
dfprintk(PAGECACHE, "NFS: write_end(%s/%s(%ld), %u@%lld) ", file->f_path.dentry->d_parent->d_name.name, file->f_path.dentry->d_name.name, mapping->host->i_ino, len, (long long) pos); |
efc91ed01 NFS: Optimise app... |
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 |
/* * Zero any uninitialised parts of the page, and then mark the page * as up to date if it turns out that we're extending the file. */ if (!PageUptodate(page)) { unsigned pglen = nfs_page_length(page); unsigned end = offset + len; if (pglen == 0) { zero_user_segments(page, 0, offset, end, PAGE_CACHE_SIZE); SetPageUptodate(page); } else if (end >= pglen) { zero_user_segment(page, end, PAGE_CACHE_SIZE); if (offset == 0) SetPageUptodate(page); } else zero_user_segment(page, pglen, PAGE_CACHE_SIZE); } |
4899f9c85 nfs: convert to n... |
401 |
status = nfs_updatepage(file, page, offset, copied); |
4899f9c85 nfs: convert to n... |
402 403 404 |
unlock_page(page); page_cache_release(page); |
3d509e545 NFS: nfs_write_en... |
405 406 407 |
if (status < 0) return status; return copied; |
1da177e4c Linux-2.6.12-rc2 |
408 |
} |
6b9b3514a NFS: Add comment ... |
409 410 411 412 |
/* * Partially or wholly invalidate a page * - Release the private state associated with a page if undergoing complete * page invalidation |
545db45f0 NFS: FS-Cache pag... |
413 |
* - Called if either PG_private or PG_fscache is set on the page |
6b9b3514a NFS: Add comment ... |
414 415 |
* - Caller holds page lock */ |
2ff28e22b [PATCH] Make addr... |
416 |
static void nfs_invalidate_page(struct page *page, unsigned long offset) |
cd52ed355 NFS: Avoid races ... |
417 |
{ |
b7eaefaa8 NFS: Add debuggin... |
418 419 |
dfprintk(PAGECACHE, "NFS: invalidate_page(%p, %lu) ", page, offset); |
1c75950b9 NFS: cleanup of n... |
420 421 |
if (offset != 0) return; |
d2ccddf04 NFS: Flesh out nf... |
422 |
/* Cancel any unstarted writes on this page */ |
1b3b4a1a2 NFS: Fix a write ... |
423 |
nfs_wb_page_cancel(page->mapping->host, page); |
545db45f0 NFS: FS-Cache pag... |
424 425 |
nfs_fscache_invalidate_page(page, page->mapping->host); |
cd52ed355 NFS: Avoid races ... |
426 |
} |
6b9b3514a NFS: Add comment ... |
427 428 |
/* * Attempt to release the private state associated with a page |
545db45f0 NFS: FS-Cache pag... |
429 |
* - Called if either PG_private or PG_fscache is set on the page |
6b9b3514a NFS: Add comment ... |
430 431 432 |
* - Caller holds page lock * - Return true (may release page) or false (may not) */ |
cd52ed355 NFS: Avoid races ... |
433 434 |
static int nfs_release_page(struct page *page, gfp_t gfp) { |
b608b283a NFS: kswapd must ... |
435 |
struct address_space *mapping = page->mapping; |
b7eaefaa8 NFS: Add debuggin... |
436 437 |
dfprintk(PAGECACHE, "NFS: release_page(%p) ", page); |
d812e5758 NFS: Prevent anot... |
438 |
/* Only do I/O if gfp is a superset of GFP_KERNEL */ |
b608b283a NFS: kswapd must ... |
439 440 441 442 443 444 445 446 |
if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL) { int how = FLUSH_SYNC; /* Don't let kswapd deadlock waiting for OOM RPC calls */ if (current_is_kswapd()) how = 0; nfs_commit_inode(mapping->host, how); } |
e3db7691e [PATCH] NFS: Fix ... |
447 |
/* If PagePrivate() is set, then the page is not freeable */ |
545db45f0 NFS: FS-Cache pag... |
448 449 450 |
if (PagePrivate(page)) return 0; return nfs_fscache_release_page(page, gfp); |
e3db7691e [PATCH] NFS: Fix ... |
451 |
} |
6b9b3514a NFS: Add comment ... |
452 453 454 455 |
/* * Attempt to clear the private state associated with a page when an error * occurs that requires the cached contents of an inode to be written back or * destroyed |
545db45f0 NFS: FS-Cache pag... |
456 |
* - Called if either PG_private or fscache is set on the page |
6b9b3514a NFS: Add comment ... |
457 458 459 |
* - Caller holds page lock * - Return 0 if successful, -error otherwise */ |
e3db7691e [PATCH] NFS: Fix ... |
460 461 |
static int nfs_launder_page(struct page *page) { |
b7eaefaa8 NFS: Add debuggin... |
462 |
struct inode *inode = page->mapping->host; |
545db45f0 NFS: FS-Cache pag... |
463 |
struct nfs_inode *nfsi = NFS_I(inode); |
b7eaefaa8 NFS: Add debuggin... |
464 465 466 467 |
dfprintk(PAGECACHE, "NFS: launder_page(%ld, %llu) ", inode->i_ino, (long long)page_offset(page)); |
545db45f0 NFS: FS-Cache pag... |
468 |
nfs_fscache_wait_on_page_write(nfsi, page); |
b7eaefaa8 NFS: Add debuggin... |
469 |
return nfs_wb_page(inode, page); |
cd52ed355 NFS: Avoid races ... |
470 |
} |
f5e54d6e5 [PATCH] mark addr... |
471 |
const struct address_space_operations nfs_file_aops = { |
1da177e4c Linux-2.6.12-rc2 |
472 473 |
.readpage = nfs_readpage, .readpages = nfs_readpages, |
9cccef950 NFS: Clean up wri... |
474 |
.set_page_dirty = __set_page_dirty_nobuffers, |
1da177e4c Linux-2.6.12-rc2 |
475 476 |
.writepage = nfs_writepage, .writepages = nfs_writepages, |
4899f9c85 nfs: convert to n... |
477 478 |
.write_begin = nfs_write_begin, .write_end = nfs_write_end, |
cd52ed355 NFS: Avoid races ... |
479 480 |
.invalidatepage = nfs_invalidate_page, .releasepage = nfs_release_page, |
1da177e4c Linux-2.6.12-rc2 |
481 |
.direct_IO = nfs_direct_IO, |
074cc1dee NFS: Add a ->migr... |
482 |
.migratepage = nfs_migrate_page, |
e3db7691e [PATCH] NFS: Fix ... |
483 |
.launder_page = nfs_launder_page, |
f590f333f HWPOISON: Enable ... |
484 |
.error_remove_page = generic_error_remove_page, |
1da177e4c Linux-2.6.12-rc2 |
485 |
}; |
6b9b3514a NFS: Add comment ... |
486 487 488 489 490 |
/* * Notification that a PTE pointing to an NFS page is about to be made * writable, implying that someone is about to modify the page through a * shared-writable mapping */ |
c2ec175c3 mm: page_mkwrite ... |
491 |
static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) |
94387fb1a NFS: Add the help... |
492 |
{ |
c2ec175c3 mm: page_mkwrite ... |
493 |
struct page *page = vmf->page; |
94387fb1a NFS: Add the help... |
494 |
struct file *filp = vma->vm_file; |
b7eaefaa8 NFS: Add debuggin... |
495 |
struct dentry *dentry = filp->f_path.dentry; |
94387fb1a NFS: Add the help... |
496 |
unsigned pagelen; |
bc4866b6e NFS: Don't SIGBUS... |
497 |
int ret = VM_FAULT_NOPAGE; |
4899f9c85 nfs: convert to n... |
498 |
struct address_space *mapping; |
94387fb1a NFS: Add the help... |
499 |
|
b7eaefaa8 NFS: Add debuggin... |
500 501 502 503 504 |
dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld) ", dentry->d_parent->d_name.name, dentry->d_name.name, filp->f_mapping->host->i_ino, (long long)page_offset(page)); |
545db45f0 NFS: FS-Cache pag... |
505 506 |
/* make sure the cache has finished storing the page */ nfs_fscache_wait_on_page_write(NFS_I(dentry->d_inode), page); |
94387fb1a NFS: Add the help... |
507 |
lock_page(page); |
4899f9c85 nfs: convert to n... |
508 |
mapping = page->mapping; |
b7eaefaa8 NFS: Add debuggin... |
509 |
if (mapping != dentry->d_inode->i_mapping) |
8b1f9ee56 NFS: Optimise nfs... |
510 |
goto out_unlock; |
94387fb1a NFS: Add the help... |
511 |
pagelen = nfs_page_length(page); |
8b1f9ee56 NFS: Optimise nfs... |
512 513 |
if (pagelen == 0) goto out_unlock; |
4899f9c85 nfs: convert to n... |
514 |
|
bc4866b6e NFS: Don't SIGBUS... |
515 516 517 518 |
ret = VM_FAULT_LOCKED; if (nfs_flush_incompatible(filp, page) == 0 && nfs_updatepage(filp, page, 0, pagelen) == 0) goto out; |
8b1f9ee56 NFS: Optimise nfs... |
519 |
|
bc4866b6e NFS: Don't SIGBUS... |
520 |
ret = VM_FAULT_SIGBUS; |
8b1f9ee56 NFS: Optimise nfs... |
521 522 |
out_unlock: unlock_page(page); |
bc4866b6e NFS: Don't SIGBUS... |
523 524 |
out: return ret; |
94387fb1a NFS: Add the help... |
525 |
} |
f0f37e2f7 const: mark struc... |
526 |
static const struct vm_operations_struct nfs_file_vm_ops = { |
94387fb1a NFS: Add the help... |
527 528 529 |
.fault = filemap_fault, .page_mkwrite = nfs_vm_page_mkwrite, }; |
7b159fc18 NFS: Fall back to... |
530 531 532 |
static int nfs_need_sync_write(struct file *filp, struct inode *inode) { struct nfs_open_context *ctx; |
6b2f3d1f7 vfs: Implement pr... |
533 |
if (IS_SYNC(inode) || (filp->f_flags & O_DSYNC)) |
7b159fc18 NFS: Fall back to... |
534 |
return 1; |
cd3758e37 NFS: Replace file... |
535 |
ctx = nfs_file_open_context(filp); |
7b159fc18 NFS: Fall back to... |
536 537 538 539 |
if (test_bit(NFS_CONTEXT_ERROR_WRITE, &ctx->flags)) return 1; return 0; } |
027445c37 [PATCH] Vectorize... |
540 541 |
static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) |
1da177e4c Linux-2.6.12-rc2 |
542 |
{ |
01cce933d [PATCH] nfs: chan... |
543 |
struct dentry * dentry = iocb->ki_filp->f_path.dentry; |
1da177e4c Linux-2.6.12-rc2 |
544 |
struct inode * inode = dentry->d_inode; |
7e381172c NFS: Improve NFS ... |
545 |
unsigned long written = 0; |
1da177e4c Linux-2.6.12-rc2 |
546 |
ssize_t result; |
027445c37 [PATCH] Vectorize... |
547 |
size_t count = iov_length(iov, nr_segs); |
1da177e4c Linux-2.6.12-rc2 |
548 |
|
1da177e4c Linux-2.6.12-rc2 |
549 |
if (iocb->ki_filp->f_flags & O_DIRECT) |
027445c37 [PATCH] Vectorize... |
550 |
return nfs_file_direct_write(iocb, iov, nr_segs, pos); |
1da177e4c Linux-2.6.12-rc2 |
551 |
|
6da24bc9c NFS: Use NFSDBG_F... |
552 553 |
dprintk("NFS: write(%s/%s, %lu@%Ld) ", |
1da177e4c Linux-2.6.12-rc2 |
554 |
dentry->d_parent->d_name.name, dentry->d_name.name, |
6da24bc9c NFS: Use NFSDBG_F... |
555 |
(unsigned long) count, (long long) pos); |
1da177e4c Linux-2.6.12-rc2 |
556 557 558 559 |
result = -EBUSY; if (IS_SWAPFILE(inode)) goto out_swapfile; |
7d52e8627 [PATCH] NFS: Clea... |
560 561 562 563 564 565 566 |
/* * O_APPEND implies that we must revalidate the file length. */ if (iocb->ki_filp->f_flags & O_APPEND) { result = nfs_revalidate_file_size(inode, iocb->ki_filp); if (result) goto out; |
fe51beecc [PATCH] NFS: Ensu... |
567 |
} |
1da177e4c Linux-2.6.12-rc2 |
568 569 570 571 |
result = count; if (!count) goto out; |
027445c37 [PATCH] Vectorize... |
572 |
result = generic_file_aio_write(iocb, iov, nr_segs, pos); |
7e381172c NFS: Improve NFS ... |
573 574 |
if (result > 0) written = result; |
6b2f3d1f7 vfs: Implement pr... |
575 |
/* Return error values for O_DSYNC and IS_SYNC() */ |
7b159fc18 NFS: Fall back to... |
576 |
if (result >= 0 && nfs_need_sync_write(iocb->ki_filp, inode)) { |
af7fa1650 NFS: Fix up the f... |
577 |
int err = vfs_fsync(iocb->ki_filp, 0); |
200baa211 NFS: Remove nfs_w... |
578 579 580 |
if (err < 0) result = err; } |
7e381172c NFS: Improve NFS ... |
581 582 |
if (result > 0) nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, written); |
1da177e4c Linux-2.6.12-rc2 |
583 584 585 586 587 588 589 590 |
out: return result; out_swapfile: printk(KERN_INFO "NFS: attempt to write to active swap file! "); goto out; } |
bf40d3435 NFS: add support ... |
591 592 593 594 595 596 |
static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe, struct file *filp, loff_t *ppos, size_t count, unsigned int flags) { struct dentry *dentry = filp->f_path.dentry; struct inode *inode = dentry->d_inode; |
7e381172c NFS: Improve NFS ... |
597 |
unsigned long written = 0; |
bf40d3435 NFS: add support ... |
598 599 600 601 602 603 604 605 606 607 |
ssize_t ret; dprintk("NFS splice_write(%s/%s, %lu@%llu) ", dentry->d_parent->d_name.name, dentry->d_name.name, (unsigned long) count, (unsigned long long) *ppos); /* * The combination of splice and an O_APPEND destination is disallowed. */ |
bf40d3435 NFS: add support ... |
608 |
ret = generic_file_splice_write(pipe, filp, ppos, count, flags); |
7e381172c NFS: Improve NFS ... |
609 610 |
if (ret > 0) written = ret; |
bf40d3435 NFS: add support ... |
611 |
if (ret >= 0 && nfs_need_sync_write(filp, inode)) { |
af7fa1650 NFS: Fix up the f... |
612 |
int err = vfs_fsync(filp, 0); |
bf40d3435 NFS: add support ... |
613 614 615 |
if (err < 0) ret = err; } |
7e381172c NFS: Improve NFS ... |
616 617 |
if (ret > 0) nfs_add_stats(inode, NFSIOS_NORMALWRITTENBYTES, written); |
bf40d3435 NFS: add support ... |
618 619 |
return ret; } |
5eebde232 nfs: introduce mo... |
620 621 |
static int do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) |
1da177e4c Linux-2.6.12-rc2 |
622 623 624 |
{ struct inode *inode = filp->f_mapping->host; int status = 0; |
21ac19d48 NFS: Fix fcntl F_... |
625 |
unsigned int saved_type = fl->fl_type; |
1da177e4c Linux-2.6.12-rc2 |
626 |
|
039c4d7a8 NFS: Fix up a rac... |
627 |
/* Try local locking first */ |
6d34ac199 locks: make posix... |
628 629 630 |
posix_test_lock(filp, fl); if (fl->fl_type != F_UNLCK) { /* found a conflict */ |
039c4d7a8 NFS: Fix up a rac... |
631 |
goto out; |
1da177e4c Linux-2.6.12-rc2 |
632 |
} |
21ac19d48 NFS: Fix fcntl F_... |
633 |
fl->fl_type = saved_type; |
039c4d7a8 NFS: Fix up a rac... |
634 635 636 |
if (nfs_have_delegation(inode, FMODE_READ)) goto out_noconflict; |
5eebde232 nfs: introduce mo... |
637 |
if (is_local) |
039c4d7a8 NFS: Fix up a rac... |
638 639 640 641 |
goto out_noconflict; status = NFS_PROTO(inode)->lock(filp, cmd, fl); out: |
1da177e4c Linux-2.6.12-rc2 |
642 |
return status; |
039c4d7a8 NFS: Fix up a rac... |
643 644 645 |
out_noconflict: fl->fl_type = F_UNLCK; goto out; |
1da177e4c Linux-2.6.12-rc2 |
646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 |
} static int do_vfs_lock(struct file *file, struct file_lock *fl) { int res = 0; switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) { case FL_POSIX: res = posix_lock_file_wait(file, fl); break; case FL_FLOCK: res = flock_lock_file_wait(file, fl); break; default: BUG(); } |
1da177e4c Linux-2.6.12-rc2 |
661 662 |
return res; } |
5eebde232 nfs: introduce mo... |
663 664 |
static int do_unlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) |
1da177e4c Linux-2.6.12-rc2 |
665 666 |
{ struct inode *inode = filp->f_mapping->host; |
1da177e4c Linux-2.6.12-rc2 |
667 |
int status; |
1da177e4c Linux-2.6.12-rc2 |
668 669 670 671 |
/* * Flush all pending writes before doing anything * with locks.. */ |
29884df0d NFS: Fix another ... |
672 |
nfs_sync_mapping(filp->f_mapping); |
1da177e4c Linux-2.6.12-rc2 |
673 674 675 676 677 |
/* NOTE: special case * If we're signalled while cleaning up locks on process exit, we * still need to complete the unlock. */ |
5eebde232 nfs: introduce mo... |
678 679 680 681 682 |
/* * Use local locking if mounted with "-onolock" or with appropriate * "-olocal_lock=" */ if (!is_local) |
1da177e4c Linux-2.6.12-rc2 |
683 684 685 |
status = NFS_PROTO(inode)->lock(filp, cmd, fl); else status = do_vfs_lock(filp, fl); |
1da177e4c Linux-2.6.12-rc2 |
686 687 |
return status; } |
5eebde232 nfs: introduce mo... |
688 |
static int |
6b96724e5 Revalidate caches... |
689 690 691 692 693 |
is_time_granular(struct timespec *ts) { return ((ts->tv_sec == 0) && (ts->tv_nsec <= 1000)); } static int |
5eebde232 nfs: introduce mo... |
694 |
do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) |
1da177e4c Linux-2.6.12-rc2 |
695 696 |
{ struct inode *inode = filp->f_mapping->host; |
1da177e4c Linux-2.6.12-rc2 |
697 |
int status; |
1da177e4c Linux-2.6.12-rc2 |
698 699 700 701 |
/* * Flush all pending writes before doing anything * with locks.. */ |
29884df0d NFS: Fix another ... |
702 703 |
status = nfs_sync_mapping(filp->f_mapping); if (status != 0) |
1da177e4c Linux-2.6.12-rc2 |
704 |
goto out; |
5eebde232 nfs: introduce mo... |
705 706 707 708 709 |
/* * Use local locking if mounted with "-onolock" or with appropriate * "-olocal_lock=" */ if (!is_local) |
1da177e4c Linux-2.6.12-rc2 |
710 |
status = NFS_PROTO(inode)->lock(filp, cmd, fl); |
c4d7c402b NFS: Remove the b... |
711 |
else |
1da177e4c Linux-2.6.12-rc2 |
712 |
status = do_vfs_lock(filp, fl); |
1da177e4c Linux-2.6.12-rc2 |
713 714 |
if (status < 0) goto out; |
6b96724e5 Revalidate caches... |
715 |
|
1da177e4c Linux-2.6.12-rc2 |
716 |
/* |
6b96724e5 Revalidate caches... |
717 718 719 720 |
* Revalidate the cache if the server has time stamps granular * enough to detect subsecond changes. Otherwise, clear the * cache to prevent missing any changes. * |
1da177e4c Linux-2.6.12-rc2 |
721 722 |
* This makes locking act as a cache coherency point. */ |
29884df0d NFS: Fix another ... |
723 |
nfs_sync_mapping(filp->f_mapping); |
6b96724e5 Revalidate caches... |
724 725 726 727 728 729 |
if (!nfs_have_delegation(inode, FMODE_READ)) { if (is_time_granular(&NFS_SERVER(inode)->time_delta)) __nfs_revalidate_inode(NFS_SERVER(inode), inode); else nfs_zap_caches(inode); } |
1da177e4c Linux-2.6.12-rc2 |
730 |
out: |
1da177e4c Linux-2.6.12-rc2 |
731 732 733 734 735 736 737 738 |
return status; } /* * Lock a (portion of) a file */ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) { |
6da24bc9c NFS: Use NFSDBG_F... |
739 |
struct inode *inode = filp->f_mapping->host; |
2116271a3 NFS: Add correct ... |
740 |
int ret = -ENOLCK; |
5eebde232 nfs: introduce mo... |
741 |
int is_local = 0; |
1da177e4c Linux-2.6.12-rc2 |
742 |
|
6da24bc9c NFS: Use NFSDBG_F... |
743 744 745 746 |
dprintk("NFS: lock(%s/%s, t=%x, fl=%x, r=%lld:%lld) ", filp->f_path.dentry->d_parent->d_name.name, filp->f_path.dentry->d_name.name, |
1da177e4c Linux-2.6.12-rc2 |
747 748 |
fl->fl_type, fl->fl_flags, (long long)fl->fl_start, (long long)fl->fl_end); |
6da24bc9c NFS: Use NFSDBG_F... |
749 |
|
91d5b4702 NFS: add I/O perf... |
750 |
nfs_inc_stats(inode, NFSIOS_VFSLOCK); |
1da177e4c Linux-2.6.12-rc2 |
751 752 |
/* No mandatory locks over NFS */ |
dfad9441b NFS: clean up exp... |
753 |
if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) |
2116271a3 NFS: Add correct ... |
754 |
goto out_err; |
5eebde232 nfs: introduce mo... |
755 756 |
if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FCNTL) is_local = 1; |
2116271a3 NFS: Add correct ... |
757 758 759 760 761 |
if (NFS_PROTO(inode)->lock_check_bounds != NULL) { ret = NFS_PROTO(inode)->lock_check_bounds(fl); if (ret < 0) goto out_err; } |
1da177e4c Linux-2.6.12-rc2 |
762 763 |
if (IS_GETLK(cmd)) |
5eebde232 nfs: introduce mo... |
764 |
ret = do_getlk(filp, cmd, fl, is_local); |
2116271a3 NFS: Add correct ... |
765 |
else if (fl->fl_type == F_UNLCK) |
5eebde232 nfs: introduce mo... |
766 |
ret = do_unlk(filp, cmd, fl, is_local); |
2116271a3 NFS: Add correct ... |
767 |
else |
5eebde232 nfs: introduce mo... |
768 |
ret = do_setlk(filp, cmd, fl, is_local); |
2116271a3 NFS: Add correct ... |
769 770 |
out_err: return ret; |
1da177e4c Linux-2.6.12-rc2 |
771 772 773 774 775 776 777 |
} /* * Lock a (portion of) a file */ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) { |
5eebde232 nfs: introduce mo... |
778 779 |
struct inode *inode = filp->f_mapping->host; int is_local = 0; |
6da24bc9c NFS: Use NFSDBG_F... |
780 781 782 783 |
dprintk("NFS: flock(%s/%s, t=%x, fl=%x) ", filp->f_path.dentry->d_parent->d_name.name, filp->f_path.dentry->d_name.name, |
1da177e4c Linux-2.6.12-rc2 |
784 |
fl->fl_type, fl->fl_flags); |
1da177e4c Linux-2.6.12-rc2 |
785 786 |
if (!(fl->fl_flags & FL_FLOCK)) return -ENOLCK; |
5eebde232 nfs: introduce mo... |
787 788 |
if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FLOCK) is_local = 1; |
1da177e4c Linux-2.6.12-rc2 |
789 790 791 792 793 794 |
/* We're simulating flock() locks using posix locks on the server */ fl->fl_owner = (fl_owner_t)filp; fl->fl_start = 0; fl->fl_end = OFFSET_MAX; if (fl->fl_type == F_UNLCK) |
5eebde232 nfs: introduce mo... |
795 796 |
return do_unlk(filp, cmd, fl, is_local); return do_setlk(filp, cmd, fl, is_local); |
1da177e4c Linux-2.6.12-rc2 |
797 |
} |
370f6599e nfs: disable leas... |
798 |
|
6da24bc9c NFS: Use NFSDBG_F... |
799 800 801 802 |
/* * There is no protocol support for leases, so we have no way to implement * them correctly in the face of opens by other clients. */ |
370f6599e nfs: disable leas... |
803 804 |
static int nfs_setlease(struct file *file, long arg, struct file_lock **fl) { |
6da24bc9c NFS: Use NFSDBG_F... |
805 806 807 808 |
dprintk("NFS: setlease(%s/%s, arg=%ld) ", file->f_path.dentry->d_parent->d_name.name, file->f_path.dentry->d_name.name, arg); |
370f6599e nfs: disable leas... |
809 810 |
return -EINVAL; } |
1788ea6e3 nfs: when attempt... |
811 |
|
0486958f5 nfs: move nfs_fil... |
812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 |
const struct file_operations nfs_file_operations = { .llseek = nfs_file_llseek, .read = do_sync_read, .write = do_sync_write, .aio_read = nfs_file_read, .aio_write = nfs_file_write, .mmap = nfs_file_mmap, .open = nfs_file_open, .flush = nfs_file_flush, .release = nfs_file_release, .fsync = nfs_file_fsync, .lock = nfs_lock, .flock = nfs_flock, .splice_read = nfs_file_splice_read, .splice_write = nfs_file_splice_write, .check_flags = nfs_check_flags, .setlease = nfs_setlease, }; |
1788ea6e3 nfs: when attempt... |
830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 |
#ifdef CONFIG_NFS_V4 static int nfs4_file_open(struct inode *inode, struct file *filp) { /* * NFSv4 opens are handled in d_lookup and d_revalidate. If we get to * this point, then something is very wrong */ dprintk("NFS: %s called! inode=%p filp=%p ", __func__, inode, filp); return -ENOTDIR; } const struct file_operations nfs4_file_operations = { .llseek = nfs_file_llseek, .read = do_sync_read, .write = do_sync_write, .aio_read = nfs_file_read, .aio_write = nfs_file_write, .mmap = nfs_file_mmap, .open = nfs4_file_open, .flush = nfs_file_flush, .release = nfs_file_release, .fsync = nfs_file_fsync, .lock = nfs_lock, .flock = nfs_flock, .splice_read = nfs_file_splice_read, .splice_write = nfs_file_splice_write, .check_flags = nfs_check_flags, .setlease = nfs_setlease, }; #endif /* CONFIG_NFS_V4 */ |