summaryrefslogtreecommitdiffstats
path: root/sys/ufs/ffs
diff options
context:
space:
mode:
authormckusick <mckusick@FreeBSD.org>2014-08-14 23:38:04 +0000
committermckusick <mckusick@FreeBSD.org>2014-08-14 23:38:04 +0000
commitd042b7653225b4e6f4a35f5cc44fb95a02edf775 (patch)
treed5eac70f2e32c6549e55859c06c5eed5ccc3b37e /sys/ufs/ffs
parentcabf1ab5da244a22f50146e3ebe638c11ce55b7e (diff)
downloadFreeBSD-src-d042b7653225b4e6f4a35f5cc44fb95a02edf775.zip
FreeBSD-src-d042b7653225b4e6f4a35f5cc44fb95a02edf775.tar.gz
MFC of 269674:
The journal is only prepared to handle full-size block numbers, so we have to adjust freeblk records to reflect the change to a full-size block. For example, suppose we have a block made up of fragments 8-15 and want to free its last two fragments. We are given a request that says: FREEBLK ino=5, blkno=14, lbn=0, frags=2, oldfrags=0 where frags are the number of frags to free and oldfrags are the number of fragments to keep. To block align it, we have to change it to have a valid full-size blkno, so it becomes: FREEBLK ino=5, blkno=8, lbn=0, frags=2, oldfrags=6 Submitted by: Mikihito Takehara Tested by: Mikihito Takehara Reviewed by: Jeff Roberson
Diffstat (limited to 'sys/ufs/ffs')
-rw-r--r--sys/ufs/ffs/ffs_softdep.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 2e0adb0..f17659a 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -931,6 +931,7 @@ static inline struct jsegdep *inoref_jseg(struct inoref *);
static struct jmvref *newjmvref(struct inode *, ino_t, off_t, off_t);
static struct jfreeblk *newjfreeblk(struct freeblks *, ufs_lbn_t,
ufs2_daddr_t, int);
+static void adjust_newfreework(struct freeblks *, int);
static struct jtrunc *newjtrunc(struct freeblks *, off_t, int);
static void move_newblock_dep(struct jaddref *, struct inodedep *);
static void cancel_jfreeblk(struct freeblks *, ufs2_daddr_t);
@@ -4066,6 +4067,33 @@ newjfreeblk(freeblks, lbn, blkno, frags)
}
/*
+ * The journal is only prepared to handle full-size block numbers, so we
+ * have to adjust the record to reflect the change to a full-size block.
+ * For example, suppose we have a block made up of fragments 8-15 and
+ * want to free its last two fragments. We are given a request that says:
+ * FREEBLK ino=5, blkno=14, lbn=0, frags=2, oldfrags=0
+ * where frags are the number of fragments to free and oldfrags are the
+ * number of fragments to keep. To block align it, we have to change it to
+ * have a valid full-size blkno, so it becomes:
+ * FREEBLK ino=5, blkno=8, lbn=0, frags=2, oldfrags=6
+ */
+static void
+adjust_newfreework(freeblks, frag_offset)
+ struct freeblks *freeblks;
+ int frag_offset;
+{
+ struct jfreeblk *jfreeblk;
+
+ KASSERT((LIST_FIRST(&freeblks->fb_jblkdephd) != NULL &&
+ LIST_FIRST(&freeblks->fb_jblkdephd)->jb_list.wk_type == D_JFREEBLK),
+ ("adjust_newfreework: Missing freeblks dependency"));
+
+ jfreeblk = WK_JFREEBLK(LIST_FIRST(&freeblks->fb_jblkdephd));
+ jfreeblk->jf_blkno -= frag_offset;
+ jfreeblk->jf_frags += frag_offset;
+}
+
+/*
* Allocate a new jtrunc to track a partial truncation.
*/
static struct jtrunc *
@@ -6432,6 +6460,9 @@ softdep_journal_freeblocks(ip, cred, length, flags)
blkno += numfrags(ip->i_fs, frags);
newfreework(ump, freeblks, NULL, lastlbn,
blkno, oldfrags, 0, needj);
+ if (needj)
+ adjust_newfreework(freeblks,
+ numfrags(ip->i_fs, frags));
} else if (blkno == 0)
allocblock = 1;
}
OpenPOWER on IntegriCloud