From 1fd136ec5eb0f9d693164b1b94d7d0c46b1519a5 Mon Sep 17 00:00:00 2001 From: Kirk McKusick Date: Tue, 16 Jul 2019 23:12:27 +0000 Subject: [PATCH] When a process attempts to allocate space on a full filesystem, a filesystem full message is sent to the offending process or the kernel log if the offending process cannot be identified. To prevent an explotion of messages, the kernel ppsratecheck() function is used to limit the messages to one per second. This revision changes the variable that tracks the rate of these messages from a systemwide limit to a per-filesystem limit by moving it from a global variable to a variable in the ufsmount structure. Suggested by: kib Reviewed by: kib Sponsored by: Netflix --- sys/ufs/ffs/ffs_alloc.c | 30 ++++++++++++++++-------------- sys/ufs/ffs/ffs_balloc.c | 36 ++++++++++++++++++++++++------------ sys/ufs/ufs/ufsmount.h | 2 ++ 3 files changed, 42 insertions(+), 26 deletions(-) diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index 9ebdec0c88c4..e6b297a680db 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -158,8 +158,6 @@ ffs_alloc(ip, lbn, bpref, size, flags, cred, bnp) struct ufsmount *ump; ufs2_daddr_t bno; u_int cg, reclaimed; - static struct timeval lastfail; - static int curfail; int64_t delta; #ifdef QUOTA int error; @@ -224,11 +222,14 @@ ffs_alloc(ip, lbn, bpref, size, flags, cred, bnp) softdep_request_cleanup(fs, ITOV(ip), cred, FLUSH_BLOCKS_WAIT); goto retry; } - UFS_UNLOCK(ump); - if (reclaimed > 0 && ppsratecheck(&lastfail, &curfail, 1)) { + if (reclaimed > 0 && + ppsratecheck(&ump->um_last_fullmsg, &ump->um_secs_fullmsg, 1)) { + UFS_UNLOCK(ump); ffs_fserr(fs, ip->i_number, "filesystem full"); uprintf("\n%s: write failed, filesystem is full\n", fs->fs_fsmnt); + } else { + UFS_UNLOCK(ump); } return (ENOSPC); } @@ -258,8 +259,6 @@ ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, flags, cred, bpp) u_int cg, request, reclaimed; int error, gbflags; ufs2_daddr_t bno; - static struct timeval lastfail; - static int curfail; int64_t delta; vp = ITOV(ip); @@ -449,14 +448,17 @@ ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, flags, cred, bpp) softdep_request_cleanup(fs, vp, cred, FLUSH_BLOCKS_WAIT); goto retry; } - UFS_UNLOCK(ump); - if (bp) - brelse(bp); - if (reclaimed > 0 && ppsratecheck(&lastfail, &curfail, 1)) { + if (reclaimed > 0 && + ppsratecheck(&ump->um_last_fullmsg, &ump->um_secs_fullmsg, 1)) { + UFS_UNLOCK(ump); ffs_fserr(fs, ip->i_number, "filesystem full"); uprintf("\n%s: write failed, filesystem is full\n", fs->fs_fsmnt); + } else { + UFS_UNLOCK(ump); } + if (bp) + brelse(bp); return (ENOSPC); } @@ -1101,8 +1103,6 @@ ffs_valloc(pvp, mode, cred, vpp) ino_t ino, ipref; u_int cg; int error, error1, reclaimed; - static struct timeval lastfail; - static int curfail; *vpp = NULL; pip = VTOI(pvp); @@ -1193,11 +1193,13 @@ ffs_valloc(pvp, mode, cred, vpp) softdep_request_cleanup(fs, pvp, cred, FLUSH_INODES_WAIT); goto retry; } - UFS_UNLOCK(ump); - if (ppsratecheck(&lastfail, &curfail, 1)) { + if (ppsratecheck(&ump->um_last_fullmsg, &ump->um_secs_fullmsg, 1)) { + UFS_UNLOCK(ump); ffs_fserr(fs, pip->i_number, "out of inodes"); uprintf("\n%s: create/symlink failed, no inodes free\n", fs->fs_fsmnt); + } else { + UFS_UNLOCK(ump); } return (ENOSPC); } diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c index ad41f316000a..30217e2ae954 100644 --- a/sys/ufs/ffs/ffs_balloc.c +++ b/sys/ufs/ffs/ffs_balloc.c @@ -108,8 +108,6 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, ufs2_daddr_t *lbns_remfree, lbns[UFS_NIADDR + 1]; int unwindidx = -1; int saved_inbdflush; - static struct timeval lastfail; - static int curfail; int gbflags, reclaimed; ip = VTOI(vp); @@ -315,17 +313,21 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, flags | IO_BUFLOCKED, cred, &newb)) != 0) { brelse(bp); + UFS_LOCK(ump); if (DOINGSOFTDEP(vp) && ++reclaimed == 1) { - UFS_LOCK(ump); softdep_request_cleanup(fs, vp, cred, FLUSH_BLOCKS_WAIT); UFS_UNLOCK(ump); goto retry; } - if (ppsratecheck(&lastfail, &curfail, 1)) { + if (ppsratecheck(&ump->um_last_fullmsg, + &ump->um_secs_fullmsg, 1)) { + UFS_UNLOCK(ump); ffs_fserr(fs, ip->i_number, "filesystem full"); uprintf("\n%s: write failed, filesystem " "is full\n", fs->fs_fsmnt); + } else { + UFS_UNLOCK(ump); } goto fail; } @@ -394,17 +396,21 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, flags | IO_BUFLOCKED, cred, &newb); if (error) { brelse(bp); + UFS_LOCK(ump); if (DOINGSOFTDEP(vp) && ++reclaimed == 1) { - UFS_LOCK(ump); softdep_request_cleanup(fs, vp, cred, FLUSH_BLOCKS_WAIT); UFS_UNLOCK(ump); goto retry; } - if (ppsratecheck(&lastfail, &curfail, 1)) { + if (ppsratecheck(&ump->um_last_fullmsg, + &ump->um_secs_fullmsg, 1)) { + UFS_UNLOCK(ump); ffs_fserr(fs, ip->i_number, "filesystem full"); uprintf("\n%s: write failed, filesystem " "is full\n", fs->fs_fsmnt); + } else { + UFS_UNLOCK(ump); } goto fail; } @@ -582,8 +588,6 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, int deallocated, osize, nsize, num, i, error; int unwindidx = -1; int saved_inbdflush; - static struct timeval lastfail; - static int curfail; int gbflags, reclaimed; ip = VTOI(vp); @@ -902,17 +906,21 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, flags | IO_BUFLOCKED, cred, &newb)) != 0) { brelse(bp); + UFS_LOCK(ump); if (DOINGSOFTDEP(vp) && ++reclaimed == 1) { - UFS_LOCK(ump); softdep_request_cleanup(fs, vp, cred, FLUSH_BLOCKS_WAIT); UFS_UNLOCK(ump); goto retry; } - if (ppsratecheck(&lastfail, &curfail, 1)) { + if (ppsratecheck(&ump->um_last_fullmsg, + &ump->um_secs_fullmsg, 1)) { + UFS_UNLOCK(ump); ffs_fserr(fs, ip->i_number, "filesystem full"); uprintf("\n%s: write failed, filesystem " "is full\n", fs->fs_fsmnt); + } else { + UFS_UNLOCK(ump); } goto fail; } @@ -982,17 +990,21 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, flags | IO_BUFLOCKED, cred, &newb); if (error) { brelse(bp); + UFS_LOCK(ump); if (DOINGSOFTDEP(vp) && ++reclaimed == 1) { - UFS_LOCK(ump); softdep_request_cleanup(fs, vp, cred, FLUSH_BLOCKS_WAIT); UFS_UNLOCK(ump); goto retry; } - if (ppsratecheck(&lastfail, &curfail, 1)) { + if (ppsratecheck(&ump->um_last_fullmsg, + &ump->um_secs_fullmsg, 1)) { + UFS_UNLOCK(ump); ffs_fserr(fs, ip->i_number, "filesystem full"); uprintf("\n%s: write failed, filesystem " "is full\n", fs->fs_fsmnt); + } else { + UFS_UNLOCK(ump); } goto fail; } diff --git a/sys/ufs/ufs/ufsmount.h b/sys/ufs/ufs/ufsmount.h index 0652e6a72930..104d6a42a396 100644 --- a/sys/ufs/ufs/ufsmount.h +++ b/sys/ufs/ufs/ufsmount.h @@ -100,6 +100,8 @@ struct ufsmount { char um_qflags[MAXQUOTAS]; /* (i) quota specific flags */ int64_t um_savedmaxfilesize; /* (c) track maxfilesize */ u_int um_flags; /* (i) filesystem flags */ + struct timeval um_last_fullmsg; /* (i) last full msg time */ + int um_secs_fullmsg; /* (i) seconds since full msg */ u_int um_trim_inflight; /* (i) outstanding trim count */ u_int um_trim_inflight_blks; /* (i) outstanding trim blks */ u_long um_trim_total; /* (i) total trim count */