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 *
--- 22 unchanged lines hidden (view full) ---
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
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 * $FreeBSD: head/sys/ufs/ffs/ffs_softdep.c 76357 2001-05-08 07:42:20Z mckusick $
40 */
41
42/*
43 * For now we want the safety net that the DIAGNOSTIC and DEBUG flags provide.
44 */
45#ifndef DIAGNOSTIC
46#define DIAGNOSTIC
47#endif
--- 4 unchanged lines hidden (view full) ---
52#include <sys/param.h>
53#include <sys/kernel.h>
54#include <sys/systm.h>
55#include <sys/bio.h>
56#include <sys/buf.h>
57#include <sys/malloc.h>
58#include <sys/mount.h>
59#include <sys/proc.h>
60#include <sys/stat.h>
61#include <sys/syslog.h>
62#include <sys/vnode.h>
63#include <sys/conf.h>
64#include <ufs/ufs/dir.h>
65#include <ufs/ufs/extattr.h>
66#include <ufs/ufs/quota.h>
67#include <ufs/ufs/inode.h>
68#include <ufs/ufs/ufsmount.h>
--- 1652 unchanged lines hidden (view full) ---
1721 struct allocdirect *adp;
1722 struct vnode *vp;
1723 struct buf *bp;
1724 struct fs *fs;
1725 int i, delay, error;
1726
1727 fs = ip->i_fs;
1728 if (length != 0)
1729 panic("softdep_setup_freeblocks: non-zero length");
1730 MALLOC(freeblks, struct freeblks *, sizeof(struct freeblks),
1731 M_FREEBLKS, M_SOFTDEP_FLAGS|M_ZERO);
1732 freeblks->fb_list.wk_type = D_FREEBLKS;
1733 freeblks->fb_uid = ip->i_uid;
1734 freeblks->fb_previousinum = ip->i_number;
1735 freeblks->fb_devvp = ip->i_devvp;
1736 freeblks->fb_mnt = ITOV(ip)->v_mount;
1737 freeblks->fb_oldsize = ip->i_size;
--- 5 unchanged lines hidden (view full) ---
1743 }
1744 for (i = 0; i < NIADDR; i++) {
1745 freeblks->fb_iblks[i] = ip->i_ib[i];
1746 ip->i_ib[i] = 0;
1747 }
1748 ip->i_blocks = 0;
1749 ip->i_size = 0;
1750 /*
1751 * If the file was removed, then the space being freed was
1752 * accounted for then (see softdep_filereleased()). If the
1753 * file is merely being truncated, then we account for it now.
1754 */
1755 if ((ip->i_flag & IN_SPACECOUNTED) == 0)
1756 fs->fs_pendingblocks += freeblks->fb_chkcnt;
1757 /*
1758 * Push the zero'ed inode to to its disk buffer so that we are free
1759 * to delete its dependencies below. Once the dependencies are gone
1760 * the buffer can be safely released.
1761 */
1762 if ((error = bread(ip->i_devvp,
1763 fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
1764 (int)fs->fs_bsize, NOCRED, &bp)) != 0)
1765 softdep_error("softdep_setup_freeblocks", error);
--- 223 unchanged lines hidden (view full) ---
1989 MALLOC(freefile, struct freefile *, sizeof(struct freefile),
1990 M_FREEFILE, M_SOFTDEP_FLAGS);
1991 freefile->fx_list.wk_type = D_FREEFILE;
1992 freefile->fx_list.wk_state = 0;
1993 freefile->fx_mode = mode;
1994 freefile->fx_oldinum = ino;
1995 freefile->fx_devvp = ip->i_devvp;
1996 freefile->fx_mnt = ITOV(ip)->v_mount;
1997 if ((ip->i_flag & IN_SPACECOUNTED) == 0)
1998 ip->i_fs->fs_pendinginodes += 1;
1999
2000 /*
2001 * If the inodedep does not exist, then the zero'ed inode has
2002 * been written to disk. If the allocated inode has never been
2003 * written to disk, then the on-disk inode is zero'ed. In either
2004 * case we can free the file immediately.
2005 */
2006 ACQUIRE_LOCK(&lk);
--- 116 unchanged lines hidden (view full) ---
2123 */
2124 for (level = (NIADDR - 1); level >= 0; level--) {
2125 if ((bn = freeblks->fb_iblks[level]) == 0)
2126 continue;
2127 if ((error = indir_trunc(&tip, fsbtodb(fs, bn), level,
2128 baselbns[level], &blocksreleased)) == 0)
2129 allerror = error;
2130 ffs_blkfree(&tip, bn, fs->fs_bsize);
2131 fs->fs_pendingblocks -= nblocks;
2132 blocksreleased += nblocks;
2133 }
2134 /*
2135 * All direct blocks or frags.
2136 */
2137 for (i = (NDADDR - 1); i >= 0; i--) {
2138 if ((bn = freeblks->fb_dblks[i]) == 0)
2139 continue;
2140 bsize = blksize(fs, &tip, i);
2141 ffs_blkfree(&tip, bn, bsize);
2142 fs->fs_pendingblocks -= btodb(bsize);
2143 blocksreleased += btodb(bsize);
2144 }
2145 /*
2146 * If we still have not finished background cleanup, then check
2147 * to see if the block count needs to be adjusted.
2148 */
2149 if (freeblks->fb_chkcnt != blocksreleased &&
2150 (fs->fs_flags & FS_UNCLEAN) != 0 && (flags & LK_NOWAIT) == 0 &&
--- 85 unchanged lines hidden (view full) ---
2236 if ((nb = bap[i]) == 0)
2237 continue;
2238 if (level != 0) {
2239 if ((error = indir_trunc(ip, fsbtodb(fs, nb),
2240 level - 1, lbn + (i * lbnadd), countp)) != 0)
2241 allerror = error;
2242 }
2243 ffs_blkfree(ip, nb, fs->fs_bsize);
2244 fs->fs_pendingblocks -= nblocks;
2245 *countp += nblocks;
2246 }
2247 bp->b_flags |= B_INVAL | B_NOCACHE;
2248 brelse(bp);
2249 return (allerror);
2250}
2251
2252/*
--- 535 unchanged lines hidden (view full) ---
2788 FREE_LOCK(&lk);
2789 panic("softdep_change_linkcnt: bad delta");
2790 }
2791 inodedep->id_nlinkdelta = ip->i_nlink - ip->i_effnlink;
2792 FREE_LOCK(&lk);
2793}
2794
2795/*
2796 * Called when the effective link count and the reference count
2797 * on an inode drops to zero. At this point there are no names
2798 * referencing the file in the filesystem and no active file
2799 * references. The space associated with the file will be freed
2800 * as soon as the necessary soft dependencies are cleared.
2801 */
2802void
2803softdep_releasefile(ip)
2804 struct inode *ip; /* inode with the zero effective link count */
2805{
2806 struct inodedep *inodedep;
2807
2808 if (ip->i_effnlink > 0)
2809 panic("softdep_filerelease: file still referenced");
2810 /*
2811 * We may be called several times as the real reference count
2812 * drops to zero. We only want to account for the space once.
2813 */
2814 if (ip->i_flag & IN_SPACECOUNTED)
2815 return;
2816 /*
2817 * We have to deactivate a snapshot otherwise copyonwrites may
2818 * add blocks and the cleanup may remove blocks after we have
2819 * tried to account for them.
2820 */
2821 if ((ip->i_flags & SF_SNAPSHOT) != 0)
2822 ffs_snapremove(ITOV(ip));
2823 /*
2824 * If we are tracking an nlinkdelta, we have to also remember
2825 * whether we accounted for the freed space yet.
2826 */
2827 ACQUIRE_LOCK(&lk);
2828 if ((inodedep_lookup(ip->i_fs, ip->i_number, 0, &inodedep)))
2829 inodedep->id_state |= SPACECOUNTED;
2830 FREE_LOCK(&lk);
2831 ip->i_fs->fs_pendingblocks += ip->i_blocks;
2832 ip->i_fs->fs_pendinginodes += 1;
2833 ip->i_flag |= IN_SPACECOUNTED;
2834}
2835
2836/*
2837 * This workitem decrements the inode's link count.
2838 * If the link count reaches zero, the file is removed.
2839 */
2840static void
2841handle_workitem_remove(dirrem)
2842 struct dirrem *dirrem;
2843{
2844 struct proc *p = CURPROC; /* XXX */
--- 109 unchanged lines hidden (view full) ---
2954 error = inodedep_lookup(fs, freefile->fx_oldinum, 0, &idp);
2955 FREE_LOCK(&lk);
2956 if (error)
2957 panic("handle_workitem_freefile: inodedep survived");
2958#endif
2959 tip.i_devvp = freefile->fx_devvp;
2960 tip.i_dev = freefile->fx_devvp->v_rdev;
2961 tip.i_fs = fs;
2962 fs->fs_pendinginodes -= 1;
2963 if ((error = ffs_freefile(&tip, freefile->fx_oldinum, freefile->fx_mode)) != 0)
2964 softdep_error("handle_workitem_freefile", error);
2965 WORKITEM_FREE(freefile, D_FREEFILE);
2966}
2967
2968/*
2969 * Disk writes.
2970 *
--- 858 unchanged lines hidden (view full) ---
3829 */
3830 ip->i_effnlink = ip->i_nlink;
3831 ACQUIRE_LOCK(&lk);
3832 if (inodedep_lookup(ip->i_fs, ip->i_number, 0, &inodedep) == 0) {
3833 FREE_LOCK(&lk);
3834 return;
3835 }
3836 ip->i_effnlink -= inodedep->id_nlinkdelta;
3837 if (inodedep->id_state & SPACECOUNTED)
3838 ip->i_flag |= IN_SPACECOUNTED;
3839 FREE_LOCK(&lk);
3840}
3841
3842/*
3843 * This routine is called just before the "in-core" inode
3844 * information is to be copied to the in-memory inode block.
3845 * Recall that an inode block contains several inodes. If
3846 * the force flag is set, then the dependencies will be
--- 1169 unchanged lines hidden ---
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 *
--- 22 unchanged lines hidden (view full) ---
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
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 * $FreeBSD: head/sys/ufs/ffs/ffs_softdep.c 76357 2001-05-08 07:42:20Z mckusick $
40 */
41
42/*
43 * For now we want the safety net that the DIAGNOSTIC and DEBUG flags provide.
44 */
45#ifndef DIAGNOSTIC
46#define DIAGNOSTIC
47#endif
--- 4 unchanged lines hidden (view full) ---
52#include <sys/param.h>
53#include <sys/kernel.h>
54#include <sys/systm.h>
55#include <sys/bio.h>
56#include <sys/buf.h>
57#include <sys/malloc.h>
58#include <sys/mount.h>
59#include <sys/proc.h>
60#include <sys/stat.h>
61#include <sys/syslog.h>
62#include <sys/vnode.h>
63#include <sys/conf.h>
64#include <ufs/ufs/dir.h>
65#include <ufs/ufs/extattr.h>
66#include <ufs/ufs/quota.h>
67#include <ufs/ufs/inode.h>
68#include <ufs/ufs/ufsmount.h>
--- 1652 unchanged lines hidden (view full) ---
1721 struct allocdirect *adp;
1722 struct vnode *vp;
1723 struct buf *bp;
1724 struct fs *fs;
1725 int i, delay, error;
1726
1727 fs = ip->i_fs;
1728 if (length != 0)
1729 panic("softdep_setup_freeblocks: non-zero length");
1730 MALLOC(freeblks, struct freeblks *, sizeof(struct freeblks),
1731 M_FREEBLKS, M_SOFTDEP_FLAGS|M_ZERO);
1732 freeblks->fb_list.wk_type = D_FREEBLKS;
1733 freeblks->fb_uid = ip->i_uid;
1734 freeblks->fb_previousinum = ip->i_number;
1735 freeblks->fb_devvp = ip->i_devvp;
1736 freeblks->fb_mnt = ITOV(ip)->v_mount;
1737 freeblks->fb_oldsize = ip->i_size;
--- 5 unchanged lines hidden (view full) ---
1743 }
1744 for (i = 0; i < NIADDR; i++) {
1745 freeblks->fb_iblks[i] = ip->i_ib[i];
1746 ip->i_ib[i] = 0;
1747 }
1748 ip->i_blocks = 0;
1749 ip->i_size = 0;
1750 /*
1751 * If the file was removed, then the space being freed was
1752 * accounted for then (see softdep_filereleased()). If the
1753 * file is merely being truncated, then we account for it now.
1754 */
1755 if ((ip->i_flag & IN_SPACECOUNTED) == 0)
1756 fs->fs_pendingblocks += freeblks->fb_chkcnt;
1757 /*
1758 * Push the zero'ed inode to to its disk buffer so that we are free
1759 * to delete its dependencies below. Once the dependencies are gone
1760 * the buffer can be safely released.
1761 */
1762 if ((error = bread(ip->i_devvp,
1763 fsbtodb(fs, ino_to_fsba(fs, ip->i_number)),
1764 (int)fs->fs_bsize, NOCRED, &bp)) != 0)
1765 softdep_error("softdep_setup_freeblocks", error);
--- 223 unchanged lines hidden (view full) ---
1989 MALLOC(freefile, struct freefile *, sizeof(struct freefile),
1990 M_FREEFILE, M_SOFTDEP_FLAGS);
1991 freefile->fx_list.wk_type = D_FREEFILE;
1992 freefile->fx_list.wk_state = 0;
1993 freefile->fx_mode = mode;
1994 freefile->fx_oldinum = ino;
1995 freefile->fx_devvp = ip->i_devvp;
1996 freefile->fx_mnt = ITOV(ip)->v_mount;
1997 if ((ip->i_flag & IN_SPACECOUNTED) == 0)
1998 ip->i_fs->fs_pendinginodes += 1;
1999
2000 /*
2001 * If the inodedep does not exist, then the zero'ed inode has
2002 * been written to disk. If the allocated inode has never been
2003 * written to disk, then the on-disk inode is zero'ed. In either
2004 * case we can free the file immediately.
2005 */
2006 ACQUIRE_LOCK(&lk);
--- 116 unchanged lines hidden (view full) ---
2123 */
2124 for (level = (NIADDR - 1); level >= 0; level--) {
2125 if ((bn = freeblks->fb_iblks[level]) == 0)
2126 continue;
2127 if ((error = indir_trunc(&tip, fsbtodb(fs, bn), level,
2128 baselbns[level], &blocksreleased)) == 0)
2129 allerror = error;
2130 ffs_blkfree(&tip, bn, fs->fs_bsize);
2131 fs->fs_pendingblocks -= nblocks;
2132 blocksreleased += nblocks;
2133 }
2134 /*
2135 * All direct blocks or frags.
2136 */
2137 for (i = (NDADDR - 1); i >= 0; i--) {
2138 if ((bn = freeblks->fb_dblks[i]) == 0)
2139 continue;
2140 bsize = blksize(fs, &tip, i);
2141 ffs_blkfree(&tip, bn, bsize);
2142 fs->fs_pendingblocks -= btodb(bsize);
2143 blocksreleased += btodb(bsize);
2144 }
2145 /*
2146 * If we still have not finished background cleanup, then check
2147 * to see if the block count needs to be adjusted.
2148 */
2149 if (freeblks->fb_chkcnt != blocksreleased &&
2150 (fs->fs_flags & FS_UNCLEAN) != 0 && (flags & LK_NOWAIT) == 0 &&
--- 85 unchanged lines hidden (view full) ---
2236 if ((nb = bap[i]) == 0)
2237 continue;
2238 if (level != 0) {
2239 if ((error = indir_trunc(ip, fsbtodb(fs, nb),
2240 level - 1, lbn + (i * lbnadd), countp)) != 0)
2241 allerror = error;
2242 }
2243 ffs_blkfree(ip, nb, fs->fs_bsize);
2244 fs->fs_pendingblocks -= nblocks;
2245 *countp += nblocks;
2246 }
2247 bp->b_flags |= B_INVAL | B_NOCACHE;
2248 brelse(bp);
2249 return (allerror);
2250}
2251
2252/*
--- 535 unchanged lines hidden (view full) ---
2788 FREE_LOCK(&lk);
2789 panic("softdep_change_linkcnt: bad delta");
2790 }
2791 inodedep->id_nlinkdelta = ip->i_nlink - ip->i_effnlink;
2792 FREE_LOCK(&lk);
2793}
2794
2795/*
2796 * Called when the effective link count and the reference count
2797 * on an inode drops to zero. At this point there are no names
2798 * referencing the file in the filesystem and no active file
2799 * references. The space associated with the file will be freed
2800 * as soon as the necessary soft dependencies are cleared.
2801 */
2802void
2803softdep_releasefile(ip)
2804 struct inode *ip; /* inode with the zero effective link count */
2805{
2806 struct inodedep *inodedep;
2807
2808 if (ip->i_effnlink > 0)
2809 panic("softdep_filerelease: file still referenced");
2810 /*
2811 * We may be called several times as the real reference count
2812 * drops to zero. We only want to account for the space once.
2813 */
2814 if (ip->i_flag & IN_SPACECOUNTED)
2815 return;
2816 /*
2817 * We have to deactivate a snapshot otherwise copyonwrites may
2818 * add blocks and the cleanup may remove blocks after we have
2819 * tried to account for them.
2820 */
2821 if ((ip->i_flags & SF_SNAPSHOT) != 0)
2822 ffs_snapremove(ITOV(ip));
2823 /*
2824 * If we are tracking an nlinkdelta, we have to also remember
2825 * whether we accounted for the freed space yet.
2826 */
2827 ACQUIRE_LOCK(&lk);
2828 if ((inodedep_lookup(ip->i_fs, ip->i_number, 0, &inodedep)))
2829 inodedep->id_state |= SPACECOUNTED;
2830 FREE_LOCK(&lk);
2831 ip->i_fs->fs_pendingblocks += ip->i_blocks;
2832 ip->i_fs->fs_pendinginodes += 1;
2833 ip->i_flag |= IN_SPACECOUNTED;
2834}
2835
2836/*
2837 * This workitem decrements the inode's link count.
2838 * If the link count reaches zero, the file is removed.
2839 */
2840static void
2841handle_workitem_remove(dirrem)
2842 struct dirrem *dirrem;
2843{
2844 struct proc *p = CURPROC; /* XXX */
--- 109 unchanged lines hidden (view full) ---
2954 error = inodedep_lookup(fs, freefile->fx_oldinum, 0, &idp);
2955 FREE_LOCK(&lk);
2956 if (error)
2957 panic("handle_workitem_freefile: inodedep survived");
2958#endif
2959 tip.i_devvp = freefile->fx_devvp;
2960 tip.i_dev = freefile->fx_devvp->v_rdev;
2961 tip.i_fs = fs;
2962 fs->fs_pendinginodes -= 1;
2963 if ((error = ffs_freefile(&tip, freefile->fx_oldinum, freefile->fx_mode)) != 0)
2964 softdep_error("handle_workitem_freefile", error);
2965 WORKITEM_FREE(freefile, D_FREEFILE);
2966}
2967
2968/*
2969 * Disk writes.
2970 *
--- 858 unchanged lines hidden (view full) ---
3829 */
3830 ip->i_effnlink = ip->i_nlink;
3831 ACQUIRE_LOCK(&lk);
3832 if (inodedep_lookup(ip->i_fs, ip->i_number, 0, &inodedep) == 0) {
3833 FREE_LOCK(&lk);
3834 return;
3835 }
3836 ip->i_effnlink -= inodedep->id_nlinkdelta;
3837 if (inodedep->id_state & SPACECOUNTED)
3838 ip->i_flag |= IN_SPACECOUNTED;
3839 FREE_LOCK(&lk);
3840}
3841
3842/*
3843 * This routine is called just before the "in-core" inode
3844 * information is to be copied to the in-memory inode block.
3845 * Recall that an inode block contains several inodes. If
3846 * the force flag is set, then the dependencies will be
--- 1169 unchanged lines hidden ---