Deleted Added
full compact
ffs_softdep.c (99220) ffs_softdep.c (100344)
1/*
2 * Copyright 1998, 2000 Marshall Kirk McKusick. All Rights Reserved.
3 *
4 * The soft updates code is derived from the appendix of a University
5 * of Michigan technical report (Gregory R. Ganger and Yale N. Patt,
6 * "Soft Updates: A Solution to the Metadata Update Problem in File
7 * Systems", CSE-TR-254-95, August 1995).
8 *

--- 25 unchanged lines hidden (view full) ---

34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * from: @(#)ffs_softdep.c 9.59 (McKusick) 6/21/00
39 */
40
41#include <sys/cdefs.h>
1/*
2 * Copyright 1998, 2000 Marshall Kirk McKusick. All Rights Reserved.
3 *
4 * The soft updates code is derived from the appendix of a University
5 * of Michigan technical report (Gregory R. Ganger and Yale N. Patt,
6 * "Soft Updates: A Solution to the Metadata Update Problem in File
7 * Systems", CSE-TR-254-95, August 1995).
8 *

--- 25 unchanged lines hidden (view full) ---

34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * from: @(#)ffs_softdep.c 9.59 (McKusick) 6/21/00
39 */
40
41#include <sys/cdefs.h>
42__FBSDID("$FreeBSD: head/sys/ufs/ffs/ffs_softdep.c 99220 2002-07-01 17:59:40Z iedowse $");
42__FBSDID("$FreeBSD: head/sys/ufs/ffs/ffs_softdep.c 100344 2002-07-19 07:29:39Z mckusick $");
43
44/*
45 * For now we want the safety net that the DIAGNOSTIC and DEBUG flags provide.
46 */
47#ifndef DIAGNOSTIC
48#define DIAGNOSTIC
49#endif
50#ifndef DEBUG

--- 101 unchanged lines hidden (view full) ---

152static void softdep_error(char *, int);
153static void drain_output(struct vnode *, int);
154static int getdirtybuf(struct buf **, int);
155static void clear_remove(struct thread *);
156static void clear_inodedeps(struct thread *);
157static int flush_pagedep_deps(struct vnode *, struct mount *,
158 struct diraddhd *);
159static int flush_inodedep_deps(struct fs *, ino_t);
43
44/*
45 * For now we want the safety net that the DIAGNOSTIC and DEBUG flags provide.
46 */
47#ifndef DIAGNOSTIC
48#define DIAGNOSTIC
49#endif
50#ifndef DEBUG

--- 101 unchanged lines hidden (view full) ---

152static void softdep_error(char *, int);
153static void drain_output(struct vnode *, int);
154static int getdirtybuf(struct buf **, int);
155static void clear_remove(struct thread *);
156static void clear_inodedeps(struct thread *);
157static int flush_pagedep_deps(struct vnode *, struct mount *,
158 struct diraddhd *);
159static int flush_inodedep_deps(struct fs *, ino_t);
160static int flush_deplist(struct allocdirectlst *, int, int *);
160static int handle_written_filepage(struct pagedep *, struct buf *);
161static void diradd_inode_written(struct diradd *, struct inodedep *);
162static int handle_written_inodeblock(struct inodedep *, struct buf *);
163static void handle_allocdirect_partdone(struct allocdirect *);
164static void handle_allocindir_partdone(struct allocindir *);
165static void initiate_write_filepage(struct pagedep *, struct buf *);
166static void handle_written_mkdir(struct mkdir *, int);
167static void initiate_write_inodeblock_ufs1(struct inodedep *, struct buf *);

--- 8 unchanged lines hidden (view full) ---

176static int indir_trunc(struct freeblks *, ufs2_daddr_t, int, ufs_lbn_t,
177 ufs2_daddr_t *);
178static void deallocate_dependencies(struct buf *, struct inodedep *);
179static void free_allocdirect(struct allocdirectlst *,
180 struct allocdirect *, int);
181static int check_inode_unwritten(struct inodedep *);
182static int free_inodedep(struct inodedep *);
183static void handle_workitem_freeblocks(struct freeblks *, int);
161static int handle_written_filepage(struct pagedep *, struct buf *);
162static void diradd_inode_written(struct diradd *, struct inodedep *);
163static int handle_written_inodeblock(struct inodedep *, struct buf *);
164static void handle_allocdirect_partdone(struct allocdirect *);
165static void handle_allocindir_partdone(struct allocindir *);
166static void initiate_write_filepage(struct pagedep *, struct buf *);
167static void handle_written_mkdir(struct mkdir *, int);
168static void initiate_write_inodeblock_ufs1(struct inodedep *, struct buf *);

--- 8 unchanged lines hidden (view full) ---

177static int indir_trunc(struct freeblks *, ufs2_daddr_t, int, ufs_lbn_t,
178 ufs2_daddr_t *);
179static void deallocate_dependencies(struct buf *, struct inodedep *);
180static void free_allocdirect(struct allocdirectlst *,
181 struct allocdirect *, int);
182static int check_inode_unwritten(struct inodedep *);
183static int free_inodedep(struct inodedep *);
184static void handle_workitem_freeblocks(struct freeblks *, int);
184static void merge_inode_lists(struct inodedep *);
185static void merge_inode_lists(struct allocdirectlst *,struct allocdirectlst *);
185static void setup_allocindir_phase2(struct buf *, struct inode *,
186 struct allocindir *);
187static struct allocindir *newallocindir(struct inode *, int, ufs2_daddr_t,
188 ufs2_daddr_t);
189static void handle_workitem_freefrag(struct freefrag *);
190static struct freefrag *newfreefrag(struct inode *, ufs2_daddr_t, long);
191static void allocdirect_merge(struct allocdirectlst *,
192 struct allocdirect *, struct allocdirect *);

--- 843 unchanged lines hidden (view full) ---

1036 M_INODEDEP, M_SOFTDEP_FLAGS);
1037 inodedep->id_list.wk_type = D_INODEDEP;
1038 inodedep->id_fs = fs;
1039 inodedep->id_ino = inum;
1040 inodedep->id_state = ALLCOMPLETE;
1041 inodedep->id_nlinkdelta = 0;
1042 inodedep->id_savedino1 = NULL;
1043 inodedep->id_savedsize = -1;
186static void setup_allocindir_phase2(struct buf *, struct inode *,
187 struct allocindir *);
188static struct allocindir *newallocindir(struct inode *, int, ufs2_daddr_t,
189 ufs2_daddr_t);
190static void handle_workitem_freefrag(struct freefrag *);
191static struct freefrag *newfreefrag(struct inode *, ufs2_daddr_t, long);
192static void allocdirect_merge(struct allocdirectlst *,
193 struct allocdirect *, struct allocdirect *);

--- 843 unchanged lines hidden (view full) ---

