diff options
author | Nathan Scott <nathans@sgi.com> | 2006-06-18 18:39:53 -0400 |
---|---|---|
committer | Nathan Scott <nathans@sgi.com> | 2006-06-18 18:39:53 -0400 |
commit | 1e69dd0eb354d6f1a77098a3946b5ba57d4e3109 (patch) | |
tree | f97ce9c94f72cf142831ad12a701fc6378dc279f /fs/xfs | |
parent | 1d47bec290a6f1f366192946840efef5076d9fc7 (diff) |
[XFS] Push some common code out of write path into core XFS code for
sharing.
SGI-PV: 904196
SGI-Modid: xfs-linux-melb:xfs-kern:26248a
Signed-off-by: Nathan Scott <nathans@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_lrw.c | 76 | ||||
-rw-r--r-- | fs/xfs/xfs_rw.c | 86 | ||||
-rw-r--r-- | fs/xfs/xfs_rw.h | 3 |
3 files changed, 90 insertions, 75 deletions
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 3e76c5c9dda1..8e5468704816 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c | |||
@@ -892,79 +892,9 @@ retry: | |||
892 | 892 | ||
893 | /* Handle various SYNC-type writes */ | 893 | /* Handle various SYNC-type writes */ |
894 | if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) { | 894 | if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) { |
895 | /* | 895 | error = xfs_write_sync_logforce(mp, xip); |
896 | * If we're treating this as O_DSYNC and we have not updated the | 896 | if (error) |
897 | * size, force the log. | 897 | goto out_unlock_internal; |
898 | */ | ||
899 | if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) && | ||
900 | !(xip->i_update_size)) { | ||
901 | xfs_inode_log_item_t *iip = xip->i_itemp; | ||
902 | |||
903 | /* | ||
904 | * If an allocation transaction occurred | ||
905 | * without extending the size, then we have to force | ||
906 | * the log up the proper point to ensure that the | ||
907 | * allocation is permanent. We can't count on | ||
908 | * the fact that buffered writes lock out direct I/O | ||
909 | * writes - the direct I/O write could have extended | ||
910 | * the size nontransactionally, then finished before | ||
911 | * we started. xfs_write_file will think that the file | ||
912 | * didn't grow but the update isn't safe unless the | ||
913 | * size change is logged. | ||
914 | * | ||
915 | * Force the log if we've committed a transaction | ||
916 | * against the inode or if someone else has and | ||
917 | * the commit record hasn't gone to disk (e.g. | ||
918 | * the inode is pinned). This guarantees that | ||
919 | * all changes affecting the inode are permanent | ||
920 | * when we return. | ||
921 | */ | ||
922 | if (iip && iip->ili_last_lsn) { | ||
923 | xfs_log_force(mp, iip->ili_last_lsn, | ||
924 | XFS_LOG_FORCE | XFS_LOG_SYNC); | ||
925 | } else if (xfs_ipincount(xip) > 0) { | ||
926 | xfs_log_force(mp, (xfs_lsn_t)0, | ||
927 | XFS_LOG_FORCE | XFS_LOG_SYNC); | ||
928 | } | ||
929 | |||
930 | } else { | ||
931 | xfs_trans_t *tp; | ||
932 | |||
933 | /* | ||
934 | * O_SYNC or O_DSYNC _with_ a size update are handled | ||
935 | * the same way. | ||
936 | * | ||
937 | * If the write was synchronous then we need to make | ||
938 | * sure that the inode modification time is permanent. | ||
939 | * We'll have updated the timestamp above, so here | ||
940 | * we use a synchronous transaction to log the inode. | ||
941 | * It's not fast, but it's necessary. | ||
942 | * | ||
943 | * If this a dsync write and the size got changed | ||
944 | * non-transactionally, then we need to ensure that | ||
945 | * the size change gets logged in a synchronous | ||
946 | * transaction. | ||
947 | */ | ||
948 | |||
949 | tp = xfs_trans_alloc(mp, XFS_TRANS_WRITE_SYNC); | ||
950 | if ((error = xfs_trans_reserve(tp, 0, | ||
951 | XFS_SWRITE_LOG_RES(mp), | ||
952 | 0, 0, 0))) { | ||
953 | /* Transaction reserve failed */ | ||
954 | xfs_trans_cancel(tp, 0); | ||
955 | } else { | ||
956 | /* Transaction reserve successful */ | ||
957 | xfs_ilock(xip, XFS_ILOCK_EXCL); | ||
958 | xfs_trans_ijoin(tp, xip, XFS_ILOCK_EXCL); | ||
959 | xfs_trans_ihold(tp, xip); | ||
960 | xfs_trans_log_inode(tp, xip, XFS_ILOG_CORE); | ||
961 | xfs_trans_set_sync(tp); | ||
962 | error = xfs_trans_commit(tp, 0, NULL); | ||
963 | xfs_iunlock(xip, XFS_ILOCK_EXCL); | ||
964 | } | ||
965 | if (error) | ||
966 | goto out_unlock_internal; | ||
967 | } | ||
968 | 898 | ||
969 | xfs_rwunlock(bdp, locktype); | 899 | xfs_rwunlock(bdp, locktype); |
970 | if (need_i_mutex) | 900 | if (need_i_mutex) |
diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index d33e4f5808e5..c55e28189aba 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -92,6 +92,90 @@ xfs_write_clear_setuid( | |||
92 | } | 92 | } |
93 | 93 | ||
94 | /* | 94 | /* |
95 | * Handle logging requirements of various synchronous types of write. | ||
96 | */ | ||
97 | int | ||
98 | xfs_write_sync_logforce( | ||
99 | xfs_mount_t *mp, | ||
100 | xfs_inode_t *ip) | ||
101 | { | ||
102 | int error = 0; | ||
103 | |||
104 | /* | ||
105 | * If we're treating this as O_DSYNC and we have not updated the | ||
106 | * size, force the log. | ||
107 | */ | ||
108 | if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) && | ||
109 | !(ip->i_update_size)) { | ||
110 | xfs_inode_log_item_t *iip = ip->i_itemp; | ||
111 | |||
112 | /* | ||
113 | * If an allocation transaction occurred | ||
114 | * without extending the size, then we have to force | ||
115 | * the log up the proper point to ensure that the | ||
116 | * allocation is permanent. We can't count on | ||
117 | * the fact that buffered writes lock out direct I/O | ||
118 | * writes - the direct I/O write could have extended | ||
119 | * the size nontransactionally, then finished before | ||
120 | * we started. xfs_write_file will think that the file | ||
121 | * didn't grow but the update isn't safe unless the | ||
122 | * size change is logged. | ||
123 | * | ||
124 | * Force the log if we've committed a transaction | ||
125 | * against the inode or if someone else has and | ||
126 | * the commit record hasn't gone to disk (e.g. | ||
127 | * the inode is pinned). This guarantees that | ||
128 | * all changes affecting the inode are permanent | ||
129 | * when we return. | ||
130 | */ | ||
131 | if (iip && iip->ili_last_lsn) { | ||
132 | xfs_log_force(mp, iip->ili_last_lsn, | ||
133 | XFS_LOG_FORCE | XFS_LOG_SYNC); | ||
134 | } else if (xfs_ipincount(ip) > 0) { | ||
135 | xfs_log_force(mp, (xfs_lsn_t)0, | ||
136 | XFS_LOG_FORCE | XFS_LOG_SYNC); | ||
137 | } | ||
138 | |||
139 | } else { | ||
140 | xfs_trans_t *tp; | ||
141 | |||
142 | /* | ||
143 | * O_SYNC or O_DSYNC _with_ a size update are handled | ||
144 | * the same way. | ||
145 | * | ||
146 | * If the write was synchronous then we need to make | ||
147 | * sure that the inode modification time is permanent. | ||
148 | * We'll have updated the timestamp above, so here | ||
149 | * we use a synchronous transaction to log the inode. | ||
150 | * It's not fast, but it's necessary. | ||
151 | * | ||
152 | * If this a dsync write and the size got changed | ||
153 | * non-transactionally, then we need to ensure that | ||
154 | * the size change gets logged in a synchronous | ||
155 | * transaction. | ||
156 | */ | ||
157 | tp = xfs_trans_alloc(mp, XFS_TRANS_WRITE_SYNC); | ||
158 | if ((error = xfs_trans_reserve(tp, 0, | ||
159 | XFS_SWRITE_LOG_RES(mp), | ||
160 | 0, 0, 0))) { | ||
161 | /* Transaction reserve failed */ | ||
162 | xfs_trans_cancel(tp, 0); | ||
163 | } else { | ||
164 | /* Transaction reserve successful */ | ||
165 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
166 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
167 | xfs_trans_ihold(tp, ip); | ||
168 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
169 | xfs_trans_set_sync(tp); | ||
170 | error = xfs_trans_commit(tp, 0, NULL); | ||
171 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | return error; | ||
176 | } | ||
177 | |||
178 | /* | ||
95 | * Force a shutdown of the filesystem instantly while keeping | 179 | * Force a shutdown of the filesystem instantly while keeping |
96 | * the filesystem consistent. We don't do an unmount here; just shutdown | 180 | * the filesystem consistent. We don't do an unmount here; just shutdown |
97 | * the shop, make sure that absolutely nothing persistent happens to | 181 | * the shop, make sure that absolutely nothing persistent happens to |
diff --git a/fs/xfs/xfs_rw.h b/fs/xfs/xfs_rw.h index a572b175dc8b..188b296ff50c 100644 --- a/fs/xfs/xfs_rw.h +++ b/fs/xfs/xfs_rw.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -75,6 +75,7 @@ xfs_fsb_to_db_io(struct xfs_iocore *io, xfs_fsblock_t fsb) | |||
75 | * Prototypes for functions in xfs_rw.c. | 75 | * Prototypes for functions in xfs_rw.c. |
76 | */ | 76 | */ |
77 | extern int xfs_write_clear_setuid(struct xfs_inode *ip); | 77 | extern int xfs_write_clear_setuid(struct xfs_inode *ip); |
78 | extern int xfs_write_sync_logforce(struct xfs_mount *mp, struct xfs_inode *ip); | ||
78 | extern int xfs_bwrite(struct xfs_mount *mp, struct xfs_buf *bp); | 79 | extern int xfs_bwrite(struct xfs_mount *mp, struct xfs_buf *bp); |
79 | extern int xfs_bioerror(struct xfs_buf *bp); | 80 | extern int xfs_bioerror(struct xfs_buf *bp); |
80 | extern int xfs_bioerror_relse(struct xfs_buf *bp); | 81 | extern int xfs_bioerror_relse(struct xfs_buf *bp); |