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 --- |