1037 M_INODEDEP, M_SOFTDEP_FLAGS);
1038 inodedep->id_list.wk_type = D_INODEDEP;
1039 inodedep->id_fs = fs;
1040 inodedep->id_ino = inum;
1041 inodedep->id_state = ALLCOMPLETE;
1042 inodedep->id_nlinkdelta = 0;
1043 inodedep->id_savedino1 = NULL;
1044 inodedep->id_savedsize = -1;
1045 inodedep->id_savedextsize = -1;
1044 inodedep->id_buf = NULL;
1045 LIST_INIT(&inodedep->id_pendinghd);
1046 LIST_INIT(&inodedep->id_inowait);
1047 LIST_INIT(&inodedep->id_bufwait);
1048 TAILQ_INIT(&inodedep->id_inoupdt);
1049 TAILQ_INIT(&inodedep->id_newinoupdt);
1046 inodedep->id_buf = NULL;
1047 LIST_INIT(&inodedep->id_pendinghd);
1048 LIST_INIT(&inodedep->id_inowait);
1049 LIST_INIT(&inodedep->id_bufwait);
1050 TAILQ_INIT(&inodedep->id_inoupdt);
1051 TAILQ_INIT(&inodedep->id_newinoupdt);
1052 TAILQ_INIT(&inodedep->id_extupdt);
1053 TAILQ_INIT(&inodedep->id_newextupdt);
1050 ACQUIRE_LOCK(&lk);
1051 LIST_INSERT_HEAD(inodedephd, inodedep, id_hash);
1052 sema_release(&inodedep_in_progress);
1053 *inodedeppp = inodedep;
1054 return (0);
1055}
1056
1057/*

--- 503 unchanged lines hidden (view full) ---

1561 struct ufsmount *ump = VFSTOUFS(freefrag->ff_mnt);
1562
1563 ffs_blkfree(ump->um_fs, ump->um_devvp, freefrag->ff_blkno,
1564 freefrag->ff_fragsize, freefrag->ff_inum);
1565 FREE(freefrag, M_FREEFRAG);
1566}
1567
1568/*
1054 ACQUIRE_LOCK(&lk);
1055 LIST_INSERT_HEAD(inodedephd, inodedep, id_hash);
1056 sema_release(&inodedep_in_progress);
1057 *inodedeppp = inodedep;
1058 return (0);
1059}
1060
1061/*

--- 503 unchanged lines hidden (view full) ---

1565 struct ufsmount *ump = VFSTOUFS(freefrag->ff_mnt);
1566
1567 ffs_blkfree(ump->um_fs, ump->um_devvp, freefrag->ff_blkno,
1568 freefrag->ff_fragsize, freefrag->ff_inum);
1569 FREE(freefrag, M_FREEFRAG);
1570}
1571
1572/*
1573 * Set up a dependency structure for an external attributes data block.
1574 * This routine follows much of the structure of softdep_setup_allocdirect.
1575 * See the description of softdep_setup_allocdirect above for details.
1576 */
1577void
1578softdep_setup_allocext(ip, lbn, newblkno, oldblkno, newsize, oldsize, bp)
1579 struct inode *ip;
1580 ufs_lbn_t lbn;
1581 ufs2_daddr_t newblkno;
1582 ufs2_daddr_t oldblkno;
1583 long newsize;
1584 long oldsize;
1585 struct buf *bp;
1586{
1587 struct allocdirect *adp, *oldadp;
1588 struct allocdirectlst *adphead;
1589 struct bmsafemap *bmsafemap;
1590 struct inodedep *inodedep;
1591 struct newblk *newblk;
1592
1593 MALLOC(adp, struct allocdirect *, sizeof(struct allocdirect),
1594 M_ALLOCDIRECT, M_SOFTDEP_FLAGS|M_ZERO);
1595 adp->ad_list.wk_type = D_ALLOCDIRECT;
1596 adp->ad_lbn = lbn;
1597 adp->ad_newblkno = newblkno;
1598 adp->ad_oldblkno = oldblkno;
1599 adp->ad_newsize = newsize;
1600 adp->ad_oldsize = oldsize;
1601 adp->ad_state = ATTACHED | EXTDATA;
1602 LIST_INIT(&adp->ad_newdirblk);
1603 if (newblkno == oldblkno)
1604 adp->ad_freefrag = NULL;
1605 else
1606 adp->ad_freefrag = newfreefrag(ip, oldblkno, oldsize);
1607
1608 if (newblk_lookup(ip->i_fs, newblkno, 0, &newblk) == 0)
1609 panic("softdep_setup_allocext: lost block");
1610
1611 ACQUIRE_LOCK(&lk);
1612 inodedep_lookup(ip->i_fs, ip->i_number, DEPALLOC | NODELAY, &inodedep);
1613 adp->ad_inodedep = inodedep;
1614
1615 if (newblk->nb_state == DEPCOMPLETE) {
1616 adp->ad_state |= DEPCOMPLETE;
1617 adp->ad_buf = NULL;
1618 } else {
1619 bmsafemap = newblk->nb_bmsafemap;
1620 adp->ad_buf = bmsafemap->sm_buf;
1621 LIST_REMOVE(newblk, nb_deps);
1622 LIST_INSERT_HEAD(&bmsafemap->sm_allocdirecthd, adp, ad_deps);
1623 }
1624 LIST_REMOVE(newblk, nb_hash);
1625 FREE(newblk, M_NEWBLK);
1626
1627 WORKLIST_INSERT(&bp->b_dep, &adp->ad_list);
1628 if (lbn >= NXADDR) {
1629 FREE_LOCK(&lk);
1630 panic("softdep_setup_allocext: lbn %d > NXADDR", lbn);
1631 }
1632 /*
1633 * The list of allocdirects must be kept in sorted and ascending
1634 * order so that the rollback routines can quickly determine the
1635 * first uncommitted block (the size of the file stored on disk
1636 * ends at the end of the lowest committed fragment, or if there
1637 * are no fragments, at the end of the highest committed block).
1638 * Since files generally grow, the typical case is that the new
1639 * block is to be added at the end of the list. We speed this
1640 * special case by checking against the last allocdirect in the
1641 * list before laboriously traversing the list looking for the
1642 * insertion point.
1643 */
1644 adphead = &inodedep->id_newextupdt;
1645 oldadp = TAILQ_LAST(adphead, allocdirectlst);
1646 if (oldadp == NULL || oldadp->ad_lbn <= lbn) {
1647 /* insert at end of list */
1648 TAILQ_INSERT_TAIL(adphead, adp, ad_next);
1649 if (oldadp != NULL && oldadp->ad_lbn == lbn)
1650 allocdirect_merge(adphead, adp, oldadp);
1651 FREE_LOCK(&lk);
1652 return;
1653 }
1654 TAILQ_FOREACH(oldadp, adphead, ad_next) {
1655 if (oldadp->ad_lbn >= lbn)
1656 break;
1657 }
1658 if (oldadp == NULL) {
1659 FREE_LOCK(&lk);
1660 panic("softdep_setup_allocext: lost entry");
1661 }
1662 /* insert in middle of list */
1663 TAILQ_INSERT_BEFORE(oldadp, adp, ad_next);
1664 if (oldadp->ad_lbn == lbn)
1665 allocdirect_merge(adphead, adp, oldadp);
1666 FREE_LOCK(&lk);
1667}
1668
1669/*
1569 * Indirect block allocation dependencies.
1570 *
1571 * The same dependencies that exist for a direct block also exist when
1572 * a new block is allocated and pointed to by an entry in a block of
1573 * indirect pointers. The undo/redo states described above are also
1574 * used here. Because an indirect block contains many pointers that
1575 * may have dependencies, a second copy of the entire in-memory indirect
1576 * block is kept. The buffer cache copy is always completely up-to-date.

--- 187 unchanged lines hidden (view full) ---

1764 M_INDIRDEP, M_SOFTDEP_FLAGS);
1765 newindirdep->ir_list.wk_type = D_INDIRDEP;
1766 newindirdep->ir_state = ATTACHED;
1767 if (ip->i_ump->um_fstype == UFS1)
1768 newindirdep->ir_state |= UFS1FMT;
1769 LIST_INIT(&newindirdep->ir_deplisthd);
1770 LIST_INIT(&newindirdep->ir_donehd);
1771 if (bp->b_blkno == bp->b_lblkno) {
1670 * Indirect block allocation dependencies.
1671 *
1672 * The same dependencies that exist for a direct block also exist when
1673 * a new block is allocated and pointed to by an entry in a block of
1674 * indirect pointers. The undo/redo states described above are also
1675 * used here. Because an indirect block contains many pointers that
1676 * may have dependencies, a second copy of the entire in-memory indirect
1677 * block is kept. The buffer cache copy is always completely up-to-date.

--- 187 unchanged lines hidden (view full) ---

1865 M_INDIRDEP, M_SOFTDEP_FLAGS);
1866 newindirdep->ir_list.wk_type = D_INDIRDEP;
1867 newindirdep->ir_state = ATTACHED;
1868 if (ip->i_ump->um_fstype == UFS1)
1869 newindirdep->ir_state |= UFS1FMT;
1870 LIST_INIT(&newindirdep->ir_deplisthd);
1871 LIST_INIT(&newindirdep->ir_donehd);
1872 if (bp->b_blkno == bp->b_lblkno) {
1772 ufs_bmaparray(bp->b_vp, bp->b_lblkno, &blkno, NULL, NULL);
1873 ufs_bmaparray(bp->b_vp, bp->b_lblkno, &blkno, bp,
1874 NULL, NULL);
1773 bp->b_blkno = blkno;
1774 }
1775 newindirdep->ir_savebp =
1776 getblk(ip->i_devvp, bp->b_blkno, bp->b_bcount, 0, 0);
1777 BUF_KERNPROC(newindirdep->ir_savebp);
1778 bcopy(bp->b_data, newindirdep->ir_savebp->b_data, bp->b_bcount);
1779 }
1780}

--- 23 unchanged lines hidden (view full) ---

1804 *
1805 * This routine should be called from the routine that shortens
1806 * a file's length, before the inode's size or block pointers
1807 * are modified. It will save the block pointer information for
1808 * later release and zero the inode so that the calling routine
1809 * can release it.
1810 */
1811void
1875 bp->b_blkno = blkno;
1876 }
1877 newindirdep->ir_savebp =
1878 getblk(ip->i_devvp, bp->b_blkno, bp->b_bcount, 0, 0);
1879 BUF_KERNPROC(newindirdep->ir_savebp);
1880 bcopy(bp->b_data, newindirdep->ir_savebp->b_data, bp->b_bcount);
1881 }
1882}

--- 23 unchanged lines hidden (view full) ---

