linux/fs/xfs/xfs_rw.c
<<
>>
Prefs
   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_mount.h"
  28#include "xfs_bmap_btree.h"
  29#include "xfs_dinode.h"
  30#include "xfs_inode.h"
  31#include "xfs_error.h"
  32#include "xfs_rw.h"
  33
  34/*
  35 * Force a shutdown of the filesystem instantly while keeping
  36 * the filesystem consistent. We don't do an unmount here; just shutdown
  37 * the shop, make sure that absolutely nothing persistent happens to
  38 * this filesystem after this point.
  39 */
  40void
  41xfs_do_force_shutdown(
  42        xfs_mount_t     *mp,
  43        int             flags,
  44        char            *fname,
  45        int             lnnum)
  46{
  47        int             logerror;
  48
  49        logerror = flags & SHUTDOWN_LOG_IO_ERROR;
  50
  51        if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
  52                xfs_notice(mp,
  53        "%s(0x%x) called from line %d of file %s.  Return address = 0x%p",
  54                        __func__, flags, lnnum, fname, __return_address);
  55        }
  56        /*
  57         * No need to duplicate efforts.
  58         */
  59        if (XFS_FORCED_SHUTDOWN(mp) && !logerror)
  60                return;
  61
  62        /*
  63         * This flags XFS_MOUNT_FS_SHUTDOWN, makes sure that we don't
  64         * queue up anybody new on the log reservations, and wakes up
  65         * everybody who's sleeping on log reservations to tell them
  66         * the bad news.
  67         */
  68        if (xfs_log_force_umount(mp, logerror))
  69                return;
  70
  71        if (flags & SHUTDOWN_CORRUPT_INCORE) {
  72                xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_CORRUPT,
  73    "Corruption of in-memory data detected.  Shutting down filesystem");
  74                if (XFS_ERRLEVEL_HIGH <= xfs_error_level)
  75                        xfs_stack_trace();
  76        } else if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
  77                if (logerror) {
  78                        xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_LOGERROR,
  79                "Log I/O Error Detected.  Shutting down filesystem");
  80                } else if (flags & SHUTDOWN_DEVICE_REQ) {
  81                        xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_IOERROR,
  82                "All device paths lost.  Shutting down filesystem");
  83                } else if (!(flags & SHUTDOWN_REMOTE_REQ)) {
  84                        xfs_alert_tag(mp, XFS_PTAG_SHUTDOWN_IOERROR,
  85                "I/O Error Detected. Shutting down filesystem");
  86                }
  87        }
  88        if (!(flags & SHUTDOWN_FORCE_UMOUNT)) {
  89                xfs_alert(mp,
  90        "Please umount the filesystem and rectify the problem(s)");
  91        }
  92}
  93
  94/*
  95 * Prints out an ALERT message about I/O error.
  96 */
  97void
  98xfs_ioerror_alert(
  99        char                    *func,
 100        struct xfs_mount        *mp,
 101        xfs_buf_t               *bp,
 102        xfs_daddr_t             blkno)
 103{
 104        xfs_alert(mp,
 105                 "I/O error occurred: meta-data dev %s block 0x%llx"
 106                 "       (\"%s\") error %d buf count %zd",
 107                XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)),
 108                (__uint64_t)blkno, func,
 109                XFS_BUF_GETERROR(bp), XFS_BUF_COUNT(bp));
 110}
 111
 112/*
 113 * This isn't an absolute requirement, but it is
 114 * just a good idea to call xfs_read_buf instead of
 115 * directly doing a read_buf call. For one, we shouldn't
 116 * be doing this disk read if we are in SHUTDOWN state anyway,
 117 * so this stops that from happening. Secondly, this does all
 118 * the error checking stuff and the brelse if appropriate for
 119 * the caller, so the code can be a little leaner.
 120 */
 121
 122int
 123xfs_read_buf(
 124        struct xfs_mount *mp,
 125        xfs_buftarg_t    *target,
 126        xfs_daddr_t      blkno,
 127        int              len,
 128        uint             flags,
 129        xfs_buf_t        **bpp)
 130{
 131        xfs_buf_t        *bp;
 132        int              error;
 133
 134        if (!flags)
 135                flags = XBF_LOCK | XBF_MAPPED;
 136
 137        bp = xfs_buf_read(target, blkno, len, flags);
 138        if (!bp)
 139                return XFS_ERROR(EIO);
 140        error = XFS_BUF_GETERROR(bp);
 141        if (bp && !error && !XFS_FORCED_SHUTDOWN(mp)) {
 142                *bpp = bp;
 143        } else {
 144                *bpp = NULL;
 145                if (error) {
 146                        xfs_ioerror_alert("xfs_read_buf", mp, bp, XFS_BUF_ADDR(bp));
 147                } else {
 148                        error = XFS_ERROR(EIO);
 149                }
 150                if (bp) {
 151                        XFS_BUF_UNDONE(bp);
 152                        XFS_BUF_UNDELAYWRITE(bp);
 153                        XFS_BUF_STALE(bp);
 154                        /*
 155                         * brelse clears B_ERROR and b_error
 156                         */
 157                        xfs_buf_relse(bp);
 158                }
 159        }
 160        return (error);
 161}
 162
 163/*
 164 * helper function to extract extent size hint from inode
 165 */
 166xfs_extlen_t
 167xfs_get_extsz_hint(
 168        struct xfs_inode        *ip)
 169{
 170        if ((ip->i_d.di_flags & XFS_DIFLAG_EXTSIZE) && ip->i_d.di_extsize)
 171                return ip->i_d.di_extsize;
 172        if (XFS_IS_REALTIME_INODE(ip))
 173                return ip->i_mount->m_sb.sb_rextsize;
 174        return 0;
 175}
 176