summaryrefslogtreecommitdiffstats
path: root/sys/fs/nandfs
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2014-04-18 17:03:35 +0000
committerimp <imp@FreeBSD.org>2014-04-18 17:03:35 +0000
commitdc1d630338e8d8a813fdacbb556799df5848769f (patch)
tree24e84b99523987d4a513aaac339ae3d299645197 /sys/fs/nandfs
parent60d8af5ab8dbbf78749c82867d7dff8923b733ed (diff)
downloadFreeBSD-src-dc1d630338e8d8a813fdacbb556799df5848769f.zip
FreeBSD-src-dc1d630338e8d8a813fdacbb556799df5848769f.tar.gz
More properly account for free/reserved segments to avoid deadlock or
worse when filling up a device and then trying to erase files to make space. Without enough space, you can't do that. Also, ensure that the metadata writes don't generate ENOSPC. They will be retried later since the buffers are still dirty... Submitted by: mjg@
Diffstat (limited to 'sys/fs/nandfs')
-rw-r--r--sys/fs/nandfs/bmap.c7
-rw-r--r--sys/fs/nandfs/nandfs.h2
-rw-r--r--sys/fs/nandfs/nandfs_subr.c2
-rw-r--r--sys/fs/nandfs/nandfs_vfsops.c13
4 files changed, 17 insertions, 7 deletions
diff --git a/sys/fs/nandfs/bmap.c b/sys/fs/nandfs/bmap.c
index 4cc4cb0..cd46d10 100644
--- a/sys/fs/nandfs/bmap.c
+++ b/sys/fs/nandfs/bmap.c
@@ -387,11 +387,10 @@ bmap_truncate_indirect(struct nandfs_node *node, int level, nandfs_lbn_t *left,
if (modified)
bcopy(copy, bp->b_data, fsdev->nd_blocksize);
- error = nandfs_dirty_buf_meta(bp, 0);
- if (error)
- return (error);
+ /* Force success even if we can't dirty the buffer metadata when freeing space */
+ nandfs_dirty_buf_meta(bp, 1);
- return (error);
+ return (0);
}
int
diff --git a/sys/fs/nandfs/nandfs.h b/sys/fs/nandfs/nandfs.h
index beb4e16..2c093be 100644
--- a/sys/fs/nandfs/nandfs.h
+++ b/sys/fs/nandfs/nandfs.h
@@ -200,6 +200,8 @@ struct nandfs_device {
uint32_t nd_devblocksize;
+ uint32_t nd_segs_reserved;
+
/* Segment usage */
uint64_t nd_clean_segs;
uint64_t *nd_free_base;
diff --git a/sys/fs/nandfs/nandfs_subr.c b/sys/fs/nandfs/nandfs_subr.c
index 961a0a8..5ed31e7 100644
--- a/sys/fs/nandfs/nandfs_subr.c
+++ b/sys/fs/nandfs/nandfs_subr.c
@@ -910,7 +910,7 @@ nandfs_fs_full(struct nandfs_device *nffsdev)
DPRINTF(BUF, ("%s: bufs:%jx space:%jx\n", __func__,
(uintmax_t)nffsdev->nd_dirty_bufs, (uintmax_t)space));
- if (nffsdev->nd_dirty_bufs + (10 * bps) >= space)
+ if (nffsdev->nd_dirty_bufs + (nffsdev->nd_segs_reserved * bps) >= space)
return (1);
return (0);
diff --git a/sys/fs/nandfs/nandfs_vfsops.c b/sys/fs/nandfs/nandfs_vfsops.c
index fd9b0c9..33b7564 100644
--- a/sys/fs/nandfs/nandfs_vfsops.c
+++ b/sys/fs/nandfs/nandfs_vfsops.c
@@ -718,15 +718,24 @@ nandfs_mount_base(struct nandfs_device *nandfsdev, struct mount *mp,
nandfsdev->nd_ts.tv_sec = nandfsdev->nd_last_segsum.ss_create;
nandfsdev->nd_last_cno = nandfsdev->nd_super.s_last_cno;
nandfsdev->nd_fakevblk = 1;
+ /*
+ * FIXME: bogus calculation. Should use actual number of usable segments
+ * instead of total amount.
+ */
+ nandfsdev->nd_segs_reserved =
+ nandfsdev->nd_fsdata.f_nsegments *
+ nandfsdev->nd_fsdata.f_r_segments_percentage / 100;
nandfsdev->nd_last_ino = NANDFS_USER_INO;
DPRINTF(VOLUMES, ("%s: last_pseg %#jx last_cno %#jx last_seq %#jx\n"
- "fsdev: last_seg: seq %#jx num %#jx, next_seg_num %#jx\n",
+ "fsdev: last_seg: seq %#jx num %#jx, next_seg_num %#jx "
+ "segs_reserved %#jx\n",
__func__, (uintmax_t)nandfsdev->nd_last_pseg,
(uintmax_t)nandfsdev->nd_last_cno,
(uintmax_t)nandfsdev->nd_seg_sequence,
(uintmax_t)nandfsdev->nd_seg_sequence,
(uintmax_t)nandfsdev->nd_seg_num,
- (uintmax_t)nandfsdev->nd_next_seg_num));
+ (uintmax_t)nandfsdev->nd_next_seg_num,
+ (uintmax_t)nandfsdev->nd_segs_reserved));
DPRINTF(VOLUMES, ("nandfs_mount: accepted super root\n"));
OpenPOWER on IntegriCloud