1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include "xfs.h"
19#include "xfs_fs.h"
20#include "xfs_types.h"
21#include "xfs_bit.h"
22#include "xfs_log.h"
23#include "xfs_inum.h"
24#include "xfs_trans.h"
25#include "xfs_sb.h"
26#include "xfs_ag.h"
27#include "xfs_dir2.h"
28#include "xfs_dmapi.h"
29#include "xfs_mount.h"
30#include "xfs_da_btree.h"
31#include "xfs_bmap_btree.h"
32#include "xfs_ialloc_btree.h"
33#include "xfs_alloc_btree.h"
34#include "xfs_dir2_sf.h"
35#include "xfs_attr_sf.h"
36#include "xfs_dinode.h"
37#include "xfs_inode.h"
38#include "xfs_inode_item.h"
39#include "xfs_btree.h"
40#include "xfs_alloc.h"
41#include "xfs_ialloc.h"
42#include "xfs_quota.h"
43#include "xfs_error.h"
44#include "xfs_bmap.h"
45#include "xfs_rw.h"
46#include "xfs_refcache.h"
47#include "xfs_buf_item.h"
48#include "xfs_log_priv.h"
49#include "xfs_dir2_trace.h"
50#include "xfs_extfree_item.h"
51#include "xfs_acl.h"
52#include "xfs_attr.h"
53#include "xfs_clnt.h"
54#include "xfs_mru_cache.h"
55#include "xfs_filestream.h"
56#include "xfs_fsops.h"
57#include "xfs_vnodeops.h"
58#include "xfs_vfsops.h"
59
60
61int
62xfs_init(void)
63{
64 extern kmem_zone_t *xfs_bmap_free_item_zone;
65 extern kmem_zone_t *xfs_btree_cur_zone;
66 extern kmem_zone_t *xfs_trans_zone;
67 extern kmem_zone_t *xfs_buf_item_zone;
68 extern kmem_zone_t *xfs_dabuf_zone;
69#ifdef XFS_DABUF_DEBUG
70 extern lock_t xfs_dabuf_global_lock;
71 spinlock_init(&xfs_dabuf_global_lock, "xfsda");
72#endif
73
74
75
76
77 xfs_bmap_free_item_zone = kmem_zone_init(sizeof(xfs_bmap_free_item_t),
78 "xfs_bmap_free_item");
79 xfs_btree_cur_zone = kmem_zone_init(sizeof(xfs_btree_cur_t),
80 "xfs_btree_cur");
81 xfs_trans_zone = kmem_zone_init(sizeof(xfs_trans_t), "xfs_trans");
82 xfs_da_state_zone =
83 kmem_zone_init(sizeof(xfs_da_state_t), "xfs_da_state");
84 xfs_dabuf_zone = kmem_zone_init(sizeof(xfs_dabuf_t), "xfs_dabuf");
85 xfs_ifork_zone = kmem_zone_init(sizeof(xfs_ifork_t), "xfs_ifork");
86 xfs_acl_zone_init(xfs_acl_zone, "xfs_acl");
87 xfs_mru_cache_init();
88 xfs_filestream_init();
89
90
91
92
93
94
95 xfs_buf_item_zone =
96 kmem_zone_init((sizeof(xfs_buf_log_item_t) +
97 (((XFS_MAX_BLOCKSIZE / XFS_BLI_CHUNK) /
98 NBWORD) * sizeof(int))),
99 "xfs_buf_item");
100 xfs_efd_zone =
101 kmem_zone_init((sizeof(xfs_efd_log_item_t) +
102 ((XFS_EFD_MAX_FAST_EXTENTS - 1) *
103 sizeof(xfs_extent_t))),
104 "xfs_efd_item");
105 xfs_efi_zone =
106 kmem_zone_init((sizeof(xfs_efi_log_item_t) +
107 ((XFS_EFI_MAX_FAST_EXTENTS - 1) *
108 sizeof(xfs_extent_t))),
109 "xfs_efi_item");
110
111
112
113
114 xfs_inode_zone =
115 kmem_zone_init_flags(sizeof(xfs_inode_t), "xfs_inode",
116 KM_ZONE_HWALIGN | KM_ZONE_RECLAIM |
117 KM_ZONE_SPREAD, NULL);
118 xfs_ili_zone =
119 kmem_zone_init_flags(sizeof(xfs_inode_log_item_t), "xfs_ili",
120 KM_ZONE_SPREAD, NULL);
121 xfs_icluster_zone =
122 kmem_zone_init_flags(sizeof(xfs_icluster_t), "xfs_icluster",
123 KM_ZONE_SPREAD, NULL);
124
125
126
127
128#ifdef XFS_ALLOC_TRACE
129 xfs_alloc_trace_buf = ktrace_alloc(XFS_ALLOC_TRACE_SIZE, KM_SLEEP);
130#endif
131#ifdef XFS_BMAP_TRACE
132 xfs_bmap_trace_buf = ktrace_alloc(XFS_BMAP_TRACE_SIZE, KM_SLEEP);
133#endif
134#ifdef XFS_BMBT_TRACE
135 xfs_bmbt_trace_buf = ktrace_alloc(XFS_BMBT_TRACE_SIZE, KM_SLEEP);
136#endif
137#ifdef XFS_ATTR_TRACE
138 xfs_attr_trace_buf = ktrace_alloc(XFS_ATTR_TRACE_SIZE, KM_SLEEP);
139#endif
140#ifdef XFS_DIR2_TRACE
141 xfs_dir2_trace_buf = ktrace_alloc(XFS_DIR2_GTRACE_SIZE, KM_SLEEP);
142#endif
143
144 xfs_dir_startup();
145
146#if (defined(DEBUG) || defined(INDUCE_IO_ERROR))
147 xfs_error_test_init();
148#endif
149
150 xfs_init_procfs();
151 xfs_sysctl_register();
152 return 0;
153}
154
155void
156xfs_cleanup(void)
157{
158 extern kmem_zone_t *xfs_bmap_free_item_zone;
159 extern kmem_zone_t *xfs_btree_cur_zone;
160 extern kmem_zone_t *xfs_inode_zone;
161 extern kmem_zone_t *xfs_trans_zone;
162 extern kmem_zone_t *xfs_da_state_zone;
163 extern kmem_zone_t *xfs_dabuf_zone;
164 extern kmem_zone_t *xfs_efd_zone;
165 extern kmem_zone_t *xfs_efi_zone;
166 extern kmem_zone_t *xfs_buf_item_zone;
167 extern kmem_zone_t *xfs_icluster_zone;
168
169 xfs_cleanup_procfs();
170 xfs_sysctl_unregister();
171 xfs_refcache_destroy();
172 xfs_filestream_uninit();
173 xfs_mru_cache_uninit();
174 xfs_acl_zone_destroy(xfs_acl_zone);
175
176#ifdef XFS_DIR2_TRACE
177 ktrace_free(xfs_dir2_trace_buf);
178#endif
179#ifdef XFS_ATTR_TRACE
180 ktrace_free(xfs_attr_trace_buf);
181#endif
182#ifdef XFS_BMBT_TRACE
183 ktrace_free(xfs_bmbt_trace_buf);
184#endif
185#ifdef XFS_BMAP_TRACE
186 ktrace_free(xfs_bmap_trace_buf);
187#endif
188#ifdef XFS_ALLOC_TRACE
189 ktrace_free(xfs_alloc_trace_buf);
190#endif
191
192 kmem_zone_destroy(xfs_bmap_free_item_zone);
193 kmem_zone_destroy(xfs_btree_cur_zone);
194 kmem_zone_destroy(xfs_inode_zone);
195 kmem_zone_destroy(xfs_trans_zone);
196 kmem_zone_destroy(xfs_da_state_zone);
197 kmem_zone_destroy(xfs_dabuf_zone);
198 kmem_zone_destroy(xfs_buf_item_zone);
199 kmem_zone_destroy(xfs_efd_zone);
200 kmem_zone_destroy(xfs_efi_zone);
201 kmem_zone_destroy(xfs_ifork_zone);
202 kmem_zone_destroy(xfs_ili_zone);
203 kmem_zone_destroy(xfs_icluster_zone);
204}
205
206
207
208
209
210
211
212STATIC int
213xfs_start_flags(
214 struct xfs_mount_args *ap,
215 struct xfs_mount *mp)
216{
217
218 if ((ap->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) {
219
220
221
222
223
224
225 mp->m_dalign = ap->sunit;
226 mp->m_swidth = ap->swidth;
227 }
228
229 if (ap->logbufs != -1 &&
230 ap->logbufs != 0 &&
231 (ap->logbufs < XLOG_MIN_ICLOGS ||
232 ap->logbufs > XLOG_MAX_ICLOGS)) {
233 cmn_err(CE_WARN,
234 "XFS: invalid logbufs value: %d [not %d-%d]",
235 ap->logbufs, XLOG_MIN_ICLOGS, XLOG_MAX_ICLOGS);
236 return XFS_ERROR(EINVAL);
237 }
238 mp->m_logbufs = ap->logbufs;
239 if (ap->logbufsize != -1 &&
240 ap->logbufsize != 0 &&
241 (ap->logbufsize < XLOG_MIN_RECORD_BSIZE ||
242 ap->logbufsize > XLOG_MAX_RECORD_BSIZE ||
243 !is_power_of_2(ap->logbufsize))) {
244 cmn_err(CE_WARN,
245 "XFS: invalid logbufsize: %d [not 16k,32k,64k,128k or 256k]",
246 ap->logbufsize);
247 return XFS_ERROR(EINVAL);
248 }
249 mp->m_logbsize = ap->logbufsize;
250 mp->m_fsname_len = strlen(ap->fsname) + 1;
251 mp->m_fsname = kmem_alloc(mp->m_fsname_len, KM_SLEEP);
252 strcpy(mp->m_fsname, ap->fsname);
253 if (ap->rtname[0]) {
254 mp->m_rtname = kmem_alloc(strlen(ap->rtname) + 1, KM_SLEEP);
255 strcpy(mp->m_rtname, ap->rtname);
256 }
257 if (ap->logname[0]) {
258 mp->m_logname = kmem_alloc(strlen(ap->logname) + 1, KM_SLEEP);
259 strcpy(mp->m_logname, ap->logname);
260 }
261
262 if (ap->flags & XFSMNT_WSYNC)
263 mp->m_flags |= XFS_MOUNT_WSYNC;
264#if XFS_BIG_INUMS
265 if (ap->flags & XFSMNT_INO64) {
266 mp->m_flags |= XFS_MOUNT_INO64;
267 mp->m_inoadd = XFS_INO64_OFFSET;
268 }
269#endif
270 if (ap->flags & XFSMNT_RETERR)
271 mp->m_flags |= XFS_MOUNT_RETERR;
272 if (ap->flags & XFSMNT_NOALIGN)
273 mp->m_flags |= XFS_MOUNT_NOALIGN;
274 if (ap->flags & XFSMNT_SWALLOC)
275 mp->m_flags |= XFS_MOUNT_SWALLOC;
276 if (ap->flags & XFSMNT_OSYNCISOSYNC)
277 mp->m_flags |= XFS_MOUNT_OSYNCISOSYNC;
278 if (ap->flags & XFSMNT_32BITINODES)
279 mp->m_flags |= XFS_MOUNT_32BITINODES;
280
281 if (ap->flags & XFSMNT_IOSIZE) {
282 if (ap->iosizelog > XFS_MAX_IO_LOG ||
283 ap->iosizelog < XFS_MIN_IO_LOG) {
284 cmn_err(CE_WARN,
285 "XFS: invalid log iosize: %d [not %d-%d]",
286 ap->iosizelog, XFS_MIN_IO_LOG,
287 XFS_MAX_IO_LOG);
288 return XFS_ERROR(EINVAL);
289 }
290
291 mp->m_flags |= XFS_MOUNT_DFLT_IOSIZE;
292 mp->m_readio_log = mp->m_writeio_log = ap->iosizelog;
293 }
294
295 if (ap->flags & XFSMNT_IDELETE)
296 mp->m_flags |= XFS_MOUNT_IDELETE;
297 if (ap->flags & XFSMNT_DIRSYNC)
298 mp->m_flags |= XFS_MOUNT_DIRSYNC;
299 if (ap->flags & XFSMNT_ATTR2)
300 mp->m_flags |= XFS_MOUNT_ATTR2;
301
302 if (ap->flags2 & XFSMNT2_COMPAT_IOSIZE)
303 mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE;
304
305
306
307
308 if (ap->flags & XFSMNT_NORECOVERY) {
309 if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
310 cmn_err(CE_WARN,
311 "XFS: tried to mount a FS read-write without recovery!");
312 return XFS_ERROR(EINVAL);
313 }
314 mp->m_flags |= XFS_MOUNT_NORECOVERY;
315 }
316
317 if (ap->flags & XFSMNT_NOUUID)
318 mp->m_flags |= XFS_MOUNT_NOUUID;
319 if (ap->flags & XFSMNT_BARRIER)
320 mp->m_flags |= XFS_MOUNT_BARRIER;
321 else
322 mp->m_flags &= ~XFS_MOUNT_BARRIER;
323
324 if (ap->flags2 & XFSMNT2_FILESTREAMS)
325 mp->m_flags |= XFS_MOUNT_FILESTREAMS;
326
327 if (ap->flags & XFSMNT_DMAPI)
328 mp->m_flags |= XFS_MOUNT_DMAPI;
329 return 0;
330}
331
332
333
334
335
336STATIC int
337xfs_finish_flags(
338 struct xfs_mount_args *ap,
339 struct xfs_mount *mp)
340{
341 int ronly = (mp->m_flags & XFS_MOUNT_RDONLY);
342
343
344 if (XFS_SB_VERSION_HASLOGV2(&mp->m_sb)) {
345 if ((ap->logbufsize <= 0) &&
346 (mp->m_sb.sb_logsunit > XLOG_BIG_RECORD_BSIZE)) {
347 mp->m_logbsize = mp->m_sb.sb_logsunit;
348 } else if (ap->logbufsize > 0 &&
349 ap->logbufsize < mp->m_sb.sb_logsunit) {
350 cmn_err(CE_WARN,
351 "XFS: logbuf size must be greater than or equal to log stripe size");
352 return XFS_ERROR(EINVAL);
353 }
354 } else {
355
356 if (ap->logbufsize > XLOG_BIG_RECORD_BSIZE) {
357 cmn_err(CE_WARN,
358 "XFS: logbuf size for version 1 logs must be 16K or 32K");
359 return XFS_ERROR(EINVAL);
360 }
361 }
362
363 if (XFS_SB_VERSION_HASATTR2(&mp->m_sb)) {
364 mp->m_flags |= XFS_MOUNT_ATTR2;
365 }
366
367
368
369
370 if ((mp->m_sb.sb_flags & XFS_SBF_READONLY) && !ronly) {
371 cmn_err(CE_WARN,
372 "XFS: cannot mount a read-only filesystem as read-write");
373 return XFS_ERROR(EROFS);
374 }
375
376
377
378
379 if (ap->flags & XFSMNT_SHARED) {
380 if (!XFS_SB_VERSION_HASSHARED(&mp->m_sb))
381 return XFS_ERROR(EINVAL);
382
383
384
385
386
387
388
389 if (!ronly || !(mp->m_sb.sb_flags & XFS_SBF_READONLY) ||
390 (mp->m_sb.sb_shared_vn != 0))
391 return XFS_ERROR(EINVAL);
392
393 mp->m_flags |= XFS_MOUNT_SHARED;
394
395
396
397
398 if (mp->m_sb.sb_shared_vn == 0 && (ap->flags & XFSMNT_DMAPI))
399 return XFS_ERROR(EINVAL);
400 }
401
402 if (ap->flags & XFSMNT_UQUOTA) {
403 mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE);
404 if (ap->flags & XFSMNT_UQUOTAENF)
405 mp->m_qflags |= XFS_UQUOTA_ENFD;
406 }
407
408 if (ap->flags & XFSMNT_GQUOTA) {
409 mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
410 if (ap->flags & XFSMNT_GQUOTAENF)
411 mp->m_qflags |= XFS_OQUOTA_ENFD;
412 } else if (ap->flags & XFSMNT_PQUOTA) {
413 mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
414 if (ap->flags & XFSMNT_PQUOTAENF)
415 mp->m_qflags |= XFS_OQUOTA_ENFD;
416 }
417
418 return 0;
419}
420
421
422
423
424
425
426
427
428
429
430
431
432
433int
434xfs_mount(
435 struct xfs_mount *mp,
436 struct xfs_mount_args *args,
437 cred_t *credp)
438{
439 struct block_device *ddev, *logdev, *rtdev;
440 int flags = 0, error;
441
442 ddev = mp->m_super->s_bdev;
443 logdev = rtdev = NULL;
444
445 error = xfs_dmops_get(mp, args);
446 if (error)
447 return error;
448 error = xfs_qmops_get(mp, args);
449 if (error)
450 return error;
451
452 mp->m_io_ops = xfs_iocore_xfs;
453
454 if (args->flags & XFSMNT_QUIET)
455 flags |= XFS_MFSI_QUIET;
456
457
458
459
460 if (args->logname[0]) {
461 error = xfs_blkdev_get(mp, args->logname, &logdev);
462 if (error)
463 return error;
464 }
465 if (args->rtname[0]) {
466 error = xfs_blkdev_get(mp, args->rtname, &rtdev);
467 if (error) {
468 xfs_blkdev_put(logdev);
469 return error;
470 }
471
472 if (rtdev == ddev || rtdev == logdev) {
473 cmn_err(CE_WARN,
474 "XFS: Cannot mount filesystem with identical rtdev and ddev/logdev.");
475 xfs_blkdev_put(logdev);
476 xfs_blkdev_put(rtdev);
477 return EINVAL;
478 }
479 }
480
481
482
483
484 error = ENOMEM;
485 mp->m_ddev_targp = xfs_alloc_buftarg(ddev, 0);
486 if (!mp->m_ddev_targp) {
487 xfs_blkdev_put(logdev);
488 xfs_blkdev_put(rtdev);
489 return error;
490 }
491 if (rtdev) {
492 mp->m_rtdev_targp = xfs_alloc_buftarg(rtdev, 1);
493 if (!mp->m_rtdev_targp) {
494 xfs_blkdev_put(logdev);
495 xfs_blkdev_put(rtdev);
496 goto error0;
497 }
498 }
499 mp->m_logdev_targp = (logdev && logdev != ddev) ?
500 xfs_alloc_buftarg(logdev, 1) : mp->m_ddev_targp;
501 if (!mp->m_logdev_targp) {
502 xfs_blkdev_put(logdev);
503 xfs_blkdev_put(rtdev);
504 goto error0;
505 }
506
507
508
509
510 error = xfs_start_flags(args, mp);
511 if (error)
512 goto error1;
513 error = xfs_readsb(mp, flags);
514 if (error)
515 goto error1;
516 error = xfs_finish_flags(args, mp);
517 if (error)
518 goto error2;
519
520
521
522
523 error = xfs_setsize_buftarg(mp->m_ddev_targp, mp->m_sb.sb_blocksize,
524 mp->m_sb.sb_sectsize);
525 if (!error && logdev && logdev != ddev) {
526 unsigned int log_sector_size = BBSIZE;
527
528 if (XFS_SB_VERSION_HASSECTOR(&mp->m_sb))
529 log_sector_size = mp->m_sb.sb_logsectsize;
530 error = xfs_setsize_buftarg(mp->m_logdev_targp,
531 mp->m_sb.sb_blocksize,
532 log_sector_size);
533 }
534 if (!error && rtdev)
535 error = xfs_setsize_buftarg(mp->m_rtdev_targp,
536 mp->m_sb.sb_blocksize,
537 mp->m_sb.sb_sectsize);
538 if (error)
539 goto error2;
540
541 if (mp->m_flags & XFS_MOUNT_BARRIER)
542 xfs_mountfs_check_barriers(mp);
543
544 if ((error = xfs_filestream_mount(mp)))
545 goto error2;
546
547 error = XFS_IOINIT(mp, args, flags);
548 if (error)
549 goto error2;
550
551 XFS_SEND_MOUNT(mp, DM_RIGHT_NULL, args->mtpt, args->fsname);
552
553 return 0;
554
555error2:
556 if (mp->m_sb_bp)
557 xfs_freesb(mp);
558error1:
559 xfs_binval(mp->m_ddev_targp);
560 if (logdev && logdev != ddev)
561 xfs_binval(mp->m_logdev_targp);
562 if (rtdev)
563 xfs_binval(mp->m_rtdev_targp);
564error0:
565 xfs_unmountfs_close(mp, credp);
566 xfs_qmops_put(mp);
567 xfs_dmops_put(mp);
568 return error;
569}
570
571int
572xfs_unmount(
573 xfs_mount_t *mp,
574 int flags,
575 cred_t *credp)
576{
577 xfs_inode_t *rip;
578 bhv_vnode_t *rvp;
579 int unmount_event_wanted = 0;
580 int unmount_event_flags = 0;
581 int xfs_unmountfs_needed = 0;
582 int error;
583
584 rip = mp->m_rootip;
585 rvp = XFS_ITOV(rip);
586
587#ifdef HAVE_DMAPI
588 if (mp->m_flags & XFS_MOUNT_DMAPI) {
589 error = XFS_SEND_PREUNMOUNT(mp,
590 rvp, DM_RIGHT_NULL, rvp, DM_RIGHT_NULL,
591 NULL, NULL, 0, 0,
592 (mp->m_dmevmask & (1<<DM_EVENT_PREUNMOUNT))?
593 0:DM_FLAGS_UNWANTED);
594 if (error)
595 return XFS_ERROR(error);
596 unmount_event_wanted = 1;
597 unmount_event_flags = (mp->m_dmevmask & (1<<DM_EVENT_UNMOUNT))?
598 0 : DM_FLAGS_UNWANTED;
599 }
600#endif
601
602
603
604
605 xfs_refcache_purge_mp(mp);
606
607
608
609
610
611
612 xfs_filestream_unmount(mp);
613
614 XFS_bflush(mp->m_ddev_targp);
615 error = xfs_unmount_flush(mp, 0);
616 if (error)
617 goto out;
618
619 ASSERT(vn_count(rvp) == 1);
620
621
622
623
624 VN_RELE(rvp);
625
626
627
628
629
630
631 if (XFS_FORCED_SHUTDOWN(mp)) {
632 error = xfs_sync(mp, SYNC_WAIT | SYNC_CLOSE);
633 ASSERT(error != EFSCORRUPTED);
634 }
635 xfs_unmountfs_needed = 1;
636
637out:
638
639
640
641
642 if (unmount_event_wanted) {
643
644
645
646 XFS_SEND_UNMOUNT(mp, error == 0 ? rvp : NULL,
647 DM_RIGHT_NULL, 0, error, unmount_event_flags);
648 }
649 if (xfs_unmountfs_needed) {
650
651
652
653
654 xfs_unmountfs(mp, credp);
655 xfs_qmops_put(mp);
656 xfs_dmops_put(mp);
657 kmem_free(mp, sizeof(xfs_mount_t));
658 }
659
660 return XFS_ERROR(error);
661}
662
663STATIC int
664xfs_quiesce_fs(
665 xfs_mount_t *mp)
666{
667 int count = 0, pincount;
668
669 xfs_refcache_purge_mp(mp);
670 xfs_flush_buftarg(mp->m_ddev_targp, 0);
671 xfs_finish_reclaim_all(mp, 0);
672
673
674
675
676
677
678
679
680 do {
681 xfs_syncsub(mp, SYNC_INODE_QUIESCE, NULL);
682 pincount = xfs_flush_buftarg(mp->m_ddev_targp, 1);
683 if (!pincount) {
684 delay(50);
685 count++;
686 }
687 } while (count < 2);
688
689 return 0;
690}
691
692
693
694
695
696
697STATIC void
698xfs_attr_quiesce(
699 xfs_mount_t *mp)
700{
701
702 while (atomic_read(&mp->m_active_trans) > 0)
703 delay(100);
704
705
706 xfs_quiesce_fs(mp);
707
708 ASSERT_ALWAYS(atomic_read(&mp->m_active_trans) == 0);
709
710
711 xfs_log_sbcount(mp, 1);
712 xfs_log_unmount_write(mp);
713 xfs_unmountfs_writesb(mp);
714}
715
716int
717xfs_mntupdate(
718 struct xfs_mount *mp,
719 int *flags,
720 struct xfs_mount_args *args)
721{
722 if (!(*flags & MS_RDONLY)) {
723 if (mp->m_flags & XFS_MOUNT_RDONLY)
724 mp->m_flags &= ~XFS_MOUNT_RDONLY;
725 if (args->flags & XFSMNT_BARRIER) {
726 mp->m_flags |= XFS_MOUNT_BARRIER;
727 xfs_mountfs_check_barriers(mp);
728 } else {
729 mp->m_flags &= ~XFS_MOUNT_BARRIER;
730 }
731 } else if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
732 xfs_filestream_flush(mp);
733 xfs_sync(mp, SYNC_DATA_QUIESCE);
734 xfs_attr_quiesce(mp);
735 mp->m_flags |= XFS_MOUNT_RDONLY;
736 }
737 return 0;
738}
739
740
741
742
743
744
745int
746xfs_unmount_flush(
747 xfs_mount_t *mp,
748
749 int relocation)
750{
751 xfs_inode_t *rip = mp->m_rootip;
752 xfs_inode_t *rbmip;
753 xfs_inode_t *rsumip = NULL;
754 bhv_vnode_t *rvp = XFS_ITOV(rip);
755 int error;
756
757 xfs_ilock(rip, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT);
758 xfs_iflock(rip);
759
760
761
762
763 if ((rbmip = mp->m_rbmip) != NULL) {
764 xfs_ilock(rbmip, XFS_ILOCK_EXCL);
765 xfs_iflock(rbmip);
766 error = xfs_iflush(rbmip, XFS_IFLUSH_SYNC);
767 xfs_iunlock(rbmip, XFS_ILOCK_EXCL);
768
769 if (error == EFSCORRUPTED)
770 goto fscorrupt_out;
771
772 ASSERT(vn_count(XFS_ITOV(rbmip)) == 1);
773
774 rsumip = mp->m_rsumip;
775 xfs_ilock(rsumip, XFS_ILOCK_EXCL);
776 xfs_iflock(rsumip);
777 error = xfs_iflush(rsumip, XFS_IFLUSH_SYNC);
778 xfs_iunlock(rsumip, XFS_ILOCK_EXCL);
779
780 if (error == EFSCORRUPTED)
781 goto fscorrupt_out;
782
783 ASSERT(vn_count(XFS_ITOV(rsumip)) == 1);
784 }
785
786
787
788
789 error = xfs_iflush(rip, XFS_IFLUSH_SYNC);
790 if (error == EFSCORRUPTED)
791 goto fscorrupt_out2;
792
793 if (vn_count(rvp) != 1 && !relocation) {
794 xfs_iunlock(rip, XFS_ILOCK_EXCL);
795 return XFS_ERROR(EBUSY);
796 }
797
798
799
800
801
802 error = XFS_QM_UNMOUNT(mp);
803 if (error == EFSCORRUPTED)
804 goto fscorrupt_out2;
805
806 if (rbmip) {
807 VN_RELE(XFS_ITOV(rbmip));
808 VN_RELE(XFS_ITOV(rsumip));
809 }
810
811 xfs_iunlock(rip, XFS_ILOCK_EXCL);
812 return 0;
813
814fscorrupt_out:
815 xfs_ifunlock(rip);
816
817fscorrupt_out2:
818 xfs_iunlock(rip, XFS_ILOCK_EXCL);
819
820 return XFS_ERROR(EFSCORRUPTED);
821}
822
823
824
825
826
827
828
829
830int
831xfs_root(
832 xfs_mount_t *mp,
833 bhv_vnode_t **vpp)
834{
835 bhv_vnode_t *vp;
836
837 vp = XFS_ITOV(mp->m_rootip);
838 VN_HOLD(vp);
839 *vpp = vp;
840 return 0;
841}
842
843
844
845
846
847
848
849
850int
851xfs_statvfs(
852 xfs_mount_t *mp,
853 bhv_statvfs_t *statp,
854 bhv_vnode_t *vp)
855{
856 __uint64_t fakeinos;
857 xfs_extlen_t lsize;
858 xfs_sb_t *sbp;
859 unsigned long s;
860
861 sbp = &(mp->m_sb);
862
863 statp->f_type = XFS_SB_MAGIC;
864
865 xfs_icsb_sync_counters_flags(mp, XFS_ICSB_LAZY_COUNT);
866 s = XFS_SB_LOCK(mp);
867 statp->f_bsize = sbp->sb_blocksize;
868 lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0;
869 statp->f_blocks = sbp->sb_dblocks - lsize;
870 statp->f_bfree = statp->f_bavail =
871 sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
872 fakeinos = statp->f_bfree << sbp->sb_inopblog;
873#if XFS_BIG_INUMS
874 fakeinos += mp->m_inoadd;
875#endif
876 statp->f_files =
877 MIN(sbp->sb_icount + fakeinos, (__uint64_t)XFS_MAXINUMBER);
878 if (mp->m_maxicount)
879#if XFS_BIG_INUMS
880 if (!mp->m_inoadd)
881#endif
882 statp->f_files = min_t(typeof(statp->f_files),
883 statp->f_files,
884 mp->m_maxicount);
885 statp->f_ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree);
886 XFS_SB_UNLOCK(mp, s);
887
888 xfs_statvfs_fsid(statp, mp);
889 statp->f_namelen = MAXNAMELEN - 1;
890
891 if (vp)
892 XFS_QM_DQSTATVFS(xfs_vtoi(vp), statp);
893 return 0;
894}
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939int
940xfs_sync(
941 xfs_mount_t *mp,
942 int flags)
943{
944 int error;
945
946
947
948
949
950
951
952
953 error = XFS_QM_DQSYNC(mp, flags);
954 if (error) {
955
956
957
958
959 ASSERT(error != EIO || XFS_FORCED_SHUTDOWN(mp));
960 if (XFS_FORCED_SHUTDOWN(mp))
961 return XFS_ERROR(error);
962 }
963
964 if (flags & SYNC_IOWAIT)
965 xfs_filestream_flush(mp);
966
967 return xfs_syncsub(mp, flags, NULL);
968}
969
970
971
972
973
974
975
976
977int
978xfs_sync_inodes(
979 xfs_mount_t *mp,
980 int flags,
981 int *bypassed)
982{
983 xfs_inode_t *ip = NULL;
984 xfs_inode_t *ip_next;
985 xfs_buf_t *bp;
986 bhv_vnode_t *vp = NULL;
987 int error;
988 int last_error;
989 uint64_t fflag;
990 uint lock_flags;
991 uint base_lock_flags;
992 boolean_t mount_locked;
993 boolean_t vnode_refed;
994 int preempt;
995 xfs_dinode_t *dip;
996 xfs_iptr_t *ipointer;
997#ifdef DEBUG
998 boolean_t ipointer_in = B_FALSE;
999
1000#define IPOINTER_SET ipointer_in = B_TRUE
1001#define IPOINTER_CLR ipointer_in = B_FALSE
1002#else
1003#define IPOINTER_SET
1004#define IPOINTER_CLR
1005#endif
1006
1007
1008
1009
1010
1011
1012#define IPOINTER_INSERT(ip, mp) { \
1013 ASSERT(ipointer_in == B_FALSE); \
1014 ipointer->ip_mnext = ip->i_mnext; \
1015 ipointer->ip_mprev = ip; \
1016 ip->i_mnext = (xfs_inode_t *)ipointer; \
1017 ipointer->ip_mnext->i_mprev = (xfs_inode_t *)ipointer; \
1018 preempt = 0; \
1019 XFS_MOUNT_IUNLOCK(mp); \
1020 mount_locked = B_FALSE; \
1021 IPOINTER_SET; \
1022 }
1023
1024
1025
1026
1027
1028
1029#define IPOINTER_REMOVE(ip, mp) { \
1030 ASSERT(ipointer_in == B_TRUE); \
1031 if (ipointer->ip_mnext != (xfs_inode_t *)ipointer) { \
1032 ip = ipointer->ip_mnext; \
1033 ip->i_mprev = ipointer->ip_mprev; \
1034 ipointer->ip_mprev->i_mnext = ip; \
1035 if (mp->m_inodes == (xfs_inode_t *)ipointer) { \
1036 mp->m_inodes = ip; \
1037 } \
1038 } else { \
1039 ASSERT(mp->m_inodes == (xfs_inode_t *)ipointer); \
1040 mp->m_inodes = NULL; \
1041 ip = NULL; \
1042 } \
1043 IPOINTER_CLR; \
1044 }
1045
1046#define XFS_PREEMPT_MASK 0x7f
1047
1048 if (bypassed)
1049 *bypassed = 0;
1050 if (mp->m_flags & XFS_MOUNT_RDONLY)
1051 return 0;
1052 error = 0;
1053 last_error = 0;
1054 preempt = 0;
1055
1056
1057 ipointer = (xfs_iptr_t *)kmem_zalloc(sizeof(xfs_iptr_t), KM_SLEEP);
1058
1059 fflag = XFS_B_ASYNC;
1060 if (flags & (SYNC_BDFLUSH | SYNC_DELWRI))
1061 fflag = XFS_B_DELWRI;
1062 if (flags & SYNC_WAIT)
1063 fflag = 0;
1064
1065 base_lock_flags = XFS_ILOCK_SHARED;
1066 if (flags & (SYNC_DELWRI | SYNC_CLOSE)) {
1067
1068
1069
1070
1071 base_lock_flags |= XFS_IOLOCK_SHARED;
1072 }
1073
1074 XFS_MOUNT_ILOCK(mp);
1075
1076 ip = mp->m_inodes;
1077
1078 mount_locked = B_TRUE;
1079 vnode_refed = B_FALSE;
1080
1081 IPOINTER_CLR;
1082
1083 do {
1084 ASSERT(ipointer_in == B_FALSE);
1085 ASSERT(vnode_refed == B_FALSE);
1086
1087 lock_flags = base_lock_flags;
1088
1089
1090
1091
1092
1093 if (ip == NULL) {
1094 break;
1095 }
1096
1097
1098
1099
1100 if (ip->i_mount == NULL) {
1101 ip = ip->i_mnext;
1102 continue;
1103 }
1104
1105 vp = XFS_ITOV_NULL(ip);
1106
1107
1108
1109
1110
1111
1112
1113 if (vp == NULL) {
1114
1115 if (ip->i_flags & XFS_IRECLAIM) {
1116 ip = ip->i_mnext;
1117 continue;
1118 }
1119 if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0) {
1120 ip = ip->i_mnext;
1121 } else if ((xfs_ipincount(ip) == 0) &&
1122 xfs_iflock_nowait(ip)) {
1123 IPOINTER_INSERT(ip, mp);
1124
1125 xfs_finish_reclaim(ip, 1,
1126 XFS_IFLUSH_DELWRI_ELSE_ASYNC);
1127
1128 XFS_MOUNT_ILOCK(mp);
1129 mount_locked = B_TRUE;
1130 IPOINTER_REMOVE(ip, mp);
1131 } else {
1132 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1133 ip = ip->i_mnext;
1134 }
1135 continue;
1136 }
1137
1138 if (VN_BAD(vp)) {
1139 ip = ip->i_mnext;
1140 continue;
1141 }
1142
1143 if (XFS_FORCED_SHUTDOWN(mp) && !(flags & SYNC_CLOSE)) {
1144 XFS_MOUNT_IUNLOCK(mp);
1145 kmem_free(ipointer, sizeof(xfs_iptr_t));
1146 return 0;
1147 }
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157 if (flags & SYNC_BDFLUSH) {
1158 if (((ip->i_itemp == NULL) ||
1159 !(ip->i_itemp->ili_format.ilf_fields &
1160 XFS_ILOG_ALL)) &&
1161 (ip->i_update_core == 0)) {
1162 ip = ip->i_mnext;
1163 continue;
1164 }
1165 }
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183 if (xfs_ilock_nowait(ip, lock_flags) == 0) {
1184 if ((flags & SYNC_BDFLUSH) || (vp == NULL)) {
1185 ip = ip->i_mnext;
1186 continue;
1187 }
1188
1189 vp = vn_grab(vp);
1190 if (vp == NULL) {
1191 ip = ip->i_mnext;
1192 continue;
1193 }
1194
1195 IPOINTER_INSERT(ip, mp);
1196 xfs_ilock(ip, lock_flags);
1197
1198 ASSERT(vp == XFS_ITOV(ip));
1199 ASSERT(ip->i_mount == mp);
1200
1201 vnode_refed = B_TRUE;
1202 }
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214 if ((flags & (SYNC_CLOSE|SYNC_IOWAIT)) ||
1215 ((flags & SYNC_DELWRI) && VN_DIRTY(vp))) {
1216 if (mount_locked) {
1217 IPOINTER_INSERT(ip, mp);
1218 }
1219 xfs_iunlock(ip, XFS_ILOCK_SHARED);
1220
1221 if (flags & SYNC_CLOSE) {
1222
1223 if (XFS_FORCED_SHUTDOWN(mp))
1224 xfs_tosspages(ip, 0, -1,
1225 FI_REMAPF);
1226 else
1227 error = xfs_flushinval_pages(ip,
1228 0, -1, FI_REMAPF);
1229 } else if ((flags & SYNC_DELWRI) && VN_DIRTY(vp)) {
1230 error = xfs_flush_pages(ip, 0,
1231 -1, fflag, FI_NONE);
1232 }
1233
1234
1235
1236
1237
1238
1239 if (flags & SYNC_IOWAIT)
1240 vn_iowait(ip);
1241
1242 xfs_ilock(ip, XFS_ILOCK_SHARED);
1243 }
1244
1245 if (flags & SYNC_BDFLUSH) {
1246 if ((flags & SYNC_ATTR) &&
1247 ((ip->i_update_core) ||
1248 ((ip->i_itemp != NULL) &&
1249 (ip->i_itemp->ili_format.ilf_fields != 0)))) {
1250
1251
1252
1253
1254 if (mount_locked) {
1255 IPOINTER_INSERT(ip, mp);
1256 }
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276 if ((xfs_ipincount(ip) == 0) &&
1277 xfs_iflock_nowait(ip)) {
1278
1279 xfs_ifunlock(ip);
1280 xfs_iunlock(ip, XFS_ILOCK_SHARED);
1281
1282 error = xfs_itobp(mp, NULL, ip,
1283 &dip, &bp, 0, 0);
1284 if (!error) {
1285 xfs_buf_relse(bp);
1286 } else {
1287
1288
1289
1290 XFS_MOUNT_ILOCK(mp);
1291 IPOINTER_REMOVE(ip, mp);
1292 XFS_MOUNT_IUNLOCK(mp);
1293
1294 ASSERT(!(lock_flags &
1295 XFS_IOLOCK_SHARED));
1296
1297 kmem_free(ipointer,
1298 sizeof(xfs_iptr_t));
1299 return (0);
1300 }
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314 XFS_MOUNT_ILOCK(mp);
1315 mount_locked = B_TRUE;
1316
1317 if (ip != ipointer->ip_mprev) {
1318 IPOINTER_REMOVE(ip, mp);
1319
1320 ASSERT(!vnode_refed);
1321 ASSERT(!(lock_flags &
1322 XFS_IOLOCK_SHARED));
1323 continue;
1324 }
1325
1326 ASSERT(ip->i_mount == mp);
1327
1328 if (xfs_ilock_nowait(ip,
1329 XFS_ILOCK_SHARED) == 0) {
1330 ASSERT(ip->i_mount == mp);
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341 lock_flags &= ~XFS_ILOCK_SHARED;
1342 IPOINTER_REMOVE(ip_next, mp);
1343 } else if ((xfs_ipincount(ip) == 0) &&
1344 xfs_iflock_nowait(ip)) {
1345 ASSERT(ip->i_mount == mp);
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357 XFS_MOUNT_IUNLOCK(mp);
1358 mount_locked = B_FALSE;
1359 error = xfs_iflush(ip,
1360 XFS_IFLUSH_DELWRI);
1361 } else {
1362 ASSERT(ip->i_mount == mp);
1363 IPOINTER_REMOVE(ip_next, mp);
1364 }
1365 }
1366
1367 }
1368
1369 } else {
1370 if ((flags & SYNC_ATTR) &&
1371 ((ip->i_update_core) ||
1372 ((ip->i_itemp != NULL) &&
1373 (ip->i_itemp->ili_format.ilf_fields != 0)))) {
1374 if (mount_locked) {
1375 IPOINTER_INSERT(ip, mp);
1376 }
1377
1378 if (flags & SYNC_WAIT) {
1379 xfs_iflock(ip);
1380 error = xfs_iflush(ip,
1381 XFS_IFLUSH_SYNC);
1382 } else {
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392 if (xfs_iflock_nowait(ip)) {
1393 error = xfs_iflush(ip,
1394 XFS_IFLUSH_DELWRI);
1395 }
1396 else if (bypassed)
1397 (*bypassed)++;
1398 }
1399 }
1400 }
1401
1402 if (lock_flags != 0) {
1403 xfs_iunlock(ip, lock_flags);
1404 }
1405
1406 if (vnode_refed) {
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419 if (mount_locked) {
1420 IPOINTER_INSERT(ip, mp);
1421 }
1422
1423 VN_RELE(vp);
1424
1425 vnode_refed = B_FALSE;
1426 }
1427
1428 if (error) {
1429 last_error = error;
1430 }
1431
1432
1433
1434
1435 if (error == EFSCORRUPTED) {
1436 if (!mount_locked) {
1437 XFS_MOUNT_ILOCK(mp);
1438 IPOINTER_REMOVE(ip, mp);
1439 }
1440 XFS_MOUNT_IUNLOCK(mp);
1441 ASSERT(ipointer_in == B_FALSE);
1442 kmem_free(ipointer, sizeof(xfs_iptr_t));
1443 return XFS_ERROR(error);
1444 }
1445
1446
1447
1448
1449
1450 if ((++preempt & XFS_PREEMPT_MASK) == 0) {
1451 if (mount_locked) {
1452 IPOINTER_INSERT(ip, mp);
1453 }
1454 }
1455
1456 if (mount_locked == B_FALSE) {
1457 XFS_MOUNT_ILOCK(mp);
1458 mount_locked = B_TRUE;
1459 IPOINTER_REMOVE(ip, mp);
1460 continue;
1461 }
1462
1463 ASSERT(ipointer_in == B_FALSE);
1464 ip = ip->i_mnext;
1465
1466 } while (ip != mp->m_inodes);
1467
1468 XFS_MOUNT_IUNLOCK(mp);
1469
1470 ASSERT(ipointer_in == B_FALSE);
1471
1472 kmem_free(ipointer, sizeof(xfs_iptr_t));
1473 return XFS_ERROR(last_error);
1474}
1475
1476
1477
1478
1479
1480
1481
1482
1483int
1484xfs_syncsub(
1485 xfs_mount_t *mp,
1486 int flags,
1487 int *bypassed)
1488{
1489 int error = 0;
1490 int last_error = 0;
1491 uint log_flags = XFS_LOG_FORCE;
1492 xfs_buf_t *bp;
1493 xfs_buf_log_item_t *bip;
1494
1495
1496
1497
1498
1499 if (flags & SYNC_WAIT)
1500 log_flags |= XFS_LOG_SYNC;
1501
1502 xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
1503
1504 if (flags & (SYNC_ATTR|SYNC_DELWRI)) {
1505 if (flags & SYNC_BDFLUSH)
1506 xfs_finish_reclaim_all(mp, 1);
1507 else
1508 error = xfs_sync_inodes(mp, flags, bypassed);
1509 }
1510
1511
1512
1513
1514
1515
1516 if (flags & SYNC_DELWRI) {
1517 xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
1518 }
1519
1520 if (flags & SYNC_FSDATA) {
1521
1522
1523
1524
1525 if (flags & SYNC_BDFLUSH) {
1526 bp = xfs_getsb(mp, XFS_BUF_TRYLOCK);
1527 if (bp != NULL) {
1528 bip = XFS_BUF_FSPRIVATE(bp,xfs_buf_log_item_t*);
1529 if ((bip != NULL) &&
1530 xfs_buf_item_dirty(bip)) {
1531 if (!(XFS_BUF_ISPINNED(bp))) {
1532 XFS_BUF_ASYNC(bp);
1533 error = xfs_bwrite(mp, bp);
1534 } else {
1535 xfs_buf_relse(bp);
1536 }
1537 } else {
1538 xfs_buf_relse(bp);
1539 }
1540 }
1541 } else {
1542 bp = xfs_getsb(mp, 0);
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552 if (XFS_BUF_ISPINNED(bp))
1553 xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);
1554 if (flags & SYNC_WAIT)
1555 XFS_BUF_UNASYNC(bp);
1556 else
1557 XFS_BUF_ASYNC(bp);
1558 error = xfs_bwrite(mp, bp);
1559 }
1560 if (error) {
1561 last_error = error;
1562 }
1563 }
1564
1565
1566
1567
1568
1569
1570 if (flags & SYNC_REFCACHE) {
1571 if (flags & SYNC_WAIT)
1572 xfs_refcache_purge_mp(mp);
1573 else
1574 xfs_refcache_purge_some(mp);
1575 }
1576
1577
1578
1579
1580
1581
1582
1583 if (flags & SYNC_SUPER)
1584 xfs_log_sbcount(mp, 0);
1585
1586
1587
1588
1589
1590 if (!(flags & SYNC_REMOUNT) && xfs_log_need_covered(mp)) {
1591 xfs_trans_t *tp;
1592 xfs_inode_t *ip;
1593
1594
1595
1596
1597
1598 tp = xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
1599 if ((error = xfs_trans_reserve(tp, 0,
1600 XFS_ICHANGE_LOG_RES(mp),
1601 0, 0, 0))) {
1602 xfs_trans_cancel(tp, 0);
1603 return error;
1604 }
1605
1606 ip = mp->m_rootip;
1607 xfs_ilock(ip, XFS_ILOCK_EXCL);
1608
1609 xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
1610 xfs_trans_ihold(tp, ip);
1611 xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
1612 error = xfs_trans_commit(tp, 0);
1613 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1614 xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
1615 }
1616
1617
1618
1619
1620
1621 if ((flags & (SYNC_CLOSE|SYNC_WAIT)) == (SYNC_CLOSE|SYNC_WAIT)) {
1622 XFS_bflush(mp->m_ddev_targp);
1623 if (mp->m_rtdev_targp) {
1624 XFS_bflush(mp->m_rtdev_targp);
1625 }
1626 }
1627
1628 return XFS_ERROR(last_error);
1629}
1630
1631
1632
1633
1634int
1635xfs_vget(
1636 xfs_mount_t *mp,
1637 bhv_vnode_t **vpp,
1638 xfs_fid_t *xfid)
1639{
1640 xfs_inode_t *ip;
1641 int error;
1642 xfs_ino_t ino;
1643 unsigned int igen;
1644
1645
1646
1647
1648
1649 if (xfid->fid_len != sizeof(*xfid) - sizeof(xfid->fid_len))
1650 return XFS_ERROR(EINVAL);
1651
1652 ino = xfid->fid_ino;
1653 igen = xfid->fid_gen;
1654
1655
1656
1657
1658 if (ino == 0)
1659 return XFS_ERROR(ESTALE);
1660
1661 error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, 0);
1662 if (error) {
1663 *vpp = NULL;
1664 return error;
1665 }
1666
1667 if (ip == NULL) {
1668 *vpp = NULL;
1669 return XFS_ERROR(EIO);
1670 }
1671
1672 if (ip->i_d.di_mode == 0 || ip->i_d.di_gen != igen) {
1673 xfs_iput_new(ip, XFS_ILOCK_SHARED);
1674 *vpp = NULL;
1675 return XFS_ERROR(ENOENT);
1676 }
1677
1678 *vpp = XFS_ITOV(ip);
1679 xfs_iunlock(ip, XFS_ILOCK_SHARED);
1680 return 0;
1681}
1682
1683
1684#define MNTOPT_LOGBUFS "logbufs"
1685#define MNTOPT_LOGBSIZE "logbsize"
1686#define MNTOPT_LOGDEV "logdev"
1687#define MNTOPT_RTDEV "rtdev"
1688#define MNTOPT_BIOSIZE "biosize"
1689#define MNTOPT_WSYNC "wsync"
1690#define MNTOPT_INO64 "ino64"
1691#define MNTOPT_NOALIGN "noalign"
1692#define MNTOPT_SWALLOC "swalloc"
1693#define MNTOPT_SUNIT "sunit"
1694#define MNTOPT_SWIDTH "swidth"
1695#define MNTOPT_NOUUID "nouuid"
1696#define MNTOPT_MTPT "mtpt"
1697#define MNTOPT_GRPID "grpid"
1698#define MNTOPT_NOGRPID "nogrpid"
1699#define MNTOPT_BSDGROUPS "bsdgroups"
1700#define MNTOPT_SYSVGROUPS "sysvgroups"
1701#define MNTOPT_ALLOCSIZE "allocsize"
1702#define MNTOPT_NORECOVERY "norecovery"
1703#define MNTOPT_BARRIER "barrier"
1704
1705#define MNTOPT_NOBARRIER "nobarrier"
1706#define MNTOPT_OSYNCISOSYNC "osyncisosync"
1707#define MNTOPT_64BITINODE "inode64"
1708#define MNTOPT_IKEEP "ikeep"
1709#define MNTOPT_NOIKEEP "noikeep"
1710#define MNTOPT_LARGEIO "largeio"
1711#define MNTOPT_NOLARGEIO "nolargeio"
1712
1713#define MNTOPT_ATTR2 "attr2"
1714#define MNTOPT_NOATTR2 "noattr2"
1715#define MNTOPT_FILESTREAM "filestreams"
1716#define MNTOPT_QUOTA "quota"
1717#define MNTOPT_NOQUOTA "noquota"
1718#define MNTOPT_USRQUOTA "usrquota"
1719#define MNTOPT_GRPQUOTA "grpquota"
1720#define MNTOPT_PRJQUOTA "prjquota"
1721#define MNTOPT_UQUOTA "uquota"
1722#define MNTOPT_GQUOTA "gquota"
1723#define MNTOPT_PQUOTA "pquota"
1724#define MNTOPT_UQUOTANOENF "uqnoenforce"
1725#define MNTOPT_GQUOTANOENF "gqnoenforce"
1726#define MNTOPT_PQUOTANOENF "pqnoenforce"
1727#define MNTOPT_QUOTANOENF "qnoenforce"
1728#define MNTOPT_DMAPI "dmapi"
1729#define MNTOPT_XDSM "xdsm"
1730#define MNTOPT_DMI "dmi"
1731
1732STATIC unsigned long
1733suffix_strtoul(char *s, char **endp, unsigned int base)
1734{
1735 int last, shift_left_factor = 0;
1736 char *value = s;
1737
1738 last = strlen(value) - 1;
1739 if (value[last] == 'K' || value[last] == 'k') {
1740 shift_left_factor = 10;
1741 value[last] = '\0';
1742 }
1743 if (value[last] == 'M' || value[last] == 'm') {
1744 shift_left_factor = 20;
1745 value[last] = '\0';
1746 }
1747 if (value[last] == 'G' || value[last] == 'g') {
1748 shift_left_factor = 30;
1749 value[last] = '\0';
1750 }
1751
1752 return simple_strtoul((const char *)s, endp, base) << shift_left_factor;
1753}
1754
1755int
1756xfs_parseargs(
1757 struct xfs_mount *mp,
1758 char *options,
1759 struct xfs_mount_args *args,
1760 int update)
1761{
1762 char *this_char, *value, *eov;
1763 int dsunit, dswidth, vol_dsunit, vol_dswidth;
1764 int iosize;
1765 int ikeep = 0;
1766
1767 args->flags |= XFSMNT_BARRIER;
1768 args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
1769
1770 if (!options)
1771 goto done;
1772
1773 iosize = dsunit = dswidth = vol_dsunit = vol_dswidth = 0;
1774
1775 while ((this_char = strsep(&options, ",")) != NULL) {
1776 if (!*this_char)
1777 continue;
1778 if ((value = strchr(this_char, '=')) != NULL)
1779 *value++ = 0;
1780
1781 if (!strcmp(this_char, MNTOPT_LOGBUFS)) {
1782 if (!value || !*value) {
1783 cmn_err(CE_WARN,
1784 "XFS: %s option requires an argument",
1785 this_char);
1786 return EINVAL;
1787 }
1788 args->logbufs = simple_strtoul(value, &eov, 10);
1789 } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) {
1790 if (!value || !*value) {
1791 cmn_err(CE_WARN,
1792 "XFS: %s option requires an argument",
1793 this_char);
1794 return EINVAL;
1795 }
1796 args->logbufsize = suffix_strtoul(value, &eov, 10);
1797 } else if (!strcmp(this_char, MNTOPT_LOGDEV)) {
1798 if (!value || !*value) {
1799 cmn_err(CE_WARN,
1800 "XFS: %s option requires an argument",
1801 this_char);
1802 return EINVAL;
1803 }
1804 strncpy(args->logname, value, MAXNAMELEN);
1805 } else if (!strcmp(this_char, MNTOPT_MTPT)) {
1806 if (!value || !*value) {
1807 cmn_err(CE_WARN,
1808 "XFS: %s option requires an argument",
1809 this_char);
1810 return EINVAL;
1811 }
1812 strncpy(args->mtpt, value, MAXNAMELEN);
1813 } else if (!strcmp(this_char, MNTOPT_RTDEV)) {
1814 if (!value || !*value) {
1815 cmn_err(CE_WARN,
1816 "XFS: %s option requires an argument",
1817 this_char);
1818 return EINVAL;
1819 }
1820 strncpy(args->rtname, value, MAXNAMELEN);
1821 } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) {
1822 if (!value || !*value) {
1823 cmn_err(CE_WARN,
1824 "XFS: %s option requires an argument",
1825 this_char);
1826 return EINVAL;
1827 }
1828 iosize = simple_strtoul(value, &eov, 10);
1829 args->flags |= XFSMNT_IOSIZE;
1830 args->iosizelog = (uint8_t) iosize;
1831 } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) {
1832 if (!value || !*value) {
1833 cmn_err(CE_WARN,
1834 "XFS: %s option requires an argument",
1835 this_char);
1836 return EINVAL;
1837 }
1838 iosize = suffix_strtoul(value, &eov, 10);
1839 args->flags |= XFSMNT_IOSIZE;
1840 args->iosizelog = ffs(iosize) - 1;
1841 } else if (!strcmp(this_char, MNTOPT_GRPID) ||
1842 !strcmp(this_char, MNTOPT_BSDGROUPS)) {
1843 mp->m_flags |= XFS_MOUNT_GRPID;
1844 } else if (!strcmp(this_char, MNTOPT_NOGRPID) ||
1845 !strcmp(this_char, MNTOPT_SYSVGROUPS)) {
1846 mp->m_flags &= ~XFS_MOUNT_GRPID;
1847 } else if (!strcmp(this_char, MNTOPT_WSYNC)) {
1848 args->flags |= XFSMNT_WSYNC;
1849 } else if (!strcmp(this_char, MNTOPT_OSYNCISOSYNC)) {
1850 args->flags |= XFSMNT_OSYNCISOSYNC;
1851 } else if (!strcmp(this_char, MNTOPT_NORECOVERY)) {
1852 args->flags |= XFSMNT_NORECOVERY;
1853 } else if (!strcmp(this_char, MNTOPT_INO64)) {
1854 args->flags |= XFSMNT_INO64;
1855#if !XFS_BIG_INUMS
1856 cmn_err(CE_WARN,
1857 "XFS: %s option not allowed on this system",
1858 this_char);
1859 return EINVAL;
1860#endif
1861 } else if (!strcmp(this_char, MNTOPT_NOALIGN)) {
1862 args->flags |= XFSMNT_NOALIGN;
1863 } else if (!strcmp(this_char, MNTOPT_SWALLOC)) {
1864 args->flags |= XFSMNT_SWALLOC;
1865 } else if (!strcmp(this_char, MNTOPT_SUNIT)) {
1866 if (!value || !*value) {
1867 cmn_err(CE_WARN,
1868 "XFS: %s option requires an argument",
1869 this_char);
1870 return EINVAL;
1871 }
1872 dsunit = simple_strtoul(value, &eov, 10);
1873 } else if (!strcmp(this_char, MNTOPT_SWIDTH)) {
1874 if (!value || !*value) {
1875 cmn_err(CE_WARN,
1876 "XFS: %s option requires an argument",
1877 this_char);
1878 return EINVAL;
1879 }
1880 dswidth = simple_strtoul(value, &eov, 10);
1881 } else if (!strcmp(this_char, MNTOPT_64BITINODE)) {
1882 args->flags &= ~XFSMNT_32BITINODES;
1883#if !XFS_BIG_INUMS
1884 cmn_err(CE_WARN,
1885 "XFS: %s option not allowed on this system",
1886 this_char);
1887 return EINVAL;
1888#endif
1889 } else if (!strcmp(this_char, MNTOPT_NOUUID)) {
1890 args->flags |= XFSMNT_NOUUID;
1891 } else if (!strcmp(this_char, MNTOPT_BARRIER)) {
1892 args->flags |= XFSMNT_BARRIER;
1893 } else if (!strcmp(this_char, MNTOPT_NOBARRIER)) {
1894 args->flags &= ~XFSMNT_BARRIER;
1895 } else if (!strcmp(this_char, MNTOPT_IKEEP)) {
1896 ikeep = 1;
1897 args->flags &= ~XFSMNT_IDELETE;
1898 } else if (!strcmp(this_char, MNTOPT_NOIKEEP)) {
1899 args->flags |= XFSMNT_IDELETE;
1900 } else if (!strcmp(this_char, MNTOPT_LARGEIO)) {
1901 args->flags2 &= ~XFSMNT2_COMPAT_IOSIZE;
1902 } else if (!strcmp(this_char, MNTOPT_NOLARGEIO)) {
1903 args->flags2 |= XFSMNT2_COMPAT_IOSIZE;
1904 } else if (!strcmp(this_char, MNTOPT_ATTR2)) {
1905 args->flags |= XFSMNT_ATTR2;
1906 } else if (!strcmp(this_char, MNTOPT_NOATTR2)) {
1907 args->flags &= ~XFSMNT_ATTR2;
1908 } else if (!strcmp(this_char, MNTOPT_FILESTREAM)) {
1909 args->flags2 |= XFSMNT2_FILESTREAMS;
1910 } else if (!strcmp(this_char, MNTOPT_NOQUOTA)) {
1911 args->flags &= ~(XFSMNT_UQUOTAENF|XFSMNT_UQUOTA);
1912 args->flags &= ~(XFSMNT_GQUOTAENF|XFSMNT_GQUOTA);
1913 } else if (!strcmp(this_char, MNTOPT_QUOTA) ||
1914 !strcmp(this_char, MNTOPT_UQUOTA) ||
1915 !strcmp(this_char, MNTOPT_USRQUOTA)) {
1916 args->flags |= XFSMNT_UQUOTA | XFSMNT_UQUOTAENF;
1917 } else if (!strcmp(this_char, MNTOPT_QUOTANOENF) ||
1918 !strcmp(this_char, MNTOPT_UQUOTANOENF)) {
1919 args->flags |= XFSMNT_UQUOTA;
1920 args->flags &= ~XFSMNT_UQUOTAENF;
1921 } else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
1922 !strcmp(this_char, MNTOPT_PRJQUOTA)) {
1923 args->flags |= XFSMNT_PQUOTA | XFSMNT_PQUOTAENF;
1924 } else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
1925 args->flags |= XFSMNT_PQUOTA;
1926 args->flags &= ~XFSMNT_PQUOTAENF;
1927 } else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
1928 !strcmp(this_char, MNTOPT_GRPQUOTA)) {
1929 args->flags |= XFSMNT_GQUOTA | XFSMNT_GQUOTAENF;
1930 } else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) {
1931 args->flags |= XFSMNT_GQUOTA;
1932 args->flags &= ~XFSMNT_GQUOTAENF;
1933 } else if (!strcmp(this_char, MNTOPT_DMAPI)) {
1934 args->flags |= XFSMNT_DMAPI;
1935 } else if (!strcmp(this_char, MNTOPT_XDSM)) {
1936 args->flags |= XFSMNT_DMAPI;
1937 } else if (!strcmp(this_char, MNTOPT_DMI)) {
1938 args->flags |= XFSMNT_DMAPI;
1939 } else if (!strcmp(this_char, "ihashsize")) {
1940 cmn_err(CE_WARN,
1941 "XFS: ihashsize no longer used, option is deprecated.");
1942 } else if (!strcmp(this_char, "osyncisdsync")) {
1943
1944 cmn_err(CE_WARN,
1945 "XFS: osyncisdsync is now the default, option is deprecated.");
1946 } else if (!strcmp(this_char, "irixsgid")) {
1947 cmn_err(CE_WARN,
1948 "XFS: irixsgid is now a sysctl(2) variable, option is deprecated.");
1949 } else {
1950 cmn_err(CE_WARN,
1951 "XFS: unknown mount option [%s].", this_char);
1952 return EINVAL;
1953 }
1954 }
1955
1956 if (args->flags & XFSMNT_NORECOVERY) {
1957 if ((mp->m_flags & XFS_MOUNT_RDONLY) == 0) {
1958 cmn_err(CE_WARN,
1959 "XFS: no-recovery mounts must be read-only.");
1960 return EINVAL;
1961 }
1962 }
1963
1964 if ((args->flags & XFSMNT_NOALIGN) && (dsunit || dswidth)) {
1965 cmn_err(CE_WARN,
1966 "XFS: sunit and swidth options incompatible with the noalign option");
1967 return EINVAL;
1968 }
1969
1970 if ((args->flags & XFSMNT_GQUOTA) && (args->flags & XFSMNT_PQUOTA)) {
1971 cmn_err(CE_WARN,
1972 "XFS: cannot mount with both project and group quota");
1973 return EINVAL;
1974 }
1975
1976 if ((args->flags & XFSMNT_DMAPI) && *args->mtpt == '\0') {
1977 printk("XFS: %s option needs the mount point option as well\n",
1978 MNTOPT_DMAPI);
1979 return EINVAL;
1980 }
1981
1982 if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
1983 cmn_err(CE_WARN,
1984 "XFS: sunit and swidth must be specified together");
1985 return EINVAL;
1986 }
1987
1988 if (dsunit && (dswidth % dsunit != 0)) {
1989 cmn_err(CE_WARN,
1990 "XFS: stripe width (%d) must be a multiple of the stripe unit (%d)",
1991 dswidth, dsunit);
1992 return EINVAL;
1993 }
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004 if (!(args->flags & XFSMNT_DMAPI) && !ikeep)
2005 args->flags |= XFSMNT_IDELETE;
2006
2007 if ((args->flags & XFSMNT_NOALIGN) != XFSMNT_NOALIGN) {
2008 if (dsunit) {
2009 args->sunit = dsunit;
2010 args->flags |= XFSMNT_RETERR;
2011 } else {
2012 args->sunit = vol_dsunit;
2013 }
2014 dswidth ? (args->swidth = dswidth) :
2015 (args->swidth = vol_dswidth);
2016 } else {
2017 args->sunit = args->swidth = 0;
2018 }
2019
2020done:
2021 if (args->flags & XFSMNT_32BITINODES)
2022 mp->m_flags |= XFS_MOUNT_SMALL_INUMS;
2023 if (args->flags2)
2024 args->flags |= XFSMNT_FLAGS2;
2025 return 0;
2026}
2027
2028int
2029xfs_showargs(
2030 struct xfs_mount *mp,
2031 struct seq_file *m)
2032{
2033 static struct proc_xfs_info {
2034 int flag;
2035 char *str;
2036 } xfs_info[] = {
2037
2038 { XFS_MOUNT_WSYNC, "," MNTOPT_WSYNC },
2039 { XFS_MOUNT_INO64, "," MNTOPT_INO64 },
2040 { XFS_MOUNT_NOALIGN, "," MNTOPT_NOALIGN },
2041 { XFS_MOUNT_SWALLOC, "," MNTOPT_SWALLOC },
2042 { XFS_MOUNT_NOUUID, "," MNTOPT_NOUUID },
2043 { XFS_MOUNT_NORECOVERY, "," MNTOPT_NORECOVERY },
2044 { XFS_MOUNT_OSYNCISOSYNC, "," MNTOPT_OSYNCISOSYNC },
2045 { 0, NULL }
2046 };
2047 struct proc_xfs_info *xfs_infop;
2048
2049 for (xfs_infop = xfs_info; xfs_infop->flag; xfs_infop++) {
2050 if (mp->m_flags & xfs_infop->flag)
2051 seq_puts(m, xfs_infop->str);
2052 }
2053
2054 if (mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)
2055 seq_printf(m, "," MNTOPT_ALLOCSIZE "=%dk",
2056 (int)(1 << mp->m_writeio_log) >> 10);
2057
2058 if (mp->m_logbufs > 0)
2059 seq_printf(m, "," MNTOPT_LOGBUFS "=%d", mp->m_logbufs);
2060 if (mp->m_logbsize > 0)
2061 seq_printf(m, "," MNTOPT_LOGBSIZE "=%dk", mp->m_logbsize >> 10);
2062
2063 if (mp->m_logname)
2064 seq_printf(m, "," MNTOPT_LOGDEV "=%s", mp->m_logname);
2065 if (mp->m_rtname)
2066 seq_printf(m, "," MNTOPT_RTDEV "=%s", mp->m_rtname);
2067
2068 if (mp->m_dalign > 0)
2069 seq_printf(m, "," MNTOPT_SUNIT "=%d",
2070 (int)XFS_FSB_TO_BB(mp, mp->m_dalign));
2071 if (mp->m_swidth > 0)
2072 seq_printf(m, "," MNTOPT_SWIDTH "=%d",
2073 (int)XFS_FSB_TO_BB(mp, mp->m_swidth));
2074
2075 if (!(mp->m_flags & XFS_MOUNT_IDELETE))
2076 seq_printf(m, "," MNTOPT_IKEEP);
2077 if (!(mp->m_flags & XFS_MOUNT_COMPAT_IOSIZE))
2078 seq_printf(m, "," MNTOPT_LARGEIO);
2079
2080 if (!(mp->m_flags & XFS_MOUNT_SMALL_INUMS))
2081 seq_printf(m, "," MNTOPT_64BITINODE);
2082 if (mp->m_flags & XFS_MOUNT_GRPID)
2083 seq_printf(m, "," MNTOPT_GRPID);
2084
2085 if (mp->m_qflags & XFS_UQUOTA_ACCT) {
2086 if (mp->m_qflags & XFS_UQUOTA_ENFD)
2087 seq_puts(m, "," MNTOPT_USRQUOTA);
2088 else
2089 seq_puts(m, "," MNTOPT_UQUOTANOENF);
2090 }
2091
2092 if (mp->m_qflags & XFS_PQUOTA_ACCT) {
2093 if (mp->m_qflags & XFS_OQUOTA_ENFD)
2094 seq_puts(m, "," MNTOPT_PRJQUOTA);
2095 else
2096 seq_puts(m, "," MNTOPT_PQUOTANOENF);
2097 }
2098
2099 if (mp->m_qflags & XFS_GQUOTA_ACCT) {
2100 if (mp->m_qflags & XFS_OQUOTA_ENFD)
2101 seq_puts(m, "," MNTOPT_GRPQUOTA);
2102 else
2103 seq_puts(m, "," MNTOPT_GQUOTANOENF);
2104 }
2105
2106 if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT))
2107 seq_puts(m, "," MNTOPT_NOQUOTA);
2108
2109 if (mp->m_flags & XFS_MOUNT_DMAPI)
2110 seq_puts(m, "," MNTOPT_DMAPI);
2111 return 0;
2112}
2113
2114
2115
2116
2117
2118
2119void
2120xfs_freeze(
2121 xfs_mount_t *mp)
2122{
2123 xfs_attr_quiesce(mp);
2124 xfs_fs_log_dummy(mp);
2125}
2126