]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/gnu/fs/xfs/FreeBSD/xfs_mountops.c
add -n option to suppress clearing the build tree and add -DNO_CLEAN
[FreeBSD/FreeBSD.git] / sys / gnu / fs / xfs / FreeBSD / xfs_mountops.c
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$
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
74 MALLOC_DEFINE(M_XFSNODE, "XFS node", "XFS vnode private part");
75
76 static vfs_mount_t      _xfs_mount;
77 static vfs_unmount_t    _xfs_unmount;
78 static vfs_root_t       _xfs_root;
79 static vfs_quotactl_t   _xfs_quotactl;
80 static vfs_statfs_t     _xfs_statfs;
81 static vfs_sync_t       _xfs_sync;
82 static vfs_vget_t       _xfs_vget;
83 static vfs_fhtovp_t     _xfs_fhtovp;
84 static vfs_init_t       _xfs_init;
85 static vfs_uninit_t     _xfs_uninit;
86 static vfs_extattrctl_t _xfs_extattrctl;
87
88 static b_strategy_t     xfs_geom_strategy;
89
90 static const char *xfs_opts[] =
91         { "from", "flags", "logbufs", "logbufsize",
92           "rtname", "logname", "iosizelog", "sunit",
93           "swidth", "export",
94           NULL };
95
96 static void
97 parse_int(struct mount *mp, const char *opt, int *val, int *error)
98 {
99         char *tmp, *ep;
100
101         tmp = vfs_getopts(mp->mnt_optnew, opt, error);
102         if (*error != 0) {
103                 return;
104         }
105         if (tmp != NULL) {
106                 *val = (int)strtol(tmp, &ep, 10);
107                 if (*ep) {
108                         *error = EINVAL;
109                         return;
110                 }
111         }
112 }
113
114 static int
115 _xfs_param_copyin(struct mount *mp, struct thread *td)
116 {
117         struct xfsmount *xmp = MNTTOXFS(mp);
118         struct xfs_mount_args *args = &xmp->m_args;
119         char *path;
120         char *fsname;
121         char *rtname;
122         char *logname;
123         int error;
124
125         path = vfs_getopts(mp->mnt_optnew, "fspath", &error);
126         if  (error)
127                 return (error);
128
129         bzero(args, sizeof(struct xfs_mount_args));
130         args->logbufs = -1;
131         args->logbufsize = -1;
132
133         parse_int(mp, "flags", &args->flags, &error);
134         if (error != 0 && error != ENOENT)
135                 return error;
136
137         args->flags |= XFSMNT_32BITINODES;
138
139         parse_int(mp, "sunit", &args->sunit, &error);
140         if (error != 0 && error != ENOENT)
141                 return error;
142
143         parse_int(mp, "swidth", &args->swidth, &error);
144         if (error != 0 && error != ENOENT)
145                 return error;
146
147         parse_int(mp, "logbufs", &args->logbufs, &error);
148         if (error != 0 && error != ENOENT)
149                 return error;
150
151         parse_int(mp, "logbufsize", &args->logbufsize, &error);
152         if (error != 0 && error != ENOENT)
153                 return error;
154
155         fsname = vfs_getopts(mp->mnt_optnew, "from", &error);
156         if (error == 0 && fsname != NULL) {
157                 strncpy(args->fsname, fsname, sizeof(args->fsname) - 1);
158         }
159
160         logname = vfs_getopts(mp->mnt_optnew, "logname", &error);
161         if (error == 0 && logname != NULL) {
162                 strncpy(args->logname, logname, sizeof(args->logname) - 1);
163         }
164
165         rtname = vfs_getopts(mp->mnt_optnew, "rtname", &error);
166         if (error == 0 && rtname != NULL) {
167                 strncpy(args->rtname, rtname, sizeof(args->rtname) - 1);
168         }
169
170         strncpy(args->mtpt, path, sizeof(args->mtpt));
171
172         printf("fsname '%s' logname '%s' rtname '%s'\n"
173                "flags 0x%x sunit %d swidth %d logbufs %d logbufsize %d\n",
174                args->fsname, args->logname, args->rtname, args->flags,
175                args->sunit, args->swidth, args->logbufs, args->logbufsize);
176
177         vfs_mountedfrom(mp, args->fsname);
178
179         return (0);
180 }
181
182 static int
183 _xfs_mount(struct mount         *mp,
184            struct thread        *td)
185 {
186         struct xfsmount         *xmp;
187         struct xfs_vnode        *rootvp;
188         struct ucred            *curcred;
189         struct vnode            *rvp, *devvp;
190         struct cdev             *ddev;
191         struct g_consumer       *cp;
192         int                     error;
193         
194         ddev = NULL;
195         cp = NULL;
196
197         if (vfs_filteropt(mp->mnt_optnew, xfs_opts))
198                 return (EINVAL);
199
200         if (mp->mnt_flag & MNT_UPDATE)
201                 return (0);
202         if ((mp->mnt_flag & MNT_RDONLY) == 0)
203                 return (EPERM);
204
205         xmp = xfsmount_allocate(mp);
206         if (xmp == NULL)
207                 return (ENOMEM);
208
209         if((error = _xfs_param_copyin(mp, td)) != 0)
210                 goto fail;
211
212         curcred = td->td_ucred;
213         XVFS_MOUNT(XFSTOVFS(xmp), &xmp->m_args, curcred, error);
214         if (error)
215                 goto fail;
216
217         XVFS_ROOT(XFSTOVFS(xmp), &rootvp, error);
218         ddev = XFS_VFSTOM(XFSTOVFS(xmp))->m_ddev_targp->dev;
219         devvp = XFS_VFSTOM(XFSTOVFS(xmp))->m_ddev_targp->specvp;
220         if (error)
221                 goto fail_unmount;
222
223         if (ddev->si_iosize_max != 0)
224                 mp->mnt_iosize_max = ddev->si_iosize_max;
225         if (mp->mnt_iosize_max > MAXPHYS)
226                 mp->mnt_iosize_max = MAXPHYS;
227
228         mp->mnt_flag |= MNT_LOCAL;
229         mp->mnt_stat.f_fsid.val[0] = dev2udev(ddev);
230         mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
231
232         if ((error = VFS_STATFS(mp, &mp->mnt_stat, td)) != 0)
233                 goto fail_unmount;
234
235         rvp = rootvp->v_vnode;
236         rvp->v_vflag |= VV_ROOT;
237         VN_RELE(rootvp);
238
239         return (0);
240
241  fail_unmount:
242         XVFS_UNMOUNT(XFSTOVFS(xmp), 0, curcred, error);
243
244         if (devvp != NULL) {
245                 cp = devvp->v_bufobj.bo_private;
246                 if (cp != NULL) {
247                         DROP_GIANT();
248                         g_topology_lock();
249                         g_vfs_close(cp);
250                         g_topology_unlock();
251                         PICKUP_GIANT();
252                 }
253         }
254
255  fail:
256         if (xmp != NULL)
257                 xfsmount_deallocate(xmp);
258
259         return (error);
260 }
261
262 /*
263  * Free reference to null layer
264  */
265 static int
266 _xfs_unmount(mp, mntflags, td)
267         struct mount *mp;
268         int mntflags;
269         struct thread *td;
270 {
271         struct vnode *devvp;
272         struct g_consumer *cp;
273         int error;
274         cp = NULL;
275         devvp = NULL;
276
277         devvp = XFS_VFSTOM((MNTTOVFS(mp)))->m_ddev_targp->specvp;
278         if (devvp != NULL)
279                 cp = devvp->v_bufobj.bo_private;
280
281         XVFS_UNMOUNT(MNTTOVFS(mp), 0, td->td_ucred, error);
282         if (error == 0) {
283                 if (cp != NULL) {
284                         DROP_GIANT();
285                         g_topology_lock();
286                         g_vfs_close(cp);
287                         g_topology_unlock();
288                         PICKUP_GIANT();
289                 }
290         }
291         return (error);
292 }
293
294 static int
295 _xfs_root(mp, flags, vpp, td)
296         struct mount *mp;
297         int flags;
298         struct vnode **vpp;
299         struct thread *td;
300 {
301         xfs_vnode_t *vp;
302         int error;
303
304         XVFS_ROOT(MNTTOVFS(mp), &vp, error);
305         if (error == 0) {
306                 *vpp = vp->v_vnode;
307                 VOP_LOCK(*vpp, flags);
308         }
309         return (error);
310 }
311
312 static int
313 _xfs_quotactl(mp, cmd, uid, arg, td)
314         struct mount *mp;
315         int cmd;
316         uid_t uid;
317         void *arg;
318         struct thread *td;
319 {
320         printf("xfs_quotactl\n");
321         return EOPNOTSUPP;
322 }
323
324 static int
325 _xfs_statfs(mp, sbp, td)
326         struct mount *mp;
327         struct statfs *sbp;
328         struct thread *td;
329 {
330         int error;
331
332         XVFS_STATVFS(MNTTOVFS(mp), sbp, NULL, error);
333         if (error)
334                 return error;
335
336         /* Fix up the values XFS statvfs calls does not know about. */
337         sbp->f_iosize = sbp->f_bsize;
338
339         return (error);
340 }
341
342 static int
343 _xfs_sync(mp, waitfor, td)
344         struct mount *mp;
345         int waitfor;
346         struct thread *td;
347 {
348         int error;
349         int flags = SYNC_FSDATA|SYNC_ATTR|SYNC_REFCACHE;
350
351         if (waitfor == MNT_WAIT)
352                 flags |= SYNC_WAIT;
353         else if (waitfor == MNT_LAZY)
354                 flags |= SYNC_BDFLUSH;
355         XVFS_SYNC(MNTTOVFS(mp), flags, td->td_ucred, error);
356         return (error);
357 }
358
359 static int
360 _xfs_vget(mp, ino, flags, vpp)
361         struct mount *mp;
362         ino_t ino;
363         int flags;
364         struct vnode **vpp;
365 {
366         xfs_vnode_t *vp = NULL;
367         int error;
368
369         printf("XVFS_GET_VNODE(MNTTOVFS(mp), &vp, ino, error);\n");
370         error = ENOSYS;
371         if (error == 0)
372                 *vpp = vp->v_vnode;
373         return (error);
374 }
375
376 static int
377 _xfs_fhtovp(mp, fidp, vpp)
378         struct mount *mp;
379         struct fid *fidp;
380         struct vnode **vpp;
381 {
382         printf("xfs_fhtovp\n");
383         return ENOSYS;
384 }
385
386 static int
387 _xfs_extattrctl(struct mount *mp, int cm,
388                 struct vnode *filename_v,
389                 int attrnamespace, const char *attrname,
390                 struct thread *td)
391 {
392         printf("xfs_extattrctl\n");
393         return ENOSYS;
394 }
395
396 int
397 _xfs_init(vfsp)
398         struct vfsconf *vfsp;
399 {
400         int error;
401
402         error = init_xfs_fs();
403
404         return (error);
405 }
406
407 int
408 _xfs_uninit(vfsp)
409         struct vfsconf *vfsp;
410 {
411         exit_xfs_fs();
412         return 0;
413 }
414
415 static struct vfsops xfs_fsops = {
416         .vfs_mount =    _xfs_mount,
417         .vfs_unmount =  _xfs_unmount,
418         .vfs_root =     _xfs_root,
419         .vfs_quotactl = _xfs_quotactl,
420         .vfs_statfs =   _xfs_statfs,
421         .vfs_sync =     _xfs_sync,
422         .vfs_vget =     _xfs_vget,
423         .vfs_fhtovp =   _xfs_fhtovp,
424         .vfs_init =     _xfs_init,
425         .vfs_uninit =   _xfs_uninit,
426         .vfs_extattrctl = _xfs_extattrctl,
427 };
428
429 VFS_SET(xfs_fsops, xfs, 0);
430
431 /*
432  *  Copy GEOM VFS functions here to provide a conveniet place to
433  *  track all XFS-related IO without being distracted by other
434  *  filesystems which happen to be mounted on the machine at the
435  *  same time.
436  */
437
438 static void
439 xfs_geom_biodone(struct bio *bip)
440 {
441         struct buf *bp;
442
443         if (bip->bio_error) {
444                 printf("g_vfs_done():");
445                 g_print_bio(bip);
446                 printf("error = %d\n", bip->bio_error);
447         }
448         bp = bip->bio_caller2;
449         bp->b_error = bip->bio_error;
450         bp->b_ioflags = bip->bio_flags;
451         if (bip->bio_error)
452                 bp->b_ioflags |= BIO_ERROR;
453         bp->b_resid = bp->b_bcount - bip->bio_completed;
454         g_destroy_bio(bip);
455         mtx_lock(&Giant);
456         bufdone(bp);
457         mtx_unlock(&Giant);
458 }
459
460 static void
461 xfs_geom_strategy(struct bufobj *bo, struct buf *bp)
462 {
463         struct g_consumer *cp;
464         struct bio *bip;
465
466         cp = bo->bo_private;
467         G_VALID_CONSUMER(cp);
468
469         bip = g_alloc_bio();
470         bip->bio_cmd = bp->b_iocmd;
471         bip->bio_offset = bp->b_iooffset;
472         bip->bio_data = bp->b_data;
473         bip->bio_done = xfs_geom_biodone;
474         bip->bio_caller2 = bp;
475         bip->bio_length = bp->b_bcount;
476         g_io_request(bip, cp);
477 }
478
479 static int
480 xfs_geom_bufwrite(struct buf *bp)
481 {
482         return bufwrite(bp);
483 }
484
485 static int
486 xfs_geom_bufsync(struct bufobj *bo, int waitfor)
487 {
488
489         return (bufsync(bo, waitfor));
490 }
491
492 static void
493 xfs_geom_bufbdflush(struct bufobj *bo, struct buf *bp)
494 {
495         bufbdflush(bo, bp);
496 }
497
498 struct buf_ops xfs_bo_ops = {
499         .bop_name =     "XFS",
500         .bop_write =    xfs_geom_bufwrite,
501         .bop_strategy = xfs_geom_strategy,
502         .bop_sync =     xfs_geom_bufsync,
503         .bop_bdflush =  xfs_geom_bufbdflush,
504 };