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