diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-06-24 08:41:41 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-06-24 13:07:53 -0400 |
| commit | 816724e65c72a90a44fbad0ef0b59b186c85fa90 (patch) | |
| tree | 421fa29aedff988e392f92780637553e275d37a0 /fs/xfs/xfs_rw.c | |
| parent | 70ac4385a13f78bc478f26d317511893741b05bd (diff) | |
| parent | d384ea691fe4ea8c2dd5b9b8d9042eb181776f18 (diff) | |
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Conflicts:
fs/nfs/inode.c
fs/super.c
Fix conflicts between patch 'NFS: Split fs/nfs/inode.c' and patch
'VFS: Permit filesystem to override root dentry on mount'
Diffstat (limited to 'fs/xfs/xfs_rw.c')
| -rw-r--r-- | fs/xfs/xfs_rw.c | 124 |
1 files changed, 105 insertions, 19 deletions
diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index a59c102cf214..defb2febaaf5 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 |
| @@ -24,14 +24,12 @@ | |||
| 24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
| 25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
| 26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
| 27 | #include "xfs_dir.h" | ||
| 28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
| 29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
| 30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
| 31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
| 32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
| 33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
| 34 | #include "xfs_dir_sf.h" | ||
| 35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
| 36 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
| 37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
| @@ -92,6 +90,90 @@ xfs_write_clear_setuid( | |||
| 92 | } | 90 | } |
| 93 | 91 | ||
| 94 | /* | 92 | /* |
| 93 | * Handle logging requirements of various synchronous types of write. | ||
| 94 | */ | ||
| 95 | int | ||
| 96 | xfs_write_sync_logforce( | ||
| 97 | xfs_mount_t *mp, | ||
| 98 | xfs_inode_t *ip) | ||
| 99 | { | ||
| 100 | int error = 0; | ||
| 101 | |||
| 102 | /* | ||
| 103 | * If we're treating this as O_DSYNC and we have not updated the | ||
| 104 | * size, force the log. | ||
| 105 | */ | ||
| 106 | if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) && | ||
| 107 | !(ip->i_update_size)) { | ||
| 108 | xfs_inode_log_item_t *iip = ip->i_itemp; | ||
| 109 | |||
| 110 | /* | ||
| 111 | * If an allocation transaction occurred | ||
| 112 | * without extending the size, then we have to force | ||
| 113 | * the log up the proper point to ensure that the | ||
| 114 | * allocation is permanent. We can't count on | ||
| 115 | * the fact that buffered writes lock out direct I/O | ||
| 116 | * writes - the direct I/O write could have extended | ||
| 117 | * the size nontransactionally, then finished before | ||
| 118 | * we started. xfs_write_file will think that the file | ||
| 119 | * didn't grow but the update isn't safe unless the | ||
| 120 | * size change is logged. | ||
| 121 | * | ||
| 122 | * Force the log if we've committed a transaction | ||
| 123 | * against the inode or if someone else has and | ||
| 124 | * the commit record hasn't gone to disk (e.g. | ||
| 125 | * the inode is pinned). This guarantees that | ||
| 126 | * all changes affecting the inode are permanent | ||
| 127 | * when we return. | ||
| 128 | */ | ||
| 129 | if (iip && iip->ili_last_lsn) { | ||
| 130 | xfs_log_force(mp, iip->ili_last_lsn, | ||
| 131 | XFS_LOG_FORCE | XFS_LOG_SYNC); | ||
| 132 | } else if (xfs_ipincount(ip) > 0) { | ||
| 133 | xfs_log_force(mp, (xfs_lsn_t)0, | ||
| 134 | XFS_LOG_FORCE | XFS_LOG_SYNC); | ||
| 135 | } | ||
| 136 | |||
| 137 | } else { | ||
| 138 | xfs_trans_t *tp; | ||
| 139 | |||
| 140 | /* | ||
| 141 | * O_SYNC or O_DSYNC _with_ a size update are handled | ||
| 142 | * the same way. | ||
| 143 | * | ||
| 144 | * If the write was synchronous then we need to make | ||
| 145 | * sure that the inode modification time is permanent. | ||
| 146 | * We'll have updated the timestamp above, so here | ||
| 147 | * we use a synchronous transaction to log the inode. | ||
| 148 | * It's not fast, but it's necessary. | ||
| 149 | * | ||
| 150 | * If this a dsync write and the size got changed | ||
| 151 | * non-transactionally, then we need to ensure that | ||
| 152 | * the size change gets logged in a synchronous | ||
| 153 | * transaction. | ||
| 154 | */ | ||
| 155 | tp = xfs_trans_alloc(mp, XFS_TRANS_WRITE_SYNC); | ||
| 156 | if ((error = xfs_trans_reserve(tp, 0, | ||
| 157 | XFS_SWRITE_LOG_RES(mp), | ||
| 158 | 0, 0, 0))) { | ||
| 159 | /* Transaction reserve failed */ | ||
| 160 | xfs_trans_cancel(tp, 0); | ||
| 161 | } else { | ||
| 162 | /* Transaction reserve successful */ | ||
| 163 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
| 164 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
| 165 | xfs_trans_ihold(tp, ip); | ||
| 166 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
| 167 | xfs_trans_set_sync(tp); | ||
| 168 | error = xfs_trans_commit(tp, 0, NULL); | ||
| 169 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
| 170 | } | ||
| 171 | } | ||
| 172 | |||
| 173 | return error; | ||
| 174 | } | ||
| 175 | |||
| 176 | /* | ||
| 95 | * Force a shutdown of the filesystem instantly while keeping | 177 | * Force a shutdown of the filesystem instantly while keeping |
| 96 | * the filesystem consistent. We don't do an unmount here; just shutdown | 178 | * the filesystem consistent. We don't do an unmount here; just shutdown |
| 97 | * the shop, make sure that absolutely nothing persistent happens to | 179 | * the shop, make sure that absolutely nothing persistent happens to |
| @@ -109,12 +191,12 @@ xfs_do_force_shutdown( | |||
| 109 | xfs_mount_t *mp; | 191 | xfs_mount_t *mp; |
| 110 | 192 | ||
| 111 | mp = XFS_BHVTOM(bdp); | 193 | mp = XFS_BHVTOM(bdp); |
| 112 | logerror = flags & XFS_LOG_IO_ERROR; | 194 | logerror = flags & SHUTDOWN_LOG_IO_ERROR; |
| 113 | 195 | ||
| 114 | if (!(flags & XFS_FORCE_UMOUNT)) { | 196 | if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { |
| 115 | cmn_err(CE_NOTE, | 197 | cmn_err(CE_NOTE, "xfs_force_shutdown(%s,0x%x) called from " |
| 116 | "xfs_force_shutdown(%s,0x%x) called from line %d of file %s. Return address = 0x%p", | 198 | "line %d of file %s. Return address = 0x%p", |
| 117 | mp->m_fsname,flags,lnnum,fname,__return_address); | 199 | mp->m_fsname, flags, lnnum, fname, __return_address); |
| 118 | } | 200 | } |
| 119 | /* | 201 | /* |
| 120 | * No need to duplicate efforts. | 202 | * No need to duplicate efforts. |
| @@ -125,33 +207,37 @@ xfs_do_force_shutdown( | |||
| 125 | /* | 207 | /* |
| 126 | * This flags XFS_MOUNT_FS_SHUTDOWN, makes sure that we don't | 208 | * This flags XFS_MOUNT_FS_SHUTDOWN, makes sure that we don't |
| 127 | * queue up anybody new on the log reservations, and wakes up | 209 | * queue up anybody new on the log reservations, and wakes up |
| 128 | * everybody who's sleeping on log reservations and tells | 210 | * everybody who's sleeping on log reservations to tell them |
| 129 | * them the bad news. | 211 | * the bad news. |
| 130 | */ | 212 | */ |
| 131 | if (xfs_log_force_umount(mp, logerror)) | 213 | if (xfs_log_force_umount(mp, logerror)) |
| 132 | return; | 214 | return; |
| 133 | 215 | ||
| 134 | if (flags & XFS_CORRUPT_INCORE) { | 216 | if (flags & SHUTDOWN_CORRUPT_INCORE) { |
| 135 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp, | 217 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp, |
| 136 | "Corruption of in-memory data detected. Shutting down filesystem: %s", | 218 | "Corruption of in-memory data detected. Shutting down filesystem: %s", |
| 137 | mp->m_fsname); | 219 | mp->m_fsname); |
| 138 | if (XFS_ERRLEVEL_HIGH <= xfs_error_level) { | 220 | if (XFS_ERRLEVEL_HIGH <= xfs_error_level) { |
| 139 | xfs_stack_trace(); | 221 | xfs_stack_trace(); |
| 140 | } | 222 | } |
| 141 | } else if (!(flags & XFS_FORCE_UMOUNT)) { | 223 | } else if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { |
| 142 | if (logerror) { | 224 | if (logerror) { |
| 143 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp, | 225 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp, |
| 144 | "Log I/O Error Detected. Shutting down filesystem: %s", | 226 | "Log I/O Error Detected. Shutting down filesystem: %s", |
| 227 | mp->m_fsname); | ||
| 228 | } else if (flags & SHUTDOWN_DEVICE_REQ) { | ||
| 229 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, | ||
| 230 | "All device paths lost. Shutting down filesystem: %s", | ||
| 145 | mp->m_fsname); | 231 | mp->m_fsname); |
| 146 | } else if (!(flags & XFS_SHUTDOWN_REMOTE_REQ)) { | 232 | } else if (!(flags & SHUTDOWN_REMOTE_REQ)) { |
| 147 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, | 233 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, |
| 148 | "I/O Error Detected. Shutting down filesystem: %s", | 234 | "I/O Error Detected. Shutting down filesystem: %s", |
| 149 | mp->m_fsname); | 235 | mp->m_fsname); |
| 150 | } | 236 | } |
| 151 | } | 237 | } |
| 152 | if (!(flags & XFS_FORCE_UMOUNT)) { | 238 | if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { |
| 153 | cmn_err(CE_ALERT, | 239 | cmn_err(CE_ALERT, "Please umount the filesystem, " |
| 154 | "Please umount the filesystem, and rectify the problem(s)"); | 240 | "and rectify the problem(s)"); |
| 155 | } | 241 | } |
| 156 | } | 242 | } |
| 157 | 243 | ||
| @@ -335,7 +421,7 @@ xfs_bwrite( | |||
| 335 | * from bwrite and we could be tracing a buffer that has | 421 | * from bwrite and we could be tracing a buffer that has |
| 336 | * been reused. | 422 | * been reused. |
| 337 | */ | 423 | */ |
| 338 | xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR); | 424 | xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); |
| 339 | } | 425 | } |
| 340 | return (error); | 426 | return (error); |
| 341 | } | 427 | } |
