diff options
Diffstat (limited to 'sys/ufs')
-rw-r--r-- | sys/ufs/ffs/ffs_inode.c | 2 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_softdep.c | 59 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_softdep_stub.c | 9 | ||||
-rw-r--r-- | sys/ufs/ffs/ffs_vfsops.c | 39 | ||||
-rw-r--r-- | sys/ufs/ffs/fs.h | 4 | ||||
-rw-r--r-- | sys/ufs/ffs/softdep.h | 7 | ||||
-rw-r--r-- | sys/ufs/ufs/inode.h | 7 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_extern.h | 1 | ||||
-rw-r--r-- | sys/ufs/ufs/ufs_inode.c | 2 |
9 files changed, 119 insertions, 11 deletions
diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c index 7a3c7ee..3af19b5 100644 --- a/sys/ufs/ffs/ffs_inode.c +++ b/sys/ufs/ffs/ffs_inode.c @@ -193,6 +193,8 @@ ffs_truncate(vp, length, flags, cred, p) if ((error = VOP_FSYNC(ovp, cred, MNT_WAIT, p)) != 0) return (error); + if (oip->i_flag & IN_SPACECOUNTED) + fs->fs_pendingblocks -= oip->i_blocks; } else { #ifdef QUOTA (void) chkdq(oip, -oip->i_blocks, NOCRED, 0); diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index 2b88fe6..d950301 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -57,6 +57,7 @@ #include <sys/malloc.h> #include <sys/mount.h> #include <sys/proc.h> +#include <sys/stat.h> #include <sys/syslog.h> #include <sys/vnode.h> #include <sys/conf.h> @@ -1725,7 +1726,7 @@ softdep_setup_freeblocks(ip, length) fs = ip->i_fs; if (length != 0) - panic("softde_setup_freeblocks: non-zero length"); + panic("softdep_setup_freeblocks: non-zero length"); MALLOC(freeblks, struct freeblks *, sizeof(struct freeblks), M_FREEBLKS, M_SOFTDEP_FLAGS|M_ZERO); freeblks->fb_list.wk_type = D_FREEBLKS; @@ -1747,6 +1748,13 @@ softdep_setup_freeblocks(ip, length) ip->i_blocks = 0; ip->i_size = 0; /* + * If the file was removed, then the space being freed was + * accounted for then (see softdep_filereleased()). If the + * file is merely being truncated, then we account for it now. + */ + if ((ip->i_flag & IN_SPACECOUNTED) == 0) + fs->fs_pendingblocks += freeblks->fb_chkcnt; + /* * Push the zero'ed inode to to its disk buffer so that we are free * to delete its dependencies below. Once the dependencies are gone * the buffer can be safely released. @@ -1986,6 +1994,8 @@ softdep_freefile(pvp, ino, mode) freefile->fx_oldinum = ino; freefile->fx_devvp = ip->i_devvp; freefile->fx_mnt = ITOV(ip)->v_mount; + if ((ip->i_flag & IN_SPACECOUNTED) == 0) + ip->i_fs->fs_pendinginodes += 1; /* * If the inodedep does not exist, then the zero'ed inode has @@ -2118,6 +2128,7 @@ handle_workitem_freeblocks(freeblks, flags) baselbns[level], &blocksreleased)) == 0) allerror = error; ffs_blkfree(&tip, bn, fs->fs_bsize); + fs->fs_pendingblocks -= nblocks; blocksreleased += nblocks; } /* @@ -2128,6 +2139,7 @@ handle_workitem_freeblocks(freeblks, flags) continue; bsize = blksize(fs, &tip, i); ffs_blkfree(&tip, bn, bsize); + fs->fs_pendingblocks -= btodb(bsize); blocksreleased += btodb(bsize); } /* @@ -2229,6 +2241,7 @@ indir_trunc(ip, dbn, level, lbn, countp) allerror = error; } ffs_blkfree(ip, nb, fs->fs_bsize); + fs->fs_pendingblocks -= nblocks; *countp += nblocks; } bp->b_flags |= B_INVAL | B_NOCACHE; @@ -2780,6 +2793,47 @@ softdep_change_linkcnt(ip) } /* + * Called when the effective link count and the reference count + * on an inode drops to zero. At this point there are no names + * referencing the file in the filesystem and no active file + * references. The space associated with the file will be freed + * as soon as the necessary soft dependencies are cleared. + */ +void +softdep_releasefile(ip) + struct inode *ip; /* inode with the zero effective link count */ +{ + struct inodedep *inodedep; + + if (ip->i_effnlink > 0) + panic("softdep_filerelease: file still referenced"); + /* + * We may be called several times as the real reference count + * drops to zero. We only want to account for the space once. + */ + if (ip->i_flag & IN_SPACECOUNTED) + return; + /* + * We have to deactivate a snapshot otherwise copyonwrites may + * add blocks and the cleanup may remove blocks after we have + * tried to account for them. + */ + if ((ip->i_flags & SF_SNAPSHOT) != 0) + ffs_snapremove(ITOV(ip)); + /* + * If we are tracking an nlinkdelta, we have to also remember + * whether we accounted for the freed space yet. + */ + ACQUIRE_LOCK(&lk); + if ((inodedep_lookup(ip->i_fs, ip->i_number, 0, &inodedep))) + inodedep->id_state |= SPACECOUNTED; + FREE_LOCK(&lk); + ip->i_fs->fs_pendingblocks += ip->i_blocks; + ip->i_fs->fs_pendinginodes += 1; + ip->i_flag |= IN_SPACECOUNTED; +} + +/* * This workitem decrements the inode's link count. * If the link count reaches zero, the file is removed. */ @@ -2905,6 +2959,7 @@ handle_workitem_freefile(freefile) tip.i_devvp = freefile->fx_devvp; tip.i_dev = freefile->fx_devvp->v_rdev; tip.i_fs = fs; + fs->fs_pendinginodes -= 1; if ((error = ffs_freefile(&tip, freefile->fx_oldinum, freefile->fx_mode)) != 0) softdep_error("handle_workitem_freefile", error); WORKITEM_FREE(freefile, D_FREEFILE); @@ -3779,6 +3834,8 @@ softdep_load_inodeblock(ip) return; } ip->i_effnlink -= inodedep->id_nlinkdelta; + if (inodedep->id_state & SPACECOUNTED) + ip->i_flag |= IN_SPACECOUNTED; FREE_LOCK(&lk); } diff --git a/sys/ufs/ffs/ffs_softdep_stub.c b/sys/ufs/ffs/ffs_softdep_stub.c index 95c9475..3460b7c 100644 --- a/sys/ufs/ffs/ffs_softdep_stub.c +++ b/sys/ufs/ffs/ffs_softdep_stub.c @@ -270,6 +270,15 @@ int softdep_slowdown(vp) struct vnode *vp; { + panic("softdep_slowdown called"); } + +void +softdep_releasefile(ip) + struct inode *ip; /* inode with the zero effective link count */ +{ + + panic("softdep_releasefile called"); +} #endif /* SOFTUPDATES not configured in */ diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index b1fb0cf..04ba155 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -192,6 +192,14 @@ ffs_mount(mp, path, data, ndp, p) vn_finished_write(mp); return (error); } + if (fs->fs_pendingblocks != 0 || + fs->fs_pendinginodes != 0) { + printf("%s: update error: blocks %d files %d\n", + fs->fs_fsmnt, fs->fs_pendingblocks, + fs->fs_pendinginodes); + fs->fs_pendingblocks = 0; + fs->fs_pendinginodes = 0; + } fs->fs_ronly = 1; if ((fs->fs_flags & (FS_UNCLEAN | FS_NEEDSFSCK)) == 0) fs->fs_clean = 1; @@ -433,6 +441,12 @@ ffs_reload(mp, cred, p) fs->fs_avgfilesize = AVFILESIZ; /* XXX */ if (fs->fs_avgfpdir <= 0) /* XXX */ fs->fs_avgfpdir = AFPDIR; /* XXX */ + if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) { + printf("%s: reload pending error: blocks %d files %d\n", + fs->fs_fsmnt, fs->fs_pendingblocks, fs->fs_pendinginodes); + fs->fs_pendingblocks = 0; + fs->fs_pendinginodes = 0; + } /* * Step 3: re-read summary information from disk. @@ -609,6 +623,18 @@ ffs_mountfs(devvp, mp, p, malloctype) error = EPERM; goto out; } + if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) { + printf("%s: lost blocks %d files %d\n", fs->fs_fsmnt, + fs->fs_pendingblocks, fs->fs_pendinginodes); + fs->fs_pendingblocks = 0; + fs->fs_pendinginodes = 0; + } + } + if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) { + printf("%s: mount pending error: blocks %d files %d\n", + fs->fs_fsmnt, fs->fs_pendingblocks, fs->fs_pendinginodes); + fs->fs_pendingblocks = 0; + fs->fs_pendinginodes = 0; } /* XXX updating 4.2 FFS superblocks trashes rotational layout tables */ if (fs->fs_postblformat == FS_42POSTBLFMT && !ronly) { @@ -826,6 +852,12 @@ ffs_unmount(mp, mntflags, p) fs->fs_cgsize = fs->fs_sparecon[0]; fs->fs_sparecon[0] = 0; } + if (fs->fs_pendingblocks != 0 || fs->fs_pendinginodes != 0) { + printf("%s: unmount pending error: blocks %d files %d\n", + fs->fs_fsmnt, fs->fs_pendingblocks, fs->fs_pendinginodes); + fs->fs_pendingblocks = 0; + fs->fs_pendinginodes = 0; + } if (fs->fs_ronly == 0) { fs->fs_clean = fs->fs_flags & (FS_UNCLEAN|FS_NEEDSFSCK) ? 0 : 1; error = ffs_sbupdate(ump, MNT_WAIT); @@ -923,10 +955,11 @@ ffs_statfs(mp, sbp, p) sbp->f_iosize = fs->fs_bsize; sbp->f_blocks = fs->fs_dsize; sbp->f_bfree = fs->fs_cstotal.cs_nbfree * fs->fs_frag + - fs->fs_cstotal.cs_nffree; - sbp->f_bavail = freespace(fs, fs->fs_minfree); + fs->fs_cstotal.cs_nffree + dbtofsb(fs, fs->fs_pendingblocks); + sbp->f_bavail = freespace(fs, fs->fs_minfree) + + dbtofsb(fs, fs->fs_pendingblocks); sbp->f_files = fs->fs_ncg * fs->fs_ipg - ROOTINO; - sbp->f_ffree = fs->fs_cstotal.cs_nifree; + sbp->f_ffree = fs->fs_cstotal.cs_nifree + fs->fs_pendinginodes; if (sbp != &mp->mnt_stat) { sbp->f_type = mp->mnt_vfc->vfc_typenum; bcopy((caddr_t)mp->mnt_stat.f_mntonname, diff --git a/sys/ufs/ffs/fs.h b/sys/ufs/ffs/fs.h index b9cab9a..0a3ad96 100644 --- a/sys/ufs/ffs/fs.h +++ b/sys/ufs/ffs/fs.h @@ -295,7 +295,9 @@ struct fs { int32_t fs_snapinum[FSMAXSNAP];/* list of snapshot inode numbers */ int32_t fs_avgfilesize; /* expected average file size */ int32_t fs_avgfpdir; /* expected # of files per directory */ - int32_t fs_sparecon[28]; /* reserved for future constants */ + int32_t fs_sparecon[26]; /* reserved for future constants */ + int32_t fs_pendingblocks; /* blocks in process of being freed */ + int32_t fs_pendinginodes; /* inodes in process of being freed */ int32_t fs_contigsumsize; /* size of cluster summary array */ int32_t fs_maxsymlinklen; /* max length of an internal symlink */ int32_t fs_inodefmt; /* format of on-disk inodes */ diff --git a/sys/ufs/ffs/softdep.h b/sys/ufs/ffs/softdep.h index cf9cac8..9a158c5 100644 --- a/sys/ufs/ffs/softdep.h +++ b/sys/ufs/ffs/softdep.h @@ -82,8 +82,10 @@ * data structure is frozen from further change until its dependencies * have been completed and its resources freed after which it will be * discarded. The IOSTARTED flag prevents multiple calls to the I/O - * start routine from doing multiple rollbacks. The ONWORKLIST flag - * shows whether the structure is currently linked onto a worklist. + * start routine from doing multiple rollbacks. The SPACECOUNTED flag + * says that the files space has been accounted to the pending free + * space count. The ONWORKLIST flag shows whether the structure is + * currently linked onto a worklist. */ #define ATTACHED 0x0001 #define UNDONE 0x0002 @@ -95,6 +97,7 @@ #define DIRCHG 0x0080 #define GOINGAWAY 0x0100 #define IOSTARTED 0x0200 +#define SPACECOUNTED 0x0400 #define ONWORKLIST 0x8000 #define ALLCOMPLETE (ATTACHED | COMPLETE | DEPCOMPLETE) diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h index 3e7c67d..0fdaee2 100644 --- a/sys/ufs/ufs/inode.h +++ b/sys/ufs/ufs/inode.h @@ -125,10 +125,9 @@ struct inode { #define IN_UPDATE 0x0004 /* Modification time update request. */ #define IN_MODIFIED 0x0008 /* Inode has been modified. */ #define IN_RENAME 0x0010 /* Inode is being renamed. */ -#define IN_SHLOCK 0x0020 /* File has shared lock. */ -#define IN_EXLOCK 0x0040 /* File has exclusive lock. */ -#define IN_HASHED 0x0080 /* Inode is on hash list */ -#define IN_LAZYMOD 0x0100 /* Modified, but don't write yet. */ +#define IN_HASHED 0x0020 /* Inode is on hash list */ +#define IN_LAZYMOD 0x0040 /* Modified, but don't write yet. */ +#define IN_SPACECOUNTED 0x0080 /* Blocks to be freed in free count. */ #ifdef _KERNEL /* diff --git a/sys/ufs/ufs/ufs_extern.h b/sys/ufs/ufs/ufs_extern.h index 2a98e9b..e08ee8d 100644 --- a/sys/ufs/ufs/ufs_extern.h +++ b/sys/ufs/ufs/ufs_extern.h @@ -104,6 +104,7 @@ void softdep_setup_remove __P((struct buf *,struct inode *, struct inode *, void softdep_setup_directory_change __P((struct buf *, struct inode *, struct inode *, long, int)); void softdep_change_linkcnt __P((struct inode *)); +void softdep_releasefile __P((struct inode *)); int softdep_slowdown __P((struct vnode *)); #endif /* !_UFS_UFS_EXTERN_H_ */ diff --git a/sys/ufs/ufs/ufs_inode.c b/sys/ufs/ufs/ufs_inode.c index d4ed8b3..4f4638d 100644 --- a/sys/ufs/ufs/ufs_inode.c +++ b/sys/ufs/ufs/ufs_inode.c @@ -77,6 +77,8 @@ ufs_inactive(ap) */ if (ip->i_mode == 0) goto out; + if (ip->i_effnlink == 0 && DOINGSOFTDEP(vp)) + softdep_releasefile(ip); if (ip->i_nlink <= 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { (void) vn_write_suspend_wait(vp, NULL, V_WAIT); #ifdef QUOTA |