diff options
author | Nathan Scott <nathans@sgi.com> | 2006-06-09 01:27:16 -0400 |
---|---|---|
committer | Nathan Scott <nathans@sgi.com> | 2006-06-09 01:27:16 -0400 |
commit | 7d4fb40ad7efe4586d1341d4731377fb4530836f (patch) | |
tree | bf802cce6bc60627186b02b71014a683f6cb4a05 /fs/xfs/xfs_vnodeops.c | |
parent | 59c1b082f5fff8269565039600a2ef18d48649b5 (diff) |
[XFS] Start writeout earlier (on last close) in the case where we have a
truncate down followed by delayed allocation (buffered writes) - worst
case scenario for the notorious NULL files problem. This reduces the
window where we are exposed to that problem significantly.
SGI-PV: 917976
SGI-Modid: xfs-linux-melb:xfs-kern:26100a
Signed-off-by: Nathan Scott <nathans@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r-- | fs/xfs/xfs_vnodeops.c | 88 |
1 files changed, 52 insertions, 36 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index cb36a56392e7..35906bae92e1 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -16,8 +16,6 @@ | |||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/capability.h> | ||
20 | |||
21 | #include "xfs.h" | 19 | #include "xfs.h" |
22 | #include "xfs_fs.h" | 20 | #include "xfs_fs.h" |
23 | #include "xfs_types.h" | 21 | #include "xfs_types.h" |
@@ -58,32 +56,14 @@ | |||
58 | #include "xfs_log_priv.h" | 56 | #include "xfs_log_priv.h" |
59 | #include "xfs_mac.h" | 57 | #include "xfs_mac.h" |
60 | 58 | ||
61 | |||
62 | /* | ||
63 | * The maximum pathlen is 1024 bytes. Since the minimum file system | ||
64 | * blocksize is 512 bytes, we can get a max of 2 extents back from | ||
65 | * bmapi. | ||
66 | */ | ||
67 | #define SYMLINK_MAPS 2 | ||
68 | |||
69 | /* | ||
70 | * For xfs, we check that the file isn't too big to be opened by this kernel. | ||
71 | * No other open action is required for regular files. Devices are handled | ||
72 | * through the specfs file system, pipes through fifofs. Device and | ||
73 | * fifo vnodes are "wrapped" by specfs and fifofs vnodes, respectively, | ||
74 | * when a new vnode is first looked up or created. | ||
75 | */ | ||
76 | STATIC int | 59 | STATIC int |
77 | xfs_open( | 60 | xfs_open( |
78 | bhv_desc_t *bdp, | 61 | bhv_desc_t *bdp, |
79 | cred_t *credp) | 62 | cred_t *credp) |
80 | { | 63 | { |
81 | int mode; | 64 | int mode; |
82 | vnode_t *vp; | 65 | vnode_t *vp = BHV_TO_VNODE(bdp); |
83 | xfs_inode_t *ip; | 66 | xfs_inode_t *ip = XFS_BHVTOI(bdp); |
84 | |||
85 | vp = BHV_TO_VNODE(bdp); | ||
86 | ip = XFS_BHVTOI(bdp); | ||
87 | 67 | ||
88 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | 68 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) |
89 | return XFS_ERROR(EIO); | 69 | return XFS_ERROR(EIO); |
@@ -101,6 +81,36 @@ xfs_open( | |||
101 | return 0; | 81 | return 0; |
102 | } | 82 | } |
103 | 83 | ||
84 | STATIC int | ||
85 | xfs_close( | ||
86 | bhv_desc_t *bdp, | ||
87 | int flags, | ||
88 | lastclose_t lastclose, | ||
89 | cred_t *credp) | ||
90 | { | ||
91 | vnode_t *vp = BHV_TO_VNODE(bdp); | ||
92 | xfs_inode_t *ip = XFS_BHVTOI(bdp); | ||
93 | int error = 0; | ||
94 | |||
95 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | ||
96 | return XFS_ERROR(EIO); | ||
97 | |||
98 | if (lastclose != L_TRUE || !VN_ISREG(vp)) | ||
99 | return 0; | ||
100 | |||
101 | /* | ||
102 | * If we previously truncated this file and removed old data in | ||
103 | * the process, we want to initiate "early" writeout on the last | ||
104 | * close. This is an attempt to combat the notorious NULL files | ||
105 | * problem which is particularly noticable from a truncate down, | ||
106 | * buffered (re-)write (delalloc), followed by a crash. What we | ||
107 | * are effectively doing here is significantly reducing the time | ||
108 | * window where we'd otherwise be exposed to that problem. | ||
109 | */ | ||
110 | if (VUNTRUNCATE(vp) && VN_DIRTY(vp) && ip->i_delayed_blks > 0) | ||
111 | VOP_FLUSH_PAGES(vp, 0, -1, XFS_B_ASYNC, FI_NONE, error); | ||
112 | return error; | ||
113 | } | ||
104 | 114 | ||
105 | /* | 115 | /* |
106 | * xfs_getattr | 116 | * xfs_getattr |
@@ -665,9 +675,17 @@ xfs_setattr( | |||
665 | ((ip->i_d.di_nlink != 0 || | 675 | ((ip->i_d.di_nlink != 0 || |
666 | !(mp->m_flags & XFS_MOUNT_WSYNC)) | 676 | !(mp->m_flags & XFS_MOUNT_WSYNC)) |
667 | ? 1 : 0)); | 677 | ? 1 : 0)); |
668 | if (code) { | 678 | if (code) |
669 | goto abort_return; | 679 | goto abort_return; |
670 | } | 680 | /* |
681 | * Truncated "down", so we're removing references | ||
682 | * to old data here - if we now delay flushing for | ||
683 | * a long time, we expose ourselves unduly to the | ||
684 | * notorious NULL files problem. So, we mark this | ||
685 | * vnode and flush it when the file is closed, and | ||
686 | * do not wait the usual (long) time for writeout. | ||
687 | */ | ||
688 | VTRUNCATE(vp); | ||
671 | } | 689 | } |
672 | /* | 690 | /* |
673 | * Have to do this even if the file's size doesn't change. | 691 | * Have to do this even if the file's size doesn't change. |
@@ -937,6 +955,13 @@ xfs_access( | |||
937 | 955 | ||
938 | 956 | ||
939 | /* | 957 | /* |
958 | * The maximum pathlen is 1024 bytes. Since the minimum file system | ||
959 | * blocksize is 512 bytes, we can get a max of 2 extents back from | ||
960 | * bmapi. | ||
961 | */ | ||
962 | #define SYMLINK_MAPS 2 | ||
963 | |||
964 | /* | ||
940 | * xfs_readlink | 965 | * xfs_readlink |
941 | * | 966 | * |
942 | */ | 967 | */ |
@@ -1470,9 +1495,6 @@ xfs_inactive_symlink_local( | |||
1470 | return 0; | 1495 | return 0; |
1471 | } | 1496 | } |
1472 | 1497 | ||
1473 | /* | ||
1474 | * | ||
1475 | */ | ||
1476 | STATIC int | 1498 | STATIC int |
1477 | xfs_inactive_attrs( | 1499 | xfs_inactive_attrs( |
1478 | xfs_inode_t *ip, | 1500 | xfs_inode_t *ip, |
@@ -1531,10 +1553,10 @@ xfs_release( | |||
1531 | 1553 | ||
1532 | vp = BHV_TO_VNODE(bdp); | 1554 | vp = BHV_TO_VNODE(bdp); |
1533 | ip = XFS_BHVTOI(bdp); | 1555 | ip = XFS_BHVTOI(bdp); |
1556 | mp = ip->i_mount; | ||
1534 | 1557 | ||
1535 | if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0)) { | 1558 | if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0)) |
1536 | return 0; | 1559 | return 0; |
1537 | } | ||
1538 | 1560 | ||
1539 | /* If this is a read-only mount, don't do this (would generate I/O) */ | 1561 | /* If this is a read-only mount, don't do this (would generate I/O) */ |
1540 | if (vp->v_vfsp->vfs_flag & VFS_RDONLY) | 1562 | if (vp->v_vfsp->vfs_flag & VFS_RDONLY) |
@@ -1546,8 +1568,6 @@ xfs_release( | |||
1546 | return 0; | 1568 | return 0; |
1547 | #endif | 1569 | #endif |
1548 | 1570 | ||
1549 | mp = ip->i_mount; | ||
1550 | |||
1551 | if (ip->i_d.di_nlink != 0) { | 1571 | if (ip->i_d.di_nlink != 0) { |
1552 | if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && | 1572 | if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && |
1553 | ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 || | 1573 | ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 || |
@@ -3745,7 +3765,6 @@ xfs_inode_flush( | |||
3745 | return error; | 3765 | return error; |
3746 | } | 3766 | } |
3747 | 3767 | ||
3748 | |||
3749 | int | 3768 | int |
3750 | xfs_set_dmattrs ( | 3769 | xfs_set_dmattrs ( |
3751 | bhv_desc_t *bdp, | 3770 | bhv_desc_t *bdp, |
@@ -3786,10 +3805,6 @@ xfs_set_dmattrs ( | |||
3786 | return error; | 3805 | return error; |
3787 | } | 3806 | } |
3788 | 3807 | ||
3789 | |||
3790 | /* | ||
3791 | * xfs_reclaim | ||
3792 | */ | ||
3793 | STATIC int | 3808 | STATIC int |
3794 | xfs_reclaim( | 3809 | xfs_reclaim( |
3795 | bhv_desc_t *bdp) | 3810 | bhv_desc_t *bdp) |
@@ -4645,6 +4660,7 @@ xfs_change_file_space( | |||
4645 | vnodeops_t xfs_vnodeops = { | 4660 | vnodeops_t xfs_vnodeops = { |
4646 | BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS), | 4661 | BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS), |
4647 | .vop_open = xfs_open, | 4662 | .vop_open = xfs_open, |
4663 | .vop_close = xfs_close, | ||
4648 | .vop_read = xfs_read, | 4664 | .vop_read = xfs_read, |
4649 | #ifdef HAVE_SENDFILE | 4665 | #ifdef HAVE_SENDFILE |
4650 | .vop_sendfile = xfs_sendfile, | 4666 | .vop_sendfile = xfs_sendfile, |