Merge git://git.kernel.org/pub/scm/linux/kernel/git/steve/gfs2-2.6-fixes
[pandora-kernel.git] / fs / xfs / xfs_rw.c
1 /*
2  * Copyright (c) 2000-2006 Silicon Graphics, Inc.
3  * All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it would be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write the Free Software Foundation,
16  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 #include "xfs.h"
19 #include "xfs_fs.h"
20 #include "xfs_types.h"
21 #include "xfs_bit.h"
22 #include "xfs_log.h"
23 #include "xfs_inum.h"
24 #include "xfs_trans.h"
25 #include "xfs_sb.h"
26 #include "xfs_ag.h"
27 #include "xfs_dir2.h"
28 #include "xfs_dmapi.h"
29 #include "xfs_mount.h"
30 #include "xfs_bmap_btree.h"
31 #include "xfs_alloc_btree.h"
32 #include "xfs_ialloc_btree.h"
33 #include "xfs_dir2_sf.h"
34 #include "xfs_attr_sf.h"
35 #include "xfs_dinode.h"
36 #include "xfs_inode.h"
37 #include "xfs_inode_item.h"
38 #include "xfs_itable.h"
39 #include "xfs_btree.h"
40 #include "xfs_alloc.h"
41 #include "xfs_ialloc.h"
42 #include "xfs_attr.h"
43 #include "xfs_bmap.h"
44 #include "xfs_error.h"
45 #include "xfs_buf_item.h"
46 #include "xfs_rw.h"
47 #include "xfs_trace.h"
48
49 /*
50  * Force a shutdown of the filesystem instantly while keeping
51  * the filesystem consistent. We don't do an unmount here; just shutdown
52  * the shop, make sure that absolutely nothing persistent happens to
53  * this filesystem after this point.
54  */
55 void
56 xfs_do_force_shutdown(
57         xfs_mount_t     *mp,
58         int             flags,
59         char            *fname,
60         int             lnnum)
61 {
62         int             logerror;
63
64         logerror = flags & SHUTDOWN_LOG_IO_ERROR;
65
66         if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
67                 cmn_err(CE_NOTE, "xfs_force_shutdown(%s,0x%x) called from "
68                                  "line %d of file %s.  Return address = 0x%p",
69                         mp->m_fsname, flags, lnnum, fname, __return_address);
70         }
71         /*
72          * No need to duplicate efforts.
73          */
74         if (XFS_FORCED_SHUTDOWN(mp) && !logerror)
75                 return;
76
77         /*
78          * This flags XFS_MOUNT_FS_SHUTDOWN, makes sure that we don't
79          * queue up anybody new on the log reservations, and wakes up
80          * everybody who's sleeping on log reservations to tell them
81          * the bad news.
82          */
83         if (xfs_log_force_umount(mp, logerror))
84                 return;
85
86         if (flags & SHUTDOWN_CORRUPT_INCORE) {
87                 xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp,
88     "Corruption of in-memory data detected.  Shutting down filesystem: %s",
89                         mp->m_fsname);
90                 if (XFS_ERRLEVEL_HIGH <= xfs_error_level) {
91                         xfs_stack_trace();
92                 }
93         } else if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
94                 if (logerror) {
95                         xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp,
96                 "Log I/O Error Detected.  Shutting down filesystem: %s",
97                                 mp->m_fsname);
98                 } else if (flags & SHUTDOWN_DEVICE_REQ) {
99                         xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp,
100                 "All device paths lost.  Shutting down filesystem: %s",
101                                 mp->m_fsname);
102                 } else if (!(flags & SHUTDOWN_REMOTE_REQ)) {
103                         xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp,
104                 "I/O Error Detected.  Shutting down filesystem: %s",
105                                 mp->m_fsname);
106                 }
107         }
108         if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
109                 cmn_err(CE_ALERT, "Please umount the filesystem, "
110                                   "and rectify the problem(s)");
111         }
112 }
113
114 /*
115  * Prints out an ALERT message about I/O error.
116  */
117 void
118 xfs_ioerror_alert(
119         char                    *func,
120         struct xfs_mount        *mp,
121         xfs_buf_t               *bp,
122         xfs_daddr_t             blkno)
123 {
124         cmn_err(CE_ALERT,
125  "I/O error in filesystem (\"%s\") meta-data dev %s block 0x%llx"
126  "       (\"%s\") error %d buf count %zd",
127                 (!mp || !mp->m_fsname) ? "(fs name not set)" : mp->m_fsname,
128                 XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)),
129                 (__uint64_t)blkno, func,
130                 XFS_BUF_GETERROR(bp), XFS_BUF_COUNT(bp));
131 }
132
133 /*
134  * This isn't an absolute requirement, but it is
135  * just a good idea to call xfs_read_buf instead of
136  * directly doing a read_buf call. For one, we shouldn't
137  * be doing this disk read if we are in SHUTDOWN state anyway,
138  * so this stops that from happening. Secondly, this does all
139  * the error checking stuff and the brelse if appropriate for
140  * the caller, so the code can be a little leaner.
141  */
142
143 int
144 xfs_read_buf(
145         struct xfs_mount *mp,
146         xfs_buftarg_t    *target,
147         xfs_daddr_t      blkno,
148         int              len,
149         uint             flags,
150         xfs_buf_t        **bpp)
151 {
152         xfs_buf_t        *bp;
153         int              error;
154
155         if (!flags)
156                 flags = XBF_LOCK | XBF_MAPPED;
157
158         bp = xfs_buf_read(target, blkno, len, flags);
159         if (!bp)
160                 return XFS_ERROR(EIO);
161         error = XFS_BUF_GETERROR(bp);
162         if (bp && !error && !XFS_FORCED_SHUTDOWN(mp)) {
163                 *bpp = bp;
164         } else {
165                 *bpp = NULL;
166                 if (error) {
167                         xfs_ioerror_alert("xfs_read_buf", mp, bp, XFS_BUF_ADDR(bp));
168                 } else {
169                         error = XFS_ERROR(EIO);
170                 }
171                 if (bp) {
172                         XFS_BUF_UNDONE(bp);
173                         XFS_BUF_UNDELAYWRITE(bp);
174                         XFS_BUF_STALE(bp);
175                         /*
176                          * brelse clears B_ERROR and b_error
177                          */
178                         xfs_buf_relse(bp);
179                 }
180         }
181         return (error);
182 }
183
184 /*
185  * helper function to extract extent size hint from inode
186  */
187 xfs_extlen_t
188 xfs_get_extsz_hint(
189         struct xfs_inode        *ip)
190 {
191         xfs_extlen_t            extsz;
192
193         if (unlikely(XFS_IS_REALTIME_INODE(ip))) {
194                 extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)
195                                 ? ip->i_d.di_extsize
196                                 : ip->i_mount->m_sb.sb_rextsize;
197                 ASSERT(extsz);
198         } else {
199                 extsz = (ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE)
200                                 ? ip->i_d.di_extsize : 0;
201         }
202
203         return extsz;
204 }