diff options
Diffstat (limited to 'fs/xfs/xfs_mount.c')
-rw-r--r-- | fs/xfs/xfs_mount.c | 308 |
1 files changed, 123 insertions, 185 deletions
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index aeb9d72ebf6e..b1498ab5a399 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 { |
@@ -199,6 +194,8 @@ xfs_uuid_unmount( | |||
199 | 194 | ||
200 | /* | 195 | /* |
201 | * Reference counting access wrappers to the perag structures. | 196 | * Reference counting access wrappers to the perag structures. |
197 | * Because we never free per-ag structures, the only thing we | ||
198 | * have to protect against changes is the tree structure itself. | ||
202 | */ | 199 | */ |
203 | struct xfs_perag * | 200 | struct xfs_perag * |
204 | xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno) | 201 | xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno) |
@@ -206,19 +203,43 @@ xfs_perag_get(struct xfs_mount *mp, xfs_agnumber_t agno) | |||
206 | struct xfs_perag *pag; | 203 | struct xfs_perag *pag; |
207 | int ref = 0; | 204 | int ref = 0; |
208 | 205 | ||
209 | spin_lock(&mp->m_perag_lock); | 206 | rcu_read_lock(); |
210 | pag = radix_tree_lookup(&mp->m_perag_tree, agno); | 207 | pag = radix_tree_lookup(&mp->m_perag_tree, agno); |
211 | if (pag) { | 208 | if (pag) { |
212 | ASSERT(atomic_read(&pag->pag_ref) >= 0); | 209 | 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); | 210 | ref = atomic_inc_return(&pag->pag_ref); |
216 | } | 211 | } |
217 | spin_unlock(&mp->m_perag_lock); | 212 | rcu_read_unlock(); |
218 | trace_xfs_perag_get(mp, agno, ref, _RET_IP_); | 213 | trace_xfs_perag_get(mp, agno, ref, _RET_IP_); |
219 | return pag; | 214 | return pag; |
220 | } | 215 | } |
221 | 216 | ||
217 | /* | ||
218 | * search from @first to find the next perag with the given tag set. | ||
219 | */ | ||
220 | struct xfs_perag * | ||
221 | xfs_perag_get_tag( | ||
222 | struct xfs_mount *mp, | ||
223 | xfs_agnumber_t first, | ||
224 | int tag) | ||
225 | { | ||
226 | struct xfs_perag *pag; | ||
227 | int found; | ||
228 | int ref; | ||
229 | |||
230 | rcu_read_lock(); | ||
231 | found = radix_tree_gang_lookup_tag(&mp->m_perag_tree, | ||
232 | (void **)&pag, first, 1, tag); | ||
233 | if (found <= 0) { | ||
234 | rcu_read_unlock(); | ||
235 | return NULL; | ||
236 | } | ||
237 | ref = atomic_inc_return(&pag->pag_ref); | ||
238 | rcu_read_unlock(); | ||
239 | trace_xfs_perag_get_tag(mp, pag->pag_agno, ref, _RET_IP_); | ||
240 | return pag; | ||
241 | } | ||
242 | |||
222 | void | 243 | void |
223 | xfs_perag_put(struct xfs_perag *pag) | 244 | xfs_perag_put(struct xfs_perag *pag) |
224 | { | 245 | { |
@@ -229,10 +250,18 @@ xfs_perag_put(struct xfs_perag *pag) | |||
229 | trace_xfs_perag_put(pag->pag_mount, pag->pag_agno, ref, _RET_IP_); | 250 | trace_xfs_perag_put(pag->pag_mount, pag->pag_agno, ref, _RET_IP_); |
230 | } | 251 | } |
231 | 252 | ||
253 | STATIC void | ||
254 | __xfs_free_perag( | ||
255 | struct rcu_head *head) | ||
256 | { | ||
257 | struct xfs_perag *pag = container_of(head, struct xfs_perag, rcu_head); | ||
258 | |||
259 | ASSERT(atomic_read(&pag->pag_ref) == 0); | ||
260 | kmem_free(pag); | ||
261 | } | ||
262 | |||
232 | /* | 263 | /* |
233 | * Free up the resources associated with a mount structure. Assume that | 264 | * 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 | */ | 265 | */ |
237 | STATIC void | 266 | STATIC void |
238 | xfs_free_perag( | 267 | xfs_free_perag( |
@@ -244,10 +273,9 @@ xfs_free_perag( | |||
244 | for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { | 273 | for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { |
245 | spin_lock(&mp->m_perag_lock); | 274 | spin_lock(&mp->m_perag_lock); |
246 | pag = radix_tree_delete(&mp->m_perag_tree, agno); | 275 | pag = radix_tree_delete(&mp->m_perag_tree, agno); |
247 | ASSERT(pag); | ||
248 | ASSERT(atomic_read(&pag->pag_ref) == 0); | ||
249 | spin_unlock(&mp->m_perag_lock); | 276 | spin_unlock(&mp->m_perag_lock); |
250 | kmem_free(pag); | 277 | ASSERT(pag); |
278 | call_rcu(&pag->rcu_head, __xfs_free_perag); | ||
251 | } | 279 | } |
252 | } | 280 | } |
253 | 281 | ||
@@ -444,7 +472,10 @@ xfs_initialize_perag( | |||
444 | pag->pag_agno = index; | 472 | pag->pag_agno = index; |
445 | pag->pag_mount = mp; | 473 | pag->pag_mount = mp; |
446 | rwlock_init(&pag->pag_ici_lock); | 474 | rwlock_init(&pag->pag_ici_lock); |
475 | mutex_init(&pag->pag_ici_reclaim_lock); | ||
447 | INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC); | 476 | INIT_RADIX_TREE(&pag->pag_ici_root, GFP_ATOMIC); |
477 | spin_lock_init(&pag->pag_buf_lock); | ||
478 | pag->pag_buf_tree = RB_ROOT; | ||
448 | 479 | ||
449 | if (radix_tree_preload(GFP_NOFS)) | 480 | if (radix_tree_preload(GFP_NOFS)) |
450 | goto out_unwind; | 481 | goto out_unwind; |
@@ -639,7 +670,6 @@ int | |||
639 | xfs_readsb(xfs_mount_t *mp, int flags) | 670 | xfs_readsb(xfs_mount_t *mp, int flags) |
640 | { | 671 | { |
641 | unsigned int sector_size; | 672 | unsigned int sector_size; |
642 | unsigned int extra_flags; | ||
643 | xfs_buf_t *bp; | 673 | xfs_buf_t *bp; |
644 | int error; | 674 | int error; |
645 | 675 | ||
@@ -652,28 +682,24 @@ xfs_readsb(xfs_mount_t *mp, int flags) | |||
652 | * access to the superblock. | 682 | * access to the superblock. |
653 | */ | 683 | */ |
654 | sector_size = xfs_getsize_buftarg(mp->m_ddev_targp); | 684 | sector_size = xfs_getsize_buftarg(mp->m_ddev_targp); |
655 | extra_flags = XBF_LOCK | XBF_FS_MANAGED | XBF_MAPPED; | ||
656 | 685 | ||
657 | bp = xfs_buf_read(mp->m_ddev_targp, XFS_SB_DADDR, BTOBB(sector_size), | 686 | reread: |
658 | extra_flags); | 687 | bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp, |
659 | if (!bp || XFS_BUF_ISERROR(bp)) { | 688 | XFS_SB_DADDR, sector_size, 0); |
660 | xfs_fs_mount_cmn_err(flags, "SB read failed"); | 689 | if (!bp) { |
661 | error = bp ? XFS_BUF_GETERROR(bp) : ENOMEM; | 690 | xfs_fs_mount_cmn_err(flags, "SB buffer read failed"); |
662 | goto fail; | 691 | return EIO; |
663 | } | 692 | } |
664 | ASSERT(XFS_BUF_ISBUSY(bp)); | ||
665 | ASSERT(XFS_BUF_VALUSEMA(bp) <= 0); | ||
666 | 693 | ||
667 | /* | 694 | /* |
668 | * Initialize the mount structure from the superblock. | 695 | * Initialize the mount structure from the superblock. |
669 | * But first do some basic consistency checking. | 696 | * But first do some basic consistency checking. |
670 | */ | 697 | */ |
671 | xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp)); | 698 | xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp)); |
672 | |||
673 | error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags); | 699 | error = xfs_mount_validate_sb(mp, &(mp->m_sb), flags); |
674 | if (error) { | 700 | if (error) { |
675 | xfs_fs_mount_cmn_err(flags, "SB validate failed"); | 701 | xfs_fs_mount_cmn_err(flags, "SB validate failed"); |
676 | goto fail; | 702 | goto release_buf; |
677 | } | 703 | } |
678 | 704 | ||
679 | /* | 705 | /* |
@@ -684,7 +710,7 @@ xfs_readsb(xfs_mount_t *mp, int flags) | |||
684 | "device supports only %u byte sectors (not %u)", | 710 | "device supports only %u byte sectors (not %u)", |
685 | sector_size, mp->m_sb.sb_sectsize); | 711 | sector_size, mp->m_sb.sb_sectsize); |
686 | error = ENOSYS; | 712 | error = ENOSYS; |
687 | goto fail; | 713 | goto release_buf; |
688 | } | 714 | } |
689 | 715 | ||
690 | /* | 716 | /* |
@@ -692,33 +718,20 @@ xfs_readsb(xfs_mount_t *mp, int flags) | |||
692 | * re-read the superblock so the buffer is correctly sized. | 718 | * re-read the superblock so the buffer is correctly sized. |
693 | */ | 719 | */ |
694 | if (sector_size < mp->m_sb.sb_sectsize) { | 720 | if (sector_size < mp->m_sb.sb_sectsize) { |
695 | XFS_BUF_UNMANAGE(bp); | ||
696 | xfs_buf_relse(bp); | 721 | xfs_buf_relse(bp); |
697 | sector_size = mp->m_sb.sb_sectsize; | 722 | sector_size = mp->m_sb.sb_sectsize; |
698 | bp = xfs_buf_read(mp->m_ddev_targp, XFS_SB_DADDR, | 723 | 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 | } | 724 | } |
708 | 725 | ||
709 | /* Initialize per-cpu counters */ | 726 | /* Initialize per-cpu counters */ |
710 | xfs_icsb_reinit_counters(mp); | 727 | xfs_icsb_reinit_counters(mp); |
711 | 728 | ||
712 | mp->m_sb_bp = bp; | 729 | mp->m_sb_bp = bp; |
713 | xfs_buf_relse(bp); | 730 | xfs_buf_unlock(bp); |
714 | ASSERT(XFS_BUF_VALUSEMA(bp) > 0); | ||
715 | return 0; | 731 | return 0; |
716 | 732 | ||
717 | fail: | 733 | release_buf: |
718 | if (bp) { | 734 | xfs_buf_relse(bp); |
719 | XFS_BUF_UNMANAGE(bp); | ||
720 | xfs_buf_relse(bp); | ||
721 | } | ||
722 | return error; | 735 | return error; |
723 | } | 736 | } |
724 | 737 | ||
@@ -991,42 +1004,35 @@ xfs_check_sizes(xfs_mount_t *mp) | |||
991 | { | 1004 | { |
992 | xfs_buf_t *bp; | 1005 | xfs_buf_t *bp; |
993 | xfs_daddr_t d; | 1006 | xfs_daddr_t d; |
994 | int error; | ||
995 | 1007 | ||
996 | d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks); | 1008 | 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) { | 1009 | if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_dblocks) { |
998 | cmn_err(CE_WARN, "XFS: size check 1 failed"); | 1010 | cmn_err(CE_WARN, "XFS: filesystem size mismatch detected"); |
999 | return XFS_ERROR(EFBIG); | 1011 | return XFS_ERROR(EFBIG); |
1000 | } | 1012 | } |
1001 | error = xfs_read_buf(mp, mp->m_ddev_targp, | 1013 | bp = xfs_buf_read_uncached(mp, mp->m_ddev_targp, |
1002 | d - XFS_FSS_TO_BB(mp, 1), | 1014 | d - XFS_FSS_TO_BB(mp, 1), |
1003 | XFS_FSS_TO_BB(mp, 1), 0, &bp); | 1015 | BBTOB(XFS_FSS_TO_BB(mp, 1)), 0); |
1004 | if (!error) { | 1016 | if (!bp) { |
1005 | xfs_buf_relse(bp); | 1017 | cmn_err(CE_WARN, "XFS: last sector read failed"); |
1006 | } else { | 1018 | 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 | } | 1019 | } |
1020 | xfs_buf_relse(bp); | ||
1012 | 1021 | ||
1013 | if (mp->m_logdev_targp != mp->m_ddev_targp) { | 1022 | if (mp->m_logdev_targp != mp->m_ddev_targp) { |
1014 | d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); | 1023 | 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) { | 1024 | if (XFS_BB_TO_FSB(mp, d) != mp->m_sb.sb_logblocks) { |
1016 | cmn_err(CE_WARN, "XFS: size check 3 failed"); | 1025 | cmn_err(CE_WARN, "XFS: log size mismatch detected"); |
1017 | return XFS_ERROR(EFBIG); | 1026 | return XFS_ERROR(EFBIG); |
1018 | } | 1027 | } |
1019 | error = xfs_read_buf(mp, mp->m_logdev_targp, | 1028 | bp = xfs_buf_read_uncached(mp, mp->m_logdev_targp, |
1020 | d - XFS_FSB_TO_BB(mp, 1), | 1029 | d - XFS_FSB_TO_BB(mp, 1), |
1021 | XFS_FSB_TO_BB(mp, 1), 0, &bp); | 1030 | XFS_FSB_TO_B(mp, 1), 0); |
1022 | if (!error) { | 1031 | if (!bp) { |
1023 | xfs_buf_relse(bp); | 1032 | cmn_err(CE_WARN, "XFS: log device read failed"); |
1024 | } else { | 1033 | 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 | } | 1034 | } |
1035 | xfs_buf_relse(bp); | ||
1030 | } | 1036 | } |
1031 | return 0; | 1037 | return 0; |
1032 | } | 1038 | } |
@@ -1601,7 +1607,7 @@ xfs_unmountfs_writesb(xfs_mount_t *mp) | |||
1601 | XFS_BUF_UNASYNC(sbp); | 1607 | XFS_BUF_UNASYNC(sbp); |
1602 | ASSERT(XFS_BUF_TARGET(sbp) == mp->m_ddev_targp); | 1608 | ASSERT(XFS_BUF_TARGET(sbp) == mp->m_ddev_targp); |
1603 | xfsbdstrat(mp, sbp); | 1609 | xfsbdstrat(mp, sbp); |
1604 | error = xfs_iowait(sbp); | 1610 | error = xfs_buf_iowait(sbp); |
1605 | if (error) | 1611 | if (error) |
1606 | xfs_ioerror_alert("xfs_unmountfs_writesb", | 1612 | xfs_ioerror_alert("xfs_unmountfs_writesb", |
1607 | mp, sbp, XFS_BUF_ADDR(sbp)); | 1613 | mp, sbp, XFS_BUF_ADDR(sbp)); |
@@ -1832,135 +1838,72 @@ xfs_mod_incore_sb_unlocked( | |||
1832 | */ | 1838 | */ |
1833 | int | 1839 | int |
1834 | xfs_mod_incore_sb( | 1840 | xfs_mod_incore_sb( |
1835 | xfs_mount_t *mp, | 1841 | struct xfs_mount *mp, |
1836 | xfs_sb_field_t field, | 1842 | xfs_sb_field_t field, |
1837 | int64_t delta, | 1843 | int64_t delta, |
1838 | int rsvd) | 1844 | int rsvd) |
1839 | { | 1845 | { |
1840 | int status; | 1846 | int status; |
1841 | 1847 | ||
1842 | /* check for per-cpu counters */ | ||
1843 | switch (field) { | ||
1844 | #ifdef HAVE_PERCPU_SB | 1848 | #ifdef HAVE_PERCPU_SB |
1845 | case XFS_SBS_ICOUNT: | 1849 | 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 | 1850 | #endif |
1855 | default: | 1851 | spin_lock(&mp->m_sb_lock); |
1856 | spin_lock(&mp->m_sb_lock); | 1852 | status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd); |
1857 | status = xfs_mod_incore_sb_unlocked(mp, field, delta, rsvd); | 1853 | spin_unlock(&mp->m_sb_lock); |
1858 | spin_unlock(&mp->m_sb_lock); | ||
1859 | break; | ||
1860 | } | ||
1861 | 1854 | ||
1862 | return status; | 1855 | return status; |
1863 | } | 1856 | } |
1864 | 1857 | ||
1865 | /* | 1858 | /* |
1866 | * xfs_mod_incore_sb_batch() is used to change more than one field | 1859 | * 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 | * | 1860 | * |
1872 | * Either all of the specified deltas will be applied or none of | 1861 | * 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 | 1862 | * xfs_mod_sb structures passed in. Either all of the specified deltas |
1874 | * will be backed out and EINVAL will be returned. | 1863 | * will be applied or none of them will. If any modified field dips below 0, |
1864 | * then all modifications will be backed out and EINVAL will be returned. | ||
1865 | * | ||
1866 | * Note that this function may not be used for the superblock values that | ||
1867 | * are tracked with the in-memory per-cpu counters - a direct call to | ||
1868 | * xfs_icsb_modify_counters is required for these. | ||
1875 | */ | 1869 | */ |
1876 | int | 1870 | int |
1877 | xfs_mod_incore_sb_batch(xfs_mount_t *mp, xfs_mod_sb_t *msb, uint nmsb, int rsvd) | 1871 | xfs_mod_incore_sb_batch( |
1872 | struct xfs_mount *mp, | ||
1873 | xfs_mod_sb_t *msb, | ||
1874 | uint nmsb, | ||
1875 | int rsvd) | ||
1878 | { | 1876 | { |
1879 | int status=0; | 1877 | xfs_mod_sb_t *msbp = &msb[0]; |
1880 | xfs_mod_sb_t *msbp; | 1878 | int error = 0; |
1881 | 1879 | ||
1882 | /* | 1880 | /* |
1883 | * Loop through the array of mod structures and apply each | 1881 | * Loop through the array of mod structures and apply each individually. |
1884 | * individually. If any fail, then back out all those | 1882 | * If any fail, then back out all those which have already been applied. |
1885 | * which have already been applied. Do all of this within | 1883 | * 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 | 1884 | * changes will be atomic. |
1887 | * be atomic. | ||
1888 | */ | 1885 | */ |
1889 | spin_lock(&mp->m_sb_lock); | 1886 | spin_lock(&mp->m_sb_lock); |
1890 | msbp = &msb[0]; | ||
1891 | for (msbp = &msbp[0]; msbp < (msb + nmsb); msbp++) { | 1887 | for (msbp = &msbp[0]; msbp < (msb + nmsb); msbp++) { |
1892 | /* | 1888 | ASSERT(msbp->msb_field < XFS_SBS_ICOUNT || |
1893 | * Apply the delta at index n. If it fails, break | 1889 | msbp->msb_field > XFS_SBS_FDBLOCKS); |
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 | 1890 | ||
1919 | if (status != 0) { | 1891 | error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field, |
1920 | break; | 1892 | msbp->msb_delta, rsvd); |
1921 | } | 1893 | if (error) |
1894 | goto unwind; | ||
1922 | } | 1895 | } |
1896 | spin_unlock(&mp->m_sb_lock); | ||
1897 | return 0; | ||
1923 | 1898 | ||
1924 | /* | 1899 | unwind: |
1925 | * If we didn't complete the loop above, then back out | 1900 | while (--msbp >= msb) { |
1926 | * any changes made to the superblock. If you add code | 1901 | error = xfs_mod_incore_sb_unlocked(mp, msbp->msb_field, |
1927 | * between the loop above and here, make sure that you | 1902 | -msbp->msb_delta, rsvd); |
1928 | * preserve the value of status. Loop back until | 1903 | 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 | } | 1904 | } |
1962 | spin_unlock(&mp->m_sb_lock); | 1905 | spin_unlock(&mp->m_sb_lock); |
1963 | return status; | 1906 | return error; |
1964 | } | 1907 | } |
1965 | 1908 | ||
1966 | /* | 1909 | /* |
@@ -1998,18 +1941,13 @@ xfs_getsb( | |||
1998 | */ | 1941 | */ |
1999 | void | 1942 | void |
2000 | xfs_freesb( | 1943 | xfs_freesb( |
2001 | xfs_mount_t *mp) | 1944 | struct xfs_mount *mp) |
2002 | { | 1945 | { |
2003 | xfs_buf_t *bp; | 1946 | struct xfs_buf *bp = mp->m_sb_bp; |
2004 | 1947 | ||
2005 | /* | 1948 | 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; | 1949 | mp->m_sb_bp = NULL; |
1950 | xfs_buf_relse(bp); | ||
2013 | } | 1951 | } |
2014 | 1952 | ||
2015 | /* | 1953 | /* |
@@ -2496,7 +2434,7 @@ xfs_icsb_balance_counter( | |||
2496 | spin_unlock(&mp->m_sb_lock); | 2434 | spin_unlock(&mp->m_sb_lock); |
2497 | } | 2435 | } |
2498 | 2436 | ||
2499 | STATIC int | 2437 | int |
2500 | xfs_icsb_modify_counters( | 2438 | xfs_icsb_modify_counters( |
2501 | xfs_mount_t *mp, | 2439 | xfs_mount_t *mp, |
2502 | xfs_sb_field_t field, | 2440 | xfs_sb_field_t field, |