diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-19 17:41:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-19 17:41:33 -0400 |
commit | fdb64f93b38a3470fa4db8cd5720b8c731922d1a (patch) | |
tree | 3b17370d30a2b580af72b26f37ec7176c9ecdd84 /fs/xfs | |
parent | 2d9ce177e68645945e3366cfe2d66ee3c28cd4f2 (diff) | |
parent | c32676eea19ce29cb74dba0f97b085e83f6b8915 (diff) |
Merge branch 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6
* 'for-linus' of git://oss.sgi.com:8090/xfs/xfs-2.6:
[XFS] Fix inode size update before data write in xfs_setattr
[XFS] Allow punching holes to free space when at ENOSPC
[XFS] Implement ->page_mkwrite in XFS.
[FS] Implement block_page_mkwrite.
Manually fix up conflict with Nick's VM fault handling patches in
fs/xfs/linux-2.6/xfs_file.c
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_file.c | 16 | ||||
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 30 |
2 files changed, 44 insertions, 2 deletions
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 2d4be2f247b2..0d4001eafd16 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
@@ -413,6 +413,20 @@ xfs_file_open_exec( | |||
413 | } | 413 | } |
414 | #endif /* HAVE_FOP_OPEN_EXEC */ | 414 | #endif /* HAVE_FOP_OPEN_EXEC */ |
415 | 415 | ||
416 | /* | ||
417 | * mmap()d file has taken write protection fault and is being made | ||
418 | * writable. We can set the page state up correctly for a writable | ||
419 | * page, which means we can do correct delalloc accounting (ENOSPC | ||
420 | * checking!) and unwritten extent mapping. | ||
421 | */ | ||
422 | STATIC int | ||
423 | xfs_vm_page_mkwrite( | ||
424 | struct vm_area_struct *vma, | ||
425 | struct page *page) | ||
426 | { | ||
427 | return block_page_mkwrite(vma, page, xfs_get_blocks); | ||
428 | } | ||
429 | |||
416 | const struct file_operations xfs_file_operations = { | 430 | const struct file_operations xfs_file_operations = { |
417 | .llseek = generic_file_llseek, | 431 | .llseek = generic_file_llseek, |
418 | .read = do_sync_read, | 432 | .read = do_sync_read, |
@@ -465,11 +479,13 @@ const struct file_operations xfs_dir_file_operations = { | |||
465 | 479 | ||
466 | static struct vm_operations_struct xfs_file_vm_ops = { | 480 | static struct vm_operations_struct xfs_file_vm_ops = { |
467 | .fault = filemap_fault, | 481 | .fault = filemap_fault, |
482 | .page_mkwrite = xfs_vm_page_mkwrite, | ||
468 | }; | 483 | }; |
469 | 484 | ||
470 | #ifdef CONFIG_XFS_DMAPI | 485 | #ifdef CONFIG_XFS_DMAPI |
471 | static struct vm_operations_struct xfs_dmapi_file_vm_ops = { | 486 | static struct vm_operations_struct xfs_dmapi_file_vm_ops = { |
472 | .fault = xfs_vm_fault, | 487 | .fault = xfs_vm_fault, |
488 | .page_mkwrite = xfs_vm_page_mkwrite, | ||
473 | #ifdef HAVE_VMOP_MPROTECT | 489 | #ifdef HAVE_VMOP_MPROTECT |
474 | .mprotect = xfs_vm_mprotect, | 490 | .mprotect = xfs_vm_mprotect, |
475 | #endif | 491 | #endif |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 79b522779aa4..1a5ad8cd97b0 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -589,7 +589,30 @@ xfs_setattr( | |||
589 | code = xfs_igrow_start(ip, vap->va_size, credp); | 589 | code = xfs_igrow_start(ip, vap->va_size, credp); |
590 | } | 590 | } |
591 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 591 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
592 | vn_iowait(vp); /* wait for the completion of any pending DIOs */ | 592 | |
593 | /* | ||
594 | * We are going to log the inode size change in this | ||
595 | * transaction so any previous writes that are beyond the on | ||
596 | * disk EOF and the new EOF that have not been written out need | ||
597 | * to be written here. If we do not write the data out, we | ||
598 | * expose ourselves to the null files problem. | ||
599 | * | ||
600 | * Only flush from the on disk size to the smaller of the in | ||
601 | * memory file size or the new size as that's the range we | ||
602 | * really care about here and prevents waiting for other data | ||
603 | * not within the range we care about here. | ||
604 | */ | ||
605 | if (!code && | ||
606 | (ip->i_size != ip->i_d.di_size) && | ||
607 | (vap->va_size > ip->i_d.di_size)) { | ||
608 | code = bhv_vop_flush_pages(XFS_ITOV(ip), | ||
609 | ip->i_d.di_size, vap->va_size, | ||
610 | XFS_B_ASYNC, FI_NONE); | ||
611 | } | ||
612 | |||
613 | /* wait for all I/O to complete */ | ||
614 | vn_iowait(vp); | ||
615 | |||
593 | if (!code) | 616 | if (!code) |
594 | code = xfs_itruncate_data(ip, vap->va_size); | 617 | code = xfs_itruncate_data(ip, vap->va_size); |
595 | if (code) { | 618 | if (code) { |
@@ -4434,9 +4457,12 @@ xfs_free_file_space( | |||
4434 | while (!error && !done) { | 4457 | while (!error && !done) { |
4435 | 4458 | ||
4436 | /* | 4459 | /* |
4437 | * allocate and setup the transaction | 4460 | * allocate and setup the transaction. Allow this |
4461 | * transaction to dip into the reserve blocks to ensure | ||
4462 | * the freeing of the space succeeds at ENOSPC. | ||
4438 | */ | 4463 | */ |
4439 | tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); | 4464 | tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); |
4465 | tp->t_flags |= XFS_TRANS_RESERVE; | ||
4440 | error = xfs_trans_reserve(tp, | 4466 | error = xfs_trans_reserve(tp, |
4441 | resblks, | 4467 | resblks, |
4442 | XFS_WRITE_LOG_RES(mp), | 4468 | XFS_WRITE_LOG_RES(mp), |