1906 *
1907 * This routine should be called from the routine that shortens
1908 * a file's length, before the inode's size or block pointers
1909 * are modified. It will save the block pointer information for
1910 * later release and zero the inode so that the calling routine
1911 * can release it.
1912 */
1913void
1812softdep_setup_freeblocks(ip, length)
1914softdep_setup_freeblocks(ip, length, flags)
1813 struct inode *ip; /* The inode whose length is to be reduced */
1814 off_t length; /* The new length for the file */
1915 struct inode *ip; /* The inode whose length is to be reduced */
1916 off_t length; /* The new length for the file */
1917 int flags; /* IO_EXT and/or IO_NORMAL */
1815{
1816 struct freeblks *freeblks;
1817 struct inodedep *inodedep;
1818 struct allocdirect *adp;
1819 struct vnode *vp;
1820 struct buf *bp;
1821 struct fs *fs;
1918{
1919 struct freeblks *freeblks;
1920 struct inodedep *inodedep;
1921 struct allocdirect *adp;
1922 struct vnode *vp;
1923 struct buf *bp;
1924 struct fs *fs;
1925 ufs2_daddr_t extblocks, datablocks;
1822 int i, delay, error;
1823
1824 fs = ip->i_fs;
1825 if (length != 0)
1826 panic("softdep_setup_freeblocks: non-zero length");
1827 MALLOC(freeblks, struct freeblks *, sizeof(struct freeblks),
1828 M_FREEBLKS, M_SOFTDEP_FLAGS|M_ZERO);
1829 freeblks->fb_list.wk_type = D_FREEBLKS;
1830 freeblks->fb_uid = ip->i_uid;
1831 freeblks->fb_previousinum = ip->i_number;
1832 freeblks->fb_devvp = ip->i_devvp;
1833 freeblks->fb_mnt = ITOV(ip)->v_mount;
1926 int i, delay, error;
1927
1928 fs = ip->i_fs;
1929 if (length != 0)
1930 panic("softdep_setup_freeblocks: non-zero length");
1931 MALLOC(freeblks, struct freeblks *, sizeof(struct freeblks),
1932 M_FREEBLKS, M_SOFTDEP_FLAGS|M_ZERO);
1933 freeblks->fb_list.wk_type = D_FREEBLKS;
1934 freeblks->fb_uid = ip->i_uid;
1935 freeblks->fb_previousinum = ip->i_number;
1936 freeblks->fb_devvp = ip->i_devvp;
1937 freeblks->fb_mnt = ITOV(ip)->v_mount;
1834 freeblks->fb_oldsize = ip->i_size;
1835 freeblks->fb_newsize = length;
1836 freeblks->fb_chkcnt = DIP(ip, i_blocks);
1837 for (i = 0; i < NDADDR; i++) {
1838 freeblks->fb_dblks[i] = DIP(ip, i_db[i]);
1839 DIP(ip, i_db[i]) = 0;
1938 extblocks = 0;
1939 if (fs->fs_magic == FS_UFS2_MAGIC)
1940 extblocks = btodb(fragroundup(fs, ip->i_din2->di_extsize));
1941 datablocks = DIP(ip, i_blocks) - extblocks;
1942 if ((flags & IO_NORMAL) == 0) {
1943 freeblks->fb_oldsize = 0;
1944 freeblks->fb_chkcnt = 0;
1945 } else {
1946 freeblks->fb_oldsize = ip->i_size;
1947 ip->i_size = 0;
1948 DIP(ip, i_size) = 0;
1949 freeblks->fb_chkcnt = datablocks;
1950 for (i = 0; i < NDADDR; i++) {
1951 freeblks->fb_dblks[i] = DIP(ip, i_db[i]);
1952 DIP(ip, i_db[i]) = 0;
1953 }
1954 for (i = 0; i < NIADDR; i++) {
1955 freeblks->fb_iblks[i] = DIP(ip, i_ib[i]);
1956 DIP(ip, i_ib[i]) = 0;
1957 }
1958 /*
1959 * If the file was removed, then the space being freed was
1960 * accounted for then (see softdep_filereleased()). If the
1961 * file is merely being truncated, then we account for it now.
1962 */
1963 if ((ip->i_flag & IN_SPACECOUNTED) == 0)
1964 fs->fs_pendingblocks += datablocks;
1840 }
1965 }
1841 for (i = 0; i < NIADDR; i++) {
1842 freeblks->fb_iblks[i] = DIP(ip, i_ib[i]);
1843 DIP(ip, i_ib[i]) = 0;
1966 if ((flags & IO_EXT) == 0) {
1967 freeblks->fb_oldextsize = 0;
1968 } else {
1969 freeblks->fb_oldextsize = ip->i_din2->di_extsize;
1970 ip->i_din2->di_extsize = 0;
1971 freeblks->fb_chkcnt += extblocks;
1972 for (i = 0; i < NXADDR; i++) {
1973 freeblks->fb_eblks[i] = ip->i_din2->di_extb[i];
1974 ip->i_din2->di_extb[i] = 0;
1975 }
1844 }
1976 }
1845 DIP(ip, i_blocks) = 0;
1846 ip->i_size = 0;
1847 DIP(ip, i_size) = 0;
1977 DIP(ip, i_blocks) -= freeblks->fb_chkcnt;
1848 /*
1978 /*
1849 * If the file was removed, then the space being freed was
1850 * accounted for then (see softdep_filereleased()). If the
1851 * file is merely being truncated, then we account for it now.
1852 */
1853 if ((ip->i_flag & IN_SPACECOUNTED) == 0)
1854 fs->fs_pendingblocks += freeblks->fb_chkcnt;
1855 /*
1856 * Push the zero'ed inode to to its disk buffer so that we are free
1857 * to delete its dependencies below. Once the dependencies are gone
1858 * the buffer can be safely released.
1859 */
1860 if ((error = bread(ip->i_devvp,
1861 fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
1862 (int)fs->fs_bsize, NOCRED, &bp)) != 0) {
1863 brelse(bp);

--- 28 unchanged lines hidden (view full) ---

1892 * Because the file length has been truncated to zero, any
1893 * pending block allocation dependency structures associated
1894 * with this inode are obsolete and can simply be de-allocated.
1895 * We must first merge the two dependency lists to get rid of
1896 * any duplicate freefrag structures, then purge the merged list.
1897 * If we still have a bitmap dependency, then the inode has never
1898 * been written to disk, so we can free any fragments without delay.
1899 */
1979 * Push the zero'ed inode to to its disk buffer so that we are free
1980 * to delete its dependencies below. Once the dependencies are gone
1981 * the buffer can be safely released.
1982 */
1983 if ((error = bread(ip->i_devvp,
1984 fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
1985 (int)fs->fs_bsize, NOCRED, &bp)) != 0) {
1986 brelse(bp);

--- 28 unchanged lines hidden (view full) ---

2015 * Because the file length has been truncated to zero, any
2016 * pending block allocation dependency structures associated
2017 * with this inode are obsolete and can simply be de-allocated.
2018 * We must first merge the two dependency lists to get rid of
2019 * any duplicate freefrag structures, then purge the merged list.
2020 * If we still have a bitmap dependency, then the inode has never
2021 * been written to disk, so we can free any fragments without delay.
2022 */
1900 merge_inode_lists(inodedep);
1901 while ((adp = TAILQ_FIRST(&inodedep->id_inoupdt)) != 0)
1902 free_allocdirect(&inodedep->id_inoupdt, adp, delay);
2023 if (flags & IO_NORMAL) {
2024 merge_inode_lists(&inodedep->id_newinoupdt,
2025 &inodedep->id_inoupdt);
2026 while ((adp = TAILQ_FIRST(&inodedep->id_inoupdt)) != 0)
2027 free_allocdirect(&inodedep->id_inoupdt, adp, delay);
2028 }
2029 if (flags & IO_EXT) {
2030 merge_inode_lists(&inodedep->id_newextupdt,
2031 &inodedep->id_extupdt);
2032 while ((adp = TAILQ_FIRST(&inodedep->id_extupdt)) != 0)
2033 free_allocdirect(&inodedep->id_extupdt, adp, delay);
2034 }
1903 FREE_LOCK(&lk);
1904 bdwrite(bp);
1905 /*
1906 * We must wait for any I/O in progress to finish so that
1907 * all potential buffers on the dirty list will be visible.
1908 * Once they are all there, walk the list and get rid of
1909 * any dependencies.
1910 */
1911 vp = ITOV(ip);
1912 ACQUIRE_LOCK(&lk);
1913 drain_output(vp, 1);
2035 FREE_LOCK(&lk);
2036 bdwrite(bp);
2037 /*
2038 * We must wait for any I/O in progress to finish so that
2039 * all potential buffers on the dirty list will be visible.
2040 * Once they are all there, walk the list and get rid of
2041 * any dependencies.
2042 */
2043 vp = ITOV(ip);
2044 ACQUIRE_LOCK(&lk);
2045 drain_output(vp, 1);
1914 while (getdirtybuf(&TAILQ_FIRST(&vp->v_dirtyblkhd), MNT_WAIT)) {
1915 bp = TAILQ_FIRST(&vp->v_dirtyblkhd);
2046restart:
2047 TAILQ_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs) {
2048 if (((flags & IO_EXT) == 0 && (bp->b_xflags & BX_ALTDATA)) ||
2049 ((flags & IO_NORMAL) == 0 &&
2050 (bp->b_xflags & BX_ALTDATA) == 0))
2051 continue;
2052 if (getdirtybuf(&bp, MNT_WAIT) == 0)
2053 goto restart;
1916 (void) inodedep_lookup(fs, ip->i_number, 0, &inodedep);
1917 deallocate_dependencies(bp, inodedep);
1918 bp->b_flags |= B_INVAL | B_NOCACHE;
1919 FREE_LOCK(&lk);
1920 brelse(bp);
1921 ACQUIRE_LOCK(&lk);
2054 (void) inodedep_lookup(fs, ip->i_number, 0, &inodedep);
2055 deallocate_dependencies(bp, inodedep);
2056 bp->b_flags |= B_INVAL | B_NOCACHE;
2057 FREE_LOCK(&lk);
2058 brelse(bp);
2059 ACQUIRE_LOCK(&lk);
2060 goto restart;
1922 }
1923 if (inodedep_lookup(fs, ip->i_number, 0, &inodedep) != 0)
1924 (void) free_inodedep(inodedep);
1925 FREE_LOCK(&lk);
1926 /*
1927 * If the inode has never been written to disk (delay == 0),
1928 * then we can process the freeblks now that we have deleted
1929 * the dependencies.

--- 281 unchanged lines hidden (view full) ---

2211{
2212
2213 if ((inodedep->id_state & DEPCOMPLETE) != 0 ||
2214 LIST_FIRST(&inodedep->id_pendinghd) != NULL ||
2215 LIST_FIRST(&inodedep->id_bufwait) != NULL ||
2216 LIST_FIRST(&inodedep->id_inowait) != NULL ||
2217 TAILQ_FIRST(&inodedep->id_inoupdt) != NULL ||
2218 TAILQ_FIRST(&inodedep->id_newinoupdt) != NULL ||
2061 }
2062 if (inodedep_lookup(fs, ip->i_number, 0, &inodedep) != 0)
2063 (void) free_inodedep(inodedep);
2064 FREE_LOCK(&lk);
2065 /*
2066 * If the inode has never been written to disk (delay == 0),
2067 * then we can process the freeblks now that we have deleted
2068 * the dependencies.

--- 281 unchanged lines hidden (view full) ---

2350{
2351
2352 if ((inodedep->id_state & DEPCOMPLETE) != 0 ||
2353 LIST_FIRST(&inodedep->id_pendinghd) != NULL ||
2354 LIST_FIRST(&inodedep->id_bufwait) != NULL ||
2355 LIST_FIRST(&inodedep->id_inowait) != NULL ||
2356 TAILQ_FIRST(&inodedep->id_inoupdt) != NULL ||
2357 TAILQ_FIRST(&inodedep->id_newinoupdt) != NULL ||
2358 TAILQ_FIRST(&inodedep->id_extupdt) != NULL ||
2359 TAILQ_FIRST(&inodedep->id_newextupdt) != NULL ||
2219 inodedep->id_nlinkdelta != 0)
2220 return (0);
2221 inodedep->id_state |= ALLCOMPLETE;
2222 LIST_REMOVE(inodedep, id_deps);
2223 inodedep->id_buf = NULL;
2224 if (inodedep->id_state & ONWORKLIST)
2225 WORKLIST_REMOVE(&inodedep->id_list);
2226 if (inodedep->id_savedino1 != NULL) {

--- 17 unchanged lines hidden (view full) ---

2244
2245 if ((inodedep->id_state & ONWORKLIST) != 0 ||
2246 (inodedep->id_state & ALLCOMPLETE) != ALLCOMPLETE ||
2247 LIST_FIRST(&inodedep->id_pendinghd) != NULL ||
2248 LIST_FIRST(&inodedep->id_bufwait) != NULL ||
2249 LIST_FIRST(&inodedep->id_inowait) != NULL ||
2250 TAILQ_FIRST(&inodedep->id_inoupdt) != NULL ||
2251 TAILQ_FIRST(&inodedep->id_newinoupdt) != NULL ||
2360 inodedep->id_nlinkdelta != 0)
2361 return (0);
2362 inodedep->id_state |= ALLCOMPLETE;
2363 LIST_REMOVE(inodedep, id_deps);
2364 inodedep->id_buf = NULL;
2365 if (inodedep->id_state & ONWORKLIST)
2366 WORKLIST_REMOVE(&inodedep->id_list);
2367 if (inodedep->id_savedino1 != NULL) {

--- 17 unchanged lines hidden (view full) ---

2385
2386 if ((inodedep->id_state & ONWORKLIST) != 0 ||
2387 (inodedep->id_state & ALLCOMPLETE) != ALLCOMPLETE ||
2388 LIST_FIRST(&inodedep->id_pendinghd) != NULL ||
2389 LIST_FIRST(&inodedep->id_bufwait) != NULL ||
2390 LIST_FIRST(&inodedep->id_inowait) != NULL ||
2391 TAILQ_FIRST(&inodedep->id_inoupdt) != NULL ||
2392 TAILQ_FIRST(&inodedep->id_newinoupdt) != NULL ||
2393 TAILQ_FIRST(&inodedep->id_extupdt) != NULL ||
2394 TAILQ_FIRST(&inodedep->id_newextupdt) != NULL ||
2252 inodedep->id_nlinkdelta != 0 || inodedep->id_savedino1 != NULL)
2253 return (0);
2254 LIST_REMOVE(inodedep, id_hash);
2255 WORKITEM_FREE(inodedep, D_INODEDEP);
2256 num_inodedep -= 1;
2257 return (1);
2258}
2259

--- 23 unchanged lines hidden (view full) ---

2283 baselbns[0] = NDADDR;
2284 for (i = 1; i < NIADDR; i++) {
2285 tmpval *= NINDIR(fs);
2286 baselbns[i] = baselbns[i - 1] + tmpval;
2287 }
2288 nblocks = btodb(fs->fs_bsize);
2289 blocksreleased = 0;
2290 /*
2395 inodedep->id_nlinkdelta != 0 || inodedep->id_savedino1 != NULL)
2396 return (0);
2397 LIST_REMOVE(inodedep, id_hash);
2398 WORKITEM_FREE(inodedep, D_INODEDEP);
2399 num_inodedep -= 1;
2400 return (1);
2401}
2402

--- 23 unchanged lines hidden (view full) ---

2426 baselbns[0] = NDADDR;
2427 for (i = 1; i < NIADDR; i++) {
2428 tmpval *= NINDIR(fs);
2429 baselbns[i] = baselbns[i - 1] + tmpval;
2430 }
2431 nblocks = btodb(fs->fs_bsize);
2432 blocksreleased = 0;
2433 /*
2291 * Indirect blocks first.
2434 * Release all extended attribute blocks or frags.
2292 */
2435 */
2293 for (level = (NIADDR - 1); level >= 0; level--) {
2294 if ((bn = freeblks->fb_iblks[level]) == 0)
2295 continue;
2296 if ((error = indir_trunc(freeblks, fsbtodb(fs, bn), level,
2297 baselbns[level], &blocksreleased)) == 0)
2298 allerror = error;
2299 ffs_blkfree(fs, freeblks->fb_devvp, bn, fs->fs_bsize,
2300 freeblks->fb_previousinum);
2301 fs->fs_pendingblocks -= nblocks;
2302 blocksreleased += nblocks;
2436 if (freeblks->fb_oldextsize > 0) {
2437 for (i = (NXADDR - 1); i >= 0; i--) {
2438 if ((bn = freeblks->fb_eblks[i]) == 0)
2439 continue;
2440 bsize = sblksize(fs, freeblks->fb_oldextsize, i);
2441 ffs_blkfree(fs, freeblks->fb_devvp, bn, bsize,
2442 freeblks->fb_previousinum);
2443 blocksreleased += btodb(bsize);
2444 }
2303 }
2304 /*
2445 }
2446 /*
2305 * All direct blocks or frags.
2447 * Release all data blocks or frags.
2306 */
2448 */
2307 for (i = (NDADDR - 1); i >= 0; i--) {
2308 if ((bn = freeblks->fb_dblks[i]) == 0)
2309 continue;
2310 bsize = sblksize(fs, freeblks->fb_oldsize, i);
2311 ffs_blkfree(fs, freeblks->fb_devvp, bn, bsize,
2312 freeblks->fb_previousinum);
2313 fs->fs_pendingblocks -= btodb(bsize);
2314 blocksreleased += btodb(bsize);
2449 if (freeblks->fb_oldsize > 0) {
2450 /*
2451 * Indirect blocks first.
2452 */
2453 for (level = (NIADDR - 1); level >= 0; level--) {
2454 if ((bn = freeblks->fb_iblks[level]) == 0)
2455 continue;
2456 if ((error = indir_trunc(freeblks, fsbtodb(fs, bn),
2457 level, baselbns[level], &blocksreleased)) == 0)
2458 allerror = error;
2459 ffs_blkfree(fs, freeblks->fb_devvp, bn, fs->fs_bsize,
2460 freeblks->fb_previousinum);
2461 fs->fs_pendingblocks -= nblocks;
2462 blocksreleased += nblocks;
2463 }
2464 /*
2465 * All direct blocks or frags.
2466 */
2467 for (i = (NDADDR - 1); i >= 0; i--) {
2468 if ((bn = freeblks->fb_dblks[i]) == 0)
2469 continue;
2470 bsize = sblksize(fs, freeblks->fb_oldsize, i);
2471 ffs_blkfree(fs, freeblks->fb_devvp, bn, bsize,
2472 freeblks->fb_previousinum);
2473 fs->fs_pendingblocks -= btodb(bsize);
2474 blocksreleased += btodb(bsize);
2475 }
2315 }
2316 /*
2317 * If we still have not finished background cleanup, then check
2318 * to see if the block count needs to be adjusted.
2319 */
2320 if (freeblks->fb_chkcnt != blocksreleased &&
2321 (fs->fs_flags & FS_UNCLEAN) != 0 &&
2322 VFS_VGET(freeblks->fb_mnt, freeblks->fb_previousinum,

--- 721 unchanged lines hidden (view full) ---

3044 * references. The space associated with the file will be freed
3045 * as soon as the necessary soft dependencies are cleared.
3046 */
3047void
3048softdep_releasefile(ip)
3049 struct inode *ip; /* inode with the zero effective link count */
3050{
3051 struct inodedep *inodedep;
2476 }
2477 /*
2478 * If we still have not finished background cleanup, then check
2479 * to see if the block count needs to be adjusted.
2480 */
2481 if (freeblks->fb_chkcnt != blocksreleased &&
2482 (fs->fs_flags & FS_UNCLEAN) != 0 &&
2483 VFS_VGET(freeblks->fb_mnt, freeblks->fb_previousinum,

--- 721 unchanged lines hidden (view full) ---

3205 * references. The space associated with the file will be freed
3206 * as soon as the necessary soft dependencies are cleared.
3207 */
3208void
3209softdep_releasefile(ip)
3210 struct inode *ip; /* inode with the zero effective link count */
3211{
3212 struct inodedep *inodedep;
3213 struct fs *fs;
3214 int extblocks;
3052
3053 if (ip->i_effnlink > 0)
3054 panic("softdep_filerelease: file still referenced");
3055 /*
3056 * We may be called several times as the real reference count
3057 * drops to zero. We only want to account for the space once.
3058 */
3059 if (ip->i_flag & IN_SPACECOUNTED)

--- 8 unchanged lines hidden (view full) ---

3068 /*
3069 * If we are tracking an nlinkdelta, we have to also remember
3070 * whether we accounted for the freed space yet.
3071 */
3072 ACQUIRE_LOCK(&lk);
3073 if ((inodedep_lookup(ip->i_fs, ip->i_number, 0, &inodedep)))
3074 inodedep->id_state |= SPACECOUNTED;
3075 FREE_LOCK(&lk);
3215
3216 if (ip->i_effnlink > 0)
3217 panic("softdep_filerelease: file still referenced");
3218 /*
3219 * We may be called several times as the real reference count
3220 * drops to zero. We only want to account for the space once.
3221 */
3222 if (ip->i_flag & IN_SPACECOUNTED)

--- 8 unchanged lines hidden (view full) ---

3231 /*
3232 * If we are tracking an nlinkdelta, we have to also remember
3233 * whether we accounted for the freed space yet.
3234 */
3235 ACQUIRE_LOCK(&lk);
3236 if ((inodedep_lookup(ip->i_fs, ip->i_number, 0, &inodedep)))
3237 inodedep->id_state |= SPACECOUNTED;
3238 FREE_LOCK(&lk);
3076 ip->i_fs->fs_pendingblocks += DIP(ip, i_blocks);
3239 fs = ip->i_fs;
3240 extblocks = 0;
3241 if (fs->fs_magic == FS_UFS2_MAGIC)
3242 extblocks = btodb(fragroundup(fs, ip->i_din2->di_extsize));
3243 ip->i_fs->fs_pendingblocks += DIP(ip, i_blocks) - extblocks;
3077 ip->i_fs->fs_pendinginodes += 1;
3078 ip->i_flag |= IN_SPACECOUNTED;
3079}
3080
3081/*
3082 * This workitem decrements the inode's link count.
3083 * If the link count reaches zero, the file is removed.
3084 */

--- 314 unchanged lines hidden (view full) ---

3399 *inodedep->id_savedino1 = *dp;
3400 bzero((caddr_t)dp, sizeof(struct ufs1_dinode));
3401 return;
3402 }
3403 /*
3404 * If no dependencies, then there is nothing to roll back.
3405 */
3406 inodedep->id_savedsize = dp->di_size;
3244 ip->i_fs->fs_pendinginodes += 1;
3245 ip->i_flag |= IN_SPACECOUNTED;
3246}
3247
3248/*
3249 * This workitem decrements the inode's link count.
3250 * If the link count reaches zero, the file is removed.
3251 */

--- 314 unchanged lines hidden (view full) ---

3566 *inodedep->id_savedino1 = *dp;
3567 bzero((caddr_t)dp, sizeof(struct ufs1_dinode));
3568 return;
3569 }
3570 /*
3571 * If no dependencies, then there is nothing to roll back.
3572 */
3573 inodedep->id_savedsize = dp->di_size;
3574 inodedep->id_savedextsize = 0;
3407 if (TAILQ_FIRST(&inodedep->id_inoupdt) == NULL)
3408 return;
3409 /*
3410 * Set the dependencies to busy.
3411 */
3412 ACQUIRE_LOCK(&lk);
3413 for (deplist = 0, adp = TAILQ_FIRST(&inodedep->id_inoupdt); adp;
3414 adp = TAILQ_NEXT(adp, ad_next)) {

--- 136 unchanged lines hidden (view full) ---

3551 *inodedep->id_savedino2 = *dp;
3552 bzero((caddr_t)dp, sizeof(struct ufs2_dinode));
3553 return;
3554 }
3555 /*
3556 * If no dependencies, then there is nothing to roll back.
3557 */
3558 inodedep->id_savedsize = dp->di_size;
3575 if (TAILQ_FIRST(&inodedep->id_inoupdt) == NULL)
3576 return;
3577 /*
3578 * Set the dependencies to busy.
3579 */
3580 ACQUIRE_LOCK(&lk);
3581 for (deplist = 0, adp = TAILQ_FIRST(&inodedep->id_inoupdt); adp;
3582 adp = TAILQ_NEXT(adp, ad_next)) {

--- 136 unchanged lines hidden (view full) ---

3719 *inodedep->id_savedino2 = *dp;
3720 bzero((caddr_t)dp, sizeof(struct ufs2_dinode));
3721 return;
3722 }
3723 /*
3724 * If no dependencies, then there is nothing to roll back.
3725 */
3726 inodedep->id_savedsize = dp->di_size;
3559 if (TAILQ_FIRST(&inodedep->id_inoupdt) == NULL)
3727 inodedep->id_savedextsize = dp->di_extsize;
3728 if (TAILQ_FIRST(&inodedep->id_inoupdt) == NULL &&
3729 TAILQ_FIRST(&inodedep->id_extupdt) == NULL)
3560 return;
3561 /*
3730 return;
3731 /*
3562 * Set the dependencies to busy.
3732 * Set the ext data dependencies to busy.
3563 */
3564 ACQUIRE_LOCK(&lk);
3733 */
3734 ACQUIRE_LOCK(&lk);
3735 for (deplist = 0, adp = TAILQ_FIRST(&inodedep->id_extupdt); adp;
3736 adp = TAILQ_NEXT(adp, ad_next)) {
3737#ifdef DIAGNOSTIC
3738 if (deplist != 0 && prevlbn >= adp->ad_lbn) {
3739 FREE_LOCK(&lk);
3740 panic("softdep_write_inodeblock: lbn order");
3741 }
3742 prevlbn = adp->ad_lbn;
3743 if (dp->di_extb[adp->ad_lbn] != adp->ad_newblkno) {
3744 FREE_LOCK(&lk);
3745 panic("%s: direct pointer #%jd mismatch %jd != %jd",
3746 "softdep_write_inodeblock",
3747 (intmax_t)adp->ad_lbn,
3748 (intmax_t)dp->di_extb[adp->ad_lbn],
3749 (intmax_t)adp->ad_newblkno);
3750 }
3751 deplist |= 1 << adp->ad_lbn;
3752 if ((adp->ad_state & ATTACHED) == 0) {
3753 FREE_LOCK(&lk);
3754 panic("softdep_write_inodeblock: Unknown state 0x%x",
3755 adp->ad_state);
3756 }
3757#endif /* DIAGNOSTIC */
3758 adp->ad_state &= ~ATTACHED;
3759 adp->ad_state |= UNDONE;
3760 }
3761 /*
3762 * The on-disk inode cannot claim to be any larger than the last
3763 * fragment that has been written. Otherwise, the on-disk inode
3764 * might have fragments that were not the last block in the ext
3765 * data which would corrupt the filesystem.
3766 */
3767 for (lastadp = NULL, adp = TAILQ_FIRST(&inodedep->id_extupdt); adp;
3768 lastadp = adp, adp = TAILQ_NEXT(adp, ad_next)) {
3769 dp->di_extb[adp->ad_lbn] = adp->ad_oldblkno;
3770 /* keep going until hitting a rollback to a frag */
3771 if (adp->ad_oldsize == 0 || adp->ad_oldsize == fs->fs_bsize)
3772 continue;
3773 dp->di_extsize = fs->fs_bsize * adp->ad_lbn + adp->ad_oldsize;
3774 for (i = adp->ad_lbn + 1; i < NXADDR; i++) {
3775#ifdef DIAGNOSTIC
3776 if (dp->di_extb[i] != 0 && (deplist & (1 << i)) == 0) {
3777 FREE_LOCK(&lk);
3778 panic("softdep_write_inodeblock: lost dep1");
3779 }
3780#endif /* DIAGNOSTIC */
3781 dp->di_extb[i] = 0;
3782 }
3783 lastadp = NULL;
3784 break;
3785 }
3786 /*
3787 * If we have zero'ed out the last allocated block of the ext
3788 * data, roll back the size to the last currently allocated block.
3789 * We know that this last allocated block is a full-sized as
3790 * we already checked for fragments in the loop above.
3791 */
3792 if (lastadp != NULL &&
3793 dp->di_extsize <= (lastadp->ad_lbn + 1) * fs->fs_bsize) {
3794 for (i = lastadp->ad_lbn; i >= 0; i--)
3795 if (dp->di_extb[i] != 0)
3796 break;
3797 dp->di_extsize = (i + 1) * fs->fs_bsize;
3798 }
3799 /*
3800 * Set the file data dependencies to busy.
3801 */
3565 for (deplist = 0, adp = TAILQ_FIRST(&inodedep->id_inoupdt); adp;
3566 adp = TAILQ_NEXT(adp, ad_next)) {
3567#ifdef DIAGNOSTIC
3568 if (deplist != 0 && prevlbn >= adp->ad_lbn) {
3569 FREE_LOCK(&lk);
3570 panic("softdep_write_inodeblock: lbn order");
3571 }
3572 prevlbn = adp->ad_lbn;

--- 39 unchanged lines hidden (view full) ---

3612 /* keep going until hitting a rollback to a frag */
3613 if (adp->ad_oldsize == 0 || adp->ad_oldsize == fs->fs_bsize)
3614 continue;
3615 dp->di_size = fs->fs_bsize * adp->ad_lbn + adp->ad_oldsize;
3616 for (i = adp->ad_lbn + 1; i < NDADDR; i++) {
3617#ifdef DIAGNOSTIC
3618 if (dp->di_db[i] != 0 && (deplist & (1 << i)) == 0) {
3619 FREE_LOCK(&lk);
3802 for (deplist = 0, adp = TAILQ_FIRST(&inodedep->id_inoupdt); adp;
3803 adp = TAILQ_NEXT(adp, ad_next)) {
3804#ifdef DIAGNOSTIC
3805 if (deplist != 0 && prevlbn >= adp->ad_lbn) {
3806 FREE_LOCK(&lk);
3807 panic("softdep_write_inodeblock: lbn order");
3808 }
3809 prevlbn = adp->ad_lbn;

--- 39 unchanged lines hidden (view full) ---

3849 /* keep going until hitting a rollback to a frag */
3850 if (adp->ad_oldsize == 0 || adp->ad_oldsize == fs->fs_bsize)
3851 continue;
3852 dp->di_size = fs->fs_bsize * adp->ad_lbn + adp->ad_oldsize;
3853 for (i = adp->ad_lbn + 1; i < NDADDR; i++) {
3854#ifdef DIAGNOSTIC
3855 if (dp->di_db[i] != 0 && (deplist & (1 << i)) == 0) {
3856 FREE_LOCK(&lk);
3620 panic("softdep_write_inodeblock: lost dep1");
3857 panic("softdep_write_inodeblock: lost dep2");
3621 }
3622#endif /* DIAGNOSTIC */
3623 dp->di_db[i] = 0;
3624 }
3625 for (i = 0; i < NIADDR; i++) {
3626#ifdef DIAGNOSTIC
3627 if (dp->di_ib[i] != 0 &&
3628 (deplist & ((1 << NDADDR) << i)) == 0) {
3629 FREE_LOCK(&lk);
3858 }
3859#endif /* DIAGNOSTIC */
3860 dp->di_db[i] = 0;
3861 }
3862 for (i = 0; i < NIADDR; i++) {
3863#ifdef DIAGNOSTIC
3864 if (dp->di_ib[i] != 0 &&
3865 (deplist & ((1 << NDADDR) << i)) == 0) {
3866 FREE_LOCK(&lk);
3630 panic("softdep_write_inodeblock: lost dep2");
3867 panic("softdep_write_inodeblock: lost dep3");
3631 }
3632#endif /* DIAGNOSTIC */
3633 dp->di_ib[i] = 0;
3634 }
3635 FREE_LOCK(&lk);
3636 return;
3637 }
3638 /*

--- 161 unchanged lines hidden (view full) ---

3800 * Called from within softdep_disk_write_complete above. Note that
3801 * this routine is always called from interrupt level with further
3802 * splbio interrupts blocked.
3803 */
3804static void
3805handle_allocdirect_partdone(adp)
3806 struct allocdirect *adp; /* the completed allocdirect */
3807{
3868 }
3869#endif /* DIAGNOSTIC */
3870 dp->di_ib[i] = 0;
3871 }
3872 FREE_LOCK(&lk);
3873 return;
3874 }
3875 /*

--- 161 unchanged lines hidden (view full) ---

4037 * Called from within softdep_disk_write_complete above. Note that
4038 * this routine is always called from interrupt level with further
4039 * splbio interrupts blocked.
4040 */
4041static void
4042handle_allocdirect_partdone(adp)
4043 struct allocdirect *adp; /* the completed allocdirect */
4044{
4045 struct allocdirectlst *listhead;
3808 struct allocdirect *listadp;
3809 struct inodedep *inodedep;
3810 long bsize, delay;
3811
3812 if ((adp->ad_state & ALLCOMPLETE) != ALLCOMPLETE)
3813 return;
3814 if (adp->ad_buf != NULL) {
3815 lk.lkt_held = NOHOLDER;
3816 panic("handle_allocdirect_partdone: dangling dep");
3817 }
3818 /*
3819 * The on-disk inode cannot claim to be any larger than the last
3820 * fragment that has been written. Otherwise, the on-disk inode
3821 * might have fragments that were not the last block in the file
3822 * which would corrupt the filesystem. Thus, we cannot free any
3823 * allocdirects after one whose ad_oldblkno claims a fragment as
3824 * these blocks must be rolled back to zero before writing the inode.
4046 struct allocdirect *listadp;
4047 struct inodedep *inodedep;
4048 long bsize, delay;
4049
4050 if ((adp->ad_state & ALLCOMPLETE) != ALLCOMPLETE)
4051 return;
4052 if (adp->ad_buf != NULL) {
4053 lk.lkt_held = NOHOLDER;
4054 panic("handle_allocdirect_partdone: dangling dep");
4055 }
4056 /*
4057 * The on-disk inode cannot claim to be any larger than the last
4058 * fragment that has been written. Otherwise, the on-disk inode
4059 * might have fragments that were not the last block in the file
4060 * which would corrupt the filesystem. Thus, we cannot free any
4061 * allocdirects after one whose ad_oldblkno claims a fragment as
4062 * these blocks must be rolled back to zero before writing the inode.
3825 * We check the currently active set of allocdirects in id_inoupdt.
4063 * We check the currently active set of allocdirects in id_inoupdt
4064 * or id_extupdt as appropriate.
3826 */
3827 inodedep = adp->ad_inodedep;
3828 bsize = inodedep->id_fs->fs_bsize;
4065 */
4066 inodedep = adp->ad_inodedep;
4067 bsize = inodedep->id_fs->fs_bsize;
3829 TAILQ_FOREACH(listadp, &inodedep->id_inoupdt, ad_next) {
4068 if (adp->ad_state & EXTDATA)
4069 listhead = &inodedep->id_extupdt;
4070 else
4071 listhead = &inodedep->id_inoupdt;
4072 TAILQ_FOREACH(listadp, listhead, ad_next) {
3830 /* found our block */
3831 if (listadp == adp)
3832 break;
3833 /* continue if ad_oldlbn is not a fragment */
3834 if (listadp->ad_oldsize == 0 ||
3835 listadp->ad_oldsize == bsize)
3836 continue;
3837 /* hit a fragment */
3838 return;
3839 }
3840 /*
3841 * If we have reached the end of the current list without
3842 * finding the just finished dependency, then it must be
3843 * on the future dependency list. Future dependencies cannot
3844 * be freed until they are moved to the current list.
3845 */
3846 if (listadp == NULL) {
3847#ifdef DEBUG
4073 /* found our block */
4074 if (listadp == adp)
4075 break;
4076 /* continue if ad_oldlbn is not a fragment */
4077 if (listadp->ad_oldsize == 0 ||
4078 listadp->ad_oldsize == bsize)
4079 continue;
4080 /* hit a fragment */
4081 return;
4082 }
4083 /*
4084 * If we have reached the end of the current list without
4085 * finding the just finished dependency, then it must be
4086 * on the future dependency list. Future dependencies cannot
4087 * be freed until they are moved to the current list.
4088 */
4089 if (listadp == NULL) {
4090#ifdef DEBUG
3848 TAILQ_FOREACH(listadp, &inodedep->id_newinoupdt, ad_next)
4091 if (adp->ad_state & EXTDATA)
4092 listhead = &inodedep->id_newextupdt;
4093 else
4094 listhead = &inodedep->id_newinoupdt;
4095 TAILQ_FOREACH(listadp, listhead, ad_next)
3849 /* found our block */
3850 if (listadp == adp)
3851 break;
3852 if (listadp == NULL) {
3853 lk.lkt_held = NOHOLDER;
3854 panic("handle_allocdirect_partdone: lost dep");
3855 }
3856#endif /* DEBUG */

--- 6 unchanged lines hidden (view full) ---

3863 * never been written to disk, hence the on-disk inode cannot
3864 * reference the old fragment so we can free it without delay.
3865 */
3866 delay = (inodedep->id_state & DEPCOMPLETE);
3867 for (; adp; adp = listadp) {
3868 listadp = TAILQ_NEXT(adp, ad_next);
3869 if ((adp->ad_state & ALLCOMPLETE) != ALLCOMPLETE)
3870 return;
4096 /* found our block */
4097 if (listadp == adp)
4098 break;
4099 if (listadp == NULL) {
4100 lk.lkt_held = NOHOLDER;
4101 panic("handle_allocdirect_partdone: lost dep");
4102 }
4103#endif /* DEBUG */

--- 6 unchanged lines hidden (view full) ---

4110 * never been written to disk, hence the on-disk inode cannot
4111 * reference the old fragment so we can free it without delay.
4112 */
4113 delay = (inodedep->id_state & DEPCOMPLETE);
4114 for (; adp; adp = listadp) {
4115 listadp = TAILQ_NEXT(adp, ad_next);
4116 if ((adp->ad_state & ALLCOMPLETE) != ALLCOMPLETE)
4117 return;
3871 free_allocdirect(&inodedep->id_inoupdt, adp, delay);
4118 free_allocdirect(listhead, adp, delay);
3872 }
3873}
3874
3875/*
3876 * Called from within softdep_disk_write_complete above. Note that
3877 * this routine is always called from interrupt level with further
3878 * splbio interrupts blocked.
3879 */

--- 138 unchanged lines hidden (view full) ---

4018 dp2->di_ib[adp->ad_lbn - NDADDR] =
4019 adp->ad_newblkno;
4020 }
4021 }
4022 adp->ad_state &= ~UNDONE;
4023 adp->ad_state |= ATTACHED;
4024 hadchanges = 1;
4025 }
4119 }
4120}
4121
4122/*
4123 * Called from within softdep_disk_write_complete above. Note that
4124 * this routine is always called from interrupt level with further
4125 * splbio interrupts blocked.
4126 */

--- 138 unchanged lines hidden (view full) ---

4265 dp2->di_ib[adp->ad_lbn - NDADDR] =
4266 adp->ad_newblkno;
4267 }
4268 }
4269 adp->ad_state &= ~UNDONE;
4270 adp->ad_state |= ATTACHED;
4271 hadchanges = 1;
4272 }
4273 for (adp = TAILQ_FIRST(&inodedep->id_extupdt); adp; adp = nextadp) {
4274 nextadp = TAILQ_NEXT(adp, ad_next);
4275 if (adp->ad_state & ATTACHED) {
4276 lk.lkt_held = NOHOLDER;
4277 panic("handle_written_inodeblock: new entry");
4278 }
4279 if (dp2->di_extb[adp->ad_lbn] != adp->ad_oldblkno) {
4280 lk.lkt_held = NOHOLDER;
4281 panic("%s: direct pointers #%jd %s %jd != %jd",
4282 "handle_written_inodeblock",
4283 (intmax_t)adp->ad_lbn, "mismatch",
4284 (intmax_t)dp2->di_extb[adp->ad_lbn],
4285 (intmax_t)adp->ad_oldblkno);
4286 }
4287 dp2->di_extb[adp->ad_lbn] = adp->ad_newblkno;
4288 adp->ad_state &= ~UNDONE;
4289 adp->ad_state |= ATTACHED;
4290 hadchanges = 1;
4291 }
4026 if (hadchanges && (bp->b_flags & B_DELWRI) == 0)
4027 stat_direct_blk_ptrs++;
4028 /*
4029 * Reset the file size to its most up-to-date value.
4030 */
4292 if (hadchanges && (bp->b_flags & B_DELWRI) == 0)
4293 stat_direct_blk_ptrs++;
4294 /*
4295 * Reset the file size to its most up-to-date value.
4296 */
4031 if (inodedep->id_savedsize == -1) {
4297 if (inodedep->id_savedsize == -1 || inodedep->id_savedextsize == -1) {
4032 lk.lkt_held = NOHOLDER;
4033 panic("handle_written_inodeblock: bad size");
4034 }
4035 if (fstype == UFS1) {
4036 if (dp1->di_size != inodedep->id_savedsize) {
4037 dp1->di_size = inodedep->id_savedsize;
4038 hadchanges = 1;
4039 }
4040 } else {
4041 if (dp2->di_size != inodedep->id_savedsize) {
4042 dp2->di_size = inodedep->id_savedsize;
4043 hadchanges = 1;
4044 }
4298 lk.lkt_held = NOHOLDER;
4299 panic("handle_written_inodeblock: bad size");
4300 }
4301 if (fstype == UFS1) {
4302 if (dp1->di_size != inodedep->id_savedsize) {
4303 dp1->di_size = inodedep->id_savedsize;
4304 hadchanges = 1;
4305 }
4306 } else {
4307 if (dp2->di_size != inodedep->id_savedsize) {
4308 dp2->di_size = inodedep->id_savedsize;
4309 hadchanges = 1;
4310 }
4311 if (dp2->di_extsize != inodedep->id_savedextsize) {
4312 dp2->di_extsize = inodedep->id_savedextsize;
4313 hadchanges = 1;
4314 }
4045 }
4046 inodedep->id_savedsize = -1;
4315 }
4316 inodedep->id_savedsize = -1;
4317 inodedep->id_savedextsize = -1;
4047 /*
4048 * If there were any rollbacks in the inode block, then it must be
4049 * marked dirty so that its will eventually get written back in
4050 * its correct form.
4051 */
4052 if (hadchanges)
4053 bdirty(bp);
4054 /*
4055 * Process any allocdirects that completed during the update.
4056 */
4057 if ((adp = TAILQ_FIRST(&inodedep->id_inoupdt)) != NULL)
4058 handle_allocdirect_partdone(adp);
4318 /*
4319 * If there were any rollbacks in the inode block, then it must be
4320 * marked dirty so that its will eventually get written back in
4321 * its correct form.
4322 */
4323 if (hadchanges)
4324 bdirty(bp);
4325 /*
4326 * Process any allocdirects that completed during the update.
4327 */
4328 if ((adp = TAILQ_FIRST(&inodedep->id_inoupdt)) != NULL)
4329 handle_allocdirect_partdone(adp);
4330 if ((adp = TAILQ_FIRST(&inodedep->id_extupdt)) != NULL)
4331 handle_allocdirect_partdone(adp);
4059 /*
4060 * Process deallocations that were held pending until the
4061 * inode had been written to disk. Freeing of the inode
4062 * is delayed until after all blocks have been freed to
4063 * avoid creation of new <vfsid, inum, lbn> triples
4064 * before the old ones have been deleted.
4065 */
4066 filefree = NULL;

--- 47 unchanged lines hidden (view full) ---

4114 }
4115 add_to_worklist(filefree);
4116 return (0);
4117 }
4118
4119 /*
4120 * If no outstanding dependencies, free it.
4121 */
4332 /*
4333 * Process deallocations that were held pending until the
4334 * inode had been written to disk. Freeing of the inode
4335 * is delayed until after all blocks have been freed to
4336 * avoid creation of new <vfsid, inum, lbn> triples
4337 * before the old ones have been deleted.
4338 */
4339 filefree = NULL;

--- 47 unchanged lines hidden (view full) ---

4387 }
4388 add_to_worklist(filefree);
4389 return (0);
4390 }
4391
4392 /*
4393 * If no outstanding dependencies, free it.
4394 */
4122 if (free_inodedep(inodedep) || TAILQ_FIRST(&inodedep->id_inoupdt) == 0)
4395 if (free_inodedep(inodedep) ||
4396 (TAILQ_FIRST(&inodedep->id_inoupdt) == 0 &&
4397 TAILQ_FIRST(&inodedep->id_extupdt) == 0))
4123 return (0);
4124 return (hadchanges);
4125}
4126
4127/*
4128 * Process a diradd entry after its dependent inode has been written.
4129 * This routine must be called with splbio interrupts blocked.
4130 */

