diff options
Diffstat (limited to 'fs/nfs/file.c')
-rw-r--r-- | fs/nfs/file.c | 161 |
1 files changed, 121 insertions, 40 deletions
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index d84a3d8f32af..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 | /** |
@@ -170,6 +178,13 @@ force_reval: | |||
170 | 178 | ||
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 | { |
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 | |||
173 | /* origin == SEEK_END => we must revalidate the cached file length */ | 188 | /* origin == SEEK_END => we must revalidate the cached file length */ |
174 | if (origin == SEEK_END) { | 189 | if (origin == SEEK_END) { |
175 | struct inode *inode = filp->f_mapping->host; | 190 | struct inode *inode = filp->f_mapping->host; |
@@ -177,11 +192,14 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) | |||
177 | if (retval < 0) | 192 | if (retval < 0) |
178 | return (loff_t)retval; | 193 | return (loff_t)retval; |
179 | } | 194 | } |
180 | return remote_llseek(filp, offset, origin); | 195 | lock_kernel(); /* BKL needed? */ |
196 | loff = generic_file_llseek_unlocked(filp, offset, origin); | ||
197 | unlock_kernel(); | ||
198 | return loff; | ||
181 | } | 199 | } |
182 | 200 | ||
183 | /* | 201 | /* |
184 | * Helper for nfs_file_flush() and nfs_fsync() | 202 | * Helper for nfs_file_flush() and nfs_file_fsync() |
185 | * | 203 | * |
186 | * 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 |
187 | * disk, but it retrieves and clears ctx->error after synching, despite | 205 | * disk, but it retrieves and clears ctx->error after synching, despite |
@@ -207,16 +225,18 @@ static int nfs_do_fsync(struct nfs_open_context *ctx, struct inode *inode) | |||
207 | 225 | ||
208 | /* | 226 | /* |
209 | * Flush all dirty pages, and check for write errors. | 227 | * Flush all dirty pages, and check for write errors. |
210 | * | ||
211 | */ | 228 | */ |
212 | static int | 229 | static int |
213 | nfs_file_flush(struct file *file, fl_owner_t id) | 230 | nfs_file_flush(struct file *file, fl_owner_t id) |
214 | { | 231 | { |
215 | struct nfs_open_context *ctx = nfs_file_open_context(file); | 232 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
216 | struct inode *inode = file->f_path.dentry->d_inode; | 233 | struct dentry *dentry = file->f_path.dentry; |
234 | struct inode *inode = dentry->d_inode; | ||
217 | int status; | 235 | int status; |
218 | 236 | ||
219 | 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); | ||
220 | 240 | ||
221 | if ((file->f_mode & FMODE_WRITE) == 0) | 241 | if ((file->f_mode & FMODE_WRITE) == 0) |
222 | return 0; | 242 | return 0; |
@@ -241,7 +261,7 @@ nfs_file_read(struct kiocb *iocb, const struct iovec *iov, | |||
241 | if (iocb->ki_filp->f_flags & O_DIRECT) | 261 | if (iocb->ki_filp->f_flags & O_DIRECT) |
242 | return nfs_file_direct_read(iocb, iov, nr_segs, pos); | 262 | return nfs_file_direct_read(iocb, iov, nr_segs, pos); |
243 | 263 | ||
244 | dfprintk(VFS, "nfs: read(%s/%s, %lu@%lu)\n", | 264 | dprintk("NFS: read(%s/%s, %lu@%lu)\n", |
245 | dentry->d_parent->d_name.name, dentry->d_name.name, | 265 | dentry->d_parent->d_name.name, dentry->d_name.name, |
246 | (unsigned long) count, (unsigned long) pos); | 266 | (unsigned long) count, (unsigned long) pos); |
247 | 267 | ||
@@ -261,7 +281,7 @@ nfs_file_splice_read(struct file *filp, loff_t *ppos, | |||
261 | struct inode *inode = dentry->d_inode; | 281 | struct inode *inode = dentry->d_inode; |
262 | ssize_t res; | 282 | ssize_t res; |
263 | 283 | ||
264 | dfprintk(VFS, "nfs: splice_read(%s/%s, %lu@%Lu)\n", | 284 | dprintk("NFS: splice_read(%s/%s, %lu@%Lu)\n", |
265 | dentry->d_parent->d_name.name, dentry->d_name.name, | 285 | dentry->d_parent->d_name.name, dentry->d_name.name, |
266 | (unsigned long) count, (unsigned long long) *ppos); | 286 | (unsigned long) count, (unsigned long long) *ppos); |
267 | 287 | ||
@@ -278,7 +298,7 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) | |||
278 | struct inode *inode = dentry->d_inode; | 298 | struct inode *inode = dentry->d_inode; |
279 | int status; | 299 | int status; |
280 | 300 | ||
281 | dfprintk(VFS, "nfs: mmap(%s/%s)\n", | 301 | dprintk("NFS: mmap(%s/%s)\n", |
282 | dentry->d_parent->d_name.name, dentry->d_name.name); | 302 | dentry->d_parent->d_name.name, dentry->d_name.name); |
283 | 303 | ||
284 | status = nfs_revalidate_mapping(inode, file->f_mapping); | 304 | status = nfs_revalidate_mapping(inode, file->f_mapping); |
@@ -296,12 +316,14 @@ nfs_file_mmap(struct file * file, struct vm_area_struct * vma) | |||
296 | * whether any write errors occurred for this process. | 316 | * whether any write errors occurred for this process. |
297 | */ | 317 | */ |
298 | static int | 318 | static int |
299 | nfs_fsync(struct file *file, struct dentry *dentry, int datasync) | 319 | nfs_file_fsync(struct file *file, struct dentry *dentry, int datasync) |
300 | { | 320 | { |
301 | struct nfs_open_context *ctx = nfs_file_open_context(file); | 321 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
302 | struct inode *inode = dentry->d_inode; | 322 | struct inode *inode = dentry->d_inode; |
303 | 323 | ||
304 | 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); | ||
305 | 327 | ||
306 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); | 328 | nfs_inc_stats(inode, NFSIOS_VFSFSYNC); |
307 | return nfs_do_fsync(ctx, inode); | 329 | return nfs_do_fsync(ctx, inode); |
@@ -324,6 +346,11 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping, | |||
324 | struct page *page; | 346 | struct page *page; |
325 | index = pos >> PAGE_CACHE_SHIFT; | 347 | index = pos >> PAGE_CACHE_SHIFT; |
326 | 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 | |||
327 | page = __grab_cache_page(mapping, index); | 354 | page = __grab_cache_page(mapping, index); |
328 | if (!page) | 355 | if (!page) |
329 | return -ENOMEM; | 356 | return -ENOMEM; |
@@ -344,9 +371,32 @@ static int nfs_write_end(struct file *file, struct address_space *mapping, | |||
344 | unsigned offset = pos & (PAGE_CACHE_SIZE - 1); | 371 | unsigned offset = pos & (PAGE_CACHE_SIZE - 1); |
345 | int status; | 372 | int status; |
346 | 373 | ||
347 | 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 | |||
348 | status = nfs_updatepage(file, page, offset, copied); | 399 | status = nfs_updatepage(file, page, offset, copied); |
349 | unlock_kernel(); | ||
350 | 400 | ||
351 | unlock_page(page); | 401 | unlock_page(page); |
352 | page_cache_release(page); | 402 | page_cache_release(page); |
@@ -358,6 +408,8 @@ static int nfs_write_end(struct file *file, struct address_space *mapping, | |||
358 | 408 | ||
359 | static void nfs_invalidate_page(struct page *page, unsigned long offset) | 409 | static void nfs_invalidate_page(struct page *page, unsigned long offset) |
360 | { | 410 | { |
411 | dfprintk(PAGECACHE, "NFS: invalidate_page(%p, %lu)\n", page, offset); | ||
412 | |||
361 | if (offset != 0) | 413 | if (offset != 0) |
362 | return; | 414 | return; |
363 | /* Cancel any unstarted writes on this page */ | 415 | /* Cancel any unstarted writes on this page */ |
@@ -366,13 +418,20 @@ static void nfs_invalidate_page(struct page *page, unsigned long offset) | |||
366 | 418 | ||
367 | static int nfs_release_page(struct page *page, gfp_t gfp) | 419 | static int nfs_release_page(struct page *page, gfp_t gfp) |
368 | { | 420 | { |
421 | dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); | ||
422 | |||
369 | /* If PagePrivate() is set, then the page is not freeable */ | 423 | /* If PagePrivate() is set, then the page is not freeable */ |
370 | return 0; | 424 | return 0; |
371 | } | 425 | } |
372 | 426 | ||
373 | static int nfs_launder_page(struct page *page) | 427 | static int nfs_launder_page(struct page *page) |
374 | { | 428 | { |
375 | 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); | ||
376 | } | 435 | } |
377 | 436 | ||
378 | const struct address_space_operations nfs_file_aops = { | 437 | const struct address_space_operations nfs_file_aops = { |
@@ -392,13 +451,19 @@ const struct address_space_operations nfs_file_aops = { | |||
392 | 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) |
393 | { | 452 | { |
394 | struct file *filp = vma->vm_file; | 453 | struct file *filp = vma->vm_file; |
454 | struct dentry *dentry = filp->f_path.dentry; | ||
395 | unsigned pagelen; | 455 | unsigned pagelen; |
396 | int ret = -EINVAL; | 456 | int ret = -EINVAL; |
397 | struct address_space *mapping; | 457 | struct address_space *mapping; |
398 | 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 | |||
399 | lock_page(page); | 464 | lock_page(page); |
400 | mapping = page->mapping; | 465 | mapping = page->mapping; |
401 | if (mapping != vma->vm_file->f_path.dentry->d_inode->i_mapping) | 466 | if (mapping != dentry->d_inode->i_mapping) |
402 | goto out_unlock; | 467 | goto out_unlock; |
403 | 468 | ||
404 | ret = 0; | 469 | ret = 0; |
@@ -446,9 +511,9 @@ static ssize_t nfs_file_write(struct kiocb *iocb, const struct iovec *iov, | |||
446 | if (iocb->ki_filp->f_flags & O_DIRECT) | 511 | if (iocb->ki_filp->f_flags & O_DIRECT) |
447 | return nfs_file_direct_write(iocb, iov, nr_segs, pos); | 512 | return nfs_file_direct_write(iocb, iov, nr_segs, pos); |
448 | 513 | ||
449 | dfprintk(VFS, "nfs: write(%s/%s(%ld), %lu@%Ld)\n", | 514 | dprintk("NFS: write(%s/%s, %lu@%Ld)\n", |
450 | dentry->d_parent->d_name.name, dentry->d_name.name, | 515 | dentry->d_parent->d_name.name, dentry->d_name.name, |
451 | inode->i_ino, (unsigned long) count, (long long) pos); | 516 | (unsigned long) count, (long long) pos); |
452 | 517 | ||
453 | result = -EBUSY; | 518 | result = -EBUSY; |
454 | if (IS_SWAPFILE(inode)) | 519 | if (IS_SWAPFILE(inode)) |
@@ -582,7 +647,8 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl) | |||
582 | * This makes locking act as a cache coherency point. | 647 | * This makes locking act as a cache coherency point. |
583 | */ | 648 | */ |
584 | nfs_sync_mapping(filp->f_mapping); | 649 | nfs_sync_mapping(filp->f_mapping); |
585 | nfs_zap_caches(inode); | 650 | if (!nfs_have_delegation(inode, FMODE_READ)) |
651 | nfs_zap_caches(inode); | ||
586 | out: | 652 | out: |
587 | return status; | 653 | return status; |
588 | } | 654 | } |
@@ -592,23 +658,35 @@ out: | |||
592 | */ | 658 | */ |
593 | 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) |
594 | { | 660 | { |
595 | struct inode * inode = filp->f_mapping->host; | 661 | struct inode *inode = filp->f_mapping->host; |
662 | int ret = -ENOLCK; | ||
596 | 663 | ||
597 | 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", |
598 | 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, | ||
599 | fl->fl_type, fl->fl_flags, | 667 | fl->fl_type, fl->fl_flags, |
600 | (long long)fl->fl_start, (long long)fl->fl_end); | 668 | (long long)fl->fl_start, (long long)fl->fl_end); |
669 | |||
601 | nfs_inc_stats(inode, NFSIOS_VFSLOCK); | 670 | nfs_inc_stats(inode, NFSIOS_VFSLOCK); |
602 | 671 | ||
603 | /* No mandatory locks over NFS */ | 672 | /* No mandatory locks over NFS */ |
604 | if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) | 673 | if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) |
605 | 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 | } | ||
606 | 681 | ||
607 | if (IS_GETLK(cmd)) | 682 | if (IS_GETLK(cmd)) |
608 | return do_getlk(filp, cmd, fl); | 683 | ret = do_getlk(filp, cmd, fl); |
609 | if (fl->fl_type == F_UNLCK) | 684 | else if (fl->fl_type == F_UNLCK) |
610 | return do_unlk(filp, cmd, fl); | 685 | ret = do_unlk(filp, cmd, fl); |
611 | return do_setlk(filp, cmd, fl); | 686 | else |
687 | ret = do_setlk(filp, cmd, fl); | ||
688 | out_err: | ||
689 | return ret; | ||
612 | } | 690 | } |
613 | 691 | ||
614 | /* | 692 | /* |
@@ -616,9 +694,9 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
616 | */ | 694 | */ |
617 | 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) |
618 | { | 696 | { |
619 | dprintk("NFS: nfs_flock(f=%s/%ld, t=%x, fl=%x)\n", | 697 | dprintk("NFS: flock(%s/%s, t=%x, fl=%x)\n", |
620 | filp->f_path.dentry->d_inode->i_sb->s_id, | 698 | filp->f_path.dentry->d_parent->d_name.name, |
621 | filp->f_path.dentry->d_inode->i_ino, | 699 | filp->f_path.dentry->d_name.name, |
622 | fl->fl_type, fl->fl_flags); | 700 | fl->fl_type, fl->fl_flags); |
623 | 701 | ||
624 | /* | 702 | /* |
@@ -641,12 +719,15 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl) | |||
641 | return do_setlk(filp, cmd, fl); | 719 | return do_setlk(filp, cmd, fl); |
642 | } | 720 | } |
643 | 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 | */ | ||
644 | 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) |
645 | { | 727 | { |
646 | /* | 728 | dprintk("NFS: setlease(%s/%s, arg=%ld)\n", |
647 | * There is no protocol support for leases, so we have no way | 729 | file->f_path.dentry->d_parent->d_name.name, |
648 | * to implement them correctly in the face of opens by other | 730 | file->f_path.dentry->d_name.name, arg); |
649 | * clients. | 731 | |
650 | */ | ||
651 | return -EINVAL; | 732 | return -EINVAL; |
652 | } | 733 | } |