Date: Fri, 18 Apr 2014 17:03:35 +0000 (UTC) From: Warner Losh <imp@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r264657 - head/sys/fs/nandfs Message-ID: <201404181703.s3IH3Zn4050308@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: imp Date: Fri Apr 18 17:03:35 2014 New Revision: 264657 URL: http://svnweb.freebsd.org/changeset/base/264657 Log: 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@ Modified: head/sys/fs/nandfs/bmap.c head/sys/fs/nandfs/nandfs.h head/sys/fs/nandfs/nandfs_subr.c head/sys/fs/nandfs/nandfs_vfsops.c Modified: head/sys/fs/nandfs/bmap.c ============================================================================== --- head/sys/fs/nandfs/bmap.c Fri Apr 18 17:03:09 2014 (r264656) +++ head/sys/fs/nandfs/bmap.c Fri Apr 18 17:03:35 2014 (r264657) @@ -387,11 +387,10 @@ bmap_truncate_indirect(struct nandfs_nod 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 Modified: head/sys/fs/nandfs/nandfs.h ============================================================================== --- head/sys/fs/nandfs/nandfs.h Fri Apr 18 17:03:09 2014 (r264656) +++ head/sys/fs/nandfs/nandfs.h Fri Apr 18 17:03:35 2014 (r264657) @@ -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; Modified: head/sys/fs/nandfs/nandfs_subr.c ============================================================================== --- head/sys/fs/nandfs/nandfs_subr.c Fri Apr 18 17:03:09 2014 (r264656) +++ head/sys/fs/nandfs/nandfs_subr.c Fri Apr 18 17:03:35 2014 (r264657) @@ -910,7 +910,7 @@ nandfs_fs_full(struct nandfs_device *nff 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); Modified: head/sys/fs/nandfs/nandfs_vfsops.c ============================================================================== --- head/sys/fs/nandfs/nandfs_vfsops.c Fri Apr 18 17:03:09 2014 (r264656) +++ head/sys/fs/nandfs/nandfs_vfsops.c Fri Apr 18 17:03:35 2014 (r264657) @@ -718,15 +718,24 @@ nandfs_mount_base(struct nandfs_device * 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"));
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201404181703.s3IH3Zn4050308>