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_trans_priv.h"
26#include "xfs_sb.h"
27#include "xfs_ag.h"
28#include "xfs_dir2.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_dinode.h"
34#include "xfs_inode.h"
35#include "xfs_btree.h"
36#include "xfs_ialloc.h"
37#include "xfs_alloc.h"
38#include "xfs_rtalloc.h"
39#include "xfs_bmap.h"
40#include "xfs_error.h"
41#include "xfs_quota.h"
42#include "xfs_fsops.h"
43#include "xfs_utils.h"
44#include "xfs_trace.h"
45
46
47#ifdef HAVE_PERCPU_SB
48STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t,
49 int);
50STATIC void xfs_icsb_balance_counter_locked(xfs_mount_t *, xfs_sb_field_t,
51 int);
52STATIC void xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t);
53#else
54
55#define xfs_icsb_balance_counter(mp, a, b) do { } while (0)
56#define xfs_icsb_balance_counter_locked(mp, a, b) do { } while (0)
57#endif
58
59static const struct {
60 short offset;
61 short type;
62
63
64} xfs_sb_info[] = {
65 { offsetof(xfs_sb_t, sb_magicnum), 0 },
66 { offsetof(xfs_sb_t, sb_blocksize), 0 },
67 { offsetof(xfs_sb_t, sb_dblocks), 0 },
68 { offsetof(xfs_sb_t, sb_rblocks), 0 },
69 { offsetof(xfs_sb_t, sb_rextents), 0 },
70 { offsetof(xfs_sb_t, sb_uuid), 1 },
71 { offsetof(xfs_sb_t, sb_logstart), 0 },
72 { offsetof(xfs_sb_t, sb_rootino), 0 },
73 { offsetof(xfs_sb_t, sb_rbmino), 0 },
74 { offsetof(xfs_sb_t, sb_rsumino), 0 },
75 { offsetof(xfs_sb_t, sb_rextsize), 0 },
76 { offsetof(xfs_sb_t, sb_agblocks), 0 },
77 { offsetof(xfs_sb_t, sb_agcount), 0 },
78 { offsetof(xfs_sb_t, sb_rbmblocks), 0 },
79 { offsetof(xfs_sb_t, sb_logblocks), 0 },
80 { offsetof(xfs_sb_t, sb_versionnum), 0 },
81 { offsetof(xfs_sb_t, sb_sectsize), 0 },
82 { offsetof(xfs_sb_t, sb_inodesize), 0 },
83 { offsetof(xfs_sb_t, sb_inopblock), 0 },
84 { offsetof(xfs_sb_t, sb_fname[0]), 1 },
85 { offsetof(xfs_sb_t, sb_blocklog), 0 },
86 { offsetof(xfs_sb_t, sb_sectlog), 0 },
87 { offsetof(xfs_sb_t, sb_inodelog), 0 },
88 { offsetof(xfs_sb_t, sb_inopblog), 0 },
89 { offsetof(xfs_sb_t, sb_agblklog), 0 },
90 { offsetof(xfs_sb_t, sb_rextslog), 0 },
91 { offsetof(xfs_sb_t, sb_inprogress), 0 },
92 { offsetof(xfs_sb_t, sb_imax_pct), 0 },
93 { offsetof(xfs_sb_t, sb_icount), 0 },
94 { offsetof(xfs_sb_t, sb_ifree), 0 },
95 { offsetof(xfs_sb_t, sb_fdblocks), 0 },
96 { offsetof(xfs_sb_t, sb_frextents), 0 },
97 { offsetof(xfs_sb_t, sb_uquotino), 0 },
98 { offsetof(xfs_sb_t, sb_gquotino), 0 },
99 { offsetof(xfs_sb_t, sb_qflags), 0 },
100 { offsetof(xfs_sb_t, sb_flags), 0 },
101 { offsetof(xfs_sb_t, sb_shared_vn), 0 },
102 { offsetof(xfs_sb_t, sb_inoalignmt), 0 },
103 { offsetof(xfs_sb_t, sb_unit), 0 },
104 { offsetof(xfs_sb_t, sb_width), 0 },
105 { offsetof(xfs_sb_t, sb_dirblklog), 0 },
106 { offsetof(xfs_sb_t, sb_logsectlog), 0 },
107 { offsetof(xfs_sb_t, sb_logsectsize),0 },
108 { offsetof(xfs_sb_t, sb_logsunit), 0 },
109 { offsetof(xfs_sb_t, sb_features2), 0 },
110 { offsetof(xfs_sb_t, sb_bad_features2), 0 },
111 { sizeof(xfs_sb_t), 0 }
112};
113
114static DEFINE_MUTEX(xfs_uuid_table_mutex);
115static int xfs_uuid_table_size;
116static uuid_t *xfs_uuid_table;
117
118
119
120
121
122STATIC int
123xfs_uuid_mount(
124 struct xfs_mount *mp)
125{
126 uuid_t *uuid = &mp->m_sb.sb_uuid;
127 int hole, i;
128
129 if (mp->m_flags & XFS_MOUNT_NOUUID)
130 return 0;
131
132 if (uuid_is_nil(uuid)) {
133 xfs_warn(mp, "Filesystem has nil UUID - can't mount");
134 return XFS_ERROR(EINVAL);
135 }
136
137 mutex_lock(&xfs_uuid_table_mutex);
138 for (i = 0, hole = -1; i < xfs_uuid_table_size; i++) {
139 if (uuid_is_nil(&xfs_uuid_table[i])) {
140 hole = i;
141 continue;
142 }
143 if (uuid_equal(uuid, &xfs_uuid_table[i]))
144 goto out_duplicate;
145 }
146
147 if (hole < 0) {
148 xfs_uuid_table = kmem_realloc(xfs_uuid_table,
149 (xfs_uuid_table_size + 1) * sizeof(*xfs_uuid_table),
150 xfs_uuid_table_size * sizeof(*xfs_uuid_table),
151 KM_SLEEP);
152 hole = xfs_uuid_table_size++;
153 }
154 xfs_uuid_table[hole] = *uuid;
155 mutex_unlock(&xfs_uuid_table_mutex);
156
157 return 0;
158
159 out_duplicate:
160 mutex_unlock(&xfs_uuid_table_mutex);
161 xfs_warn(mp, "Filesystem has duplicate UUID %pU - can't mount", uuid);
162 return XFS_ERROR(EINVAL);
163}
164
165STATIC void
166xfs_uuid_unmount(
167 struct xfs_mount *mp)
168{
169 uuid_t *uuid = &mp->m_sb.sb_uuid;
170 int i;
171
172 if (mp->m_flags & XFS_MOUNT_NOUUID)
173 return;
174
175 mutex_lock(&xfs_uuid_table_mutex);
176 for (i = 0; i < xfs_uuid_table_size; i++) {
177 if (uuid_is_nil(&xfs_uuid_table[i]))
178 continue;
179 if (!uuid_equal(uuid, &xfs_uuid_table[i]))
180 continue;
181 memset(&xfs_uuid_table[i], 0, sizeof(uuid_t));
182 break;
183 }
184 ASSERT(i < xfs_uuid_table_size);
185 mutex_unlock(&xfs_uuid_table_mutex);
186}
187
188
189
190
191
192
193
194struct xfs_perag *
195xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno)
196{
197 struct xfs_perag *pag;
198 int ref = 0;
199
200 rcu_read_lock();
201 pag = radix_tree_lookup(&mp->m_perag_tree, agno);
202 if (pag) {
203 ASSERT(atomic_read(&pag->pag_ref) >= 0);
204 ref = atomic_inc_return(&pag->pag_ref);
205 }
206 rcu_read_unlock();
207 trace_xfs_perag_get(mp, agno, ref, _RET_IP_);
208 return pag;
209}
210
211
212
213
214struct xfs_perag *
215xfs_perag_get_tag(
216 struct xfs_mount *mp,
217 xfs_agnumber_t first,
218 int tag)
219{
220 struct xfs_perag *pag;
221 int found;
222 int ref;
223
224 rcu_read_lock();
225 found = radix_tree_gang_lookup_tag(&mp->m_perag_tree,
226 (void **)&pag, first, 1, tag);
227 if (found <= 0) {
228 rcu_read_unlock();
229 return NULL;
230 }
231 ref = atomic_inc_return(&pag->pag_ref);
232 rcu_read_unlock();
233 trace_xfs_perag_get_tag(mp, pag->pag_agno, ref, _RET_IP_);
234 return pag;
235}
236
237void
238xfs_perag_put(struct xfs_perag *pag)
239{
240 int ref;
241
242 ASSERT(atomic_read(&pag->pag_ref) > 0);
243 ref = atomic_dec_return(&pag->pag_ref);
244 trace_xfs_perag_put(pag->pag_mount, pag->pag_agno, ref, _RET_IP_);
245}
246
247STATIC void
248__xfs_free_perag(
249 struct rcu_head *head)
250{
251 struct xfs_perag *pag = container_of(head, struct xfs_perag, rcu_head);
252
253 ASSERT(atomic_read(&pag->pag_ref) == 0);
254 kmem_free(pag);
255}
256
257
258
259
260STATIC void
261xfs_free_perag(
262 xfs_mount_t *mp)
263{
264 xfs_agnumber_t agno;
265 struct xfs_perag *pag;
266
267 for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
268 spin_lock(&mp->m_perag_lock);
269 pag = radix_tree_delete(&mp->m_perag_tree, agno);
270 spin_unlock(&mp->m_perag_lock);
271 ASSERT(pag);
272 ASSERT(atomic_read(&pag->pag_ref) == 0);
273 call_rcu(&pag->rcu_head, __xfs_free_perag);
274 }
275}
276
277
278
279
280
281int
282xfs_sb_validate_fsb_count(
283 xfs_sb_t *sbp,
284 __uint64_t nblocks)
285{
286 ASSERT(PAGE_SHIFT >= sbp->sb_blocklog);
287 ASSERT(sbp->sb_blocklog >= BBSHIFT);
288
289#if XFS_BIG_BLKNOS
290 if (nblocks >> (PAGE_CACHE_SHIFT - sbp->sb_blocklog) > ULONG_MAX)
291 return EFBIG;
292#else
293 if (nblocks << (sbp->sb_blocklog - BBSHIFT) > UINT_MAX)
294 return EFBIG;
295#endif
296 return 0;
297}
298
299
300
301
302STATIC int
303xfs_mount_validate_sb(
304 xfs_mount_t *mp,
305 xfs_sb_t *sbp,
306 int flags)
307{
308 int loud = !(flags & XFS_MFSI_QUIET);
309
310
311
312
313
314
315
316
317 if (sbp->sb_magicnum != XFS_SB_MAGIC) {
318 if (loud)
319 xfs_warn(mp, "bad magic number");
320 return XFS_ERROR(EWRONGFS);
321 }
322
323 if (!xfs_sb_good_version(sbp)) {
324 if (loud)
325 xfs_warn(mp, "bad version");
326 return XFS_ERROR(EWRONGFS);
327 }
328
329 if (unlikely(
330 sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) {
331 if (loud)
332 xfs_warn(mp,
333 "filesystem is marked as having an external log; "
334 "specify logdev on the mount command line.");
335 return XFS_ERROR(EINVAL);
336 }
337
338 if (unlikely(
339 sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) {
340 if (loud)
341 xfs_warn(mp,
342 "filesystem is marked as having an internal log; "
343 "do not specify logdev on the mount command line.");
344 return XFS_ERROR(EINVAL);
345 }
346
347
348
349
350
351 if (unlikely(
352 sbp->sb_agcount <= 0 ||
353 sbp->sb_sectsize < XFS_MIN_SECTORSIZE ||
354 sbp->sb_sectsize > XFS_MAX_SECTORSIZE ||
355 sbp->sb_sectlog < XFS_MIN_SECTORSIZE_LOG ||
356 sbp->sb_sectlog > XFS_MAX_SECTORSIZE_LOG ||
357 sbp->sb_sectsize != (1 << sbp->sb_sectlog) ||
358 sbp->sb_blocksize < XFS_MIN_BLOCKSIZE ||
359 sbp->sb_blocksize > XFS_MAX_BLOCKSIZE ||
360 sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG ||
361 sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG ||
362 sbp->sb_blocksize != (1 << sbp->sb_blocklog) ||
363 sbp->sb_inodesize < XFS_DINODE_MIN_SIZE ||
364 sbp->sb_inodesize > XFS_DINODE_MAX_SIZE ||
365 sbp->sb_inodelog < XFS_DINODE_MIN_LOG ||
366 sbp->sb_inodelog > XFS_DINODE_MAX_LOG ||
367 sbp->sb_inodesize != (1 << sbp->sb_inodelog) ||
368 (sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog) ||
369 (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) ||
370 (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) ||
371 (sbp->sb_imax_pct > 100 ) ||
372 sbp->sb_dblocks == 0 ||
373 sbp->sb_dblocks > XFS_MAX_DBLOCKS(sbp) ||
374 sbp->sb_dblocks < XFS_MIN_DBLOCKS(sbp))) {
375 if (loud)
376 XFS_CORRUPTION_ERROR("SB sanity check failed",
377 XFS_ERRLEVEL_LOW, mp, sbp);
378 return XFS_ERROR(EFSCORRUPTED);
379 }
380
381
382
383
384 if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) {
385 if (loud) {
386 xfs_warn(mp,
387 "File system with blocksize %d bytes. "
388 "Only pagesize (%ld) or less will currently work.",
389 sbp->sb_blocksize, PAGE_SIZE);
390 }
391 return XFS_ERROR(ENOSYS);
392 }
393
394
395
396
397 switch (sbp->sb_inodesize) {
398 case 256:
399 case 512:
400 case 1024:
401 case 2048:
402 break;
403 default:
404 if (loud)
405 xfs_warn(mp, "inode size of %d bytes not supported",
406 sbp->sb_inodesize);
407 return XFS_ERROR(ENOSYS);
408 }
409
410 if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) ||
411 xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) {
412 if (loud)
413 xfs_warn(mp,
414 "file system too large to be mounted on this system.");
415 return XFS_ERROR(EFBIG);
416 }
417
418 if (unlikely(sbp->sb_inprogress)) {
419 if (loud)
420 xfs_warn(mp, "file system busy");
421 return XFS_ERROR(EFSCORRUPTED);
422 }
423
424
425
426
427 if (unlikely(!xfs_sb_version_hasdirv2(sbp))) {
428 if (loud)
429 xfs_warn(mp,
430 "file system using version 1 directory format");
431 return XFS_ERROR(ENOSYS);
432 }
433
434 return 0;
435}
436
437int
438xfs_initialize_perag(
439 xfs_mount_t *mp,
440 xfs_agnumber_t agcount,
441 xfs_agnumber_t *maxagi)
442{
443 xfs_agnumber_t index, max_metadata;
444 xfs_agnumber_t first_initialised = 0;
445 xfs_perag_t *pag;
446 xfs_agino_t agino;
447 xfs_ino_t ino;
448 xfs_sb_t *sbp = &mp->m_sb;
449 int error = -ENOMEM;
450
451
452
453
454
455
456 for (index = 0; index < agcount; index++) {
457 pag = xfs_perag_get(mp, index);
458 if (pag) {
459 xfs_perag_put(pag);
460 continue;
461 }
462 if (!first_initialised)
463 first_initialised = index;
464
465 pag = kmem_zalloc(sizeof(*pag), KM_MAYFAIL);
466 if (!pag)
467 goto out_unwind;
468 pag->pag_agno = index;
469 pag->pag_mount = mp;
470 spin_lock_init(&pag->pag_ici_lock);
471 mutex_init(&pag->pag_ici_reclaim_lock);
472 INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC);
473 spin_lock_init(&pag->pag_buf_lock);
474 pag->pag_buf_tree = RB_ROOT;
475
476 if (radix_tree_preload(GFP_NOFS))
477 goto out_unwind;
478
479 spin_lock(&mp->m_perag_lock);
480 if (radix_tree_insert(&mp->m_perag_tree, index, pag)) {
481 BUG();
482 spin_unlock(&mp->m_perag_lock);
483 radix_tree_preload_end();
484 error = -EEXIST;
485 goto out_unwind;
486 }
487 spin_unlock(&mp->m_perag_lock);
488 radix_tree_preload_end();
489 }
490
491
492
493
494
495 agino = XFS_OFFBNO_TO_AGINO(mp, sbp->sb_agblocks - 1, 0);
496 ino = XFS_AGINO_TO_INO(mp, agcount - 1, agino);
497
498 if ((mp->m_flags & XFS_MOUNT_SMALL_INUMS) && ino > XFS_MAXINUMBER_32)
499 mp->m_flags |= XFS_MOUNT_32BITINODES;
500 else
501 mp->m_flags &= ~XFS_MOUNT_32BITINODES;
502
503 if (mp->m_flags & XFS_MOUNT_32BITINODES) {
504
505
506
507
508 if (mp->m_maxicount) {
509 __uint64_t icount;
510
511 icount = sbp->sb_dblocks * sbp->sb_imax_pct;
512 do_div(icount, 100);
513 icount += sbp->sb_agblocks - 1;
514 do_div(icount, sbp->sb_agblocks);
515 max_metadata = icount;
516 } else {
517 max_metadata = agcount;
518 }
519
520 for (index = 0; index < agcount; index++) {
521 ino = XFS_AGINO_TO_INO(mp, index, agino);
522 if (ino > XFS_MAXINUMBER_32) {
523 index++;
524 break;
525 }
526
527 pag = xfs_perag_get(mp, index);
528 pag->pagi_inodeok = 1;
529 if (index < max_metadata)
530 pag->pagf_metadata = 1;
531 xfs_perag_put(pag);
532 }
533 } else {
534 for (index = 0; index < agcount; index++) {
535 pag = xfs_perag_get(mp, index);
536 pag->pagi_inodeok = 1;
537 xfs_perag_put(pag);
538 }
539 }
540
541 if (maxagi)
542 *maxagi = index;
543 return 0;
544
545out_unwind:
546 kmem_free(pag);
547 for (; index > first_initialised; index--) {
548 pag = radix_tree_delete(&mp->m_perag_tree, index);
549 kmem_free(pag);
550 }
551 return error;
552}
553
554void
555xfs_sb_from_disk(
556 struct xfs_mount *mp,
557 xfs_dsb_t *from)
558{
559 struct xfs_sb *to = &mp->m_sb;
560
561 to->sb_magicnum = be32_to_cpu(from->sb_magicnum);
562 to->sb_blocksize = be32_to_cpu(from->sb_blocksize);
563 to->sb_dblocks = be64_to_cpu(from->sb_dblocks);
564 to->sb_rblocks = be64_to_cpu(from->sb_rblocks);
565 to->sb_rextents = be64_to_cpu(from->sb_rextents);
566 memcpy(&to->sb_uuid, &from->sb_uuid, sizeof(to->sb_uuid));
567 to->sb_logstart = be64_to_cpu(from->sb_logstart);
568 to->sb_rootino = be64_to_cpu(from->sb_rootino);
569 to->sb_rbmino = be64_to_cpu(from->sb_rbmino);
570 to->sb_rsumino = be64_to_cpu(from->sb_rsumino);
571 to->sb_rextsize = be32_to_cpu(from->sb_rextsize);
572 to->sb_agblocks = be32_to_cpu(from->sb_agblocks);
573 to->sb_agcount = be32_to_cpu(from->sb_agcount);
574 to->sb_rbmblocks = be32_to_cpu(from->sb_rbmblocks);
575 to->sb_logblocks = be32_to_cpu(from->sb_logblocks);
576 to->sb_versionnum = be16_to_cpu(from->sb_versionnum);
577 to->sb_sectsize = be16_to_cpu(from->sb_sectsize);
578 to->sb_inodesize = be16_to_cpu(from->sb_inodesize);
579 to->sb_inopblock = be16_to_cpu(from->sb_inopblock);
580 memcpy(&to->sb_fname, &from->sb_fname, sizeof(to->sb_fname));
581 to->sb_blocklog = from->sb_blocklog;
582 to->sb_sectlog = from->sb_sectlog;
583 to->sb_inodelog = from->sb_inodelog;
584 to->sb_inopblog = from->sb_inopblog;
585 to->sb_agblklog = from->sb_agblklog;
586 to->sb_rextslog = from->sb_rextslog;
587 to->sb_inprogress = from->sb_inprogress;
588 to->sb_imax_pct = from->sb_imax_pct;
589 to->sb_icount = be64_to_cpu(from->sb_icount);
590 to->sb_ifree = be64_to_cpu(from->sb_ifree);
591 to->sb_fdblocks = be64_to_cpu(from->sb_fdblocks);
592 to->sb_frextents = be64_to_cpu(from->sb_frextents);
593 to->sb_uquotino = be64_to_cpu(from->sb_uquotino);
594 to->sb_gquotino = be64_to_cpu(from->sb_gquotino);
595 to->sb_qflags = be16_to_cpu(from->sb_qflags);
596 to->sb_flags = from->sb_flags;
597 to->sb_shared_vn = from->sb_shared_vn;
598 to->sb_inoalignmt = be32_to_cpu(from->sb_inoalignmt);
599 to->sb_unit = be32_to_cpu(from->sb_unit);
600 to->sb_width = be32_to_cpu(from->sb_width);
601 to->sb_dirblklog = from->sb_dirblklog;
602 to->sb_logsectlog = from->sb_logsectlog;
603 to->sb_logsectsize = be16_to_cpu(from->sb_logsectsize);
604 to->sb_logsunit = be32_to_cpu(from->sb_logsunit);
605 to->sb_features2 = be32_to_cpu(from->sb_features2);
606 to->sb_bad_features2 = be32_to_cpu(from->sb_bad_features2);
607}
608
609
610
611
612
613
614void
615xfs_sb_to_disk(
616 xfs_dsb_t *to,
617 xfs_sb_t *from,
618 __int64_t fields)
619{
620 xfs_caddr_t to_ptr = (xfs_caddr_t)to;
621 xfs_caddr_t from_ptr = (xfs_caddr_t)from;
622 xfs_sb_field_t f;
623 int first;
624 int size;
625
626 ASSERT(fields);
627 if (!fields)
628 return;
629
630 while (fields) {
631 f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
632 first = xfs_sb_info[f].offset;
633 size = xfs_sb_info[f + 1].offset - first;
634
635 ASSERT(xfs_sb_info[f].type == 0 || xfs_sb_info[f].type == 1);
636
637 if (size == 1 || xfs_sb_info[f].type == 1) {
638 memcpy(to_ptr + first, from_ptr + first, size);
639 } else {
640 switch (size) {
641 case 2:
642 *(__be16 *)(to_ptr + first) =
643 cpu_to_be16(*(__u16 *)(from_ptr + first));
644 break;
645 case 4:
646 *(__be32 *)(to_ptr + first) =
647 cpu_to_be32(*(__u32 *)(from_ptr + first));
648 break;
649 case 8:
650 *(__be64 *)(to_ptr + first) =
651 cpu_to_be64(*(__u64 *)(from_ptr + first));
652 break;
653 default:
654 ASSERT(0);
655 }
656 }
657
658 fields &= ~(1LL << f);
659 }
660}
661
662
663
664
665
666
667int
668xfs_readsb(xfs_mount_t *mp, int flags)
669{
670 unsigned int sector_size;
671 xfs_buf_t *bp;
672 int error;
673 int loud = !(flags & XFS_MFSI_QUIET);
674
675 ASSERT(mp->m_sb_bp == NULL);
676 ASSERT(mp->m_ddev_targp != NULL);
677
678
679
680
681
682
683 sector_size = xfs_getsize_buftarg(mp->m_ddev_targp);
684
685reread:
686 bp = xfs_buf_read_uncached(mp->m_ddev_targp, XFS_SB_DADDR,
687 BTOBB(sector_size), 0);
688 if (!bp) {
689 if (loud)
690 xfs_warn(mp, "SB buffer read failed");
691 return EIO;
692 }
693
694
695
696
697
698 xfs_sb_from_disk(mp, XFS_BUF_TO_SBP(bp));
699 error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
700 if (error) {
701 if (loud)
702 xfs_warn(mp, "SB validate failed");
703 goto release_buf;
704 }
705
706
707
708
709 if (sector_size > mp->m_sb.sb_sectsize) {
710 if (loud)
711 xfs_warn(mp, "device supports %u byte sectors (not %u)",
712 sector_size, mp->m_sb.sb_sectsize);
713 error = ENOSYS;
714 goto release_buf;
715 }
716
717
718
719
720
721 if (sector_size < mp->m_sb.sb_sectsize) {
722 xfs_buf_relse(bp);
723 sector_size = mp->m_sb.sb_sectsize;
724 goto reread;
725 }
726
727
728 xfs_icsb_reinit_counters(mp);
729
730 mp->m_sb_bp = bp;
731 xfs_buf_unlock(bp);
732 return 0;
733
734release_buf:
735 xfs_buf_relse(bp);
736 return error;
737}
738
739
740
741
742
743
744
745
746
747STATIC void
748xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
749{
750 mp->m_agfrotor = mp->m_agirotor = 0;
751 spin_lock_init(&mp->m_agirotor_lock);
752 mp->m_maxagi = mp->m_sb.sb_agcount;
753 mp->m_blkbit_log = sbp->sb_blocklog + XFS_NBBYLOG;
754 mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT;
755 mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT;
756 mp->m_agno_log = xfs_highbit32(sbp->sb_agcount - 1) + 1;
757 mp->m_agino_log = sbp->sb_inopblog + sbp->sb_agblklog;
758 mp->m_blockmask = sbp->sb_blocksize - 1;
759 mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
760 mp->m_blockwmask = mp->m_blockwsize - 1;
761
762 mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1);
763 mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0);
764 mp->m_alloc_mnr[0] = mp->m_alloc_mxr[0] / 2;
765 mp->m_alloc_mnr[1] = mp->m_alloc_mxr[1] / 2;
766
767 mp->m_inobt_mxr[0] = xfs_inobt_maxrecs(mp, sbp->sb_blocksize, 1);
768 mp->m_inobt_mxr[1] = xfs_inobt_maxrecs(mp, sbp->sb_blocksize, 0);
769 mp->m_inobt_mnr[0] = mp->m_inobt_mxr[0] / 2;
770 mp->m_inobt_mnr[1] = mp->m_inobt_mxr[1] / 2;
771
772 mp->m_bmap_dmxr[0] = xfs_bmbt_maxrecs(mp, sbp->sb_blocksize, 1);
773 mp->m_bmap_dmxr[1] = xfs_bmbt_maxrecs(mp, sbp->sb_blocksize, 0);
774 mp->m_bmap_dmnr[0] = mp->m_bmap_dmxr[0] / 2;
775 mp->m_bmap_dmnr[1] = mp->m_bmap_dmxr[1] / 2;
776
777 mp->m_bsize = XFS_FSB_TO_BB(mp, 1);
778 mp->m_ialloc_inos = (int)MAX((__uint16_t)XFS_INODES_PER_CHUNK,
779 sbp->sb_inopblock);
780 mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog;
781}
782
783
784
785
786
787
788
789
790
791STATIC int
792xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount)
793{
794 xfs_agnumber_t index;
795 xfs_perag_t *pag;
796 xfs_sb_t *sbp = &mp->m_sb;
797 uint64_t ifree = 0;
798 uint64_t ialloc = 0;
799 uint64_t bfree = 0;
800 uint64_t bfreelst = 0;
801 uint64_t btree = 0;
802 int error;
803
804 for (index = 0; index < agcount; index++) {
805
806
807
808
809
810 error = xfs_alloc_pagf_init(mp, NULL, index, 0);
811 if (error)
812 return error;
813
814 error = xfs_ialloc_pagi_init(mp, NULL, index);
815 if (error)
816 return error;
817 pag = xfs_perag_get(mp, index);
818 ifree += pag->pagi_freecount;
819 ialloc += pag->pagi_count;
820 bfree += pag->pagf_freeblks;
821 bfreelst += pag->pagf_flcount;
822 btree += pag->pagf_btreeblks;
823 xfs_perag_put(pag);
824 }
825
826
827
828 spin_lock(&mp->m_sb_lock);
829 sbp->sb_ifree = ifree;
830 sbp->sb_icount = ialloc;
831 sbp->sb_fdblocks = bfree + bfreelst + btree;
832 spin_unlock(&mp->m_sb_lock);
833
834
835 xfs_icsb_reinit_counters(mp);
836
837 return 0;
838}
839
840
841
842
843STATIC int
844xfs_update_alignment(xfs_mount_t *mp)
845{
846 xfs_sb_t *sbp = &(mp->m_sb);
847
848 if (mp->m_dalign) {
849
850
851
852
853 if ((BBTOB(mp->m_dalign) & mp->m_blockmask) ||
854 (BBTOB(mp->m_swidth) & mp->m_blockmask)) {
855 if (mp->m_flags & XFS_MOUNT_RETERR) {
856 xfs_warn(mp, "alignment check failed: "
857 "(sunit/swidth vs. blocksize)");
858 return XFS_ERROR(EINVAL);
859 }
860 mp->m_dalign = mp->m_swidth = 0;
861 } else {
862
863
864
865 mp->m_dalign = XFS_BB_TO_FSBT(mp, mp->m_dalign);
866 if (mp->m_dalign && (sbp->sb_agblocks % mp->m_dalign)) {
867 if (mp->m_flags & XFS_MOUNT_RETERR) {
868 xfs_warn(mp, "alignment check failed: "
869 "(sunit/swidth vs. ag size)");
870 return XFS_ERROR(EINVAL);
871 }
872 xfs_warn(mp,
873 "stripe alignment turned off: sunit(%d)/swidth(%d) "
874 "incompatible with agsize(%d)",
875 mp->m_dalign, mp->m_swidth,
876 sbp->sb_agblocks);
877
878 mp->m_dalign = 0;
879 mp->m_swidth = 0;
880 } else if (mp->m_dalign) {
881 mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth);
882 } else {
883 if (mp->m_flags & XFS_MOUNT_RETERR) {
884 xfs_warn(mp, "alignment check failed: "
885 "sunit(%d) less than bsize(%d)",
886 mp->m_dalign,
887 mp->m_blockmask +1);
888 return XFS_ERROR(EINVAL);
889 }
890 mp->m_swidth = 0;
891 }
892 }
893
894
895
896
897
898 if (xfs_sb_version_hasdalign(sbp)) {
899 if (sbp->sb_unit != mp->m_dalign) {
900 sbp->sb_unit = mp->m_dalign;
901 mp->m_update_flags |= XFS_SB_UNIT;
902 }
903 if (sbp->sb_width != mp->m_swidth) {
904 sbp->sb_width = mp->m_swidth;
905 mp->m_update_flags |= XFS_SB_WIDTH;
906 }
907 }
908 } else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN &&
909 xfs_sb_version_hasdalign(&mp->m_sb)) {
910 mp->m_dalign = sbp->sb_unit;
911 mp->m_swidth = sbp->sb_width;
912 }
913
914 return 0;
915}
916
917
918
919
920STATIC void
921xfs_set_maxicount(xfs_mount_t *mp)
922{
923 xfs_sb_t *sbp = &(mp->m_sb);
924 __uint64_t icount;
925
926 if (sbp->sb_imax_pct) {
927
928
929
930
931 icount = sbp->sb_dblocks * sbp->sb_imax_pct;
932 do_div(icount, 100);
933 do_div(icount, mp->m_ialloc_blks);
934 mp->m_maxicount = (icount * mp->m_ialloc_blks) <<
935 sbp->sb_inopblog;
936 } else {
937 mp->m_maxicount = 0;
938 }
939}
940
941
942
943
944
945
946
947STATIC void
948xfs_set_rw_sizes(xfs_mount_t *mp)
949{
950 xfs_sb_t *sbp = &(mp->m_sb);
951 int readio_log, writeio_log;
952
953 if (!(mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)) {
954 if (mp->m_flags & XFS_MOUNT_WSYNC) {
955 readio_log = XFS_WSYNC_READIO_LOG;
956 writeio_log = XFS_WSYNC_WRITEIO_LOG;
957 } else {
958 readio_log = XFS_READIO_LOG_LARGE;
959 writeio_log = XFS_WRITEIO_LOG_LARGE;
960 }
961 } else {
962 readio_log = mp->m_readio_log;
963 writeio_log = mp->m_writeio_log;
964 }
965
966 if (sbp->sb_blocklog > readio_log) {
967 mp->m_readio_log = sbp->sb_blocklog;
968 } else {
969 mp->m_readio_log = readio_log;
970 }
971 mp->m_readio_blocks = 1 << (mp->m_readio_log - sbp->sb_blocklog);
972 if (sbp->sb_blocklog > writeio_log) {
973 mp->m_writeio_log = sbp->sb_blocklog;
974 } else {
975 mp->m_writeio_log = writeio_log;
976 }
977 mp->m_writeio_blocks = 1 << (mp->m_writeio_log - sbp->sb_blocklog);
978}
979
980
981
982
983void
984xfs_set_low_space_thresholds(
985 struct xfs_mount *mp)
986{
987 int i;
988
989 for (i = 0; i < XFS_LOWSP_MAX; i++) {
990 __uint64_t space = mp->m_sb.sb_dblocks;
991
992 do_div(space, 100);
993 mp->m_low_space[i] = space * (i + 1);
994 }
995}
996
997
998
999
1000
1001STATIC void
1002xfs_set_inoalignment(xfs_mount_t *mp)
1003{
1004 if (xfs_sb_version_hasalign(&mp->m_sb) &&
1005 mp->m_sb.sb_inoalignmt >=
1006 XFS_B_TO_FSBT(mp, mp->m_inode_cluster_size))
1007 mp->m_inoalign_mask = mp->m_sb.sb_inoalignmt - 1;
1008 else
1009 mp->m_inoalign_mask = 0;
1010
1011
1012
1013
1014 if (mp->m_dalign && mp->m_inoalign_mask &&
1015 !(mp->m_dalign & mp->m_inoalign_mask))
1016 mp->m_sinoalign = mp->m_dalign;
1017 else
1018 mp->m_sinoalign = 0;
1019}
1020
1021
1022
1023
1024STATIC int
1025xfs_check_sizes(xfs_mount_t *mp)
1026{
1027 xfs_buf_t *bp;
1028 xfs_daddr_t d;
1029
1030 d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
1031 if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) {
1032 xfs_warn(mp, "filesystem size mismatch detected");
1033 return XFS_ERROR(EFBIG);
1034 }
1035 bp = xfs_buf_read_uncached(mp->m_ddev_targp,
1036 d - XFS_FSS_TO_BB(mp, 1),
1037 XFS_FSS_TO_BB(mp, 1), 0);
1038 if (!bp) {
1039 xfs_warn(mp, "last sector read failed");
1040 return EIO;
1041 }
1042 xfs_buf_relse(bp);
1043
1044 if (mp->m_logdev_targp != mp->m_ddev_targp) {
1045 d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
1046 if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) {
1047 xfs_warn(mp, "log size mismatch detected");
1048 return XFS_ERROR(EFBIG);
1049 }
1050 bp = xfs_buf_read_uncached(mp->m_logdev_targp,
1051 d - XFS_FSB_TO_BB(mp, 1),
1052 XFS_FSB_TO_BB(mp, 1), 0);
1053 if (!bp) {
1054 xfs_warn(mp, "log device read failed");
1055 return EIO;
1056 }
1057 xfs_buf_relse(bp);
1058 }
1059 return 0;
1060}
1061
1062
1063
1064
1065int
1066xfs_mount_reset_sbqflags(
1067 struct xfs_mount *mp)
1068{
1069 int error;
1070 struct xfs_trans *tp;
1071
1072 mp->m_qflags = 0;
1073
1074
1075
1076
1077
1078 if (mp->m_sb.sb_qflags == 0)
1079 return 0;
1080 spin_lock(&mp->m_sb_lock);
1081 mp->m_sb.sb_qflags = 0;
1082 spin_unlock(&mp->m_sb_lock);
1083
1084
1085
1086
1087
1088 if (mp->m_flags & XFS_MOUNT_RDONLY)
1089 return 0;
1090
1091 tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE);
1092 error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
1093 XFS_DEFAULT_LOG_COUNT);
1094 if (error) {
1095 xfs_trans_cancel(tp, 0);
1096 xfs_alert(mp, "%s: Superblock update failed!", __func__);
1097 return error;
1098 }
1099
1100 xfs_mod_sb(tp, XFS_SB_QFLAGS);
1101 return xfs_trans_commit(tp, 0);
1102}
1103
1104__uint64_t
1105xfs_default_resblks(xfs_mount_t *mp)
1106{
1107 __uint64_t resblks;
1108
1109
1110
1111
1112
1113
1114
1115
1116 resblks = mp->m_sb.sb_dblocks;
1117 do_div(resblks, 20);
1118 resblks = min_t(__uint64_t, resblks, 8192);
1119 return resblks;
1120}
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132int
1133xfs_mountfs(
1134 xfs_mount_t *mp)
1135{
1136 xfs_sb_t *sbp = &(mp->m_sb);
1137 xfs_inode_t *rip;
1138 __uint64_t resblks;
1139 uint quotamount = 0;
1140 uint quotaflags = 0;
1141 int error = 0;
1142
1143 xfs_mount_common(mp, sbp);
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161 if (xfs_sb_has_mismatched_features2(sbp)) {
1162 xfs_warn(mp, "correcting sb_features alignment problem");
1163 sbp->sb_features2 |= sbp->sb_bad_features2;
1164 sbp->sb_bad_features2 = sbp->sb_features2;
1165 mp->m_update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2;
1166
1167
1168
1169
1170
1171 if (xfs_sb_version_hasattr2(&mp->m_sb) &&
1172 !(mp->m_flags & XFS_MOUNT_NOATTR2))
1173 mp->m_flags |= XFS_MOUNT_ATTR2;
1174 }
1175
1176 if (xfs_sb_version_hasattr2(&mp->m_sb) &&
1177 (mp->m_flags & XFS_MOUNT_NOATTR2)) {
1178 xfs_sb_version_removeattr2(&mp->m_sb);
1179 mp->m_update_flags |= XFS_SB_FEATURES2;
1180
1181
1182 if (!sbp->sb_features2)
1183 mp->m_update_flags |= XFS_SB_VERSIONNUM;
1184 }
1185
1186
1187
1188
1189
1190
1191
1192 error = xfs_update_alignment(mp);
1193 if (error)
1194 goto out;
1195
1196 xfs_alloc_compute_maxlevels(mp);
1197 xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK);
1198 xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK);
1199 xfs_ialloc_compute_maxlevels(mp);
1200
1201 xfs_set_maxicount(mp);
1202
1203 error = xfs_uuid_mount(mp);
1204 if (error)
1205 goto out;
1206
1207
1208
1209
1210 xfs_set_rw_sizes(mp);
1211
1212
1213 xfs_set_low_space_thresholds(mp);
1214
1215
1216
1217
1218
1219
1220 mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
1221
1222
1223
1224
1225 xfs_set_inoalignment(mp);
1226
1227
1228
1229
1230 error = xfs_check_sizes(mp);
1231 if (error)
1232 goto out_remove_uuid;
1233
1234
1235
1236
1237 error = xfs_rtmount_init(mp);
1238 if (error) {
1239 xfs_warn(mp, "RT mount failed");
1240 goto out_remove_uuid;
1241 }
1242
1243
1244
1245
1246
1247 uuid_getnodeuniq(&sbp->sb_uuid, mp->m_fixedfsid);
1248
1249 mp->m_dmevmask = 0;
1250
1251 xfs_dir_mount(mp);
1252
1253
1254
1255
1256 mp->m_attr_magicpct = (mp->m_sb.sb_blocksize * 37) / 100;
1257
1258
1259
1260
1261 xfs_trans_init(mp);
1262
1263
1264
1265
1266 spin_lock_init(&mp->m_perag_lock);
1267 INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC);
1268 error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi);
1269 if (error) {
1270 xfs_warn(mp, "Failed per-ag init: %d", error);
1271 goto out_remove_uuid;
1272 }
1273
1274 if (!sbp->sb_logblocks) {
1275 xfs_warn(mp, "no log defined");
1276 XFS_ERROR_REPORT("xfs_mountfs", XFS_ERRLEVEL_LOW, mp);
1277 error = XFS_ERROR(EFSCORRUPTED);
1278 goto out_free_perag;
1279 }
1280
1281
1282
1283
1284 error = xfs_log_mount(mp, mp->m_logdev_targp,
1285 XFS_FSB_TO_DADDR(mp, sbp->sb_logstart),
1286 XFS_FSB_TO_BB(mp, sbp->sb_logblocks));
1287 if (error) {
1288 xfs_warn(mp, "log mount failed");
1289 goto out_fail_wait;
1290 }
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311 if (xfs_sb_version_haslazysbcount(&mp->m_sb) &&
1312 !XFS_LAST_UNMOUNT_WAS_CLEAN(mp) &&
1313 !mp->m_sb.sb_inprogress) {
1314 error = xfs_initialize_perag_data(mp, sbp->sb_agcount);
1315 if (error)
1316 goto out_fail_wait;
1317 }
1318
1319
1320
1321
1322
1323 error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip);
1324 if (error) {
1325 xfs_warn(mp, "failed to read root inode");
1326 goto out_log_dealloc;
1327 }
1328
1329 ASSERT(rip != NULL);
1330
1331 if (unlikely(!S_ISDIR(rip->i_d.di_mode))) {
1332 xfs_warn(mp, "corrupted root inode %llu: not a directory",
1333 (unsigned long long)rip->i_ino);
1334 xfs_iunlock(rip, XFS_ILOCK_EXCL);
1335 XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW,
1336 mp);
1337 error = XFS_ERROR(EFSCORRUPTED);
1338 goto out_rele_rip;
1339 }
1340 mp->m_rootip = rip;
1341
1342 xfs_iunlock(rip, XFS_ILOCK_EXCL);
1343
1344
1345
1346
1347 error = xfs_rtmount_inodes(mp);
1348 if (error) {
1349
1350
1351
1352 xfs_warn(mp, "failed to read RT inodes");
1353 goto out_rele_rip;
1354 }
1355
1356
1357
1358
1359
1360
1361 if (mp->m_update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) {
1362 error = xfs_mount_log_sb(mp, mp->m_update_flags);
1363 if (error) {
1364 xfs_warn(mp, "failed to write sb changes");
1365 goto out_rtunmount;
1366 }
1367 }
1368
1369
1370
1371
1372 if (XFS_IS_QUOTA_RUNNING(mp)) {
1373 error = xfs_qm_newmount(mp, "amount, "aflags);
1374 if (error)
1375 goto out_rtunmount;
1376 } else {
1377 ASSERT(!XFS_IS_QUOTA_ON(mp));
1378
1379
1380
1381
1382
1383
1384 if (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT) {
1385 xfs_notice(mp, "resetting quota flags");
1386 error = xfs_mount_reset_sbqflags(mp);
1387 if (error)
1388 return error;
1389 }
1390 }
1391
1392
1393
1394
1395
1396
1397 error = xfs_log_mount_finish(mp);
1398 if (error) {
1399 xfs_warn(mp, "log mount finish failed");
1400 goto out_rtunmount;
1401 }
1402
1403
1404
1405
1406 if (quotamount) {
1407 ASSERT(mp->m_qflags == 0);
1408 mp->m_qflags = quotaflags;
1409
1410 xfs_qm_mount_quotas(mp);
1411 }
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424 if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
1425 resblks = xfs_default_resblks(mp);
1426 error = xfs_reserve_blocks(mp, &resblks, NULL);
1427 if (error)
1428 xfs_warn(mp,
1429 "Unable to allocate reserve blocks. Continuing without reserve pool.");
1430 }
1431
1432 return 0;
1433
1434 out_rtunmount:
1435 xfs_rtunmount_inodes(mp);
1436 out_rele_rip:
1437 IRELE(rip);
1438 out_log_dealloc:
1439 xfs_log_unmount(mp);
1440 out_fail_wait:
1441 if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp)
1442 xfs_wait_buftarg(mp->m_logdev_targp);
1443 xfs_wait_buftarg(mp->m_ddev_targp);
1444 out_free_perag:
1445 xfs_free_perag(mp);
1446 out_remove_uuid:
1447 xfs_uuid_unmount(mp);
1448 out:
1449 return error;
1450}
1451
1452
1453
1454
1455
1456void
1457xfs_unmountfs(
1458 struct xfs_mount *mp)
1459{
1460 __uint64_t resblks;
1461 int error;
1462
1463 xfs_qm_unmount_quotas(mp);
1464 xfs_rtunmount_inodes(mp);
1465 IRELE(mp->m_rootip);
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477 xfs_log_force(mp, XFS_LOG_SYNC);
1478
1479
1480
1481
1482 xfs_ail_push_all_sync(mp->m_ail);
1483
1484
1485
1486
1487
1488
1489 xfs_reclaim_inodes(mp, SYNC_WAIT);
1490
1491 xfs_qm_unmount(mp);
1492
1493
1494
1495
1496
1497
1498 xfs_log_force(mp, XFS_LOG_SYNC);
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514 resblks = 0;
1515 error = xfs_reserve_blocks(mp, &resblks, NULL);
1516 if (error)
1517 xfs_warn(mp, "Unable to free reserved block pool. "
1518 "Freespace may not be correct on next mount.");
1519
1520 error = xfs_log_sbcount(mp);
1521 if (error)
1522 xfs_warn(mp, "Unable to update superblock counters. "
1523 "Freespace may not be correct on next mount.");
1524
1525
1526
1527
1528
1529 xfs_ail_push_all_sync(mp->m_ail);
1530 xfs_wait_buftarg(mp->m_ddev_targp);
1531
1532
1533
1534
1535
1536
1537
1538 xfs_buf_lock(mp->m_sb_bp);
1539 xfs_buf_unlock(mp->m_sb_bp);
1540
1541 xfs_log_unmount_write(mp);
1542 xfs_log_unmount(mp);
1543 xfs_uuid_unmount(mp);
1544
1545#if defined(DEBUG)
1546 xfs_errortag_clearall(mp, 0);
1547#endif
1548 xfs_free_perag(mp);
1549}
1550
1551int
1552xfs_fs_writable(xfs_mount_t *mp)
1553{
1554 return !(mp->m_super->s_writers.frozen || XFS_FORCED_SHUTDOWN(mp) ||
1555 (mp->m_flags & XFS_MOUNT_RDONLY));
1556}
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567int
1568xfs_log_sbcount(xfs_mount_t *mp)
1569{
1570 xfs_trans_t *tp;
1571 int error;
1572
1573 if (!xfs_fs_writable(mp))
1574 return 0;
1575
1576 xfs_icsb_sync_counters(mp, 0);
1577
1578
1579
1580
1581
1582 if (!xfs_sb_version_haslazysbcount(&mp->m_sb))
1583 return 0;
1584
1585 tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_COUNT, KM_SLEEP);
1586 error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
1587 XFS_DEFAULT_LOG_COUNT);
1588 if (error) {
1589 xfs_trans_cancel(tp, 0);
1590 return error;
1591 }
1592
1593 xfs_mod_sb(tp, XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS);
1594 xfs_trans_set_sync(tp);
1595 error = xfs_trans_commit(tp, 0);
1596 return error;
1597}
1598
1599
1600
1601
1602
1603
1604
1605
1606void
1607xfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
1608{
1609 xfs_buf_t *bp;
1610 int first;
1611 int last;
1612 xfs_mount_t *mp;
1613 xfs_sb_field_t f;
1614
1615 ASSERT(fields);
1616 if (!fields)
1617 return;
1618 mp = tp->t_mountp;
1619 bp = xfs_trans_getsb(tp, mp, 0);
1620 first = sizeof(xfs_sb_t);
1621 last = 0;
1622
1623
1624
1625 xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, fields);
1626
1627
1628 f = (xfs_sb_field_t)xfs_highbit64((__uint64_t)fields);
1629 ASSERT((1LL << f) & XFS_SB_MOD_BITS);
1630 last = xfs_sb_info[f + 1].offset - 1;
1631
1632 f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
1633 ASSERT((1LL << f) & XFS_SB_MOD_BITS);
1634 first = xfs_sb_info[f].offset;
1635
1636 xfs_trans_log_buf(tp, bp, first, last);
1637}
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649STATIC int
1650xfs_mod_incore_sb_unlocked(
1651 xfs_mount_t *mp,
1652 xfs_sb_field_t field,
1653 int64_t delta,
1654 int rsvd)
1655{
1656 int scounter;
1657 long long lcounter;
1658 long long res_used, rem;
1659
1660
1661
1662
1663
1664
1665
1666 switch (field) {
1667 case XFS_SBS_ICOUNT:
1668 lcounter = (long long)mp->m_sb.sb_icount;
1669 lcounter += delta;
1670 if (lcounter < 0) {
1671 ASSERT(0);
1672 return XFS_ERROR(EINVAL);
1673 }
1674 mp->m_sb.sb_icount = lcounter;
1675 return 0;
1676 case XFS_SBS_IFREE:
1677 lcounter = (long long)mp->m_sb.sb_ifree;
1678 lcounter += delta;
1679 if (lcounter < 0) {
1680 ASSERT(0);
1681 return XFS_ERROR(EINVAL);
1682 }
1683 mp->m_sb.sb_ifree = lcounter;
1684 return 0;
1685 case XFS_SBS_FDBLOCKS:
1686 lcounter = (long long)
1687 mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
1688 res_used = (long long)(mp->m_resblks - mp->m_resblks_avail);
1689
1690 if (delta > 0) {
1691 if (res_used > delta) {
1692 mp->m_resblks_avail += delta;
1693 } else {
1694 rem = delta - res_used;
1695 mp->m_resblks_avail = mp->m_resblks;
1696 lcounter += rem;
1697 }
1698 } else {
1699 lcounter += delta;
1700 if (lcounter >= 0) {
1701 mp->m_sb.sb_fdblocks = lcounter +
1702 XFS_ALLOC_SET_ASIDE(mp);
1703 return 0;
1704 }
1705
1706
1707
1708
1709
1710 if (!rsvd)
1711 return XFS_ERROR(ENOSPC);
1712
1713 lcounter = (long long)mp->m_resblks_avail + delta;
1714 if (lcounter >= 0) {
1715 mp->m_resblks_avail = lcounter;
1716 return 0;
1717 }
1718 printk_once(KERN_WARNING
1719 "Filesystem \"%s\": reserve blocks depleted! "
1720 "Consider increasing reserve pool size.",
1721 mp->m_fsname);
1722 return XFS_ERROR(ENOSPC);
1723 }
1724
1725 mp->m_sb.sb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
1726 return 0;
1727 case XFS_SBS_FREXTENTS:
1728 lcounter = (long long)mp->m_sb.sb_frextents;
1729 lcounter += delta;
1730 if (lcounter < 0) {
1731 return XFS_ERROR(ENOSPC);
1732 }
1733 mp->m_sb.sb_frextents = lcounter;
1734 return 0;
1735 case XFS_SBS_DBLOCKS:
1736 lcounter = (long long)mp->m_sb.sb_dblocks;
1737 lcounter += delta;
1738 if (lcounter < 0) {
1739 ASSERT(0);
1740 return XFS_ERROR(EINVAL);
1741 }
1742 mp->m_sb.sb_dblocks = lcounter;
1743 return 0;
1744 case XFS_SBS_AGCOUNT:
1745 scounter = mp->m_sb.sb_agcount;
1746 scounter += delta;
1747 if (scounter < 0) {
1748 ASSERT(0);
1749 return XFS_ERROR(EINVAL);
1750 }
1751 mp->m_sb.sb_agcount = scounter;
1752 return 0;
1753 case XFS_SBS_IMAX_PCT:
1754 scounter = mp->m_sb.sb_imax_pct;
1755 scounter += delta;
1756 if (scounter < 0) {
1757 ASSERT(0);
1758 return XFS_ERROR(EINVAL);
1759 }
1760 mp->m_sb.sb_imax_pct = scounter;
1761 return 0;
1762 case XFS_SBS_REXTSIZE:
1763 scounter = mp->m_sb.sb_rextsize;
1764 scounter += delta;
1765 if (scounter < 0) {
1766 ASSERT(0);
1767 return XFS_ERROR(EINVAL);
1768 }
1769 mp->m_sb.sb_rextsize = scounter;
1770 return 0;
1771 case XFS_SBS_RBMBLOCKS:
1772 scounter = mp->m_sb.sb_rbmblocks;
1773 scounter += delta;
1774 if (scounter < 0) {
1775 ASSERT(0);
1776 return XFS_ERROR(EINVAL);
1777 }
1778 mp->m_sb.sb_rbmblocks = scounter;
1779 return 0;
1780 case XFS_SBS_RBLOCKS:
1781 lcounter = (long long)mp->m_sb.sb_rblocks;
1782 lcounter += delta;
1783 if (lcounter < 0) {
1784 ASSERT(0);
1785 return XFS_ERROR(EINVAL);
1786 }
1787 mp->m_sb.sb_rblocks = lcounter;
1788 return 0;
1789 case XFS_SBS_REXTENTS:
1790 lcounter = (long long)mp->m_sb.sb_rextents;
1791 lcounter += delta;
1792 if (lcounter < 0) {
1793 ASSERT(0);
1794 return XFS_ERROR(EINVAL);
1795 }
1796 mp->m_sb.sb_rextents = lcounter;
1797 return 0;
1798 case XFS_SBS_REXTSLOG:
1799 scounter = mp->m_sb.sb_rextslog;
1800 scounter += delta;
1801 if (scounter < 0) {
1802 ASSERT(0);
1803 return XFS_ERROR(EINVAL);
1804 }
1805 mp->m_sb.sb_rextslog = scounter;
1806 return 0;
1807 default:
1808 ASSERT(0);
1809 return XFS_ERROR(EINVAL);
1810 }
1811}
1812
1813
1814
1815
1816
1817
1818
1819int
1820xfs_mod_incore_sb(
1821 struct xfs_mount *mp,
1822 xfs_sb_field_t field,
1823 int64_t delta,
1824 int rsvd)
1825{
1826 int status;
1827
1828#ifdef HAVE_PERCPU_SB
1829 ASSERT(field < XFS_SBS_ICOUNT || field > XFS_SBS_FDBLOCKS);
1830#endif
1831 spin_lock(&mp->m_sb_lock);
1832 status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
1833 spin_unlock(&mp->m_sb_lock);
1834
1835 return status;
1836}
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850int
1851xfs_mod_incore_sb_batch(
1852 struct xfs_mount *mp,
1853 xfs_mod_sb_t *msb,
1854 uint nmsb,
1855 int rsvd)
1856{
1857 xfs_mod_sb_t *msbp;
1858 int error = 0;
1859
1860
1861
1862
1863
1864
1865
1866 spin_lock(&mp->m_sb_lock);
1867 for (msbp = msb; msbp < (msb + nmsb); msbp++) {
1868 ASSERT(msbp->msb_field < XFS_SBS_ICOUNT ||
1869 msbp->msb_field > XFS_SBS_FDBLOCKS);
1870
1871 error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field,
1872 msbp->msb_delta, rsvd);
1873 if (error)
1874 goto unwind;
1875 }
1876 spin_unlock(&mp->m_sb_lock);
1877 return 0;
1878
1879unwind:
1880 while (--msbp >= msb) {
1881 error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field,
1882 -msbp->msb_delta, rsvd);
1883 ASSERT(error == 0);
1884 }
1885 spin_unlock(&mp->m_sb_lock);
1886 return error;
1887}
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898struct xfs_buf *
1899xfs_getsb(
1900 struct xfs_mount *mp,
1901 int flags)
1902{
1903 struct xfs_buf *bp = mp->m_sb_bp;
1904
1905 if (!xfs_buf_trylock(bp)) {
1906 if (flags & XBF_TRYLOCK)
1907 return NULL;
1908 xfs_buf_lock(bp);
1909 }
1910
1911 xfs_buf_hold(bp);
1912 ASSERT(XFS_BUF_ISDONE(bp));
1913 return bp;
1914}
1915
1916
1917
1918
1919void
1920xfs_freesb(
1921 struct xfs_mount *mp)
1922{
1923 struct xfs_buf *bp = mp->m_sb_bp;
1924
1925 xfs_buf_lock(bp);
1926 mp->m_sb_bp = NULL;
1927 xfs_buf_relse(bp);
1928}
1929
1930
1931
1932
1933
1934
1935int
1936xfs_mount_log_sb(
1937 xfs_mount_t *mp,
1938 __int64_t fields)
1939{
1940 xfs_trans_t *tp;
1941 int error;
1942
1943 ASSERT(fields & (XFS_SB_UNIT | XFS_SB_WIDTH | XFS_SB_UUID |
1944 XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2 |
1945 XFS_SB_VERSIONNUM));
1946
1947 tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT);
1948 error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
1949 XFS_DEFAULT_LOG_COUNT);
1950 if (error) {
1951 xfs_trans_cancel(tp, 0);
1952 return error;
1953 }
1954 xfs_mod_sb(tp, fields);
1955 error = xfs_trans_commit(tp, 0);
1956 return error;
1957}
1958
1959
1960
1961
1962
1963int
1964xfs_dev_is_read_only(
1965 struct xfs_mount *mp,
1966 char *message)
1967{
1968 if (xfs_readonly_buftarg(mp->m_ddev_targp) ||
1969 xfs_readonly_buftarg(mp->m_logdev_targp) ||
1970 (mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp))) {
1971 xfs_notice(mp, "%s required on read-only device.", message);
1972 xfs_notice(mp, "write access unavailable, cannot proceed.");
1973 return EROFS;
1974 }
1975 return 0;
1976}
1977
1978#ifdef HAVE_PERCPU_SB
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031#ifdef CONFIG_HOTPLUG_CPU
2032
2033
2034
2035
2036
2037
2038
2039
2040STATIC int
2041xfs_icsb_cpu_notify(
2042 struct notifier_block *nfb,
2043 unsigned long action,
2044 void *hcpu)
2045{
2046 xfs_icsb_cnts_t *cntp;
2047 xfs_mount_t *mp;
2048
2049 mp = (xfs_mount_t *)container_of(nfb, xfs_mount_t, m_icsb_notifier);
2050 cntp = (xfs_icsb_cnts_t *)
2051 per_cpu_ptr(mp->m_sb_cnts, (unsigned long)hcpu);
2052 switch (action) {
2053 case CPU_UP_PREPARE:
2054 case CPU_UP_PREPARE_FROZEN:
2055
2056
2057 memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
2058 break;
2059 case CPU_ONLINE:
2060 case CPU_ONLINE_FROZEN:
2061 xfs_icsb_lock(mp);
2062 xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
2063 xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
2064 xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
2065 xfs_icsb_unlock(mp);
2066 break;
2067 case CPU_DEAD:
2068 case CPU_DEAD_FROZEN:
2069
2070
2071
2072 xfs_icsb_lock(mp);
2073 spin_lock(&mp->m_sb_lock);
2074 xfs_icsb_disable_counter(mp, XFS_SBS_ICOUNT);
2075 xfs_icsb_disable_counter(mp, XFS_SBS_IFREE);
2076 xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS);
2077
2078 mp->m_sb.sb_icount += cntp->icsb_icount;
2079 mp->m_sb.sb_ifree += cntp->icsb_ifree;
2080 mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks;
2081
2082 memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
2083
2084 xfs_icsb_balance_counter_locked(mp, XFS_SBS_ICOUNT, 0);
2085 xfs_icsb_balance_counter_locked(mp, XFS_SBS_IFREE, 0);
2086 xfs_icsb_balance_counter_locked(mp, XFS_SBS_FDBLOCKS, 0);
2087 spin_unlock(&mp->m_sb_lock);
2088 xfs_icsb_unlock(mp);
2089 break;
2090 }
2091
2092 return NOTIFY_OK;
2093}
2094#endif
2095
2096int
2097xfs_icsb_init_counters(
2098 xfs_mount_t *mp)
2099{
2100 xfs_icsb_cnts_t *cntp;
2101 int i;
2102
2103 mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t);
2104 if (mp->m_sb_cnts == NULL)
2105 return -ENOMEM;
2106
2107#ifdef CONFIG_HOTPLUG_CPU
2108 mp->m_icsb_notifier.notifier_call = xfs_icsb_cpu_notify;
2109 mp->m_icsb_notifier.priority = 0;
2110 register_hotcpu_notifier(&mp->m_icsb_notifier);
2111#endif
2112
2113 for_each_online_cpu(i) {
2114 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
2115 memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
2116 }
2117
2118 mutex_init(&mp->m_icsb_mutex);
2119
2120
2121
2122
2123
2124 mp->m_icsb_counters = -1;
2125 return 0;
2126}
2127
2128void
2129xfs_icsb_reinit_counters(
2130 xfs_mount_t *mp)
2131{
2132 xfs_icsb_lock(mp);
2133
2134
2135
2136
2137 mp->m_icsb_counters = -1;
2138 xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
2139 xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
2140 xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
2141 xfs_icsb_unlock(mp);
2142}
2143
2144void
2145xfs_icsb_destroy_counters(
2146 xfs_mount_t *mp)
2147{
2148 if (mp->m_sb_cnts) {
2149 unregister_hotcpu_notifier(&mp->m_icsb_notifier);
2150 free_percpu(mp->m_sb_cnts);
2151 }
2152 mutex_destroy(&mp->m_icsb_mutex);
2153}
2154
2155STATIC void
2156xfs_icsb_lock_cntr(
2157 xfs_icsb_cnts_t *icsbp)
2158{
2159 while (test_and_set_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags)) {
2160 ndelay(1000);
2161 }
2162}
2163
2164STATIC void
2165xfs_icsb_unlock_cntr(
2166 xfs_icsb_cnts_t *icsbp)
2167{
2168 clear_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags);
2169}
2170
2171
2172STATIC void
2173xfs_icsb_lock_all_counters(
2174 xfs_mount_t *mp)
2175{
2176 xfs_icsb_cnts_t *cntp;
2177 int i;
2178
2179 for_each_online_cpu(i) {
2180 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
2181 xfs_icsb_lock_cntr(cntp);
2182 }
2183}
2184
2185STATIC void
2186xfs_icsb_unlock_all_counters(
2187 xfs_mount_t *mp)
2188{
2189 xfs_icsb_cnts_t *cntp;
2190 int i;
2191
2192 for_each_online_cpu(i) {
2193 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
2194 xfs_icsb_unlock_cntr(cntp);
2195 }
2196}
2197
2198STATIC void
2199xfs_icsb_count(
2200 xfs_mount_t *mp,
2201 xfs_icsb_cnts_t *cnt,
2202 int flags)
2203{
2204 xfs_icsb_cnts_t *cntp;
2205 int i;
2206
2207 memset(cnt, 0, sizeof(xfs_icsb_cnts_t));
2208
2209 if (!(flags & XFS_ICSB_LAZY_COUNT))
2210 xfs_icsb_lock_all_counters(mp);
2211
2212 for_each_online_cpu(i) {
2213 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
2214 cnt->icsb_icount += cntp->icsb_icount;
2215 cnt->icsb_ifree += cntp->icsb_ifree;
2216 cnt->icsb_fdblocks += cntp->icsb_fdblocks;
2217 }
2218
2219 if (!(flags & XFS_ICSB_LAZY_COUNT))
2220 xfs_icsb_unlock_all_counters(mp);
2221}
2222
2223STATIC int
2224xfs_icsb_counter_disabled(
2225 xfs_mount_t *mp,
2226 xfs_sb_field_t field)
2227{
2228 ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
2229 return test_bit(field, &mp->m_icsb_counters);
2230}
2231
2232STATIC void
2233xfs_icsb_disable_counter(
2234 xfs_mount_t *mp,
2235 xfs_sb_field_t field)
2236{
2237 xfs_icsb_cnts_t cnt;
2238
2239 ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249 if (xfs_icsb_counter_disabled(mp, field))
2250 return;
2251
2252 xfs_icsb_lock_all_counters(mp);
2253 if (!test_and_set_bit(field, &mp->m_icsb_counters)) {
2254
2255
2256 xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT);
2257 switch(field) {
2258 case XFS_SBS_ICOUNT:
2259 mp->m_sb.sb_icount = cnt.icsb_icount;
2260 break;
2261 case XFS_SBS_IFREE:
2262 mp->m_sb.sb_ifree = cnt.icsb_ifree;
2263 break;
2264 case XFS_SBS_FDBLOCKS:
2265 mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
2266 break;
2267 default:
2268 BUG();
2269 }
2270 }
2271
2272 xfs_icsb_unlock_all_counters(mp);
2273}
2274
2275STATIC void
2276xfs_icsb_enable_counter(
2277 xfs_mount_t *mp,
2278 xfs_sb_field_t field,
2279 uint64_t count,
2280 uint64_t resid)
2281{
2282 xfs_icsb_cnts_t *cntp;
2283 int i;
2284
2285 ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
2286
2287 xfs_icsb_lock_all_counters(mp);
2288 for_each_online_cpu(i) {
2289 cntp = per_cpu_ptr(mp->m_sb_cnts, i);
2290 switch (field) {
2291 case XFS_SBS_ICOUNT:
2292 cntp->icsb_icount = count + resid;
2293 break;
2294 case XFS_SBS_IFREE:
2295 cntp->icsb_ifree = count + resid;
2296 break;
2297 case XFS_SBS_FDBLOCKS:
2298 cntp->icsb_fdblocks = count + resid;
2299 break;
2300 default:
2301 BUG();
2302 break;
2303 }
2304 resid = 0;
2305 }
2306 clear_bit(field, &mp->m_icsb_counters);
2307 xfs_icsb_unlock_all_counters(mp);
2308}
2309
2310void
2311xfs_icsb_sync_counters_locked(
2312 xfs_mount_t *mp,
2313 int flags)
2314{
2315 xfs_icsb_cnts_t cnt;
2316
2317 xfs_icsb_count(mp, &cnt, flags);
2318
2319 if (!xfs_icsb_counter_disabled(mp, XFS_SBS_ICOUNT))
2320 mp->m_sb.sb_icount = cnt.icsb_icount;
2321 if (!xfs_icsb_counter_disabled(mp, XFS_SBS_IFREE))
2322 mp->m_sb.sb_ifree = cnt.icsb_ifree;
2323 if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
2324 mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
2325}
2326
2327
2328
2329
2330void
2331xfs_icsb_sync_counters(
2332 xfs_mount_t *mp,
2333 int flags)
2334{
2335 spin_lock(&mp->m_sb_lock);
2336 xfs_icsb_sync_counters_locked(mp, flags);
2337 spin_unlock(&mp->m_sb_lock);
2338}
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356#define XFS_ICSB_INO_CNTR_REENABLE (uint64_t)64
2357#define XFS_ICSB_FDBLK_CNTR_REENABLE(mp) \
2358 (uint64_t)(512 + XFS_ALLOC_SET_ASIDE(mp))
2359STATIC void
2360xfs_icsb_balance_counter_locked(
2361 xfs_mount_t *mp,
2362 xfs_sb_field_t field,
2363 int min_per_cpu)
2364{
2365 uint64_t count, resid;
2366 int weight = num_online_cpus();
2367 uint64_t min = (uint64_t)min_per_cpu;
2368
2369
2370 xfs_icsb_disable_counter(mp, field);
2371
2372
2373 switch (field) {
2374 case XFS_SBS_ICOUNT:
2375 count = mp->m_sb.sb_icount;
2376 resid = do_div(count, weight);
2377 if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
2378 return;
2379 break;
2380 case XFS_SBS_IFREE:
2381 count = mp->m_sb.sb_ifree;
2382 resid = do_div(count, weight);
2383 if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
2384 return;
2385 break;
2386 case XFS_SBS_FDBLOCKS:
2387 count = mp->m_sb.sb_fdblocks;
2388 resid = do_div(count, weight);
2389 if (count < max(min, XFS_ICSB_FDBLK_CNTR_REENABLE(mp)))
2390 return;
2391 break;
2392 default:
2393 BUG();
2394 count = resid = 0;
2395 break;
2396 }
2397
2398 xfs_icsb_enable_counter(mp, field, count, resid);
2399}
2400
2401STATIC void
2402xfs_icsb_balance_counter(
2403 xfs_mount_t *mp,
2404 xfs_sb_field_t fields,
2405 int min_per_cpu)
2406{
2407 spin_lock(&mp->m_sb_lock);
2408 xfs_icsb_balance_counter_locked(mp, fields, min_per_cpu);
2409 spin_unlock(&mp->m_sb_lock);
2410}
2411
2412int
2413xfs_icsb_modify_counters(
2414 xfs_mount_t *mp,
2415 xfs_sb_field_t field,
2416 int64_t delta,
2417 int rsvd)
2418{
2419 xfs_icsb_cnts_t *icsbp;
2420 long long lcounter;
2421 int ret = 0;
2422
2423 might_sleep();
2424again:
2425 preempt_disable();
2426 icsbp = this_cpu_ptr(mp->m_sb_cnts);
2427
2428
2429
2430
2431 if (unlikely(xfs_icsb_counter_disabled(mp, field)))
2432 goto slow_path;
2433 xfs_icsb_lock_cntr(icsbp);
2434 if (unlikely(xfs_icsb_counter_disabled(mp, field))) {
2435 xfs_icsb_unlock_cntr(icsbp);
2436 goto slow_path;
2437 }
2438
2439 switch (field) {
2440 case XFS_SBS_ICOUNT:
2441 lcounter = icsbp->icsb_icount;
2442 lcounter += delta;
2443 if (unlikely(lcounter < 0))
2444 goto balance_counter;
2445 icsbp->icsb_icount = lcounter;
2446 break;
2447
2448 case XFS_SBS_IFREE:
2449 lcounter = icsbp->icsb_ifree;
2450 lcounter += delta;
2451 if (unlikely(lcounter < 0))
2452 goto balance_counter;
2453 icsbp->icsb_ifree = lcounter;
2454 break;
2455
2456 case XFS_SBS_FDBLOCKS:
2457 BUG_ON((mp->m_resblks - mp->m_resblks_avail) != 0);
2458
2459 lcounter = icsbp->icsb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
2460 lcounter += delta;
2461 if (unlikely(lcounter < 0))
2462 goto balance_counter;
2463 icsbp->icsb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
2464 break;
2465 default:
2466 BUG();
2467 break;
2468 }
2469 xfs_icsb_unlock_cntr(icsbp);
2470 preempt_enable();
2471 return 0;
2472
2473slow_path:
2474 preempt_enable();
2475
2476
2477
2478
2479
2480
2481 xfs_icsb_lock(mp);
2482
2483
2484
2485
2486
2487
2488
2489 if (!(xfs_icsb_counter_disabled(mp, field))) {
2490 xfs_icsb_unlock(mp);
2491 goto again;
2492 }
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505 spin_lock(&mp->m_sb_lock);
2506 ret = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
2507 spin_unlock(&mp->m_sb_lock);
2508
2509
2510
2511
2512
2513
2514
2515 if (ret != ENOSPC)
2516 xfs_icsb_balance_counter(mp, field, 0);
2517 xfs_icsb_unlock(mp);
2518 return ret;
2519
2520balance_counter:
2521 xfs_icsb_unlock_cntr(icsbp);
2522 preempt_enable();
2523
2524
2525
2526
2527
2528
2529
2530 xfs_icsb_lock(mp);
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540 xfs_icsb_balance_counter(mp, field, delta);
2541 xfs_icsb_unlock(mp);
2542 goto again;
2543}
2544
2545#endif
2546