diff options
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 155 |
1 files changed, 116 insertions, 39 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 4e98a56a1777..78460657f5cb 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -50,7 +50,7 @@ static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov, | |||
50 | static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov, | 50 | static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov, |
51 | unsigned long nr_segs, loff_t pos); | 51 | unsigned long nr_segs, loff_t pos); |
52 | static int nfs_file_flush(struct file *, fl_owner_t id); | 52 | static int nfs_file_flush(struct file *, fl_owner_t id); |
53 | static int nfs_fsync(struct file *, struct dentry *dentry, int datasync); | 53 | static int nfs_file_fsync(struct file *, struct dentry *dentry, int datasync); |
54 | static int nfs_check_flags(int flags); | 54 | static int nfs_check_flags(int flags); |
55 | static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); | 55 | static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); |
56 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); | 56 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); |
@@ -72,7 +72,7 @@ const struct file_operations nfs_file_operations = { | |||
72 | .open = nfs_file_open, | 72 | .open = nfs_file_open, |
73 | .flush = nfs_file_flush, | 73 | .flush = nfs_file_flush, |
74 | .release = nfs_file_release, | 74 | .release = nfs_file_release, |
75 | .fsync = nfs_fsync, | 75 | .fsync = nfs_file_fsync, |
76 | .lock = nfs_lock, | 76 | .lock = nfs_lock, |
77 | .flock = nfs_flock, | 77 | .flock = nfs_flock, |
78 | .splice_read = nfs_file_splice_read, | 78 | .splice_read = nfs_file_splice_read, |
@@ -119,25 +119,33 @@ nfs_file_open(struct inode *inode, struct file *filp) | |||
119 | { | 119 | { |
120 | int res; | 120 | int res; |
121 | 121 | ||
122 | dprintk("NFS: open file(%s/%s)\n", | ||
123 | filp->f_path.dentry->d_parent->d_name.name, | ||
124 | filp->f_path.dentry->d_name.name); | ||
125 | |||
122 | res = nfs_check_flags(filp->f_flags); | 126 | res = nfs_check_flags(filp->f_flags); |
123 | if (res) | 127 | if (res) |
124 | return res; | 128 | return res; |
125 | 129 | ||
126 | nfs_inc_stats(inode, NFSIOS_VFSOPEN); | 130 | nfs_inc_stats(inode, NFSIOS_VFSOPEN); |
127 | lock_kernel(); | 131 | res = nfs_open(inode, filp); |
128 | res = NFS_PROTO(inode)->file_open(inode, filp); | ||
129 | unlock_kernel(); | ||
130 | return res; | 132 | return res; |
131 | } | 133 | } |
132 | 134 | ||
133 | static int | 135 | static int |
134 | nfs_file_release(struct inode *inode, struct file *filp) | 136 | nfs_file_release(struct inode *inode, struct file *filp) |
135 | { | 137 | { |
138 | struct dentry *dentry = filp->f_path.dentry; | ||
139 | |||
140 | dprintk("NFS: release(%s/%s)\n", | ||
141 | dentry->d_parent->d_name.name, | ||
142 | dentry->d_name.name); | ||
143 | |||
136 | /* Ensure that dirty pages are flushed out with the right creds */ | 144 | /* Ensure that dirty pages are flushed out with the right creds */ |
137 | if (filp->f_mode & FMODE_WRITE) | 145 | if (filp->f_mode & FMODE_WRITE) |
138 | nfs_wb_all(filp->f_path.dentry->d_inode); | 146 | nfs_wb_all(dentry->d_inode); |
139 | nfs_inc_stats(inode, NFSIOS_VFSRELEASE); | 147 | nfs_inc_stats(inode, NFSIOS_VFSRELEASE); |
140 | return NFS_PROTO(inode)->file_release(inode, filp); | 148 | return nfs_release(inode, filp); |
141 | } | 149 | } |
142 | 150 | ||
143 | /** | 151 | /** |
@@ -171,6 +179,12 @@ force_reval: | |||
171 | static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) | 179 | static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) |
172 | { | 180 | { |
173 | loff_t loff; | 181 | loff_t loff; |
182 | |||
183 | dprintk("NFS: llseek file(%s/%s, %lld, %d)\n", | ||
184 | filp->f_path.dentry->d_parent->d_name.name, | ||
185 | filp->f_path.dentry->d_name.name, | ||
186 | offset, origin); | ||
187 | |||
174 | /* origin == SEEK_END => we must revalidate the cached file length */ | 188 | /* origin == SEEK_END => we must revalidate the cached file length */ |
175 | if (origin == SEEK_END) { | 189 | if (origin == SEEK_END) { |
176 | struct inode *inode = filp->f_mapping->host; | 190 | struct inode *inode = filp->f_mapping->host; |
@@ -185,7 +199,7 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) | |||
185 | } | 199 | } |
186 | 200 | ||
187 | /* | 201 | /* |
188 | * Helper for nfs_file_flush() and nfs_fsync() | 202 | * Helper for nfs_file_flush() and nfs_file_fsync() |
189 | * | 203 | * |
190 | * Notice that it clears the NFS_CONTEXT_ERROR_WRITE before synching to | 204 | * Notice that it clears the NFS_CONTEXT_ERROR_WRITE before synching to |
191 | * disk, but it retrieves and clears ctx->error after synching, despite | 205 | * disk, but it retrieves and clears ctx->error after synching, despite |
@@ -211,16 +225,18 @@ static int nfs_do_fsync(struct nfs_open_context *ctx, struct inode *inode) | |||
211 | 225 | ||
212 | /* | 226 | /* |
213 | * Flush all dirty pages, and check for write errors. | 227 | * Flush all dirty pages, and check for write errors. |
214 | * | ||
215 | */ | 228 | */ |
216 | static int | 229 | static int |
217 | nfs_file_flush(struct file *file, fl_owner_t id) | 230 | nfs_file_flush(struct file *file, fl_owner_t id) |
218 | { | 231 | { |
219 | struct nfs_open_context *ctx = nfs_file_open_context(file); | 232 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
220 | struct inode *inode = file->f_path.dentry->d_inode; | 233 | struct dentry *dentry = file->f_path.dentry; |
234 | struct inode *inode = dentry->d_inode; | ||
221 | int status; | 235 | int status; |
222 | 236 | ||
223 | dfprintk(VFS, "nfs: flush(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino); | 237 | dprintk("NFS: flush(%s/%s)\n", |
238 | dentry->d_parent->d_name.name, | ||
239 | dentry->d_name.name); | ||
224 | 240 | ||
225 | if ((file->f_mode & FMODE_WRITE) == 0) | 241 | if ((file->f_mode & FMODE_WRITE) == 0) |
226 | return 0; | 242 | return 0; |
@@ -245,7 +261,7 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov, | |||
245 | if (iocb->ki_filp->f_flags & O_DIRECT) | 261 | if (iocb->ki_filp->f_flags & O_DIRECT) |
246 | return nfs_file_direct_read(iocb, iov, nr_segs, pos); | 262 | return nfs_file_direct_read(iocb, iov, nr_segs, pos); |
247 | 263 | ||
248 | dfprintk(VFS, "nfs: read(%s/%s, %lu@%lu)\n", | 264 | dprintk("NFS: read(%s/%s, %lu@%lu)\n", |
249 | dentry->d_parent->d_name.name, dentry->d_name.name, | 265 | dentry->d_parent->d_name.name, dentry->d_name.name, |
250 | (unsigned long) count, (unsigned long) pos); | 266 | (unsigned long) count, (unsigned long) pos); |
251 | 267 | ||
@@ -265,7 +281,7 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos, | |||
265 | struct inode *inode = dentry->d_inode; | 281 | struct inode *inode = dentry->d_inode; |
266 | ssize_t res; | 282 | ssize_t res; |
267 | 283 | ||
268 | dfprintk(VFS, "nfs: splice_read(%s/%s, %lu@%Lu)\n", | 284 | dprintk("NFS: splice_read(%s/%s, %lu@%Lu)\n", |
269 | dentry->d_parent->d_name.name, dentry->d_name.name, | 285 | dentry->d_parent->d_name.name, dentry->d_name.name, |
270 | (unsigned long) count, (unsigned long long) *ppos); | 286 | (unsigned long) count, (unsigned long long) *ppos); |
271 | 287 | ||
@@ -282,7 +298,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) | |||
282 | struct inode *inode = dentry->d_inode; | 298 | struct inode *inode = dentry->d_inode; |
283 | int status; | 299 | int status; |
284 | 300 | ||
285 | dfprintk(VFS, "nfs: mmap(%s/%s)\n", | 301 | dprintk("NFS: mmap(%s/%s)\n", |
286 | dentry->d_parent->d_name.name, dentry->d_name.name); | 302 | dentry->d_parent->d_name.name, dentry->d_name.name); |
287 | 303 | ||
288 | status = nfs_revalidate_mapping(inode, file->f_mapping); | 304 | status = nfs_revalidate_mapping(inode, file->f_mapping); |
@@ -300,12 +316,14 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) | |||
300 | * whether any write errors occurred for this process. | 316 | * whether any write errors occurred for this process. |
301 | */ | 317 | */ |
302 | static int | 318 | static int |
303 | nfs_fsync(struct file *file, struct dentry *dentry, int datasync) | 319 | nfs_file_fsync(struct file *file, struct dentry *dentry, int datasync) |
304 | { | 320 | { |
305 | struct nfs_open_context *ctx = nfs_file_open_context(file); | 321 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
306 | struct inode *inode = dentry->d_inode; | 322 | struct inode *inode = dentry->d_inode; |
307 | 323 | ||
308 | dfprintk(VFS, "nfs: fsync(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino); | 324 | dprintk("NFS: fsync file(%s/%s) datasync %d\n", |
325 | dentry->d_parent->d_name.name, dentry->d_name.name, | ||
326 | datasync); | ||
309 | 327 | ||
310 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); | 328 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); |
311 | return nfs_do_fsync(ctx, inode); | 329 | return nfs_do_fsync(ctx, inode); |
@@ -328,6 +346,11 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping, | |||
328 | struct page *page; | 346 | struct page *page; |
329 | index = pos >> PAGE_CACHE_SHIFT; | 347 | index = pos >> PAGE_CACHE_SHIFT; |
330 | 348 | ||
349 | dfprintk(PAGECACHE, "NFS: write_begin(%s/%s(%ld), %u@%lld)\n", | ||
350 | file->f_path.dentry->d_parent->d_name.name, | ||
351 | file->f_path.dentry->d_name.name, | ||
352 | mapping->host->i_ino, len, (long long) pos); | ||
353 | |||
331 | page = __grab_cache_page(mapping, index); | 354 | page = __grab_cache_page(mapping, index); |
332 | if (!page) | 355 | if (!page) |
333 | return -ENOMEM; | 356 | return -ENOMEM; |
@@ -348,9 +371,32 @@ static int nfs_write_end(struct file *file, struct address_space *mapping, | |||
348 | unsigned offset = pos & (PAGE_CACHE_SIZE - 1); | 371 | unsigned offset = pos & (PAGE_CACHE_SIZE - 1); |
349 | int status; | 372 | int status; |
350 | 373 | ||
351 | lock_kernel(); | 374 | dfprintk(PAGECACHE, "NFS: write_end(%s/%s(%ld), %u@%lld)\n", |
375 | file->f_path.dentry->d_parent->d_name.name, | ||
376 | file->f_path.dentry->d_name.name, | ||
377 | mapping->host->i_ino, len, (long long) pos); | ||
378 | |||
379 | /* | ||
380 | * Zero any uninitialised parts of the page, and then mark the page | ||
381 | * as up to date if it turns out that we're extending the file. | ||
382 | */ | ||
383 | if (!PageUptodate(page)) { | ||
384 | unsigned pglen = nfs_page_length(page); | ||
385 | unsigned end = offset + len; | ||
386 | |||
387 | if (pglen == 0) { | ||
388 | zero_user_segments(page, 0, offset, | ||
389 | end, PAGE_CACHE_SIZE); | ||
390 | SetPageUptodate(page); | ||
391 | } else if (end >= pglen) { | ||
392 | zero_user_segment(page, end, PAGE_CACHE_SIZE); | ||
393 | if (offset == 0) | ||
394 | SetPageUptodate(page); | ||
395 | } else | ||
396 | zero_user_segment(page, pglen, PAGE_CACHE_SIZE); | ||
397 | } | ||
398 | |||
352 | status = nfs_updatepage(file, page, offset, copied); | 399 | status = nfs_updatepage(file, page, offset, copied); |
353 | unlock_kernel(); | ||
354 | 400 | ||
355 | unlock_page(page); | 401 | unlock_page(page); |
356 | page_cache_release(page); | 402 | page_cache_release(page); |
@@ -362,6 +408,8 @@ static int nfs_write_end(struct file *file, struct address_space *mapping, | |||
362 | 408 | ||
363 | static void nfs_invalidate_page(struct page *page, unsigned long offset) | 409 | static void nfs_invalidate_page(struct page *page, unsigned long offset) |
364 | { | 410 | { |
411 | dfprintk(PAGECACHE, "NFS: invalidate_page(%p, %lu)\n", page, offset); | ||
412 | |||
365 | if (offset != 0) | 413 | if (offset != 0) |
366 | return; | 414 | return; |
367 | /* Cancel any unstarted writes on this page */ | 415 | /* Cancel any unstarted writes on this page */ |
@@ -370,13 +418,20 @@ static void nfs_invalidate_page(struct page *page, unsigned long offset) | |||
370 | 418 | ||
371 | static int nfs_release_page(struct page *page, gfp_t gfp) | 419 | static int nfs_release_page(struct page *page, gfp_t gfp) |
372 | { | 420 | { |
421 | dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); | ||
422 | |||
373 | /* If PagePrivate() is set, then the page is not freeable */ | 423 | /* If PagePrivate() is set, then the page is not freeable */ |
374 | return 0; | 424 | return 0; |
375 | } | 425 | } |
376 | 426 | ||
377 | static int nfs_launder_page(struct page *page) | 427 | static int nfs_launder_page(struct page *page) |
378 | { | 428 | { |
379 | return nfs_wb_page(page->mapping->host, page); | 429 | struct inode *inode = page->mapping->host; |
430 | |||
431 | dfprintk(PAGECACHE, "NFS: launder_page(%ld, %llu)\n", | ||
432 | inode->i_ino, (long long)page_offset(page)); | ||
433 | |||
434 | return nfs_wb_page(inode, page); | ||
380 | } | 435 | } |
381 | 436 | ||
382 | const struct address_space_operations nfs_file_aops = { | 437 | const struct address_space_operations nfs_file_aops = { |
@@ -396,13 +451,19 @@ const struct address_space_operations nfs_file_aops = { | |||
396 | static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page) | 451 | static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct page *page) |
397 | { | 452 | { |
398 | struct file *filp = vma->vm_file; | 453 | struct file *filp = vma->vm_file; |
454 | struct dentry *dentry = filp->f_path.dentry; | ||
399 | unsigned pagelen; | 455 | unsigned pagelen; |
400 | int ret = -EINVAL; | 456 | int ret = -EINVAL; |
401 | struct address_space *mapping; | 457 | struct address_space *mapping; |
402 | 458 | ||
459 | dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n", | ||
460 | dentry->d_parent->d_name.name, dentry->d_name.name, | ||
461 | filp->f_mapping->host->i_ino, | ||
462 | (long long)page_offset(page)); | ||
463 | |||
403 | lock_page(page); | 464 | lock_page(page); |
404 | mapping = page->mapping; | 465 | mapping = page->mapping; |
405 | if (mapping != vma->vm_file->f_path.dentry->d_inode->i_mapping) | 466 | if (mapping != dentry->d_inode->i_mapping) |
406 | goto out_unlock; | 467 | goto out_unlock; |
407 | 468 | ||
408 | ret = 0; | 469 | ret = 0; |
@@ -450,9 +511,9 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, | |||
450 | if (iocb->ki_filp->f_flags & O_DIRECT) | 511 | if (iocb->ki_filp->f_flags & O_DIRECT) |
451 | return nfs_file_direct_write(iocb, iov, nr_segs, pos); | 512 | return nfs_file_direct_write(iocb, iov, nr_segs, pos); |
452 | 513 | ||
453 | dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%Ld)\n", | 514 | dprintk("NFS: write(%s/%s, %lu@%Ld)\n", |
454 | dentry->d_parent->d_name.name, dentry->d_name.name, | 515 | dentry->d_parent->d_name.name, dentry->d_name.name, |
455 | inode->i_ino, (unsigned long) count, (long long) pos); | 516 | (unsigned long) count, (long long) pos); |
456 | 517 | ||
457 | result = -EBUSY; | 518 | result = -EBUSY; |
458 | if (IS_SWAPFILE(inode)) | 519 | if (IS_SWAPFILE(inode)) |
@@ -586,7 +647,8 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) | |||
586 | * This makes locking act as a cache coherency point. | 647 | * This makes locking act as a cache coherency point. |
587 | */ | 648 | */ |
588 | nfs_sync_mapping(filp->f_mapping); | 649 | nfs_sync_mapping(filp->f_mapping); |
589 | nfs_zap_caches(inode); | 650 | if (!nfs_have_delegation(inode, FMODE_READ)) |
651 | nfs_zap_caches(inode); | ||
590 | out: | 652 | out: |
591 | return status; | 653 | return status; |
592 | } | 654 | } |
@@ -596,23 +658,35 @@ out: | |||
596 | */ | 658 | */ |
597 | static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) | 659 | static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) |
598 | { | 660 | { |
599 | struct inode * inode = filp->f_mapping->host; | 661 | struct inode *inode = filp->f_mapping->host; |
662 | int ret = -ENOLCK; | ||
600 | 663 | ||
601 | dprintk("NFS: nfs_lock(f=%s/%ld, t=%x, fl=%x, r=%Ld:%Ld)\n", | 664 | dprintk("NFS: lock(%s/%s, t=%x, fl=%x, r=%lld:%lld)\n", |
602 | inode->i_sb->s_id, inode->i_ino, | 665 | filp->f_path.dentry->d_parent->d_name.name, |
666 | filp->f_path.dentry->d_name.name, | ||
603 | fl->fl_type, fl->fl_flags, | 667 | fl->fl_type, fl->fl_flags, |
604 | (long long)fl->fl_start, (long long)fl->fl_end); | 668 | (long long)fl->fl_start, (long long)fl->fl_end); |
669 | |||
605 | nfs_inc_stats(inode, NFSIOS_VFSLOCK); | 670 | nfs_inc_stats(inode, NFSIOS_VFSLOCK); |
606 | 671 | ||
607 | /* No mandatory locks over NFS */ | 672 | /* No mandatory locks over NFS */ |
608 | if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) | 673 | if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) |
609 | return -ENOLCK; | 674 | goto out_err; |
675 | |||
676 | if (NFS_PROTO(inode)->lock_check_bounds != NULL) { | ||
677 | ret = NFS_PROTO(inode)->lock_check_bounds(fl); | ||
678 | if (ret < 0) | ||
679 | goto out_err; | ||
680 | } | ||
610 | 681 | ||
611 | if (IS_GETLK(cmd)) | 682 | if (IS_GETLK(cmd)) |
612 | return do_getlk(filp, cmd, fl); | 683 | ret = do_getlk(filp, cmd, fl); |
613 | if (fl->fl_type == F_UNLCK) | 684 | else if (fl->fl_type == F_UNLCK) |
614 | return do_unlk(filp, cmd, fl); | 685 | ret = do_unlk(filp, cmd, fl); |
615 | return do_setlk(filp, cmd, fl); | 686 | else |
687 | ret = do_setlk(filp, cmd, fl); | ||
688 | out_err: | ||
689 | return ret; | ||
616 | } | 690 | } |
617 | 691 | ||
618 | /* | 692 | /* |
@@ -620,9 +694,9 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
620 | */ | 694 | */ |
621 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) | 695 | static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) |
622 | { | 696 | { |
623 | dprintk("NFS: nfs_flock(f=%s/%ld, t=%x, fl=%x)\n", | 697 | dprintk("NFS: flock(%s/%s, t=%x, fl=%x)\n", |
624 | filp->f_path.dentry->d_inode->i_sb->s_id, | 698 | filp->f_path.dentry->d_parent->d_name.name, |
625 | filp->f_path.dentry->d_inode->i_ino, | 699 | filp->f_path.dentry->d_name.name, |
626 | fl->fl_type, fl->fl_flags); | 700 | fl->fl_type, fl->fl_flags); |
627 | 701 | ||
628 | /* | 702 | /* |
@@ -645,12 +719,15 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) | |||
645 | return do_setlk(filp, cmd, fl); | 719 | return do_setlk(filp, cmd, fl); |
646 | } | 720 | } |
647 | 721 | ||
722 | /* | ||
723 | * There is no protocol support for leases, so we have no way to implement | ||
724 | * them correctly in the face of opens by other clients. | ||
725 | */ | ||
648 | static int nfs_setlease(struct file *file, long arg, struct file_lock **fl) | 726 | static int nfs_setlease(struct file *file, long arg, struct file_lock **fl) |
649 | { | 727 | { |
650 | /* | 728 | dprintk("NFS: setlease(%s/%s, arg=%ld)\n", |
651 | * There is no protocol support for leases, so we have no way | 729 | file->f_path.dentry->d_parent->d_name.name, |
652 | * to implement them correctly in the face of opens by other | 730 | file->f_path.dentry->d_name.name, arg); |
653 | * clients. | 731 | |
654 | */ | ||
655 | return -EINVAL; | 732 | return -EINVAL; |
656 | } | 733 | } |