--- 222 unchanged lines hidden (view full) ---

4353 if ((inodedep->id_state & ONWORKLIST) == 0)
4354 WORKLIST_INSERT(&bp->b_dep, &inodedep->id_list);
4355 /*
4356 * Any new dependencies associated with the incore inode must
4357 * now be moved to the list associated with the buffer holding
4358 * the in-memory copy of the inode. Once merged process any
4359 * allocdirects that are completed by the merger.
4360 */
4398 return (0);
4399 return (hadchanges);
4400}
4401
4402/*
4403 * Process a diradd entry after its dependent inode has been written.
4404 * This routine must be called with splbio interrupts blocked.
4405 */

--- 222 unchanged lines hidden (view full) ---

4628 if ((inodedep->id_state & ONWORKLIST) == 0)
4629 WORKLIST_INSERT(&bp->b_dep, &inodedep->id_list);
4630 /*
4631 * Any new dependencies associated with the incore inode must
4632 * now be moved to the list associated with the buffer holding
4633 * the in-memory copy of the inode. Once merged process any
4634 * allocdirects that are completed by the merger.
4635 */
4361 merge_inode_lists(inodedep);
4636 merge_inode_lists(&inodedep->id_newinoupdt, &inodedep->id_inoupdt);
4362 if (TAILQ_FIRST(&inodedep->id_inoupdt) != NULL)
4363 handle_allocdirect_partdone(TAILQ_FIRST(&inodedep->id_inoupdt));
4637 if (TAILQ_FIRST(&inodedep->id_inoupdt) != NULL)
4638 handle_allocdirect_partdone(TAILQ_FIRST(&inodedep->id_inoupdt));
4639 merge_inode_lists(&inodedep->id_newextupdt, &inodedep->id_extupdt);
4640 if (TAILQ_FIRST(&inodedep->id_extupdt) != NULL)
4641 handle_allocdirect_partdone(TAILQ_FIRST(&inodedep->id_extupdt));
4364 /*
4365 * Now that the inode has been pushed into the buffer, the
4366 * operations dependent on the inode being written to disk
4367 * can be moved to the id_bufwait so that they will be
4368 * processed when the buffer I/O completes.
4369 */
4370 while ((wk = LIST_FIRST(&inodedep->id_inowait)) != NULL) {
4371 WORKLIST_REMOVE(wk);

--- 15 unchanged lines hidden (view full) ---

4387 if (gotit &&
4388 (error = BUF_WRITE(inodedep->id_buf)) != 0)
4389 softdep_error("softdep_update_inodeblock: bwrite", error);
4390 if ((inodedep->id_state & DEPCOMPLETE) == 0)
4391 panic("softdep_update_inodeblock: update failed");
4392}
4393
4394/*
4642 /*
4643 * Now that the inode has been pushed into the buffer, the
4644 * operations dependent on the inode being written to disk
4645 * can be moved to the id_bufwait so that they will be
4646 * processed when the buffer I/O completes.
4647 */
4648 while ((wk = LIST_FIRST(&inodedep->id_inowait)) != NULL) {
4649 WORKLIST_REMOVE(wk);

--- 15 unchanged lines hidden (view full) ---

4665 if (gotit &&
4666 (error = BUF_WRITE(inodedep->id_buf)) != 0)
4667 softdep_error("softdep_update_inodeblock: bwrite", error);
4668 if ((inodedep->id_state & DEPCOMPLETE) == 0)
4669 panic("softdep_update_inodeblock: update failed");
4670}
4671
4672/*
4395 * Merge the new inode dependency list (id_newinoupdt) into the old
4396 * inode dependency list (id_inoupdt). This routine must be called
4397 * with splbio interrupts blocked.
4673 * Merge the a new inode dependency list (such as id_newinoupdt) into an
4674 * old inode dependency list (such as id_inoupdt). This routine must be
4675 * called with splbio interrupts blocked.
4398 */
4399static void
4676 */
4677static void
4400merge_inode_lists(inodedep)
4401 struct inodedep *inodedep;
4678merge_inode_lists(newlisthead, oldlisthead)
4679 struct allocdirectlst *newlisthead;
4680 struct allocdirectlst *oldlisthead;
4402{
4403 struct allocdirect *listadp, *newadp;
4404
4681{
4682 struct allocdirect *listadp, *newadp;
4683
4405 newadp = TAILQ_FIRST(&inodedep->id_newinoupdt);
4406 for (listadp = TAILQ_FIRST(&inodedep->id_inoupdt); listadp && newadp;) {
4684 newadp = TAILQ_FIRST(newlisthead);
4685 for (listadp = TAILQ_FIRST(oldlisthead); listadp && newadp;) {
4407 if (listadp->ad_lbn < newadp->ad_lbn) {
4408 listadp = TAILQ_NEXT(listadp, ad_next);
4409 continue;
4410 }
4686 if (listadp->ad_lbn < newadp->ad_lbn) {
4687 listadp = TAILQ_NEXT(listadp, ad_next);
4688 continue;
4689 }
4411 TAILQ_REMOVE(&inodedep->id_newinoupdt, newadp, ad_next);
4690 TAILQ_REMOVE(newlisthead, newadp, ad_next);
4412 TAILQ_INSERT_BEFORE(listadp, newadp, ad_next);
4413 if (listadp->ad_lbn == newadp->ad_lbn) {
4691 TAILQ_INSERT_BEFORE(listadp, newadp, ad_next);
4692 if (listadp->ad_lbn == newadp->ad_lbn) {
4414 allocdirect_merge(&inodedep->id_inoupdt, newadp,
4693 allocdirect_merge(oldlisthead, newadp,
4415 listadp);
4416 listadp = newadp;
4417 }
4694 listadp);
4695 listadp = newadp;
4696 }
4418 newadp = TAILQ_FIRST(&inodedep->id_newinoupdt);
4697 newadp = TAILQ_FIRST(newlisthead);
4419 }
4698 }
4420 while ((newadp = TAILQ_FIRST(&inodedep->id_newinoupdt)) != NULL) {
4421 TAILQ_REMOVE(&inodedep->id_newinoupdt, newadp, ad_next);
4422 TAILQ_INSERT_TAIL(&inodedep->id_inoupdt, newadp, ad_next);
4699 while ((newadp = TAILQ_FIRST(newlisthead)) != NULL) {
4700 TAILQ_REMOVE(newlisthead, newadp, ad_next);
4701 TAILQ_INSERT_TAIL(oldlisthead, newadp, ad_next);
4423 }
4424}
4425
4426/*
4427 * If we are doing an fsync, then we must ensure that any directory
4428 * entries for the inode have been written after the inode gets to disk.
4429 */
4430int

--- 18 unchanged lines hidden (view full) ---

4449 fs = ip->i_fs;
4450 ACQUIRE_LOCK(&lk);
4451 if (inodedep_lookup(fs, ip->i_number, 0, &inodedep) == 0) {
4452 FREE_LOCK(&lk);
4453 return (0);
4454 }
4455 if (LIST_FIRST(&inodedep->id_inowait) != NULL ||
4456 LIST_FIRST(&inodedep->id_bufwait) != NULL ||
4702 }
4703}
4704
4705/*
4706 * If we are doing an fsync, then we must ensure that any directory
4707 * entries for the inode have been written after the inode gets to disk.
4708 */
4709int

--- 18 unchanged lines hidden (view full) ---

4728 fs = ip->i_fs;
4729 ACQUIRE_LOCK(&lk);
4730 if (inodedep_lookup(fs, ip->i_number, 0, &inodedep) == 0) {
4731 FREE_LOCK(&lk);
4732 return (0);
4733 }
4734 if (LIST_FIRST(&inodedep->id_inowait) != NULL ||
4735 LIST_FIRST(&inodedep->id_bufwait) != NULL ||
4736 TAILQ_FIRST(&inodedep->id_extupdt) != NULL ||
4737 TAILQ_FIRST(&inodedep->id_newextupdt) != NULL ||
4457 TAILQ_FIRST(&inodedep->id_inoupdt) != NULL ||
4458 TAILQ_FIRST(&inodedep->id_newinoupdt) != NULL) {
4459 FREE_LOCK(&lk);
4460 panic("softdep_fsync: pending ops");
4461 }
4462 for (error = 0, flushparent = 0; ; ) {
4463 if ((wk = LIST_FIRST(&inodedep->id_pendinghd)) == NULL)
4464 break;

--- 407 unchanged lines hidden (view full) ---

4872 * Called with splbio blocked.
4873 */
4874static int
4875flush_inodedep_deps(fs, ino)
4876 struct fs *fs;
4877 ino_t ino;
4878{
4879 struct inodedep *inodedep;
4738 TAILQ_FIRST(&inodedep->id_inoupdt) != NULL ||
4739 TAILQ_FIRST(&inodedep->id_newinoupdt) != NULL) {
4740 FREE_LOCK(&lk);
4741 panic("softdep_fsync: pending ops");
4742 }
4743 for (error = 0, flushparent = 0; ; ) {
4744 if ((wk = LIST_FIRST(&inodedep->id_pendinghd)) == NULL)
4745 break;

--- 407 unchanged lines hidden (view full) ---

5153 * Called with splbio blocked.
5154 */
5155static int
5156flush_inodedep_deps(fs, ino)
5157 struct fs *fs;
5158 ino_t ino;
5159{
5160 struct inodedep *inodedep;
4880 struct allocdirect *adp;
4881 int error, waitfor;
5161 int error, waitfor;
4882 struct buf *bp;
4883
4884 /*
4885 * This work is done in two passes. The first pass grabs most
4886 * of the buffers and begins asynchronously writing them. The
4887 * only way to wait for these asynchronous writes is to sleep
4888 * on the filesystem vnode which may stay busy for a long time
4889 * if the filesystem is active. So, instead, we make a second
4890 * pass over the dependencies blocking on each write. In the
4891 * usual case we will be blocking against a write that we
4892 * initiated, so when it is done the dependency will have been
4893 * resolved. Thus the second pass is expected to end quickly.
4894 * We give a brief window at the top of the loop to allow
4895 * any pending I/O to complete.
4896 */
5162
5163 /*
5164 * This work is done in two passes. The first pass grabs most
5165 * of the buffers and begins asynchronously writing them. The
5166 * only way to wait for these asynchronous writes is to sleep
5167 * on the filesystem vnode which may stay busy for a long time
5168 * if the filesystem is active. So, instead, we make a second
5169 * pass over the dependencies blocking on each write. In the
5170 * usual case we will be blocking against a write that we
5171 * initiated, so when it is done the dependency will have been
5172 * resolved. Thus the second pass is expected to end quickly.
5173 * We give a brief window at the top of the loop to allow
5174 * any pending I/O to complete.
5175 */
4897 for (waitfor = MNT_NOWAIT; ; ) {
5176 for (error = 0, waitfor = MNT_NOWAIT; ; ) {
5177 if (error)
5178 return (error);
4898 FREE_LOCK(&lk);
4899 ACQUIRE_LOCK(&lk);
4900 if (inodedep_lookup(fs, ino, 0, &inodedep) == 0)
4901 return (0);
5179 FREE_LOCK(&lk);
5180 ACQUIRE_LOCK(&lk);
5181 if (inodedep_lookup(fs, ino, 0, &inodedep) == 0)
5182 return (0);
4902 TAILQ_FOREACH(adp, &inodedep->id_inoupdt, ad_next) {
4903 if (adp->ad_state & DEPCOMPLETE)
4904 continue;
4905 bp = adp->ad_buf;
4906 if (getdirtybuf(&bp, waitfor) == 0) {
4907 if (waitfor == MNT_NOWAIT)
4908 continue;
4909 break;
4910 }
4911 FREE_LOCK(&lk);
4912 if (waitfor == MNT_NOWAIT) {
4913 bawrite(bp);
4914 } else if ((error = BUF_WRITE(bp)) != 0) {
4915 ACQUIRE_LOCK(&lk);
4916 return (error);
4917 }
4918 ACQUIRE_LOCK(&lk);
4919 break;
4920 }
4921 if (adp != NULL)
5183 if (flush_deplist(&inodedep->id_inoupdt, waitfor, &error) ||
5184 flush_deplist(&inodedep->id_newinoupdt, waitfor, &error) ||
5185 flush_deplist(&inodedep->id_extupdt, waitfor, &error) ||
5186 flush_deplist(&inodedep->id_newextupdt, waitfor, &error))
4922 continue;
5187 continue;
4923 TAILQ_FOREACH(adp, &inodedep->id_newinoupdt, ad_next) {
4924 if (adp->ad_state & DEPCOMPLETE)
4925 continue;
4926 bp = adp->ad_buf;
4927 if (getdirtybuf(&bp, waitfor) == 0) {
4928 if (waitfor == MNT_NOWAIT)
4929 continue;
4930 break;
4931 }
4932 FREE_LOCK(&lk);
4933 if (waitfor == MNT_NOWAIT) {
4934 bawrite(bp);
4935 } else if ((error = BUF_WRITE(bp)) != 0) {
4936 ACQUIRE_LOCK(&lk);
4937 return (error);
4938 }
4939 ACQUIRE_LOCK(&lk);
4940 break;
4941 }
4942 if (adp != NULL)
4943 continue;
4944 /*
4945 * If pass2, we are done, otherwise do pass 2.
4946 */
4947 if (waitfor == MNT_WAIT)
4948 break;
4949 waitfor = MNT_WAIT;
4950 }
4951 /*
4952 * Try freeing inodedep in case all dependencies have been removed.
4953 */
4954 if (inodedep_lookup(fs, ino, 0, &inodedep) != 0)
4955 (void) free_inodedep(inodedep);
4956 return (0);
4957}
4958
4959/*
5188 /*
5189 * If pass2, we are done, otherwise do pass 2.
5190 */
5191 if (waitfor == MNT_WAIT)
5192 break;
5193 waitfor = MNT_WAIT;
5194 }
5195 /*
5196 * Try freeing inodedep in case all dependencies have been removed.
5197 */
5198 if (inodedep_lookup(fs, ino, 0, &inodedep) != 0)
5199 (void) free_inodedep(inodedep);
5200 return (0);
5201}
5202
5203/*
5204 * Flush an inode dependency list.
5205 * Called with splbio blocked.
5206 */
5207static int
5208flush_deplist(listhead, waitfor, errorp)
5209 struct allocdirectlst *listhead;
5210 int waitfor;
5211 int *errorp;
5212{
5213 struct allocdirect *adp;
5214 struct buf *bp;
5215
5216 TAILQ_FOREACH(adp, listhead, ad_next) {
5217 if (adp->ad_state & DEPCOMPLETE)
5218 continue;
5219 bp = adp->ad_buf;
5220 if (getdirtybuf(&bp, waitfor) == 0) {
5221 if (waitfor == MNT_NOWAIT)
5222 continue;
5223 return (1);
5224 }
5225 FREE_LOCK(&lk);
5226 if (waitfor == MNT_NOWAIT) {
5227 bawrite(bp);
5228 } else if ((*errorp = BUF_WRITE(bp)) != 0) {
5229 ACQUIRE_LOCK(&lk);
5230 return (1);
5231 }
5232 ACQUIRE_LOCK(&lk);
5233 return (1);
5234 }
5235 return (0);
5236}
5237
5238/*
4960 * Eliminate a pagedep dependency by flushing out all its diradd dependencies.
4961 * Called with splbio blocked.
4962 */
4963static int
4964flush_pagedep_deps(pvp, mp, diraddhdp)
4965 struct vnode *pvp;
4966 struct mount *mp;
4967 struct diraddhd *diraddhdp;

--- 433 unchanged lines hidden (view full) ---

5401 goto out;
5402 }
5403 if (TAILQ_FIRST(&inodedep->id_inoupdt)) {
5404 /* direct block pointer dependency */
5405 retval += 1;
5406 if (!wantcount)
5407 goto out;
5408 }
5239 * Eliminate a pagedep dependency by flushing out all its diradd dependencies.
5240 * Called with splbio blocked.
5241 */
5242static int
5243flush_pagedep_deps(pvp, mp, diraddhdp)
5244 struct vnode *pvp;
5245 struct mount *mp;
5246 struct diraddhd *diraddhdp;

--- 433 unchanged lines hidden (view full) ---

5680 goto out;
5681 }
5682 if (TAILQ_FIRST(&inodedep->id_inoupdt)) {
5683 /* direct block pointer dependency */
5684 retval += 1;
5685 if (!wantcount)
5686 goto out;
5687 }
5688 if (TAILQ_FIRST(&inodedep->id_extupdt)) {
5689 /* direct block pointer dependency */
5690 retval += 1;
5691 if (!wantcount)
5692 goto out;
5693 }
5409 continue;
5410
5411 case D_INDIRDEP:
5412 indirdep = WK_INDIRDEP(wk);
5413
5414 LIST_FOREACH(aip, &indirdep->ir_deplisthd, ai_next) {
5415 /* indirect block pointer dependency */
5416 retval += 1;

--- 130 unchanged lines hidden ---
5694 continue;
5695
5696 case D_INDIRDEP:
5697 indirdep = WK_INDIRDEP(wk);
5698
5699 LIST_FOREACH(aip, &indirdep->ir_deplisthd, ai_next) {
5700 /* indirect block pointer dependency */
5701 retval += 1;

--- 130 unchanged lines hidden ---