summaryrefslogtreecommitdiffstats
path: root/sys/ufs/ffs
diff options
context:
space:
mode:
Diffstat (limited to 'sys/ufs/ffs')
-rw-r--r--sys/ufs/ffs/ffs_inode.c2
-rw-r--r--sys/ufs/ffs/ffs_softdep.c59
-rw-r--r--sys/ufs/ffs/ffs_softdep_stub.c9
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c39
-rw-r--r--sys/ufs/ffs/fs.h4
-rw-r--r--sys/ufs/ffs/softdep.h7
6 files changed, 113 insertions, 7 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)
OpenPOWER on IntegriCloud