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;
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 index = xfs_set_inode32(mp);
505 else
506 index = xfs_set_inode64(mp);
507
508 if (maxagi)
509 *maxagi = index;
510 return 0;
511
512out_unwind:
513 kmem_free(pag);
514 for (; index > first_initialised; index--) {
515 pag = radix_tree_delete(&mp->m_perag_tree, index);
516 kmem_free(pag);
517 }
518 return error;
519}
520
521void
522xfs_sb_from_disk(
523 struct xfs_mount *mp,
524 xfs_dsb_t *from)
525{
526 struct xfs_sb *to = &mp->m_sb;
527
528 to->sb_magicnum = be32_to_cpu(from->sb_magicnum);
529 to->sb_blocksize = be32_to_cpu(from->sb_blocksize);
530 to->sb_dblocks = be64_to_cpu(from->sb_dblocks);
531 to->sb_rblocks = be64_to_cpu(from->sb_rblocks);
532 to->sb_rextents = be64_to_cpu(from->sb_rextents);
533 memcpy(&to->sb_uuid, &from->sb_uuid, sizeof(to->sb_uuid));
534 to->sb_logstart = be64_to_cpu(from->sb_logstart);
535 to->sb_rootino = be64_to_cpu(from->sb_rootino);
536 to->sb_rbmino = be64_to_cpu(from->sb_rbmino);
537 to->sb_rsumino = be64_to_cpu(from->sb_rsumino);
538 to->sb_rextsize = be32_to_cpu(from->sb_rextsize);
539 to->sb_agblocks = be32_to_cpu(from->sb_agblocks);
540 to->sb_agcount = be32_to_cpu(from->sb_agcount);
541 to->sb_rbmblocks = be32_to_cpu(from->sb_rbmblocks);
542 to->sb_logblocks = be32_to_cpu(from->sb_logblocks);
543 to->sb_versionnum = be16_to_cpu(from->sb_versionnum);
544 to->sb_sectsize = be16_to_cpu(from->sb_sectsize);
545 to->sb_inodesize = be16_to_cpu(from->sb_inodesize);
546 to->sb_inopblock = be16_to_cpu(from->sb_inopblock);
547 memcpy(&to->sb_fname, &from->sb_fname, sizeof(to->sb_fname));
548 to->sb_blocklog = from->sb_blocklog;
549 to->sb_sectlog = from->sb_sectlog;
550 to->sb_inodelog = from->sb_inodelog;
551 to->sb_inopblog = from->sb_inopblog;
552 to->sb_agblklog = from->sb_agblklog;
553 to->sb_rextslog = from->sb_rextslog;
554 to->sb_inprogress = from->sb_inprogress;
555 to->sb_imax_pct = from->sb_imax_pct;
556 to->sb_icount = be64_to_cpu(from->sb_icount);
557 to->sb_ifree = be64_to_cpu(from->sb_ifree);
558 to->sb_fdblocks = be64_to_cpu(from->sb_fdblocks);
559 to->sb_frextents = be64_to_cpu(from->sb_frextents);
560 to->sb_uquotino = be64_to_cpu(from->sb_uquotino);
561 to->sb_gquotino = be64_to_cpu(from->sb_gquotino);
562 to->sb_qflags = be16_to_cpu(from->sb_qflags);
563 to->sb_flags = from->sb_flags;
564 to->sb_shared_vn = from->sb_shared_vn;
565 to->sb_inoalignmt = be32_to_cpu(from->sb_inoalignmt);
566 to->sb_unit = be32_to_cpu(from->sb_unit);
567 to->sb_width = be32_to_cpu(from->sb_width);
568 to->sb_dirblklog = from->sb_dirblklog;
569 to->sb_logsectlog = from->sb_logsectlog;
570 to->sb_logsectsize = be16_to_cpu(from->sb_logsectsize);
571 to->sb_logsunit = be32_to_cpu(from->sb_logsunit);
572 to->sb_features2 = be32_to_cpu(from->sb_features2);
573 to->sb_bad_features2 = be32_to_cpu(from->sb_bad_features2);
574}
575
576
577
578
579
580
581void
582xfs_sb_to_disk(
583 xfs_dsb_t *to,
584 xfs_sb_t *from,
585 __int64_t fields)
586{
587 xfs_caddr_t to_ptr = (xfs_caddr_t)to;
588 xfs_caddr_t from_ptr = (xfs_caddr_t)from;
589 xfs_sb_field_t f;
590 int first;
591 int size;
592
593 ASSERT(fields);
594 if (!fields)
595 return;
596
597 while (fields) {
598 f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
599 first = xfs_sb_info[f].offset;
600 size = xfs_sb_info[f + 1].offset - first;
601
602 ASSERT(xfs_sb_info[f].type == 0 || xfs_sb_info[f].type == 1);
603
604 if (size == 1 || xfs_sb_info[f].type == 1) {
605 memcpy(to_ptr + first, from_ptr + first, size);
606 } else {
607 switch (size) {
608 case 2:
609 *(__be16 *)(to_ptr + first) =
610 cpu_to_be16(*(__u16 *)(from_ptr + first));
611 break;
612 case 4:
613 *(__be32 *)(to_ptr + first) =
614 cpu_to_be32(*(__u32 *)(from_ptr + first));
615 break;
616 case 8:
617 *(__be64 *)(to_ptr + first) =
618 cpu_to_be64(*(__u64 *)(from_ptr + first));
619 break;
620 default:
621 ASSERT(0);
622 }
623 }
624
625 fields &= ~(1LL << f);
626 }
627}
628
629
630
631
632
633
634int
635xfs_readsb(xfs_mount_t *mp, int flags)
636{
637 unsigned int sector_size;
638 xfs_buf_t *bp;
639 int error;
640 int loud = !(flags & XFS_MFSI_QUIET);
641
642 ASSERT(mp->m_sb_bp == NULL);
643 ASSERT(mp->m_ddev_targp != NULL);
644
645
646
647
648
649
650 sector_size = xfs_getsize_buftarg(mp->m_ddev_targp);
651
652reread:
653 bp = xfs_buf_read_uncached(mp->m_ddev_targp, XFS_SB_DADDR,
654 BTOBB(sector_size), 0);
655 if (!bp) {
656 if (loud)
657 xfs_warn(mp, "SB buffer read failed");
658 return EIO;
659 }
660
661
662
663
664
665 xfs_sb_from_disk(mp, XFS_BUF_TO_SBP(bp));
666 error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags);
667 if (error) {
668 if (loud)
669 xfs_warn(mp, "SB validate failed");
670 goto release_buf;
671 }
672
673
674
675
676 if (sector_size > mp->m_sb.sb_sectsize) {
677 if (loud)
678 xfs_warn(mp, "device supports %u byte sectors (not %u)",
679 sector_size, mp->m_sb.sb_sectsize);
680 error = ENOSYS;
681 goto release_buf;
682 }
683
684
685
686
687
688 if (sector_size < mp->m_sb.sb_sectsize) {
689 xfs_buf_relse(bp);
690 sector_size = mp->m_sb.sb_sectsize;
691 goto reread;
692 }
693
694
695 xfs_icsb_reinit_counters(mp);
696
697 mp->m_sb_bp = bp;
698 xfs_buf_unlock(bp);
699 return 0;
700
701release_buf:
702 xfs_buf_relse(bp);
703 return error;
704}
705
706
707
708
709
710
711
712
713
714STATIC void
715xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp)
716{
717 mp->m_agfrotor = mp->m_agirotor = 0;
718 spin_lock_init(&mp->m_agirotor_lock);
719 mp->m_maxagi = mp->m_sb.sb_agcount;
720 mp->m_blkbit_log = sbp->sb_blocklog + XFS_NBBYLOG;
721 mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT;
722 mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT;
723 mp->m_agno_log = xfs_highbit32(sbp->sb_agcount - 1) + 1;
724 mp->m_agino_log = sbp->sb_inopblog + sbp->sb_agblklog;
725 mp->m_blockmask = sbp->sb_blocksize - 1;
726 mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG;
727 mp->m_blockwmask = mp->m_blockwsize - 1;
728
729 mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1);
730 mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0);
731 mp->m_alloc_mnr[0] = mp->m_alloc_mxr[0] / 2;
732 mp->m_alloc_mnr[1] = mp->m_alloc_mxr[1] / 2;
733
734 mp->m_inobt_mxr[0] = xfs_inobt_maxrecs(mp, sbp->sb_blocksize, 1);
735 mp->m_inobt_mxr[1] = xfs_inobt_maxrecs(mp, sbp->sb_blocksize, 0);
736 mp->m_inobt_mnr[0] = mp->m_inobt_mxr[0] / 2;
737 mp->m_inobt_mnr[1] = mp->m_inobt_mxr[1] / 2;
738
739 mp->m_bmap_dmxr[0] = xfs_bmbt_maxrecs(mp, sbp->sb_blocksize, 1);
740 mp->m_bmap_dmxr[1] = xfs_bmbt_maxrecs(mp, sbp->sb_blocksize, 0);
741 mp->m_bmap_dmnr[0] = mp->m_bmap_dmxr[0] / 2;
742 mp->m_bmap_dmnr[1] = mp->m_bmap_dmxr[1] / 2;
743
744 mp->m_bsize = XFS_FSB_TO_BB(mp, 1);
745 mp->m_ialloc_inos = (int)MAX((__uint16_t)XFS_INODES_PER_CHUNK,
746 sbp->sb_inopblock);
747 mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog;
748}
749
750
751
752
753
754
755
756
757
758STATIC int
759xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount)
760{
761 xfs_agnumber_t index;
762 xfs_perag_t *pag;
763 xfs_sb_t *sbp = &mp->m_sb;
764 uint64_t ifree = 0;
765 uint64_t ialloc = 0;
766 uint64_t bfree = 0;
767 uint64_t bfreelst = 0;
768 uint64_t btree = 0;
769 int error;
770
771 for (index = 0; index < agcount; index++) {
772
773
774
775
776
777 error = xfs_alloc_pagf_init(mp, NULL, index, 0);
778 if (error)
779 return error;
780
781 error = xfs_ialloc_pagi_init(mp, NULL, index);
782 if (error)
783 return error;
784 pag = xfs_perag_get(mp, index);
785 ifree += pag->pagi_freecount;
786 ialloc += pag->pagi_count;
787 bfree += pag->pagf_freeblks;
788 bfreelst += pag->pagf_flcount;
789 btree += pag->pagf_btreeblks;
790 xfs_perag_put(pag);
791 }
792
793
794
795 spin_lock(&mp->m_sb_lock);
796 sbp->sb_ifree = ifree;
797 sbp->sb_icount = ialloc;
798 sbp->sb_fdblocks = bfree + bfreelst + btree;
799 spin_unlock(&mp->m_sb_lock);
800
801
802 xfs_icsb_reinit_counters(mp);
803
804 return 0;
805}
806
807
808
809
810STATIC int
811xfs_update_alignment(xfs_mount_t *mp)
812{
813 xfs_sb_t *sbp = &(mp->m_sb);
814
815 if (mp->m_dalign) {
816
817
818
819
820 if ((BBTOB(mp->m_dalign) & mp->m_blockmask) ||
821 (BBTOB(mp->m_swidth) & mp->m_blockmask)) {
822 if (mp->m_flags & XFS_MOUNT_RETERR) {
823 xfs_warn(mp, "alignment check failed: "
824 "(sunit/swidth vs. blocksize)");
825 return XFS_ERROR(EINVAL);
826 }
827 mp->m_dalign = mp->m_swidth = 0;
828 } else {
829
830
831
832 mp->m_dalign = XFS_BB_TO_FSBT(mp, mp->m_dalign);
833 if (mp->m_dalign && (sbp->sb_agblocks % mp->m_dalign)) {
834 if (mp->m_flags & XFS_MOUNT_RETERR) {
835 xfs_warn(mp, "alignment check failed: "
836 "(sunit/swidth vs. ag size)");
837 return XFS_ERROR(EINVAL);
838 }
839 xfs_warn(mp,
840 "stripe alignment turned off: sunit(%d)/swidth(%d) "
841 "incompatible with agsize(%d)",
842 mp->m_dalign, mp->m_swidth,
843 sbp->sb_agblocks);
844
845 mp->m_dalign = 0;
846 mp->m_swidth = 0;
847 } else if (mp->m_dalign) {
848 mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth);
849 } else {
850 if (mp->m_flags & XFS_MOUNT_RETERR) {
851 xfs_warn(mp, "alignment check failed: "
852 "sunit(%d) less than bsize(%d)",
853 mp->m_dalign,
854 mp->m_blockmask +1);
855 return XFS_ERROR(EINVAL);
856 }
857 mp->m_swidth = 0;
858 }
859 }
860
861
862
863
864
865 if (xfs_sb_version_hasdalign(sbp)) {
866 if (sbp->sb_unit != mp->m_dalign) {
867 sbp->sb_unit = mp->m_dalign;
868 mp->m_update_flags |= XFS_SB_UNIT;
869 }
870 if (sbp->sb_width != mp->m_swidth) {
871 sbp->sb_width = mp->m_swidth;
872 mp->m_update_flags |= XFS_SB_WIDTH;
873 }
874 }
875 } else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN &&
876 xfs_sb_version_hasdalign(&mp->m_sb)) {
877 mp->m_dalign = sbp->sb_unit;
878 mp->m_swidth = sbp->sb_width;
879 }
880
881 return 0;
882}
883
884
885
886
887STATIC void
888xfs_set_maxicount(xfs_mount_t *mp)
889{
890 xfs_sb_t *sbp = &(mp->m_sb);
891 __uint64_t icount;
892
893 if (sbp->sb_imax_pct) {
894
895
896
897
898 icount = sbp->sb_dblocks * sbp->sb_imax_pct;
899 do_div(icount, 100);
900 do_div(icount, mp->m_ialloc_blks);
901 mp->m_maxicount = (icount * mp->m_ialloc_blks) <<
902 sbp->sb_inopblog;
903 } else {
904 mp->m_maxicount = 0;
905 }
906}
907
908
909
910
911
912
913
914STATIC void
915xfs_set_rw_sizes(xfs_mount_t *mp)
916{
917 xfs_sb_t *sbp = &(mp->m_sb);
918 int readio_log, writeio_log;
919
920 if (!(mp->m_flags & XFS_MOUNT_DFLT_IOSIZE)) {
921 if (mp->m_flags & XFS_MOUNT_WSYNC) {
922 readio_log = XFS_WSYNC_READIO_LOG;
923 writeio_log = XFS_WSYNC_WRITEIO_LOG;
924 } else {
925 readio_log = XFS_READIO_LOG_LARGE;
926 writeio_log = XFS_WRITEIO_LOG_LARGE;
927 }
928 } else {
929 readio_log = mp->m_readio_log;
930 writeio_log = mp->m_writeio_log;
931 }
932
933 if (sbp->sb_blocklog > readio_log) {
934 mp->m_readio_log = sbp->sb_blocklog;
935 } else {
936 mp->m_readio_log = readio_log;
937 }
938 mp->m_readio_blocks = 1 << (mp->m_readio_log - sbp->sb_blocklog);
939 if (sbp->sb_blocklog > writeio_log) {
940 mp->m_writeio_log = sbp->sb_blocklog;
941 } else {
942 mp->m_writeio_log = writeio_log;
943 }
944 mp->m_writeio_blocks = 1 << (mp->m_writeio_log - sbp->sb_blocklog);
945}
946
947
948
949
950void
951xfs_set_low_space_thresholds(
952 struct xfs_mount *mp)
953{
954 int i;
955
956 for (i = 0; i < XFS_LOWSP_MAX; i++) {
957 __uint64_t space = mp->m_sb.sb_dblocks;
958
959 do_div(space, 100);
960 mp->m_low_space[i] = space * (i + 1);
961 }
962}
963
964
965
966
967
968STATIC void
969xfs_set_inoalignment(xfs_mount_t *mp)
970{
971 if (xfs_sb_version_hasalign(&mp->m_sb) &&
972 mp->m_sb.sb_inoalignmt >=
973 XFS_B_TO_FSBT(mp, mp->m_inode_cluster_size))
974 mp->m_inoalign_mask = mp->m_sb.sb_inoalignmt - 1;
975 else
976 mp->m_inoalign_mask = 0;
977
978
979
980
981 if (mp->m_dalign && mp->m_inoalign_mask &&
982 !(mp->m_dalign & mp->m_inoalign_mask))
983 mp->m_sinoalign = mp->m_dalign;
984 else
985 mp->m_sinoalign = 0;
986}
987
988
989
990
991STATIC int
992xfs_check_sizes(xfs_mount_t *mp)
993{
994 xfs_buf_t *bp;
995 xfs_daddr_t d;
996
997 d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks);
998 if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) {
999 xfs_warn(mp, "filesystem size mismatch detected");
1000 return XFS_ERROR(EFBIG);
1001 }
1002 bp = xfs_buf_read_uncached(mp->m_ddev_targp,
1003 d - XFS_FSS_TO_BB(mp, 1),
1004 XFS_FSS_TO_BB(mp, 1), 0);
1005 if (!bp) {
1006 xfs_warn(mp, "last sector read failed");
1007 return EIO;
1008 }
1009 xfs_buf_relse(bp);
1010
1011 if (mp->m_logdev_targp != mp->m_ddev_targp) {
1012 d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
1013 if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) {
1014 xfs_warn(mp, "log size mismatch detected");
1015 return XFS_ERROR(EFBIG);
1016 }
1017 bp = xfs_buf_read_uncached(mp->m_logdev_targp,
1018 d - XFS_FSB_TO_BB(mp, 1),
1019 XFS_FSB_TO_BB(mp, 1), 0);
1020 if (!bp) {
1021 xfs_warn(mp, "log device read failed");
1022 return EIO;
1023 }
1024 xfs_buf_relse(bp);
1025 }
1026 return 0;
1027}
1028
1029
1030
1031
1032int
1033xfs_mount_reset_sbqflags(
1034 struct xfs_mount *mp)
1035{
1036 int error;
1037 struct xfs_trans *tp;
1038
1039 mp->m_qflags = 0;
1040
1041
1042
1043
1044
1045 if (mp->m_sb.sb_qflags == 0)
1046 return 0;
1047 spin_lock(&mp->m_sb_lock);
1048 mp->m_sb.sb_qflags = 0;
1049 spin_unlock(&mp->m_sb_lock);
1050
1051
1052
1053
1054
1055 if (mp->m_flags & XFS_MOUNT_RDONLY)
1056 return 0;
1057
1058 tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE);
1059 error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
1060 XFS_DEFAULT_LOG_COUNT);
1061 if (error) {
1062 xfs_trans_cancel(tp, 0);
1063 xfs_alert(mp, "%s: Superblock update failed!", __func__);
1064 return error;
1065 }
1066
1067 xfs_mod_sb(tp, XFS_SB_QFLAGS);
1068 return xfs_trans_commit(tp, 0);
1069}
1070
1071__uint64_t
1072xfs_default_resblks(xfs_mount_t *mp)
1073{
1074 __uint64_t resblks;
1075
1076
1077
1078
1079
1080
1081
1082
1083 resblks = mp->m_sb.sb_dblocks;
1084 do_div(resblks, 20);
1085 resblks = min_t(__uint64_t, resblks, 8192);
1086 return resblks;
1087}
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099int
1100xfs_mountfs(
1101 xfs_mount_t *mp)
1102{
1103 xfs_sb_t *sbp = &(mp->m_sb);
1104 xfs_inode_t *rip;
1105 __uint64_t resblks;
1106 uint quotamount = 0;
1107 uint quotaflags = 0;
1108 int error = 0;
1109
1110 xfs_mount_common(mp, sbp);
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128 if (xfs_sb_has_mismatched_features2(sbp)) {
1129 xfs_warn(mp, "correcting sb_features alignment problem");
1130 sbp->sb_features2 |= sbp->sb_bad_features2;
1131 sbp->sb_bad_features2 = sbp->sb_features2;
1132 mp->m_update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2;
1133
1134
1135
1136
1137
1138 if (xfs_sb_version_hasattr2(&mp->m_sb) &&
1139 !(mp->m_flags & XFS_MOUNT_NOATTR2))
1140 mp->m_flags |= XFS_MOUNT_ATTR2;
1141 }
1142
1143 if (xfs_sb_version_hasattr2(&mp->m_sb) &&
1144 (mp->m_flags & XFS_MOUNT_NOATTR2)) {
1145 xfs_sb_version_removeattr2(&mp->m_sb);
1146 mp->m_update_flags |= XFS_SB_FEATURES2;
1147
1148
1149 if (!sbp->sb_features2)
1150 mp->m_update_flags |= XFS_SB_VERSIONNUM;
1151 }
1152
1153
1154
1155
1156
1157
1158
1159 error = xfs_update_alignment(mp);
1160 if (error)
1161 goto out;
1162
1163 xfs_alloc_compute_maxlevels(mp);
1164 xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK);
1165 xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK);
1166 xfs_ialloc_compute_maxlevels(mp);
1167
1168 xfs_set_maxicount(mp);
1169
1170 error = xfs_uuid_mount(mp);
1171 if (error)
1172 goto out;
1173
1174
1175
1176
1177 xfs_set_rw_sizes(mp);
1178
1179
1180 xfs_set_low_space_thresholds(mp);
1181
1182
1183
1184
1185
1186
1187 mp->m_inode_cluster_size = XFS_INODE_BIG_CLUSTER_SIZE;
1188
1189
1190
1191
1192 xfs_set_inoalignment(mp);
1193
1194
1195
1196
1197 error = xfs_check_sizes(mp);
1198 if (error)
1199 goto out_remove_uuid;
1200
1201
1202
1203
1204 error = xfs_rtmount_init(mp);
1205 if (error) {
1206 xfs_warn(mp, "RT mount failed");
1207 goto out_remove_uuid;
1208 }
1209
1210
1211
1212
1213
1214 uuid_getnodeuniq(&sbp->sb_uuid, mp->m_fixedfsid);
1215
1216 mp->m_dmevmask = 0;
1217
1218 xfs_dir_mount(mp);
1219
1220
1221
1222
1223 mp->m_attr_magicpct = (mp->m_sb.sb_blocksize * 37) / 100;
1224
1225
1226
1227
1228 xfs_trans_init(mp);
1229
1230
1231
1232
1233 spin_lock_init(&mp->m_perag_lock);
1234 INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC);
1235 error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi);
1236 if (error) {
1237 xfs_warn(mp, "Failed per-ag init: %d", error);
1238 goto out_remove_uuid;
1239 }
1240
1241 if (!sbp->sb_logblocks) {
1242 xfs_warn(mp, "no log defined");
1243 XFS_ERROR_REPORT("xfs_mountfs", XFS_ERRLEVEL_LOW, mp);
1244 error = XFS_ERROR(EFSCORRUPTED);
1245 goto out_free_perag;
1246 }
1247
1248
1249
1250
1251 error = xfs_log_mount(mp, mp->m_logdev_targp,
1252 XFS_FSB_TO_DADDR(mp, sbp->sb_logstart),
1253 XFS_FSB_TO_BB(mp, sbp->sb_logblocks));
1254 if (error) {
1255 xfs_warn(mp, "log mount failed");
1256 goto out_fail_wait;
1257 }
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278 if (xfs_sb_version_haslazysbcount(&mp->m_sb) &&
1279 !XFS_LAST_UNMOUNT_WAS_CLEAN(mp) &&
1280 !mp->m_sb.sb_inprogress) {
1281 error = xfs_initialize_perag_data(mp, sbp->sb_agcount);
1282 if (error)
1283 goto out_fail_wait;
1284 }
1285
1286
1287
1288
1289
1290 error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip);
1291 if (error) {
1292 xfs_warn(mp, "failed to read root inode");
1293 goto out_log_dealloc;
1294 }
1295
1296 ASSERT(rip != NULL);
1297
1298 if (unlikely(!S_ISDIR(rip->i_d.di_mode))) {
1299 xfs_warn(mp, "corrupted root inode %llu: not a directory",
1300 (unsigned long long)rip->i_ino);
1301 xfs_iunlock(rip, XFS_ILOCK_EXCL);
1302 XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW,
1303 mp);
1304 error = XFS_ERROR(EFSCORRUPTED);
1305 goto out_rele_rip;
1306 }
1307 mp->m_rootip = rip;
1308
1309 xfs_iunlock(rip, XFS_ILOCK_EXCL);
1310
1311
1312
1313
1314 error = xfs_rtmount_inodes(mp);
1315 if (error) {
1316
1317
1318
1319 xfs_warn(mp, "failed to read RT inodes");
1320 goto out_rele_rip;
1321 }
1322
1323
1324
1325
1326
1327
1328 if (mp->m_update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) {
1329 error = xfs_mount_log_sb(mp, mp->m_update_flags);
1330 if (error) {
1331 xfs_warn(mp, "failed to write sb changes");
1332 goto out_rtunmount;
1333 }
1334 }
1335
1336
1337
1338
1339 if (XFS_IS_QUOTA_RUNNING(mp)) {
1340 error = xfs_qm_newmount(mp, "amount, "aflags);
1341 if (error)
1342 goto out_rtunmount;
1343 } else {
1344 ASSERT(!XFS_IS_QUOTA_ON(mp));
1345
1346
1347
1348
1349
1350
1351 if (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT) {
1352 xfs_notice(mp, "resetting quota flags");
1353 error = xfs_mount_reset_sbqflags(mp);
1354 if (error)
1355 return error;
1356 }
1357 }
1358
1359
1360
1361
1362
1363
1364 error = xfs_log_mount_finish(mp);
1365 if (error) {
1366 xfs_warn(mp, "log mount finish failed");
1367 goto out_rtunmount;
1368 }
1369
1370
1371
1372
1373 if (quotamount) {
1374 ASSERT(mp->m_qflags == 0);
1375 mp->m_qflags = quotaflags;
1376
1377 xfs_qm_mount_quotas(mp);
1378 }
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391 if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
1392 resblks = xfs_default_resblks(mp);
1393 error = xfs_reserve_blocks(mp, &resblks, NULL);
1394 if (error)
1395 xfs_warn(mp,
1396 "Unable to allocate reserve blocks. Continuing without reserve pool.");
1397 }
1398
1399 return 0;
1400
1401 out_rtunmount:
1402 xfs_rtunmount_inodes(mp);
1403 out_rele_rip:
1404 IRELE(rip);
1405 out_log_dealloc:
1406 xfs_log_unmount(mp);
1407 out_fail_wait:
1408 if (mp->m_logdev_targp && mp->m_logdev_targp != mp->m_ddev_targp)
1409 xfs_wait_buftarg(mp->m_logdev_targp);
1410 xfs_wait_buftarg(mp->m_ddev_targp);
1411 out_free_perag:
1412 xfs_free_perag(mp);
1413 out_remove_uuid:
1414 xfs_uuid_unmount(mp);
1415 out:
1416 return error;
1417}
1418
1419
1420
1421
1422
1423void
1424xfs_unmountfs(
1425 struct xfs_mount *mp)
1426{
1427 __uint64_t resblks;
1428 int error;
1429
1430 xfs_qm_unmount_quotas(mp);
1431 xfs_rtunmount_inodes(mp);
1432 IRELE(mp->m_rootip);
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444 xfs_log_force(mp, XFS_LOG_SYNC);
1445
1446
1447
1448
1449 xfs_ail_push_all_sync(mp->m_ail);
1450
1451
1452
1453
1454
1455
1456 xfs_reclaim_inodes(mp, SYNC_WAIT);
1457
1458 xfs_qm_unmount(mp);
1459
1460
1461
1462
1463
1464
1465 xfs_log_force(mp, XFS_LOG_SYNC);
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481 resblks = 0;
1482 error = xfs_reserve_blocks(mp, &resblks, NULL);
1483 if (error)
1484 xfs_warn(mp, "Unable to free reserved block pool. "
1485 "Freespace may not be correct on next mount.");
1486
1487 error = xfs_log_sbcount(mp);
1488 if (error)
1489 xfs_warn(mp, "Unable to update superblock counters. "
1490 "Freespace may not be correct on next mount.");
1491
1492
1493
1494
1495
1496 xfs_ail_push_all_sync(mp->m_ail);
1497 xfs_wait_buftarg(mp->m_ddev_targp);
1498
1499
1500
1501
1502
1503
1504
1505 xfs_buf_lock(mp->m_sb_bp);
1506 xfs_buf_unlock(mp->m_sb_bp);
1507
1508 xfs_log_unmount_write(mp);
1509 xfs_log_unmount(mp);
1510 xfs_uuid_unmount(mp);
1511
1512#if defined(DEBUG)
1513 xfs_errortag_clearall(mp, 0);
1514#endif
1515 xfs_free_perag(mp);
1516}
1517
1518int
1519xfs_fs_writable(xfs_mount_t *mp)
1520{
1521 return !(mp->m_super->s_writers.frozen || XFS_FORCED_SHUTDOWN(mp) ||
1522 (mp->m_flags & XFS_MOUNT_RDONLY));
1523}
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534int
1535xfs_log_sbcount(xfs_mount_t *mp)
1536{
1537 xfs_trans_t *tp;
1538 int error;
1539
1540 if (!xfs_fs_writable(mp))
1541 return 0;
1542
1543 xfs_icsb_sync_counters(mp, 0);
1544
1545
1546
1547
1548
1549 if (!xfs_sb_version_haslazysbcount(&mp->m_sb))
1550 return 0;
1551
1552 tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_COUNT, KM_SLEEP);
1553 error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
1554 XFS_DEFAULT_LOG_COUNT);
1555 if (error) {
1556 xfs_trans_cancel(tp, 0);
1557 return error;
1558 }
1559
1560 xfs_mod_sb(tp, XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS);
1561 xfs_trans_set_sync(tp);
1562 error = xfs_trans_commit(tp, 0);
1563 return error;
1564}
1565
1566
1567
1568
1569
1570
1571
1572
1573void
1574xfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
1575{
1576 xfs_buf_t *bp;
1577 int first;
1578 int last;
1579 xfs_mount_t *mp;
1580 xfs_sb_field_t f;
1581
1582 ASSERT(fields);
1583 if (!fields)
1584 return;
1585 mp = tp->t_mountp;
1586 bp = xfs_trans_getsb(tp, mp, 0);
1587 first = sizeof(xfs_sb_t);
1588 last = 0;
1589
1590
1591
1592 xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, fields);
1593
1594
1595 f = (xfs_sb_field_t)xfs_highbit64((__uint64_t)fields);
1596 ASSERT((1LL << f) & XFS_SB_MOD_BITS);
1597 last = xfs_sb_info[f + 1].offset - 1;
1598
1599 f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
1600 ASSERT((1LL << f) & XFS_SB_MOD_BITS);
1601 first = xfs_sb_info[f].offset;
1602
1603 xfs_trans_log_buf(tp, bp, first, last);
1604}
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616STATIC int
1617xfs_mod_incore_sb_unlocked(
1618 xfs_mount_t *mp,
1619 xfs_sb_field_t field,
1620 int64_t delta,
1621 int rsvd)
1622{
1623 int scounter;
1624 long long lcounter;
1625 long long res_used, rem;
1626
1627
1628
1629
1630
1631
1632
1633 switch (field) {
1634 case XFS_SBS_ICOUNT:
1635 lcounter = (long long)mp->m_sb.sb_icount;
1636 lcounter += delta;
1637 if (lcounter < 0) {
1638 ASSERT(0);
1639 return XFS_ERROR(EINVAL);
1640 }
1641 mp->m_sb.sb_icount = lcounter;
1642 return 0;
1643 case XFS_SBS_IFREE:
1644 lcounter = (long long)mp->m_sb.sb_ifree;
1645 lcounter += delta;
1646 if (lcounter < 0) {
1647 ASSERT(0);
1648 return XFS_ERROR(EINVAL);
1649 }
1650 mp->m_sb.sb_ifree = lcounter;
1651 return 0;
1652 case XFS_SBS_FDBLOCKS:
1653 lcounter = (long long)
1654 mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
1655 res_used = (long long)(mp->m_resblks - mp->m_resblks_avail);
1656
1657 if (delta > 0) {
1658 if (res_used > delta) {
1659 mp->m_resblks_avail += delta;
1660 } else {
1661 rem = delta - res_used;
1662 mp->m_resblks_avail = mp->m_resblks;
1663 lcounter += rem;
1664 }
1665 } else {
1666 lcounter += delta;
1667 if (lcounter >= 0) {
1668 mp->m_sb.sb_fdblocks = lcounter +
1669 XFS_ALLOC_SET_ASIDE(mp);
1670 return 0;
1671 }
1672
1673
1674
1675
1676
1677 if (!rsvd)
1678 return XFS_ERROR(ENOSPC);
1679
1680 lcounter = (long long)mp->m_resblks_avail + delta;
1681 if (lcounter >= 0) {
1682 mp->m_resblks_avail = lcounter;
1683 return 0;
1684 }
1685 printk_once(KERN_WARNING
1686 "Filesystem \"%s\": reserve blocks depleted! "
1687 "Consider increasing reserve pool size.",
1688 mp->m_fsname);
1689 return XFS_ERROR(ENOSPC);
1690 }
1691
1692 mp->m_sb.sb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
1693 return 0;
1694 case XFS_SBS_FREXTENTS:
1695 lcounter = (long long)mp->m_sb.sb_frextents;
1696 lcounter += delta;
1697 if (lcounter < 0) {
1698 return XFS_ERROR(ENOSPC);
1699 }
1700 mp->m_sb.sb_frextents = lcounter;
1701 return 0;
1702 case XFS_SBS_DBLOCKS:
1703 lcounter = (long long)mp->m_sb.sb_dblocks;
1704 lcounter += delta;
1705 if (lcounter < 0) {
1706 ASSERT(0);
1707 return XFS_ERROR(EINVAL);
1708 }
1709 mp->m_sb.sb_dblocks = lcounter;
1710 return 0;
1711 case XFS_SBS_AGCOUNT:
1712 scounter = mp->m_sb.sb_agcount;
1713 scounter += delta;
1714 if (scounter < 0) {
1715 ASSERT(0);
1716 return XFS_ERROR(EINVAL);
1717 }
1718 mp->m_sb.sb_agcount = scounter;
1719 return 0;
1720 case XFS_SBS_IMAX_PCT:
1721 scounter = mp->m_sb.sb_imax_pct;
1722 scounter += delta;
1723 if (scounter < 0) {
1724 ASSERT(0);
1725 return XFS_ERROR(EINVAL);
1726 }
1727 mp->m_sb.sb_imax_pct = scounter;
1728 return 0;
1729 case XFS_SBS_REXTSIZE:
1730 scounter = mp->m_sb.sb_rextsize;
1731 scounter += delta;
1732 if (scounter < 0) {
1733 ASSERT(0);
1734 return XFS_ERROR(EINVAL);
1735 }
1736 mp->m_sb.sb_rextsize = scounter;
1737 return 0;
1738 case XFS_SBS_RBMBLOCKS:
1739 scounter = mp->m_sb.sb_rbmblocks;
1740 scounter += delta;
1741 if (scounter < 0) {
1742 ASSERT(0);
1743 return XFS_ERROR(EINVAL);
1744 }
1745 mp->m_sb.sb_rbmblocks = scounter;
1746 return 0;
1747 case XFS_SBS_RBLOCKS:
1748 lcounter = (long long)mp->m_sb.sb_rblocks;
1749 lcounter += delta;
1750 if (lcounter < 0) {
1751 ASSERT(0);
1752 return XFS_ERROR(EINVAL);
1753 }
1754 mp->m_sb.sb_rblocks = lcounter;
1755 return 0;
1756 case XFS_SBS_REXTENTS:
1757 lcounter = (long long)mp->m_sb.sb_rextents;
1758 lcounter += delta;
1759 if (lcounter < 0) {
1760 ASSERT(0);
1761 return XFS_ERROR(EINVAL);
1762 }
1763 mp->m_sb.sb_rextents = lcounter;
1764 return 0;
1765 case XFS_SBS_REXTSLOG:
1766 scounter = mp->m_sb.sb_rextslog;
1767 scounter += delta;
1768 if (scounter < 0) {
1769 ASSERT(0);
1770 return XFS_ERROR(EINVAL);
1771 }
1772 mp->m_sb.sb_rextslog = scounter;
1773 return 0;
1774 default:
1775 ASSERT(0);
1776 return XFS_ERROR(EINVAL);
1777 }
1778}
1779
1780
1781
1782
1783
1784
1785
1786int
1787xfs_mod_incore_sb(
1788 struct xfs_mount *mp,
1789 xfs_sb_field_t field,
1790 int64_t delta,
1791 int rsvd)
1792{
1793 int status;
1794
1795#ifdef HAVE_PERCPU_SB
1796 ASSERT(field < XFS_SBS_ICOUNT || field > XFS_SBS_FDBLOCKS);
1797#endif
1798 spin_lock(&mp->m_sb_lock);
1799 status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
1800 spin_unlock(&mp->m_sb_lock);
1801
1802 return status;
1803}
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817int
1818xfs_mod_incore_sb_batch(
1819 struct xfs_mount *mp,
1820 xfs_mod_sb_t *msb,
1821 uint nmsb,
1822 int rsvd)
1823{
1824 xfs_mod_sb_t *msbp;
1825 int error = 0;
1826
1827
1828
1829
1830
1831
1832
1833 spin_lock(&mp->m_sb_lock);
1834 for (msbp = msb; msbp < (msb + nmsb); msbp++) {
1835 ASSERT(msbp->msb_field < XFS_SBS_ICOUNT ||
1836 msbp->msb_field > XFS_SBS_FDBLOCKS);
1837
1838 error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field,
1839 msbp->msb_delta, rsvd);
1840 if (error)
1841 goto unwind;
1842 }
1843 spin_unlock(&mp->m_sb_lock);
1844 return 0;
1845
1846unwind:
1847 while (--msbp >= msb) {
1848 error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field,
1849 -msbp->msb_delta, rsvd);
1850 ASSERT(error == 0);
1851 }
1852 spin_unlock(&mp->m_sb_lock);
1853 return error;
1854}
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865struct xfs_buf *
1866xfs_getsb(
1867 struct xfs_mount *mp,
1868 int flags)
1869{
1870 struct xfs_buf *bp = mp->m_sb_bp;
1871
1872 if (!xfs_buf_trylock(bp)) {
1873 if (flags & XBF_TRYLOCK)
1874 return NULL;
1875 xfs_buf_lock(bp);
1876 }
1877
1878 xfs_buf_hold(bp);
1879 ASSERT(XFS_BUF_ISDONE(bp));
1880 return bp;
1881}
1882
1883
1884
1885
1886void
1887xfs_freesb(
1888 struct xfs_mount *mp)
1889{
1890 struct xfs_buf *bp = mp->m_sb_bp;
1891
1892 xfs_buf_lock(bp);
1893 mp->m_sb_bp = NULL;
1894 xfs_buf_relse(bp);
1895}
1896
1897
1898
1899
1900
1901
1902int
1903xfs_mount_log_sb(
1904 xfs_mount_t *mp,
1905 __int64_t fields)
1906{
1907 xfs_trans_t *tp;
1908 int error;
1909
1910 ASSERT(fields & (XFS_SB_UNIT | XFS_SB_WIDTH | XFS_SB_UUID |
1911 XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2 |
1912 XFS_SB_VERSIONNUM));
1913
1914 tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT);
1915 error = xfs_trans_reserve(tp, 0, mp->m_sb.sb_sectsize + 128, 0, 0,
1916 XFS_DEFAULT_LOG_COUNT);
1917 if (error) {
1918 xfs_trans_cancel(tp, 0);
1919 return error;
1920 }
1921 xfs_mod_sb(tp, fields);
1922 error = xfs_trans_commit(tp, 0);
1923 return error;
1924}
1925
1926
1927
1928
1929
1930int
1931xfs_dev_is_read_only(
1932 struct xfs_mount *mp,
1933 char *message)
1934{
1935 if (xfs_readonly_buftarg(mp->m_ddev_targp) ||
1936 xfs_readonly_buftarg(mp->m_logdev_targp) ||
1937 (mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp))) {
1938 xfs_notice(mp, "%s required on read-only device.", message);
1939 xfs_notice(mp, "write access unavailable, cannot proceed.");
1940 return EROFS;
1941 }
1942 return 0;
1943}
1944
1945#ifdef HAVE_PERCPU_SB
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998#ifdef CONFIG_HOTPLUG_CPU
1999
2000
2001
2002
2003
2004
2005
2006
2007STATIC int
2008xfs_icsb_cpu_notify(
2009 struct notifier_block *nfb,
2010 unsigned long action,
2011 void *hcpu)
2012{
2013 xfs_icsb_cnts_t *cntp;
2014 xfs_mount_t *mp;
2015
2016 mp = (xfs_mount_t *)container_of(nfb, xfs_mount_t, m_icsb_notifier);
2017 cntp = (xfs_icsb_cnts_t *)
2018 per_cpu_ptr(mp->m_sb_cnts, (unsigned long)hcpu);
2019 switch (action) {
2020 case CPU_UP_PREPARE:
2021 case CPU_UP_PREPARE_FROZEN:
2022
2023
2024 memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
2025 break;
2026 case CPU_ONLINE:
2027 case CPU_ONLINE_FROZEN:
2028 xfs_icsb_lock(mp);
2029 xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
2030 xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
2031 xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
2032 xfs_icsb_unlock(mp);
2033 break;
2034 case CPU_DEAD:
2035 case CPU_DEAD_FROZEN:
2036
2037
2038
2039 xfs_icsb_lock(mp);
2040 spin_lock(&mp->m_sb_lock);
2041 xfs_icsb_disable_counter(mp, XFS_SBS_ICOUNT);
2042 xfs_icsb_disable_counter(mp, XFS_SBS_IFREE);
2043 xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS);
2044
2045 mp->m_sb.sb_icount += cntp->icsb_icount;
2046 mp->m_sb.sb_ifree += cntp->icsb_ifree;
2047 mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks;
2048
2049 memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
2050
2051 xfs_icsb_balance_counter_locked(mp, XFS_SBS_ICOUNT, 0);
2052 xfs_icsb_balance_counter_locked(mp, XFS_SBS_IFREE, 0);
2053 xfs_icsb_balance_counter_locked(mp, XFS_SBS_FDBLOCKS, 0);
2054 spin_unlock(&mp->m_sb_lock);
2055 xfs_icsb_unlock(mp);
2056 break;
2057 }
2058
2059 return NOTIFY_OK;
2060}
2061#endif
2062
2063int
2064xfs_icsb_init_counters(
2065 xfs_mount_t *mp)
2066{
2067 xfs_icsb_cnts_t *cntp;
2068 int i;
2069
2070 mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t);
2071 if (mp->m_sb_cnts == NULL)
2072 return -ENOMEM;
2073
2074#ifdef CONFIG_HOTPLUG_CPU
2075 mp->m_icsb_notifier.notifier_call = xfs_icsb_cpu_notify;
2076 mp->m_icsb_notifier.priority = 0;
2077 register_hotcpu_notifier(&mp->m_icsb_notifier);
2078#endif
2079
2080 for_each_online_cpu(i) {
2081 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
2082 memset(cntp, 0, sizeof(xfs_icsb_cnts_t));
2083 }
2084
2085 mutex_init(&mp->m_icsb_mutex);
2086
2087
2088
2089
2090
2091 mp->m_icsb_counters = -1;
2092 return 0;
2093}
2094
2095void
2096xfs_icsb_reinit_counters(
2097 xfs_mount_t *mp)
2098{
2099 xfs_icsb_lock(mp);
2100
2101
2102
2103
2104 mp->m_icsb_counters = -1;
2105 xfs_icsb_balance_counter(mp, XFS_SBS_ICOUNT, 0);
2106 xfs_icsb_balance_counter(mp, XFS_SBS_IFREE, 0);
2107 xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0);
2108 xfs_icsb_unlock(mp);
2109}
2110
2111void
2112xfs_icsb_destroy_counters(
2113 xfs_mount_t *mp)
2114{
2115 if (mp->m_sb_cnts) {
2116 unregister_hotcpu_notifier(&mp->m_icsb_notifier);
2117 free_percpu(mp->m_sb_cnts);
2118 }
2119 mutex_destroy(&mp->m_icsb_mutex);
2120}
2121
2122STATIC void
2123xfs_icsb_lock_cntr(
2124 xfs_icsb_cnts_t *icsbp)
2125{
2126 while (test_and_set_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags)) {
2127 ndelay(1000);
2128 }
2129}
2130
2131STATIC void
2132xfs_icsb_unlock_cntr(
2133 xfs_icsb_cnts_t *icsbp)
2134{
2135 clear_bit(XFS_ICSB_FLAG_LOCK, &icsbp->icsb_flags);
2136}
2137
2138
2139STATIC void
2140xfs_icsb_lock_all_counters(
2141 xfs_mount_t *mp)
2142{
2143 xfs_icsb_cnts_t *cntp;
2144 int i;
2145
2146 for_each_online_cpu(i) {
2147 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
2148 xfs_icsb_lock_cntr(cntp);
2149 }
2150}
2151
2152STATIC void
2153xfs_icsb_unlock_all_counters(
2154 xfs_mount_t *mp)
2155{
2156 xfs_icsb_cnts_t *cntp;
2157 int i;
2158
2159 for_each_online_cpu(i) {
2160 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
2161 xfs_icsb_unlock_cntr(cntp);
2162 }
2163}
2164
2165STATIC void
2166xfs_icsb_count(
2167 xfs_mount_t *mp,
2168 xfs_icsb_cnts_t *cnt,
2169 int flags)
2170{
2171 xfs_icsb_cnts_t *cntp;
2172 int i;
2173
2174 memset(cnt, 0, sizeof(xfs_icsb_cnts_t));
2175
2176 if (!(flags & XFS_ICSB_LAZY_COUNT))
2177 xfs_icsb_lock_all_counters(mp);
2178
2179 for_each_online_cpu(i) {
2180 cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i);
2181 cnt->icsb_icount += cntp->icsb_icount;
2182 cnt->icsb_ifree += cntp->icsb_ifree;
2183 cnt->icsb_fdblocks += cntp->icsb_fdblocks;
2184 }
2185
2186 if (!(flags & XFS_ICSB_LAZY_COUNT))
2187 xfs_icsb_unlock_all_counters(mp);
2188}
2189
2190STATIC int
2191xfs_icsb_counter_disabled(
2192 xfs_mount_t *mp,
2193 xfs_sb_field_t field)
2194{
2195 ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
2196 return test_bit(field, &mp->m_icsb_counters);
2197}
2198
2199STATIC void
2200xfs_icsb_disable_counter(
2201 xfs_mount_t *mp,
2202 xfs_sb_field_t field)
2203{
2204 xfs_icsb_cnts_t cnt;
2205
2206 ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216 if (xfs_icsb_counter_disabled(mp, field))
2217 return;
2218
2219 xfs_icsb_lock_all_counters(mp);
2220 if (!test_and_set_bit(field, &mp->m_icsb_counters)) {
2221
2222
2223 xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT);
2224 switch(field) {
2225 case XFS_SBS_ICOUNT:
2226 mp->m_sb.sb_icount = cnt.icsb_icount;
2227 break;
2228 case XFS_SBS_IFREE:
2229 mp->m_sb.sb_ifree = cnt.icsb_ifree;
2230 break;
2231 case XFS_SBS_FDBLOCKS:
2232 mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
2233 break;
2234 default:
2235 BUG();
2236 }
2237 }
2238
2239 xfs_icsb_unlock_all_counters(mp);
2240}
2241
2242STATIC void
2243xfs_icsb_enable_counter(
2244 xfs_mount_t *mp,
2245 xfs_sb_field_t field,
2246 uint64_t count,
2247 uint64_t resid)
2248{
2249 xfs_icsb_cnts_t *cntp;
2250 int i;
2251
2252 ASSERT((field >= XFS_SBS_ICOUNT) && (field <= XFS_SBS_FDBLOCKS));
2253
2254 xfs_icsb_lock_all_counters(mp);
2255 for_each_online_cpu(i) {
2256 cntp = per_cpu_ptr(mp->m_sb_cnts, i);
2257 switch (field) {
2258 case XFS_SBS_ICOUNT:
2259 cntp->icsb_icount = count + resid;
2260 break;
2261 case XFS_SBS_IFREE:
2262 cntp->icsb_ifree = count + resid;
2263 break;
2264 case XFS_SBS_FDBLOCKS:
2265 cntp->icsb_fdblocks = count + resid;
2266 break;
2267 default:
2268 BUG();
2269 break;
2270 }
2271 resid = 0;
2272 }
2273 clear_bit(field, &mp->m_icsb_counters);
2274 xfs_icsb_unlock_all_counters(mp);
2275}
2276
2277void
2278xfs_icsb_sync_counters_locked(
2279 xfs_mount_t *mp,
2280 int flags)
2281{
2282 xfs_icsb_cnts_t cnt;
2283
2284 xfs_icsb_count(mp, &cnt, flags);
2285
2286 if (!xfs_icsb_counter_disabled(mp, XFS_SBS_ICOUNT))
2287 mp->m_sb.sb_icount = cnt.icsb_icount;
2288 if (!xfs_icsb_counter_disabled(mp, XFS_SBS_IFREE))
2289 mp->m_sb.sb_ifree = cnt.icsb_ifree;
2290 if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS))
2291 mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks;
2292}
2293
2294
2295
2296
2297void
2298xfs_icsb_sync_counters(
2299 xfs_mount_t *mp,
2300 int flags)
2301{
2302 spin_lock(&mp->m_sb_lock);
2303 xfs_icsb_sync_counters_locked(mp, flags);
2304 spin_unlock(&mp->m_sb_lock);
2305}
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323#define XFS_ICSB_INO_CNTR_REENABLE (uint64_t)64
2324#define XFS_ICSB_FDBLK_CNTR_REENABLE(mp) \
2325 (uint64_t)(512 + XFS_ALLOC_SET_ASIDE(mp))
2326STATIC void
2327xfs_icsb_balance_counter_locked(
2328 xfs_mount_t *mp,
2329 xfs_sb_field_t field,
2330 int min_per_cpu)
2331{
2332 uint64_t count, resid;
2333 int weight = num_online_cpus();
2334 uint64_t min = (uint64_t)min_per_cpu;
2335
2336
2337 xfs_icsb_disable_counter(mp, field);
2338
2339
2340 switch (field) {
2341 case XFS_SBS_ICOUNT:
2342 count = mp->m_sb.sb_icount;
2343 resid = do_div(count, weight);
2344 if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
2345 return;
2346 break;
2347 case XFS_SBS_IFREE:
2348 count = mp->m_sb.sb_ifree;
2349 resid = do_div(count, weight);
2350 if (count < max(min, XFS_ICSB_INO_CNTR_REENABLE))
2351 return;
2352 break;
2353 case XFS_SBS_FDBLOCKS:
2354 count = mp->m_sb.sb_fdblocks;
2355 resid = do_div(count, weight);
2356 if (count < max(min, XFS_ICSB_FDBLK_CNTR_REENABLE(mp)))
2357 return;
2358 break;
2359 default:
2360 BUG();
2361 count = resid = 0;
2362 break;
2363 }
2364
2365 xfs_icsb_enable_counter(mp, field, count, resid);
2366}
2367
2368STATIC void
2369xfs_icsb_balance_counter(
2370 xfs_mount_t *mp,
2371 xfs_sb_field_t fields,
2372 int min_per_cpu)
2373{
2374 spin_lock(&mp->m_sb_lock);
2375 xfs_icsb_balance_counter_locked(mp, fields, min_per_cpu);
2376 spin_unlock(&mp->m_sb_lock);
2377}
2378
2379int
2380xfs_icsb_modify_counters(
2381 xfs_mount_t *mp,
2382 xfs_sb_field_t field,
2383 int64_t delta,
2384 int rsvd)
2385{
2386 xfs_icsb_cnts_t *icsbp;
2387 long long lcounter;
2388 int ret = 0;
2389
2390 might_sleep();
2391again:
2392 preempt_disable();
2393 icsbp = this_cpu_ptr(mp->m_sb_cnts);
2394
2395
2396
2397
2398 if (unlikely(xfs_icsb_counter_disabled(mp, field)))
2399 goto slow_path;
2400 xfs_icsb_lock_cntr(icsbp);
2401 if (unlikely(xfs_icsb_counter_disabled(mp, field))) {
2402 xfs_icsb_unlock_cntr(icsbp);
2403 goto slow_path;
2404 }
2405
2406 switch (field) {
2407 case XFS_SBS_ICOUNT:
2408 lcounter = icsbp->icsb_icount;
2409 lcounter += delta;
2410 if (unlikely(lcounter < 0))
2411 goto balance_counter;
2412 icsbp->icsb_icount = lcounter;
2413 break;
2414
2415 case XFS_SBS_IFREE:
2416 lcounter = icsbp->icsb_ifree;
2417 lcounter += delta;
2418 if (unlikely(lcounter < 0))
2419 goto balance_counter;
2420 icsbp->icsb_ifree = lcounter;
2421 break;
2422
2423 case XFS_SBS_FDBLOCKS:
2424 BUG_ON((mp->m_resblks - mp->m_resblks_avail) != 0);
2425
2426 lcounter = icsbp->icsb_fdblocks - XFS_ALLOC_SET_ASIDE(mp);
2427 lcounter += delta;
2428 if (unlikely(lcounter < 0))
2429 goto balance_counter;
2430 icsbp->icsb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
2431 break;
2432 default:
2433 BUG();
2434 break;
2435 }
2436 xfs_icsb_unlock_cntr(icsbp);
2437 preempt_enable();
2438 return 0;
2439
2440slow_path:
2441 preempt_enable();
2442
2443
2444
2445
2446
2447
2448 xfs_icsb_lock(mp);
2449
2450
2451
2452
2453
2454
2455
2456 if (!(xfs_icsb_counter_disabled(mp, field))) {
2457 xfs_icsb_unlock(mp);
2458 goto again;
2459 }
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472 spin_lock(&mp->m_sb_lock);
2473 ret = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd);
2474 spin_unlock(&mp->m_sb_lock);
2475
2476
2477
2478
2479
2480
2481
2482 if (ret != ENOSPC)
2483 xfs_icsb_balance_counter(mp, field, 0);
2484 xfs_icsb_unlock(mp);
2485 return ret;
2486
2487balance_counter:
2488 xfs_icsb_unlock_cntr(icsbp);
2489 preempt_enable();
2490
2491
2492
2493
2494
2495
2496
2497 xfs_icsb_lock(mp);
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507 xfs_icsb_balance_counter(mp, field, delta);
2508 xfs_icsb_unlock(mp);
2509 goto again;
2510}
2511
2512#endif
2513