aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_vnodeops.c
diff options
context:
space:
mode:
authorNathan Scott <nathans@sgi.com>2006-06-09 01:27:16 -0400
committerNathan Scott <nathans@sgi.com>2006-06-09 01:27:16 -0400
commit7d4fb40ad7efe4586d1341d4731377fb4530836f (patch)
treebf802cce6bc60627186b02b71014a683f6cb4a05 /fs/xfs/xfs_vnodeops.c
parent59c1b082f5fff8269565039600a2ef18d48649b5 (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.c88
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 */
76STATIC int 59STATIC int
77xfs_open( 60xfs_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
84STATIC int
85xfs_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 */
1476STATIC int 1498STATIC int
1477xfs_inactive_attrs( 1499xfs_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
3749int 3768int
3750xfs_set_dmattrs ( 3769xfs_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 */
3793STATIC int 3808STATIC int
3794xfs_reclaim( 3809xfs_reclaim(
3795 bhv_desc_t *bdp) 3810 bhv_desc_t *bdp)
@@ -4645,6 +4660,7 @@ xfs_change_file_space(
4645vnodeops_t xfs_vnodeops = { 4660vnodeops_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,