]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/gnu/fs/xfs/FreeBSD/xfs_mountops.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.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
203         xmp = xfsmount_allocate(mp);
204         if (xmp == NULL)
205                 return (ENOMEM);
206
207         if((error = _xfs_param_copyin(mp, td)) != 0)
208                 goto fail;
209
210         curcred = td->td_ucred;
211         XVFS_MOUNT(XFSTOVFS(xmp), &xmp->m_args, curcred, error);
212         if (error)
213                 goto fail;
214
215         XVFS_ROOT(XFSTOVFS(xmp), &rootvp, error);
216         ddev = XFS_VFSTOM(XFSTOVFS(xmp))->m_ddev_targp->dev;
217         devvp = XFS_VFSTOM(XFSTOVFS(xmp))->m_ddev_targp->specvp;
218         if (error)
219                 goto fail_unmount;
220
221         if (ddev->si_iosize_max != 0)
222                 mp->mnt_iosize_max = ddev->si_iosize_max;
223         if (mp->mnt_iosize_max > MAXPHYS)
224                 mp->mnt_iosize_max = MAXPHYS;
225
226         mp->mnt_flag |= MNT_LOCAL;
227         mp->mnt_stat.f_fsid.val[0] = dev2udev(ddev);
228         mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
229
230         if ((error = VFS_STATFS(mp, &mp->mnt_stat, td)) != 0)
231                 goto fail_unmount;
232
233         rvp = rootvp->v_vnode;
234         rvp->v_vflag |= VV_ROOT;
235         VN_RELE(rootvp);
236
237         return (0);
238
239  fail_unmount:
240         XVFS_UNMOUNT(XFSTOVFS(xmp), 0, curcred, error);
241
242         if (devvp != NULL) {
243                 cp = devvp->v_bufobj.bo_private;
244                 if (cp != NULL) {
245                         DROP_GIANT();
246                         g_topology_lock();
247                         g_vfs_close(cp, td);
248                         g_topology_unlock();
249                         PICKUP_GIANT();
250                 }
251         }
252
253  fail:
254         if (xmp != NULL)
255                 xfsmount_deallocate(xmp);
256
257         return (error);
258 }
259
260 /*
261  * Free reference to null layer
262  */
263 static int
264 _xfs_unmount(mp, mntflags, td)
265         struct mount *mp;
266         int mntflags;
267         struct thread *td;
268 {
269         struct vnode *devvp;
270         struct g_consumer *cp;
271         int error;
272         cp = NULL;
273         devvp = NULL;
274
275         devvp = XFS_VFSTOM((MNTTOVFS(mp)))->m_ddev_targp->specvp;
276         if (devvp != NULL)
277                 cp = devvp->v_bufobj.bo_private;
278
279         XVFS_UNMOUNT(MNTTOVFS(mp), 0, td->td_ucred, error);
280         if (error == 0) {
281                 if (cp != NULL) {
282                         DROP_GIANT();
283                         g_topology_lock();
284                         g_vfs_close(cp, td);
285                         g_topology_unlock();
286                         PICKUP_GIANT();
287                 }
288         }
289         return (error);
290 }
291
292 static int
293 _xfs_root(mp, flags, vpp, td)
294         struct mount *mp;
295         int flags;
296         struct vnode **vpp;
297         struct thread *td;
298 {
299         xfs_vnode_t *vp;
300         int error;
301
302         XVFS_ROOT(MNTTOVFS(mp), &vp, error);
303         if (error == 0) {
304                 *vpp = vp->v_vnode;
305                 VOP_LOCK(*vpp, flags, curthread);
306         }
307         return (error);
308 }
309
310 static int
311 _xfs_quotactl(mp, cmd, uid, arg, td)
312         struct mount *mp;
313         int cmd;
314         uid_t uid;
315         void *arg;
316         struct thread *td;
317 {
318         printf("xfs_quotactl\n");
319         return EOPNOTSUPP;
320 }
321
322 static int
323 _xfs_statfs(mp, sbp, td)
324         struct mount *mp;
325         struct statfs *sbp;
326         struct thread *td;
327 {
328         int error;
329
330         XVFS_STATVFS(MNTTOVFS(mp), sbp, NULL, error);
331         if (error)
332                 return error;
333
334         /* Fix up the values XFS statvfs calls does not know about. */
335         sbp->f_iosize = sbp->f_bsize;
336
337         return (error);
338 }
339
340 static int
341 _xfs_sync(mp, waitfor, td)
342         struct mount *mp;
343         int waitfor;
344         struct thread *td;
345 {
346         int error;
347         int flags = SYNC_FSDATA|SYNC_ATTR|SYNC_REFCACHE;
348
349         if (waitfor == MNT_WAIT)
350                 flags |= SYNC_WAIT;
351         else if (waitfor == MNT_LAZY)
352                 flags |= SYNC_BDFLUSH;
353         XVFS_SYNC(MNTTOVFS(mp), flags, td->td_ucred, error);
354         return (error);
355 }
356
357 static int
358 _xfs_vget(mp, ino, flags, vpp)
359         struct mount *mp;
360         ino_t ino;
361         int flags;
362         struct vnode **vpp;
363 {
364         xfs_vnode_t *vp = NULL;
365         int error;
366
367         printf("XVFS_GET_VNODE(MNTTOVFS(mp), &vp, ino, error);\n");
368         error = ENOSYS;
369         if (error == 0)
370                 *vpp = vp->v_vnode;
371         return (error);
372 }
373
374 static int
375 _xfs_fhtovp(mp, fidp, vpp)
376         struct mount *mp;
377         struct fid *fidp;
378         struct vnode **vpp;
379 {
380         printf("xfs_fhtovp\n");
381         return ENOSYS;
382 }
383
384 static int
385 _xfs_extattrctl(struct mount *mp, int cm,
386                 struct vnode *filename_v,
387                 int attrnamespace, const char *attrname,
388                 struct thread *td)
389 {
390         printf("xfs_extattrctl\n");
391         return ENOSYS;
392 }
393
394 int
395 _xfs_init(vfsp)
396         struct vfsconf *vfsp;
397 {
398         int error;
399
400         error = init_xfs_fs();
401
402         return (error);
403 }
404
405 int
406 _xfs_uninit(vfsp)
407         struct vfsconf *vfsp;
408 {
409         exit_xfs_fs();
410         return 0;
411 }
412
413 static struct vfsops xfs_fsops = {
414         .vfs_mount =    _xfs_mount,
415         .vfs_unmount =  _xfs_unmount,
416         .vfs_root =     _xfs_root,
417         .vfs_quotactl = _xfs_quotactl,
418         .vfs_statfs =   _xfs_statfs,
419         .vfs_sync =     _xfs_sync,
420         .vfs_vget =     _xfs_vget,
421         .vfs_fhtovp =   _xfs_fhtovp,
422         .vfs_init =     _xfs_init,
423         .vfs_uninit =   _xfs_uninit,
424         .vfs_extattrctl = _xfs_extattrctl,
425 };
426
427 VFS_SET(xfs_fsops, xfs, 0);
428
429 /*
430  *  Copy GEOM VFS functions here to provide a conveniet place to
431  *  track all XFS-related IO without being distracted by other
432  *  filesystems which happen to be mounted on the machine at the
433  *  same time.
434  */
435
436 static void
437 xfs_geom_biodone(struct bio *bip)
438 {
439         struct buf *bp;
440
441         if (bip->bio_error) {
442                 printf("g_vfs_done():");
443                 g_print_bio(bip);
444                 printf("error = %d\n", bip->bio_error);
445         }
446         bp = bip->bio_caller2;
447         bp->b_error = bip->bio_error;
448         bp->b_ioflags = bip->bio_flags;
449         if (bip->bio_error)
450                 bp->b_ioflags |= BIO_ERROR;
451         bp->b_resid = bp->b_bcount - bip->bio_completed;
452         g_destroy_bio(bip);
453         mtx_lock(&Giant);
454         bufdone(bp);
455         mtx_unlock(&Giant);
456 }
457
458 static void
459 xfs_geom_strategy(struct bufobj *bo, struct buf *bp)
460 {
461         struct g_consumer *cp;
462         struct bio *bip;
463
464         cp = bo->bo_private;
465         G_VALID_CONSUMER(cp);
466
467         bip = g_alloc_bio();
468         bip->bio_cmd = bp->b_iocmd;
469         bip->bio_offset = bp->b_iooffset;
470         bip->bio_data = bp->b_data;
471         bip->bio_done = xfs_geom_biodone;
472         bip->bio_caller2 = bp;
473         bip->bio_length = bp->b_bcount;
474         g_io_request(bip, cp);
475 }
476
477 static int
478 xfs_geom_bufwrite(struct buf *bp)
479 {
480         return bufwrite(bp);
481 }
482
483 static int
484 xfs_geom_bufsync(struct bufobj *bo, int waitfor, struct thread *td)
485 {
486         return bufsync(bo,waitfor,td);
487 }
488
489 static void
490 xfs_geom_bufbdflush(struct bufobj *bo, struct buf *bp)
491 {
492         bufbdflush(bo, bp);
493 }
494
495 struct buf_ops xfs_bo_ops = {
496         .bop_name =     "XFS",
497         .bop_write =    xfs_geom_bufwrite,
498         .bop_strategy = xfs_geom_strategy,
499         .bop_sync =     xfs_geom_bufsync,
500         .bop_bdflush =  xfs_geom_bufbdflush,
501 };