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_bmap_btree.h"
31#include "xfs_alloc_btree.h"
32#include "xfs_ialloc_btree.h"
33#include "xfs_dir2_sf.h"
34#include "xfs_attr_sf.h"
35#include "xfs_dinode.h"
36#include "xfs_inode.h"
37#include "xfs_btree.h"
38#include "xfs_ialloc.h"
39#include "xfs_alloc.h"
40#include "xfs_rtalloc.h"
41#include "xfs_bmap.h"
42#include "xfs_error.h"
43#include "xfs_rw.h"
44#include "xfs_quota.h"
45#include "xfs_fsops.h"
46
47STATIC void xfs_mount_log_sbunit(xfs_mount_t *, __int64_t);
48STATIC int xfs_uuid_mount(xfs_mount_t *);
49STATIC void xfs_uuid_unmount(xfs_mount_t *mp);
50STATIC void xfs_unmountfs_wait(xfs_mount_t *);
51
52
53#ifdef HAVE_PERCPU_SB
54STATIC void xfs_icsb_destroy_counters(xfs_mount_t *);
55STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t, int);
56STATIC void xfs_icsb_sync_counters(xfs_mount_t *);
57STATIC int xfs_icsb_modify_counters(xfs_mount_t *, xfs_sb_field_t,
58 int, int);
59STATIC int xfs_icsb_modify_counters_locked(xfs_mount_t *, xfs_sb_field_t,
60 int, int);
61STATIC int xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
62
63#else
64
65#define xfs_icsb_destroy_counters(mp) do { } while (0)
66#define xfs_icsb_balance_counter(mp, a, b) do { } while (0)
67#define xfs_icsb_sync_counters(mp) do { } while (0)
68#define xfs_icsb_modify_counters(mp, a, b, c) do { } while (0)
69#define xfs_icsb_modify_counters_locked(mp, a, b, c) do { } while (0)
70
71#endif
72
73static const struct {
74 short offset;
75 short type;
76
77
78} xfs_sb_info[] = {
79 { offsetof(xfs_sb_t, sb_magicnum), 0 },
80 { offsetof(xfs_sb_t, sb_blocksize), 0 },
81 { offsetof(xfs_sb_t, sb_dblocks), 0 },
82 { offsetof(xfs_sb_t, sb_rblocks), 0 },
83 { offsetof(xfs_sb_t, sb_rextents), 0 },
84 { offsetof(xfs_sb_t, sb_uuid), 1 },
85 { offsetof(xfs_sb_t, sb_logstart), 0 },
86 { offsetof(xfs_sb_t, sb_rootino), 0 },
87 { offsetof(xfs_sb_t, sb_rbmino), 0 },
88 { offsetof(xfs_sb_t, sb_rsumino), 0 },
89 { offsetof(xfs_sb_t, sb_rextsize), 0 },
90 { offsetof(xfs_sb_t, sb_agblocks), 0 },
91 { offsetof(xfs_sb_t, sb_agcount), 0 },
92 { offsetof(xfs_sb_t, sb_rbmblocks), 0 },
93 { offsetof(xfs_sb_t, sb_logblocks), 0 },
94 { offsetof(xfs_sb_t, sb_versionnum), 0 },
95 { offsetof(xfs_sb_t, sb_sectsize), 0 },
96 { offsetof(xfs_sb_t, sb_inodesize), 0 },
97 { offsetof(xfs_sb_t, sb_inopblock), 0 },
98 { offsetof(xfs_sb_t, sb_fname[0]), 1 },
99 { offsetof(xfs_sb_t, sb_blocklog), 0 },
100 { offsetof(xfs_sb_t, sb_sectlog), 0 },
101 { offsetof(xfs_sb_t, sb_inodelog), 0 },
102 { offsetof(xfs_sb_t, sb_inopblog), 0 },
103 { offsetof(xfs_sb_t, sb_agblklog), 0 },
104 { offsetof(xfs_sb_t, sb_rextslog), 0 },
105 { offsetof(xfs_sb_t, sb_inprogress), 0 },
106 { offsetof(xfs_sb_t, sb_imax_pct), 0 },
107 { offsetof(xfs_sb_t, sb_icount), 0 },
108 { offsetof(xfs_sb_t, sb_ifree), 0 },
109 { offsetof(xfs_sb_t, sb_fdblocks), 0 },
110 { offsetof(xfs_sb_t, sb_frextents), 0 },
111 { offsetof(xfs_sb_t, sb_uquotino), 0 },
112 { offsetof(xfs_sb_t, sb_gquotino), 0 },
113 { offsetof(xfs_sb_t, sb_qflags), 0 },
114 { offsetof(xfs_sb_t, sb_flags), 0 },
115 { offsetof(xfs_sb_t, sb_shared_vn), 0 },
116 { offsetof(xfs_sb_t, sb_inoalignmt), 0 },
117 { offsetof(xfs_sb_t, sb_unit), 0 },
118 { offsetof(xfs_sb_t, sb_width), 0 },
119 { offsetof(xfs_sb_t, sb_dirblklog), 0 },
120 { offsetof(xfs_sb_t, sb_logsectlog), 0 },
121 { offsetof(xfs_sb_t, sb_logsectsize),0 },
122 { offsetof(xfs_sb_t, sb_logsunit), 0 },
123 { offsetof(xfs_sb_t, sb_features2), 0 },
124 { sizeof(xfs_sb_t), 0 }
125};
126
127
128
129
130xfs_mount_t *
131xfs_mount_init(void)
132{
133 xfs_mount_t *mp;
134
135 mp = kmem_zalloc(sizeof(xfs_mount_t), KM_SLEEP);
136
137 if (xfs_icsb_init_counters(mp)) {
138 mp->m_flags |= XFS_MOUNT_NO_PERCPU_SB;
139 }
140
141 AIL_LOCKINIT(&mp->m_ail_lock, "xfs_ail");
142 spinlock_init(&mp->m_sb_lock, "xfs_sb");
143 mutex_init(&mp->m_ilock);
144 initnsema(&mp->m_growlock, 1, "xfs_grow");
145
146
147
148 xfs_trans_ail_init(mp);
149
150 atomic_set(&mp->m_active_trans, 0);
151
152 return mp;
153}
154
155
156
157
158
159
160void
161xfs_mount_free(
162 xfs_mount_t *mp,
163 int remove_bhv)
164{
165 if (mp->m_ihash)
166 xfs_ihash_free(mp);
167 if (mp->m_chash)
168 xfs_chash_free(mp);
169
170 if (mp->m_perag) {
171 int agno;
172
173 for (agno = 0; agno < mp->m_maxagi; agno++)
174 if (mp->m_perag[agno].pagb_list)
175 kmem_free(mp->m_perag[agno].pagb_list,
176 sizeof(xfs_perag_busy_t) *
177 XFS_PAGB_NUM_SLOTS);
178 kmem_free(mp->m_perag,
179 sizeof(xfs_perag_t) * mp->m_sb.sb_agcount);
180 }
181
182 AIL_LOCK_DESTROY(&mp->m_ail_lock);
183 spinlock_destroy(&mp->m_sb_lock);
184 mutex_destroy(&mp->m_ilock);
185 freesema(&mp->m_growlock);
186 if (mp->m_quotainfo)
187 XFS_QM_DONE(mp);
188
189 if (mp->m_fsname != NULL)
190 kmem_free(mp->m_fsname, mp->m_fsname_len);
191 if (mp->m_rtname != NULL)
192 kmem_free(mp->m_rtname, strlen(mp->m_rtname) + 1);
193 if (mp->m_logname != NULL)
194 kmem_free(mp->m_logname, strlen(mp->m_logname) + 1);
195
196 if (remove_bhv) {
197 struct bhv_vfs *vfsp = XFS_MTOVFS(mp);
198
199 bhv_remove_all_vfsops(vfsp, 0);
200 VFS_REMOVEBHV(vfsp, &mp->m_bhv);
201 }
202
203 xfs_icsb_destroy_counters(mp);
204 kmem_free(mp, sizeof(xfs_mount_t));
205}
206
207
208
209
210
211STATIC int
212xfs_mount_validate_sb(
213 xfs_mount_t *mp,
214 xfs_sb_t *sbp,
215 int flags)
216{
217
218
219
220
221
222
223
224 if (sbp->sb_magicnum != XFS_SB_MAGIC) {
225 xfs_fs_mount_cmn_err(flags, "bad magic number");
226 return XFS_ERROR(EWRONGFS);
227 }
228
229 if (!XFS_SB_GOOD_VERSION(sbp)) {
230 xfs_fs_mount_cmn_err(flags, "bad version");
231 return XFS_ERROR(EWRONGFS);
232 }
233
234 if (unlikely(
235 sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
236 xfs_fs_mount_cmn_err(flags,
237 "filesystem is marked as having an external log; "
238 "specify logdev on the\nmount command line.");
239 return XFS_ERROR(EINVAL);
240 }
241
242 if (unlikely(
243 sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) {
244 xfs_fs_mount_cmn_err(flags,
245 "filesystem is marked as having an internal log; "
246 "do not specify logdev on\nthe mount command line.");
247 return XFS_ERROR(EINVAL);
248 }
249
250
251
252
253
254 if (unlikely(
255 sbp->sb_agcount <= 0 ||
256 sbp->sb_sectsize < XFS_MIN_SECTORSIZE ||
257 sbp->sb_sectsize > XFS_MAX_SECTORSIZE ||
258 sbp->sb_sectlog < XFS_MIN_SECTORSIZE_LOG ||
259 sbp->sb_sectlog > XFS_MAX_SECTORSIZE_LOG ||
260 sbp->sb_blocksize < XFS_MIN_BLOCKSIZE ||
261 sbp->sb_blocksize > XFS_MAX_BLOCKSIZE ||
262 sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG ||
263 sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG ||
264 sbp->sb_inodesize < XFS_DINODE_MIN_SIZE ||
265 sbp->sb_inodesize > XFS_DINODE_MAX_SIZE ||
266 sbp->sb_inodelog < XFS_DINODE_MIN_LOG ||
267 sbp->sb_inodelog > XFS_DINODE_MAX_LOG ||
268 (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog) ||
269 (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) ||
270 (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) ||
271 (sbp->sb_imax_pct > 100 ))) {
272 xfs_fs_mount_cmn_err(flags, "SB sanity check 1 failed");
273 return XFS_ERROR(EFSCORRUPTED);
274 }
275
276
277
278
279 if (unlikely(
280 sbp->sb_dblocks == 0 ||
281 sbp->sb_dblocks >
282 (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks ||
283 sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) *
284 sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) {
285 xfs_fs_mount_cmn_err(flags, "SB sanity check 2 failed");
286 return XFS_ERROR(EFSCORRUPTED);
287 }
288
289 ASSERT(PAGE_SHIFT >= sbp->sb_blocklog);
290 ASSERT(sbp->sb_blocklog >= BBSHIFT);
291
292#if XFS_BIG_BLKNOS
293 if (unlikely(
294 (sbp->sb_dblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX ||
295 (sbp->sb_rblocks >> (PAGE_SHIFT - sbp->sb_blocklog)) > ULONG_MAX)) {
296#else
297 if (unlikely(
298 (sbp->sb_dblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX ||
299 (sbp->sb_rblocks << (sbp->sb_blocklog - BBSHIFT)) > UINT_MAX)) {
300#endif
301 xfs_fs_mount_cmn_err(flags,
302 "file system too large to be mounted on this system.");
303 return XFS_ERROR(E2BIG);
304 }
305
306 if (unlikely(sbp->sb_inprogress)) {
307 xfs_fs_mount_cmn_err(flags, "file system busy");
308 return XFS_ERROR(EFSCORRUPTED);
309 }
310
311
312
313
314 if (unlikely(!XFS_SB_VERSION_HASDIRV2(sbp))) {
315 xfs_fs_mount_cmn_err(flags,
316 "file system using version 1 directory format");
317 return XFS_ERROR(ENOSYS);
318 }
319
320
321
322
323 if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
324 xfs_fs_mount_cmn_err(flags,
325 "file system with blocksize %d bytes",
326 sbp->sb_blocksize);
327 xfs_fs_mount_cmn_err(flags,
328 "only pagesize (%ld) or less will currently work.",
329 PAGE_SIZE);
330 return XFS_ERROR(ENOSYS);
331 }
332
333 return 0;
334}
335
336xfs_agnumber_t
337xfs_initialize_perag(
338 bhv_vfs_t *vfs,
339 xfs_mount_t *mp,
340 xfs_agnumber_t agcount)
341{
342 xfs_agnumber_t index, max_metadata;
343 xfs_perag_t *pag;
344 xfs_agino_t agino;
345 xfs_ino_t ino;
346 xfs_sb_t *sbp = &mp->m_sb;
347 xfs_ino_t max_inum = XFS_MAXINUMBER_32;
348
349
350 agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);
351 ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
352
353
354
355
356 if ((vfs->vfs_flag & VFS_32BITINODES) && ino > max_inum) {
357 mp->m_flags |= XFS_MOUNT_32BITINODES;
358 } else {
359 mp->m_flags &= ~XFS_MOUNT_32BITINODES;
360 }
361
362
363 if (mp->m_flags & XFS_MOUNT_32BITINODES) {
364
365
366
367 if (mp->m_maxicount) {
368 __uint64_t icount;
369
370 icount = sbp->sb_dblocks * sbp->sb_imax_pct;
371 do_div(icount, 100);
372 icount += sbp->sb_agblocks - 1;
373 do_div(icount, sbp->sb_agblocks);
374 max_metadata = icount;
375 } else {
376 max_metadata = agcount;
377 }
378 for (index = 0; index < agcount; index++) {
379 ino = XFS_AGINO_TO_INO(mp, index, agino);
380 if (ino > max_inum) {
381 index++;
382 break;
383 }
384
385
386 pag = &mp->m_perag[index];
387 pag->pagi_inodeok = 1;
388 if (index < max_metadata)
389 pag->pagf_metadata = 1;
390 }
391 } else {
392
393 for (index = 0; index < agcount; index++) {
394 pag = &mp->m_perag[index];
395 pag->pagi_inodeok = 1;
396 }
397 }
398 return index;
399}
400
401
402
403
404
405
406
407
408
409
410void
411xfs_xlatesb(
412 void *data,
413 xfs_sb_t *sb,
414 int dir,
415 __int64_t fields)
416{
417 xfs_caddr_t buf_ptr;
418 xfs_caddr_t mem_ptr;
419 xfs_sb_field_t f;
420 int first;
421 int size;
422
423 ASSERT(dir);
424 ASSERT(fields);
425
426 if (!fields)
427 return;
428
429 buf_ptr = (xfs_caddr_t)data;
430 mem_ptr = (xfs_caddr_t)sb;
431
432 while (fields) {
433 f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
434 first = xfs_sb_info[f].offset;
435 size = xfs_sb_info[f + 1].offset - first;
436
437 ASSERT(xfs_sb_info[f].type == 0 || xfs_sb_info[f].type == 1);
438
439 if (size == 1 || xfs_sb_info[f].type == 1) {
440 if (dir > 0) {
441 memcpy(mem_ptr + first, buf_ptr + first, size);
442 } else {
443 memcpy(buf_ptr + first, mem_ptr + first, size);
444 }
445 } else {
446 switch (size) {
447 case 2:
448 INT_XLATE(*(__uint16_t*)(buf_ptr+first),
449 *(__uint16_t*)(mem_ptr+first),
450 dir, ARCH_CONVERT);
451 break;
452 case 4:
453 INT_XLATE(*(__uint32_t*)(buf_ptr+first),
454 *(__uint32_t*)(mem_ptr+first),
455 dir, ARCH_CONVERT);
456 break;
457 case 8:
458 INT_XLATE(*(__uint64_t*)(buf_ptr+first),
459 *(__uint64_t*)(mem_ptr+first), dir, ARCH_CONVERT);
460 break;
461 default:
462 ASSERT(0);
463 }
464 }
465
466 fields &= ~(1LL << f);
467 }
468}
469
470
471
472
473
474
475int
476xfs_readsb(xfs_mount_t *mp, int flags)
477{
478 unsigned int sector_size;
479 unsigned int extra_flags;
480 xfs_buf_t *bp;
481 xfs_sb_t *sbp;
482 int error;
483
484 ASSERT(mp->m_sb_bp == NULL);
485 ASSERT(mp->m_ddev_targp != NULL);
486
487
488
489
490
491
492 sector_size = xfs_getsize_buftarg(mp->m_ddev_targp);
493 extra_flags = XFS_BUF_LOCK | XFS_BUF_MANAGE | XFS_BUF_MAPPED;
494
495 bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR,
496 BTOBB(sector_size), extra_flags);
497 if (!bp || XFS_BUF_ISERROR(bp)) {
498 xfs_fs_mount_cmn_err(flags, "SB read failed");
499 error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
500 goto fail;
501 }
502 ASSERT(XFS_BUF_ISBUSY(bp));
503 ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
504
505
506
507
508
509 sbp = XFS_BUF_TO_SBP(bp);
510 xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), 1, XFS_SB_ALL_BITS);
511
512 error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
513 if (error) {
514 xfs_fs_mount_cmn_err(flags, "SB validate failed");
515 goto fail;
516 }
517
518
519
520
521 if (sector_size > mp->m_sb.sb_sectsize) {
522 xfs_fs_mount_cmn_err(flags,
523 "device supports only %u byte sectors (not %u)",
524 sector_size, mp->m_sb.sb_sectsize);
525 error = ENOSYS;
526 goto fail;
527 }
528
529
530
531
532
533 if (sector_size < mp->m_sb.sb_sectsize) {
534 XFS_BUF_UNMANAGE(bp);
535 xfs_buf_relse(bp);
536 sector_size = mp->m_sb.sb_sectsize;
537 bp = xfs_buf_read_flags(mp->m_ddev_targp, XFS_SB_DADDR,
538 BTOBB(sector_size), extra_flags);
539 if (!bp || XFS_BUF_ISERROR(bp)) {
540 xfs_fs_mount_cmn_err(flags, "SB re-read failed");
541 error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM;
542 goto fail;
543 }
544 ASSERT(XFS_BUF_ISBUSY(bp));
545 ASSERT(XFS_BUF_VALUSEMA(bp) <= 0);
546 }
547
548 xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
549 xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
550 xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
551
552 mp->m_sb_bp = bp;
553 xfs_buf_relse(bp);
554 ASSERT(XFS_BUF_VALUSEMA(bp) > 0);
555 return 0;
556
557 fail:
558 if (bp) {
559 XFS_BUF_UNMANAGE(bp);
560 xfs_buf_relse(bp);
561 }
562 return error;
563}
564
565
566
567
568
569
570
571
572
573STATIC void
574xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
575{
576 int i;
577
578 mp->m_agfrotor = mp->m_agirotor = 0;
579 spinlock_init(&mp->m_agirotor_lock, "m_agirotor_lock");
580 mp->m_maxagi = mp->m_sb.sb_agcount;
581 mp->m_blkbit_log = sbp->sb_blocklog + XFS_NBBYLOG;
582 mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT;
583 mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT;
584 mp->m_agno_log = xfs_highbit32(sbp->sb_agcount - 1) + 1;
585 mp->m_agino_log = sbp->sb_inopblog + sbp->sb_agblklog;
586 mp->m_litino = sbp->sb_inodesize -
587 ((uint)sizeof(xfs_dinode_core_t) + (uint)sizeof(xfs_agino_t));
588 mp->m_blockmask = sbp->sb_blocksize - 1;
589 mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
590 mp->m_blockwmask = mp->m_blockwsize - 1;
591 INIT_LIST_HEAD(&mp->m_del_inodes);
592
593
594
595
596
597
598 ASSERT(sbp->sb_inodesize >= 256 && sbp->sb_inodesize <= 2048);
599 switch (sbp->sb_inodesize) {
600 case 256:
601 mp->m_attroffset = XFS_LITINO(mp) -
602 XFS_BMDR_SPACE_CALC(MINABTPTRS);
603 break;
604 case 512:
605 case 1024:
606 case 2048:
607 mp->m_attroffset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS);
608 break;
609 default:
610 ASSERT(0);
611 }
612 ASSERT(mp->m_attroffset < XFS_LITINO(mp));
613
614 for (i = 0; i < 2; i++) {
615 mp->m_alloc_mxr[i] = XFS_BTREE_BLOCK_MAXRECS(sbp->sb_blocksize,
616 xfs_alloc, i == 0);
617 mp->m_alloc_mnr[i] = XFS_BTREE_BLOCK_MINRECS(sbp->sb_blocksize,
618 xfs_alloc, i == 0);
619 }
620 for (i = 0; i < 2; i++) {
621 mp->m_bmap_dmxr[i] = XFS_BTREE_BLOCK_MAXRECS(sbp->sb_blocksize,
622 xfs_bmbt, i == 0);
623 mp->m_bmap_dmnr[i] = XFS_BTREE_BLOCK_MINRECS(sbp->sb_blocksize,
624 xfs_bmbt, i == 0);
625 }
626 for (i = 0; i < 2; i++) {
627 mp->m_inobt_mxr[i] = XFS_BTREE_BLOCK_MAXRECS(sbp->sb_blocksize,
628 xfs_inobt, i == 0);
629 mp->m_inobt_mnr[i] = XFS_BTREE_BLOCK_MINRECS(sbp->sb_blocksize,
630 xfs_inobt, i == 0);
631 }
632
633 mp->m_bsize = XFS_FSB_TO_BB(mp, 1);
634 mp->m_ialloc_inos = (int)MAX((__uint16_t)XFS_INODES_PER_CHUNK,
635 sbp->sb_inopblock);
636 mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog;
637}
638
639
640
641
642
643
644
645
646
647
648
649
650int
651xfs_mountfs(
652 bhv_vfs_t *vfsp,
653 xfs_mount_t *mp,
654 int mfsi_flags)
655{
656 xfs_buf_t *bp;
657 xfs_sb_t *sbp = &(mp->m_sb);
658 xfs_inode_t *rip;
659 bhv_vnode_t *rvp = NULL;
660 int readio_log, writeio_log;
661 xfs_daddr_t d;
662 __uint64_t ret64;
663 __int64_t update_flags;
664 uint quotamount, quotaflags;
665 int agno;
666 int uuid_mounted = 0;
667 int error = 0;
668
669 if (mp->m_sb_bp == NULL) {
670 if ((error = xfs_readsb(mp, mfsi_flags))) {
671 return error;
672 }
673 }
674 xfs_mount_common(mp, sbp);
675
676
677
678
679
680
681
682 update_flags = 0LL;
683 if (mp->m_dalign && !(mfsi_flags & XFS_MFSI_SECOND)) {
684
685
686
687
688 if ((BBTOB(mp->m_dalign) & mp->m_blockmask) ||
689 (BBTOB(mp->m_swidth) & mp->m_blockmask)) {
690 if (mp->m_flags & XFS_MOUNT_RETERR) {
691 cmn_err(CE_WARN,
692 "XFS: alignment check 1 failed");
693 error = XFS_ERROR(EINVAL);
694 goto error1;
695 }
696 mp->m_dalign = mp->m_swidth = 0;
697 } else {
698
699
700
701 mp->m_dalign = XFS_BB_TO_FSBT(mp, mp->m_dalign);
702 if (mp->m_dalign && (sbp->sb_agblocks % mp->m_dalign)) {
703 if (mp->m_flags & XFS_MOUNT_RETERR) {
704 error = XFS_ERROR(EINVAL);
705 goto error1;
706 }
707 xfs_fs_cmn_err(CE_WARN, mp,
708"stripe alignment turned off: sunit(%d)/swidth(%d) incompatible with agsize(%d)",
709 mp->m_dalign, mp->m_swidth,
710 sbp->sb_agblocks);
711
712 mp->m_dalign = 0;
713 mp->m_swidth = 0;
714 } else if (mp->m_dalign) {
715 mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth);
716 } else {
717 if (mp->m_flags & XFS_MOUNT_RETERR) {
718 xfs_fs_cmn_err(CE_WARN, mp,
719"stripe alignment turned off: sunit(%d) less than bsize(%d)",
720 mp->m_dalign,
721 mp->m_blockmask +1);
722 error = XFS_ERROR(EINVAL);
723 goto error1;
724 }
725 mp->m_swidth = 0;
726 }
727 }
728
729
730
731
732
733 if (XFS_SB_VERSION_HASDALIGN(sbp)) {
734 if (sbp->sb_unit != mp->m_dalign) {
735 sbp->sb_unit = mp->m_dalign;
736 update_flags |= XFS_SB_UNIT;
737 }
738 if (sbp->sb_width != mp->m_swidth) {
739 sbp->sb_width = mp->m_swidth;
740 update_flags |= XFS_SB_WIDTH;
741 }
742 }
743 } else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN &&
744 XFS_SB_VERSION_HASDALIGN(&mp->m_sb)) {
745 mp->m_dalign = sbp->sb_unit;
746 mp->m_swidth = sbp->sb_width;
747 }
748
749 xfs_alloc_compute_maxlevels(mp);
750 xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK);
751 xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK);
752 xfs_ialloc_compute_maxlevels(mp);
753
754 if (sbp->sb_imax_pct) {
755 __uint64_t icount;
756
757
758
759
760
761 icount = sbp->sb_dblocks * sbp->sb_imax_pct;
762 do_div(icount, 100);
763 do_div(icount, mp->m_ialloc_blks);
764 mp->m_maxicount = (icount * mp->m_ialloc_blks) <<
765 sbp->sb_inopblog;
766 } else
767 mp->m_maxicount = 0;
768
769 mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog);
770
771
772
773
774
775
776
777 if ((mfsi_flags & XFS_MFSI_SECOND) == 0 &&
778 (mp->m_flags & XFS_MOUNT_NOUUID) == 0) {
779 if (xfs_uuid_mount(mp)) {
780 error = XFS_ERROR(EINVAL);
781 goto error1;
782 }
783 uuid_mounted=1;
784 ret64 = uuid_hash64(&sbp->sb_uuid);
785 memcpy(&vfsp->vfs_fsid, &ret64, sizeof(ret64));
786 }
787
788
789
790
791
792
793
794 if (!(mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)) {
795 if (mp->m_flags & XFS_MOUNT_WSYNC) {
796 readio_log = XFS_WSYNC_READIO_LOG;
797 writeio_log = XFS_WSYNC_WRITEIO_LOG;
798 } else {
799 readio_log = XFS_READIO_LOG_LARGE;
800 writeio_log = XFS_WRITEIO_LOG_LARGE;
801 }
802 } else {
803 readio_log = mp->m_readio_log;
804 writeio_log = mp->m_writeio_log;
805 }
806
807
808
809
810
811 if (xfs_physmem <= 4096)
812 mp->m_nreadaheads = XFS_RW_NREADAHEAD_16MB;
813 else if (xfs_physmem <= 8192)
814 mp->m_nreadaheads = XFS_RW_NREADAHEAD_32MB;
815 else
816 mp->m_nreadaheads = XFS_RW_NREADAHEAD_K32;
817 if (sbp->sb_blocklog > readio_log) {
818 mp->m_readio_log = sbp->sb_blocklog;
819 } else {
820 mp->m_readio_log = readio_log;
821 }
822 mp->m_readio_blocks = 1 << (mp->m_readio_log - sbp->sb_blocklog);
823 if (sbp->sb_blocklog > writeio_log) {
824 mp->m_writeio_log = sbp->sb_blocklog;
825 } else {
826 mp->m_writeio_log = writeio_log;
827 }
828 mp->m_writeio_blocks = 1 << (mp->m_writeio_log - sbp->sb_blocklog);
829
830
831
832
833
834
835 if (xfs_physmem <= btoc(32 * 1024 * 1024)) {
836 mp->m_inode_cluster_size = XFS_INODE_SMALL_CLUSTER_SIZE;
837 } else {
838 mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
839 }
840
841
842
843 if (XFS_SB_VERSION_HASALIGN(&mp->m_sb) &&
844 mp->m_sb.sb_inoalignmt >=
845 XFS_B_TO_FSBT(mp, mp->m_inode_cluster_size))
846 mp->m_inoalign_mask = mp->m_sb.sb_inoalignmt - 1;
847 else
848 mp->m_inoalign_mask = 0;
849
850
851
852
853 if (mp->m_dalign && mp->m_inoalign_mask &&
854 !(mp->m_dalign & mp->m_inoalign_mask))
855 mp->m_sinoalign = mp->m_dalign;
856 else
857 mp->m_sinoalign = 0;
858
859
860
861 d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
862 if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) {
863 cmn_err(CE_WARN, "XFS: size check 1 failed");
864 error = XFS_ERROR(E2BIG);
865 goto error1;
866 }
867 error = xfs_read_buf(mp, mp->m_ddev_targp,
868 d - XFS_FSS_TO_BB(mp, 1),
869 XFS_FSS_TO_BB(mp, 1), 0, &bp);
870 if (!error) {
871 xfs_buf_relse(bp);
872 } else {
873 cmn_err(CE_WARN, "XFS: size check 2 failed");
874 if (error == ENOSPC) {
875 error = XFS_ERROR(E2BIG);
876 }
877 goto error1;
878 }
879
880 if (((mfsi_flags & XFS_MFSI_CLIENT) == 0) &&
881 mp->m_logdev_targp != mp->m_ddev_targp) {
882 d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
883 if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) {
884 cmn_err(CE_WARN, "XFS: size check 3 failed");
885 error = XFS_ERROR(E2BIG);
886 goto error1;
887 }
888 error = xfs_read_buf(mp, mp->m_logdev_targp,
889 d - XFS_FSB_TO_BB(mp, 1),
890 XFS_FSB_TO_BB(mp, 1), 0, &bp);
891 if (!error) {
892 xfs_buf_relse(bp);
893 } else {
894 cmn_err(CE_WARN, "XFS: size check 3 failed");
895 if (error == ENOSPC) {
896 error = XFS_ERROR(E2BIG);
897 }
898 goto error1;
899 }
900 }
901
902
903
904
905 if ((error = xfs_rtmount_init(mp))) {
906 cmn_err(CE_WARN, "XFS: RT mount failed");
907 goto error1;
908 }
909
910
911
912
913 if (mfsi_flags & XFS_MFSI_CLIENT) {
914 return 0;
915 }
916
917
918
919
920
921 uuid_getnodeuniq(&sbp->sb_uuid, mp->m_fixedfsid);
922
923
924
925
926
927
928
929
930
931
932 vfsp->vfs_altfsid = (xfs_fsid_t *)mp->m_fixedfsid;
933 mp->m_dmevmask = 0;
934
935 xfs_dir_mount(mp);
936
937
938
939
940 mp->m_attr_magicpct = (mp->m_sb.sb_blocksize * 37) / 100;
941
942
943
944
945 xfs_trans_init(mp);
946
947
948
949
950
951 xfs_ihash_init(mp);
952 xfs_chash_init(mp);
953
954
955
956
957 init_rwsem(&mp->m_peraglock);
958 mp->m_perag =
959 kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), KM_SLEEP);
960
961 mp->m_maxagi = xfs_initialize_perag(vfsp, mp, sbp->sb_agcount);
962
963
964
965
966 if (likely(sbp->sb_logblocks > 0)) {
967 error = xfs_log_mount(mp, mp->m_logdev_targp,
968 XFS_FSB_TO_DADDR(mp, sbp->sb_logstart),
969 XFS_FSB_TO_BB(mp, sbp->sb_logblocks));
970 if (error) {
971 cmn_err(CE_WARN, "XFS: log mount failed");
972 goto error2;
973 }
974 } else {
975 cmn_err(CE_WARN, "XFS: no log defined");
976 XFS_ERROR_REPORT("xfs_mountfs_int(1)", XFS_ERRLEVEL_LOW, mp);
977 error = XFS_ERROR(EFSCORRUPTED);
978 goto error2;
979 }
980
981
982
983
984
985 error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip, 0);
986 if (error) {
987 cmn_err(CE_WARN, "XFS: failed to read root inode");
988 goto error3;
989 }
990
991 ASSERT(rip != NULL);
992 rvp = XFS_ITOV(rip);
993
994 if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) {
995 cmn_err(CE_WARN, "XFS: corrupted root inode");
996 cmn_err(CE_WARN, "Device %s - root %llu is not a directory",
997 XFS_BUFTARG_NAME(mp->m_ddev_targp),
998 (unsigned long long)rip->i_ino);
999 xfs_iunlock(rip, XFS_ILOCK_EXCL);
1000 XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW,
1001 mp);
1002 error = XFS_ERROR(EFSCORRUPTED);
1003 goto error4;
1004 }
1005 mp->m_rootip = rip;
1006
1007 xfs_iunlock(rip, XFS_ILOCK_EXCL);
1008
1009
1010
1011
1012 if ((error = xfs_rtmount_inodes(mp))) {
1013
1014
1015
1016 cmn_err(CE_WARN, "XFS: failed to read RT inodes");
1017 goto error4;
1018 }
1019
1020
1021
1022
1023
1024 if (update_flags && !(vfsp->vfs_flag & VFS_RDONLY))
1025 xfs_mount_log_sbunit(mp, update_flags);
1026
1027
1028
1029
1030 if ((error = XFS_QM_INIT(mp, "amount, "aflags)))
1031 goto error4;
1032
1033
1034
1035
1036
1037
1038 error = xfs_log_mount_finish(mp, mfsi_flags);
1039 if (error) {
1040 cmn_err(CE_WARN, "XFS: log mount finish failed");
1041 goto error4;
1042 }
1043
1044
1045
1046
1047 if ((error = XFS_QM_MOUNT(mp, quotamount, quotaflags, mfsi_flags)))
1048 goto error4;
1049
1050 return 0;
1051
1052 error4:
1053
1054
1055
1056 VN_RELE(rvp);
1057 error3:
1058 xfs_log_unmount_dealloc(mp);
1059 error2:
1060 xfs_ihash_free(mp);
1061 xfs_chash_free(mp);
1062 for (agno = 0; agno < sbp->sb_agcount; agno++)
1063 if (mp->m_perag[agno].pagb_list)
1064 kmem_free(mp->m_perag[agno].pagb_list,
1065 sizeof(xfs_perag_busy_t) * XFS_PAGB_NUM_SLOTS);
1066 kmem_free(mp->m_perag, sbp->sb_agcount * sizeof(xfs_perag_t));
1067 mp->m_perag = NULL;
1068
1069 error1:
1070 if (uuid_mounted)
1071 xfs_uuid_unmount(mp);
1072 xfs_freesb(mp);
1073 return error;
1074}
1075
1076
1077
1078
1079
1080
1081
1082int
1083xfs_unmountfs(xfs_mount_t *mp, struct cred *cr)
1084{
1085 struct bhv_vfs *vfsp = XFS_MTOVFS(mp);
1086#if defined(DEBUG) || defined(INDUCE_IO_ERROR)
1087 int64_t fsid;
1088#endif
1089
1090 xfs_iflush_all(mp);
1091
1092 XFS_QM_DQPURGEALL(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_UMOUNTING);
1093
1094
1095
1096
1097
1098
1099 xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE | XFS_LOG_SYNC);
1100
1101 xfs_binval(mp->m_ddev_targp);
1102 if (mp->m_rtdev_targp) {
1103 xfs_binval(mp->m_rtdev_targp);
1104 }
1105
1106 xfs_unmountfs_writesb(mp);
1107
1108 xfs_unmountfs_wait(mp);
1109
1110 xfs_log_unmount(mp);
1111
1112 xfs_freesb(mp);
1113
1114
1115
1116
1117 ASSERT(mp->m_inodes == NULL);
1118
1119 xfs_unmountfs_close(mp, cr);
1120 if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0)
1121 xfs_uuid_unmount(mp);
1122
1123#if defined(DEBUG) || defined(INDUCE_IO_ERROR)
1124
1125
1126
1127 memcpy(&fsid, &vfsp->vfs_fsid, sizeof(int64_t));
1128 xfs_errortag_clearall_umount(fsid, mp->m_fsname, 0);
1129#endif
1130 XFS_IODONE(vfsp);
1131 xfs_mount_free(mp, 1);
1132 return 0;
1133}
1134
1135void
1136xfs_unmountfs_close(xfs_mount_t *mp, struct cred *cr)
1137{
1138 if (mp->m_logdev_targp != mp->m_ddev_targp)
1139 xfs_free_buftarg(mp->m_logdev_targp, 1);
1140 if (mp->m_rtdev_targp)
1141 xfs_free_buftarg(mp->m_rtdev_targp, 1);
1142 xfs_free_buftarg(mp->m_ddev_targp, 0);
1143}
1144
1145STATIC void
1146xfs_unmountfs_wait(xfs_mount_t *mp)
1147{
1148 if (mp->m_logdev_targp != mp->m_ddev_targp)
1149 xfs_wait_buftarg(mp->m_logdev_targp);
1150 if (mp->m_rtdev_targp)
1151 xfs_wait_buftarg(mp->m_rtdev_targp);
1152 xfs_wait_buftarg(mp->m_ddev_targp);
1153}
1154
1155int
1156xfs_unmountfs_writesb(xfs_mount_t *mp)
1157{
1158 xfs_buf_t *sbp;
1159 xfs_sb_t *sb;
1160 int error = 0;
1161
1162
1163
1164
1165
1166 sbp = xfs_getsb(mp, 0);
1167 if (!(XFS_MTOVFS(mp)->vfs_flag & VFS_RDONLY ||
1168 XFS_FORCED_SHUTDOWN(mp))) {
1169
1170 xfs_icsb_sync_counters(mp);
1171
1172
1173
1174
1175 sb = XFS_BUF_TO_SBP(sbp);
1176 if (mp->m_mk_sharedro) {
1177 if (!(sb->sb_flags & XFS_SBF_READONLY))
1178 sb->sb_flags |= XFS_SBF_READONLY;
1179 if (!XFS_SB_VERSION_HASSHARED(sb))
1180 XFS_SB_VERSION_ADDSHARED(sb);
1181 xfs_fs_cmn_err(CE_NOTE, mp,
1182 "Unmounting, marking shared read-only");
1183 }
1184 XFS_BUF_UNDONE(sbp);
1185 XFS_BUF_UNREAD(sbp);
1186 XFS_BUF_UNDELAYWRITE(sbp);
1187 XFS_BUF_WRITE(sbp);
1188 XFS_BUF_UNASYNC(sbp);
1189 ASSERT(XFS_BUF_TARGET(sbp) == mp->m_ddev_targp);
1190 xfsbdstrat(mp, sbp);
1191
1192 error = xfs_iowait(sbp);
1193 if (error)
1194 xfs_ioerror_alert("xfs_unmountfs_writesb",
1195 mp, sbp, XFS_BUF_ADDR(sbp));
1196 if (error && mp->m_mk_sharedro)
1197 xfs_fs_cmn_err(CE_ALERT, mp, "Superblock write error detected while unmounting. Filesystem may not be marked shared readonly");
1198 }
1199 xfs_buf_relse(sbp);
1200 return error;
1201}
1202
1203
1204
1205
1206
1207
1208
1209
1210void
1211xfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
1212{
1213 xfs_buf_t *bp;
1214 int first;
1215 int last;
1216 xfs_mount_t *mp;
1217 xfs_sb_t *sbp;
1218 xfs_sb_field_t f;
1219
1220 ASSERT(fields);
1221 if (!fields)
1222 return;
1223 mp = tp->t_mountp;
1224 bp = xfs_trans_getsb(tp, mp, 0);
1225 sbp = XFS_BUF_TO_SBP(bp);
1226 first = sizeof(xfs_sb_t);
1227 last = 0;
1228
1229
1230
1231 xfs_xlatesb(XFS_BUF_PTR(bp), &(mp->m_sb), -1, fields);
1232
1233
1234
1235 f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
1236 ASSERT((1LL << f) & XFS_SB_MOD_BITS);
1237 first = xfs_sb_info[f].offset;
1238
1239 f = (xfs_sb_field_t)xfs_highbit64((__uint64_t)fields);
1240 ASSERT((1LL << f) & XFS_SB_MOD_BITS);
1241 last = xfs_sb_info[f + 1].offset - 1;
1242
1243 xfs_trans_log_buf(tp, bp, first, last);
1244}
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256int
1257xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field,
1258 int delta, int rsvd)
1259{
1260 int scounter;
1261 long long lcounter;
1262 long long res_used, rem;
1263
1264
1265
1266
1267
1268
1269
1270 switch (field) {
1271 case XFS_SBS_ICOUNT:
1272 lcounter = (long long)mp->m_sb.sb_icount;
1273 lcounter += delta;
1274 if (lcounter < 0) {
1275 ASSERT(0);
1276 return XFS_ERROR(EINVAL);
1277 }
1278 mp->m_sb.sb_icount = lcounter;
1279 return 0;
1280 case XFS_SBS_IFREE:
1281 lcounter = (long long)mp->m_sb.sb_ifree;
1282 lcounter += delta;
1283 if (lcounter < 0) {
1284 ASSERT(0);
1285 return XFS_ERROR(EINVAL);
1286 }
1287 mp->m_sb.sb_ifree = lcounter;
1288 return 0;
1289 case XFS_SBS_FDBLOCKS:
1290
1291 lcounter = (long long)
1292 mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
1293 res_used = (long long)(mp->m_resblks - mp->m_resblks_avail);
1294
1295 if (delta > 0) {
1296 if (res_used > delta) {
1297 mp->m_resblks_avail += delta;
1298 } else {
1299 rem = delta - res_used;
1300 mp->m_resblks_avail = mp->m_resblks;
1301 lcounter += rem;
1302 }
1303 } else {
1304
1305 lcounter += delta;
1306
1307
1308
1309
1310
1311
1312 if (lcounter < 0) {
1313 if (rsvd) {
1314 lcounter = (long long)mp->m_resblks_avail + delta;
1315 if (lcounter < 0) {
1316 return XFS_ERROR(ENOSPC);
1317 }
1318 mp->m_resblks_avail = lcounter;
1319 return 0;
1320 } else {
1321 return XFS_ERROR(ENOSPC);
1322 }
1323 }
1324 }
1325
1326 mp->m_sb.sb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
1327 return 0;
1328 case XFS_SBS_FREXTENTS:
1329 lcounter = (long long)mp->m_sb.sb_frextents;
1330 lcounter += delta;
1331 if (lcounter < 0) {
1332 return XFS_ERROR(ENOSPC);
1333 }
1334 mp->m_sb.sb_frextents = lcounter;
1335 return 0;
1336 case XFS_SBS_DBLOCKS:
1337 lcounter = (long long)mp->m_sb.sb_dblocks;
1338 lcounter += delta;
1339 if (lcounter < 0) {
1340 ASSERT(0);
1341 return XFS_ERROR(EINVAL);
1342 }
1343 mp->m_sb.sb_dblocks = lcounter;
1344 return 0;
1345 case XFS_SBS_AGCOUNT:
1346 scounter = mp->m_sb.sb_agcount;
1347 scounter += delta;
1348 if (scounter < 0) {
1349 ASSERT(0);
1350 return XFS_ERROR(EINVAL);
1351 }
1352 mp->m_sb.sb_agcount = scounter;
1353 return 0;
1354 case XFS_SBS_IMAX_PCT:
1355 scounter = mp->m_sb.sb_imax_pct;
1356 scounter += delta;
1357 if (scounter < 0) {
1358 ASSERT(0);
1359 return XFS_ERROR(EINVAL);
1360 }
1361 mp->m_sb.sb_imax_pct = scounter;
1362 return 0;
1363 case XFS_SBS_REXTSIZE:
1364 scounter = mp->m_sb.sb_rextsize;
1365 scounter += delta;
1366 if (scounter < 0) {
1367 ASSERT(0);
1368 return XFS_ERROR(EINVAL);
1369 }
1370 mp->m_sb.sb_rextsize = scounter;
1371 return 0;
1372 case XFS_SBS_RBMBLOCKS:
1373 scounter = mp->m_sb.sb_rbmblocks;
1374 scounter += delta;
1375 if (scounter < 0) {
1376 ASSERT(0);
1377 return XFS_ERROR(EINVAL);
1378 }
1379 mp->m_sb.sb_rbmblocks = scounter;
1380 return 0;
1381 case XFS_SBS_RBLOCKS:
1382 lcounter = (long long)mp->m_sb.sb_rblocks;
1383 lcounter += delta;
1384 if (lcounter < 0) {
1385 ASSERT(0);
1386 return XFS_ERROR(EINVAL);
1387 }
1388 mp->m_sb.sb_rblocks = lcounter;
1389 return 0;
1390 case XFS_SBS_REXTENTS:
1391 lcounter = (long long)mp->m_sb.sb_rextents;
1392 lcounter += delta;
1393 if (lcounter < 0) {
1394 ASSERT(0);
1395 return XFS_ERROR(EINVAL);
1396 }
1397 mp->m_sb.sb_rextents = lcounter;
1398 return 0;
1399 case XFS_SBS_REXTSLOG:
1400 scounter = mp->m_sb.sb_rextslog;
1401 scounter += delta;
1402 if (scounter < 0) {
1403 ASSERT(0);
1404 return XFS_ERROR(EINVAL);
1405 }
1406 mp->m_sb.sb_rextslog = scounter;
1407 return 0;
1408 default:
1409 ASSERT(0);
1410 return XFS_ERROR(EINVAL);
1411 }
1412}
1413
1414
1415
1416
1417
1418
1419
1420int
1421xfs_mod_incore_sb(xfs_mount_t *mp, xfs_sb_field_t field, int delta, int rsvd)
1422{
1423 unsigned long s;
1424 int status;
1425
1426
1427 switch (field) {
1428#ifdef HAVE_PERCPU_SB
1429 case XFS_SBS_ICOUNT:
1430 case XFS_SBS_IFREE:
1431 case XFS_SBS_FDBLOCKS:
1432 if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) {
1433 status = xfs_icsb_modify_counters(mp, field,
1434 delta, rsvd);
1435 break;
1436 }
1437
1438#endif
1439 default:
1440 s = XFS_SB_LOCK(mp);
1441 status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
1442 XFS_SB_UNLOCK(mp, s);
1443 break;
1444 }
1445
1446 return status;
1447}
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460int
1461xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd)
1462{
1463 unsigned long s;
1464 int status=0;
1465 xfs_mod_sb_t *msbp;
1466
1467
1468
1469
1470
1471
1472
1473
1474 s = XFS_SB_LOCK(mp);
1475 msbp = &msb[0];
1476 for (msbp = &msbp[0]; msbp < (msb + nmsb); msbp++) {
1477
1478
1479
1480
1481
1482 switch (msbp->msb_field) {
1483#ifdef HAVE_PERCPU_SB
1484 case XFS_SBS_ICOUNT:
1485 case XFS_SBS_IFREE:
1486 case XFS_SBS_FDBLOCKS:
1487 if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) {
1488 status = xfs_icsb_modify_counters_locked(mp,
1489 msbp->msb_field,
1490 msbp->msb_delta, rsvd);
1491 break;
1492 }
1493
1494#endif
1495 default:
1496 status = xfs_mod_incore_sb_unlocked(mp,
1497 msbp->msb_field,
1498 msbp->msb_delta, rsvd);
1499 break;
1500 }
1501
1502 if (status != 0) {
1503 break;
1504 }
1505 }
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515 if (status != 0) {
1516 msbp--;
1517 while (msbp >= msb) {
1518 switch (msbp->msb_field) {
1519#ifdef HAVE_PERCPU_SB
1520 case XFS_SBS_ICOUNT:
1521 case XFS_SBS_IFREE:
1522 case XFS_SBS_FDBLOCKS:
1523 if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) {
1524 status =
1525 xfs_icsb_modify_counters_locked(mp,
1526 msbp->msb_field,
1527 -(msbp->msb_delta),
1528 rsvd);
1529 break;
1530 }
1531
1532#endif
1533 default:
1534 status = xfs_mod_incore_sb_unlocked(mp,
1535 msbp->msb_field,
1536 -(msbp->msb_delta),
1537 rsvd);
1538 break;
1539 }
1540 ASSERT(status == 0);
1541 msbp--;
1542 }
1543 }
1544 XFS_SB_UNLOCK(mp, s);
1545 return status;
1546}
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557xfs_buf_t *
1558xfs_getsb(
1559 xfs_mount_t *mp,
1560 int flags)
1561{
1562 xfs_buf_t *bp;
1563
1564 ASSERT(mp->m_sb_bp != NULL);
1565 bp = mp->m_sb_bp;
1566 if (flags & XFS_BUF_TRYLOCK) {
1567 if (!XFS_BUF_CPSEMA(bp)) {
1568 return NULL;
1569 }
1570 } else {
1571 XFS_BUF_PSEMA(bp, PRIBIO);
1572 }
1573 XFS_BUF_HOLD(bp);
1574 ASSERT(XFS_BUF_ISDONE(bp));
1575 return bp;
1576}
1577
1578
1579
1580
1581void
1582xfs_freesb(
1583 xfs_mount_t *mp)
1584{
1585 xfs_buf_t *bp;
1586
1587
1588
1589
1590
1591 bp = xfs_getsb(mp, 0);
1592 XFS_BUF_UNMANAGE(bp);
1593 xfs_buf_relse(bp);
1594 mp->m_sb_bp = NULL;
1595}
1596
1597
1598
1599
1600
1601STATIC int
1602xfs_uuid_mount(
1603 xfs_mount_t *mp)
1604{
1605 if (uuid_is_nil(&mp->m_sb.sb_uuid)) {
1606 cmn_err(CE_WARN,
1607 "XFS: Filesystem %s has nil UUID - can't mount",
1608 mp->m_fsname);
1609 return -1;
1610 }
1611 if (!uuid_table_insert(&mp->m_sb.sb_uuid)) {
1612 cmn_err(CE_WARN,
1613 "XFS: Filesystem %s has duplicate UUID - can't mount",
1614 mp->m_fsname);
1615 return -1;
1616 }
1617 return 0;
1618}
1619
1620
1621
1622
1623STATIC void
1624xfs_uuid_unmount(
1625 xfs_mount_t *mp)
1626{
1627 uuid_table_remove(&mp->m_sb.sb_uuid);
1628}
1629
1630
1631
1632
1633
1634STATIC void
1635xfs_mount_log_sbunit(
1636 xfs_mount_t *mp,
1637 __int64_t fields)
1638{
1639 xfs_trans_t *tp;
1640
1641 ASSERT(fields & (XFS_SB_UNIT|XFS_SB_WIDTH|XFS_SB_UUID));
1642
1643 tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT);
1644 if (xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
1645 XFS_DEFAULT_LOG_COUNT)) {
1646 xfs_trans_cancel(tp, 0);
1647 return;
1648 }
1649 xfs_mod_sb(tp, fields);
1650 xfs_trans_commit(tp, 0, NULL);
1651}
1652
1653
1654#ifdef HAVE_PERCPU_SB
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707#ifdef CONFIG_HOTPLUG_CPU
1708
1709
1710
1711
1712
1713
1714
1715
1716STATIC int
1717xfs_icsb_cpu_notify(
1718 struct notifier_block *nfb,
1719 unsigned long action,
1720 void *hcpu)
1721{
1722 xfs_icsb_cnts_t *cntp;
1723 xfs_mount_t *mp;
1724 int s;
1725
1726 mp = (xfs_mount_t *)container_of(nfb, xfs_mount_t, m_icsb_notifier);
1727 cntp = (xfs_icsb_cnts_t *)
1728 per_cpu_ptr(mp->m_sb_cnts, (unsigned long)hcpu);
1729 switch (action) {
1730 case CPU_UP_PREPARE:
1731
1732
1733 memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
1734 break;
1735 case CPU_ONLINE:
1736 xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
1737 xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
1738 xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
1739 break;
1740 case CPU_DEAD:
1741
1742
1743
1744 s = XFS_SB_LOCK(mp);
1745 xfs_icsb_disable_counter(mp, XFS_SBS_ICOUNT);
1746 xfs_icsb_disable_counter(mp, XFS_SBS_IFREE);
1747 xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS);
1748
1749 mp->m_sb.sb_icount += cntp->icsb_icount;
1750 mp->m_sb.sb_ifree += cntp->icsb_ifree;
1751 mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks;
1752
1753 memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
1754
1755 xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, XFS_ICSB_SB_LOCKED);
1756 xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, XFS_ICSB_SB_LOCKED);
1757 xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, XFS_ICSB_SB_LOCKED);
1758 XFS_SB_UNLOCK(mp, s);
1759 break;
1760 }
1761
1762 return NOTIFY_OK;
1763}
1764#endif
1765
1766int
1767xfs_icsb_init_counters(
1768 xfs_mount_t *mp)
1769{
1770 xfs_icsb_cnts_t *cntp;
1771 int i;
1772
1773 mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t);
1774 if (mp->m_sb_cnts == NULL)
1775 return -ENOMEM;
1776
1777#ifdef CONFIG_HOTPLUG_CPU
1778 mp->m_icsb_notifier.notifier_call = xfs_icsb_cpu_notify;
1779 mp->m_icsb_notifier.priority = 0;
1780 register_hotcpu_notifier(&mp->m_icsb_notifier);
1781#endif
1782
1783 for_each_online_cpu(i) {
1784 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
1785 memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
1786 }
1787
1788
1789
1790
1791 mp->m_icsb_counters = -1;
1792 return 0;
1793}
1794
1795STATIC void
1796xfs_icsb_destroy_counters(
1797 xfs_mount_t *mp)
1798{
1799 if (mp->m_sb_cnts) {
1800 unregister_hotcpu_notifier(&mp->m_icsb_notifier);
1801 free_percpu(mp->m_sb_cnts);
1802 }
1803}
1804
1805STATIC inline void
1806xfs_icsb_lock_cntr(
1807 xfs_icsb_cnts_t *icsbp)
1808{
1809 while (test_and_set_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags)) {
1810 ndelay(1000);
1811 }
1812}
1813
1814STATIC inline void
1815xfs_icsb_unlock_cntr(
1816 xfs_icsb_cnts_t *icsbp)
1817{
1818 clear_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags);
1819}
1820
1821
1822STATIC inline void
1823xfs_icsb_lock_all_counters(
1824 xfs_mount_t *mp)
1825{
1826 xfs_icsb_cnts_t *cntp;
1827 int i;
1828
1829 for_each_online_cpu(i) {
1830 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
1831 xfs_icsb_lock_cntr(cntp);
1832 }
1833}
1834
1835STATIC inline void
1836xfs_icsb_unlock_all_counters(
1837 xfs_mount_t *mp)
1838{
1839 xfs_icsb_cnts_t *cntp;
1840 int i;
1841
1842 for_each_online_cpu(i) {
1843 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
1844 xfs_icsb_unlock_cntr(cntp);
1845 }
1846}
1847
1848STATIC void
1849xfs_icsb_count(
1850 xfs_mount_t *mp,
1851 xfs_icsb_cnts_t *cnt,
1852 int flags)
1853{
1854 xfs_icsb_cnts_t *cntp;
1855 int i;
1856
1857 memset(cnt, 0, sizeof(xfs_icsb_cnts_t));
1858
1859 if (!(flags & XFS_ICSB_LAZY_COUNT))
1860 xfs_icsb_lock_all_counters(mp);
1861
1862 for_each_online_cpu(i) {
1863 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
1864 cnt->icsb_icount += cntp->icsb_icount;
1865 cnt->icsb_ifree += cntp->icsb_ifree;
1866 cnt->icsb_fdblocks += cntp->icsb_fdblocks;
1867 }
1868
1869 if (!(flags & XFS_ICSB_LAZY_COUNT))
1870 xfs_icsb_unlock_all_counters(mp);
1871}
1872
1873STATIC int
1874xfs_icsb_counter_disabled(
1875 xfs_mount_t *mp,
1876 xfs_sb_field_t field)
1877{
1878 ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
1879 return test_bit(field, &mp->m_icsb_counters);
1880}
1881
1882STATIC int
1883xfs_icsb_disable_counter(
1884 xfs_mount_t *mp,
1885 xfs_sb_field_t field)
1886{
1887 xfs_icsb_cnts_t cnt;
1888
1889 ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
1890
1891 xfs_icsb_lock_all_counters(mp);
1892 if (!test_and_set_bit(field, &mp->m_icsb_counters)) {
1893
1894
1895 xfs_icsb_count(mp, &cnt, XFS_ICSB_SB_LOCKED|XFS_ICSB_LAZY_COUNT);
1896 switch(field) {
1897 case XFS_SBS_ICOUNT:
1898 mp->m_sb.sb_icount = cnt.icsb_icount;
1899 break;
1900 case XFS_SBS_IFREE:
1901 mp->m_sb.sb_ifree = cnt.icsb_ifree;
1902 break;
1903 case XFS_SBS_FDBLOCKS:
1904 mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
1905 break;
1906 default:
1907 BUG();
1908 }
1909 }
1910
1911 xfs_icsb_unlock_all_counters(mp);
1912
1913 return 0;
1914}
1915
1916STATIC void
1917xfs_icsb_enable_counter(
1918 xfs_mount_t *mp,
1919 xfs_sb_field_t field,
1920 uint64_t count,
1921 uint64_t resid)
1922{
1923 xfs_icsb_cnts_t *cntp;
1924 int i;
1925
1926 ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
1927
1928 xfs_icsb_lock_all_counters(mp);
1929 for_each_online_cpu(i) {
1930 cntp = per_cpu_ptr(mp->m_sb_cnts, i);
1931 switch (field) {
1932 case XFS_SBS_ICOUNT:
1933 cntp->icsb_icount = count + resid;
1934 break;
1935 case XFS_SBS_IFREE:
1936 cntp->icsb_ifree = count + resid;
1937 break;
1938 case XFS_SBS_FDBLOCKS:
1939 cntp->icsb_fdblocks = count + resid;
1940 break;
1941 default:
1942 BUG();
1943 break;
1944 }
1945 resid = 0;
1946 }
1947 clear_bit(field, &mp->m_icsb_counters);
1948 xfs_icsb_unlock_all_counters(mp);
1949}
1950
1951STATIC void
1952xfs_icsb_sync_counters_int(
1953 xfs_mount_t *mp,
1954 int flags)
1955{
1956 xfs_icsb_cnts_t cnt;
1957 int s;
1958
1959
1960 if ((flags & XFS_ICSB_SB_LOCKED) == 0)
1961 s = XFS_SB_LOCK(mp);
1962
1963 xfs_icsb_count(mp, &cnt, flags);
1964
1965
1966 if (!xfs_icsb_counter_disabled(mp, XFS_SBS_ICOUNT))
1967 mp->m_sb.sb_icount = cnt.icsb_icount;
1968 if (!xfs_icsb_counter_disabled(mp, XFS_SBS_IFREE))
1969 mp->m_sb.sb_ifree = cnt.icsb_ifree;
1970 if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
1971 mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
1972
1973 if ((flags & XFS_ICSB_SB_LOCKED) == 0)
1974 XFS_SB_UNLOCK(mp, s);
1975}
1976
1977
1978
1979
1980STATIC void
1981xfs_icsb_sync_counters(
1982 xfs_mount_t *mp)
1983{
1984 xfs_icsb_sync_counters_int(mp, 0);
1985}
1986
1987
1988
1989
1990void
1991xfs_icsb_sync_counters_lazy(
1992 xfs_mount_t *mp)
1993{
1994 xfs_icsb_sync_counters_int(mp, XFS_ICSB_LAZY_COUNT);
1995}
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006#define XFS_ICSB_INO_CNTR_REENABLE 64
2007#define XFS_ICSB_FDBLK_CNTR_REENABLE(mp) \
2008 (512 + XFS_ALLOC_SET_ASIDE(mp))
2009STATIC void
2010xfs_icsb_balance_counter(
2011 xfs_mount_t *mp,
2012 xfs_sb_field_t field,
2013 int flags)
2014{
2015 uint64_t count, resid;
2016 int weight = num_online_cpus();
2017 int s;
2018
2019 if (!(flags & XFS_ICSB_SB_LOCKED))
2020 s = XFS_SB_LOCK(mp);
2021
2022
2023 xfs_icsb_disable_counter(mp, field);
2024
2025
2026 switch (field) {
2027 case XFS_SBS_ICOUNT:
2028 count = mp->m_sb.sb_icount;
2029 resid = do_div(count, weight);
2030 if (count < XFS_ICSB_INO_CNTR_REENABLE)
2031 goto out;
2032 break;
2033 case XFS_SBS_IFREE:
2034 count = mp->m_sb.sb_ifree;
2035 resid = do_div(count, weight);
2036 if (count < XFS_ICSB_INO_CNTR_REENABLE)
2037 goto out;
2038 break;
2039 case XFS_SBS_FDBLOCKS:
2040 count = mp->m_sb.sb_fdblocks;
2041 resid = do_div(count, weight);
2042 if (count < XFS_ICSB_FDBLK_CNTR_REENABLE(mp))
2043 goto out;
2044 break;
2045 default:
2046 BUG();
2047 count = resid = 0;
2048 break;
2049 }
2050
2051 xfs_icsb_enable_counter(mp, field, count, resid);
2052out:
2053 if (!(flags & XFS_ICSB_SB_LOCKED))
2054 XFS_SB_UNLOCK(mp, s);
2055}
2056
2057STATIC int
2058xfs_icsb_modify_counters_int(
2059 xfs_mount_t *mp,
2060 xfs_sb_field_t field,
2061 int delta,
2062 int rsvd,
2063 int flags)
2064{
2065 xfs_icsb_cnts_t *icsbp;
2066 long long lcounter;
2067 int cpu, s, locked = 0;
2068 int ret = 0, balance_done = 0;
2069
2070again:
2071 cpu = get_cpu();
2072 icsbp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, cpu),
2073 xfs_icsb_lock_cntr(icsbp);
2074 if (unlikely(xfs_icsb_counter_disabled(mp, field)))
2075 goto slow_path;
2076
2077 switch (field) {
2078 case XFS_SBS_ICOUNT:
2079 lcounter = icsbp->icsb_icount;
2080 lcounter += delta;
2081 if (unlikely(lcounter < 0))
2082 goto slow_path;
2083 icsbp->icsb_icount = lcounter;
2084 break;
2085
2086 case XFS_SBS_IFREE:
2087 lcounter = icsbp->icsb_ifree;
2088 lcounter += delta;
2089 if (unlikely(lcounter < 0))
2090 goto slow_path;
2091 icsbp->icsb_ifree = lcounter;
2092 break;
2093
2094 case XFS_SBS_FDBLOCKS:
2095 BUG_ON((mp->m_resblks - mp->m_resblks_avail) != 0);
2096
2097 lcounter = icsbp->icsb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
2098 lcounter += delta;
2099 if (unlikely(lcounter < 0))
2100 goto slow_path;
2101 icsbp->icsb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
2102 break;
2103 default:
2104 BUG();
2105 break;
2106 }
2107 xfs_icsb_unlock_cntr(icsbp);
2108 put_cpu();
2109 if (locked)
2110 XFS_SB_UNLOCK(mp, s);
2111 return 0;
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122slow_path:
2123 xfs_icsb_unlock_cntr(icsbp);
2124 put_cpu();
2125
2126
2127
2128 if (!(flags & XFS_ICSB_SB_LOCKED)) {
2129 s = XFS_SB_LOCK(mp);
2130 locked = 1;
2131 flags |= XFS_ICSB_SB_LOCKED;
2132 }
2133 if (!balance_done) {
2134 xfs_icsb_balance_counter(mp, field, flags);
2135 balance_done = 1;
2136 goto again;
2137 } else {
2138
2139
2140
2141
2142
2143
2144 xfs_icsb_disable_counter(mp, field);
2145 }
2146
2147 ret = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
2148
2149 if (locked)
2150 XFS_SB_UNLOCK(mp, s);
2151 return ret;
2152}
2153
2154STATIC int
2155xfs_icsb_modify_counters(
2156 xfs_mount_t *mp,
2157 xfs_sb_field_t field,
2158 int delta,
2159 int rsvd)
2160{
2161 return xfs_icsb_modify_counters_int(mp, field, delta, rsvd, 0);
2162}
2163
2164
2165
2166
2167STATIC int
2168xfs_icsb_modify_counters_locked(
2169 xfs_mount_t *mp,
2170 xfs_sb_field_t field,
2171 int delta,
2172 int rsvd)
2173{
2174 return xfs_icsb_modify_counters_int(mp, field, delta,
2175 rsvd, XFS_ICSB_SB_LOCKED);
2176}
2177#endif
2178