blob: 07779c5ab42f4726ef430c7772e0a0ef79c64c96 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * XFS filesystem operations.
3 *
4 * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of version 2 of the GNU General Public License as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it would be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 *
14 * Further, this software is distributed without any warranty that it is
15 * free of the rightful claim of any third person regarding infringement
16 * or the like. Any license provided herein, whether implied or
17 * otherwise, applies only to this software file. Patent licenses, if
18 * any, provided herein do not apply to combinations of this program with
19 * other software, or any other product whatsoever.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write the Free Software Foundation, Inc., 59
23 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
24 *
25 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
26 * Mountain View, CA 94043, or:
27 *
28 * http://www.sgi.com
29 *
30 * For further information regarding this notice, see:
31 *
32 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
33 */
34
35#include "xfs.h"
36#include "xfs_macros.h"
37#include "xfs_types.h"
38#include "xfs_inum.h"
39#include "xfs_log.h"
40#include "xfs_trans.h"
41#include "xfs_sb.h"
42#include "xfs_dir.h"
43#include "xfs_dir2.h"
44#include "xfs_dmapi.h"
45#include "xfs_mount.h"
46#include "xfs_bmap_btree.h"
47#include "xfs_ialloc_btree.h"
48#include "xfs_alloc_btree.h"
49#include "xfs_btree.h"
50#include "xfs_alloc.h"
51#include "xfs_ialloc.h"
52#include "xfs_attr_sf.h"
53#include "xfs_dir_sf.h"
54#include "xfs_dir2_sf.h"
55#include "xfs_dinode.h"
56#include "xfs_inode_item.h"
57#include "xfs_inode.h"
58#include "xfs_ag.h"
59#include "xfs_error.h"
60#include "xfs_bmap.h"
61#include "xfs_da_btree.h"
62#include "xfs_rw.h"
63#include "xfs_refcache.h"
64#include "xfs_buf_item.h"
65#include "xfs_extfree_item.h"
66#include "xfs_quota.h"
67#include "xfs_dir2_trace.h"
68#include "xfs_acl.h"
69#include "xfs_attr.h"
70#include "xfs_clnt.h"
71#include "xfs_log_priv.h"
72
73STATIC int xfs_sync(bhv_desc_t *, int, cred_t *);
74
75int
76xfs_init(void)
77{
78 extern kmem_zone_t *xfs_bmap_free_item_zone;
79 extern kmem_zone_t *xfs_btree_cur_zone;
80 extern kmem_zone_t *xfs_trans_zone;
81 extern kmem_zone_t *xfs_buf_item_zone;
82 extern kmem_zone_t *xfs_dabuf_zone;
83#ifdef XFS_DABUF_DEBUG
84 extern lock_t xfs_dabuf_global_lock;
85 spinlock_init(&xfs_dabuf_global_lock, "xfsda");
86#endif
87
88 /*
89 * Initialize all of the zone allocators we use.
90 */
91 xfs_bmap_free_item_zone = kmem_zone_init(sizeof(xfs_bmap_free_item_t),
92 "xfs_bmap_free_item");
93 xfs_btree_cur_zone = kmem_zone_init(sizeof(xfs_btree_cur_t),
94 "xfs_btree_cur");
95 xfs_inode_zone = kmem_zone_init(sizeof(xfs_inode_t), "xfs_inode");
96 xfs_trans_zone = kmem_zone_init(sizeof(xfs_trans_t), "xfs_trans");
97 xfs_da_state_zone =
98 kmem_zone_init(sizeof(xfs_da_state_t), "xfs_da_state");
99 xfs_dabuf_zone = kmem_zone_init(sizeof(xfs_dabuf_t), "xfs_dabuf");
100
101 /*
102 * The size of the zone allocated buf log item is the maximum
103 * size possible under XFS. This wastes a little bit of memory,
104 * but it is much faster.
105 */
106 xfs_buf_item_zone =
107 kmem_zone_init((sizeof(xfs_buf_log_item_t) +
108 (((XFS_MAX_BLOCKSIZE / XFS_BLI_CHUNK) /
109 NBWORD) * sizeof(int))),
110 "xfs_buf_item");
111 xfs_efd_zone = kmem_zone_init((sizeof(xfs_efd_log_item_t) +
112 ((XFS_EFD_MAX_FAST_EXTENTS - 1) * sizeof(xfs_extent_t))),
113 "xfs_efd_item");
114 xfs_efi_zone = kmem_zone_init((sizeof(xfs_efi_log_item_t) +
115 ((XFS_EFI_MAX_FAST_EXTENTS - 1) * sizeof(xfs_extent_t))),
116 "xfs_efi_item");
117 xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork");
118 xfs_ili_zone = kmem_zone_init(sizeof(xfs_inode_log_item_t), "xfs_ili");
119 xfs_chashlist_zone = kmem_zone_init(sizeof(xfs_chashlist_t),
120 "xfs_chashlist");
121 xfs_acl_zone_init(xfs_acl_zone, "xfs_acl");
122
123 /*
124 * Allocate global trace buffers.
125 */
126#ifdef XFS_ALLOC_TRACE
127 xfs_alloc_trace_buf = ktrace_alloc(XFS_ALLOC_TRACE_SIZE, KM_SLEEP);
128#endif
129#ifdef XFS_BMAP_TRACE
130 xfs_bmap_trace_buf = ktrace_alloc(XFS_BMAP_TRACE_SIZE, KM_SLEEP);
131#endif
132#ifdef XFS_BMBT_TRACE
133 xfs_bmbt_trace_buf = ktrace_alloc(XFS_BMBT_TRACE_SIZE, KM_SLEEP);
134#endif
135#ifdef XFS_DIR_TRACE
136 xfs_dir_trace_buf = ktrace_alloc(XFS_DIR_TRACE_SIZE, KM_SLEEP);
137#endif
138#ifdef XFS_ATTR_TRACE
139 xfs_attr_trace_buf = ktrace_alloc(XFS_ATTR_TRACE_SIZE, KM_SLEEP);
140#endif
141#ifdef XFS_DIR2_TRACE
142 xfs_dir2_trace_buf = ktrace_alloc(XFS_DIR2_GTRACE_SIZE, KM_SLEEP);
143#endif
144
145 xfs_dir_startup();
146
147#if (defined(DEBUG) || defined(INDUCE_IO_ERROR))
148 xfs_error_test_init();
149#endif /* DEBUG || INDUCE_IO_ERROR */
150
151 xfs_init_procfs();
152 xfs_sysctl_register();
153 return 0;
154}
155
156void
157xfs_cleanup(void)
158{
159 extern kmem_zone_t *xfs_bmap_free_item_zone;
160 extern kmem_zone_t *xfs_btree_cur_zone;
161 extern kmem_zone_t *xfs_inode_zone;
162 extern kmem_zone_t *xfs_trans_zone;
163 extern kmem_zone_t *xfs_da_state_zone;
164 extern kmem_zone_t *xfs_dabuf_zone;
165 extern kmem_zone_t *xfs_efd_zone;
166 extern kmem_zone_t *xfs_efi_zone;
167 extern kmem_zone_t *xfs_buf_item_zone;
168 extern kmem_zone_t *xfs_chashlist_zone;
169
170 xfs_cleanup_procfs();
171 xfs_sysctl_unregister();
172 xfs_refcache_destroy();
173 xfs_acl_zone_destroy(xfs_acl_zone);
174
175#ifdef XFS_DIR2_TRACE
176 ktrace_free(xfs_dir2_trace_buf);
177#endif
178#ifdef XFS_ATTR_TRACE
179 ktrace_free(xfs_attr_trace_buf);
180#endif
181#ifdef XFS_DIR_TRACE
182 ktrace_free(xfs_dir_trace_buf);
183#endif
184#ifdef XFS_BMBT_TRACE
185 ktrace_free(xfs_bmbt_trace_buf);
186#endif
187#ifdef XFS_BMAP_TRACE
188 ktrace_free(xfs_bmap_trace_buf);
189#endif
190#ifdef XFS_ALLOC_TRACE
191 ktrace_free(xfs_alloc_trace_buf);
192#endif
193
194 kmem_cache_destroy(xfs_bmap_free_item_zone);
195 kmem_cache_destroy(xfs_btree_cur_zone);
196 kmem_cache_destroy(xfs_inode_zone);
197 kmem_cache_destroy(xfs_trans_zone);
198 kmem_cache_destroy(xfs_da_state_zone);
199 kmem_cache_destroy(xfs_dabuf_zone);
200 kmem_cache_destroy(xfs_buf_item_zone);
201 kmem_cache_destroy(xfs_efd_zone);
202 kmem_cache_destroy(xfs_efi_zone);
203 kmem_cache_destroy(xfs_ifork_zone);
204 kmem_cache_destroy(xfs_ili_zone);
205 kmem_cache_destroy(xfs_chashlist_zone);
206}
207
208/*
209 * xfs_start_flags
210 *
211 * This function fills in xfs_mount_t fields based on mount args.
212 * Note: the superblock has _not_ yet been read in.
213 */
214STATIC int
215xfs_start_flags(
216 struct vfs *vfs,
217 struct xfs_mount_args *ap,
218 struct xfs_mount *mp)
219{
220 /* Values are in BBs */
221 if ((ap->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) {
222 /*
223 * At this point the superblock has not been read
224 * in, therefore we do not know the block size.
225 * Before the mount call ends we will convert
226 * these to FSBs.
227 */
228 mp->m_dalign = ap->sunit;
229 mp->m_swidth = ap->swidth;
230 }
231
232 if (ap->logbufs != -1 &&
233#if defined(DEBUG) || defined(XLOG_NOLOG)
234 ap->logbufs != 0 &&
235#endif
236 (ap->logbufs < XLOG_MIN_ICLOGS ||
237 ap->logbufs > XLOG_MAX_ICLOGS)) {
238 cmn_err(CE_WARN,
239 "XFS: invalid logbufs value: %d [not %d-%d]",
240 ap->logbufs, XLOG_MIN_ICLOGS, XLOG_MAX_ICLOGS);
241 return XFS_ERROR(EINVAL);
242 }
243 mp->m_logbufs = ap->logbufs;
244 if (ap->logbufsize != -1 &&
245 ap->logbufsize != 16 * 1024 &&
246 ap->logbufsize != 32 * 1024 &&
247 ap->logbufsize != 64 * 1024 &&
248 ap->logbufsize != 128 * 1024 &&
249 ap->logbufsize != 256 * 1024) {
250 cmn_err(CE_WARN,
251 "XFS: invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]",
252 ap->logbufsize);
253 return XFS_ERROR(EINVAL);
254 }
255 mp->m_ihsize = ap->ihashsize;
256 mp->m_logbsize = ap->logbufsize;
257 mp->m_fsname_len = strlen(ap->fsname) + 1;
258 mp->m_fsname = kmem_alloc(mp->m_fsname_len, KM_SLEEP);
259 strcpy(mp->m_fsname, ap->fsname);
260
261 if (ap->flags & XFSMNT_WSYNC)
262 mp->m_flags |= XFS_MOUNT_WSYNC;
263#if XFS_BIG_INUMS
264 if (ap->flags & XFSMNT_INO64) {
265 mp->m_flags |= XFS_MOUNT_INO64;
266 mp->m_inoadd = XFS_INO64_OFFSET;
267 }
268#endif
269 if (ap->flags & XFSMNT_NOATIME)
270 mp->m_flags |= XFS_MOUNT_NOATIME;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271 if (ap->flags & XFSMNT_RETERR)
272 mp->m_flags |= XFS_MOUNT_RETERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273 if (ap->flags & XFSMNT_NOALIGN)
274 mp->m_flags |= XFS_MOUNT_NOALIGN;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 if (ap->flags & XFSMNT_SWALLOC)
276 mp->m_flags |= XFS_MOUNT_SWALLOC;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 if (ap->flags & XFSMNT_OSYNCISOSYNC)
278 mp->m_flags |= XFS_MOUNT_OSYNCISOSYNC;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 if (ap->flags & XFSMNT_32BITINODES)
280 mp->m_flags |= (XFS_MOUNT_32BITINODES | XFS_MOUNT_32BITINOOPT);
281
282 if (ap->flags & XFSMNT_IOSIZE) {
283 if (ap->iosizelog > XFS_MAX_IO_LOG ||
284 ap->iosizelog < XFS_MIN_IO_LOG) {
285 cmn_err(CE_WARN,
286 "XFS: invalid log iosize: %d [not %d-%d]",
287 ap->iosizelog, XFS_MIN_IO_LOG,
288 XFS_MAX_IO_LOG);
289 return XFS_ERROR(EINVAL);
290 }
291
292 mp->m_flags |= XFS_MOUNT_DFLT_IOSIZE;
293 mp->m_readio_log = mp->m_writeio_log = ap->iosizelog;
294 }
295
296 if (ap->flags & XFSMNT_IHASHSIZE)
297 mp->m_flags |= XFS_MOUNT_IHASHSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 if (ap->flags & XFSMNT_IDELETE)
299 mp->m_flags |= XFS_MOUNT_IDELETE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300 if (ap->flags & XFSMNT_DIRSYNC)
301 mp->m_flags |= XFS_MOUNT_DIRSYNC;
David Chinnere8c8b3a2005-11-02 10:33:05 +1100302 if (ap->flags & XFSMNT_COMPAT_IOSIZE)
303 mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE;
Nathan Scottd8cc8902005-11-02 10:34:53 +1100304 if (ap->flags & XFSMNT_COMPAT_ATTR)
305 mp->m_flags |= XFS_MOUNT_COMPAT_ATTR;
David Chinnere8c8b3a2005-11-02 10:33:05 +1100306
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 /*
308 * no recovery flag requires a read-only mount
309 */
310 if (ap->flags & XFSMNT_NORECOVERY) {
311 if (!(vfs->vfs_flag & VFS_RDONLY)) {
312 cmn_err(CE_WARN,
313 "XFS: tried to mount a FS read-write without recovery!");
314 return XFS_ERROR(EINVAL);
315 }
316 mp->m_flags |= XFS_MOUNT_NORECOVERY;
317 }
318
319 if (ap->flags & XFSMNT_NOUUID)
320 mp->m_flags |= XFS_MOUNT_NOUUID;
Christoph Hellwigf538d4d2005-11-02 10:26:59 +1100321 if (ap->flags & XFSMNT_BARRIER)
322 mp->m_flags |= XFS_MOUNT_BARRIER;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323
324 return 0;
325}
326
327/*
328 * This function fills in xfs_mount_t fields based on mount args.
329 * Note: the superblock _has_ now been read in.
330 */
331STATIC int
332xfs_finish_flags(
333 struct vfs *vfs,
334 struct xfs_mount_args *ap,
335 struct xfs_mount *mp)
336{
337 int ronly = (vfs->vfs_flag & VFS_RDONLY);
338
339 /* Fail a mount where the logbuf is smaller then the log stripe */
340 if (XFS_SB_VERSION_HASLOGV2(&mp->m_sb)) {
341 if ((ap->logbufsize == -1) &&
342 (mp->m_sb.sb_logsunit > XLOG_BIG_RECORD_BSIZE)) {
343 mp->m_logbsize = mp->m_sb.sb_logsunit;
344 } else if (ap->logbufsize < mp->m_sb.sb_logsunit) {
345 cmn_err(CE_WARN,
346 "XFS: logbuf size must be greater than or equal to log stripe size");
347 return XFS_ERROR(EINVAL);
348 }
349 } else {
350 /* Fail a mount if the logbuf is larger than 32K */
351 if (ap->logbufsize > XLOG_BIG_RECORD_BSIZE) {
352 cmn_err(CE_WARN,
353 "XFS: logbuf size for version 1 logs must be 16K or 32K");
354 return XFS_ERROR(EINVAL);
355 }
356 }
357
358 /*
359 * prohibit r/w mounts of read-only filesystems
360 */
361 if ((mp->m_sb.sb_flags & XFS_SBF_READONLY) && !ronly) {
362 cmn_err(CE_WARN,
363 "XFS: cannot mount a read-only filesystem as read-write");
364 return XFS_ERROR(EROFS);
365 }
366
367 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368 * check for shared mount.
369 */
370 if (ap->flags & XFSMNT_SHARED) {
371 if (!XFS_SB_VERSION_HASSHARED(&mp->m_sb))
372 return XFS_ERROR(EINVAL);
373
374 /*
375 * For IRIX 6.5, shared mounts must have the shared
376 * version bit set, have the persistent readonly
377 * field set, must be version 0 and can only be mounted
378 * read-only.
379 */
380 if (!ronly || !(mp->m_sb.sb_flags & XFS_SBF_READONLY) ||
381 (mp->m_sb.sb_shared_vn != 0))
382 return XFS_ERROR(EINVAL);
383
384 mp->m_flags |= XFS_MOUNT_SHARED;
385
386 /*
387 * Shared XFS V0 can't deal with DMI. Return EINVAL.
388 */
389 if (mp->m_sb.sb_shared_vn == 0 && (ap->flags & XFSMNT_DMAPI))
390 return XFS_ERROR(EINVAL);
391 }
392
393 return 0;
394}
395
396/*
397 * xfs_mount
398 *
399 * The file system configurations are:
400 * (1) device (partition) with data and internal log
401 * (2) logical volume with data and log subvolumes.
402 * (3) logical volume with data, log, and realtime subvolumes.
403 *
404 * We only have to handle opening the log and realtime volumes here if
405 * they are present. The data subvolume has already been opened by
406 * get_sb_bdev() and is stored in vfsp->vfs_super->s_bdev.
407 */
408STATIC int
409xfs_mount(
410 struct bhv_desc *bhvp,
411 struct xfs_mount_args *args,
412 cred_t *credp)
413{
414 struct vfs *vfsp = bhvtovfs(bhvp);
415 struct bhv_desc *p;
416 struct xfs_mount *mp = XFS_BHVTOM(bhvp);
417 struct block_device *ddev, *logdev, *rtdev;
418 int flags = 0, error;
419
420 ddev = vfsp->vfs_super->s_bdev;
421 logdev = rtdev = NULL;
422
423 /*
424 * Setup xfs_mount function vectors from available behaviors
425 */
426 p = vfs_bhv_lookup(vfsp, VFS_POSITION_DM);
427 mp->m_dm_ops = p ? *(xfs_dmops_t *) vfs_bhv_custom(p) : xfs_dmcore_stub;
428 p = vfs_bhv_lookup(vfsp, VFS_POSITION_QM);
429 mp->m_qm_ops = p ? *(xfs_qmops_t *) vfs_bhv_custom(p) : xfs_qmcore_stub;
430 p = vfs_bhv_lookup(vfsp, VFS_POSITION_IO);
431 mp->m_io_ops = p ? *(xfs_ioops_t *) vfs_bhv_custom(p) : xfs_iocore_xfs;
432
433 /*
434 * Open real time and log devices - order is important.
435 */
436 if (args->logname[0]) {
437 error = xfs_blkdev_get(mp, args->logname, &logdev);
438 if (error)
439 return error;
440 }
441 if (args->rtname[0]) {
442 error = xfs_blkdev_get(mp, args->rtname, &rtdev);
443 if (error) {
444 xfs_blkdev_put(logdev);
445 return error;
446 }
447
448 if (rtdev == ddev || rtdev == logdev) {
449 cmn_err(CE_WARN,
450 "XFS: Cannot mount filesystem with identical rtdev and ddev/logdev.");
451 xfs_blkdev_put(logdev);
452 xfs_blkdev_put(rtdev);
453 return EINVAL;
454 }
455 }
456
457 /*
458 * Setup xfs_mount buffer target pointers
459 */
460 error = ENOMEM;
461 mp->m_ddev_targp = xfs_alloc_buftarg(ddev, 0);
462 if (!mp->m_ddev_targp) {
463 xfs_blkdev_put(logdev);
464 xfs_blkdev_put(rtdev);
465 return error;
466 }
467 if (rtdev) {
468 mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev, 1);
469 if (!mp->m_rtdev_targp)
470 goto error0;
471 }
472 mp->m_logdev_targp = (logdev && logdev != ddev) ?
473 xfs_alloc_buftarg(logdev, 1) : mp->m_ddev_targp;
474 if (!mp->m_logdev_targp)
475 goto error0;
476
477 /*
478 * Setup flags based on mount(2) options and then the superblock
479 */
480 error = xfs_start_flags(vfsp, args, mp);
481 if (error)
482 goto error1;
483 error = xfs_readsb(mp);
484 if (error)
485 goto error1;
486 error = xfs_finish_flags(vfsp, args, mp);
487 if (error)
488 goto error2;
489
490 /*
491 * Setup xfs_mount buffer target pointers based on superblock
492 */
493 error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,
494 mp->m_sb.sb_sectsize);
495 if (!error && logdev && logdev != ddev) {
496 unsigned int log_sector_size = BBSIZE;
497
498 if (XFS_SB_VERSION_HASSECTOR(&mp->m_sb))
499 log_sector_size = mp->m_sb.sb_logsectsize;
500 error = xfs_setsize_buftarg(mp->m_logdev_targp,
501 mp->m_sb.sb_blocksize,
502 log_sector_size);
503 }
504 if (!error && rtdev)
505 error = xfs_setsize_buftarg(mp->m_rtdev_targp,
506 mp->m_sb.sb_blocksize,
507 mp->m_sb.sb_sectsize);
508 if (error)
509 goto error2;
510
511 error = XFS_IOINIT(vfsp, args, flags);
Christoph Hellwigf538d4d2005-11-02 10:26:59 +1100512 if (error)
513 goto error2;
514
515 if ((args->flags & XFSMNT_BARRIER) &&
516 !(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY))
517 xfs_mountfs_check_barriers(mp);
518 return 0;
519
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520error2:
521 if (mp->m_sb_bp)
522 xfs_freesb(mp);
523error1:
524 xfs_binval(mp->m_ddev_targp);
525 if (logdev && logdev != ddev)
526 xfs_binval(mp->m_logdev_targp);
527 if (rtdev)
528 xfs_binval(mp->m_rtdev_targp);
529error0:
530 xfs_unmountfs_close(mp, credp);
531 return error;
532}
533
534STATIC int
535xfs_unmount(
536 bhv_desc_t *bdp,
537 int flags,
538 cred_t *credp)
539{
540 struct vfs *vfsp = bhvtovfs(bdp);
541 xfs_mount_t *mp = XFS_BHVTOM(bdp);
542 xfs_inode_t *rip;
543 vnode_t *rvp;
544 int unmount_event_wanted = 0;
545 int unmount_event_flags = 0;
546 int xfs_unmountfs_needed = 0;
547 int error;
548
549 rip = mp->m_rootip;
550 rvp = XFS_ITOV(rip);
551
552 if (vfsp->vfs_flag & VFS_DMI) {
553 error = XFS_SEND_PREUNMOUNT(mp, vfsp,
554 rvp, DM_RIGHT_NULL, rvp, DM_RIGHT_NULL,
555 NULL, NULL, 0, 0,
556 (mp->m_dmevmask & (1<<DM_EVENT_PREUNMOUNT))?
557 0:DM_FLAGS_UNWANTED);
558 if (error)
559 return XFS_ERROR(error);
560 unmount_event_wanted = 1;
561 unmount_event_flags = (mp->m_dmevmask & (1<<DM_EVENT_UNMOUNT))?
562 0 : DM_FLAGS_UNWANTED;
563 }
564
565 /*
566 * First blow any referenced inode from this file system
567 * out of the reference cache, and delete the timer.
568 */
569 xfs_refcache_purge_mp(mp);
570
571 XFS_bflush(mp->m_ddev_targp);
572 error = xfs_unmount_flush(mp, 0);
573 if (error)
574 goto out;
575
576 ASSERT(vn_count(rvp) == 1);
577
578 /*
579 * Drop the reference count
580 */
581 VN_RELE(rvp);
582
583 /*
584 * If we're forcing a shutdown, typically because of a media error,
585 * we want to make sure we invalidate dirty pages that belong to
586 * referenced vnodes as well.
587 */
588 if (XFS_FORCED_SHUTDOWN(mp)) {
589 error = xfs_sync(&mp->m_bhv,
590 (SYNC_WAIT | SYNC_CLOSE), credp);
591 ASSERT(error != EFSCORRUPTED);
592 }
593 xfs_unmountfs_needed = 1;
594
595out:
596 /* Send DMAPI event, if required.
597 * Then do xfs_unmountfs() if needed.
598 * Then return error (or zero).
599 */
600 if (unmount_event_wanted) {
601 /* Note: mp structure must still exist for
602 * XFS_SEND_UNMOUNT() call.
603 */
604 XFS_SEND_UNMOUNT(mp, vfsp, error == 0 ? rvp : NULL,
605 DM_RIGHT_NULL, 0, error, unmount_event_flags);
606 }
607 if (xfs_unmountfs_needed) {
608 /*
609 * Call common unmount function to flush to disk
610 * and free the super block buffer & mount structures.
611 */
612 xfs_unmountfs(mp, credp);
613 }
614
615 return XFS_ERROR(error);
616}
617
Christoph Hellwigf898d6c2005-06-21 15:40:48 +1000618STATIC int
619xfs_quiesce_fs(
620 xfs_mount_t *mp)
621{
622 int count = 0, pincount;
623
624 xfs_refcache_purge_mp(mp);
625 xfs_flush_buftarg(mp->m_ddev_targp, 0);
626 xfs_finish_reclaim_all(mp, 0);
627
628 /* This loop must run at least twice.
629 * The first instance of the loop will flush
630 * most meta data but that will generate more
631 * meta data (typically directory updates).
632 * Which then must be flushed and logged before
633 * we can write the unmount record.
634 */
635 do {
636 xfs_syncsub(mp, SYNC_REMOUNT|SYNC_ATTR|SYNC_WAIT, 0, NULL);
637 pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
638 if (!pincount) {
639 delay(50);
640 count++;
641 }
642 } while (count < 2);
643
644 return 0;
645}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646
647STATIC int
648xfs_mntupdate(
649 bhv_desc_t *bdp,
650 int *flags,
651 struct xfs_mount_args *args)
652{
653 struct vfs *vfsp = bhvtovfs(bdp);
654 xfs_mount_t *mp = XFS_BHVTOM(bdp);
Christoph Hellwigf898d6c2005-06-21 15:40:48 +1000655 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
657 if (args->flags & XFSMNT_NOATIME)
658 mp->m_flags |= XFS_MOUNT_NOATIME;
659 else
660 mp->m_flags &= ~XFS_MOUNT_NOATIME;
661
Christoph Hellwigf538d4d2005-11-02 10:26:59 +1100662 if ((vfsp->vfs_flag & VFS_RDONLY) &&
663 !(*flags & MS_RDONLY)) {
664 vfsp->vfs_flag &= ~VFS_RDONLY;
665
666 if (args->flags & XFSMNT_BARRIER)
667 xfs_mountfs_check_barriers(mp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 }
669
Christoph Hellwigf538d4d2005-11-02 10:26:59 +1100670 if (!(vfsp->vfs_flag & VFS_RDONLY) &&
671 (*flags & MS_RDONLY)) {
672 VFS_SYNC(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL, error);
673
Christoph Hellwigf898d6c2005-06-21 15:40:48 +1000674 xfs_quiesce_fs(mp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675
676 /* Ok now write out an unmount record */
677 xfs_log_unmount_write(mp);
678 xfs_unmountfs_writesb(mp);
679 vfsp->vfs_flag |= VFS_RDONLY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 }
681
682 return 0;
683}
684
685/*
686 * xfs_unmount_flush implements a set of flush operation on special
687 * inodes, which are needed as a separate set of operations so that
688 * they can be called as part of relocation process.
689 */
690int
691xfs_unmount_flush(
692 xfs_mount_t *mp, /* Mount structure we are getting
693 rid of. */
694 int relocation) /* Called from vfs relocation. */
695{
696 xfs_inode_t *rip = mp->m_rootip;
697 xfs_inode_t *rbmip;
698 xfs_inode_t *rsumip = NULL;
699 vnode_t *rvp = XFS_ITOV(rip);
700 int error;
701
702 xfs_ilock(rip, XFS_ILOCK_EXCL);
703 xfs_iflock(rip);
704
705 /*
706 * Flush out the real time inodes.
707 */
708 if ((rbmip = mp->m_rbmip) != NULL) {
709 xfs_ilock(rbmip, XFS_ILOCK_EXCL);
710 xfs_iflock(rbmip);
711 error = xfs_iflush(rbmip, XFS_IFLUSH_SYNC);
712 xfs_iunlock(rbmip, XFS_ILOCK_EXCL);
713
714 if (error == EFSCORRUPTED)
715 goto fscorrupt_out;
716
717 ASSERT(vn_count(XFS_ITOV(rbmip)) == 1);
718
719 rsumip = mp->m_rsumip;
720 xfs_ilock(rsumip, XFS_ILOCK_EXCL);
721 xfs_iflock(rsumip);
722 error = xfs_iflush(rsumip, XFS_IFLUSH_SYNC);
723 xfs_iunlock(rsumip, XFS_ILOCK_EXCL);
724
725 if (error == EFSCORRUPTED)
726 goto fscorrupt_out;
727
728 ASSERT(vn_count(XFS_ITOV(rsumip)) == 1);
729 }
730
731 /*
732 * Synchronously flush root inode to disk
733 */
734 error = xfs_iflush(rip, XFS_IFLUSH_SYNC);
735 if (error == EFSCORRUPTED)
736 goto fscorrupt_out2;
737
738 if (vn_count(rvp) != 1 && !relocation) {
739 xfs_iunlock(rip, XFS_ILOCK_EXCL);
740 return XFS_ERROR(EBUSY);
741 }
742
743 /*
744 * Release dquot that rootinode, rbmino and rsumino might be holding,
745 * flush and purge the quota inodes.
746 */
747 error = XFS_QM_UNMOUNT(mp);
748 if (error == EFSCORRUPTED)
749 goto fscorrupt_out2;
750
751 if (rbmip) {
752 VN_RELE(XFS_ITOV(rbmip));
753 VN_RELE(XFS_ITOV(rsumip));
754 }
755
756 xfs_iunlock(rip, XFS_ILOCK_EXCL);
757 return 0;
758
759fscorrupt_out:
760 xfs_ifunlock(rip);
761
762fscorrupt_out2:
763 xfs_iunlock(rip, XFS_ILOCK_EXCL);
764
765 return XFS_ERROR(EFSCORRUPTED);
766}
767
768/*
769 * xfs_root extracts the root vnode from a vfs.
770 *
771 * vfsp -- the vfs struct for the desired file system
772 * vpp -- address of the caller's vnode pointer which should be
773 * set to the desired fs root vnode
774 */
775STATIC int
776xfs_root(
777 bhv_desc_t *bdp,
778 vnode_t **vpp)
779{
780 vnode_t *vp;
781
782 vp = XFS_ITOV((XFS_BHVTOM(bdp))->m_rootip);
783 VN_HOLD(vp);
784 *vpp = vp;
785 return 0;
786}
787
788/*
789 * xfs_statvfs
790 *
791 * Fill in the statvfs structure for the given file system. We use
792 * the superblock lock in the mount structure to ensure a consistent
793 * snapshot of the counters returned.
794 */
795STATIC int
796xfs_statvfs(
797 bhv_desc_t *bdp,
798 xfs_statfs_t *statp,
799 vnode_t *vp)
800{
801 __uint64_t fakeinos;
802 xfs_extlen_t lsize;
803 xfs_mount_t *mp;
804 xfs_sb_t *sbp;
805 unsigned long s;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806
807 mp = XFS_BHVTOM(bdp);
808 sbp = &(mp->m_sb);
809
810 statp->f_type = XFS_SB_MAGIC;
811
812 s = XFS_SB_LOCK(mp);
813 statp->f_bsize = sbp->sb_blocksize;
814 lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0;
815 statp->f_blocks = sbp->sb_dblocks - lsize;
816 statp->f_bfree = statp->f_bavail = sbp->sb_fdblocks;
817 fakeinos = statp->f_bfree << sbp->sb_inopblog;
818#if XFS_BIG_INUMS
819 fakeinos += mp->m_inoadd;
820#endif
821 statp->f_files =
822 MIN(sbp->sb_icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
823 if (mp->m_maxicount)
824#if XFS_BIG_INUMS
825 if (!mp->m_inoadd)
826#endif
827 statp->f_files = min_t(typeof(statp->f_files),
828 statp->f_files,
829 mp->m_maxicount);
830 statp->f_ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree);
831 XFS_SB_UNLOCK(mp, s);
832
Nathan Scottcde410a2005-09-05 11:47:01 +1000833 xfs_statvfs_fsid(statp, mp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 statp->f_namelen = MAXNAMELEN - 1;
835
836 return 0;
837}
838
839
840/*
841 * xfs_sync flushes any pending I/O to file system vfsp.
842 *
843 * This routine is called by vfs_sync() to make sure that things make it
844 * out to disk eventually, on sync() system calls to flush out everything,
845 * and when the file system is unmounted. For the vfs_sync() case, all
846 * we really need to do is sync out the log to make all of our meta-data
847 * updates permanent (except for timestamps). For calls from pflushd(),
848 * dirty pages are kept moving by calling pdflush() on the inodes
849 * containing them. We also flush the inodes that we can lock without
850 * sleeping and the superblock if we can lock it without sleeping from
851 * vfs_sync() so that items at the tail of the log are always moving out.
852 *
853 * Flags:
854 * SYNC_BDFLUSH - We're being called from vfs_sync() so we don't want
855 * to sleep if we can help it. All we really need
856 * to do is ensure that the log is synced at least
857 * periodically. We also push the inodes and
858 * superblock if we can lock them without sleeping
859 * and they are not pinned.
860 * SYNC_ATTR - We need to flush the inodes. If SYNC_BDFLUSH is not
861 * set, then we really want to lock each inode and flush
862 * it.
863 * SYNC_WAIT - All the flushes that take place in this call should
864 * be synchronous.
865 * SYNC_DELWRI - This tells us to push dirty pages associated with
866 * inodes. SYNC_WAIT and SYNC_BDFLUSH are used to
867 * determine if they should be flushed sync, async, or
868 * delwri.
869 * SYNC_CLOSE - This flag is passed when the system is being
870 * unmounted. We should sync and invalidate everthing.
871 * SYNC_FSDATA - This indicates that the caller would like to make
872 * sure the superblock is safe on disk. We can ensure
873 * this by simply makeing sure the log gets flushed
874 * if SYNC_BDFLUSH is set, and by actually writing it
875 * out otherwise.
876 *
877 */
878/*ARGSUSED*/
879STATIC int
880xfs_sync(
881 bhv_desc_t *bdp,
882 int flags,
883 cred_t *credp)
884{
Christoph Hellwigf898d6c2005-06-21 15:40:48 +1000885 xfs_mount_t *mp = XFS_BHVTOM(bdp);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
Christoph Hellwigf898d6c2005-06-21 15:40:48 +1000887 if (unlikely(flags == SYNC_QUIESCE))
888 return xfs_quiesce_fs(mp);
889 else
890 return xfs_syncsub(mp, flags, 0, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891}
892
893/*
894 * xfs sync routine for internal use
895 *
896 * This routine supports all of the flags defined for the generic VFS_SYNC
897 * interface as explained above under xfs_sync. In the interests of not
898 * changing interfaces within the 6.5 family, additional internallly-
899 * required functions are specified within a separate xflags parameter,
900 * only available by calling this routine.
901 *
902 */
Nathan Scottee348072005-11-02 10:32:38 +1100903int
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904xfs_sync_inodes(
905 xfs_mount_t *mp,
906 int flags,
907 int xflags,
908 int *bypassed)
909{
910 xfs_inode_t *ip = NULL;
911 xfs_inode_t *ip_next;
912 xfs_buf_t *bp;
913 vnode_t *vp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 int error;
915 int last_error;
916 uint64_t fflag;
917 uint lock_flags;
918 uint base_lock_flags;
919 boolean_t mount_locked;
920 boolean_t vnode_refed;
921 int preempt;
922 xfs_dinode_t *dip;
923 xfs_iptr_t *ipointer;
924#ifdef DEBUG
925 boolean_t ipointer_in = B_FALSE;
926
927#define IPOINTER_SET ipointer_in = B_TRUE
928#define IPOINTER_CLR ipointer_in = B_FALSE
929#else
930#define IPOINTER_SET
931#define IPOINTER_CLR
932#endif
933
934
935/* Insert a marker record into the inode list after inode ip. The list
936 * must be locked when this is called. After the call the list will no
937 * longer be locked.
938 */
939#define IPOINTER_INSERT(ip, mp) { \
940 ASSERT(ipointer_in == B_FALSE); \
941 ipointer->ip_mnext = ip->i_mnext; \
942 ipointer->ip_mprev = ip; \
943 ip->i_mnext = (xfs_inode_t *)ipointer; \
944 ipointer->ip_mnext->i_mprev = (xfs_inode_t *)ipointer; \
945 preempt = 0; \
946 XFS_MOUNT_IUNLOCK(mp); \
947 mount_locked = B_FALSE; \
948 IPOINTER_SET; \
949 }
950
951/* Remove the marker from the inode list. If the marker was the only item
952 * in the list then there are no remaining inodes and we should zero out
953 * the whole list. If we are the current head of the list then move the head
954 * past us.
955 */
956#define IPOINTER_REMOVE(ip, mp) { \
957 ASSERT(ipointer_in == B_TRUE); \
958 if (ipointer->ip_mnext != (xfs_inode_t *)ipointer) { \
959 ip = ipointer->ip_mnext; \
960 ip->i_mprev = ipointer->ip_mprev; \
961 ipointer->ip_mprev->i_mnext = ip; \
962 if (mp->m_inodes == (xfs_inode_t *)ipointer) { \
963 mp->m_inodes = ip; \
964 } \
965 } else { \
966 ASSERT(mp->m_inodes == (xfs_inode_t *)ipointer); \
967 mp->m_inodes = NULL; \
968 ip = NULL; \
969 } \
970 IPOINTER_CLR; \
971 }
972
973#define XFS_PREEMPT_MASK 0x7f
974
975 if (bypassed)
976 *bypassed = 0;
977 if (XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY)
978 return 0;
979 error = 0;
980 last_error = 0;
981 preempt = 0;
982
983 /* Allocate a reference marker */
984 ipointer = (xfs_iptr_t *)kmem_zalloc(sizeof(xfs_iptr_t), KM_SLEEP);
985
986 fflag = XFS_B_ASYNC; /* default is don't wait */
Nathan Scottee348072005-11-02 10:32:38 +1100987 if (flags & (SYNC_BDFLUSH | SYNC_DELWRI))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 fflag = XFS_B_DELWRI;
989 if (flags & SYNC_WAIT)
990 fflag = 0; /* synchronous overrides all */
991
992 base_lock_flags = XFS_ILOCK_SHARED;
993 if (flags & (SYNC_DELWRI | SYNC_CLOSE)) {
994 /*
995 * We need the I/O lock if we're going to call any of
996 * the flush/inval routines.
997 */
998 base_lock_flags |= XFS_IOLOCK_SHARED;
999 }
1000
1001 XFS_MOUNT_ILOCK(mp);
1002
1003 ip = mp->m_inodes;
1004
1005 mount_locked = B_TRUE;
1006 vnode_refed = B_FALSE;
1007
1008 IPOINTER_CLR;
1009
1010 do {
1011 ASSERT(ipointer_in == B_FALSE);
1012 ASSERT(vnode_refed == B_FALSE);
1013
1014 lock_flags = base_lock_flags;
1015
1016 /*
1017 * There were no inodes in the list, just break out
1018 * of the loop.
1019 */
1020 if (ip == NULL) {
1021 break;
1022 }
1023
1024 /*
1025 * We found another sync thread marker - skip it
1026 */
1027 if (ip->i_mount == NULL) {
1028 ip = ip->i_mnext;
1029 continue;
1030 }
1031
1032 vp = XFS_ITOV_NULL(ip);
1033
1034 /*
1035 * If the vnode is gone then this is being torn down,
1036 * call reclaim if it is flushed, else let regular flush
1037 * code deal with it later in the loop.
1038 */
1039
1040 if (vp == NULL) {
1041 /* Skip ones already in reclaim */
1042 if (ip->i_flags & XFS_IRECLAIM) {
1043 ip = ip->i_mnext;
1044 continue;
1045 }
1046 if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0) {
1047 ip = ip->i_mnext;
1048 } else if ((xfs_ipincount(ip) == 0) &&
1049 xfs_iflock_nowait(ip)) {
1050 IPOINTER_INSERT(ip, mp);
1051
1052 xfs_finish_reclaim(ip, 1,
1053 XFS_IFLUSH_DELWRI_ELSE_ASYNC);
1054
1055 XFS_MOUNT_ILOCK(mp);
1056 mount_locked = B_TRUE;
1057 IPOINTER_REMOVE(ip, mp);
1058 } else {
1059 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1060 ip = ip->i_mnext;
1061 }
1062 continue;
1063 }
1064
1065 if (VN_BAD(vp)) {
1066 ip = ip->i_mnext;
1067 continue;
1068 }
1069
1070 if (XFS_FORCED_SHUTDOWN(mp) && !(flags & SYNC_CLOSE)) {
1071 XFS_MOUNT_IUNLOCK(mp);
1072 kmem_free(ipointer, sizeof(xfs_iptr_t));
1073 return 0;
1074 }
1075
1076 /*
1077 * If this is just vfs_sync() or pflushd() calling
1078 * then we can skip inodes for which it looks like
1079 * there is nothing to do. Since we don't have the
1080 * inode locked this is racey, but these are periodic
1081 * calls so it doesn't matter. For the others we want
1082 * to know for sure, so we at least try to lock them.
1083 */
1084 if (flags & SYNC_BDFLUSH) {
1085 if (((ip->i_itemp == NULL) ||
1086 !(ip->i_itemp->ili_format.ilf_fields &
1087 XFS_ILOG_ALL)) &&
1088 (ip->i_update_core == 0)) {
1089 ip = ip->i_mnext;
1090 continue;
1091 }
1092 }
1093
1094 /*
1095 * Try to lock without sleeping. We're out of order with
1096 * the inode list lock here, so if we fail we need to drop
1097 * the mount lock and try again. If we're called from
1098 * bdflush() here, then don't bother.
1099 *
1100 * The inode lock here actually coordinates with the
1101 * almost spurious inode lock in xfs_ireclaim() to prevent
1102 * the vnode we handle here without a reference from
1103 * being freed while we reference it. If we lock the inode
1104 * while it's on the mount list here, then the spurious inode
1105 * lock in xfs_ireclaim() after the inode is pulled from
1106 * the mount list will sleep until we release it here.
1107 * This keeps the vnode from being freed while we reference
Christoph Hellwigcdb62682005-09-02 16:24:19 +10001108 * it.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 */
1110 if (xfs_ilock_nowait(ip, lock_flags) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 if ((flags & SYNC_BDFLUSH) || (vp == NULL)) {
1112 ip = ip->i_mnext;
1113 continue;
1114 }
1115
Christoph Hellwigcdb62682005-09-02 16:24:19 +10001116 vp = vn_grab(vp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 if (vp == NULL) {
Christoph Hellwigcdb62682005-09-02 16:24:19 +10001118 ip = ip->i_mnext;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119 continue;
1120 }
1121
Christoph Hellwigcdb62682005-09-02 16:24:19 +10001122 IPOINTER_INSERT(ip, mp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 xfs_ilock(ip, lock_flags);
1124
1125 ASSERT(vp == XFS_ITOV(ip));
1126 ASSERT(ip->i_mount == mp);
1127
1128 vnode_refed = B_TRUE;
1129 }
1130
1131 /* From here on in the loop we may have a marker record
1132 * in the inode list.
1133 */
1134
1135 if ((flags & SYNC_CLOSE) && (vp != NULL)) {
1136 /*
1137 * This is the shutdown case. We just need to
1138 * flush and invalidate all the pages associated
1139 * with the inode. Drop the inode lock since
1140 * we can't hold it across calls to the buffer
1141 * cache.
1142 *
1143 * We don't set the VREMAPPING bit in the vnode
1144 * here, because we don't hold the vnode lock
1145 * exclusively. It doesn't really matter, though,
1146 * because we only come here when we're shutting
1147 * down anyway.
1148 */
1149 xfs_iunlock(ip, XFS_ILOCK_SHARED);
1150
1151 if (XFS_FORCED_SHUTDOWN(mp)) {
1152 VOP_TOSS_PAGES(vp, 0, -1, FI_REMAPF);
1153 } else {
1154 VOP_FLUSHINVAL_PAGES(vp, 0, -1, FI_REMAPF);
1155 }
1156
1157 xfs_ilock(ip, XFS_ILOCK_SHARED);
1158
1159 } else if ((flags & SYNC_DELWRI) && (vp != NULL)) {
1160 if (VN_DIRTY(vp)) {
1161 /* We need to have dropped the lock here,
1162 * so insert a marker if we have not already
1163 * done so.
1164 */
1165 if (mount_locked) {
1166 IPOINTER_INSERT(ip, mp);
1167 }
1168
1169 /*
1170 * Drop the inode lock since we can't hold it
1171 * across calls to the buffer cache.
1172 */
1173 xfs_iunlock(ip, XFS_ILOCK_SHARED);
1174 VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1,
1175 fflag, FI_NONE, error);
1176 xfs_ilock(ip, XFS_ILOCK_SHARED);
1177 }
1178
1179 }
1180
1181 if (flags & SYNC_BDFLUSH) {
1182 if ((flags & SYNC_ATTR) &&
1183 ((ip->i_update_core) ||
1184 ((ip->i_itemp != NULL) &&
1185 (ip->i_itemp->ili_format.ilf_fields != 0)))) {
1186
1187 /* Insert marker and drop lock if not already
1188 * done.
1189 */
1190 if (mount_locked) {
1191 IPOINTER_INSERT(ip, mp);
1192 }
1193
1194 /*
1195 * We don't want the periodic flushing of the
1196 * inodes by vfs_sync() to interfere with
1197 * I/O to the file, especially read I/O
1198 * where it is only the access time stamp
1199 * that is being flushed out. To prevent
1200 * long periods where we have both inode
1201 * locks held shared here while reading the
1202 * inode's buffer in from disk, we drop the
1203 * inode lock while reading in the inode
1204 * buffer. We have to release the buffer
1205 * and reacquire the inode lock so that they
1206 * are acquired in the proper order (inode
1207 * locks first). The buffer will go at the
1208 * end of the lru chain, though, so we can
1209 * expect it to still be there when we go
1210 * for it again in xfs_iflush().
1211 */
1212 if ((xfs_ipincount(ip) == 0) &&
1213 xfs_iflock_nowait(ip)) {
1214
1215 xfs_ifunlock(ip);
1216 xfs_iunlock(ip, XFS_ILOCK_SHARED);
1217
1218 error = xfs_itobp(mp, NULL, ip,
1219 &dip, &bp, 0);
1220 if (!error) {
1221 xfs_buf_relse(bp);
1222 } else {
1223 /* Bailing out, remove the
1224 * marker and free it.
1225 */
1226 XFS_MOUNT_ILOCK(mp);
1227
1228 IPOINTER_REMOVE(ip, mp);
1229
1230 XFS_MOUNT_IUNLOCK(mp);
1231
1232 ASSERT(!(lock_flags &
1233 XFS_IOLOCK_SHARED));
1234
1235 kmem_free(ipointer,
1236 sizeof(xfs_iptr_t));
1237 return (0);
1238 }
1239
1240 /*
1241 * Since we dropped the inode lock,
1242 * the inode may have been reclaimed.
1243 * Therefore, we reacquire the mount
1244 * lock and check to see if we were the
1245 * inode reclaimed. If this happened
1246 * then the ipointer marker will no
1247 * longer point back at us. In this
1248 * case, move ip along to the inode
1249 * after the marker, remove the marker
1250 * and continue.
1251 */
1252 XFS_MOUNT_ILOCK(mp);
1253 mount_locked = B_TRUE;
1254
1255 if (ip != ipointer->ip_mprev) {
1256 IPOINTER_REMOVE(ip, mp);
1257
1258 ASSERT(!vnode_refed);
1259 ASSERT(!(lock_flags &
1260 XFS_IOLOCK_SHARED));
1261 continue;
1262 }
1263
1264 ASSERT(ip->i_mount == mp);
1265
1266 if (xfs_ilock_nowait(ip,
1267 XFS_ILOCK_SHARED) == 0) {
1268 ASSERT(ip->i_mount == mp);
1269 /*
1270 * We failed to reacquire
1271 * the inode lock without
1272 * sleeping, so just skip
1273 * the inode for now. We
1274 * clear the ILOCK bit from
1275 * the lock_flags so that we
1276 * won't try to drop a lock
1277 * we don't hold below.
1278 */
1279 lock_flags &= ~XFS_ILOCK_SHARED;
1280 IPOINTER_REMOVE(ip_next, mp);
1281 } else if ((xfs_ipincount(ip) == 0) &&
1282 xfs_iflock_nowait(ip)) {
1283 ASSERT(ip->i_mount == mp);
1284 /*
1285 * Since this is vfs_sync()
1286 * calling we only flush the
1287 * inode out if we can lock
1288 * it without sleeping and
1289 * it is not pinned. Drop
1290 * the mount lock here so
1291 * that we don't hold it for
1292 * too long. We already have
1293 * a marker in the list here.
1294 */
1295 XFS_MOUNT_IUNLOCK(mp);
1296 mount_locked = B_FALSE;
1297 error = xfs_iflush(ip,
1298 XFS_IFLUSH_DELWRI);
1299 } else {
1300 ASSERT(ip->i_mount == mp);
1301 IPOINTER_REMOVE(ip_next, mp);
1302 }
1303 }
1304
1305 }
1306
1307 } else {
1308 if ((flags & SYNC_ATTR) &&
1309 ((ip->i_update_core) ||
1310 ((ip->i_itemp != NULL) &&
1311 (ip->i_itemp->ili_format.ilf_fields != 0)))) {
1312 if (mount_locked) {
1313 IPOINTER_INSERT(ip, mp);
1314 }
1315
1316 if (flags & SYNC_WAIT) {
1317 xfs_iflock(ip);
1318 error = xfs_iflush(ip,
1319 XFS_IFLUSH_SYNC);
1320 } else {
1321 /*
1322 * If we can't acquire the flush
1323 * lock, then the inode is already
1324 * being flushed so don't bother
1325 * waiting. If we can lock it then
1326 * do a delwri flush so we can
1327 * combine multiple inode flushes
1328 * in each disk write.
1329 */
1330 if (xfs_iflock_nowait(ip)) {
1331 error = xfs_iflush(ip,
1332 XFS_IFLUSH_DELWRI);
1333 }
1334 else if (bypassed)
1335 (*bypassed)++;
1336 }
1337 }
1338 }
1339
1340 if (lock_flags != 0) {
1341 xfs_iunlock(ip, lock_flags);
1342 }
1343
1344 if (vnode_refed) {
1345 /*
1346 * If we had to take a reference on the vnode
1347 * above, then wait until after we've unlocked
1348 * the inode to release the reference. This is
1349 * because we can be already holding the inode
1350 * lock when VN_RELE() calls xfs_inactive().
1351 *
1352 * Make sure to drop the mount lock before calling
1353 * VN_RELE() so that we don't trip over ourselves if
1354 * we have to go for the mount lock again in the
1355 * inactive code.
1356 */
1357 if (mount_locked) {
1358 IPOINTER_INSERT(ip, mp);
1359 }
1360
1361 VN_RELE(vp);
1362
1363 vnode_refed = B_FALSE;
1364 }
1365
1366 if (error) {
1367 last_error = error;
1368 }
1369
1370 /*
1371 * bail out if the filesystem is corrupted.
1372 */
1373 if (error == EFSCORRUPTED) {
1374 if (!mount_locked) {
1375 XFS_MOUNT_ILOCK(mp);
1376 IPOINTER_REMOVE(ip, mp);
1377 }
1378 XFS_MOUNT_IUNLOCK(mp);
1379 ASSERT(ipointer_in == B_FALSE);
1380 kmem_free(ipointer, sizeof(xfs_iptr_t));
1381 return XFS_ERROR(error);
1382 }
1383
1384 /* Let other threads have a chance at the mount lock
1385 * if we have looped many times without dropping the
1386 * lock.
1387 */
1388 if ((++preempt & XFS_PREEMPT_MASK) == 0) {
1389 if (mount_locked) {
1390 IPOINTER_INSERT(ip, mp);
1391 }
1392 }
1393
1394 if (mount_locked == B_FALSE) {
1395 XFS_MOUNT_ILOCK(mp);
1396 mount_locked = B_TRUE;
1397 IPOINTER_REMOVE(ip, mp);
1398 continue;
1399 }
1400
1401 ASSERT(ipointer_in == B_FALSE);
1402 ip = ip->i_mnext;
1403
1404 } while (ip != mp->m_inodes);
1405
1406 XFS_MOUNT_IUNLOCK(mp);
1407
1408 ASSERT(ipointer_in == B_FALSE);
1409
1410 kmem_free(ipointer, sizeof(xfs_iptr_t));
1411 return XFS_ERROR(last_error);
1412}
1413
1414/*
1415 * xfs sync routine for internal use
1416 *
1417 * This routine supports all of the flags defined for the generic VFS_SYNC
1418 * interface as explained above under xfs_sync. In the interests of not
1419 * changing interfaces within the 6.5 family, additional internallly-
1420 * required functions are specified within a separate xflags parameter,
1421 * only available by calling this routine.
1422 *
1423 */
1424int
1425xfs_syncsub(
1426 xfs_mount_t *mp,
1427 int flags,
1428 int xflags,
1429 int *bypassed)
1430{
1431 int error = 0;
1432 int last_error = 0;
1433 uint log_flags = XFS_LOG_FORCE;
1434 xfs_buf_t *bp;
1435 xfs_buf_log_item_t *bip;
1436
1437 /*
1438 * Sync out the log. This ensures that the log is periodically
1439 * flushed even if there is not enough activity to fill it up.
1440 */
1441 if (flags & SYNC_WAIT)
1442 log_flags |= XFS_LOG_SYNC;
1443
1444 xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
1445
1446 if (flags & (SYNC_ATTR|SYNC_DELWRI)) {
1447 if (flags & SYNC_BDFLUSH)
1448 xfs_finish_reclaim_all(mp, 1);
1449 else
1450 error = xfs_sync_inodes(mp, flags, xflags, bypassed);
1451 }
1452
1453 /*
1454 * Flushing out dirty data above probably generated more
1455 * log activity, so if this isn't vfs_sync() then flush
1456 * the log again.
1457 */
1458 if (flags & SYNC_DELWRI) {
1459 xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
1460 }
1461
1462 if (flags & SYNC_FSDATA) {
1463 /*
1464 * If this is vfs_sync() then only sync the superblock
1465 * if we can lock it without sleeping and it is not pinned.
1466 */
1467 if (flags & SYNC_BDFLUSH) {
1468 bp = xfs_getsb(mp, XFS_BUF_TRYLOCK);
1469 if (bp != NULL) {
1470 bip = XFS_BUF_FSPRIVATE(bp,xfs_buf_log_item_t*);
1471 if ((bip != NULL) &&
1472 xfs_buf_item_dirty(bip)) {
1473 if (!(XFS_BUF_ISPINNED(bp))) {
1474 XFS_BUF_ASYNC(bp);
1475 error = xfs_bwrite(mp, bp);
1476 } else {
1477 xfs_buf_relse(bp);
1478 }
1479 } else {
1480 xfs_buf_relse(bp);
1481 }
1482 }
1483 } else {
1484 bp = xfs_getsb(mp, 0);
1485 /*
1486 * If the buffer is pinned then push on the log so
1487 * we won't get stuck waiting in the write for
1488 * someone, maybe ourselves, to flush the log.
1489 * Even though we just pushed the log above, we
1490 * did not have the superblock buffer locked at
1491 * that point so it can become pinned in between
1492 * there and here.
1493 */
1494 if (XFS_BUF_ISPINNED(bp))
1495 xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);
1496 if (flags & SYNC_WAIT)
1497 XFS_BUF_UNASYNC(bp);
1498 else
1499 XFS_BUF_ASYNC(bp);
1500 error = xfs_bwrite(mp, bp);
1501 }
1502 if (error) {
1503 last_error = error;
1504 }
1505 }
1506
1507 /*
1508 * If this is the periodic sync, then kick some entries out of
1509 * the reference cache. This ensures that idle entries are
1510 * eventually kicked out of the cache.
1511 */
1512 if (flags & SYNC_REFCACHE) {
Nathan Scottcde410a2005-09-05 11:47:01 +10001513 if (flags & SYNC_WAIT)
1514 xfs_refcache_purge_mp(mp);
1515 else
1516 xfs_refcache_purge_some(mp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 }
1518
1519 /*
1520 * Now check to see if the log needs a "dummy" transaction.
1521 */
1522
1523 if (!(flags & SYNC_REMOUNT) && xfs_log_need_covered(mp)) {
1524 xfs_trans_t *tp;
1525 xfs_inode_t *ip;
1526
1527 /*
1528 * Put a dummy transaction in the log to tell
1529 * recovery that all others are OK.
1530 */
1531 tp = xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
1532 if ((error = xfs_trans_reserve(tp, 0,
1533 XFS_ICHANGE_LOG_RES(mp),
1534 0, 0, 0))) {
1535 xfs_trans_cancel(tp, 0);
1536 return error;
1537 }
1538
1539 ip = mp->m_rootip;
1540 xfs_ilock(ip, XFS_ILOCK_EXCL);
1541
1542 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
1543 xfs_trans_ihold(tp, ip);
1544 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1545 error = xfs_trans_commit(tp, 0, NULL);
1546 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1547 xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
1548 }
1549
1550 /*
1551 * When shutting down, we need to insure that the AIL is pushed
1552 * to disk or the filesystem can appear corrupt from the PROM.
1553 */
1554 if ((flags & (SYNC_CLOSE|SYNC_WAIT)) == (SYNC_CLOSE|SYNC_WAIT)) {
1555 XFS_bflush(mp->m_ddev_targp);
1556 if (mp->m_rtdev_targp) {
1557 XFS_bflush(mp->m_rtdev_targp);
1558 }
1559 }
1560
1561 return XFS_ERROR(last_error);
1562}
1563
1564/*
1565 * xfs_vget - called by DMAPI and NFSD to get vnode from file handle
1566 */
1567STATIC int
1568xfs_vget(
1569 bhv_desc_t *bdp,
1570 vnode_t **vpp,
1571 fid_t *fidp)
1572{
1573 xfs_mount_t *mp = XFS_BHVTOM(bdp);
1574 xfs_fid_t *xfid = (struct xfs_fid *)fidp;
1575 xfs_inode_t *ip;
1576 int error;
1577 xfs_ino_t ino;
1578 unsigned int igen;
1579
1580 /*
1581 * Invalid. Since handles can be created in user space and passed in
1582 * via gethandle(), this is not cause for a panic.
1583 */
1584 if (xfid->xfs_fid_len != sizeof(*xfid) - sizeof(xfid->xfs_fid_len))
1585 return XFS_ERROR(EINVAL);
1586
1587 ino = xfid->xfs_fid_ino;
1588 igen = xfid->xfs_fid_gen;
1589
1590 /*
1591 * NFS can sometimes send requests for ino 0. Fail them gracefully.
1592 */
1593 if (ino == 0)
1594 return XFS_ERROR(ESTALE);
1595
1596 error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0);
1597 if (error) {
1598 *vpp = NULL;
1599 return error;
1600 }
1601
1602 if (ip == NULL) {
1603 *vpp = NULL;
1604 return XFS_ERROR(EIO);
1605 }
1606
1607 if (ip->i_d.di_mode == 0 || ip->i_d.di_gen != igen) {
1608 xfs_iput_new(ip, XFS_ILOCK_SHARED);
1609 *vpp = NULL;
1610 return XFS_ERROR(ENOENT);
1611 }
1612
1613 *vpp = XFS_ITOV(ip);
1614 xfs_iunlock(ip, XFS_ILOCK_SHARED);
1615 return 0;
1616}
1617
1618
1619#define MNTOPT_LOGBUFS "logbufs" /* number of XFS log buffers */
1620#define MNTOPT_LOGBSIZE "logbsize" /* size of XFS log buffers */
1621#define MNTOPT_LOGDEV "logdev" /* log device */
1622#define MNTOPT_RTDEV "rtdev" /* realtime I/O device */
1623#define MNTOPT_BIOSIZE "biosize" /* log2 of preferred buffered io size */
1624#define MNTOPT_WSYNC "wsync" /* safe-mode nfs compatible mount */
1625#define MNTOPT_INO64 "ino64" /* force inodes into 64-bit range */
1626#define MNTOPT_NOALIGN "noalign" /* turn off stripe alignment */
1627#define MNTOPT_SWALLOC "swalloc" /* turn on stripe width allocation */
1628#define MNTOPT_SUNIT "sunit" /* data volume stripe unit */
1629#define MNTOPT_SWIDTH "swidth" /* data volume stripe width */
1630#define MNTOPT_NOUUID "nouuid" /* ignore filesystem UUID */
1631#define MNTOPT_MTPT "mtpt" /* filesystem mount point */
Nathan Scotte69a3332005-09-02 16:42:26 +10001632#define MNTOPT_GRPID "grpid" /* group-ID from parent directory */
1633#define MNTOPT_NOGRPID "nogrpid" /* group-ID from current process */
1634#define MNTOPT_BSDGROUPS "bsdgroups" /* group-ID from parent directory */
1635#define MNTOPT_SYSVGROUPS "sysvgroups" /* group-ID from current process */
Nathan Scott1f443ad2005-05-05 13:28:29 -07001636#define MNTOPT_ALLOCSIZE "allocsize" /* preferred allocation size */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637#define MNTOPT_IHASHSIZE "ihashsize" /* size of inode hash table */
1638#define MNTOPT_NORECOVERY "norecovery" /* don't run XFS recovery */
Christoph Hellwigf538d4d2005-11-02 10:26:59 +11001639#define MNTOPT_BARRIER "barrier" /* use writer barriers for log write and
Nathan Scottd8cc8902005-11-02 10:34:53 +11001640 * unwritten extent conversion */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641#define MNTOPT_OSYNCISOSYNC "osyncisosync" /* o_sync is REALLY o_sync */
1642#define MNTOPT_64BITINODE "inode64" /* inodes can be allocated anywhere */
1643#define MNTOPT_IKEEP "ikeep" /* do not free empty inode clusters */
1644#define MNTOPT_NOIKEEP "noikeep" /* free empty inode clusters */
David Chinnere8c8b3a2005-11-02 10:33:05 +11001645#define MNTOPT_LARGEIO "largeio" /* report large I/O sizes in stat() */
1646#define MNTOPT_NOLARGEIO "nolargeio" /* do not report large I/O sizes
1647 * in stat(). */
Nathan Scottd8cc8902005-11-02 10:34:53 +11001648#define MNTOPT_ATTR2 "attr2" /* do use attr2 attribute format */
1649#define MNTOPT_NOATTR2 "noattr2" /* do not use attr2 attribute format */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650
Nathan Scott1f443ad2005-05-05 13:28:29 -07001651STATIC unsigned long
1652suffix_strtoul(const char *cp, char **endp, unsigned int base)
1653{
1654 int last, shift_left_factor = 0;
1655 char *value = (char *)cp;
1656
1657 last = strlen(value) - 1;
1658 if (value[last] == 'K' || value[last] == 'k') {
1659 shift_left_factor = 10;
1660 value[last] = '\0';
1661 }
1662 if (value[last] == 'M' || value[last] == 'm') {
1663 shift_left_factor = 20;
1664 value[last] = '\0';
1665 }
1666 if (value[last] == 'G' || value[last] == 'g') {
1667 shift_left_factor = 30;
1668 value[last] = '\0';
1669 }
1670
1671 return simple_strtoul(cp, endp, base) << shift_left_factor;
1672}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673
Christoph Hellwigba0f32d2005-06-21 15:36:52 +10001674STATIC int
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675xfs_parseargs(
1676 struct bhv_desc *bhv,
1677 char *options,
1678 struct xfs_mount_args *args,
1679 int update)
1680{
1681 struct vfs *vfsp = bhvtovfs(bhv);
1682 char *this_char, *value, *eov;
1683 int dsunit, dswidth, vol_dsunit, vol_dswidth;
1684 int iosize;
1685
David Chinnere8c8b3a2005-11-02 10:33:05 +11001686 args->flags |= XFSMNT_COMPAT_IOSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687#if 0 /* XXX: off by default, until some remaining issues ironed out */
1688 args->flags |= XFSMNT_IDELETE; /* default to on */
1689#endif
1690
1691 if (!options)
1692 return 0;
1693
1694 iosize = dsunit = dswidth = vol_dsunit = vol_dswidth = 0;
1695
1696 while ((this_char = strsep(&options, ",")) != NULL) {
1697 if (!*this_char)
1698 continue;
1699 if ((value = strchr(this_char, '=')) != NULL)
1700 *value++ = 0;
1701
1702 if (!strcmp(this_char, MNTOPT_LOGBUFS)) {
1703 if (!value || !*value) {
1704 printk("XFS: %s option requires an argument\n",
Nathan Scott1f443ad2005-05-05 13:28:29 -07001705 this_char);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 return EINVAL;
1707 }
1708 args->logbufs = simple_strtoul(value, &eov, 10);
1709 } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710 if (!value || !*value) {
1711 printk("XFS: %s option requires an argument\n",
Nathan Scott1f443ad2005-05-05 13:28:29 -07001712 this_char);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 return EINVAL;
1714 }
Nathan Scott1f443ad2005-05-05 13:28:29 -07001715 args->logbufsize = suffix_strtoul(value, &eov, 10);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 } else if (!strcmp(this_char, MNTOPT_LOGDEV)) {
1717 if (!value || !*value) {
1718 printk("XFS: %s option requires an argument\n",
Nathan Scott1f443ad2005-05-05 13:28:29 -07001719 this_char);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 return EINVAL;
1721 }
1722 strncpy(args->logname, value, MAXNAMELEN);
1723 } else if (!strcmp(this_char, MNTOPT_MTPT)) {
1724 if (!value || !*value) {
1725 printk("XFS: %s option requires an argument\n",
Nathan Scott1f443ad2005-05-05 13:28:29 -07001726 this_char);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 return EINVAL;
1728 }
1729 strncpy(args->mtpt, value, MAXNAMELEN);
1730 } else if (!strcmp(this_char, MNTOPT_RTDEV)) {
1731 if (!value || !*value) {
1732 printk("XFS: %s option requires an argument\n",
Nathan Scott1f443ad2005-05-05 13:28:29 -07001733 this_char);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734 return EINVAL;
1735 }
1736 strncpy(args->rtname, value, MAXNAMELEN);
1737 } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) {
1738 if (!value || !*value) {
1739 printk("XFS: %s option requires an argument\n",
Nathan Scott1f443ad2005-05-05 13:28:29 -07001740 this_char);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 return EINVAL;
1742 }
1743 iosize = simple_strtoul(value, &eov, 10);
1744 args->flags |= XFSMNT_IOSIZE;
1745 args->iosizelog = (uint8_t) iosize;
Nathan Scott1f443ad2005-05-05 13:28:29 -07001746 } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) {
1747 if (!value || !*value) {
1748 printk("XFS: %s option requires an argument\n",
1749 this_char);
1750 return EINVAL;
1751 }
1752 iosize = suffix_strtoul(value, &eov, 10);
1753 args->flags |= XFSMNT_IOSIZE;
1754 args->iosizelog = ffs(iosize) - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 } else if (!strcmp(this_char, MNTOPT_IHASHSIZE)) {
1756 if (!value || !*value) {
1757 printk("XFS: %s option requires an argument\n",
Nathan Scott1f443ad2005-05-05 13:28:29 -07001758 this_char);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 return EINVAL;
1760 }
1761 args->flags |= XFSMNT_IHASHSIZE;
1762 args->ihashsize = simple_strtoul(value, &eov, 10);
Nathan Scotte69a3332005-09-02 16:42:26 +10001763 } else if (!strcmp(this_char, MNTOPT_GRPID) ||
1764 !strcmp(this_char, MNTOPT_BSDGROUPS)) {
1765 vfsp->vfs_flag |= VFS_GRPID;
1766 } else if (!strcmp(this_char, MNTOPT_NOGRPID) ||
1767 !strcmp(this_char, MNTOPT_SYSVGROUPS)) {
1768 vfsp->vfs_flag &= ~VFS_GRPID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 } else if (!strcmp(this_char, MNTOPT_WSYNC)) {
1770 args->flags |= XFSMNT_WSYNC;
1771 } else if (!strcmp(this_char, MNTOPT_OSYNCISOSYNC)) {
1772 args->flags |= XFSMNT_OSYNCISOSYNC;
1773 } else if (!strcmp(this_char, MNTOPT_NORECOVERY)) {
1774 args->flags |= XFSMNT_NORECOVERY;
1775 } else if (!strcmp(this_char, MNTOPT_INO64)) {
1776 args->flags |= XFSMNT_INO64;
1777#if !XFS_BIG_INUMS
1778 printk("XFS: %s option not allowed on this system\n",
Nathan Scott1f443ad2005-05-05 13:28:29 -07001779 this_char);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780 return EINVAL;
1781#endif
1782 } else if (!strcmp(this_char, MNTOPT_NOALIGN)) {
1783 args->flags |= XFSMNT_NOALIGN;
1784 } else if (!strcmp(this_char, MNTOPT_SWALLOC)) {
1785 args->flags |= XFSMNT_SWALLOC;
1786 } else if (!strcmp(this_char, MNTOPT_SUNIT)) {
1787 if (!value || !*value) {
1788 printk("XFS: %s option requires an argument\n",
Nathan Scott1f443ad2005-05-05 13:28:29 -07001789 this_char);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790 return EINVAL;
1791 }
1792 dsunit = simple_strtoul(value, &eov, 10);
1793 } else if (!strcmp(this_char, MNTOPT_SWIDTH)) {
1794 if (!value || !*value) {
1795 printk("XFS: %s option requires an argument\n",
Nathan Scott1f443ad2005-05-05 13:28:29 -07001796 this_char);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 return EINVAL;
1798 }
1799 dswidth = simple_strtoul(value, &eov, 10);
1800 } else if (!strcmp(this_char, MNTOPT_64BITINODE)) {
1801 args->flags &= ~XFSMNT_32BITINODES;
1802#if !XFS_BIG_INUMS
1803 printk("XFS: %s option not allowed on this system\n",
Nathan Scott1f443ad2005-05-05 13:28:29 -07001804 this_char);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 return EINVAL;
1806#endif
1807 } else if (!strcmp(this_char, MNTOPT_NOUUID)) {
1808 args->flags |= XFSMNT_NOUUID;
Christoph Hellwigf538d4d2005-11-02 10:26:59 +11001809 } else if (!strcmp(this_char, MNTOPT_BARRIER)) {
1810 args->flags |= XFSMNT_BARRIER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811 } else if (!strcmp(this_char, MNTOPT_IKEEP)) {
1812 args->flags &= ~XFSMNT_IDELETE;
1813 } else if (!strcmp(this_char, MNTOPT_NOIKEEP)) {
1814 args->flags |= XFSMNT_IDELETE;
David Chinnere8c8b3a2005-11-02 10:33:05 +11001815 } else if (!strcmp(this_char, MNTOPT_LARGEIO)) {
1816 args->flags &= ~XFSMNT_COMPAT_IOSIZE;
1817 } else if (!strcmp(this_char, MNTOPT_NOLARGEIO)) {
1818 args->flags |= XFSMNT_COMPAT_IOSIZE;
Nathan Scottd8cc8902005-11-02 10:34:53 +11001819 } else if (!strcmp(this_char, MNTOPT_ATTR2)) {
1820 args->flags &= ~XFSMNT_COMPAT_ATTR;
1821 } else if (!strcmp(this_char, MNTOPT_NOATTR2)) {
1822 args->flags |= XFSMNT_COMPAT_ATTR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823 } else if (!strcmp(this_char, "osyncisdsync")) {
1824 /* no-op, this is now the default */
1825printk("XFS: osyncisdsync is now the default, option is deprecated.\n");
1826 } else if (!strcmp(this_char, "irixsgid")) {
1827printk("XFS: irixsgid is now a sysctl(2) variable, option is deprecated.\n");
1828 } else {
1829 printk("XFS: unknown mount option [%s].\n", this_char);
1830 return EINVAL;
1831 }
1832 }
1833
1834 if (args->flags & XFSMNT_NORECOVERY) {
1835 if ((vfsp->vfs_flag & VFS_RDONLY) == 0) {
1836 printk("XFS: no-recovery mounts must be read-only.\n");
1837 return EINVAL;
1838 }
1839 }
1840
1841 if ((args->flags & XFSMNT_NOALIGN) && (dsunit || dswidth)) {
1842 printk(
1843 "XFS: sunit and swidth options incompatible with the noalign option\n");
1844 return EINVAL;
1845 }
1846
1847 if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
1848 printk("XFS: sunit and swidth must be specified together\n");
1849 return EINVAL;
1850 }
1851
1852 if (dsunit && (dswidth % dsunit != 0)) {
1853 printk(
1854 "XFS: stripe width (%d) must be a multiple of the stripe unit (%d)\n",
1855 dswidth, dsunit);
1856 return EINVAL;
1857 }
1858
1859 if ((args->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) {
1860 if (dsunit) {
1861 args->sunit = dsunit;
1862 args->flags |= XFSMNT_RETERR;
1863 } else {
1864 args->sunit = vol_dsunit;
1865 }
1866 dswidth ? (args->swidth = dswidth) :
1867 (args->swidth = vol_dswidth);
1868 } else {
1869 args->sunit = args->swidth = 0;
1870 }
1871
1872 return 0;
1873}
1874
Christoph Hellwigba0f32d2005-06-21 15:36:52 +10001875STATIC int
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876xfs_showargs(
1877 struct bhv_desc *bhv,
1878 struct seq_file *m)
1879{
1880 static struct proc_xfs_info {
1881 int flag;
1882 char *str;
1883 } xfs_info[] = {
1884 /* the few simple ones we can get from the mount struct */
1885 { XFS_MOUNT_WSYNC, "," MNTOPT_WSYNC },
1886 { XFS_MOUNT_INO64, "," MNTOPT_INO64 },
1887 { XFS_MOUNT_NOALIGN, "," MNTOPT_NOALIGN },
1888 { XFS_MOUNT_SWALLOC, "," MNTOPT_SWALLOC },
1889 { XFS_MOUNT_NOUUID, "," MNTOPT_NOUUID },
1890 { XFS_MOUNT_NORECOVERY, "," MNTOPT_NORECOVERY },
1891 { XFS_MOUNT_OSYNCISOSYNC, "," MNTOPT_OSYNCISOSYNC },
Christoph Hellwigf538d4d2005-11-02 10:26:59 +11001892 { XFS_MOUNT_BARRIER, "," MNTOPT_BARRIER },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893 { XFS_MOUNT_IDELETE, "," MNTOPT_NOIKEEP },
1894 { 0, NULL }
1895 };
1896 struct proc_xfs_info *xfs_infop;
1897 struct xfs_mount *mp = XFS_BHVTOM(bhv);
Nathan Scotte69a3332005-09-02 16:42:26 +10001898 struct vfs *vfsp = XFS_MTOVFS(mp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899
1900 for (xfs_infop = xfs_info; xfs_infop->flag; xfs_infop++) {
1901 if (mp->m_flags & xfs_infop->flag)
1902 seq_puts(m, xfs_infop->str);
1903 }
1904
1905 if (mp->m_flags & XFS_MOUNT_IHASHSIZE)
1906 seq_printf(m, "," MNTOPT_IHASHSIZE "=%d", mp->m_ihsize);
1907
1908 if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)
Nathan Scott1f443ad2005-05-05 13:28:29 -07001909 seq_printf(m, "," MNTOPT_ALLOCSIZE "=%d", 1<<mp->m_writeio_log);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910
1911 if (mp->m_logbufs > 0)
1912 seq_printf(m, "," MNTOPT_LOGBUFS "=%d", mp->m_logbufs);
1913
1914 if (mp->m_logbsize > 0)
1915 seq_printf(m, "," MNTOPT_LOGBSIZE "=%d", mp->m_logbsize);
1916
1917 if (mp->m_ddev_targp != mp->m_logdev_targp)
1918 seq_printf(m, "," MNTOPT_LOGDEV "=%s",
1919 XFS_BUFTARG_NAME(mp->m_logdev_targp));
1920
1921 if (mp->m_rtdev_targp && mp->m_ddev_targp != mp->m_rtdev_targp)
1922 seq_printf(m, "," MNTOPT_RTDEV "=%s",
1923 XFS_BUFTARG_NAME(mp->m_rtdev_targp));
1924
1925 if (mp->m_dalign > 0)
1926 seq_printf(m, "," MNTOPT_SUNIT "=%d",
1927 (int)XFS_FSB_TO_BB(mp, mp->m_dalign));
1928
1929 if (mp->m_swidth > 0)
1930 seq_printf(m, "," MNTOPT_SWIDTH "=%d",
1931 (int)XFS_FSB_TO_BB(mp, mp->m_swidth));
1932
1933 if (!(mp->m_flags & XFS_MOUNT_32BITINOOPT))
1934 seq_printf(m, "," MNTOPT_64BITINODE);
Nathan Scotte69a3332005-09-02 16:42:26 +10001935
1936 if (vfsp->vfs_flag & VFS_GRPID)
1937 seq_printf(m, "," MNTOPT_GRPID);
1938
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939 return 0;
1940}
1941
1942STATIC void
1943xfs_freeze(
1944 bhv_desc_t *bdp)
1945{
1946 xfs_mount_t *mp = XFS_BHVTOM(bdp);
1947
1948 while (atomic_read(&mp->m_active_trans) > 0)
1949 delay(100);
1950
1951 /* Push the superblock and write an unmount record */
1952 xfs_log_unmount_write(mp);
1953 xfs_unmountfs_writesb(mp);
1954}
1955
1956
1957vfsops_t xfs_vfsops = {
1958 BHV_IDENTITY_INIT(VFS_BHV_XFS,VFS_POSITION_XFS),
1959 .vfs_parseargs = xfs_parseargs,
1960 .vfs_showargs = xfs_showargs,
1961 .vfs_mount = xfs_mount,
1962 .vfs_unmount = xfs_unmount,
1963 .vfs_mntupdate = xfs_mntupdate,
1964 .vfs_root = xfs_root,
1965 .vfs_statvfs = xfs_statvfs,
1966 .vfs_sync = xfs_sync,
1967 .vfs_vget = xfs_vget,
1968 .vfs_dmapiops = (vfs_dmapiops_t)fs_nosys,
1969 .vfs_quotactl = (vfs_quotactl_t)fs_nosys,
1970 .vfs_init_vnode = xfs_initialize_vnode,
1971 .vfs_force_shutdown = xfs_do_force_shutdown,
1972 .vfs_freeze = xfs_freeze,
1973};