xfs_mountops.c revision 159451
1/* 2 * Copyright (c) 2001,2006 Alexander Kabaev, Russell Cattelan Digital Elves Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/gnu/fs/xfs/FreeBSD/xfs_mountops.c 159451 2006-06-09 06:04:06Z rodrigc $ 27 */ 28 29#include <sys/param.h> 30#include <sys/systm.h> 31#include <sys/kernel.h> 32#include <sys/proc.h> 33#include <sys/malloc.h> 34#include <sys/vnode.h> 35#include <sys/mount.h> 36#include <sys/namei.h> 37 38#include <geom/geom.h> 39#include <geom/geom_vfs.h> 40 41#include "xfs.h" 42#include "xfs_types.h" 43#include "xfs_bit.h" 44#include "xfs_inum.h" 45#include "xfs_log.h" 46#include "xfs_trans.h" 47#include "xfs_sb.h" 48#include "xfs_ag.h" 49#include "xfs_dir.h" 50#include "xfs_dir2.h" 51#include "xfs_dmapi.h" 52#include "xfs_mount.h" 53#include "xfs_alloc_btree.h" 54#include "xfs_bmap_btree.h" 55#include "xfs_ialloc_btree.h" 56#include "xfs_btree.h" 57#include "xfs_attr_sf.h" 58#include "xfs_dir_sf.h" 59#include "xfs_dir2_sf.h" 60#include "xfs_dinode.h" 61#include "xfs_ialloc.h" 62#include "xfs_inode.h" 63#include "xfs_alloc.h" 64#include "xfs_rtalloc.h" 65#include "xfs_bmap.h" 66#include "xfs_error.h" 67#include "xfs_rw.h" 68#include "xfs_quota.h" 69#include "xfs_fsops.h" 70#include "xfs_clnt.h" 71 72#include <xfs_mountops.h> 73 74MALLOC_DEFINE(M_XFSNODE, "XFS node", "XFS vnode private part"); 75 76static vfs_mount_t _xfs_mount; 77static vfs_unmount_t _xfs_unmount; 78static vfs_root_t _xfs_root; 79static vfs_quotactl_t _xfs_quotactl; 80static vfs_statfs_t _xfs_statfs; 81static vfs_sync_t _xfs_sync; 82static vfs_vget_t _xfs_vget; 83static vfs_fhtovp_t _xfs_fhtovp; 84static vfs_vptofh_t _xfs_vptofh; 85static vfs_init_t _xfs_init; 86static vfs_uninit_t _xfs_uninit; 87static vfs_extattrctl_t _xfs_extattrctl; 88 89static b_strategy_t xfs_geom_strategy; 90 91static const char *xfs_opts[] = 92 { "from", "flags", "logbufs", "logbufsize", 93 "rtname", "logname", "iosizelog", "sunit", 94 "swidth", "export", 95 NULL }; 96 97static void 98parse_int(struct mount *mp, const char *opt, int *val, int *error) 99{ 100 char *tmp, *ep; 101 102 tmp = vfs_getopts(mp->mnt_optnew, opt, error); 103 if (*error != 0) { 104 return; 105 } 106 if (tmp != NULL) { 107 *val = (int)strtol(tmp, &ep, 10); 108 if (*ep) { 109 *error = EINVAL; 110 return; 111 } 112 } 113} 114 115static int 116_xfs_param_copyin(struct mount *mp, struct thread *td) 117{ 118 struct xfsmount *xmp = MNTTOXFS(mp); 119 struct xfs_mount_args *args = &xmp->m_args; 120 char *path; 121 char *fsname; 122 char *rtname; 123 char *logname; 124 int error; 125 126 path = vfs_getopts(mp->mnt_optnew, "fspath", &error); 127 if (error) 128 return (error); 129 130 bzero(args, sizeof(struct xfs_mount_args)); 131 args->logbufs = -1; 132 args->logbufsize = -1; 133 134 parse_int(mp, "flags", &args->flags, &error); 135 if (error != 0) 136 return error; 137 138 args->flags |= XFSMNT_32BITINODES; 139 140 parse_int(mp, "sunit", &args->sunit, &error); 141 if (error != 0) 142 return error; 143 144 parse_int(mp, "swidth", &args->swidth, &error); 145 if (error != 0) 146 return error; 147 148 parse_int(mp, "logbufs", &args->logbufs, &error); 149 if (error != 0) 150 return error; 151 152 parse_int(mp, "logbufsize", &args->logbufsize, &error); 153 if (error != 0) 154 return error; 155 156 fsname = vfs_getopts(mp->mnt_optnew, "from", &error); 157 if (error == 0 && fsname != NULL) { 158 strncpy(args->fsname, fsname, sizeof(args->fsname) - 1); 159 } 160 161 logname = vfs_getopts(mp->mnt_optnew, "logname", &error); 162 if (error == 0 && logname != NULL) { 163 strncpy(args->logname, logname, sizeof(args->logname) - 1); 164 } 165 166 rtname = vfs_getopts(mp->mnt_optnew, "rtname", &error); 167 if (error == 0 && rtname != NULL) { 168 strncpy(args->rtname, rtname, sizeof(args->rtname) - 1); 169 } 170 171 strncpy(args->mtpt, path, sizeof(args->mtpt)); 172 173 printf("fsname '%s' logname '%s' rtname '%s'\n" 174 "flags 0x%x sunit %d swidth %d logbufs %d logbufsize %d\n", 175 args->fsname, args->logname, args->rtname, args->flags, 176 args->sunit, args->swidth, args->logbufs, args->logbufsize); 177 178 vfs_mountedfrom(mp, args->fsname); 179 180 return (0); 181} 182 183static int 184_xfs_mount(struct mount *mp, 185 struct thread *td) 186{ 187 struct xfsmount *xmp; 188 struct xfs_vnode *rootvp; 189 struct ucred *curcred; 190 struct vnode *rvp; 191 struct cdev *ddev; 192 int error; 193 194 if (vfs_filteropt(mp->mnt_optnew, xfs_opts)) 195 return (EINVAL); 196 197 if (mp->mnt_flag & MNT_UPDATE) 198 return (0); 199 200 xmp = xfsmount_allocate(mp); 201 if (xmp == NULL) 202 return (ENOMEM); 203 204 if((error = _xfs_param_copyin(mp, td)) != 0) 205 goto fail; 206 207 curcred = td->td_ucred; 208 XVFS_MOUNT(XFSTOVFS(xmp), &xmp->m_args, curcred, error); 209 if (error) 210 goto fail; 211 212 XVFS_ROOT(XFSTOVFS(xmp), &rootvp, error); 213 if (error) 214 goto fail_unmount; 215 216 ddev = XFS_VFSTOM(XFSTOVFS(xmp))->m_ddev_targp->dev; 217 if (ddev->si_iosize_max != 0) 218 mp->mnt_iosize_max = ddev->si_iosize_max; 219 if (mp->mnt_iosize_max > MAXPHYS) 220 mp->mnt_iosize_max = MAXPHYS; 221 222 mp->mnt_flag |= MNT_LOCAL; 223 mp->mnt_stat.f_fsid.val[0] = dev2udev(ddev); 224 mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum; 225 226 if ((error = VFS_STATFS(mp, &mp->mnt_stat, td)) != 0) 227 goto fail_unmount; 228 229 rvp = rootvp->v_vnode; 230 rvp->v_vflag |= VV_ROOT; 231 VN_RELE(rootvp); 232 233 return (0); 234 235 fail_unmount: 236 XVFS_UNMOUNT(XFSTOVFS(xmp), 0, curcred, error); 237 238 fail: 239 if (xmp != NULL) 240 xfsmount_deallocate(xmp); 241 242 return (error); 243} 244 245/* 246 * Free reference to null layer 247 */ 248static int 249_xfs_unmount(mp, mntflags, td) 250 struct mount *mp; 251 int mntflags; 252 struct thread *td; 253{ 254 int error; 255 256 XVFS_UNMOUNT(MNTTOVFS(mp), 0, td->td_ucred, error); 257 return (error); 258} 259 260static int 261_xfs_root(mp, flags, vpp, td) 262 struct mount *mp; 263 int flags; 264 struct vnode **vpp; 265 struct thread *td; 266{ 267 xfs_vnode_t *vp; 268 int error; 269 270 XVFS_ROOT(MNTTOVFS(mp), &vp, error); 271 if (error == 0) { 272 *vpp = vp->v_vnode; 273 VOP_LOCK(*vpp, flags, curthread); 274 } 275 return (error); 276} 277 278static int 279_xfs_quotactl(mp, cmd, uid, arg, td) 280 struct mount *mp; 281 int cmd; 282 uid_t uid; 283 void *arg; 284 struct thread *td; 285{ 286 printf("xfs_quotactl\n"); 287 return EOPNOTSUPP; 288} 289 290static int 291_xfs_statfs(mp, sbp, td) 292 struct mount *mp; 293 struct statfs *sbp; 294 struct thread *td; 295{ 296 int error; 297 298 XVFS_STATVFS(MNTTOVFS(mp), sbp, NULL, error); 299 if (error) 300 return error; 301 302 /* Fix up the values XFS statvfs calls does not know about. */ 303 sbp->f_iosize = sbp->f_bsize; 304 305 return (error); 306} 307 308static int 309_xfs_sync(mp, waitfor, td) 310 struct mount *mp; 311 int waitfor; 312 struct thread *td; 313{ 314 int error; 315 int flags = SYNC_FSDATA|SYNC_ATTR|SYNC_REFCACHE; 316 317 if (waitfor == MNT_WAIT) 318 flags |= SYNC_WAIT; 319 else if (waitfor == MNT_LAZY) 320 flags |= SYNC_BDFLUSH; 321 XVFS_SYNC(MNTTOVFS(mp), flags, td->td_ucred, error); 322 return (error); 323} 324 325static int 326_xfs_vget(mp, ino, flags, vpp) 327 struct mount *mp; 328 ino_t ino; 329 int flags; 330 struct vnode **vpp; 331{ 332 xfs_vnode_t *vp; 333 int error; 334 335 printf("XVFS_GET_VNODE(MNTTOVFS(mp), &vp, ino, error);\n"); 336 error = ENOSYS; 337 if (error == 0) 338 *vpp = vp->v_vnode; 339 return (error); 340} 341 342static int 343_xfs_fhtovp(mp, fidp, vpp) 344 struct mount *mp; 345 struct fid *fidp; 346 struct vnode **vpp; 347{ 348 printf("xfs_fhtovp\n"); 349 return ENOSYS; 350} 351 352static int 353_xfs_vptofh(vp, fhp) 354 struct vnode *vp; 355 struct fid *fhp; 356{ 357 printf("xfs_vptofh"); 358 return ENOSYS; 359} 360 361static int 362_xfs_extattrctl(struct mount *mp, int cm, 363 struct vnode *filename_v, 364 int attrnamespace, const char *attrname, 365 struct thread *td) 366{ 367 printf("xfs_extattrctl\n"); 368 return ENOSYS; 369} 370 371int 372_xfs_init(vfsp) 373 struct vfsconf *vfsp; 374{ 375 int error; 376 377 error = init_xfs_fs(); 378 379 return (error); 380} 381 382int 383_xfs_uninit(vfsp) 384 struct vfsconf *vfsp; 385{ 386 exit_xfs_fs(); 387 return 0; 388} 389 390static struct vfsops xfs_fsops = { 391 .vfs_mount = _xfs_mount, 392 .vfs_unmount = _xfs_unmount, 393 .vfs_root = _xfs_root, 394 .vfs_quotactl = _xfs_quotactl, 395 .vfs_statfs = _xfs_statfs, 396 .vfs_sync = _xfs_sync, 397 .vfs_vget = _xfs_vget, 398 .vfs_fhtovp = _xfs_fhtovp, 399 .vfs_vptofh = _xfs_vptofh, 400 .vfs_init = _xfs_init, 401 .vfs_uninit = _xfs_uninit, 402 .vfs_extattrctl = _xfs_extattrctl, 403}; 404 405VFS_SET(xfs_fsops, xfs, 0); 406 407/* 408 * Copy GEOM VFS functions here to provide a conveniet place to 409 * track all XFS-related IO without being distracted by other 410 * filesystems which happen to be mounted on the machine at the 411 * same time. 412 */ 413 414static void 415xfs_geom_biodone(struct bio *bip) 416{ 417 struct buf *bp; 418 419 if (bip->bio_error) { 420 printf("g_vfs_done():"); 421 g_print_bio(bip); 422 printf("error = %d\n", bip->bio_error); 423 } 424 bp = bip->bio_caller2; 425 bp->b_error = bip->bio_error; 426 bp->b_ioflags = bip->bio_flags; 427 if (bip->bio_error) 428 bp->b_ioflags |= BIO_ERROR; 429 bp->b_resid = bp->b_bcount - bip->bio_completed; 430 g_destroy_bio(bip); 431 mtx_lock(&Giant); 432 bufdone(bp); 433 mtx_unlock(&Giant); 434} 435 436static void 437xfs_geom_strategy(struct bufobj *bo, struct buf *bp) 438{ 439 struct g_consumer *cp; 440 struct bio *bip; 441 442 cp = bo->bo_private; 443 G_VALID_CONSUMER(cp); 444 445 bip = g_alloc_bio(); 446 bip->bio_cmd = bp->b_iocmd; 447 bip->bio_offset = bp->b_iooffset; 448 bip->bio_data = bp->b_data; 449 bip->bio_done = xfs_geom_biodone; 450 bip->bio_caller2 = bp; 451 bip->bio_length = bp->b_bcount; 452 g_io_request(bip, cp); 453} 454 455static int 456xfs_geom_bufwrite(struct buf *bp) 457{ 458 return bufwrite(bp); 459} 460 461static int 462xfs_geom_bufsync(struct bufobj *bo, int waitfor, struct thread *td) 463{ 464 return bufsync(bo,waitfor,td); 465} 466 467struct buf_ops xfs_bo_ops = { 468 .bop_name = "XFS", 469 .bop_write = xfs_geom_bufwrite, 470 .bop_strategy = xfs_geom_strategy, 471 .bop_sync = xfs_geom_bufsync, 472}; 473