diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /fs/xfs/xfs_mount.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r-- | fs/xfs/xfs_mount.c | 470 |
1 files changed, 216 insertions, 254 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index aeb9d72ebf6e..b49b82363d20 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -52,16 +52,11 @@ STATIC void xfs_icsb_balance_counter(xfs_mount_t *, xfs_sb_field_t, | |||
52 | int); | 52 | int); |
53 | STATIC void xfs_icsb_balance_counter_locked(xfs_mount_t *, xfs_sb_field_t, | 53 | STATIC void xfs_icsb_balance_counter_locked(xfs_mount_t *, xfs_sb_field_t, |
54 | int); | 54 | int); |
55 | STATIC int xfs_icsb_modify_counters(xfs_mount_t *, xfs_sb_field_t, | ||
56 | int64_t, int); | ||
57 | STATIC void xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t); | 55 | STATIC void xfs_icsb_disable_counter(xfs_mount_t *, xfs_sb_field_t); |
58 | |||
59 | #else | 56 | #else |
60 | 57 | ||
61 | #define xfs_icsb_balance_counter(mp, a, b) do { } while (0) | 58 | #define xfs_icsb_balance_counter(mp, a, b) do { } while (0) |
62 | #define xfs_icsb_balance_counter_locked(mp, a, b) do { } while (0) | 59 | #define xfs_icsb_balance_counter_locked(mp, a, b) do { } while (0) |
63 | #define xfs_icsb_modify_counters(mp, a, b, c) do { } while (0) | ||
64 | |||
65 | #endif | 60 | #endif |
66 | 61 | ||
67 | static const struct { | 62 | static const struct { |
@@ -138,9 +133,7 @@ xfs_uuid_mount( | |||
138 | return 0; | 133 | return 0; |
139 | 134 | ||
140 | if (uuid_is_nil(uuid)) { | 135 | if (uuid_is_nil(uuid)) { |
141 | cmn_err(CE_WARN, | 136 | xfs_warn(mp, "Filesystem has nil UUID - can't mount"); |
142 | "XFS: Filesystem %s has nil UUID - can't mount", | ||
143 | mp->m_fsname); | ||
144 | return XFS_ERROR(EINVAL); | 137 | return XFS_ERROR(EINVAL); |
145 | } | 138 | } |
146 | 139 | ||
@@ -168,8 +161,7 @@ xfs_uuid_mount( | |||
168 | 161 | ||
169 | out_duplicate: | 162 | out_duplicate: |
170 | mutex_unlock(&xfs_uuid_table_mutex); | 163 | mutex_unlock(&xfs_uuid_table_mutex); |
171 | cmn_err(CE_WARN, "XFS: Filesystem %s has duplicate UUID - can't mount", | 164 | xfs_warn(mp, "Filesystem has duplicate UUID - can't mount"); |
172 | mp->m_fsname); | ||
173 | return XFS_ERROR(EINVAL); | 165 | return XFS_ERROR(EINVAL); |
174 | } | 166 | } |
175 | 167 | ||
@@ -199,6 +191,8 @@ xfs_uuid_unmount( | |||
199 | 191 | ||
200 | /* | 192 | /* |
201 | * Reference counting access wrappers to the perag structures. | 193 | * Reference counting access wrappers to the perag structures. |
194 | * Because we never free per-ag structures, the only thing we | ||
195 | * have to protect against changes is the tree structure itself. | ||
202 | */ | 196 | */ |
203 | struct xfs_perag * | 197 | struct xfs_perag * |
204 | xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno) | 198 | xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno) |
@@ -206,19 +200,43 @@ xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno) | |||
206 | struct xfs_perag *pag; | 200 | struct xfs_perag *pag; |
207 | int ref = 0; | 201 | int ref = 0; |
208 | 202 | ||
209 | spin_lock(&mp->m_perag_lock); | 203 | rcu_read_lock(); |
210 | pag = radix_tree_lookup(&mp->m_perag_tree, agno); | 204 | pag = radix_tree_lookup(&mp->m_perag_tree, agno); |
211 | if (pag) { | 205 | if (pag) { |
212 | ASSERT(atomic_read(&pag->pag_ref) >= 0); | 206 | ASSERT(atomic_read(&pag->pag_ref) >= 0); |
213 | /* catch leaks in the positive direction during testing */ | ||
214 | ASSERT(atomic_read(&pag->pag_ref) < 1000); | ||
215 | ref = atomic_inc_return(&pag->pag_ref); | 207 | ref = atomic_inc_return(&pag->pag_ref); |
216 | } | 208 | } |
217 | spin_unlock(&mp->m_perag_lock); | 209 | rcu_read_unlock(); |
218 | trace_xfs_perag_get(mp, agno, ref, _RET_IP_); | 210 | trace_xfs_perag_get(mp, agno, ref, _RET_IP_); |
219 | return pag; | 211 | return pag; |
220 | } | 212 | } |
221 | 213 | ||
214 | /* | ||
215 | * search from @first to find the next perag with the given tag set. | ||
216 | */ | ||
217 | struct xfs_perag * | ||
218 | xfs_perag_get_tag( | ||
219 | struct xfs_mount *mp, | ||
220 | xfs_agnumber_t first, | ||
221 | int tag) | ||
222 | { | ||
223 | struct xfs_perag *pag; | ||
224 | int found; | ||
225 | int ref; | ||
226 | |||
227 | rcu_read_lock(); | ||
228 | found = radix_tree_gang_lookup_tag(&mp->m_perag_tree, | ||
229 | (void **)&pag, first, 1, tag); | ||
230 | if (found <= 0) { | ||
231 | rcu_read_unlock(); | ||
232 | return NULL; | ||
233 | } | ||
234 | ref = atomic_inc_return(&pag->pag_ref); | ||
235 | rcu_read_unlock(); | ||
236 | trace_xfs_perag_get_tag(mp, pag->pag_agno, ref, _RET_IP_); | ||
237 | return pag; | ||
238 | } | ||
239 | |||
222 | void | 240 | void |
223 | xfs_perag_put(struct xfs_perag *pag) | 241 | xfs_perag_put(struct xfs_perag *pag) |
224 | { | 242 | { |
@@ -229,10 +247,18 @@ xfs_perag_put(struct xfs_perag *pag) | |||
229 | trace_xfs_perag_put(pag->pag_mount, pag->pag_agno, ref, _RET_IP_); | 247 | trace_xfs_perag_put(pag->pag_mount, pag->pag_agno, ref, _RET_IP_); |
230 | } | 248 | } |
231 | 249 | ||
250 | STATIC void | ||
251 | __xfs_free_perag( | ||
252 | struct rcu_head *head) | ||
253 | { | ||
254 | struct xfs_perag *pag = container_of(head, struct xfs_perag, rcu_head); | ||
255 | |||
256 | ASSERT(atomic_read(&pag->pag_ref) == 0); | ||
257 | kmem_free(pag); | ||
258 | } | ||
259 | |||
232 | /* | 260 | /* |
233 | * Free up the resources associated with a mount structure. Assume that | 261 | * Free up the per-ag resources associated with the mount structure. |
234 | * the structure was initially zeroed, so we can tell which fields got | ||
235 | * initialized. | ||
236 | */ | 262 | */ |
237 | STATIC void | 263 | STATIC void |
238 | xfs_free_perag( | 264 | xfs_free_perag( |
@@ -244,10 +270,10 @@ xfs_free_perag( | |||
244 | for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { | 270 | for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { |
245 | spin_lock(&mp->m_perag_lock); | 271 | spin_lock(&mp->m_perag_lock); |
246 | pag = radix_tree_delete(&mp->m_perag_tree, agno); | 272 | pag = radix_tree_delete(&mp->m_perag_tree, agno); |
273 | spin_unlock(&mp->m_perag_lock); | ||
247 | ASSERT(pag); | 274 | ASSERT(pag); |
248 | ASSERT(atomic_read(&pag->pag_ref) == 0); | 275 | ASSERT(atomic_read(&pag->pag_ref) == 0); |
249 | spin_unlock(&mp->m_perag_lock); | 276 | call_rcu(&pag->rcu_head, __xfs_free_perag); |
250 | kmem_free(pag); | ||
251 | } | 277 | } |
252 | } | 278 | } |
253 | 279 | ||
@@ -282,6 +308,8 @@ xfs_mount_validate_sb( | |||
282 | xfs_sb_t *sbp, | 308 | xfs_sb_t *sbp, |
283 | int flags) | 309 | int flags) |
284 | { | 310 | { |
311 | int loud = !(flags & XFS_MFSI_QUIET); | ||
312 | |||
285 | /* | 313 | /* |
286 | * If the log device and data device have the | 314 | * If the log device and data device have the |
287 | * same device number, the log is internal. | 315 | * same device number, the log is internal. |
@@ -290,28 +318,32 @@ xfs_mount_validate_sb( | |||
290 | * a volume filesystem in a non-volume manner. | 318 | * a volume filesystem in a non-volume manner. |
291 | */ | 319 | */ |
292 | if (sbp->sb_magicnum != XFS_SB_MAGIC) { | 320 | if (sbp->sb_magicnum != XFS_SB_MAGIC) { |
293 | xfs_fs_mount_cmn_err(flags, "bad magic number"); | 321 | if (loud) |
322 | xfs_warn(mp, "bad magic number"); | ||
294 | return XFS_ERROR(EWRONGFS); | 323 | return XFS_ERROR(EWRONGFS); |
295 | } | 324 | } |
296 | 325 | ||
297 | if (!xfs_sb_good_version(sbp)) { | 326 | if (!xfs_sb_good_version(sbp)) { |
298 | xfs_fs_mount_cmn_err(flags, "bad version"); | 327 | if (loud) |
328 | xfs_warn(mp, "bad version"); | ||
299 | return XFS_ERROR(EWRONGFS); | 329 | return XFS_ERROR(EWRONGFS); |
300 | } | 330 | } |
301 | 331 | ||
302 | if (unlikely( | 332 | if (unlikely( |
303 | sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) { | 333 | sbp->sb_logstart == 0 && mp->m_logdev_targp == mp->m_ddev_targp)) { |
304 | xfs_fs_mount_cmn_err(flags, | 334 | if (loud) |
305 | "filesystem is marked as having an external log; " | 335 | xfs_warn(mp, |
306 | "specify logdev on the\nmount command line."); | 336 | "filesystem is marked as having an external log; " |
337 | "specify logdev on the mount command line."); | ||
307 | return XFS_ERROR(EINVAL); | 338 | return XFS_ERROR(EINVAL); |
308 | } | 339 | } |
309 | 340 | ||
310 | if (unlikely( | 341 | if (unlikely( |
311 | sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) { | 342 | sbp->sb_logstart != 0 && mp->m_logdev_targp != mp->m_ddev_targp)) { |
312 | xfs_fs_mount_cmn_err(flags, | 343 | if (loud) |
313 | "filesystem is marked as having an internal log; " | 344 | xfs_warn(mp, |
314 | "do not specify logdev on\nthe mount command line."); | 345 | "filesystem is marked as having an internal log; " |
346 | "do not specify logdev on the mount command line."); | ||
315 | return XFS_ERROR(EINVAL); | 347 | return XFS_ERROR(EINVAL); |
316 | } | 348 | } |
317 | 349 | ||
@@ -340,7 +372,8 @@ xfs_mount_validate_sb( | |||
340 | (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) || | 372 | (sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) || |
341 | (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) || | 373 | (sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) || |
342 | (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */))) { | 374 | (sbp->sb_imax_pct > 100 /* zero sb_imax_pct is valid */))) { |
343 | xfs_fs_mount_cmn_err(flags, "SB sanity check 1 failed"); | 375 | if (loud) |
376 | xfs_warn(mp, "SB sanity check 1 failed"); | ||
344 | return XFS_ERROR(EFSCORRUPTED); | 377 | return XFS_ERROR(EFSCORRUPTED); |
345 | } | 378 | } |
346 | 379 | ||
@@ -353,7 +386,8 @@ xfs_mount_validate_sb( | |||
353 | (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks || | 386 | (xfs_drfsbno_t)sbp->sb_agcount * sbp->sb_agblocks || |
354 | sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) * | 387 | sbp->sb_dblocks < (xfs_drfsbno_t)(sbp->sb_agcount - 1) * |
355 | sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) { | 388 | sbp->sb_agblocks + XFS_MIN_AG_BLOCKS)) { |
356 | xfs_fs_mount_cmn_err(flags, "SB sanity check 2 failed"); | 389 | if (loud) |
390 | xfs_warn(mp, "SB sanity check 2 failed"); | ||
357 | return XFS_ERROR(EFSCORRUPTED); | 391 | return XFS_ERROR(EFSCORRUPTED); |
358 | } | 392 | } |
359 | 393 | ||
@@ -361,12 +395,12 @@ xfs_mount_validate_sb( | |||
361 | * Until this is fixed only page-sized or smaller data blocks work. | 395 | * Until this is fixed only page-sized or smaller data blocks work. |
362 | */ | 396 | */ |
363 | if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) { | 397 | if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) { |
364 | xfs_fs_mount_cmn_err(flags, | 398 | if (loud) { |
365 | "file system with blocksize %d bytes", | 399 | xfs_warn(mp, |
366 | sbp->sb_blocksize); | 400 | "File system with blocksize %d bytes. " |
367 | xfs_fs_mount_cmn_err(flags, | 401 | "Only pagesize (%ld) or less will currently work.", |
368 | "only pagesize (%ld) or less will currently work.", | 402 | sbp->sb_blocksize, PAGE_SIZE); |
369 | PAGE_SIZE); | 403 | } |
370 | return XFS_ERROR(ENOSYS); | 404 | return XFS_ERROR(ENOSYS); |
371 | } | 405 | } |
372 | 406 | ||
@@ -380,21 +414,23 @@ xfs_mount_validate_sb( | |||
380 | case 2048: | 414 | case 2048: |
381 | break; | 415 | break; |
382 | default: | 416 | default: |
383 | xfs_fs_mount_cmn_err(flags, | 417 | if (loud) |
384 | "inode size of %d bytes not supported", | 418 | xfs_warn(mp, "inode size of %d bytes not supported", |
385 | sbp->sb_inodesize); | 419 | sbp->sb_inodesize); |
386 | return XFS_ERROR(ENOSYS); | 420 | return XFS_ERROR(ENOSYS); |
387 | } | 421 | } |
388 | 422 | ||
389 | if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) || | 423 | if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) || |
390 | xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) { | 424 | xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) { |
391 | xfs_fs_mount_cmn_err(flags, | 425 | if (loud) |
392 | "file system too large to be mounted on this system."); | 426 | xfs_warn(mp, |
427 | "file system too large to be mounted on this system."); | ||
393 | return XFS_ERROR(EFBIG); | 428 | return XFS_ERROR(EFBIG); |
394 | } | 429 | } |
395 | 430 | ||
396 | if (unlikely(sbp->sb_inprogress)) { | 431 | if (unlikely(sbp->sb_inprogress)) { |
397 | xfs_fs_mount_cmn_err(flags, "file system busy"); | 432 | if (loud) |
433 | xfs_warn(mp, "file system busy"); | ||
398 | return XFS_ERROR(EFSCORRUPTED); | 434 | return XFS_ERROR(EFSCORRUPTED); |
399 | } | 435 | } |
400 | 436 | ||
@@ -402,8 +438,9 @@ xfs_mount_validate_sb( | |||
402 | * Version 1 directory format has never worked on Linux. | 438 | * Version 1 directory format has never worked on Linux. |
403 | */ | 439 | */ |
404 | if (unlikely(!xfs_sb_version_hasdirv2(sbp))) { | 440 | if (unlikely(!xfs_sb_version_hasdirv2(sbp))) { |
405 | xfs_fs_mount_cmn_err(flags, | 441 | if (loud) |
406 | "file system using version 1 directory format"); | 442 | xfs_warn(mp, |
443 | "file system using version 1 directory format"); | ||
407 | return XFS_ERROR(ENOSYS); | 444 | return XFS_ERROR(ENOSYS); |
408 | } | 445 | } |
409 | 446 | ||
@@ -443,8 +480,11 @@ xfs_initialize_perag( | |||
443 | goto out_unwind; | 480 | goto out_unwind; |
444 | pag->pag_agno = index; | 481 | pag->pag_agno = index; |
445 | pag->pag_mount = mp; | 482 | pag->pag_mount = mp; |
446 | rwlock_init(&pag->pag_ici_lock); | 483 | spin_lock_init(&pag->pag_ici_lock); |
484 | mutex_init(&pag->pag_ici_reclaim_lock); | ||
447 | INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC); | 485 | INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC); |
486 | spin_lock_init(&pag->pag_buf_lock); | ||
487 | pag->pag_buf_tree = RB_ROOT; | ||
448 | 488 | ||
449 | if (radix_tree_preload(GFP_NOFS)) | 489 | if (radix_tree_preload(GFP_NOFS)) |
450 | goto out_unwind; | 490 | goto out_unwind; |
@@ -639,9 +679,9 @@ int | |||
639 | xfs_readsb(xfs_mount_t *mp, int flags) | 679 | xfs_readsb(xfs_mount_t *mp, int flags) |
640 | { | 680 | { |
641 | unsigned int sector_size; | 681 | unsigned int sector_size; |
642 | unsigned int extra_flags; | ||
643 | xfs_buf_t *bp; | 682 | xfs_buf_t *bp; |
644 | int error; | 683 | int error; |
684 | int loud = !(flags & XFS_MFSI_QUIET); | ||
645 | 685 | ||
646 | ASSERT(mp->m_sb_bp == NULL); | 686 | ASSERT(mp->m_sb_bp == NULL); |
647 | ASSERT(mp->m_ddev_targp != NULL); | 687 | ASSERT(mp->m_ddev_targp != NULL); |
@@ -652,39 +692,37 @@ xfs_readsb(xfs_mount_t *mp, int flags) | |||
652 | * access to the superblock. | 692 | * access to the superblock. |
653 | */ | 693 | */ |
654 | sector_size = xfs_getsize_buftarg(mp->m_ddev_targp); | 694 | sector_size = xfs_getsize_buftarg(mp->m_ddev_targp); |
655 | extra_flags = XBF_LOCK | XBF_FS_MANAGED | XBF_MAPPED; | ||
656 | 695 | ||
657 | bp = xfs_buf_read(mp->m_ddev_targp, XFS_SB_DADDR, BTOBB(sector_size), | 696 | reread: |
658 | extra_flags); | 697 | bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp, |
659 | if (!bp || XFS_BUF_ISERROR(bp)) { | 698 | XFS_SB_DADDR, sector_size, 0); |
660 | xfs_fs_mount_cmn_err(flags, "SB read failed"); | 699 | if (!bp) { |
661 | error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM; | 700 | if (loud) |
662 | goto fail; | 701 | xfs_warn(mp, "SB buffer read failed"); |
702 | return EIO; | ||
663 | } | 703 | } |
664 | ASSERT(XFS_BUF_ISBUSY(bp)); | ||
665 | ASSERT(XFS_BUF_VALUSEMA(bp) <= 0); | ||
666 | 704 | ||
667 | /* | 705 | /* |
668 | * Initialize the mount structure from the superblock. | 706 | * Initialize the mount structure from the superblock. |
669 | * But first do some basic consistency checking. | 707 | * But first do some basic consistency checking. |
670 | */ | 708 | */ |
671 | xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp)); | 709 | xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp)); |
672 | |||
673 | error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags); | 710 | error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags); |
674 | if (error) { | 711 | if (error) { |
675 | xfs_fs_mount_cmn_err(flags, "SB validate failed"); | 712 | if (loud) |
676 | goto fail; | 713 | xfs_warn(mp, "SB validate failed"); |
714 | goto release_buf; | ||
677 | } | 715 | } |
678 | 716 | ||
679 | /* | 717 | /* |
680 | * We must be able to do sector-sized and sector-aligned IO. | 718 | * We must be able to do sector-sized and sector-aligned IO. |
681 | */ | 719 | */ |
682 | if (sector_size > mp->m_sb.sb_sectsize) { | 720 | if (sector_size > mp->m_sb.sb_sectsize) { |
683 | xfs_fs_mount_cmn_err(flags, | 721 | if (loud) |
684 | "device supports only %u byte sectors (not %u)", | 722 | xfs_warn(mp, "device supports %u byte sectors (not %u)", |
685 | sector_size, mp->m_sb.sb_sectsize); | 723 | sector_size, mp->m_sb.sb_sectsize); |
686 | error = ENOSYS; | 724 | error = ENOSYS; |
687 | goto fail; | 725 | goto release_buf; |
688 | } | 726 | } |
689 | 727 | ||
690 | /* | 728 | /* |
@@ -692,33 +730,20 @@ xfs_readsb(xfs_mount_t *mp, int flags) | |||
692 | * re-read the superblock so the buffer is correctly sized. | 730 | * re-read the superblock so the buffer is correctly sized. |
693 | */ | 731 | */ |
694 | if (sector_size < mp->m_sb.sb_sectsize) { | 732 | if (sector_size < mp->m_sb.sb_sectsize) { |
695 | XFS_BUF_UNMANAGE(bp); | ||
696 | xfs_buf_relse(bp); | 733 | xfs_buf_relse(bp); |
697 | sector_size = mp->m_sb.sb_sectsize; | 734 | sector_size = mp->m_sb.sb_sectsize; |
698 | bp = xfs_buf_read(mp->m_ddev_targp, XFS_SB_DADDR, | 735 | goto reread; |
699 | BTOBB(sector_size), extra_flags); | ||
700 | if (!bp || XFS_BUF_ISERROR(bp)) { | ||
701 | xfs_fs_mount_cmn_err(flags, "SB re-read failed"); | ||
702 | error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM; | ||
703 | goto fail; | ||
704 | } | ||
705 | ASSERT(XFS_BUF_ISBUSY(bp)); | ||
706 | ASSERT(XFS_BUF_VALUSEMA(bp) <= 0); | ||
707 | } | 736 | } |
708 | 737 | ||
709 | /* Initialize per-cpu counters */ | 738 | /* Initialize per-cpu counters */ |
710 | xfs_icsb_reinit_counters(mp); | 739 | xfs_icsb_reinit_counters(mp); |
711 | 740 | ||
712 | mp->m_sb_bp = bp; | 741 | mp->m_sb_bp = bp; |
713 | xfs_buf_relse(bp); | 742 | xfs_buf_unlock(bp); |
714 | ASSERT(XFS_BUF_VALUSEMA(bp) > 0); | ||
715 | return 0; | 743 | return 0; |
716 | 744 | ||
717 | fail: | 745 | release_buf: |
718 | if (bp) { | 746 | xfs_buf_relse(bp); |
719 | XFS_BUF_UNMANAGE(bp); | ||
720 | xfs_buf_relse(bp); | ||
721 | } | ||
722 | return error; | 747 | return error; |
723 | } | 748 | } |
724 | 749 | ||
@@ -839,8 +864,7 @@ xfs_update_alignment(xfs_mount_t *mp) | |||
839 | if ((BBTOB(mp->m_dalign) & mp->m_blockmask) || | 864 | if ((BBTOB(mp->m_dalign) & mp->m_blockmask) || |
840 | (BBTOB(mp->m_swidth) & mp->m_blockmask)) { | 865 | (BBTOB(mp->m_swidth) & mp->m_blockmask)) { |
841 | if (mp->m_flags & XFS_MOUNT_RETERR) { | 866 | if (mp->m_flags & XFS_MOUNT_RETERR) { |
842 | cmn_err(CE_WARN, | 867 | xfs_warn(mp, "alignment check 1 failed"); |
843 | "XFS: alignment check 1 failed"); | ||
844 | return XFS_ERROR(EINVAL); | 868 | return XFS_ERROR(EINVAL); |
845 | } | 869 | } |
846 | mp->m_dalign = mp->m_swidth = 0; | 870 | mp->m_dalign = mp->m_swidth = 0; |
@@ -853,8 +877,9 @@ xfs_update_alignment(xfs_mount_t *mp) | |||
853 | if (mp->m_flags & XFS_MOUNT_RETERR) { | 877 | if (mp->m_flags & XFS_MOUNT_RETERR) { |
854 | return XFS_ERROR(EINVAL); | 878 | return XFS_ERROR(EINVAL); |
855 | } | 879 | } |
856 | xfs_fs_cmn_err(CE_WARN, mp, | 880 | xfs_warn(mp, |
857 | "stripe alignment turned off: sunit(%d)/swidth(%d) incompatible with agsize(%d)", | 881 | "stripe alignment turned off: sunit(%d)/swidth(%d) " |
882 | "incompatible with agsize(%d)", | ||
858 | mp->m_dalign, mp->m_swidth, | 883 | mp->m_dalign, mp->m_swidth, |
859 | sbp->sb_agblocks); | 884 | sbp->sb_agblocks); |
860 | 885 | ||
@@ -864,9 +889,9 @@ xfs_update_alignment(xfs_mount_t *mp) | |||
864 | mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth); | 889 | mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth); |
865 | } else { | 890 | } else { |
866 | if (mp->m_flags & XFS_MOUNT_RETERR) { | 891 | if (mp->m_flags & XFS_MOUNT_RETERR) { |
867 | xfs_fs_cmn_err(CE_WARN, mp, | 892 | xfs_warn(mp, |
868 | "stripe alignment turned off: sunit(%d) less than bsize(%d)", | 893 | "stripe alignment turned off: sunit(%d) less than bsize(%d)", |
869 | mp->m_dalign, | 894 | mp->m_dalign, |
870 | mp->m_blockmask +1); | 895 | mp->m_blockmask +1); |
871 | return XFS_ERROR(EINVAL); | 896 | return XFS_ERROR(EINVAL); |
872 | } | 897 | } |
@@ -961,6 +986,24 @@ xfs_set_rw_sizes(xfs_mount_t *mp) | |||
961 | } | 986 | } |
962 | 987 | ||
963 | /* | 988 | /* |
989 | * precalculate the low space thresholds for dynamic speculative preallocation. | ||
990 | */ | ||
991 | void | ||
992 | xfs_set_low_space_thresholds( | ||
993 | struct xfs_mount *mp) | ||
994 | { | ||
995 | int i; | ||
996 | |||
997 | for (i = 0; i < XFS_LOWSP_MAX; i++) { | ||
998 | __uint64_t space = mp->m_sb.sb_dblocks; | ||
999 | |||
1000 | do_div(space, 100); | ||
1001 | mp->m_low_space[i] = space * (i + 1); | ||
1002 | } | ||
1003 | } | ||
1004 | |||
1005 | |||
1006 | /* | ||
964 | * Set whether we're using inode alignment. | 1007 | * Set whether we're using inode alignment. |
965 | */ | 1008 | */ |
966 | STATIC void | 1009 | STATIC void |
@@ -991,42 +1034,35 @@ xfs_check_sizes(xfs_mount_t *mp) | |||
991 | { | 1034 | { |
992 | xfs_buf_t *bp; | 1035 | xfs_buf_t *bp; |
993 | xfs_daddr_t d; | 1036 | xfs_daddr_t d; |
994 | int error; | ||
995 | 1037 | ||
996 | d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks); | 1038 | d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks); |
997 | if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) { | 1039 | if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) { |
998 | cmn_err(CE_WARN, "XFS: size check 1 failed"); | 1040 | xfs_warn(mp, "filesystem size mismatch detected"); |
999 | return XFS_ERROR(EFBIG); | 1041 | return XFS_ERROR(EFBIG); |
1000 | } | 1042 | } |
1001 | error = xfs_read_buf(mp, mp->m_ddev_targp, | 1043 | bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp, |
1002 | d - XFS_FSS_TO_BB(mp, 1), | 1044 | d - XFS_FSS_TO_BB(mp, 1), |
1003 | XFS_FSS_TO_BB(mp, 1), 0, &bp); | 1045 | BBTOB(XFS_FSS_TO_BB(mp, 1)), 0); |
1004 | if (!error) { | 1046 | if (!bp) { |
1005 | xfs_buf_relse(bp); | 1047 | xfs_warn(mp, "last sector read failed"); |
1006 | } else { | 1048 | return EIO; |
1007 | cmn_err(CE_WARN, "XFS: size check 2 failed"); | ||
1008 | if (error == ENOSPC) | ||
1009 | error = XFS_ERROR(EFBIG); | ||
1010 | return error; | ||
1011 | } | 1049 | } |
1050 | xfs_buf_relse(bp); | ||
1012 | 1051 | ||
1013 | if (mp->m_logdev_targp != mp->m_ddev_targp) { | 1052 | if (mp->m_logdev_targp != mp->m_ddev_targp) { |
1014 | d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); | 1053 | d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); |
1015 | if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) { | 1054 | if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) { |
1016 | cmn_err(CE_WARN, "XFS: size check 3 failed"); | 1055 | xfs_warn(mp, "log size mismatch detected"); |
1017 | return XFS_ERROR(EFBIG); | 1056 | return XFS_ERROR(EFBIG); |
1018 | } | 1057 | } |
1019 | error = xfs_read_buf(mp, mp->m_logdev_targp, | 1058 | bp = xfs_buf_read_uncached(mp, mp->m_logdev_targp, |
1020 | d - XFS_FSB_TO_BB(mp, 1), | 1059 | d - XFS_FSB_TO_BB(mp, 1), |
1021 | XFS_FSB_TO_BB(mp, 1), 0, &bp); | 1060 | XFS_FSB_TO_B(mp, 1), 0); |
1022 | if (!error) { | 1061 | if (!bp) { |
1023 | xfs_buf_relse(bp); | 1062 | xfs_warn(mp, "log device read failed"); |
1024 | } else { | 1063 | return EIO; |
1025 | cmn_err(CE_WARN, "XFS: size check 3 failed"); | ||
1026 | if (error == ENOSPC) | ||
1027 | error = XFS_ERROR(EFBIG); | ||
1028 | return error; | ||
1029 | } | 1064 | } |
1065 | xfs_buf_relse(bp); | ||
1030 | } | 1066 | } |
1031 | return 0; | 1067 | return 0; |
1032 | } | 1068 | } |
@@ -1061,7 +1097,7 @@ xfs_mount_reset_sbqflags( | |||
1061 | return 0; | 1097 | return 0; |
1062 | 1098 | ||
1063 | #ifdef QUOTADEBUG | 1099 | #ifdef QUOTADEBUG |
1064 | xfs_fs_cmn_err(CE_NOTE, mp, "Writing superblock quota changes"); | 1100 | xfs_notice(mp, "Writing superblock quota changes"); |
1065 | #endif | 1101 | #endif |
1066 | 1102 | ||
1067 | tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE); | 1103 | tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE); |
@@ -1069,8 +1105,7 @@ xfs_mount_reset_sbqflags( | |||
1069 | XFS_DEFAULT_LOG_COUNT); | 1105 | XFS_DEFAULT_LOG_COUNT); |
1070 | if (error) { | 1106 | if (error) { |
1071 | xfs_trans_cancel(tp, 0); | 1107 | xfs_trans_cancel(tp, 0); |
1072 | xfs_fs_cmn_err(CE_ALERT, mp, | 1108 | xfs_alert(mp, "%s: Superblock update failed!", __func__); |
1073 | "xfs_mount_reset_sbqflags: Superblock update failed!"); | ||
1074 | return error; | 1109 | return error; |
1075 | } | 1110 | } |
1076 | 1111 | ||
@@ -1136,8 +1171,7 @@ xfs_mountfs( | |||
1136 | * transaction subsystem is online. | 1171 | * transaction subsystem is online. |
1137 | */ | 1172 | */ |
1138 | if (xfs_sb_has_mismatched_features2(sbp)) { | 1173 | if (xfs_sb_has_mismatched_features2(sbp)) { |
1139 | cmn_err(CE_WARN, | 1174 | xfs_warn(mp, "correcting sb_features alignment problem"); |
1140 | "XFS: correcting sb_features alignment problem"); | ||
1141 | sbp->sb_features2 |= sbp->sb_bad_features2; | 1175 | sbp->sb_features2 |= sbp->sb_bad_features2; |
1142 | sbp->sb_bad_features2 = sbp->sb_features2; | 1176 | sbp->sb_bad_features2 = sbp->sb_features2; |
1143 | mp->m_update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2; | 1177 | mp->m_update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2; |
@@ -1189,6 +1223,9 @@ xfs_mountfs( | |||
1189 | */ | 1223 | */ |
1190 | xfs_set_rw_sizes(mp); | 1224 | xfs_set_rw_sizes(mp); |
1191 | 1225 | ||
1226 | /* set the low space thresholds for dynamic preallocation */ | ||
1227 | xfs_set_low_space_thresholds(mp); | ||
1228 | |||
1192 | /* | 1229 | /* |
1193 | * Set the inode cluster size. | 1230 | * Set the inode cluster size. |
1194 | * This may still be overridden by the file system | 1231 | * This may still be overridden by the file system |
@@ -1213,7 +1250,7 @@ xfs_mountfs( | |||
1213 | */ | 1250 | */ |
1214 | error = xfs_rtmount_init(mp); | 1251 | error = xfs_rtmount_init(mp); |
1215 | if (error) { | 1252 | if (error) { |
1216 | cmn_err(CE_WARN, "XFS: RT mount failed"); | 1253 | xfs_warn(mp, "RT mount failed"); |
1217 | goto out_remove_uuid; | 1254 | goto out_remove_uuid; |
1218 | } | 1255 | } |
1219 | 1256 | ||
@@ -1244,12 +1281,12 @@ xfs_mountfs( | |||
1244 | INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC); | 1281 | INIT_RADIX_TREE(&mp->m_perag_tree, GFP_ATOMIC); |
1245 | error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi); | 1282 | error = xfs_initialize_perag(mp, sbp->sb_agcount, &mp->m_maxagi); |
1246 | if (error) { | 1283 | if (error) { |
1247 | cmn_err(CE_WARN, "XFS: Failed per-ag init: %d", error); | 1284 | xfs_warn(mp, "Failed per-ag init: %d", error); |
1248 | goto out_remove_uuid; | 1285 | goto out_remove_uuid; |
1249 | } | 1286 | } |
1250 | 1287 | ||
1251 | if (!sbp->sb_logblocks) { | 1288 | if (!sbp->sb_logblocks) { |
1252 | cmn_err(CE_WARN, "XFS: no log defined"); | 1289 | xfs_warn(mp, "no log defined"); |
1253 | XFS_ERROR_REPORT("xfs_mountfs", XFS_ERRLEVEL_LOW, mp); | 1290 | XFS_ERROR_REPORT("xfs_mountfs", XFS_ERRLEVEL_LOW, mp); |
1254 | error = XFS_ERROR(EFSCORRUPTED); | 1291 | error = XFS_ERROR(EFSCORRUPTED); |
1255 | goto out_free_perag; | 1292 | goto out_free_perag; |
@@ -1262,7 +1299,7 @@ xfs_mountfs( | |||
1262 | XFS_FSB_TO_DADDR(mp, sbp->sb_logstart), | 1299 | XFS_FSB_TO_DADDR(mp, sbp->sb_logstart), |
1263 | XFS_FSB_TO_BB(mp, sbp->sb_logblocks)); | 1300 | XFS_FSB_TO_BB(mp, sbp->sb_logblocks)); |
1264 | if (error) { | 1301 | if (error) { |
1265 | cmn_err(CE_WARN, "XFS: log mount failed"); | 1302 | xfs_warn(mp, "log mount failed"); |
1266 | goto out_free_perag; | 1303 | goto out_free_perag; |
1267 | } | 1304 | } |
1268 | 1305 | ||
@@ -1299,16 +1336,14 @@ xfs_mountfs( | |||
1299 | */ | 1336 | */ |
1300 | error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip); | 1337 | error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip); |
1301 | if (error) { | 1338 | if (error) { |
1302 | cmn_err(CE_WARN, "XFS: failed to read root inode"); | 1339 | xfs_warn(mp, "failed to read root inode"); |
1303 | goto out_log_dealloc; | 1340 | goto out_log_dealloc; |
1304 | } | 1341 | } |
1305 | 1342 | ||
1306 | ASSERT(rip != NULL); | 1343 | ASSERT(rip != NULL); |
1307 | 1344 | ||
1308 | if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) { | 1345 | if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) { |
1309 | cmn_err(CE_WARN, "XFS: corrupted root inode"); | 1346 | xfs_warn(mp, "corrupted root inode %llu: not a directory", |
1310 | cmn_err(CE_WARN, "Device %s - root %llu is not a directory", | ||
1311 | XFS_BUFTARG_NAME(mp->m_ddev_targp), | ||
1312 | (unsigned long long)rip->i_ino); | 1347 | (unsigned long long)rip->i_ino); |
1313 | xfs_iunlock(rip, XFS_ILOCK_EXCL); | 1348 | xfs_iunlock(rip, XFS_ILOCK_EXCL); |
1314 | XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW, | 1349 | XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW, |
@@ -1328,7 +1363,7 @@ xfs_mountfs( | |||
1328 | /* | 1363 | /* |
1329 | * Free up the root inode. | 1364 | * Free up the root inode. |
1330 | */ | 1365 | */ |
1331 | cmn_err(CE_WARN, "XFS: failed to read RT inodes"); | 1366 | xfs_warn(mp, "failed to read RT inodes"); |
1332 | goto out_rele_rip; | 1367 | goto out_rele_rip; |
1333 | } | 1368 | } |
1334 | 1369 | ||
@@ -1340,7 +1375,7 @@ xfs_mountfs( | |||
1340 | if (mp->m_update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) { | 1375 | if (mp->m_update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) { |
1341 | error = xfs_mount_log_sb(mp, mp->m_update_flags); | 1376 | error = xfs_mount_log_sb(mp, mp->m_update_flags); |
1342 | if (error) { | 1377 | if (error) { |
1343 | cmn_err(CE_WARN, "XFS: failed to write sb changes"); | 1378 | xfs_warn(mp, "failed to write sb changes"); |
1344 | goto out_rtunmount; | 1379 | goto out_rtunmount; |
1345 | } | 1380 | } |
1346 | } | 1381 | } |
@@ -1361,10 +1396,7 @@ xfs_mountfs( | |||
1361 | * quotachecked license. | 1396 | * quotachecked license. |
1362 | */ | 1397 | */ |
1363 | if (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT) { | 1398 | if (mp->m_sb.sb_qflags & XFS_ALL_QUOTA_ACCT) { |
1364 | cmn_err(CE_NOTE, | 1399 | xfs_notice(mp, "resetting quota flags"); |
1365 | "XFS: resetting qflags for filesystem %s", | ||
1366 | mp->m_fsname); | ||
1367 | |||
1368 | error = xfs_mount_reset_sbqflags(mp); | 1400 | error = xfs_mount_reset_sbqflags(mp); |
1369 | if (error) | 1401 | if (error) |
1370 | return error; | 1402 | return error; |
@@ -1378,7 +1410,7 @@ xfs_mountfs( | |||
1378 | */ | 1410 | */ |
1379 | error = xfs_log_mount_finish(mp); | 1411 | error = xfs_log_mount_finish(mp); |
1380 | if (error) { | 1412 | if (error) { |
1381 | cmn_err(CE_WARN, "XFS: log mount finish failed"); | 1413 | xfs_warn(mp, "log mount finish failed"); |
1382 | goto out_rtunmount; | 1414 | goto out_rtunmount; |
1383 | } | 1415 | } |
1384 | 1416 | ||
@@ -1407,8 +1439,8 @@ xfs_mountfs( | |||
1407 | resblks = xfs_default_resblks(mp); | 1439 | resblks = xfs_default_resblks(mp); |
1408 | error = xfs_reserve_blocks(mp, &resblks, NULL); | 1440 | error = xfs_reserve_blocks(mp, &resblks, NULL); |
1409 | if (error) | 1441 | if (error) |
1410 | cmn_err(CE_WARN, "XFS: Unable to allocate reserve " | 1442 | xfs_warn(mp, |
1411 | "blocks. Continuing without a reserve pool."); | 1443 | "Unable to allocate reserve blocks. Continuing without reserve pool."); |
1412 | } | 1444 | } |
1413 | 1445 | ||
1414 | return 0; | 1446 | return 0; |
@@ -1497,12 +1529,12 @@ xfs_unmountfs( | |||
1497 | resblks = 0; | 1529 | resblks = 0; |
1498 | error = xfs_reserve_blocks(mp, &resblks, NULL); | 1530 | error = xfs_reserve_blocks(mp, &resblks, NULL); |
1499 | if (error) | 1531 | if (error) |
1500 | cmn_err(CE_WARN, "XFS: Unable to free reserved block pool. " | 1532 | xfs_warn(mp, "Unable to free reserved block pool. " |
1501 | "Freespace may not be correct on next mount."); | 1533 | "Freespace may not be correct on next mount."); |
1502 | 1534 | ||
1503 | error = xfs_log_sbcount(mp, 1); | 1535 | error = xfs_log_sbcount(mp, 1); |
1504 | if (error) | 1536 | if (error) |
1505 | cmn_err(CE_WARN, "XFS: Unable to update superblock counters. " | 1537 | xfs_warn(mp, "Unable to update superblock counters. " |
1506 | "Freespace may not be correct on next mount."); | 1538 | "Freespace may not be correct on next mount."); |
1507 | xfs_unmountfs_writesb(mp); | 1539 | xfs_unmountfs_writesb(mp); |
1508 | xfs_unmountfs_wait(mp); /* wait for async bufs */ | 1540 | xfs_unmountfs_wait(mp); /* wait for async bufs */ |
@@ -1601,7 +1633,7 @@ xfs_unmountfs_writesb(xfs_mount_t *mp) | |||
1601 | XFS_BUF_UNASYNC(sbp); | 1633 | XFS_BUF_UNASYNC(sbp); |
1602 | ASSERT(XFS_BUF_TARGET(sbp) == mp->m_ddev_targp); | 1634 | ASSERT(XFS_BUF_TARGET(sbp) == mp->m_ddev_targp); |
1603 | xfsbdstrat(mp, sbp); | 1635 | xfsbdstrat(mp, sbp); |
1604 | error = xfs_iowait(sbp); | 1636 | error = xfs_buf_iowait(sbp); |
1605 | if (error) | 1637 | if (error) |
1606 | xfs_ioerror_alert("xfs_unmountfs_writesb", | 1638 | xfs_ioerror_alert("xfs_unmountfs_writesb", |
1607 | mp, sbp, XFS_BUF_ADDR(sbp)); | 1639 | mp, sbp, XFS_BUF_ADDR(sbp)); |
@@ -1832,135 +1864,72 @@ xfs_mod_incore_sb_unlocked( | |||
1832 | */ | 1864 | */ |
1833 | int | 1865 | int |
1834 | xfs_mod_incore_sb( | 1866 | xfs_mod_incore_sb( |
1835 | xfs_mount_t *mp, | 1867 | struct xfs_mount *mp, |
1836 | xfs_sb_field_t field, | 1868 | xfs_sb_field_t field, |
1837 | int64_t delta, | 1869 | int64_t delta, |
1838 | int rsvd) | 1870 | int rsvd) |
1839 | { | 1871 | { |
1840 | int status; | 1872 | int status; |
1841 | 1873 | ||
1842 | /* check for per-cpu counters */ | ||
1843 | switch (field) { | ||
1844 | #ifdef HAVE_PERCPU_SB | 1874 | #ifdef HAVE_PERCPU_SB |
1845 | case XFS_SBS_ICOUNT: | 1875 | ASSERT(field < XFS_SBS_ICOUNT || field > XFS_SBS_FDBLOCKS); |
1846 | case XFS_SBS_IFREE: | ||
1847 | case XFS_SBS_FDBLOCKS: | ||
1848 | if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) { | ||
1849 | status = xfs_icsb_modify_counters(mp, field, | ||
1850 | delta, rsvd); | ||
1851 | break; | ||
1852 | } | ||
1853 | /* FALLTHROUGH */ | ||
1854 | #endif | 1876 | #endif |
1855 | default: | 1877 | spin_lock(&mp->m_sb_lock); |
1856 | spin_lock(&mp->m_sb_lock); | 1878 | status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd); |
1857 | status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd); | 1879 | spin_unlock(&mp->m_sb_lock); |
1858 | spin_unlock(&mp->m_sb_lock); | ||
1859 | break; | ||
1860 | } | ||
1861 | 1880 | ||
1862 | return status; | 1881 | return status; |
1863 | } | 1882 | } |
1864 | 1883 | ||
1865 | /* | 1884 | /* |
1866 | * xfs_mod_incore_sb_batch() is used to change more than one field | 1885 | * Change more than one field in the in-core superblock structure at a time. |
1867 | * in the in-core superblock structure at a time. This modification | ||
1868 | * is protected by a lock internal to this module. The fields and | ||
1869 | * changes to those fields are specified in the array of xfs_mod_sb | ||
1870 | * structures passed in. | ||
1871 | * | 1886 | * |
1872 | * Either all of the specified deltas will be applied or none of | 1887 | * The fields and changes to those fields are specified in the array of |
1873 | * them will. If any modified field dips below 0, then all modifications | 1888 | * xfs_mod_sb structures passed in. Either all of the specified deltas |
1874 | * will be backed out and EINVAL will be returned. | 1889 | * will be applied or none of them will. If any modified field dips below 0, |
1890 | * then all modifications will be backed out and EINVAL will be returned. | ||
1891 | * | ||
1892 | * Note that this function may not be used for the superblock values that | ||
1893 | * are tracked with the in-memory per-cpu counters - a direct call to | ||
1894 | * xfs_icsb_modify_counters is required for these. | ||
1875 | */ | 1895 | */ |
1876 | int | 1896 | int |
1877 | xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd) | 1897 | xfs_mod_incore_sb_batch( |
1898 | struct xfs_mount *mp, | ||
1899 | xfs_mod_sb_t *msb, | ||
1900 | uint nmsb, | ||
1901 | int rsvd) | ||
1878 | { | 1902 | { |
1879 | int status=0; | 1903 | xfs_mod_sb_t *msbp; |
1880 | xfs_mod_sb_t *msbp; | 1904 | int error = 0; |
1881 | 1905 | ||
1882 | /* | 1906 | /* |
1883 | * Loop through the array of mod structures and apply each | 1907 | * Loop through the array of mod structures and apply each individually. |
1884 | * individually. If any fail, then back out all those | 1908 | * If any fail, then back out all those which have already been applied. |
1885 | * which have already been applied. Do all of this within | 1909 | * Do all of this within the scope of the m_sb_lock so that all of the |
1886 | * the scope of the m_sb_lock so that all of the changes will | 1910 | * changes will be atomic. |
1887 | * be atomic. | ||
1888 | */ | 1911 | */ |
1889 | spin_lock(&mp->m_sb_lock); | 1912 | spin_lock(&mp->m_sb_lock); |
1890 | msbp = &msb[0]; | 1913 | for (msbp = msb; msbp < (msb + nmsb); msbp++) { |
1891 | for (msbp = &msbp[0]; msbp < (msb + nmsb); msbp++) { | 1914 | ASSERT(msbp->msb_field < XFS_SBS_ICOUNT || |
1892 | /* | 1915 | msbp->msb_field > XFS_SBS_FDBLOCKS); |
1893 | * Apply the delta at index n. If it fails, break | ||
1894 | * from the loop so we'll fall into the undo loop | ||
1895 | * below. | ||
1896 | */ | ||
1897 | switch (msbp->msb_field) { | ||
1898 | #ifdef HAVE_PERCPU_SB | ||
1899 | case XFS_SBS_ICOUNT: | ||
1900 | case XFS_SBS_IFREE: | ||
1901 | case XFS_SBS_FDBLOCKS: | ||
1902 | if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) { | ||
1903 | spin_unlock(&mp->m_sb_lock); | ||
1904 | status = xfs_icsb_modify_counters(mp, | ||
1905 | msbp->msb_field, | ||
1906 | msbp->msb_delta, rsvd); | ||
1907 | spin_lock(&mp->m_sb_lock); | ||
1908 | break; | ||
1909 | } | ||
1910 | /* FALLTHROUGH */ | ||
1911 | #endif | ||
1912 | default: | ||
1913 | status = xfs_mod_incore_sb_unlocked(mp, | ||
1914 | msbp->msb_field, | ||
1915 | msbp->msb_delta, rsvd); | ||
1916 | break; | ||
1917 | } | ||
1918 | 1916 | ||
1919 | if (status != 0) { | 1917 | error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field, |
1920 | break; | 1918 | msbp->msb_delta, rsvd); |
1921 | } | 1919 | if (error) |
1920 | goto unwind; | ||
1922 | } | 1921 | } |
1922 | spin_unlock(&mp->m_sb_lock); | ||
1923 | return 0; | ||
1923 | 1924 | ||
1924 | /* | 1925 | unwind: |
1925 | * If we didn't complete the loop above, then back out | 1926 | while (--msbp >= msb) { |
1926 | * any changes made to the superblock. If you add code | 1927 | error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field, |
1927 | * between the loop above and here, make sure that you | 1928 | -msbp->msb_delta, rsvd); |
1928 | * preserve the value of status. Loop back until | 1929 | ASSERT(error == 0); |
1929 | * we step below the beginning of the array. Make sure | ||
1930 | * we don't touch anything back there. | ||
1931 | */ | ||
1932 | if (status != 0) { | ||
1933 | msbp--; | ||
1934 | while (msbp >= msb) { | ||
1935 | switch (msbp->msb_field) { | ||
1936 | #ifdef HAVE_PERCPU_SB | ||
1937 | case XFS_SBS_ICOUNT: | ||
1938 | case XFS_SBS_IFREE: | ||
1939 | case XFS_SBS_FDBLOCKS: | ||
1940 | if (!(mp->m_flags & XFS_MOUNT_NO_PERCPU_SB)) { | ||
1941 | spin_unlock(&mp->m_sb_lock); | ||
1942 | status = xfs_icsb_modify_counters(mp, | ||
1943 | msbp->msb_field, | ||
1944 | -(msbp->msb_delta), | ||
1945 | rsvd); | ||
1946 | spin_lock(&mp->m_sb_lock); | ||
1947 | break; | ||
1948 | } | ||
1949 | /* FALLTHROUGH */ | ||
1950 | #endif | ||
1951 | default: | ||
1952 | status = xfs_mod_incore_sb_unlocked(mp, | ||
1953 | msbp->msb_field, | ||
1954 | -(msbp->msb_delta), | ||
1955 | rsvd); | ||
1956 | break; | ||
1957 | } | ||
1958 | ASSERT(status == 0); | ||
1959 | msbp--; | ||
1960 | } | ||
1961 | } | 1930 | } |
1962 | spin_unlock(&mp->m_sb_lock); | 1931 | spin_unlock(&mp->m_sb_lock); |
1963 | return status; | 1932 | return error; |
1964 | } | 1933 | } |
1965 | 1934 | ||
1966 | /* | 1935 | /* |
@@ -1998,18 +1967,13 @@ xfs_getsb( | |||
1998 | */ | 1967 | */ |
1999 | void | 1968 | void |
2000 | xfs_freesb( | 1969 | xfs_freesb( |
2001 | xfs_mount_t *mp) | 1970 | struct xfs_mount *mp) |
2002 | { | 1971 | { |
2003 | xfs_buf_t *bp; | 1972 | struct xfs_buf *bp = mp->m_sb_bp; |
2004 | 1973 | ||
2005 | /* | 1974 | xfs_buf_lock(bp); |
2006 | * Use xfs_getsb() so that the buffer will be locked | ||
2007 | * when we call xfs_buf_relse(). | ||
2008 | */ | ||
2009 | bp = xfs_getsb(mp, 0); | ||
2010 | XFS_BUF_UNMANAGE(bp); | ||
2011 | xfs_buf_relse(bp); | ||
2012 | mp->m_sb_bp = NULL; | 1975 | mp->m_sb_bp = NULL; |
1976 | xfs_buf_relse(bp); | ||
2013 | } | 1977 | } |
2014 | 1978 | ||
2015 | /* | 1979 | /* |
@@ -2053,10 +2017,8 @@ xfs_dev_is_read_only( | |||
2053 | if (xfs_readonly_buftarg(mp->m_ddev_targp) || | 2017 | if (xfs_readonly_buftarg(mp->m_ddev_targp) || |
2054 | xfs_readonly_buftarg(mp->m_logdev_targp) || | 2018 | xfs_readonly_buftarg(mp->m_logdev_targp) || |
2055 | (mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp))) { | 2019 | (mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp))) { |
2056 | cmn_err(CE_NOTE, | 2020 | xfs_notice(mp, "%s required on read-only device.", message); |
2057 | "XFS: %s required on read-only device.", message); | 2021 | xfs_notice(mp, "write access unavailable, cannot proceed."); |
2058 | cmn_err(CE_NOTE, | ||
2059 | "XFS: write access unavailable, cannot proceed."); | ||
2060 | return EROFS; | 2022 | return EROFS; |
2061 | } | 2023 | } |
2062 | return 0; | 2024 | return 0; |
@@ -2496,7 +2458,7 @@ xfs_icsb_balance_counter( | |||
2496 | spin_unlock(&mp->m_sb_lock); | 2458 | spin_unlock(&mp->m_sb_lock); |
2497 | } | 2459 | } |
2498 | 2460 | ||
2499 | STATIC int | 2461 | int |
2500 | xfs_icsb_modify_counters( | 2462 | xfs_icsb_modify_counters( |
2501 | xfs_mount_t *mp, | 2463 | xfs_mount_t *mp, |
2502 | xfs_sb_field_t field, | 2464 | xfs_sb_field_t field, |