1/*
2 * Copyright (c) 2000-2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17 */
18#include "xfs.h"
19#include "xfs_fs.h"
20#include "xfs_inum.h"
21#include "xfs_log.h"
22#include "xfs_clnt.h"
23#include "xfs_trans.h"
24#include "xfs_sb.h"
25#include "xfs_ag.h"
26#include "xfs_dir.h"
27#include "xfs_dir2.h"
28#include "xfs_imap.h"
29#include "xfs_alloc.h"
30#include "xfs_dmapi.h"
31#include "xfs_mount.h"
32#include "xfs_quota.h"
33
34#include "xfs_mountops.h"
35
36int
37xvfs_mount(
38	struct bhv_desc		*bdp,
39	struct xfs_mount_args	*args,
40	struct cred		*cr)
41{
42	struct bhv_desc		*next = bdp;
43
44	ASSERT(next);
45	while (! (bhvtovfsops(next))->xvfs_mount)
46		next = BHV_NEXT(next);
47	return ((*bhvtovfsops(next)->xvfs_mount)(next, args, cr));
48}
49
50int
51xvfs_parseargs(
52	struct bhv_desc		*bdp,
53	char			*s,
54	struct xfs_mount_args	*args,
55	int			f)
56{
57	struct bhv_desc		*next = bdp;
58
59	ASSERT(next);
60	while (! (bhvtovfsops(next))->xvfs_parseargs)
61		next = BHV_NEXT(next);
62	return ((*bhvtovfsops(next)->xvfs_parseargs)(next, s, args, f));
63}
64
65int
66xvfs_showargs(
67	struct bhv_desc		*bdp,
68	struct sbuf		*m)
69{
70	struct bhv_desc		*next = bdp;
71
72	ASSERT(next);
73	while (! (bhvtovfsops(next))->xvfs_showargs)
74		next = BHV_NEXT(next);
75	return ((*bhvtovfsops(next)->xvfs_showargs)(next, m));
76}
77
78int
79xvfs_unmount(
80	struct bhv_desc		*bdp,
81	int			fl,
82	struct cred		*cr)
83{
84	struct bhv_desc		*next = bdp;
85
86	ASSERT(next);
87	while (! (bhvtovfsops(next))->xvfs_unmount)
88		next = BHV_NEXT(next);
89	return ((*bhvtovfsops(next)->xvfs_unmount)(next, fl, cr));
90}
91
92int
93xvfs_mntupdate(
94	struct bhv_desc		*bdp,
95	int			*fl,
96	struct xfs_mount_args	*args)
97{
98	struct bhv_desc		*next = bdp;
99
100	ASSERT(next);
101	while (! (bhvtovfsops(next))->xvfs_mntupdate)
102		next = BHV_NEXT(next);
103	return ((*bhvtovfsops(next)->xvfs_mntupdate)(next, fl, args));
104}
105
106int
107xvfs_root(
108	struct bhv_desc		*bdp,
109	struct xfs_vnode	**vpp)
110{
111	struct bhv_desc		*next = bdp;
112
113	ASSERT(next);
114	while (! (bhvtovfsops(next))->xvfs_root)
115		next = BHV_NEXT(next);
116	return ((*bhvtovfsops(next)->xvfs_root)(next, vpp));
117}
118
119int
120xvfs_statvfs(
121	struct bhv_desc		*bdp,
122	struct statfs		*sp,
123	struct xfs_vnode	*vp)
124{
125	struct bhv_desc		*next = bdp;
126
127	ASSERT(next);
128	while (! (bhvtovfsops(next))->xvfs_statvfs)
129		next = BHV_NEXT(next);
130	return ((*bhvtovfsops(next)->xvfs_statvfs)(next, sp, vp));
131}
132
133int
134xvfs_sync(
135	struct bhv_desc		*bdp,
136	int			fl,
137	struct cred		*cr)
138{
139	struct bhv_desc		*next = bdp;
140
141	ASSERT(next);
142	while (! (bhvtovfsops(next))->xvfs_sync)
143		next = BHV_NEXT(next);
144	return ((*bhvtovfsops(next)->xvfs_sync)(next, fl, cr));
145}
146
147int
148xvfs_vget(
149	struct bhv_desc		*bdp,
150	struct xfs_vnode	**vpp,
151	struct fid		*fidp)
152{
153	struct bhv_desc		*next = bdp;
154
155	ASSERT(next);
156	while (! (bhvtovfsops(next))->xvfs_vget)
157		next = BHV_NEXT(next);
158	return ((*bhvtovfsops(next)->xvfs_vget)(next, vpp, fidp));
159}
160
161int
162xvfs_dmapiops(
163	struct bhv_desc		*bdp,
164	caddr_t			addr)
165{
166	struct bhv_desc		*next = bdp;
167
168	ASSERT(next);
169	while (! (bhvtovfsops(next))->xvfs_dmapiops)
170		next = BHV_NEXT(next);
171	return ((*bhvtovfsops(next)->xvfs_dmapiops)(next, addr));
172}
173
174int
175xvfs_quotactl(
176	struct bhv_desc		*bdp,
177	int			cmd,
178	int			id,
179	caddr_t			addr)
180{
181	struct bhv_desc		*next = bdp;
182
183	ASSERT(next);
184	while (! (bhvtovfsops(next))->xvfs_quotactl)
185		next = BHV_NEXT(next);
186	return ((*bhvtovfsops(next)->xvfs_quotactl)(next, cmd, id, addr));
187}
188
189struct inode *
190xvfs_get_inode(
191	struct bhv_desc		*bdp,
192	xfs_ino_t		ino,
193	int			fl)
194{
195	struct bhv_desc		*next = bdp;
196
197	while (! (bhvtovfsops(next))->xvfs_get_inode)
198		next = BHV_NEXTNULL(next);
199	return ((*bhvtovfsops(next)->xvfs_get_inode)(next, ino, fl));
200}
201
202void
203xvfs_init_vnode(
204	struct bhv_desc		*bdp,
205	struct xfs_vnode	*vp,
206	struct bhv_desc		*bp,
207	int			unlock)
208{
209	struct bhv_desc		*next = bdp;
210
211	ASSERT(next);
212	while (! (bhvtovfsops(next))->xvfs_init_vnode)
213		next = BHV_NEXT(next);
214	((*bhvtovfsops(next)->xvfs_init_vnode)(next, vp, bp, unlock));
215}
216
217void
218xvfs_force_shutdown(
219	struct bhv_desc		*bdp,
220	int			fl,
221	char			*file,
222	int			line)
223{
224	struct bhv_desc		*next = bdp;
225
226	ASSERT(next);
227	while (! (bhvtovfsops(next))->xvfs_force_shutdown)
228		next = BHV_NEXT(next);
229	((*bhvtovfsops(next)->xvfs_force_shutdown)(next, fl, file, line));
230}
231
232xfs_vfs_t *
233vfs_allocate(struct mount *mp)
234{
235	struct xfs_vfs	 *vfsp;
236	struct xfsmount  *xmp;
237
238	xmp  = kmem_zalloc(sizeof(*xmp), KM_SLEEP);
239	vfsp = XFSTOVFS(xmp);
240
241	bhv_head_init(VFS_BHVHEAD(vfsp), "vfs");
242
243	xmp->m_mp = mp;
244	mp->mnt_data = xmp;
245	vfsp->vfs_mp = mp;
246
247	return vfsp;
248}
249
250void
251vfs_deallocate(
252	struct xfs_vfs		*vfsp)
253{
254	struct xfsmount *xmp;
255
256	bhv_head_destroy(VFS_BHVHEAD(vfsp));
257
258	xmp = VFSTOXFS(vfsp);
259	kmem_free(xmp, sizeof(*xmp));
260}
261
262/*
263 * Allocate and initialize a new XFS mount structure
264 */
265struct xfsmount *
266xfsmount_allocate(struct mount *mp)
267{
268	xfs_vfs_t	*vfsp;
269
270	vfsp = vfs_allocate(mp);
271
272	ASSERT(vfsp);
273
274	if (mp->mnt_flag & MNT_RDONLY)
275		vfsp->vfs_flag |= VFS_RDONLY;
276
277	bhv_insert_all_vfsops(vfsp);
278	return (VFSTOXFS(vfsp));
279}
280
281void
282xfsmount_deallocate(struct xfsmount *xmp)
283{
284	xfs_vfs_t	*vfsp;
285
286	vfsp = XFSTOVFS(xmp);
287	bhv_remove_all_vfsops(vfsp, 1);
288	vfs_deallocate(vfsp);
289}
290
291
292void
293vfs_insertops(
294	struct xfs_vfs		*vfsp,
295	struct bhv_vfsops	*vfsops)
296{
297	struct bhv_desc		*bdp;
298
299	bdp = kmem_alloc(sizeof(struct bhv_desc), KM_SLEEP);
300	bhv_desc_init(bdp, NULL, vfsp, vfsops);
301	bhv_insert(&vfsp->vfs_bh, bdp);
302}
303
304void
305vfs_insertbhv(
306	struct xfs_vfs		*vfsp,
307	struct bhv_desc		*bdp,
308	struct xvfsops		*vfsops,
309	void			*mount)
310{
311	bhv_desc_init(bdp, mount, vfsp, vfsops);
312	bhv_insert_initial(&vfsp->vfs_bh, bdp);
313}
314
315void
316bhv_remove_vfsops(
317	struct xfs_vfs		*vfsp,
318	int			pos)
319{
320	struct bhv_desc		*bhv;
321
322	bhv = bhv_lookup_range(&vfsp->vfs_bh, pos, pos);
323	if (bhv) {
324		bhv_remove(&vfsp->vfs_bh, bhv);
325		kmem_free(bhv, sizeof(*bhv));
326	}
327}
328
329void
330bhv_remove_all_vfsops(
331	struct xfs_vfs		*vfsp,
332	int			freebase)
333{
334	struct xfs_mount	*mp;
335
336	bhv_remove_vfsops(vfsp, VFS_POSITION_QM);
337	bhv_remove_vfsops(vfsp, VFS_POSITION_DM);
338	bhv_remove_vfsops(vfsp, VFS_POSITION_IO);
339	if (!freebase)
340		return;
341	mp = XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfsp), &xfs_vfsops));
342	VFS_REMOVEBHV(vfsp, &mp->m_bhv);
343	xfs_mount_free(mp, 0);
344}
345
346void
347bhv_insert_all_vfsops(
348	struct xfs_vfs		*vfsp)
349{
350	struct xfs_mount	*mp;
351
352	mp = xfs_mount_init();
353	vfs_insertbhv(vfsp, &mp->m_bhv, &xfs_vfsops, mp);
354        vfs_insertdmapi(vfsp);
355        vfs_insertquota(vfsp);
356}
357