aboutsummaryrefslogtreecommitdiff
path: root/sbin/fsdb
diff options
context:
space:
mode:
authorKirk McKusick <mckusick@FreeBSD.org>2019-02-25 21:58:19 +0000
committerKirk McKusick <mckusick@FreeBSD.org>2019-02-25 21:58:19 +0000
commitac4b20a0a71e693d9b241a8396ec4540fc4cef68 (patch)
tree7ccbacf263cde50d88aae9e36a7a6fed7dad8103 /sbin/fsdb
parent2528b7e2cb5c0d6fe0ad020dd80a1573d02a6240 (diff)
downloadsrc-ac4b20a0a71e693d9b241a8396ec4540fc4cef68.tar.gz
src-ac4b20a0a71e693d9b241a8396ec4540fc4cef68.zip
After a crash, a file that extends into indirect blocks may end up
shorter than its size resulting in a hole as its final block (which is a violation of the invarients of the UFS filesystem). Soft updates will always ensure that the file size is correct when writing inodes to disk for files that contain only direct block pointers. However soft updates does not roll back sizes for files with indirect blocks that it has set to unallocated because their contents have not yet been written to disk. Hence, the file can appear to have a hole at its end because the block pointer has been rolled back to zero when its inode was written to disk. Thus, fsck_ffs calculates the last allocated block in the file. For files that extend into indirect blocks, fsck_ffs checks for a size past the last allocated block of the file and if that is found, shortens the file to reference the last allocated block thus avoiding having it reference a hole at its end. Submitted by: Chuck Silvers <chs@netflix.com> Tested by: Chuck Silvers <chs@netflix.com> MFC after: 1 week Sponsored by: Netflix
Notes
Notes: svn path=/head/; revision=344552
Diffstat (limited to 'sbin/fsdb')
-rw-r--r--sbin/fsdb/fsdb.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/sbin/fsdb/fsdb.c b/sbin/fsdb/fsdb.c
index c3553a687066..74b3a82a8c8b 100644
--- a/sbin/fsdb/fsdb.c
+++ b/sbin/fsdb/fsdb.c
@@ -157,6 +157,7 @@ CMDFUNC(chctime); /* Change ctime */
CMDFUNC(chatime); /* Change atime */
CMDFUNC(chinum); /* Change inode # of dirent */
CMDFUNC(chname); /* Change dirname of dirent */
+CMDFUNC(chsize); /* Change size */
struct cmdtable cmds[] = {
{ "help", "Print out help", 1, 1, FL_RO, helpfn },
@@ -186,6 +187,7 @@ struct cmdtable cmds[] = {
{ "chgrp", "Change group of current inode to GROUP", 2, 2, FL_WR, chgroup },
{ "chflags", "Change flags of current inode to FLAGS", 2, 2, FL_WR, chaflags },
{ "chgen", "Change generation number of current inode to GEN", 2, 2, FL_WR, chgen },
+ { "chsize", "Change size of current inode to SIZE", 2, 2, FL_WR, chsize },
{ "btime", "Change btime of current inode to BTIME", 2, 2, FL_WR, chbtime },
{ "mtime", "Change mtime of current inode to MTIME", 2, 2, FL_WR, chmtime },
{ "ctime", "Change ctime of current inode to CTIME", 2, 2, FL_WR, chctime },
@@ -1017,6 +1019,31 @@ CMDFUNCSTART(chgen)
return rval;
}
+CMDFUNCSTART(chsize)
+{
+ int rval = 1;
+ off_t size;
+ char *cp;
+
+ if (!checkactive())
+ return 1;
+
+ size = strtoll(argv[1], &cp, 0);
+ if (cp == argv[1] || *cp != '\0') {
+ warnx("bad size `%s'", argv[1]);
+ return 1;
+ }
+
+ if (size < 0) {
+ warnx("size set to negative (%jd)\n", (intmax_t)size);
+ return(1);
+ }
+ DIP_SET(curinode, di_size, size);
+ inodirty(curinode);
+ printactive(0);
+ return rval;
+}
+
CMDFUNCSTART(linkcount)
{
int rval = 1;