void xfs_do_force_shutdown( bhv_desc_t *bdp, int flags, char *fname, int lnnum) { int logerror; xfs_mount_t *mp; mp = XFS_BHVTOM(bdp); logerror = flags & SHUTDOWN_LOG_IO_ERROR; if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { cmn_err(CE_NOTE, "xfs_force_shutdown(%s,0x%x) called from " "line %d of file %s. Return address = 0x%p", mp->m_fsname, flags, lnnum, fname, __return_address); } /* * No need to duplicate efforts. */ if (XFS_FORCED_SHUTDOWN(mp) && !logerror) return; /* * This flags XFS_MOUNT_FS_SHUTDOWN, makes sure that we don't * queue up anybody new on the log reservations, and wakes up * everybody who's sleeping on log reservations to tell them * the bad news. */ if (xfs_log_force_umount(mp, logerror)) return; if (flags & SHUTDOWN_CORRUPT_INCORE) { xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp, "Corruption of in-memory data detected. Shutting down filesystem: %s", mp->m_fsname); if (XFS_ERRLEVEL_HIGH <= xfs_error_level) { xfs_stack_trace(); } } else if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { if (logerror) { xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp, "Log I/O Error Detected. Shutting down filesystem: %s", mp->m_fsname); } else if (flags & SHUTDOWN_DEVICE_REQ) { xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, "All device paths lost. Shutting down filesystem: %s", mp->m_fsname); } else if (!(flags & SHUTDOWN_REMOTE_REQ)) { xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, "I/O Error Detected. Shutting down filesystem: %s", mp->m_fsname); } } if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { cmn_err(CE_ALERT, "Please umount the filesystem, " "and rectify the problem(s)"); } }
void xfs_initialize_vnode( bhv_desc_t *bdp, vnode_t *vp, bhv_desc_t *inode_bhv, int unlock) { xfs_inode_t *ip = XFS_BHVTOI(inode_bhv); struct inode *inode = LINVFS_GET_IP(vp); if (!inode_bhv->bd_vobj) { vp->v_vfsp = bhvtovfs(bdp); bhv_desc_init(inode_bhv, ip, vp, &xfs_vnodeops); bhv_insert(VN_BHV_HEAD(vp), inode_bhv); } vp->v_type = IFTOVT(ip->i_d.di_mode); /* Have we been called during the new inode create process, * in which case we are too early to fill in the Linux inode. */ if (vp->v_type == VNON) return; xfs_revalidate_inode(XFS_BHVTOM(bdp), vp, ip); /* For new inodes we need to set the ops vectors, * and unlock the inode. */ if (unlock && (inode->i_state & I_NEW)) { xfs_set_inodeops(inode); unlock_new_inode(inode); } }
/*ARGSUSED*/ STATIC int xfs_sync( bhv_desc_t *bdp, int flags, cred_t *credp) { xfs_mount_t *mp; mp = XFS_BHVTOM(bdp); return (xfs_syncsub(mp, flags, 0, NULL)); }
/* * xfs_root extracts the root vnode from a vfs. * * vfsp -- the vfs struct for the desired file system * vpp -- address of the caller's vnode pointer which should be * set to the desired fs root vnode */ STATIC int xfs_root( bhv_desc_t *bdp, vnode_t **vpp) { vnode_t *vp; vp = XFS_ITOV((XFS_BHVTOM(bdp))->m_rootip); VN_HOLD(vp); *vpp = vp; return 0; }
STATIC int xfs_mntupdate( bhv_desc_t *bdp, int *flags, struct xfs_mount_args *args) { struct vfs *vfsp = bhvtovfs(bdp); xfs_mount_t *mp = XFS_BHVTOM(bdp); int pincount, error; int count = 0; if (args->flags & XFSMNT_NOATIME) mp->m_flags |= XFS_MOUNT_NOATIME; else mp->m_flags &= ~XFS_MOUNT_NOATIME; if (!(vfsp->vfs_flag & VFS_RDONLY)) { VFS_SYNC(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL, error); } if (*flags & MS_RDONLY) { xfs_refcache_purge_mp(mp); xfs_flush_buftarg(mp->m_ddev_targp, 0); xfs_finish_reclaim_all(mp, 0); /* This loop must run at least twice. * The first instance of the loop will flush * most meta data but that will generate more * meta data (typically directory updates). * Which then must be flushed and logged before * we can write the unmount record. */ do { VFS_SYNC(vfsp, REMOUNT_READONLY_FLAGS, NULL, error); pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1); if (!pincount) { delay(50); count++; } } while (count < 2); /* Ok now write out an unmount record */ xfs_log_unmount_write(mp); xfs_unmountfs_writesb(mp); vfsp->vfs_flag |= VFS_RDONLY; } else { vfsp->vfs_flag &= ~VFS_RDONLY; } return 0; }
void bhv_remove_all_vfsops( struct vfs *vfsp, int freebase) { struct xfs_mount *mp; bhv_remove_vfsops(vfsp, VFS_POSITION_QM); bhv_remove_vfsops(vfsp, VFS_POSITION_DM); if (!freebase) return; mp = XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfsp), &xfs_vfsops)); VFS_REMOVEBHV(vfsp, &mp->m_bhv); xfs_mount_free(mp, 0); }
/* * xfs_statvfs * * Fill in the statvfs structure for the given file system. We use * the superblock lock in the mount structure to ensure a consistent * snapshot of the counters returned. */ STATIC int xfs_statvfs( bhv_desc_t *bdp, xfs_statfs_t *statp, vnode_t *vp) { __uint64_t fakeinos; xfs_extlen_t lsize; xfs_mount_t *mp; xfs_sb_t *sbp; unsigned long s; u64 id; mp = XFS_BHVTOM(bdp); sbp = &(mp->m_sb); statp->f_type = XFS_SB_MAGIC; s = XFS_SB_LOCK(mp); statp->f_bsize = sbp->sb_blocksize; lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0; statp->f_blocks = sbp->sb_dblocks - lsize; statp->f_bfree = statp->f_bavail = sbp->sb_fdblocks; fakeinos = statp->f_bfree << sbp->sb_inopblog; #if XFS_BIG_INUMS fakeinos += mp->m_inoadd; #endif statp->f_files = MIN(sbp->sb_icount + fakeinos, (__uint64_t)XFS_MAXINUMBER); if (mp->m_maxicount) #if XFS_BIG_INUMS if (!mp->m_inoadd) #endif statp->f_files = min_t(typeof(statp->f_files), statp->f_files, mp->m_maxicount); statp->f_ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree); XFS_SB_UNLOCK(mp, s); id = huge_encode_dev(mp->m_dev); statp->f_fsid.val[0] = (u32)id; statp->f_fsid.val[1] = (u32)(id >> 32); statp->f_namelen = MAXNAMELEN - 1; return 0; }
xfs_mount_t * xfs_bhvtom(bhv_desc_t *bdp) { return XFS_BHVTOM(bdp); }
STATIC int xfs_unmount( bhv_desc_t *bdp, int flags, cred_t *credp) { struct vfs *vfsp = bhvtovfs(bdp); xfs_mount_t *mp = XFS_BHVTOM(bdp); xfs_inode_t *rip; vnode_t *rvp; int unmount_event_wanted = 0; int unmount_event_flags = 0; int xfs_unmountfs_needed = 0; int error; rip = mp->m_rootip; rvp = XFS_ITOV(rip); if (vfsp->vfs_flag & VFS_DMI) { error = XFS_SEND_PREUNMOUNT(mp, vfsp, rvp, DM_RIGHT_NULL, rvp, DM_RIGHT_NULL, NULL, NULL, 0, 0, (mp->m_dmevmask & (1<<DM_EVENT_PREUNMOUNT))? 0:DM_FLAGS_UNWANTED); if (error) return XFS_ERROR(error); unmount_event_wanted = 1; unmount_event_flags = (mp->m_dmevmask & (1<<DM_EVENT_UNMOUNT))? 0 : DM_FLAGS_UNWANTED; } /* * First blow any referenced inode from this file system * out of the reference cache, and delete the timer. */ xfs_refcache_purge_mp(mp); XFS_bflush(mp->m_ddev_targp); error = xfs_unmount_flush(mp, 0); if (error) goto out; ASSERT(vn_count(rvp) == 1); /* * Drop the reference count */ VN_RELE(rvp); /* * If we're forcing a shutdown, typically because of a media error, * we want to make sure we invalidate dirty pages that belong to * referenced vnodes as well. */ if (XFS_FORCED_SHUTDOWN(mp)) { error = xfs_sync(&mp->m_bhv, (SYNC_WAIT | SYNC_CLOSE), credp); ASSERT(error != EFSCORRUPTED); } xfs_unmountfs_needed = 1; out: /* Send DMAPI event, if required. * Then do xfs_unmountfs() if needed. * Then return error (or zero). */ if (unmount_event_wanted) { /* Note: mp structure must still exist for * XFS_SEND_UNMOUNT() call. */ XFS_SEND_UNMOUNT(mp, vfsp, error == 0 ? rvp : NULL, DM_RIGHT_NULL, 0, error, unmount_event_flags); } if (xfs_unmountfs_needed) { /* * Call common unmount function to flush to disk * and free the super block buffer & mount structures. */ xfs_unmountfs(mp, credp); } return XFS_ERROR(error); }
/* * xfs_mount * * The file system configurations are: * (1) device (partition) with data and internal log * (2) logical volume with data and log subvolumes. * (3) logical volume with data, log, and realtime subvolumes. * * We only have to handle opening the log and realtime volumes here if * they are present. The data subvolume has already been opened by * get_sb_bdev() and is stored in vfsp->vfs_super->s_bdev. */ STATIC int xfs_mount( struct bhv_desc *bhvp, struct xfs_mount_args *args, cred_t *credp) { struct vfs *vfsp = bhvtovfs(bhvp); struct bhv_desc *p; struct xfs_mount *mp = XFS_BHVTOM(bhvp); struct block_device *ddev, *logdev, *rtdev; int flags = 0, error; ddev = vfsp->vfs_super->s_bdev; logdev = rtdev = NULL; /* * Open real time and log devices - order is important. */ if (args->logname[0]) { error = xfs_blkdev_get(mp, args->logname, &logdev); if (error) return error; } if (args->rtname[0]) { error = xfs_blkdev_get(mp, args->rtname, &rtdev); if (error) { xfs_blkdev_put(logdev); return error; } if (rtdev == ddev || rtdev == logdev) { cmn_err(CE_WARN, "XFS: Cannot mount filesystem with identical rtdev and ddev/logdev."); xfs_blkdev_put(logdev); xfs_blkdev_put(rtdev); return EINVAL; } } /* * Setup xfs_mount function vectors from available behaviors */ p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM); mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub; p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM); mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub; p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO); mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs; /* * Setup xfs_mount buffer target pointers */ mp->m_ddev_targp = xfs_alloc_buftarg(ddev); if (rtdev) mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev); mp->m_logdev_targp = (logdev && logdev != ddev) ? xfs_alloc_buftarg(logdev) : mp->m_ddev_targp; /* * Setup flags based on mount(2) options and then the superblock */ error = xfs_start_flags(vfsp, args, mp); if (error) goto error; error = xfs_readsb(mp); if (error) goto error; error = xfs_finish_flags(vfsp, args, mp); if (error) { xfs_freesb(mp); goto error; } /* * Setup xfs_mount buffer target pointers based on superblock */ xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize, mp->m_sb.sb_sectsize); if (logdev && logdev != ddev) { unsigned int log_sector_size = BBSIZE; if (XFS_SB_VERSION_HASSECTOR(&mp->m_sb)) log_sector_size = mp->m_sb.sb_logsectsize; xfs_setsize_buftarg(mp->m_logdev_targp, mp->m_sb.sb_blocksize, log_sector_size); } if (rtdev) xfs_setsize_buftarg(mp->m_rtdev_targp, mp->m_sb.sb_blocksize, mp->m_sb.sb_blocksize); if (!(error = XFS_IOINIT(vfsp, args, flags))) return 0; error: xfs_binval(mp->m_ddev_targp); if (logdev != NULL && logdev != ddev) { xfs_binval(mp->m_logdev_targp); } if (rtdev != NULL) { xfs_binval(mp->m_rtdev_targp); } xfs_unmountfs_close(mp, NULL); return error; }