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