xfs_mountops.c revision 153400
1153323Srodrigc#include <sys/param.h> 2153323Srodrigc#include <sys/systm.h> 3153323Srodrigc#include <sys/kernel.h> 4153323Srodrigc#include <sys/proc.h> 5153323Srodrigc#include <sys/malloc.h> 6153323Srodrigc#include <sys/vnode.h> 7153323Srodrigc#include <sys/mount.h> 8153323Srodrigc#include <sys/namei.h> 9153323Srodrigc 10153323Srodrigc#include <geom/geom.h> 11153323Srodrigc#include <geom/geom_vfs.h> 12153323Srodrigc 13153323Srodrigc#include "xfs.h" 14153323Srodrigc#include "xfs_macros.h" 15153323Srodrigc#include "xfs_types.h" 16153323Srodrigc#include "xfs_inum.h" 17153323Srodrigc#include "xfs_log.h" 18153323Srodrigc#include "xfs_trans.h" 19153323Srodrigc#include "xfs_sb.h" 20153323Srodrigc#include "xfs_ag.h" 21153323Srodrigc#include "xfs_dir.h" 22153323Srodrigc#include "xfs_dir2.h" 23153323Srodrigc#include "xfs_dmapi.h" 24153323Srodrigc#include "xfs_mount.h" 25153323Srodrigc#include "xfs_alloc_btree.h" 26153323Srodrigc#include "xfs_bmap_btree.h" 27153323Srodrigc#include "xfs_ialloc_btree.h" 28153323Srodrigc#include "xfs_btree.h" 29153323Srodrigc#include "xfs_ialloc.h" 30153323Srodrigc#include "xfs_attr_sf.h" 31153323Srodrigc#include "xfs_dir_sf.h" 32153323Srodrigc#include "xfs_dir2_sf.h" 33153323Srodrigc#include "xfs_dinode.h" 34153323Srodrigc#include "xfs_inode.h" 35153323Srodrigc#include "xfs_alloc.h" 36153323Srodrigc#include "xfs_rtalloc.h" 37153323Srodrigc#include "xfs_bmap.h" 38153323Srodrigc#include "xfs_error.h" 39153323Srodrigc#include "xfs_bit.h" 40153323Srodrigc#include "xfs_rw.h" 41153323Srodrigc#include "xfs_quota.h" 42153323Srodrigc#include "xfs_fsops.h" 43153323Srodrigc#include "xfs_clnt.h" 44153323Srodrigc 45153323Srodrigc#include <xfs_mountops.h> 46153323Srodrigc 47153323SrodrigcMALLOC_DEFINE(M_XFSNODE, "XFS node", "XFS vnode private part"); 48153323Srodrigc 49153323Srodrigcstatic vfs_mount_t _xfs_mount; 50153323Srodrigcstatic vfs_unmount_t _xfs_unmount; 51153323Srodrigcstatic vfs_root_t _xfs_root; 52153323Srodrigcstatic vfs_quotactl_t _xfs_quotactl; 53153323Srodrigcstatic vfs_statfs_t _xfs_statfs; 54153323Srodrigcstatic vfs_sync_t _xfs_sync; 55153323Srodrigcstatic vfs_vget_t _xfs_vget; 56153323Srodrigcstatic vfs_fhtovp_t _xfs_fhtovp; 57153323Srodrigcstatic vfs_checkexp_t _xfs_checkexp; 58153323Srodrigcstatic vfs_vptofh_t _xfs_vptofh; 59153323Srodrigcstatic vfs_init_t _xfs_init; 60153323Srodrigcstatic vfs_uninit_t _xfs_uninit; 61153323Srodrigcstatic vfs_extattrctl_t _xfs_extattrctl; 62153323Srodrigc 63153323Srodrigcstatic b_strategy_t xfs_geom_strategy; 64153323Srodrigc 65153323Srodrigcstatic const char *xfs_opts[] = 66153323Srodrigc { "from", "flags", "logbufs", "logbufsize", 67153323Srodrigc "rtname", "logname", "iosizelog", "sunit", 68153323Srodrigc "swidth", 69153323Srodrigc NULL }; 70153323Srodrigc 71153323Srodrigcstatic void 72153323Srodrigcparse_int(struct mount *mp, const char *opt, int *val, int *error) 73153323Srodrigc{ 74153323Srodrigc char *tmp, *ep; 75153323Srodrigc 76153323Srodrigc tmp = vfs_getopts(mp->mnt_optnew, opt, error); 77153323Srodrigc if (*error != 0) { 78153323Srodrigc return; 79153323Srodrigc } 80153323Srodrigc if (tmp != NULL) { 81153323Srodrigc *val = (int)strtol(tmp, &ep, 10); 82153323Srodrigc if (*ep) { 83153323Srodrigc *error = EINVAL; 84153323Srodrigc return; 85153323Srodrigc } 86153323Srodrigc } 87153323Srodrigc} 88153323Srodrigc 89153323Srodrigcstatic int 90153323Srodrigc_xfs_param_copyin(struct mount *mp, struct thread *td) 91153323Srodrigc{ 92153323Srodrigc struct xfsmount *xmp = MNTTOXFS(mp); 93153323Srodrigc struct xfs_mount_args *args = &xmp->m_args; 94153323Srodrigc char *path; 95153323Srodrigc char *fsname; 96153323Srodrigc char *rtname; 97153323Srodrigc char *logname; 98153323Srodrigc int error; 99153323Srodrigc 100153323Srodrigc path = vfs_getopts(mp->mnt_optnew, "fspath", &error); 101153323Srodrigc if (error) 102153323Srodrigc return (error); 103153323Srodrigc 104153323Srodrigc bzero(args, sizeof(struct xfs_mount_args)); 105153323Srodrigc args->logbufs = -1; 106153323Srodrigc args->logbufsize = -1; 107153323Srodrigc 108153323Srodrigc parse_int(mp, "flags", &args->flags, &error); 109153323Srodrigc if (error != 0) 110153323Srodrigc return error; 111153323Srodrigc 112153323Srodrigc args->flags |= XFSMNT_32BITINODES; 113153323Srodrigc 114153323Srodrigc parse_int(mp, "sunit", &args->sunit, &error); 115153323Srodrigc if (error != 0) 116153323Srodrigc return error; 117153323Srodrigc 118153323Srodrigc parse_int(mp, "swidth", &args->swidth, &error); 119153323Srodrigc if (error != 0) 120153323Srodrigc return error; 121153323Srodrigc 122153323Srodrigc parse_int(mp, "logbufs", &args->logbufs, &error); 123153323Srodrigc if (error != 0) 124153323Srodrigc return error; 125153323Srodrigc 126153323Srodrigc parse_int(mp, "logbufsize", &args->logbufsize, &error); 127153323Srodrigc if (error != 0) 128153323Srodrigc return error; 129153323Srodrigc 130153323Srodrigc fsname = vfs_getopts(mp->mnt_optnew, "from", &error); 131153323Srodrigc if (error == 0 && fsname != NULL) { 132153323Srodrigc strncpy(args->fsname, fsname, sizeof(args->fsname) - 1); 133153323Srodrigc } 134153323Srodrigc 135153323Srodrigc logname = vfs_getopts(mp->mnt_optnew, "logname", &error); 136153323Srodrigc if (error == 0 && logname != NULL) { 137153323Srodrigc strncpy(args->logname, logname, sizeof(args->logname) - 1); 138153323Srodrigc } 139153323Srodrigc 140153323Srodrigc rtname = vfs_getopts(mp->mnt_optnew, "rtname", &error); 141153323Srodrigc if (error == 0 && rtname != NULL) { 142153323Srodrigc strncpy(args->rtname, rtname, sizeof(args->rtname) - 1); 143153323Srodrigc } 144153323Srodrigc 145153323Srodrigc strncpy(args->mtpt, path, sizeof(args->mtpt)); 146153323Srodrigc 147153323Srodrigc printf("fsname '%s' logname '%s' rtname '%s'\n" 148153323Srodrigc "flags 0x%x sunit %d swidth %d logbufs %d logbufsize %d\n", 149153323Srodrigc args->fsname, args->logname, args->rtname, args->flags, 150153323Srodrigc args->sunit, args->swidth, args->logbufs, args->logbufsize); 151153323Srodrigc 152153323Srodrigc vfs_mountedfrom(mp, args->fsname); 153153323Srodrigc 154153323Srodrigc return (0); 155153323Srodrigc} 156153323Srodrigc 157153323Srodrigcstatic int 158153323Srodrigc_xfs_mount(struct mount *mp, 159153323Srodrigc struct thread *td) 160153323Srodrigc{ 161153323Srodrigc struct xfsmount *xmp; 162153323Srodrigc struct xfs_vnode *rootvp; 163153323Srodrigc struct ucred *curcred; 164153323Srodrigc struct vnode *rvp; 165153323Srodrigc struct cdev *ddev; 166153323Srodrigc int error; 167153323Srodrigc 168153323Srodrigc if (vfs_filteropt(mp->mnt_optnew, xfs_opts)) 169153323Srodrigc return (EINVAL); 170153323Srodrigc 171153323Srodrigc xmp = xfsmount_allocate(mp); 172153323Srodrigc if (xmp == NULL) 173153323Srodrigc return (ENOMEM); 174153323Srodrigc 175153323Srodrigc if((error = _xfs_param_copyin(mp, td)) != 0) 176153323Srodrigc goto fail; 177153323Srodrigc 178153323Srodrigc /* Force read-only mounts in this branch. */ 179153323Srodrigc XFSTOVFS(xmp)->vfs_flag |= VFS_RDONLY; 180153323Srodrigc mp->mnt_flag |= MNT_RDONLY; 181153323Srodrigc 182153323Srodrigc /* XXX: Do not support MNT_UPDATE yet */ 183153323Srodrigc if (mp->mnt_flag & MNT_UPDATE) 184153323Srodrigc return EOPNOTSUPP; 185153323Srodrigc 186153323Srodrigc curcred = td->td_ucred; 187153323Srodrigc XVFS_MOUNT(XFSTOVFS(xmp), &xmp->m_args, curcred, error); 188153323Srodrigc if (error) 189153323Srodrigc goto fail; 190153323Srodrigc 191153323Srodrigc XVFS_ROOT(XFSTOVFS(xmp), &rootvp, error); 192153323Srodrigc if (error) 193153323Srodrigc goto fail_unmount; 194153323Srodrigc 195153323Srodrigc ddev = XFS_VFSTOM(XFSTOVFS(xmp))->m_dev; 196153323Srodrigc if (ddev->si_iosize_max != 0) 197153323Srodrigc mp->mnt_iosize_max = ddev->si_iosize_max; 198153323Srodrigc if (mp->mnt_iosize_max > MAXPHYS) 199153323Srodrigc mp->mnt_iosize_max = MAXPHYS; 200153323Srodrigc 201153323Srodrigc mp->mnt_flag |= MNT_LOCAL | MNT_RDONLY; 202153323Srodrigc mp->mnt_stat.f_fsid.val[0] = dev2udev(ddev); 203153323Srodrigc mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; 204153323Srodrigc 205153323Srodrigc VFS_STATFS(mp, &mp->mnt_stat, td); 206153323Srodrigc if (error) 207153323Srodrigc goto fail_unmount; 208153323Srodrigc 209153323Srodrigc rvp = rootvp->v_vnode; 210153323Srodrigc rvp->v_vflag |= VV_ROOT; 211153323Srodrigc VN_RELE(rootvp); 212153323Srodrigc 213153323Srodrigc return (0); 214153323Srodrigc 215153323Srodrigc fail_unmount: 216153323Srodrigc XVFS_UNMOUNT(XFSTOVFS(xmp), 0, curcred, error); 217153323Srodrigc 218153323Srodrigc fail: 219153323Srodrigc if (xmp != NULL) 220153323Srodrigc xfsmount_deallocate(xmp); 221153323Srodrigc 222153323Srodrigc return (error); 223153323Srodrigc} 224153323Srodrigc 225153323Srodrigc/* 226153323Srodrigc * Free reference to null layer 227153323Srodrigc */ 228153323Srodrigcstatic int 229153323Srodrigc_xfs_unmount(mp, mntflags, td) 230153323Srodrigc struct mount *mp; 231153323Srodrigc int mntflags; 232153323Srodrigc struct thread *td; 233153323Srodrigc{ 234153323Srodrigc int error; 235153323Srodrigc 236153323Srodrigc XVFS_UNMOUNT(MNTTOVFS(mp), 0, td->td_ucred, error); 237153323Srodrigc return (error); 238153323Srodrigc} 239153323Srodrigc 240153323Srodrigcstatic int 241153323Srodrigc_xfs_root(mp, flags, vpp, td) 242153323Srodrigc struct mount *mp; 243153323Srodrigc int flags; 244153323Srodrigc struct vnode **vpp; 245153323Srodrigc struct thread *td; 246153323Srodrigc{ 247153323Srodrigc xfs_vnode_t *vp; 248153323Srodrigc int error; 249153323Srodrigc 250153323Srodrigc XVFS_ROOT(MNTTOVFS(mp), &vp, error); 251153323Srodrigc if (error == 0) { 252153323Srodrigc *vpp = vp->v_vnode; 253153323Srodrigc VOP_LOCK(*vpp, flags, curthread); 254153323Srodrigc } 255153323Srodrigc return (error); 256153323Srodrigc} 257153323Srodrigc 258153323Srodrigcstatic int 259153323Srodrigc_xfs_quotactl(mp, cmd, uid, arg, td) 260153323Srodrigc struct mount *mp; 261153323Srodrigc int cmd; 262153323Srodrigc uid_t uid; 263153400Sdes void *arg; 264153323Srodrigc struct thread *td; 265153323Srodrigc{ 266153323Srodrigc printf("xfs_quotactl\n"); 267153323Srodrigc return ENOSYS; 268153323Srodrigc} 269153323Srodrigc 270153323Srodrigcstatic int 271153323Srodrigc_xfs_statfs(mp, sbp, td) 272153323Srodrigc struct mount *mp; 273153323Srodrigc struct statfs *sbp; 274153323Srodrigc struct thread *td; 275153323Srodrigc{ 276153323Srodrigc int error; 277153323Srodrigc 278153323Srodrigc XVFS_STATVFS(MNTTOVFS(mp), sbp, NULL, error); 279153323Srodrigc if (error) 280153323Srodrigc return error; 281153323Srodrigc 282153323Srodrigc /* Fix up the values XFS statvfs calls does not know about. */ 283153323Srodrigc sbp->f_iosize = sbp->f_bsize; 284153323Srodrigc 285153323Srodrigc return (error); 286153323Srodrigc} 287153323Srodrigc 288153323Srodrigcstatic int 289153323Srodrigc_xfs_sync(mp, waitfor, td) 290153323Srodrigc struct mount *mp; 291153323Srodrigc int waitfor; 292153323Srodrigc struct thread *td; 293153323Srodrigc{ 294153323Srodrigc int error; 295153323Srodrigc int flags = SYNC_FSDATA|SYNC_ATTR|SYNC_REFCACHE; 296153323Srodrigc 297153323Srodrigc if (waitfor == MNT_WAIT) 298153323Srodrigc flags |= SYNC_WAIT; 299153323Srodrigc else if (waitfor == MNT_LAZY) 300153323Srodrigc flags |= SYNC_BDFLUSH; 301153323Srodrigc XVFS_SYNC(MNTTOVFS(mp), flags, td->td_ucred, error); 302153323Srodrigc return (error); 303153323Srodrigc} 304153323Srodrigc 305153323Srodrigcstatic int 306153323Srodrigc_xfs_vget(mp, ino, flags, vpp) 307153323Srodrigc struct mount *mp; 308153323Srodrigc ino_t ino; 309153323Srodrigc int flags; 310153323Srodrigc struct vnode **vpp; 311153323Srodrigc{ 312153323Srodrigc xfs_vnode_t *vp; 313153323Srodrigc int error; 314153323Srodrigc 315153323Srodrigc printf("XVFS_GET_VNODE(MNTTOVFS(mp), &vp, ino, error);\n"); 316153323Srodrigc error = ENOSYS; 317153323Srodrigc if (error == 0) 318153323Srodrigc *vpp = vp->v_vnode; 319153323Srodrigc return (error); 320153323Srodrigc} 321153323Srodrigc 322153323Srodrigcstatic int 323153323Srodrigc_xfs_fhtovp(mp, fidp, vpp) 324153323Srodrigc struct mount *mp; 325153323Srodrigc struct fid *fidp; 326153323Srodrigc struct vnode **vpp; 327153323Srodrigc{ 328153323Srodrigc printf("xfs_fhtovp\n"); 329153323Srodrigc return ENOSYS; 330153323Srodrigc} 331153323Srodrigc 332153323Srodrigcstatic int 333153323Srodrigc_xfs_checkexp(mp, nam, extflagsp, credanonp) 334153323Srodrigc struct mount *mp; 335153323Srodrigc struct sockaddr *nam; 336153323Srodrigc int *extflagsp; 337153323Srodrigc struct ucred **credanonp; 338153323Srodrigc{ 339153323Srodrigc printf("xfs_checkexp\n"); 340153323Srodrigc return ENOSYS; 341153323Srodrigc} 342153323Srodrigc 343153323Srodrigcstatic int 344153323Srodrigc_xfs_vptofh(vp, fhp) 345153323Srodrigc struct vnode *vp; 346153323Srodrigc struct fid *fhp; 347153323Srodrigc{ 348153323Srodrigc printf("xfs_vptofh"); 349153323Srodrigc return ENOSYS; 350153323Srodrigc} 351153323Srodrigc 352153323Srodrigcstatic int 353153323Srodrigc_xfs_extattrctl(struct mount *mp, int cm, 354153323Srodrigc struct vnode *filename_v, 355153323Srodrigc int attrnamespace, const char *attrname, 356153323Srodrigc struct thread *td) 357153323Srodrigc{ 358153323Srodrigc printf("xfs_extattrctl\n"); 359153323Srodrigc return ENOSYS; 360153323Srodrigc} 361153323Srodrigc 362153323Srodrigcint 363153323Srodrigc_xfs_init(vfsp) 364153323Srodrigc struct vfsconf *vfsp; 365153323Srodrigc{ 366153323Srodrigc int error; 367153323Srodrigc 368153323Srodrigc error = init_xfs_fs(); 369153323Srodrigc 370153323Srodrigc return (error); 371153323Srodrigc} 372153323Srodrigc 373153323Srodrigcint 374153323Srodrigc_xfs_uninit(vfsp) 375153323Srodrigc struct vfsconf *vfsp; 376153323Srodrigc{ 377153323Srodrigc exit_xfs_fs(); 378153323Srodrigc return 0; 379153323Srodrigc} 380153323Srodrigc 381153323Srodrigcstatic struct vfsops xfs_fsops = { 382153323Srodrigc .vfs_mount = _xfs_mount, 383153323Srodrigc .vfs_unmount = _xfs_unmount, 384153323Srodrigc .vfs_root = _xfs_root, 385153323Srodrigc .vfs_quotactl = _xfs_quotactl, 386153323Srodrigc .vfs_statfs = _xfs_statfs, 387153323Srodrigc .vfs_sync = _xfs_sync, 388153323Srodrigc .vfs_vget = _xfs_vget, 389153323Srodrigc .vfs_fhtovp = _xfs_fhtovp, 390153323Srodrigc .vfs_checkexp = _xfs_checkexp, 391153323Srodrigc .vfs_vptofh = _xfs_vptofh, 392153323Srodrigc .vfs_init = _xfs_init, 393153323Srodrigc .vfs_uninit = _xfs_uninit, 394153323Srodrigc .vfs_extattrctl = _xfs_extattrctl, 395153323Srodrigc}; 396153323Srodrigc 397153323Srodrigc/* XXX: Read-only for now */ 398153323SrodrigcVFS_SET(xfs_fsops, xfs, VFCF_READONLY); 399153323Srodrigc 400153323Srodrigc/* 401153323Srodrigc * Copy GEOM VFS functions here to provide a conveniet place to 402153323Srodrigc * track all XFS-related IO without being distracted by other 403153323Srodrigc * filesystems which happen to be mounted on the machine at the 404153323Srodrigc * same time. 405153323Srodrigc */ 406153323Srodrigc 407153323Srodrigcstatic void 408153323Srodrigcxfs_geom_biodone(struct bio *bip) 409153323Srodrigc{ 410153323Srodrigc struct buf *bp; 411153323Srodrigc 412153323Srodrigc if (bip->bio_error) { 413153323Srodrigc printf("g_vfs_done():"); 414153323Srodrigc g_print_bio(bip); 415153323Srodrigc printf("error = %d\n", bip->bio_error); 416153323Srodrigc } 417153323Srodrigc bp = bip->bio_caller2; 418153323Srodrigc bp->b_error = bip->bio_error; 419153323Srodrigc bp->b_ioflags = bip->bio_flags; 420153323Srodrigc if (bip->bio_error) 421153323Srodrigc bp->b_ioflags |= BIO_ERROR; 422153323Srodrigc bp->b_resid = bp->b_bcount - bip->bio_completed; 423153323Srodrigc g_destroy_bio(bip); 424153323Srodrigc mtx_lock(&Giant); 425153323Srodrigc bufdone(bp); 426153323Srodrigc mtx_unlock(&Giant); 427153323Srodrigc} 428153323Srodrigc 429153323Srodrigcstatic void 430153323Srodrigcxfs_geom_strategy(struct bufobj *bo, struct buf *bp) 431153323Srodrigc{ 432153323Srodrigc struct g_consumer *cp; 433153323Srodrigc struct bio *bip; 434153323Srodrigc 435153323Srodrigc cp = bo->bo_private; 436153323Srodrigc G_VALID_CONSUMER(cp); 437153323Srodrigc 438153323Srodrigc bip = g_alloc_bio(); 439153323Srodrigc bip->bio_cmd = bp->b_iocmd; 440153323Srodrigc bip->bio_offset = bp->b_iooffset; 441153323Srodrigc bip->bio_data = bp->b_data; 442153323Srodrigc bip->bio_done = xfs_geom_biodone; 443153323Srodrigc bip->bio_caller2 = bp; 444153323Srodrigc bip->bio_length = bp->b_bcount; 445153323Srodrigc g_io_request(bip, cp); 446153323Srodrigc} 447153323Srodrigc 448153323Srodrigcstatic int 449153323Srodrigcxfs_geom_bufwrite(struct buf *bp) 450153323Srodrigc{ 451153323Srodrigc return bufwrite(bp); 452153323Srodrigc} 453153323Srodrigc 454153323Srodrigcstruct buf_ops xfs_ops = { 455153323Srodrigc .bop_name = "XFS", 456153323Srodrigc .bop_write = xfs_geom_bufwrite, 457153323Srodrigc .bop_strategy = xfs_geom_strategy, 458153323Srodrigc .bop_sync = bufsync, 459153323Srodrigc}; 460