aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Mahoney <jeffm@suse.com>2012-10-11 11:27:42 -0400
committerJeff Mahoney <jeffm@suse.com>2012-10-11 11:27:42 -0400
commitb69459eb802ace45677c9a12d909f70beff3de18 (patch)
tree3cd4822efbdda00b7a18a084adcb172213a84583
parente7102bdb66ffebd7d55ac54c46124706e15a4233 (diff)
downloadreiserfsprogs-b69459eb802ace45677c9a12d909f70beff3de18.tar.gz
Imported reiserfsprogs-3.6.2v3.6.2
-rw-r--r--ChangeLog156
-rw-r--r--Makefile.am8
-rw-r--r--Makefile.in76
-rw-r--r--aclocal.m433
-rwxr-xr-xconfigure4271
-rw-r--r--configure.in29
-rw-r--r--debugreiserfs/Makefile.am8
-rw-r--r--debugreiserfs/Makefile.in54
-rw-r--r--debugreiserfs/corruption.c487
-rw-r--r--debugreiserfs/debugreiserfs.877
-rw-r--r--debugreiserfs/debugreiserfs.c1235
-rw-r--r--debugreiserfs/debugreiserfs.h223
-rw-r--r--debugreiserfs/journal.c196
-rw-r--r--debugreiserfs/pack.c625
-rw-r--r--debugreiserfs/recover.c238
-rw-r--r--debugreiserfs/scan.c941
-rw-r--r--debugreiserfs/stat.c272
-rw-r--r--debugreiserfs/unpack.c287
-rw-r--r--fsck/Makefile.am10
-rw-r--r--fsck/Makefile.in80
-rw-r--r--fsck/check.c46
-rw-r--r--fsck/check_tree.c988
-rw-r--r--fsck/fsck.h435
-rw-r--r--fsck/info.c149
-rw-r--r--fsck/journal.c219
-rw-r--r--fsck/lost+found.c192
-rw-r--r--fsck/main.c1236
-rw-r--r--fsck/pass0.c1524
-rw-r--r--fsck/pass1.c684
-rw-r--r--fsck/pass2.c339
-rw-r--r--fsck/pass4.c58
-rw-r--r--fsck/reiserfsck.8185
-rw-r--r--fsck/segments.c202
-rw-r--r--fsck/semantic.c1346
-rw-r--r--fsck/semantic_check.c731
-rw-r--r--fsck/semantic_rebuild.c1192
-rw-r--r--fsck/super.c552
-rw-r--r--fsck/ubitmap.c37
-rw-r--r--fsck/ufile.c838
-rw-r--r--fsck/uobjectid.c253
-rw-r--r--fsck/ustree.c558
-rw-r--r--include/Makefile.am2
-rw-r--r--include/Makefile.in68
-rw-r--r--include/config.h.in90
-rw-r--r--include/io.h60
-rw-r--r--include/misc.h140
-rw-r--r--include/reiserfs_fs.h1039
-rw-r--r--include/reiserfs_lib.h369
-rw-r--r--include/stamp-h.in0
-rw-r--r--include/swab.h25
-rw-r--r--lib/Makefile.am18
-rw-r--r--lib/Makefile.in17
-rw-r--r--lib/io.c737
-rw-r--r--lib/misc.c771
-rw-r--r--mkreiserfs/Makefile.am3
-rw-r--r--mkreiserfs/Makefile.in20
-rw-r--r--mkreiserfs/mkreiserfs.8113
-rw-r--r--mkreiserfs/mkreiserfs.c968
-rw-r--r--reiserfscore/Makefile.am4
-rw-r--r--reiserfscore/Makefile.in44
-rw-r--r--reiserfscore/bitmap.c428
-rw-r--r--reiserfscore/do_balan.c761
-rw-r--r--reiserfscore/fix_node.c2841
-rw-r--r--reiserfscore/hashes.c33
-rw-r--r--reiserfscore/ibalance.c409
-rw-r--r--reiserfscore/includes.h1
-rw-r--r--reiserfscore/journal.c711
-rw-r--r--reiserfscore/lbalance.c599
-rw-r--r--reiserfscore/node_formats.c954
-rw-r--r--reiserfscore/prints.c558
-rw-r--r--reiserfscore/reiserfslib.c1261
-rw-r--r--reiserfscore/stree.c263
-rw-r--r--reiserfsprogs.spec52
-rw-r--r--resize_reiserfs/Makefile.am3
-rw-r--r--resize_reiserfs/Makefile.in30
-rw-r--r--resize_reiserfs/do_shrink.c135
-rw-r--r--resize_reiserfs/fe.c2
-rw-r--r--resize_reiserfs/resize.h17
-rw-r--r--resize_reiserfs/resize_reiserfs.815
-rw-r--r--resize_reiserfs/resize_reiserfs.c197
-rw-r--r--tune/Makefile.am9
-rw-r--r--tune/Makefile.in328
-rw-r--r--tune/reiserfstune.8147
-rw-r--r--tune/tune.c563
-rw-r--r--tune/tune.h48
-rw-r--r--version.h8
86 files changed, 22822 insertions, 13109 deletions
diff --git a/ChangeLog b/ChangeLog
index 5a06c97..f8ae6a0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,157 @@
+2002-06-27
+ * reiserfsprogs
+ called 3.6.2
+2002-05-23
+ * reiserfsck
+ speedup for pass2: do not check whether a file should be relocated
+ if the file body was previously deleted from the tree and is
+ inserted again.
+2002-05-10
+ * reiserfsck
+ fix-fixable is able to fix wrong nlinks.
+ check makes some check about nlinks also.
+2002-04-30
+ * reiserfsck
+ delete direntries of old format in new format directories
+2002-03-29
+ * reiserfsprogs
+ bad blocks support added.
+2002-03-15
+ * reiserfsprogs
+ different blocksize support added.
+2002-02-18
+ * debugreiserfs
+ new option -J, prints a journal header.
+2002-02-10
+ * reiserfsprogs
+ a few speedups were added.
+2002-02-05
+ * reiserfsprogs
+ optimization of the work with disk buffers.
+2002-01-28
+ * mkreiserfs
+ zeroing the first block on the device if not SPARC
+2002-01-26
+ * reiserfsck
+ a few speedups were added.
+2002-01-20
+ * debugreiserfs
+ investigation of unused space added (-D -U options, hidden)
+2002-01-16
+ * reiserfsprogs
+ support for UUID and LABEL was added
+2002-01-15
+ * reiserfstune
+ creates a standard journal from a non-standard
+2001-12-25
+ * reiserfsck
+ Handles safe links.
+2001-12-03
+ * reiserfsck
+ Filenames output during tree scan is now nicely scrolled
+ left and right, when entire line does not fit the screen.
+2001-11-20
+ * reiserfsck
+ Can rebuild superblock properly.
+2001-11-03
+ * reiserfsck
+ Can now backup all data which get changed during fscking
+ and can rollback all changes.
+2001-10-30
+ * reiserfsprogs
+ mkreiserfs/reiserfsck/reiserfstune/debugreiserfs work with
+ relocated journal
+2001-09-30
+ * debugreiserfs
+ super block editor (-C -B 16)
+2001-08-23
+ * reiserfsck
+ --fix-fixable becomes a mode, can fix everything what does
+ not need to rebuild a tree.
+ --fix-non-critical option moved to --ajust-file-size option,
+ work in --fix-fixable and --rebuild-tree modes.
+2001-07-19
+ * mkreiserfs
+ can now create non-standard journal: journal size,
+ offset, device may now vary
+ * reiserfstune
+ initial release. Allows to change journal parameters for
+ existing filesystems
+ * reisrefsck
+ it now sets "consistency checked" flag after
+ --rebuild-tree and --check which did not find anything
+ broken
+ * man pages
+ updated
+
+2001-06-25
+ * mkreiserfs
+ long options (--journal-device, --journal-size)
+ * library
+ reiserfs_create, reiserfs_create_journal
+
+2001-06-20
+ * global changes
+ Jeff's patch (safe endianness) is merged (with changes)
+ mlock is used to estimate amount of memory available
+
+2001-06-14
+ * reiserfsck
+ update journal header when transaction is replayed
+
+2001-06-13
+ * reiserfsck
+ lost+found's mode is set to drwx------ after lost+found pass
+
+2001-06-08
+ * library
+ functions to deal with journal
+
+2001-06-05
+ * global change
+ Unified access via get_/set_ macroses is added for fields
+ of struct key, struct item_head, struct
+ reiserfs_journal_desc/commit, struct block_head, struct disk_child
+
+2001-05-22
+ * global change
+ Access to super block's fields are unified vid get_sb_xxx
+ and set_sb_xxx macroses
+
+2001-05-05
+ * called 3.x.0k-pre4
+ * reiserfsck
+ entries in lost+found are removed on pass 0
+
+2001-05-03
+ * mkreiserfs
+ first 64k get zeroed now. This kills JFS if it was there
+ * reiserfsprogs.spec (Anthon van der Neut)
+ prereleases can be built by rpm now
+ link from /sbin/mkreiserfs to /sbin/mkfs.reiserfs
+ guess about reiserfs kernel support is added
+
+2001-04-16
+ * reiserfsck
+ in --check mode it exits with 0 if there were no
+ corruptions found, 1 if there were only corruptions
+ fixable by --fix-fixable or 2 if --rebuild-tree is
+ required
+ man page updated, simple example of using reiserfsck is
+ added
+
+2001-04-15
+ * mkreiserfs
+ bug in confirmation dialogs fixed
+
+2001-04-13-Friday
+ * reiserfsck
+ --hash option makes reiserfsck to skip blocks having
+ directory entries created with other hash. It is useful
+ together with --scan-whole-partition
+ --background option allows to fork fsck end exit (useful
+ for running remotely)
+
2001-03-31
* reiserfsck
empty lost directories do not get linked into /lost+found
@@ -98,7 +252,7 @@
--interactive option is added
* debugreiserfs:
few bugs fixed
-
+
2001-01-07
* reiserfs library:
started with reiserfs_open, reiserfs_close, bitmap tools
diff --git a/Makefile.am b/Makefile.am
index 2e88813..ce451a7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,8 @@
-SUBDIRS = include lib reiserfscore mkreiserfs fsck debugreiserfs resize_reiserfs
+SUBDIRS = include lib reiserfscore fsck debugreiserfs resize_reiserfs mkreiserfs tune
-EXTRA_DIST = version.h reiserfsprogs.spec
+noinst_DATA = reiserfsprogs.spec
+EXTRA_DIST = version.h
+
+dist-hook:
+ cp -f reiserfsprogs.spec $(distdir)
diff --git a/Makefile.in b/Makefile.in
index 5f9f214..d61620d 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -62,16 +62,22 @@ MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
+sbindir = @sbindir@
+
+SUBDIRS = include lib reiserfscore fsck debugreiserfs resize_reiserfs mkreiserfs tune
-SUBDIRS = include lib reiserfscore mkreiserfs fsck debugreiserfs resize_reiserfs
+noinst_DATA = reiserfsprogs.spec
-EXTRA_DIST = version.h reiserfsprogs.spec
+EXTRA_DIST = version.h
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ./include/config.h
CONFIG_CLEAN_FILES =
+DATA = $(noinst_DATA)
+
DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \
-Makefile.in NEWS aclocal.m4 configure configure.in install-sh missing \
-mkinstalldirs
+Makefile.in NEWS acconfig.h aclocal.m4 configure configure.in \
+include/config.h.in include/stamp-h.in install-sh missing mkinstalldirs
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
@@ -95,6 +101,34 @@ config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
cd $(srcdir) && $(AUTOCONF)
+include/config.h: include/stamp-h
+ @if test ! -f $@; then \
+ rm -f include/stamp-h; \
+ $(MAKE) include/stamp-h; \
+ else :; fi
+include/stamp-h: $(srcdir)/include/config.h.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES= CONFIG_HEADERS=include/config.h \
+ $(SHELL) ./config.status
+ @echo timestamp > include/stamp-h 2> /dev/null
+$(srcdir)/include/config.h.in: $(srcdir)/include/stamp-h.in
+ @if test ! -f $@; then \
+ rm -f $(srcdir)/include/stamp-h.in; \
+ $(MAKE) $(srcdir)/include/stamp-h.in; \
+ else :; fi
+$(srcdir)/include/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) acconfig.h
+ cd $(top_srcdir) && $(AUTOHEADER)
+ @echo timestamp > $(srcdir)/include/stamp-h.in 2> /dev/null
+
+mostlyclean-hdr:
+
+clean-hdr:
+
+distclean-hdr:
+ -rm -f include/config.h
+
+maintainer-clean-hdr:
+
# This directory's subdirectories are mostly independent; you can cd
# into them and run `make' without going through this Makefile.
# To change the values of `make' variables: instead of editing Makefiles,
@@ -131,7 +165,7 @@ maintainer-clean-recursive:
dot_seen=no; \
rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
rev="$$subdir $$rev"; \
- test "$$subdir" = "." && dot_seen=yes; \
+ test "$$subdir" != "." || dot_seen=yes; \
done; \
test "$$dot_seen" = "no" && rev=". $$rev"; \
target=`echo $@ | sed s/-recursive//`; \
@@ -225,7 +259,7 @@ distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
- cp -pr $$/$$file $(distdir)/$$file; \
+ cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
@@ -242,6 +276,7 @@ distdir: $(DISTFILES)
|| exit 1; \
fi; \
done
+ $(MAKE) $(AM_MAKEFLAGS) top_distdir="$(top_distdir)" distdir="$(distdir)" dist-hook
info-am:
info: info-recursive
dvi-am:
@@ -261,7 +296,7 @@ install-am: all-am
install: install-recursive
uninstall-am:
uninstall: uninstall-recursive
-all-am: Makefile
+all-am: Makefile $(DATA)
all-redirect: all-recursive
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
@@ -278,32 +313,32 @@ distclean-generic:
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
-mostlyclean-am: mostlyclean-tags mostlyclean-generic
+mostlyclean-am: mostlyclean-hdr mostlyclean-tags mostlyclean-generic
mostlyclean: mostlyclean-recursive
-clean-am: clean-tags clean-generic mostlyclean-am
+clean-am: clean-hdr clean-tags clean-generic mostlyclean-am
clean: clean-recursive
-distclean-am: distclean-tags distclean-generic clean-am
+distclean-am: distclean-hdr distclean-tags distclean-generic clean-am
distclean: distclean-recursive
-rm -f config.status
-maintainer-clean-am: maintainer-clean-tags maintainer-clean-generic \
- distclean-am
+maintainer-clean-am: maintainer-clean-hdr maintainer-clean-tags \
+ maintainer-clean-generic distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-recursive
-rm -f config.status
-.PHONY: install-data-recursive uninstall-data-recursive \
-install-exec-recursive uninstall-exec-recursive installdirs-recursive \
-uninstalldirs-recursive all-recursive check-recursive \
-installcheck-recursive info-recursive dvi-recursive \
-mostlyclean-recursive distclean-recursive clean-recursive \
+.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
+install-data-recursive uninstall-data-recursive install-exec-recursive \
+uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \
+all-recursive check-recursive installcheck-recursive info-recursive \
+dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \
maintainer-clean-recursive tags tags-recursive mostlyclean-tags \
distclean-tags clean-tags maintainer-clean-tags distdir info-am info \
dvi-am dvi check check-am installcheck-am installcheck install-exec-am \
@@ -313,6 +348,9 @@ installdirs mostlyclean-generic distclean-generic clean-generic \
maintainer-clean-generic clean mostlyclean distclean maintainer-clean
+dist-hook:
+ cp -f reiserfsprogs.spec $(distdir)
+
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
diff --git a/aclocal.m4 b/aclocal.m4
index 9f8add8..c461ff3 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,6 +1,6 @@
-dnl aclocal.m4 generated automatically by aclocal 1.4
+dnl aclocal.m4 generated automatically by aclocal 1.4-p5
-dnl Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+dnl Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
@@ -19,7 +19,7 @@ dnl PARTICULAR PURPOSE.
dnl Usage:
dnl AM_INIT_AUTOMAKE(package,version, [no-define])
-AC_DEFUN(AM_INIT_AUTOMAKE,
+AC_DEFUN([AM_INIT_AUTOMAKE],
[AC_REQUIRE([AC_PROG_INSTALL])
PACKAGE=[$1]
AC_SUBST(PACKAGE)
@@ -47,7 +47,7 @@ AC_REQUIRE([AC_PROG_MAKE_SET])])
# Check to make sure that the build environment is sane.
#
-AC_DEFUN(AM_SANITY_CHECK,
+AC_DEFUN([AM_SANITY_CHECK],
[AC_MSG_CHECKING([whether build environment is sane])
# Just in case
sleep 1
@@ -88,7 +88,7 @@ AC_MSG_RESULT(yes)])
dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
dnl The program must properly implement --version.
-AC_DEFUN(AM_MISSING_PROG,
+AC_DEFUN([AM_MISSING_PROG],
[AC_MSG_CHECKING(for working $2)
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
@@ -102,3 +102,26 @@ else
fi
AC_SUBST($1)])
+# Like AC_CONFIG_HEADER, but automatically create stamp file.
+
+AC_DEFUN([AM_CONFIG_HEADER],
+[AC_PREREQ([2.12])
+AC_CONFIG_HEADER([$1])
+dnl When config.status generates a header, we must update the stamp-h file.
+dnl This file resides in the same directory as the config header
+dnl that is generated. We must strip everything past the first ":",
+dnl and everything past the last "/".
+AC_OUTPUT_COMMANDS(changequote(<<,>>)dnl
+ifelse(patsubst(<<$1>>, <<[^ ]>>, <<>>), <<>>,
+<<test -z "<<$>>CONFIG_HEADERS" || echo timestamp > patsubst(<<$1>>, <<^\([^:]*/\)?.*>>, <<\1>>)stamp-h<<>>dnl>>,
+<<am_indx=1
+for am_file in <<$1>>; do
+ case " <<$>>CONFIG_HEADERS " in
+ *" <<$>>am_file "*<<)>>
+ echo timestamp > `echo <<$>>am_file | sed -e 's%:.*%%' -e 's%[^/]*$%%'`stamp-h$am_indx
+ ;;
+ esac
+ am_indx=`expr "<<$>>am_indx" + 1`
+done<<>>dnl>>)
+changequote([,]))])
+
diff --git a/configure b/configure
index 59577f1..efa751d 100755
--- a/configure
+++ b/configure
@@ -1,27 +1,155 @@
#! /bin/sh
-
# Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.13
-# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
+# Generated by Autoconf 2.52.
#
+# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
# This configure script is free software; the Free Software Foundation
# gives unlimited permission to copy, distribute and modify it.
-# Defaults:
-ac_help=
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+
+# Name of the executable.
+as_me=`echo "$0" |sed 's,.*[\\/],,'`
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+as_executable_p="test -f"
+
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+# NLS nuisances.
+$as_unset LANG || test "${LANG+set}" != set || { LANG=C; export LANG; }
+$as_unset LC_ALL || test "${LC_ALL+set}" != set || { LC_ALL=C; export LC_ALL; }
+$as_unset LC_TIME || test "${LC_TIME+set}" != set || { LC_TIME=C; export LC_TIME; }
+$as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set || { LC_CTYPE=C; export LC_CTYPE; }
+$as_unset LANGUAGE || test "${LANGUAGE+set}" != set || { LANGUAGE=C; export LANGUAGE; }
+$as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set || { LC_COLLATE=C; export LC_COLLATE; }
+$as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set || { LC_NUMERIC=C; export LC_NUMERIC; }
+$as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set || { LC_MESSAGES=C; export LC_MESSAGES; }
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=:; export CDPATH; }
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
ac_default_prefix=/usr/local
-# Any additions from configure.in:
-ac_default_prefix=/
+cross_compiling=no
+subdirs=
+MFLAGS= MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete. It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+ac_unique_file="version.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# if HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#if HAVE_INTTYPES_H
+# include <inttypes.h>
+#else
+# if HAVE_STDINT_H
+# include <stdint.h>
+# endif
+#endif
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
# The variables have the same names as the options, with
# dashes changed to underlines.
-build=NONE
-cache_file=./config.cache
+cache_file=/dev/null
exec_prefix=NONE
-host=NONE
no_create=
-nonopt=NONE
no_recursion=
prefix=NONE
program_prefix=NONE
@@ -30,10 +158,15 @@ program_transform_name=s,x,x,
silent=
site=
srcdir=
-target=NONE
verbose=
x_includes=NONE
x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
bindir='${exec_prefix}/bin'
sbindir='${exec_prefix}/sbin'
libexecdir='${exec_prefix}/libexec'
@@ -47,17 +180,16 @@ oldincludedir='/usr/include'
infodir='${prefix}/info'
mandir='${prefix}/man'
-# Initialize some other variables.
-subdirs=
-MFLAGS= MAKEFLAGS=
-SHELL=${CONFIG_SHELL-/bin/sh}
-# Maximum number of lines to put in a shell here document.
-ac_max_here_lines=12
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
ac_prev=
for ac_option
do
-
# If the previous option needs an argument, assign it.
if test -n "$ac_prev"; then
eval "$ac_prev=\$ac_option"
@@ -65,59 +197,59 @@ do
continue
fi
- case "$ac_option" in
- -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
- *) ac_optarg= ;;
- esac
+ ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
# Accept the important Cygnus configure options, so we can diagnose typos.
- case "$ac_option" in
+ case $ac_option in
-bindir | --bindir | --bindi | --bind | --bin | --bi)
ac_prev=bindir ;;
-bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
- bindir="$ac_optarg" ;;
+ bindir=$ac_optarg ;;
-build | --build | --buil | --bui | --bu)
- ac_prev=build ;;
+ ac_prev=build_alias ;;
-build=* | --build=* | --buil=* | --bui=* | --bu=*)
- build="$ac_optarg" ;;
+ build_alias=$ac_optarg ;;
-cache-file | --cache-file | --cache-fil | --cache-fi \
| --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
ac_prev=cache_file ;;
-cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
| --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
- cache_file="$ac_optarg" ;;
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
-datadir | --datadir | --datadi | --datad | --data | --dat | --da)
ac_prev=datadir ;;
-datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
| --da=*)
- datadir="$ac_optarg" ;;
+ datadir=$ac_optarg ;;
-disable-* | --disable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
# Reject names that are not valid shell variable names.
- if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
- { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
- fi
- ac_feature=`echo $ac_feature| sed 's/-/_/g'`
- eval "enable_${ac_feature}=no" ;;
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ eval "enable_$ac_feature=no" ;;
-enable-* | --enable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
# Reject names that are not valid shell variable names.
- if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
- { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
- fi
- ac_feature=`echo $ac_feature| sed 's/-/_/g'`
- case "$ac_option" in
- *=*) ;;
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
*) ac_optarg=yes ;;
esac
- eval "enable_${ac_feature}='$ac_optarg'" ;;
+ eval "enable_$ac_feature='$ac_optarg'" ;;
-exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
| --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
@@ -126,95 +258,47 @@ do
-exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
| --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
| --exec=* | --exe=* | --ex=*)
- exec_prefix="$ac_optarg" ;;
+ exec_prefix=$ac_optarg ;;
-gas | --gas | --ga | --g)
# Obsolete; use --with-gas.
with_gas=yes ;;
- -help | --help | --hel | --he)
- # Omit some internal or obsolete options to make the list less imposing.
- # This message is too long to be a string in the A/UX 3.1 sh.
- cat << EOF
-Usage: configure [options] [host]
-Options: [defaults in brackets after descriptions]
-Configuration:
- --cache-file=FILE cache test results in FILE
- --help print this message
- --no-create do not create output files
- --quiet, --silent do not print \`checking...' messages
- --version print the version of autoconf that created configure
-Directory and file names:
- --prefix=PREFIX install architecture-independent files in PREFIX
- [$ac_default_prefix]
- --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
- [same as prefix]
- --bindir=DIR user executables in DIR [EPREFIX/bin]
- --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
- --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
- --datadir=DIR read-only architecture-independent data in DIR
- [PREFIX/share]
- --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
- --sharedstatedir=DIR modifiable architecture-independent data in DIR
- [PREFIX/com]
- --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
- --libdir=DIR object code libraries in DIR [EPREFIX/lib]
- --includedir=DIR C header files in DIR [PREFIX/include]
- --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
- --infodir=DIR info documentation in DIR [PREFIX/info]
- --mandir=DIR man documentation in DIR [PREFIX/man]
- --srcdir=DIR find the sources in DIR [configure dir or ..]
- --program-prefix=PREFIX prepend PREFIX to installed program names
- --program-suffix=SUFFIX append SUFFIX to installed program names
- --program-transform-name=PROGRAM
- run sed PROGRAM on installed program names
-EOF
- cat << EOF
-Host type:
- --build=BUILD configure for building on BUILD [BUILD=HOST]
- --host=HOST configure for HOST [guessed]
- --target=TARGET configure for TARGET [TARGET=HOST]
-Features and packages:
- --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
- --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --x-includes=DIR X include files are in DIR
- --x-libraries=DIR X library files are in DIR
-EOF
- if test -n "$ac_help"; then
- echo "--enable and --with options recognized:$ac_help"
- fi
- exit 0 ;;
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
-host | --host | --hos | --ho)
- ac_prev=host ;;
+ ac_prev=host_alias ;;
-host=* | --host=* | --hos=* | --ho=*)
- host="$ac_optarg" ;;
+ host_alias=$ac_optarg ;;
-includedir | --includedir | --includedi | --included | --include \
| --includ | --inclu | --incl | --inc)
ac_prev=includedir ;;
-includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
| --includ=* | --inclu=* | --incl=* | --inc=*)
- includedir="$ac_optarg" ;;
+ includedir=$ac_optarg ;;
-infodir | --infodir | --infodi | --infod | --info | --inf)
ac_prev=infodir ;;
-infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
- infodir="$ac_optarg" ;;
+ infodir=$ac_optarg ;;
-libdir | --libdir | --libdi | --libd)
ac_prev=libdir ;;
-libdir=* | --libdir=* | --libdi=* | --libd=*)
- libdir="$ac_optarg" ;;
+ libdir=$ac_optarg ;;
-libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
| --libexe | --libex | --libe)
ac_prev=libexecdir ;;
-libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
| --libexe=* | --libex=* | --libe=*)
- libexecdir="$ac_optarg" ;;
+ libexecdir=$ac_optarg ;;
-localstatedir | --localstatedir | --localstatedi | --localstated \
| --localstate | --localstat | --localsta | --localst \
@@ -223,12 +307,12 @@ EOF
-localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
| --localstate=* | --localstat=* | --localsta=* | --localst=* \
| --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
- localstatedir="$ac_optarg" ;;
+ localstatedir=$ac_optarg ;;
-mandir | --mandir | --mandi | --mand | --man | --ma | --m)
ac_prev=mandir ;;
-mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
- mandir="$ac_optarg" ;;
+ mandir=$ac_optarg ;;
-nfp | --nfp | --nf)
# Obsolete; use --without-fp.
@@ -249,26 +333,26 @@ EOF
-oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
| --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
| --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
- oldincludedir="$ac_optarg" ;;
+ oldincludedir=$ac_optarg ;;
-prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
ac_prev=prefix ;;
-prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
- prefix="$ac_optarg" ;;
+ prefix=$ac_optarg ;;
-program-prefix | --program-prefix | --program-prefi | --program-pref \
| --program-pre | --program-pr | --program-p)
ac_prev=program_prefix ;;
-program-prefix=* | --program-prefix=* | --program-prefi=* \
| --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
- program_prefix="$ac_optarg" ;;
+ program_prefix=$ac_optarg ;;
-program-suffix | --program-suffix | --program-suffi | --program-suff \
| --program-suf | --program-su | --program-s)
ac_prev=program_suffix ;;
-program-suffix=* | --program-suffix=* | --program-suffi=* \
| --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
- program_suffix="$ac_optarg" ;;
+ program_suffix=$ac_optarg ;;
-program-transform-name | --program-transform-name \
| --program-transform-nam | --program-transform-na \
@@ -285,7 +369,7 @@ EOF
| --program-transfo=* | --program-transf=* \
| --program-trans=* | --program-tran=* \
| --progr-tra=* | --program-tr=* | --program-t=*)
- program_transform_name="$ac_optarg" ;;
+ program_transform_name=$ac_optarg ;;
-q | -quiet | --quiet | --quie | --qui | --qu | --q \
| -silent | --silent | --silen | --sile | --sil)
@@ -295,7 +379,7 @@ EOF
ac_prev=sbindir ;;
-sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
| --sbi=* | --sb=*)
- sbindir="$ac_optarg" ;;
+ sbindir=$ac_optarg ;;
-sharedstatedir | --sharedstatedir | --sharedstatedi \
| --sharedstated | --sharedstate | --sharedstat | --sharedsta \
@@ -306,58 +390,57 @@ EOF
| --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
| --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
| --sha=* | --sh=*)
- sharedstatedir="$ac_optarg" ;;
+ sharedstatedir=$ac_optarg ;;
-site | --site | --sit)
ac_prev=site ;;
-site=* | --site=* | --sit=*)
- site="$ac_optarg" ;;
+ site=$ac_optarg ;;
-srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
ac_prev=srcdir ;;
-srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
- srcdir="$ac_optarg" ;;
+ srcdir=$ac_optarg ;;
-sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
| --syscon | --sysco | --sysc | --sys | --sy)
ac_prev=sysconfdir ;;
-sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
| --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
- sysconfdir="$ac_optarg" ;;
+ sysconfdir=$ac_optarg ;;
-target | --target | --targe | --targ | --tar | --ta | --t)
- ac_prev=target ;;
+ ac_prev=target_alias ;;
-target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
- target="$ac_optarg" ;;
+ target_alias=$ac_optarg ;;
-v | -verbose | --verbose | --verbos | --verbo | --verb)
verbose=yes ;;
- -version | --version | --versio | --versi | --vers)
- echo "configure generated by autoconf version 2.13"
- exit 0 ;;
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
-with-* | --with-*)
- ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
# Reject names that are not valid shell variable names.
- if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
- { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
- fi
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
ac_package=`echo $ac_package| sed 's/-/_/g'`
- case "$ac_option" in
- *=*) ;;
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
*) ac_optarg=yes ;;
esac
- eval "with_${ac_package}='$ac_optarg'" ;;
+ eval "with_$ac_package='$ac_optarg'" ;;
-without-* | --without-*)
- ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
# Reject names that are not valid shell variable names.
- if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
- { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
- fi
- ac_package=`echo $ac_package| sed 's/-/_/g'`
- eval "with_${ac_package}=no" ;;
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/-/_/g'`
+ eval "with_$ac_package=no" ;;
--x)
# Obsolete; use --with-x.
@@ -368,98 +451,98 @@ EOF
ac_prev=x_includes ;;
-x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
| --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
- x_includes="$ac_optarg" ;;
+ x_includes=$ac_optarg ;;
-x-libraries | --x-libraries | --x-librarie | --x-librari \
| --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
ac_prev=x_libraries ;;
-x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
| --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
- x_libraries="$ac_optarg" ;;
+ x_libraries=$ac_optarg ;;
- -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
;;
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+ eval "$ac_envvar='$ac_optarg'"
+ export $ac_envvar ;;
+
*)
- if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
- echo "configure: warning: $ac_option: invalid host type" 1>&2
- fi
- if test "x$nonopt" != xNONE; then
- { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
- fi
- nonopt="$ac_option"
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
;;
esac
done
if test -n "$ac_prev"; then
- { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
-fi
-
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
-# File descriptor usage:
-# 0 standard input
-# 1 file creation
-# 2 errors and warnings
-# 3 some systems may open it to /dev/tty
-# 4 used on the Kubota Titan
-# 6 checking for... messages and results
-# 5 compiler messages saved in config.log
-if test "$silent" = yes; then
- exec 6>/dev/null
-else
- exec 6>&1
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
fi
-exec 5>./config.log
-echo "\
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-" 1>&5
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+ *) { echo "$as_me: error: expected an absolute path for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Also quote any args containing shell metacharacters.
-ac_configure_args=
-for ac_arg
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+ localstatedir libdir includedir oldincludedir infodir mandir
do
- case "$ac_arg" in
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c) ;;
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
- *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
- ac_configure_args="$ac_configure_args '$ac_arg'" ;;
- *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) ;;
+ *) { echo "$as_me: error: expected an absolute path for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
esac
done
-# NLS nuisances.
-# Only set these to C if already set. These must not be set unconditionally
-# because not all systems understand e.g. LANG=C (notably SCO).
-# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
-# Non-C LC_CTYPE values break the ctype check.
-if test "${LANG+set}" = set; then LANG=C; export LANG; fi
-if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
-if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
-if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: should be removed in autoconf 3.0.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -rf conftest* confdefs.h
-# AIX cpp loses on an empty file, so make sure it contains at least a newline.
-echo > confdefs.h
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
-# A filename unique to this package, relative to the directory that
-# configure is in, which we can look for to find out if srcdir is correct.
-ac_unique_file=version.h
+test "$silent" = yes && exec 6>/dev/null
# Find the source files, if location was not specified.
if test -z "$srcdir"; then
ac_srcdir_defaulted=yes
# Try the directory containing this script, then its parent.
ac_prog=$0
- ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+ ac_confdir=`echo "$ac_prog" | sed 's%[\\/][^\\/][^\\/]*$%%'`
test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
srcdir=$ac_confdir
if test ! -r $srcdir/$ac_unique_file; then
@@ -470,13 +553,305 @@ else
fi
if test ! -r $srcdir/$ac_unique_file; then
if test "$ac_srcdir_defaulted" = yes; then
- { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+ { echo "$as_me: error: cannot find sources in $ac_confdir or .." >&2
+ { (exit 1); exit 1; }; }
else
- { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+ { echo "$as_me: error: cannot find sources in $srcdir" >&2
+ { (exit 1); exit 1; }; }
fi
fi
-srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CC_set=${CC+set}
+ac_env_CC_value=$CC
+ac_cv_env_CC_set=${CC+set}
+ac_cv_env_CC_value=$CC
+ac_env_CFLAGS_set=${CFLAGS+set}
+ac_env_CFLAGS_value=$CFLAGS
+ac_cv_env_CFLAGS_set=${CFLAGS+set}
+ac_cv_env_CFLAGS_value=$CFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CPP_set=${CPP+set}
+ac_env_CPP_value=$CPP
+ac_cv_env_CPP_set=${CPP+set}
+ac_cv_env_CPP_value=$CPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<EOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+EOF
+
+ cat <<EOF
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --infodir=DIR info documentation [PREFIX/info]
+ --mandir=DIR man documentation [PREFIX/man]
+EOF
+
+ cat <<\EOF
+
+Program names:
+ --program-prefix=PREFIX prepend PREFIX to installed program names
+ --program-suffix=SUFFIX append SUFFIX to installed program names
+ --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+EOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\EOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-io-failure-emulation Never use that. It is for debugging only
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
+ headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+EOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ ac_popdir=`pwd`
+ for ac_subdir in : $ac_subdirs_all; do test "x$ac_subdir" = x: && continue
+ cd $ac_subdir
+ # A "../" for each directory in /$ac_subdir.
+ ac_dots=`echo $ac_subdir |
+ sed 's,^\./,,;s,[^/]$,&/,;s,[^/]*/,../,g'`
+
+ case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_sub_srcdir=$srcdir ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_sub_srcdir=$srcdir/$ac_subdir ;;
+ *) # Relative path.
+ ac_sub_srcdir=$ac_dots$srcdir/$ac_subdir ;;
+ esac
+
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f $ac_sub_srcdir/configure.gnu; then
+ echo
+ $SHELL $ac_sub_srcdir/configure.gnu --help=recursive
+ elif test -f $ac_sub_srcdir/configure; then
+ echo
+ $SHELL $ac_sub_srcdir/configure --help=recursive
+ elif test -f $ac_sub_srcdir/configure.ac ||
+ test -f $ac_sub_srcdir/configure.in; then
+ echo
+ $ac_configure --help
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_subdir" >&2
+ fi
+ cd $ac_popdir
+ done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+ cat <<\EOF
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+EOF
+ exit 0
+fi
+exec 5>config.log
+cat >&5 <<EOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.52. Invocation command line was
+
+ $ $0 $@
+
+EOF
+{
+cat <<_ASUNAME
+## ---------- ##
+## Platform. ##
+## ---------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo = `(hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+PATH = $PATH
+
+_ASUNAME
+} >&5
+
+cat >&5 <<EOF
+## ------------ ##
+## Core tests. ##
+## ------------ ##
+
+EOF
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell meta-characters.
+ac_configure_args=
+ac_sep=
+for ac_arg
+do
+ case $ac_arg in
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c) ;;
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"`
+ ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+ ac_sep=" " ;;
+ *) ac_configure_args="$ac_configure_args$ac_sep$ac_arg"
+ ac_sep=" " ;;
+ esac
+ # Get rid of the leading space.
+done
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ echo >&5
+ echo "## ----------------- ##" >&5
+ echo "## Cache variables. ##" >&5
+ echo "## ----------------- ##" >&5
+ echo >&5
+ # The following way of writing the cache mishandles newlines in values,
+{
+ (set) 2>&1 |
+ case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ sed -n \
+ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+ ;;
+ *)
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+} >&5
+ sed "/^$/d" confdefs.h >conftest.log
+ if test -s conftest.log; then
+ echo >&5
+ echo "## ------------ ##" >&5
+ echo "## confdefs.h. ##" >&5
+ echo "## ------------ ##" >&5
+ echo >&5
+ cat conftest.log >&5
+ fi
+ (echo; echo) >&5
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal" >&5
+ echo "$as_me: exit $exit_status" >&5
+ rm -rf conftest* confdefs* core core.* *.core conf$$* $ac_clean_files &&
+ exit $exit_status
+ ' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Let the site file select an alternate cache file if it wants to.
# Prefer explicitly selected file to automatically selected ones.
if test -z "$CONFIG_SITE"; then
if test "x$prefix" != xNONE; then
@@ -487,41 +862,107 @@ if test -z "$CONFIG_SITE"; then
fi
for ac_site_file in $CONFIG_SITE; do
if test -r "$ac_site_file"; then
- echo "loading site script $ac_site_file"
+ { echo "$as_me:865: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ cat "$ac_site_file" >&5
. "$ac_site_file"
fi
done
if test -r "$cache_file"; then
- echo "loading cache $cache_file"
- . $cache_file
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:876: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . $cache_file;;
+ *) . ./$cache_file;;
+ esac
+ fi
else
- echo "creating cache $cache_file"
- > $cache_file
+ { echo "$as_me:884: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+ sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+ eval ac_new_val="\$ac_env_${ac_var}_value"
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:900: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:904: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:910: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:912: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:914: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status. It doesn't matter if
+ # we pass some twice (in addition to the command line arguments).
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"`
+ ac_configure_args="$ac_configure_args '$ac_arg'"
+ ;;
+ *) ac_configure_args="$ac_configure_args $ac_var=$ac_new_val"
+ ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:933: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:935: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
fi
ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-ac_exeext=
-ac_objext=o
-if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
- # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
- if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
- ac_n= ac_c='
-' ac_t=' '
- else
- ac_n=-n ac_c= ac_t=
- fi
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+echo "#! $SHELL" >conftest.sh
+echo "exit 0" >>conftest.sh
+chmod +x conftest.sh
+if { (echo "$as_me:955: PATH=\".;.\"; conftest.sh") >&5
+ (PATH=".;."; conftest.sh) 2>&5
+ ac_status=$?
+ echo "$as_me:958: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ ac_path_separator=';'
else
- ac_n= ac_c='\c' ac_t=
+ ac_path_separator=:
fi
-
-
+PATH_SEPARATOR="$ac_path_separator"
+rm -f conftest.sh
ac_aux_dir=
for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
@@ -533,14 +974,20 @@ for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
ac_aux_dir=$ac_dir
ac_install_sh="$ac_aux_dir/install.sh -c"
break
+ elif test -f $ac_dir/shtool; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
fi
done
if test -z "$ac_aux_dir"; then
- { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
+ { { echo "$as_me:984: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5
+echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;}
+ { (exit 1); exit 1; }; }
fi
-ac_config_guess=$ac_aux_dir/config.guess
-ac_config_sub=$ac_aux_dir/config.sub
-ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"
+ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure.
# Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or
@@ -549,31 +996,39 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
# SunOS /usr/etc/install
# IRIX /sbin/install
# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
# AFS /usr/afsws/bin/install, which mishandles nonexistent args
# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
# ./install, which can be erroneously created by make from ./install.sh.
-echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:558: checking for a BSD compatible install" >&5
+echo "$as_me:1004: checking for a BSD compatible install" >&5
+echo $ECHO_N "checking for a BSD compatible install... $ECHO_C" >&6
if test -z "$INSTALL"; then
-if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+if test "${ac_cv_path_install+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
+ ac_save_IFS=$IFS; IFS=$ac_path_separator
for ac_dir in $PATH; do
+ IFS=$ac_save_IFS
# Account for people who put trailing slashes in PATH elements.
- case "$ac_dir/" in
- /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
+ case $ac_dir/ in
+ / | ./ | .// | /cC/* \
+ | /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* \
+ | /usr/ucb/* ) ;;
*)
# OSF1 and SCO ODT 3.0 have their own names for install.
# Don't use installbsd from OSF since it installs stuff as root
# by default.
for ac_prog in ginstall scoinst install; do
- if test -f $ac_dir/$ac_prog; then
+ if $as_executable_p "$ac_dir/$ac_prog"; then
if test $ac_prog = install &&
- grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
+ grep dspmsg "$ac_dir/$ac_prog" >/dev/null 2>&1; then
# AIX install. It has an incompatible calling convention.
:
+ elif test $ac_prog = install &&
+ grep pwplus "$ac_dir/$ac_prog" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
else
ac_cv_path_install="$ac_dir/$ac_prog -c"
break 2
@@ -583,31 +1038,31 @@ else
;;
esac
done
- IFS="$ac_save_IFS"
fi
if test "${ac_cv_path_install+set}" = set; then
- INSTALL="$ac_cv_path_install"
+ INSTALL=$ac_cv_path_install
else
# As a last resort, use the slow shell script. We don't cache a
# path for INSTALL within a source directory, because that will
# break other packages using the cache if that directory is
# removed, or if the path is relative.
- INSTALL="$ac_install_sh"
+ INSTALL=$ac_install_sh
fi
fi
-echo "$ac_t""$INSTALL" 1>&6
+echo "$as_me:1053: result: $INSTALL" >&5
+echo "${ECHO_T}$INSTALL" >&6
# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
# It thinks the first close brace ends the variable substitution.
test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
-test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-echo $ac_n "checking whether build environment is sane""... $ac_c" 1>&6
-echo "configure:611: checking whether build environment is sane" >&5
+echo "$as_me:1064: checking whether build environment is sane" >&5
+echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6
# Just in case
sleep 1
echo timestamp > conftestfile
@@ -629,8 +1084,11 @@ if (
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
- { echo "configure: error: ls -t appears to fail. Make sure there is not a broken
-alias in your environment" 1>&2; exit 1; }
+ { { echo "$as_me:1087: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" >&5
+echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken
+alias in your environment" >&2;}
+ { (exit 1); exit 1; }; }
fi
test "$2" = conftestfile
@@ -639,354 +1097,728 @@ then
# Ok.
:
else
- { echo "configure: error: newly created file is older than distributed files!
-Check your system clock" 1>&2; exit 1; }
+ { { echo "$as_me:1100: error: newly created file is older than distributed files!
+Check your system clock" >&5
+echo "$as_me: error: newly created file is older than distributed files!
+Check your system clock" >&2;}
+ { (exit 1); exit 1; }; }
fi
rm -f conftest*
-echo "$ac_t""yes" 1>&6
-if test "$program_transform_name" = s,x,x,; then
- program_transform_name=
-else
- # Double any \ or $. echo might interpret backslashes.
- cat <<\EOF_SED > conftestsed
-s,\\,\\\\,g; s,\$,$$,g
-EOF_SED
- program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
- rm -f conftestsed
-fi
+echo "$as_me:1107: result: yes" >&5
+echo "${ECHO_T}yes" >&6
test "$program_prefix" != NONE &&
- program_transform_name="s,^,${program_prefix},; $program_transform_name"
+ program_transform_name="s,^,$program_prefix,;$program_transform_name"
# Use a double $ so make ignores it.
test "$program_suffix" != NONE &&
- program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
-
-# sed with no file args requires a program.
-test "$program_transform_name" = "" && program_transform_name="s,x,x,"
-
-echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:668: checking whether ${MAKE-make} sets \${MAKE}" >&5
-set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ program_transform_name="s,\$,$program_suffix,;$program_transform_name"
+# Double any \ or $. echo might interpret backslashes.
+# By default was `s,x,x', remove it if useless.
+cat <<\_ACEOF >conftest.sed
+s/[\\$]/&&/g;s/;s,x,x,$//
+_ACEOF
+program_transform_name=`echo $program_transform_name | sed -f conftest.sed`
+rm conftest.sed
+
+echo "$as_me:1122: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo $ECHO_N "checking whether ${MAKE-make} sets \${MAKE}... $ECHO_C" >&6
+set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'`
+if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftestmake <<\EOF
+ cat >conftest.make <<\EOF
all:
@echo 'ac_maketemp="${MAKE}"'
EOF
# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
-eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=`
if test -n "$ac_maketemp"; then
eval ac_cv_prog_make_${ac_make}_set=yes
else
eval ac_cv_prog_make_${ac_make}_set=no
fi
-rm -f conftestmake
+rm -f conftest.make
fi
if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
- echo "$ac_t""yes" 1>&6
+ echo "$as_me:1142: result: yes" >&5
+echo "${ECHO_T}yes" >&6
SET_MAKE=
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:1146: result: no" >&5
+echo "${ECHO_T}no" >&6
SET_MAKE="MAKE=${MAKE-make}"
fi
-
PACKAGE=reiserfsprogs
-VERSION=3.x.0j
+VERSION=3.6.2
if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
- { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; }
+ { { echo "$as_me:1156: error: source directory already configured; run \"make distclean\" there first" >&5
+echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
+ { (exit 1); exit 1; }; }
fi
-cat >> confdefs.h <<EOF
+
+cat >>confdefs.h <<EOF
#define PACKAGE "$PACKAGE"
EOF
-cat >> confdefs.h <<EOF
+cat >>confdefs.h <<EOF
#define VERSION "$VERSION"
EOF
-
-
missing_dir=`cd $ac_aux_dir && pwd`
-echo $ac_n "checking for working aclocal""... $ac_c" 1>&6
-echo "configure:714: checking for working aclocal" >&5
+echo "$as_me:1170: checking for working aclocal" >&5
+echo $ECHO_N "checking for working aclocal... $ECHO_C" >&6
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if (aclocal --version) < /dev/null > /dev/null 2>&1; then
ACLOCAL=aclocal
- echo "$ac_t""found" 1>&6
+ echo "$as_me:1177: result: found" >&5
+echo "${ECHO_T}found" >&6
else
ACLOCAL="$missing_dir/missing aclocal"
- echo "$ac_t""missing" 1>&6
+ echo "$as_me:1181: result: missing" >&5
+echo "${ECHO_T}missing" >&6
fi
-echo $ac_n "checking for working autoconf""... $ac_c" 1>&6
-echo "configure:727: checking for working autoconf" >&5
+echo "$as_me:1185: checking for working autoconf" >&5
+echo $ECHO_N "checking for working autoconf... $ECHO_C" >&6
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if (autoconf --version) < /dev/null > /dev/null 2>&1; then
AUTOCONF=autoconf
- echo "$ac_t""found" 1>&6
+ echo "$as_me:1192: result: found" >&5
+echo "${ECHO_T}found" >&6
else
AUTOCONF="$missing_dir/missing autoconf"
- echo "$ac_t""missing" 1>&6
+ echo "$as_me:1196: result: missing" >&5
+echo "${ECHO_T}missing" >&6
fi
-echo $ac_n "checking for working automake""... $ac_c" 1>&6
-echo "configure:740: checking for working automake" >&5
+echo "$as_me:1200: checking for working automake" >&5
+echo $ECHO_N "checking for working automake... $ECHO_C" >&6
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if (automake --version) < /dev/null > /dev/null 2>&1; then
AUTOMAKE=automake
- echo "$ac_t""found" 1>&6
+ echo "$as_me:1207: result: found" >&5
+echo "${ECHO_T}found" >&6
else
AUTOMAKE="$missing_dir/missing automake"
- echo "$ac_t""missing" 1>&6
+ echo "$as_me:1211: result: missing" >&5
+echo "${ECHO_T}missing" >&6
fi
-echo $ac_n "checking for working autoheader""... $ac_c" 1>&6
-echo "configure:753: checking for working autoheader" >&5
+echo "$as_me:1215: checking for working autoheader" >&5
+echo $ECHO_N "checking for working autoheader... $ECHO_C" >&6
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if (autoheader --version) < /dev/null > /dev/null 2>&1; then
AUTOHEADER=autoheader
- echo "$ac_t""found" 1>&6
+ echo "$as_me:1222: result: found" >&5
+echo "${ECHO_T}found" >&6
else
AUTOHEADER="$missing_dir/missing autoheader"
- echo "$ac_t""missing" 1>&6
+ echo "$as_me:1226: result: missing" >&5
+echo "${ECHO_T}missing" >&6
fi
-echo $ac_n "checking for working makeinfo""... $ac_c" 1>&6
-echo "configure:766: checking for working makeinfo" >&5
+echo "$as_me:1230: checking for working makeinfo" >&5
+echo $ECHO_N "checking for working makeinfo... $ECHO_C" >&6
# Run test in a subshell; some versions of sh will print an error if
# an executable is not found, even if stderr is redirected.
# Redirect stdin to placate older versions of autoconf. Sigh.
if (makeinfo --version) < /dev/null > /dev/null 2>&1; then
MAKEINFO=makeinfo
- echo "$ac_t""found" 1>&6
+ echo "$as_me:1237: result: found" >&5
+echo "${ECHO_T}found" >&6
else
MAKEINFO="$missing_dir/missing makeinfo"
- echo "$ac_t""missing" 1>&6
+ echo "$as_me:1241: result: missing" >&5
+echo "${ECHO_T}missing" >&6
fi
+ac_config_headers="$ac_config_headers include/config.h"
+ac_config_commands="$ac_config_commands default-1"
+PRESET_CFLAGS=$CFLAGS
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+echo "$as_me:1258: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+ IFS=$ac_save_IFS
+ test -z "$ac_dir" && ac_dir=.
+ $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_CC="${ac_tool_prefix}gcc"
+echo "$as_me:1273: found $ac_dir/$ac_word" >&5
+break
+done
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ echo "$as_me:1281: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:1284: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
-PRESET_CFLAGS=$CFLAGS
-# Extract the first word of "gcc", so it can be a program name with args.
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
set dummy gcc; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:786: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:1293: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+ ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+ IFS=$ac_save_IFS
+ test -z "$ac_dir" && ac_dir=.
+ $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_ac_ct_CC="gcc"
+echo "$as_me:1308: found $ac_dir/$ac_word" >&5
+break
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:1316: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:1319: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+echo "$as_me:1332: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_CC="gcc"
- break
- fi
- done
- IFS="$ac_save_ifs"
+ ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+ IFS=$ac_save_IFS
+ test -z "$ac_dir" && ac_dir=.
+ $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_CC="${ac_tool_prefix}cc"
+echo "$as_me:1347: found $ac_dir/$ac_word" >&5
+break
+done
+
fi
fi
-CC="$ac_cv_prog_CC"
+CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
+ echo "$as_me:1355: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
+else
+ echo "$as_me:1358: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+echo "$as_me:1367: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+ ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+ IFS=$ac_save_IFS
+ test -z "$ac_dir" && ac_dir=.
+ $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_ac_ct_CC="cc"
+echo "$as_me:1382: found $ac_dir/$ac_word" >&5
+break
+done
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:1390: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:1393: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ CC=$ac_ct_CC
else
- echo "$ac_t""no" 1>&6
+ CC="$ac_cv_prog_CC"
fi
+fi
if test -z "$CC"; then
# Extract the first word of "cc", so it can be a program name with args.
set dummy cc; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:816: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:1406: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
ac_prog_rejected=no
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
- ac_prog_rejected=yes
- continue
- fi
- ac_cv_prog_CC="cc"
- break
- fi
- done
- IFS="$ac_save_ifs"
+ ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+ IFS=$ac_save_IFS
+ test -z "$ac_dir" && ac_dir=.
+ $as_executable_p "$ac_dir/$ac_word" || continue
+if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+fi
+ac_cv_prog_CC="cc"
+echo "$as_me:1426: found $ac_dir/$ac_word" >&5
+break
+done
+
if test $ac_prog_rejected = yes; then
# We found a bogon in the path, so make sure we never use it.
set dummy $ac_cv_prog_CC
shift
- if test $# -gt 0; then
+ if test $# != 0; then
# We chose a different compiler from the bogus one.
# However, it has the same basename, so the bogon will be chosen
# first if we set CC to just the basename; use the full file name.
shift
- set dummy "$ac_dir/$ac_word" "$@"
+ set dummy "$ac_dir/$ac_word" ${1+"$@"}
shift
ac_cv_prog_CC="$@"
fi
fi
fi
fi
-CC="$ac_cv_prog_CC"
+CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
+ echo "$as_me:1448: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:1451: result: no" >&5
+echo "${ECHO_T}no" >&6
fi
- if test -z "$CC"; then
- case "`uname -s`" in
- *win32* | *WIN32*)
- # Extract the first word of "cl", so it can be a program name with args.
-set dummy cl; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:867: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:1462: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$CC"; then
ac_cv_prog_CC="$CC" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_CC="cl"
- break
- fi
- done
- IFS="$ac_save_ifs"
+ ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+ IFS=$ac_save_IFS
+ test -z "$ac_dir" && ac_dir=.
+ $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+echo "$as_me:1477: found $ac_dir/$ac_word" >&5
+break
+done
+
fi
fi
-CC="$ac_cv_prog_CC"
+CC=$ac_cv_prog_CC
if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
+ echo "$as_me:1485: result: $CC" >&5
+echo "${ECHO_T}$CC" >&6
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:1488: result: no" >&5
+echo "${ECHO_T}no" >&6
fi
- ;;
- esac
- fi
- test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
+
+ test -n "$CC" && break
+ done
fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:1501: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+ ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+ IFS=$ac_save_IFS
+ test -z "$ac_dir" && ac_dir=.
+ $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_ac_ct_CC="$ac_prog"
+echo "$as_me:1516: found $ac_dir/$ac_word" >&5
+break
+done
-echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:899: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ echo "$as_me:1524: result: $ac_ct_CC" >&5
+echo "${ECHO_T}$ac_ct_CC" >&6
+else
+ echo "$as_me:1527: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
+ test -n "$ac_ct_CC" && break
+done
-cat > conftest.$ac_ext << EOF
+ CC=$ac_ct_CC
+fi
-#line 910 "configure"
+fi
+
+test -z "$CC" && { { echo "$as_me:1539: error: no acceptable cc found in \$PATH" >&5
+echo "$as_me: error: no acceptable cc found in \$PATH" >&2;}
+ { (exit 1); exit 1; }; }
+
+# Provide some information about the compiler.
+echo "$as_me:1544:" \
+ "checking for C compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:1547: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:1550: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:1552: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:1555: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:1557: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:1560: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+#line 1564 "configure"
#include "confdefs.h"
-main(){return(0);}
-EOF
-if { (eval echo configure:915: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- ac_cv_prog_cc_works=yes
- # If we can't run a trivial program, we are probably using a cross compiler.
- if (./conftest; exit) 2>/dev/null; then
- ac_cv_prog_cc_cross=no
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:1580: checking for C compiler default output" >&5
+echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:1583: \"$ac_link_default\"") >&5
+ (eval $ac_link_default) 2>&5
+ ac_status=$?
+ echo "$as_me:1586: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Find the output, starting from the most likely. This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+for ac_file in `ls a.exe conftest.exe 2>/dev/null;
+ ls a.out conftest 2>/dev/null;
+ ls a.* conftest.* 2>/dev/null`; do
+ case $ac_file in
+ *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb ) ;;
+ a.out ) # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ # FIXME: I believe we export ac_cv_exeext for Libtool --akim.
+ export ac_cv_exeext
+ break;;
+ * ) break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+{ { echo "$as_me:1609: error: C compiler cannot create executables" >&5
+echo "$as_me: error: C compiler cannot create executables" >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:1615: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:1620: checking whether the C compiler works" >&5
+echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (eval echo "$as_me:1626: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:1629: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
else
- ac_cv_prog_cc_cross=yes
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:1636: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'." >&5
+echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
fi
+fi
+echo "$as_me:1644: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:1651: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:1653: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:1656: checking for executable suffix" >&5
+echo $ECHO_N "checking for executable suffix... $ECHO_C" >&6
+if { (eval echo "$as_me:1658: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:1661: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in `(ls conftest.exe; ls conftest; ls conftest.*) 2>/dev/null`; do
+ case $ac_file in
+ *.$ac_ext | *.o | *.obj | *.xcoff | *.tds | *.d | *.pdb ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ export ac_cv_exeext
+ break;;
+ * ) break;;
+ esac
+done
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- ac_cv_prog_cc_works=no
+ { { echo "$as_me:1677: error: cannot compute EXEEXT: cannot compile and link" >&5
+echo "$as_me: error: cannot compute EXEEXT: cannot compile and link" >&2;}
+ { (exit 1); exit 1; }; }
fi
-rm -fr conftest*
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
-if test $ac_cv_prog_cc_works = no; then
- { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
-fi
-echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:941: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
-echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
-cross_compiling=$ac_cv_prog_cc_cross
-
-echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:946: checking whether we are using GNU C" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.c <<EOF
-#ifdef __GNUC__
- yes;
-#endif
-EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:955: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
- ac_cv_prog_gcc=yes
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:1683: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:1689: checking for object suffix" >&5
+echo $ECHO_N "checking for object suffix... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- ac_cv_prog_gcc=no
+ cat >conftest.$ac_ext <<_ACEOF
+#line 1695 "configure"
+#include "confdefs.h"
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:1707: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:1710: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+{ { echo "$as_me:1722: error: cannot compute OBJEXT: cannot compile" >&5
+echo "$as_me: error: cannot compute OBJEXT: cannot compile" >&2;}
+ { (exit 1); exit 1; }; }
fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
fi
+echo "$as_me:1729: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:1733: checking whether we are using the GNU C compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line 1739 "configure"
+#include "confdefs.h"
-echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
-if test $ac_cv_prog_gcc = yes; then
- GCC=yes
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:1754: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:1757: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:1760: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:1763: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
else
- GCC=
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_compiler_gnu=no
fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
-ac_test_CFLAGS="${CFLAGS+set}"
-ac_save_CFLAGS="$CFLAGS"
-CFLAGS=
-echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:974: checking whether ${CC-cc} accepts -g" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+fi
+echo "$as_me:1775: result: $ac_cv_c_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6
+GCC=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+CFLAGS="-g"
+echo "$as_me:1781: checking whether $CC accepts -g" >&5
+echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- echo 'void f(){}' > conftest.c
-if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+ cat >conftest.$ac_ext <<_ACEOF
+#line 1787 "configure"
+#include "confdefs.h"
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:1799: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:1802: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:1805: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:1808: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
ac_cv_prog_cc_g=yes
else
- ac_cv_prog_cc_g=no
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_prog_cc_g=no
fi
-rm -f conftest*
-
+rm -f conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
+echo "$as_me:1818: result: $ac_cv_prog_cc_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_g" >&6
if test "$ac_test_CFLAGS" = set; then
- CFLAGS="$ac_save_CFLAGS"
+ CFLAGS=$ac_save_CFLAGS
elif test $ac_cv_prog_cc_g = yes; then
if test "$GCC" = yes; then
CFLAGS="-g -O2"
@@ -1000,163 +1832,446 @@ else
CFLAGS=
fi
fi
+# Some people use a C++ compiler to compile C. Since we use `exit',
+# in C++ we need to declare it. In case someone uses the same compiler
+# for both compiling C and C++ we need to have the C++ compiler decide
+# the declaration of exit, since it's the most demanding environment.
+cat >conftest.$ac_ext <<_ACEOF
+#ifndef __cplusplus
+ choke me
+#endif
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:1845: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:1848: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:1851: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:1854: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ for ac_declaration in \
+ ''\
+ '#include <stdlib.h>' \
+ 'extern "C" void std::exit (int) throw (); using std::exit;' \
+ 'extern "C" void std::exit (int); using std::exit;' \
+ 'extern "C" void exit (int) throw ();' \
+ 'extern "C" void exit (int);' \
+ 'void exit (int);'
+do
+ cat >conftest.$ac_ext <<_ACEOF
+#line 1866 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+$ac_declaration
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:1879: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:1882: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:1885: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:1888: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+continue
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+#line 1898 "configure"
+#include "confdefs.h"
+$ac_declaration
+int
+main ()
+{
+exit (42);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:1910: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:1913: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:1916: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:1919: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+ echo '#ifdef __cplusplus' >>confdefs.h
+ echo $ac_declaration >>confdefs.h
+ echo '#endif' >>confdefs.h
+fi
+
+else
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
-if test -z $PRESET_CFLAGS; then
- CFLAGS="${RPM_OPT_FLAGS} -g -O2 -Wall"
+if test "x" = "x$PRESET_CFLAGS"; then
+ CFLAGS="${RPM_OPT_FLAGS} $CFLAGS -Wall"
fi
-# Extract the first word of "ranlib", so it can be a program name with args.
-set dummy ranlib; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1012: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+echo "$as_me:1953: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test -n "$RANLIB"; then
ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
- ac_dummy="$PATH"
- for ac_dir in $ac_dummy; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_RANLIB="ranlib"
- break
- fi
- done
- IFS="$ac_save_ifs"
- test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
+ ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+ IFS=$ac_save_IFS
+ test -z "$ac_dir" && ac_dir=.
+ $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+echo "$as_me:1968: found $ac_dir/$ac_word" >&5
+break
+done
+
fi
fi
-RANLIB="$ac_cv_prog_RANLIB"
+RANLIB=$ac_cv_prog_RANLIB
if test -n "$RANLIB"; then
- echo "$ac_t""$RANLIB" 1>&6
+ echo "$as_me:1976: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6
else
- echo "$ac_t""no" 1>&6
+ echo "$as_me:1979: result: no" >&5
+echo "${ECHO_T}no" >&6
fi
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+echo "$as_me:1988: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+ ac_save_IFS=$IFS; IFS=$ac_path_separator
+ac_dummy="$PATH"
+for ac_dir in $ac_dummy; do
+ IFS=$ac_save_IFS
+ test -z "$ac_dir" && ac_dir=.
+ $as_executable_p "$ac_dir/$ac_word" || continue
+ac_cv_prog_ac_ct_RANLIB="ranlib"
+echo "$as_me:2003: found $ac_dir/$ac_word" >&5
+break
+done
+ test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":"
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ echo "$as_me:2012: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6
+else
+ echo "$as_me:2015: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
-echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:1042: checking how to run the C preprocessor" >&5
+ RANLIB=$ac_ct_RANLIB
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+echo "$as_me:2029: checking how to run the C preprocessor" >&5
+echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
fi
if test -z "$CPP"; then
-if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ if test "${ac_cv_prog_CPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- # This must be in double quotes, not single quotes, because CPP may get
- # substituted into the Makefile and "${CC-cc}" will confuse make.
- CPP="${CC-cc} -E"
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
# On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp.
- cat > conftest.$ac_ext <<EOF
-#line 1057 "configure"
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+#line 2050 "configure"
#include "confdefs.h"
#include <assert.h>
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1063: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:2055: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ egrep -v '^ *\+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:2061: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
:
else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
+ echo "$as_me: failed program was:" >&5
cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP="${CC-cc} -E -traditional-cpp"
- cat > conftest.$ac_ext <<EOF
-#line 1074 "configure"
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+#line 2084 "configure"
#include "confdefs.h"
-#include <assert.h>
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1080: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- :
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:2088: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ egrep -v '^ *\+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:2094: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP="${CC-cc} -nologo -E"
- cat > conftest.$ac_ext <<EOF
-#line 1091 "configure"
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+echo "$as_me:2131: result: $CPP" >&5
+echo "${ECHO_T}$CPP" >&6
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+#line 2141 "configure"
#include "confdefs.h"
#include <assert.h>
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1097: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:2146: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ egrep -v '^ *\+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:2152: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
:
else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
+ echo "$as_me: failed program was:" >&5
cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP=/lib/cpp
-fi
-rm -f conftest*
+ # Broken: fails on valid input.
+continue
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+#line 2175 "configure"
+#include "confdefs.h"
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:2179: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ egrep -v '^ *\+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:2185: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
fi
-rm -f conftest*
- ac_cv_prog_CPP="$CPP"
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ # Passes both tests.
+ac_preproc_ok=:
+break
fi
- CPP="$ac_cv_prog_CPP"
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
else
- ac_cv_prog_CPP="$CPP"
+ { { echo "$as_me:2213: error: C preprocessor \"$CPP\" fails sanity check" >&5
+echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check" >&2;}
+ { (exit 1); exit 1; }; }
fi
-echo "$ac_t""$CPP" 1>&6
-echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:1122: checking for ANSI C header files" >&5
-if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+echo "$as_me:2224: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 1127 "configure"
+ cat >conftest.$ac_ext <<_ACEOF
+#line 2230 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <float.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1135: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
+
+_ACEOF
+if { (eval echo "$as_me:2238: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ egrep -v '^ *\+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:2244: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
ac_cv_header_stdc=yes
else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
+ echo "$as_me: failed program was:" >&5
cat conftest.$ac_ext >&5
- rm -rf conftest*
ac_cv_header_stdc=no
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_ext
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
-cat > conftest.$ac_ext <<EOF
-#line 1152 "configure"
+ cat >conftest.$ac_ext <<_ACEOF
+#line 2266 "configure"
#include "confdefs.h"
#include <string.h>
-EOF
+
+_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
egrep "memchr" >/dev/null 2>&1; then
:
else
- rm -rf conftest*
ac_cv_header_stdc=no
fi
rm -f conftest*
@@ -1165,16 +2280,16 @@ fi
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
-cat > conftest.$ac_ext <<EOF
-#line 1170 "configure"
+ cat >conftest.$ac_ext <<_ACEOF
+#line 2284 "configure"
#include "confdefs.h"
#include <stdlib.h>
-EOF
+
+_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
egrep "free" >/dev/null 2>&1; then
:
else
- rm -rf conftest*
ac_cv_header_stdc=no
fi
rm -f conftest*
@@ -1183,884 +2298,1818 @@ fi
if test $ac_cv_header_stdc = yes; then
# /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
-if test "$cross_compiling" = yes; then
+ if test "$cross_compiling" = yes; then
:
else
- cat > conftest.$ac_ext <<EOF
-#line 1191 "configure"
+ cat >conftest.$ac_ext <<_ACEOF
+#line 2305 "configure"
#include "confdefs.h"
#include <ctype.h>
-#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int main () { int i; for (i = 0; i < 256; i++)
-if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
-exit (0); }
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
-EOF
-if { (eval echo configure:1202: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ exit(2);
+ exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:2331: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:2334: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:2336: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:2339: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
:
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_header_stdc=no
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_header_stdc=no
fi
-rm -fr conftest*
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
-
fi
fi
-
-echo "$ac_t""$ac_cv_header_stdc" 1>&6
+echo "$as_me:2352: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
if test $ac_cv_header_stdc = yes; then
- cat >> confdefs.h <<\EOF
+
+cat >>confdefs.h <<\EOF
#define STDC_HEADERS 1
EOF
fi
-for ac_hdr in fcntl.h limits.h malloc.h sys/ioctl.h unistd.h
+for ac_header in fcntl.h limits.h malloc.h sys/ioctl.h unistd.h
do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1229: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1234 "configure"
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:2365: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line 2371 "configure"
#include "confdefs.h"
-#include <$ac_hdr>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1239: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
+#include <$ac_header>
+_ACEOF
+if { (eval echo "$as_me:2375: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ egrep -v '^ *\+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:2381: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_c_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
+ eval "$as_ac_Header=no"
fi
-rm -f conftest*
+rm -f conftest.err conftest.$ac_ext
fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
+echo "$as_me:2400: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
EOF
-
-else
- echo "$ac_t""no" 1>&6
+
fi
done
-
-echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:1267: checking for working const" >&5
-if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:2410: checking for $CC option to accept ANSI C" >&5
+echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6
+if test "${ac_cv_prog_cc_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 1272 "configure"
+ ac_cv_prog_cc_stdc=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+#line 2418 "configure"
#include "confdefs.h"
-
-int main() {
-
-/* Ultrix mips cc rejects this. */
-typedef int charset[2]; const charset x;
-/* SunOS 4.1.1 cc rejects this. */
-char const *const *ccp;
-char **p;
-/* NEC SVR4.0.2 mips cc rejects this. */
-struct point {int x, y;};
-static struct point const zero = {0,0};
-/* AIX XL C 1.02.0.0 rejects this.
- It does not let you subtract one const X* pointer from another in an arm
- of an if-expression whose if-part is not a constant expression */
-const char *g = "string";
-ccp = &g + (g ? g-g : 0);
-/* HPUX 7.0 cc rejects these. */
-++ccp;
-p = (char**) ccp;
-ccp = (char const *const *) p;
-{ /* SCO 3.2v4 cc rejects this. */
- char *t;
- char const *s = 0 ? (char *) 0 : (char const *) 0;
-
- *t++ = 0;
-}
-{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
- int x[] = {25, 17};
- const int *foo = &x[0];
- ++foo;
-}
-{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
- typedef const int *iptr;
- iptr p = 0;
- ++p;
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
}
-{ /* AIX XL C 1.02.0.0 rejects this saying
- "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
- struct s { int j; const int *ap[3]; };
- struct s *b; b->j = 5;
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
}
-{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
- const int foo = 10;
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
}
+_ACEOF
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX 10.20 and later -Ae
+# HP-UX older versions -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ rm -f conftest.$ac_objext
+if { (eval echo "$as_me:2467: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:2470: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:2473: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:2476: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cc_stdc=$ac_arg
+break
+else
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+fi
+rm -f conftest.$ac_objext
+done
+rm -f conftest.$ac_ext conftest.$ac_objext
+CC=$ac_save_CC
-; return 0; }
-EOF
-if { (eval echo configure:1321: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+fi
+
+case "x$ac_cv_prog_cc_stdc" in
+ x|xno)
+ echo "$as_me:2493: result: none needed" >&5
+echo "${ECHO_T}none needed" >&6 ;;
+ *)
+ echo "$as_me:2496: result: $ac_cv_prog_cc_stdc" >&5
+echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6
+ CC="$CC $ac_cv_prog_cc_stdc" ;;
+esac
+
+echo "$as_me:2501: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6
+if test "${ac_cv_c_const+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line 2507 "configure"
+#include "confdefs.h"
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+ /* Ultrix mips cc rejects this. */
+ typedef int charset[2];
+ const charset x;
+ /* SunOS 4.1.1 cc rejects this. */
+ char const *const *ccp;
+ char **p;
+ /* NEC SVR4.0.2 mips cc rejects this. */
+ struct point {int x, y;};
+ static struct point const zero = {0,0};
+ /* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in
+ an arm of an if-expression whose if-part is not a constant
+ expression */
+ const char *g = "string";
+ ccp = &g + (g ? g-g : 0);
+ /* HPUX 7.0 cc rejects these. */
+ ++ccp;
+ p = (char**) ccp;
+ ccp = (char const *const *) p;
+ { /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+ }
+ { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+ }
+ { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+ }
+ { /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+ }
+ { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+ }
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:2565: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:2568: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:2571: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:2574: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
ac_cv_c_const=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_c_const=no
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_c_const=no
fi
-rm -f conftest*
+rm -f conftest.$ac_objext conftest.$ac_ext
fi
-
-echo "$ac_t""$ac_cv_c_const" 1>&6
+echo "$as_me:2584: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6
if test $ac_cv_c_const = no; then
- cat >> confdefs.h <<\EOF
-#define const
+
+cat >>confdefs.h <<\EOF
+#define const
EOF
fi
-echo $ac_n "checking for inline""... $ac_c" 1>&6
-echo "configure:1342: checking for inline" >&5
-if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:2594: checking for inline" >&5
+echo $ECHO_N "checking for inline... $ECHO_C" >&6
+if test "${ac_cv_c_inline+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
ac_cv_c_inline=no
for ac_kw in inline __inline__ __inline; do
- cat > conftest.$ac_ext <<EOF
-#line 1349 "configure"
+ cat >conftest.$ac_ext <<_ACEOF
+#line 2602 "configure"
#include "confdefs.h"
+#ifndef __cplusplus
+static $ac_kw int static_foo () {return 0; }
+$ac_kw int foo () {return 0; }
+#endif
-int main() {
-} $ac_kw foo() {
-; return 0; }
-EOF
-if { (eval echo configure:1356: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:2611: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:2614: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:2617: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:2620: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
ac_cv_c_inline=$ac_kw; break
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
fi
-rm -f conftest*
+rm -f conftest.$ac_objext conftest.$ac_ext
done
fi
-
-echo "$ac_t""$ac_cv_c_inline" 1>&6
-case "$ac_cv_c_inline" in
+echo "$as_me:2631: result: $ac_cv_c_inline" >&5
+echo "${ECHO_T}$ac_cv_c_inline" >&6
+case $ac_cv_c_inline in
inline | yes) ;;
- no) cat >> confdefs.h <<\EOF
-#define inline
+ no)
+cat >>confdefs.h <<\EOF
+#define inline
EOF
;;
- *) cat >> confdefs.h <<EOF
+ *) cat >>confdefs.h <<EOF
#define inline $ac_cv_c_inline
EOF
;;
esac
-echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:1382: checking for size_t" >&5
-if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+echo "$as_me:2652: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6
+if eval "test \"\${$as_ac_Header+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 1387 "configure"
+ cat >conftest.$ac_ext <<_ACEOF
+#line 2658 "configure"
#include "confdefs.h"
-#include <sys/types.h>
-#if STDC_HEADERS
-#include <stdlib.h>
-#include <stddef.h>
-#endif
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:2664: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:2667: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:2670: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:2673: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$as_ac_Header=no"
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:2683: result: `eval echo '${'$as_ac_Header'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "(^|[^a-zA-Z_0-9])size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
- rm -rf conftest*
+
+fi
+done
+
+echo "$as_me:2693: checking for size_t" >&5
+echo $ECHO_N "checking for size_t... $ECHO_C" >&6
+if test "${ac_cv_type_size_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line 2699 "configure"
+#include "confdefs.h"
+$ac_includes_default
+int
+main ()
+{
+if ((size_t *) 0)
+ return 0;
+if (sizeof (size_t))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:2714: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:2717: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:2720: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:2723: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
ac_cv_type_size_t=yes
else
- rm -rf conftest*
- ac_cv_type_size_t=no
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_type_size_t=no
fi
-rm -f conftest*
-
+rm -f conftest.$ac_objext conftest.$ac_ext
fi
-echo "$ac_t""$ac_cv_type_size_t" 1>&6
-if test $ac_cv_type_size_t = no; then
- cat >> confdefs.h <<\EOF
+echo "$as_me:2733: result: $ac_cv_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_type_size_t" >&6
+if test $ac_cv_type_size_t = yes; then
+ :
+else
+
+cat >>confdefs.h <<EOF
#define size_t unsigned
EOF
fi
-echo $ac_n "checking for st_rdev in struct stat""... $ac_c" 1>&6
-echo "configure:1415: checking for st_rdev in struct stat" >&5
-if eval "test \"`echo '$''{'ac_cv_struct_st_rdev'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:2745: checking for struct stat.st_rdev" >&5
+echo $ECHO_N "checking for struct stat.st_rdev... $ECHO_C" >&6
+if test "${ac_cv_member_struct_stat_st_rdev+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 1420 "configure"
+ cat >conftest.$ac_ext <<_ACEOF
+#line 2751 "configure"
#include "confdefs.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-int main() {
-struct stat s; s.st_rdev;
-; return 0; }
-EOF
-if { (eval echo configure:1428: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_struct_st_rdev=yes
+$ac_includes_default
+int
+main ()
+{
+static struct stat ac_aggr;
+if (ac_aggr.st_rdev)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:2765: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:2768: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:2771: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:2774: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_member_struct_stat_st_rdev=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_struct_st_rdev=no
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_member_struct_stat_st_rdev=no
fi
-rm -f conftest*
+rm -f conftest.$ac_objext conftest.$ac_ext
fi
+echo "$as_me:2784: result: $ac_cv_member_struct_stat_st_rdev" >&5
+echo "${ECHO_T}$ac_cv_member_struct_stat_st_rdev" >&6
+if test $ac_cv_member_struct_stat_st_rdev = yes; then
-echo "$ac_t""$ac_cv_struct_st_rdev" 1>&6
-if test $ac_cv_struct_st_rdev = yes; then
- cat >> confdefs.h <<\EOF
+cat >>confdefs.h <<EOF
+#define HAVE_STRUCT_STAT_ST_RDEV 1
+EOF
+
+cat >>confdefs.h <<\EOF
#define HAVE_ST_RDEV 1
EOF
fi
-
-if test $ac_cv_prog_gcc = yes; then
- echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
-echo "configure:1451: checking whether ${CC-cc} needs -traditional" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+if test $ac_cv_c_compiler_gnu = yes; then
+ echo "$as_me:2799: checking whether $CC needs -traditional" >&5
+echo $ECHO_N "checking whether $CC needs -traditional... $ECHO_C" >&6
+if test "${ac_cv_prog_gcc_traditional+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
ac_pattern="Autoconf.*'x'"
- cat > conftest.$ac_ext <<EOF
-#line 1457 "configure"
+ cat >conftest.$ac_ext <<_ACEOF
+#line 2806 "configure"
#include "confdefs.h"
#include <sgtty.h>
Autoconf TIOCGETP
-EOF
+_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
egrep "$ac_pattern" >/dev/null 2>&1; then
- rm -rf conftest*
ac_cv_prog_gcc_traditional=yes
else
- rm -rf conftest*
ac_cv_prog_gcc_traditional=no
fi
rm -f conftest*
-
if test $ac_cv_prog_gcc_traditional = no; then
- cat > conftest.$ac_ext <<EOF
-#line 1475 "configure"
+ cat >conftest.$ac_ext <<_ACEOF
+#line 2821 "configure"
#include "confdefs.h"
#include <termio.h>
Autoconf TCGETA
-EOF
+_ACEOF
if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
egrep "$ac_pattern" >/dev/null 2>&1; then
- rm -rf conftest*
ac_cv_prog_gcc_traditional=yes
fi
rm -f conftest*
fi
fi
-
-echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6
+echo "$as_me:2834: result: $ac_cv_prog_gcc_traditional" >&5
+echo "${ECHO_T}$ac_cv_prog_gcc_traditional" >&6
if test $ac_cv_prog_gcc_traditional = yes; then
CC="$CC -traditional"
fi
fi
-echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6
-echo "configure:1497: checking for 8-bit clean memcmp" >&5
-if eval "test \"`echo '$''{'ac_cv_func_memcmp_clean'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+echo "$as_me:2841: checking for working memcmp" >&5
+echo $ECHO_N "checking for working memcmp... $ECHO_C" >&6
+if test "${ac_cv_func_memcmp_working+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
if test "$cross_compiling" = yes; then
- ac_cv_func_memcmp_clean=no
+ ac_cv_func_memcmp_working=no
else
- cat > conftest.$ac_ext <<EOF
-#line 1505 "configure"
+ cat >conftest.$ac_ext <<_ACEOF
+#line 2850 "configure"
#include "confdefs.h"
-main()
+int
+main ()
{
+
+ /* Some versions of memcmp are not 8-bit clean. */
char c0 = 0x40, c1 = 0x80, c2 = 0x81;
- exit(memcmp(&c0, &c2, 1) < 0 && memcmp(&c1, &c2, 1) < 0 ? 0 : 1);
+ if (memcmp(&c0, &c2, 1) >= 0 || memcmp(&c1, &c2, 1) >= 0)
+ exit (1);
+
+ /* The Next x86 OpenStep bug shows up only when comparing 16 bytes
+ or more and with at least one buffer not starting on a 4-byte boundary.
+ William Lewis provided this test program. */
+ {
+ char foo[21];
+ char bar[21];
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ char *a = foo + i;
+ char *b = bar + i;
+ strcpy (a, "--------01111111");
+ strcpy (b, "--------10000000");
+ if (memcmp (a, b, 16) >= 0)
+ exit (1);
+ }
+ exit (0);
+ }
+
+ ;
+ return 0;
}
-
-EOF
-if { (eval echo configure:1515: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
-then
- ac_cv_func_memcmp_clean=yes
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:2886: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:2889: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:2891: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:2894: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_memcmp_working=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_func_memcmp_clean=no
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_func_memcmp_working=no
fi
-rm -fr conftest*
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
fi
-
fi
+echo "$as_me:2906: result: $ac_cv_func_memcmp_working" >&5
+echo "${ECHO_T}$ac_cv_func_memcmp_working" >&6
+test $ac_cv_func_memcmp_working = no && LIBOBJS="$LIBOBJS memcmp.$ac_objext"
-echo "$ac_t""$ac_cv_func_memcmp_clean" 1>&6
-test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}"
-
-echo $ac_n "checking for strftime""... $ac_c" 1>&6
-echo "configure:1533: checking for strftime" >&5
-if eval "test \"`echo '$''{'ac_cv_func_strftime'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+for ac_func in strftime
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:2913: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 1538 "configure"
+ cat >conftest.$ac_ext <<_ACEOF
+#line 2919 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char strftime(); below. */
+ which can conflict with char $ac_func (); below. */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char strftime();
-
-int main() {
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+char (*f) ();
+int
+main ()
+{
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
-#if defined (__stub_strftime) || defined (__stub___strftime)
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
-strftime();
+f = $ac_func;
#endif
-; return 0; }
-EOF
-if { (eval echo configure:1561: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_strftime=yes"
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:2950: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:2953: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:2956: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:2959: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_strftime=no"
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$as_ac_var=no"
fi
-rm -f conftest*
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
fi
-
-if eval "test \"`echo '$ac_cv_func_'strftime`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- cat >> confdefs.h <<\EOF
-#define HAVE_STRFTIME 1
+echo "$as_me:2969: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
EOF
else
- echo "$ac_t""no" 1>&6
-# strftime is in -lintl on SCO UNIX.
-echo $ac_n "checking for strftime in -lintl""... $ac_c" 1>&6
-echo "configure:1583: checking for strftime in -lintl" >&5
-ac_lib_var=`echo intl'_'strftime | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+ # strftime is in -lintl on SCO UNIX.
+echo "$as_me:2978: checking for strftime in -lintl" >&5
+echo $ECHO_N "checking for strftime in -lintl... $ECHO_C" >&6
+if test "${ac_cv_lib_intl_strftime+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- ac_save_LIBS="$LIBS"
+ ac_check_lib_save_LIBS=$LIBS
LIBS="-lintl $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1591 "configure"
+cat >conftest.$ac_ext <<_ACEOF
+#line 2986 "configure"
#include "confdefs.h"
+
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char strftime();
-
-int main() {
-strftime()
-; return 0; }
-EOF
-if { (eval echo configure:1602: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
+ builtin and then its argument prototype would still apply. */
+char strftime ();
+int
+main ()
+{
+strftime ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:3005: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:3008: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:3011: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:3014: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_lib_intl_strftime=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_lib_intl_strftime=no
fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- cat >> confdefs.h <<\EOF
+echo "$as_me:3025: result: $ac_cv_lib_intl_strftime" >&5
+echo "${ECHO_T}$ac_cv_lib_intl_strftime" >&6
+if test $ac_cv_lib_intl_strftime = yes; then
+ cat >>confdefs.h <<\EOF
#define HAVE_STRFTIME 1
EOF
LIBS="-lintl $LIBS"
-else
- echo "$ac_t""no" 1>&6
fi
fi
+done
-echo $ac_n "checking for vprintf""... $ac_c" 1>&6
-echo "configure:1629: checking for vprintf" >&5
-if eval "test \"`echo '$''{'ac_cv_func_vprintf'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+for ac_func in vprintf
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:3041: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 1634 "configure"
+ cat >conftest.$ac_ext <<_ACEOF
+#line 3047 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char vprintf(); below. */
+ which can conflict with char $ac_func (); below. */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char vprintf();
-
-int main() {
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+char (*f) ();
+int
+main ()
+{
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
-#if defined (__stub_vprintf) || defined (__stub___vprintf)
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
-vprintf();
+f = $ac_func;
#endif
-; return 0; }
-EOF
-if { (eval echo configure:1657: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_vprintf=yes"
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:3078: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:3081: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:3084: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:3087: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_vprintf=no"
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$as_ac_var=no"
fi
-rm -f conftest*
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
fi
-
-if eval "test \"`echo '$ac_cv_func_'vprintf`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- cat >> confdefs.h <<\EOF
-#define HAVE_VPRINTF 1
+echo "$as_me:3097: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
EOF
+echo "$as_me:3104: checking for _doprnt" >&5
+echo $ECHO_N "checking for _doprnt... $ECHO_C" >&6
+if test "${ac_cv_func__doprnt+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- echo "$ac_t""no" 1>&6
-fi
-
-if test "$ac_cv_func_vprintf" != yes; then
-echo $ac_n "checking for _doprnt""... $ac_c" 1>&6
-echo "configure:1681: checking for _doprnt" >&5
-if eval "test \"`echo '$''{'ac_cv_func__doprnt'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1686 "configure"
+ cat >conftest.$ac_ext <<_ACEOF
+#line 3110 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char _doprnt(); below. */
+ which can conflict with char _doprnt (); below. */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char _doprnt();
-
-int main() {
+ builtin and then its argument prototype would still apply. */
+char _doprnt ();
+char (*f) ();
+int
+main ()
+{
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub__doprnt) || defined (__stub____doprnt)
choke me
#else
-_doprnt();
+f = _doprnt;
#endif
-; return 0; }
-EOF
-if { (eval echo configure:1709: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func__doprnt=yes"
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:3141: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:3144: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:3147: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:3150: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func__doprnt=yes
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func__doprnt=no"
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+ac_cv_func__doprnt=no
fi
-rm -f conftest*
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
fi
+echo "$as_me:3160: result: $ac_cv_func__doprnt" >&5
+echo "${ECHO_T}$ac_cv_func__doprnt" >&6
+if test $ac_cv_func__doprnt = yes; then
-if eval "test \"`echo '$ac_cv_func_'_doprnt`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- cat >> confdefs.h <<\EOF
+cat >>confdefs.h <<\EOF
#define HAVE_DOPRNT 1
EOF
-else
- echo "$ac_t""no" 1>&6
fi
fi
+done
for ac_func in strerror strstr strtol
do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:1736: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:3176: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
else
- cat > conftest.$ac_ext <<EOF
-#line 1741 "configure"
+ cat >conftest.$ac_ext <<_ACEOF
+#line 3182 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
+ which can conflict with char $ac_func (); below. */
#include <assert.h>
/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+#endif
/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
-
-int main() {
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+char (*f) ();
+int
+main ()
+{
/* The GNU C library defines this for functions which it implements
to always fail with ENOSYS. Some functions are actually named
something starting with __ and the normal name is an alias. */
#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
choke me
#else
-$ac_func();
+f = $ac_func;
#endif
-; return 0; }
-EOF
-if { (eval echo configure:1764: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:3213: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:3216: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:3219: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:3222: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
+ echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+eval "$as_ac_var=no"
fi
-rm -f conftest*
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
fi
-
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
+echo "$as_me:3232: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<EOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
EOF
-
-else
- echo "$ac_t""no" 1>&6
+
fi
done
+# Check whether --enable-io-failure-emulation or --disable-io-failure-emulation was given.
+if test "${enable_io_failure_emulation+set}" = set; then
+ enableval="$enable_io_failure_emulation"
+ if test "$enableval" = "yes" ; then
+ echo -e "\nCarefull! IO failure emulation is ON\n"
-trap '' 1 2 15
-cat > confcache <<\EOF
+cat >>confdefs.h <<\EOF
+#define IO_FAILURE_EMULATION 1
+EOF
+
+ fi
+
+fi;
+
+ac_config_files="$ac_config_files include/Makefile mkreiserfs/Makefile resize_reiserfs/Makefile fsck/Makefile lib/Makefile Makefile reiserfscore/Makefile debugreiserfs/Makefile tune/Makefile"
+cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
-# scripts and configure runs. It is not useful on other systems.
-# If it contains results you don't want to keep, you may remove or edit it.
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
#
-# By default, configure uses ./config.cache as the cache file,
-# creating it if it does not exist already. You can give configure
-# the --cache-file=FILE option to use a different cache file; that is
-# what configure does when it calls configure scripts in
-# subdirectories, so they share the cache.
-# Giving --cache-file=/dev/null disables caching, for debugging configure.
-# config.status only pays attention to the cache file if you give it the
-# --recheck option to rerun configure.
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
#
-EOF
+# `ac_cv_env_foo' variables (set or unset) will be overriden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
# The following way of writing the cache mishandles newlines in values,
# but we know of no workaround that is simple, portable, and efficient.
# So, don't put newlines in cache variables' values.
# Ultrix sh set writes to stderr and can't be redirected directly,
# and sets the high bit in the cache file unless we assign to the vars.
-(set) 2>&1 |
- case `(ac_space=' '; set | grep ac_space) 2>&1` in
- *ac_space=\ *)
- # `set' does not quote correctly, so add quotes (double-quote substitution
- # turns \\\\ into \\, and sed turns \\ into \).
- sed -n \
- -e "s/'/'\\\\''/g" \
- -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
- ;;
- *)
- # `set' quotes correctly as required by POSIX, so do not add quotes.
- sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
- ;;
- esac >> confcache
-if cmp -s $cache_file confcache; then
- :
-else
+{
+ (set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+} |
+ sed '
+ t clear
+ : clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ : end' >>confcache
+if cmp -s $cache_file confcache; then :; else
if test -w $cache_file; then
- echo "updating cache $cache_file"
- cat confcache > $cache_file
+ test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+ cat confcache >$cache_file
else
echo "not updating unwritable cache $cache_file"
fi
fi
rm -f confcache
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
test "x$prefix" = xNONE && prefix=$ac_default_prefix
# Let make expand exec_prefix.
test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-# Any assignment to VPATH causes Sun make to only execute
-# the first set of double-colon rules, so remove it if not needed.
-# If there is a colon in the path, we need to keep it.
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
if test "x$srcdir" = x.; then
- ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[ ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[ ]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:3336: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+ac_cs_invocation="\$0 \$@"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
fi
-trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+# Name of the executable.
+as_me=`echo "$0" |sed 's,.*[\\/],,'`
-# Transform confdefs.h into DEFS.
-# Protect against shell expansion while executing Makefile rules.
-# Protect against Makefile macro expansion.
-cat > conftest.defs <<\EOF
-s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
-s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
-s%\[%\\&%g
-s%\]%\\&%g
-s%\$%$$%g
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+as_executable_p="test -f"
+
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+# NLS nuisances.
+$as_unset LANG || test "${LANG+set}" != set || { LANG=C; export LANG; }
+$as_unset LC_ALL || test "${LC_ALL+set}" != set || { LC_ALL=C; export LC_ALL; }
+$as_unset LC_TIME || test "${LC_TIME+set}" != set || { LC_TIME=C; export LC_TIME; }
+$as_unset LC_CTYPE || test "${LC_CTYPE+set}" != set || { LC_CTYPE=C; export LC_CTYPE; }
+$as_unset LANGUAGE || test "${LANGUAGE+set}" != set || { LANGUAGE=C; export LANGUAGE; }
+$as_unset LC_COLLATE || test "${LC_COLLATE+set}" != set || { LC_COLLATE=C; export LC_COLLATE; }
+$as_unset LC_NUMERIC || test "${LC_NUMERIC+set}" != set || { LC_NUMERIC=C; export LC_NUMERIC; }
+$as_unset LC_MESSAGES || test "${LC_MESSAGES+set}" != set || { LC_MESSAGES=C; export LC_MESSAGES; }
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH || test "${CDPATH+set}" != set || { CDPATH=:; export CDPATH; }
+
+exec 6>&1
+
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+ echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+ echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+ echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+ echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\EOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
EOF
-DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
-rm -f conftest.defs
+cat >>$CONFIG_STATUS <<EOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.52,
+ with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+INSTALL="$INSTALL"
+EOF
-# Without the "./", some shells look in PATH for config.status.
-: ${CONFIG_STATUS=./config.status}
+cat >>$CONFIG_STATUS <<\EOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "x$1" : 'x\([^=]*\)='`
+ ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+ shift
+ set dummy "$ac_option" "$ac_optarg" ${1+"$@"}
+ shift
+ ;;
+ -*);;
+ *) # This is not an option, so the user has probably given explicit
+ # arguments.
+ ac_need_defaults=false;;
+ esac
-echo creating $CONFIG_STATUS
-rm -f $CONFIG_STATUS
-cat > $CONFIG_STATUS <<EOF
-#! /bin/sh
-# Generated automatically by configure.
-# Run this file to recreate the current configuration.
-# This directory was configured as follows,
-# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+ case $1 in
+ # Handling of the options.
+EOF
+cat >>$CONFIG_STATUS <<EOF
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ echo "running $SHELL $0 " $ac_configure_args " --no-create --no-recursion"
+ exec $SHELL $0 $ac_configure_args --no-create --no-recursion ;;
+EOF
+cat >>$CONFIG_STATUS <<\EOF
+ --version | --vers* | -V )
+ echo "$ac_cs_version"; exit 0 ;;
+ --he | --h)
+ # Conflict between --help and --header
+ { { echo "$as_me:3512: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ shift
+ CONFIG_FILES="$CONFIG_FILES $1"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $1"
+ ac_need_defaults=false;;
+
+ # This is an error.
+ -*) { { echo "$as_me:3531: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1" ;;
+
+ esac
+ shift
+done
+
+exec 5>>config.log
+cat >&5 << _ACEOF
+
+## ----------------------- ##
+## Running config.status. ##
+## ----------------------- ##
+
+This file was extended by $as_me 2.52, executed with
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ > $ac_cs_invocation
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+
+_ACEOF
+EOF
+
+cat >>$CONFIG_STATUS <<EOF
#
-# $0 $ac_configure_args
+# INIT-COMMANDS section.
#
-# Compiler output produced by configure, useful for debugging
-# configure, is in ./config.log if it exists.
-ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
-for ac_option
+EOF
+
+cat >>$CONFIG_STATUS <<\EOF
+for ac_config_target in $ac_config_targets
do
- case "\$ac_option" in
- -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
- echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
- exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
- -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
- echo "$CONFIG_STATUS generated by autoconf version 2.13"
- exit 0 ;;
- -help | --help | --hel | --he | --h)
- echo "\$ac_cs_usage"; exit 0 ;;
- *) echo "\$ac_cs_usage"; exit 1 ;;
+ case "$ac_config_target" in
+ # Handling of arguments.
+ "include/Makefile" ) CONFIG_FILES="$CONFIG_FILES include/Makefile" ;;
+ "mkreiserfs/Makefile" ) CONFIG_FILES="$CONFIG_FILES mkreiserfs/Makefile" ;;
+ "resize_reiserfs/Makefile" ) CONFIG_FILES="$CONFIG_FILES resize_reiserfs/Makefile" ;;
+ "fsck/Makefile" ) CONFIG_FILES="$CONFIG_FILES fsck/Makefile" ;;
+ "lib/Makefile" ) CONFIG_FILES="$CONFIG_FILES lib/Makefile" ;;
+ "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "reiserfscore/Makefile" ) CONFIG_FILES="$CONFIG_FILES reiserfscore/Makefile" ;;
+ "debugreiserfs/Makefile" ) CONFIG_FILES="$CONFIG_FILES debugreiserfs/Makefile" ;;
+ "tune/Makefile" ) CONFIG_FILES="$CONFIG_FILES tune/Makefile" ;;
+ "default-1" ) CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
+ "include/config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS include/config.h" ;;
+ *) { { echo "$as_me:3584: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
esac
done
-ac_given_srcdir=$srcdir
-ac_given_INSTALL="$INSTALL"
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+ trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+: ${TMPDIR=/tmp}
+{
+ tmp=`(umask 077 && mktemp -d -q "$TMPDIR/csXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=$TMPDIR/cs$$-$RANDOM
+ (umask 077 && mkdir $tmp)
+} ||
+{
+ echo "$me: cannot create a temporary directory in $TMPDIR" >&2
+ { (exit 1); exit 1; }
+}
-trap 'rm -fr `echo "include/Makefile mkreiserfs/Makefile resize_reiserfs/Makefile fsck/Makefile lib/Makefile Makefile reiserfscore/Makefile debugreiserfs/Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF
-cat >> $CONFIG_STATUS <<EOF
-# Protect against being on the right side of a sed subst in config.status.
-sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
- s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
-$ac_vpsub
-$extrasub
-s%@SHELL@%$SHELL%g
-s%@CFLAGS@%$CFLAGS%g
-s%@CPPFLAGS@%$CPPFLAGS%g
-s%@CXXFLAGS@%$CXXFLAGS%g
-s%@FFLAGS@%$FFLAGS%g
-s%@DEFS@%$DEFS%g
-s%@LDFLAGS@%$LDFLAGS%g
-s%@LIBS@%$LIBS%g
-s%@exec_prefix@%$exec_prefix%g
-s%@prefix@%$prefix%g
-s%@program_transform_name@%$program_transform_name%g
-s%@bindir@%$bindir%g
-s%@sbindir@%$sbindir%g
-s%@libexecdir@%$libexecdir%g
-s%@datadir@%$datadir%g
-s%@sysconfdir@%$sysconfdir%g
-s%@sharedstatedir@%$sharedstatedir%g
-s%@localstatedir@%$localstatedir%g
-s%@libdir@%$libdir%g
-s%@includedir@%$includedir%g
-s%@oldincludedir@%$oldincludedir%g
-s%@infodir@%$infodir%g
-s%@mandir@%$mandir%g
-s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
-s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
-s%@INSTALL_DATA@%$INSTALL_DATA%g
-s%@PACKAGE@%$PACKAGE%g
-s%@VERSION@%$VERSION%g
-s%@ACLOCAL@%$ACLOCAL%g
-s%@AUTOCONF@%$AUTOCONF%g
-s%@AUTOMAKE@%$AUTOMAKE%g
-s%@AUTOHEADER@%$AUTOHEADER%g
-s%@MAKEINFO@%$MAKEINFO%g
-s%@SET_MAKE@%$SET_MAKE%g
-s%@CC@%$CC%g
-s%@RANLIB@%$RANLIB%g
-s%@CPP@%$CPP%g
-s%@LIBOBJS@%$LIBOBJS%g
+cat >>$CONFIG_STATUS <<EOF
+
+#
+# CONFIG_FILES section.
+#
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+ # Protect against being on the right side of a sed subst in config.status.
+ sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+ s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@DEFS@,$DEFS,;t t
+s,@LIBS@,$LIBS,;t t
+s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t
+s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t
+s,@INSTALL_DATA@,$INSTALL_DATA,;t t
+s,@PACKAGE@,$PACKAGE,;t t
+s,@VERSION@,$VERSION,;t t
+s,@ACLOCAL@,$ACLOCAL,;t t
+s,@AUTOCONF@,$AUTOCONF,;t t
+s,@AUTOMAKE@,$AUTOMAKE,;t t
+s,@AUTOHEADER@,$AUTOHEADER,;t t
+s,@MAKEINFO@,$MAKEINFO,;t t
+s,@SET_MAKE@,$SET_MAKE,;t t
+s,@CC@,$CC,;t t
+s,@CFLAGS@,$CFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CC@,$ac_ct_CC,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@RANLIB@,$RANLIB,;t t
+s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t
+s,@CPP@,$CPP,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
CEOF
+
EOF
-cat >> $CONFIG_STATUS <<\EOF
-
-# Split the substitutions into bite-sized pieces for seds with
-# small command number limits, like on Digital OSF/1 and HP-UX.
-ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
-ac_file=1 # Number of current file.
-ac_beg=1 # First line for current file.
-ac_end=$ac_max_sed_cmds # Line after last line for current file.
-ac_more_lines=:
-ac_sed_cmds=""
-while $ac_more_lines; do
- if test $ac_beg -gt 1; then
- sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
- else
- sed "${ac_end}q" conftest.subs > conftest.s$ac_file
- fi
- if test ! -s conftest.s$ac_file; then
- ac_more_lines=false
- rm -f conftest.s$ac_file
- else
- if test -z "$ac_sed_cmds"; then
- ac_sed_cmds="sed -f conftest.s$ac_file"
+ cat >>$CONFIG_STATUS <<\EOF
+ # Split the substitutions into bite-sized pieces for seds with
+ # small command number limits, like on Digital OSF/1 and HP-UX.
+ ac_max_sed_lines=48
+ ac_sed_frag=1 # Number of current file.
+ ac_beg=1 # First line for current file.
+ ac_end=$ac_max_sed_lines # Line after last line for current file.
+ ac_more_lines=:
+ ac_sed_cmds=
+ while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ else
+ sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ fi
+ if test ! -s $tmp/subs.frag; then
+ ac_more_lines=false
else
- ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+ # The purpose of the label and of the branching condition is to
+ # speed up the sed processing (if there are no `@' at all, there
+ # is no need to browse any of the substitutions).
+ # These are the two extra sed commands mentioned above.
+ (echo ':t
+ /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+ fi
+ ac_sed_frag=`expr $ac_sed_frag + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_lines`
fi
- ac_file=`expr $ac_file + 1`
- ac_beg=$ac_end
- ac_end=`expr $ac_end + $ac_max_sed_cmds`
+ done
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
fi
-done
-if test -z "$ac_sed_cmds"; then
- ac_sed_cmds=cat
-fi
-EOF
-
-cat >> $CONFIG_STATUS <<EOF
+fi # test -n "$CONFIG_FILES"
-CONFIG_FILES=\${CONFIG_FILES-"include/Makefile mkreiserfs/Makefile resize_reiserfs/Makefile fsck/Makefile lib/Makefile Makefile reiserfscore/Makefile debugreiserfs/Makefile"}
EOF
-cat >> $CONFIG_STATUS <<\EOF
-for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+cat >>$CONFIG_STATUS <<\EOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
# Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
- case "$ac_file" in
- *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
- ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
- *) ac_file_in="${ac_file}.in" ;;
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
esac
- # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
-
- # Remove last slash and all that follows it. Not all systems have dirname.
- ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+ # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+ ac_dir=`$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
- # The file is in a subdirectory.
- test ! -d "$ac_dir" && mkdir "$ac_dir"
- ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+ { case "$ac_dir" in
+ [\\/]* | ?:[\\/]* ) as_incr_dir=;;
+ *) as_incr_dir=.;;
+esac
+as_dummy="$ac_dir"
+for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do
+ case $as_mkdir_dir in
+ # Skip DOS drivespec
+ ?:) as_incr_dir=$as_mkdir_dir ;;
+ *)
+ as_incr_dir=$as_incr_dir/$as_mkdir_dir
+ test -d "$as_incr_dir" || mkdir "$as_incr_dir"
+ ;;
+ esac
+done; }
+
+ ac_dir_suffix="/`echo $ac_dir|sed 's,^\./,,'`"
# A "../" for each directory in $ac_dir_suffix.
- ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+ ac_dots=`echo "$ac_dir_suffix" | sed 's,/[^/]*,../,g'`
else
ac_dir_suffix= ac_dots=
fi
- case "$ac_given_srcdir" in
- .) srcdir=.
- if test -z "$ac_dots"; then top_srcdir=.
- else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
- /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+ case $srcdir in
+ .) ac_srcdir=.
+ if test -z "$ac_dots"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_dots | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* )
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
*) # Relative path.
- srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
- top_srcdir="$ac_dots$ac_given_srcdir" ;;
+ ac_srcdir=$ac_dots$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_dots$srcdir ;;
esac
- case "$ac_given_INSTALL" in
- [/$]*) INSTALL="$ac_given_INSTALL" ;;
- *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_dots$INSTALL ;;
esac
- echo creating "$ac_file"
- rm -f "$ac_file"
- configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
- case "$ac_file" in
- *Makefile*) ac_comsub="1i\\
-# $configure_input" ;;
- *) ac_comsub= ;;
+ if test x"$ac_file" != x-; then
+ { echo "$as_me:3802: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ rm -f "$ac_file"
+ fi
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated automatically by config.status. */
+ configure_input="Generated automatically from `echo $ac_file_in |
+ sed 's,.*/,,'` by configure."
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:3820: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ echo $f;;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo $f
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo $srcdir/$f
+ else
+ # /dev/null tree
+ { { echo "$as_me:3833: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+EOF
+cat >>$CONFIG_STATUS <<EOF
+ sed "$ac_vpsub
+$extrasub
+EOF
+cat >>$CONFIG_STATUS <<\EOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@INSTALL@,$ac_INSTALL,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+ rm -f $tmp/stdin
+ if test x"$ac_file" != x-; then
+ mv $tmp/out $ac_file
+ else
+ cat $tmp/out
+ rm -f $tmp/out
+ fi
+
+done
+EOF
+cat >>$CONFIG_STATUS <<\EOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='[ ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
esac
- ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
- sed -e "$ac_comsub
-s%@configure_input@%$configure_input%g
-s%@srcdir@%$srcdir%g
-s%@top_srcdir@%$top_srcdir%g
-s%@INSTALL@%$INSTALL%g
-" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
-fi; done
-rm -f conftest.s*
+ test x"$ac_file" != x- && { echo "$as_me:3894: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:3905: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ echo $f;;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo $f
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo $srcdir/$f
+ else
+ # /dev/null tree
+ { { echo "$as_me:3918: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+ # Remove the trailing spaces.
+ sed 's/[ ]*$//' $ac_file_inputs >$tmp/in
EOF
-cat >> $CONFIG_STATUS <<EOF
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h. The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status. Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\EOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[ ]*#[ ]*define[ ][ ]*\(\([^ (][^ (]*\)([^)]*)\)[ ]*\(.*\)$,${ac_dA}\2${ac_dB}\1${ac_dC}\3${ac_dD},gp
+t end
+s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
EOF
-cat >> $CONFIG_STATUS <<\EOF
-
-exit 0
+# If some macros were called several times there might be several times
+# the same #defines, which is useless. Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\EOF
+s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
EOF
-chmod +x $CONFIG_STATUS
-rm -fr confdefs* $ac_clean_files
-test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
-
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo ' if egrep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo ' :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+ # Write a limited-size here document to $tmp/defines.sed.
+ echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#define' lines.
+ echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f $tmp/defines.sed $tmp/in >$tmp/out
+ rm -f $tmp/in
+ mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo ' fi # egrep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo ' # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+ # Write a limited-size here document to $tmp/undefs.sed.
+ echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#undef'
+ echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+ rm -f $tmp/in
+ mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+ rm -f conftest.undefs
+ mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\EOF
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated automatically by config.status. */
+ if test x"$ac_file" = x-; then
+ echo "/* Generated automatically by configure. */" >$tmp/config.h
+ else
+ echo "/* $ac_file. Generated automatically by configure. */" >$tmp/config.h
+ fi
+ cat $tmp/in >>$tmp/config.h
+ rm -f $tmp/in
+ if test x"$ac_file" != x-; then
+ if cmp -s $ac_file $tmp/config.h 2>/dev/null; then
+ { echo "$as_me:4035: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ ac_dir=`$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+ { case "$ac_dir" in
+ [\\/]* | ?:[\\/]* ) as_incr_dir=;;
+ *) as_incr_dir=.;;
+esac
+as_dummy="$ac_dir"
+for as_mkdir_dir in `IFS='/\\'; set X $as_dummy; shift; echo "$@"`; do
+ case $as_mkdir_dir in
+ # Skip DOS drivespec
+ ?:) as_incr_dir=$as_mkdir_dir ;;
+ *)
+ as_incr_dir=$as_incr_dir/$as_mkdir_dir
+ test -d "$as_incr_dir" || mkdir "$as_incr_dir"
+ ;;
+ esac
+done; }
+ fi
+ rm -f $ac_file
+ mv $tmp/config.h $ac_file
+ fi
+ else
+ cat $tmp/config.h
+ rm -f $tmp/config.h
+ fi
+done
+EOF
+cat >>$CONFIG_STATUS <<\EOF
+#
+# CONFIG_COMMANDS section.
+#
+for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue
+ ac_dest=`echo "$ac_file" | sed 's,:.*,,'`
+ ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ case $ac_dest in
+ default-1 ) test -z "$CONFIG_HEADERS" || echo timestamp > include/stamp-h ;;
+ esac
+done
+EOF
+cat >>$CONFIG_STATUS <<\EOF
+{ (exit 0); exit 0; }
+EOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
diff --git a/configure.in b/configure.in
index 476aee4..0e5a3e3 100644
--- a/configure.in
+++ b/configure.in
@@ -1,16 +1,19 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(version.h)
-AM_INIT_AUTOMAKE(reiserfsprogs, 3.x.0j)
+AM_INIT_AUTOMAKE(reiserfsprogs, 3.6.2)
dnl We install in /sbin, the utils are to be available on boot
-AC_PREFIX_DEFAULT(/)
+dnl AC_PREFIX(/)
+
+AM_CONFIG_HEADER(include/config.h)
+
+AC_SUBST(sbindir)
PRESET_CFLAGS=$CFLAGS
AC_PROG_CC
-if test -z $PRESET_CFLAGS; then
-dnl CFLAGS="${RPM_OPT_FLAGS} $CFLAGS -Wall"
- CFLAGS="${RPM_OPT_FLAGS} -g -O2 -Wall"
+if test "x" = "x$PRESET_CFLAGS"; then
+ CFLAGS="${RPM_OPT_FLAGS} $CFLAGS -Wall"
fi
dnl Checks for programs.
@@ -38,11 +41,13 @@ AC_FUNC_STRFTIME
AC_FUNC_VPRINTF
AC_CHECK_FUNCS(strerror strstr strtol)
-AC_OUTPUT(include/Makefile mkreiserfs/Makefile resize_reiserfs/Makefile fsck/Makefile lib/Makefile Makefile reiserfscore/Makefile debugreiserfs/Makefile)
-
-
-
-
-
-
+dnl Never enable this. It is for debugging only
+AC_ARG_ENABLE(io-failure-emulation,
+[ --enable-io-failure-emulation Never use that. It is for debugging only],
+[ if test "$enableval" = "yes" ; then
+ echo -e "\nCarefull! IO failure emulation is ON\n"
+ AC_DEFINE(IO_FAILURE_EMULATION, 1, [gets set when configure --enable-io-failure-emulation])
+ fi
+])
+AC_OUTPUT(include/Makefile mkreiserfs/Makefile resize_reiserfs/Makefile fsck/Makefile lib/Makefile Makefile reiserfscore/Makefile debugreiserfs/Makefile tune/Makefile)
diff --git a/debugreiserfs/Makefile.am b/debugreiserfs/Makefile.am
index a5b1124..8bec80f 100644
--- a/debugreiserfs/Makefile.am
+++ b/debugreiserfs/Makefile.am
@@ -1,10 +1,8 @@
sbin_PROGRAMS = debugreiserfs unpack
-debugreiserfs_SOURCES = debugreiserfs.c pack.c
-unpack_SOURCES = unpack.c debugreiserfs.h
+debugreiserfs_SOURCES = debugreiserfs.c pack.c stat.c corruption.c scan.c recover.c journal.c
+unpack_SOURCES = unpack.c pack.c debugreiserfs.h
man_MANS = debugreiserfs.8
EXTRA_DIST = $(man_MANS)
-LDADD = ../lib/libmisc.a ../reiserfscore/libcore.a
-
-INCLUDES = -I../include
+LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a
diff --git a/debugreiserfs/Makefile.in b/debugreiserfs/Makefile.in
index c73aa68..4c25cb4 100644
--- a/debugreiserfs/Makefile.in
+++ b/debugreiserfs/Makefile.in
@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -62,33 +62,36 @@ MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
+sbindir = @sbindir@
sbin_PROGRAMS = debugreiserfs unpack
-debugreiserfs_SOURCES = debugreiserfs.c pack.c
-unpack_SOURCES = unpack.c debugreiserfs.h
+debugreiserfs_SOURCES = debugreiserfs.c pack.c stat.c corruption.c scan.c recover.c journal.c
+unpack_SOURCES = unpack.c pack.c debugreiserfs.h
man_MANS = debugreiserfs.8
EXTRA_DIST = $(man_MANS)
-LDADD = ../lib/libmisc.a ../reiserfscore/libcore.a
-
-INCLUDES = -I../include
+LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../include/config.h
CONFIG_CLEAN_FILES =
PROGRAMS = $(sbin_PROGRAMS)
-DEFS = @DEFS@ -I. -I$(srcdir)
+DEFS = @DEFS@ -I. -I$(srcdir) -I../include
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
-debugreiserfs_OBJECTS = debugreiserfs.o pack.o
+debugreiserfs_OBJECTS = debugreiserfs.o pack.o stat.o corruption.o \
+scan.o recover.o journal.o
debugreiserfs_LDADD = $(LDADD)
-debugreiserfs_DEPENDENCIES = ../lib/libmisc.a ../reiserfscore/libcore.a
+debugreiserfs_DEPENDENCIES = $(top_srcdir)/lib/libmisc.a \
+$(top_srcdir)/reiserfscore/libcore.a
debugreiserfs_LDFLAGS =
-unpack_OBJECTS = unpack.o
+unpack_OBJECTS = unpack.o pack.o
unpack_LDADD = $(LDADD)
-unpack_DEPENDENCIES = ../lib/libmisc.a ../reiserfscore/libcore.a
+unpack_DEPENDENCIES = $(top_srcdir)/lib/libmisc.a \
+$(top_srcdir)/reiserfscore/libcore.a
unpack_LDFLAGS =
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -247,20 +250,37 @@ distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
- cp -pr $$/$$file $(distdir)/$$file; \
+ cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
+corruption.o: corruption.c debugreiserfs.h ../include/io.h \
+ ../include/misc.h ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h ../include/config.h ../version.h
debugreiserfs.o: debugreiserfs.c debugreiserfs.h ../include/io.h \
- ../include/misc.h ../include/reiserfs_lib.h \
- ../include/reiserfs_fs.h ../version.h
+ ../include/misc.h ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h ../include/config.h ../version.h
+journal.o: journal.c debugreiserfs.h ../include/io.h ../include/misc.h \
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h ../include/config.h ../version.h
pack.o: pack.c debugreiserfs.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h ../version.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h ../include/config.h ../version.h
+recover.o: recover.c debugreiserfs.h ../include/io.h ../include/misc.h \
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h ../include/config.h ../version.h
+scan.o: scan.c debugreiserfs.h ../include/io.h ../include/misc.h \
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h ../include/config.h ../version.h
+stat.o: stat.c debugreiserfs.h ../include/io.h ../include/misc.h \
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h ../include/config.h ../version.h
unpack.o: unpack.c debugreiserfs.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h ../version.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h ../include/config.h ../version.h
info-am:
info: info-am
diff --git a/debugreiserfs/corruption.c b/debugreiserfs/corruption.c
new file mode 100644
index 0000000..a913bad
--- /dev/null
+++ b/debugreiserfs/corruption.c
@@ -0,0 +1,487 @@
+/*
+ * Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
+ */
+
+#include "debugreiserfs.h"
+
+
+static int str2int (char * str, int * res)
+{
+ int val;
+ char * tmp;
+
+ val = (int) strtol (str, &tmp, 0);
+ if (tmp == str)
+ /* could not convert string into a number */
+ return 0;
+ *res = val;
+ return 1;
+}
+
+
+static void edit_journal_params (struct journal_params * jp)
+{
+ char * str;
+ size_t n;
+ int num;
+
+ printf ("Journal parameters:\n");
+ printf ("\tDevice: current: %x: new:", get_jp_journal_dev (jp));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_jp_journal_dev (jp, num);
+
+ printf ("\tFirst block: current: %d: new:",
+ get_jp_journal_1st_block (jp));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_jp_journal_1st_block (jp, num);
+
+ printf ("\tSize: current: %d: new:", get_jp_journal_size (jp));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_jp_journal_size (jp, num);
+
+ printf ("\tMagic number: current: %d: new:", get_jp_journal_magic (jp));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_jp_journal_magic (jp, num);
+
+ printf ("\tMax transaction size: current: %d: new:",
+ get_jp_journal_max_trans_len (jp));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_jp_journal_max_trans_len (jp, num);
+
+ printf ("\tMax batch size: current: %d: new:",
+ get_jp_journal_max_batch (jp));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_jp_journal_max_batch (jp, num);
+
+ printf ("\tMax commit age: current: %d: new:",
+ get_jp_journal_max_commit_age (jp));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_jp_journal_max_commit_age (jp, num);
+}
+
+
+/* this allows to edit all super block fields */
+static void edit_super_block (reiserfs_filsys_t * fs)
+{
+ char * str;
+ size_t n;
+ int num;
+
+
+ str = 0;
+ n = 0;
+
+ /* bs_block_count */
+ printf ("\tBlock count: current: %u: new:",
+ get_sb_block_count (fs->fs_ondisk_sb));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_sb_block_count (fs->fs_ondisk_sb, num);
+
+
+ /* sb_free_blocks */
+ printf ("\tFree block count: current: %u: new:",
+ get_sb_free_blocks (fs->fs_ondisk_sb));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_sb_free_blocks (fs->fs_ondisk_sb, num);
+
+ /* sb_root_block */
+ printf ("\tRoot block: current: %u: new:",
+ get_sb_root_block (fs->fs_ondisk_sb));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_sb_root_block (fs->fs_ondisk_sb, num);
+
+ /* sb_journal */
+ edit_journal_params (sb_jp (fs->fs_ondisk_sb));
+
+ /* sb_blocksize */
+ printf ("\tBlocksize: current: %u: new:",
+ get_sb_block_size (fs->fs_ondisk_sb));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_sb_block_size (fs->fs_ondisk_sb, num);
+
+ /* sb_oid_maxsize */
+ printf ("\tMax objectid size: current: %u: new:",
+ get_sb_oid_maxsize (fs->fs_ondisk_sb));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_sb_oid_maxsize (fs->fs_ondisk_sb, num);
+
+ /* sb_oid_cursize */
+ printf ("\tCur objectid size: current: %u: new:",
+ get_sb_oid_cursize (fs->fs_ondisk_sb));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_sb_oid_cursize (fs->fs_ondisk_sb, num);
+
+ /* sb_state */
+ printf ("\tUmount state: current: %u: new:",
+ get_sb_umount_state (fs->fs_ondisk_sb));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_sb_umount_state (fs->fs_ondisk_sb, num);
+
+ /* char s_magic [10]; */
+ printf ("\tMagic: current: \"%s\": new:", fs->fs_ondisk_sb->s_v1.s_magic);
+ getline (&str, &n, stdin);
+ if (strcmp (str, "\n"))
+ strncpy (fs->fs_ondisk_sb->s_v1.s_magic, str, n > 10 ? 10 : n);
+
+ /* __u16 sb_fsck_state; */
+ printf ("\tFielsystem state: current: %u: new:", get_sb_fs_state (fs->fs_ondisk_sb));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_sb_fs_state (fs->fs_ondisk_sb, num);
+
+ /* __u32 sb_hash_function_code; */
+ printf ("\tHash code: current: %u: new (tea %d, r5 %d, rupasov %d):",
+ get_sb_hash_code (fs->fs_ondisk_sb), TEA_HASH, R5_HASH, YURA_HASH);
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_sb_hash_code (fs->fs_ondisk_sb, num);
+
+ /* __u16 sb_tree_height; */
+ printf ("\tTree height: current: %u: new:",
+ get_sb_tree_height (fs->fs_ondisk_sb));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_sb_tree_height (fs->fs_ondisk_sb, num);
+
+ /* __u16 sb_bmap_nr; */
+ printf ("\tNumber of bitmaps: current: %u: new:",
+ get_sb_bmap_nr (fs->fs_ondisk_sb));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_sb_bmap_nr (fs->fs_ondisk_sb, num);
+
+ /* __u16 sb_version; */
+ printf ("\tFilesystem format: current: %u: new:",
+ le16_to_cpu (fs->fs_ondisk_sb->s_v1.sb_version));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_sb_version (fs->fs_ondisk_sb, num);
+
+ /* __u16 sb_reserved_for_journal; */
+ printf ("\tSpace reserved for journal: current: %u: new:",
+ get_sb_reserved_for_journal (fs->fs_ondisk_sb));
+ getline (&str, &n, stdin);
+ if (str2int (str, &num))
+ set_sb_reserved_for_journal (fs->fs_ondisk_sb, num);
+
+
+ print_block (stdout, fs, fs->fs_super_bh);
+ if (user_confirmed (stderr, "Is this ok ? [N/Yes]: ", "Yes\n")) {
+ mark_buffer_dirty (fs->fs_super_bh);
+ bwrite (fs->fs_super_bh);
+ }
+}
+
+
+static void corrupt_clobber_hash (char * name, struct item_head * ih,
+ struct reiserfs_de_head * deh)
+{
+ printf ("\tCorrupting deh_offset of entry \"%s\" of [%u %u]\n", name,
+ get_key_dirid (&ih->ih_key), get_key_objectid (&ih->ih_key));
+ set_deh_offset (deh, 700);
+}
+
+
+/* this reads list of desired corruptions from stdin and perform the
+ corruptions. Format of that list:
+ A hash_code
+ C name objectid - 'C'ut entry 'name' from directory item with 'objectid'
+ H name objectid - clobber 'H'hash of entry 'name' of directory 'objectid'
+ I item_num pos_in_item make pos_in_item-th slot of indirect item to point out of device
+ O item_num - destroy item 'O'rder - make 'item_num'-th to have key bigger than 'item_num' + 1-th item
+ D item_num - 'D'elete item_num-th item
+ S item_num value - change file size (item_num-th item must be stat data)
+ F item_num value - change sd_first_direct_byte of stat data
+ J item_num objectid
+ E name objectid new - change entry's deh_objectid to new
+ P - print the block
+*/
+void do_corrupt_one_block (reiserfs_filsys_t * fs)
+{
+ struct buffer_head * bh;
+ int i, j;
+ struct item_head * ih;
+ int item_num;
+ char * line = 0;
+ size_t n = 0;
+ char code, name [100];
+ __u32 objectid, new_objectid;
+ int value;
+ int hash_code;
+ int pos_in_item;
+ unsigned long block;
+ int type, format;
+
+
+ block = certain_block (fs);
+ if (block == fs->fs_super_bh->b_blocknr) {
+ edit_super_block (fs);
+ return;
+ }
+
+ if (!fs->fs_bitmap2) {
+ struct buffer_head * bm_bh;
+ unsigned long bm_block;
+
+ if (spread_bitmaps (fs))
+ bm_block = ( block / (fs->fs_blocksize * 8) ) ?
+ (block / (fs->fs_blocksize * 8)) * (fs->fs_blocksize * 8) :
+ fs->fs_super_bh->b_blocknr + 1;
+ else
+ bm_block = fs->fs_super_bh->b_blocknr + 1 + (block / (fs->fs_blocksize * 8));
+
+ bm_bh = bread (fs->fs_dev, bm_block, fs->fs_blocksize);
+ if (bm_bh) {
+ if ( test_bit((block % (fs->fs_blocksize * 8)), bm_bh->b_data) )
+ fprintf (stderr, "%lu is used in ondisk bitmap\n", block);
+ else
+ fprintf (stderr, "%lu is free in ondisk bitmap\n", block);
+
+ brelse (bm_bh);
+ }
+ } else {
+ if (reiserfs_bitmap_test_bit (fs->fs_bitmap2, block))
+ fprintf (stderr, "%lu is used in ondisk bitmap\n", block);
+ else
+ fprintf (stderr, "%lu is free in ondisk bitmap\n", block);
+ }
+
+ bh = bread (fs->fs_dev, block, fs->fs_blocksize);
+ if (!bh) {
+ printf ("corrupt_one_block: bread fialed\n");
+ return;
+ }
+
+ if (who_is_this (bh->b_data, fs->fs_blocksize) != THE_LEAF) {
+ printf ("Can not corrupt not a leaf node\n");
+ brelse (bh);
+ return;
+ }
+
+ printf ("Corrupting block %lu..\n", bh->b_blocknr);
+
+ while (getline (&line, &n, stdin) != -1) {
+ switch (line[0]) {
+ case '#':
+ case '\n':
+ continue;
+ case '?':
+ printf ("A hash_code - reset hAsh code in super block\n"
+ "T item_num type (0, 1, 2, 3) format (0, 1)\n"
+ "C name objectid - Cut entry 'name' from directory item with 'objectid'\n"
+ "H name objectid - clobber Hash of entry 'name' of directory 'objectid'\n"
+ "I item_num pos_in_item make pos_in_tem-th slot of Indirect item to point out of device\n"
+ "O item_num - destroy item Order - make 'item_num'-th to have key bigger than 'item_num' + 1-th item\n"
+ "D item_num - Delete item_num-th item\n"
+ "S item_num value - change file Size (item_num-th item must be stat data)\n"
+ "F item_num value - change sd_First_direct_byte of stat data\n"
+ "J item_num objectid - set 'obJectid' of 'item_num'-th item\n"
+ "E name objectid objectid - set deh_objectid of an entry to objectid\n");
+
+ continue;
+
+ case 'P':
+ print_block (stderr, fs, bh, 3, -1, -1);
+ break;
+
+ case 'A':
+ /* corrupt hash record in super block */
+ if (sscanf (line, "%c %d\n", &code, &hash_code) != 2) {
+ printf ("Wrong format \'%c\'\n", line [0]);
+ continue;
+ }
+ break;
+
+ case 'C': /* cut entry */
+ case 'H': /* make hash wrong */
+ if (sscanf (line, "%c %s %u\n", &code, name, &objectid) != 3) {
+ printf ("Wrong format \'%c\'\n", line [0]);
+ continue;
+ }
+ break;
+
+ case 'T': /* set type of item */
+ if (sscanf (line, "%c %d %d %d\n", &code, &item_num, &type, &format) != 4) {
+ printf ("Wrong format \'%c\'\n", line [0]);
+ continue;
+ }
+ break;
+
+ case 'J': /* set objectid : used to simulate objectid sharing problem */
+ if (sscanf (line, "%c %d %d\n", &code, &item_num, &objectid) != 3) {
+ printf ("Wrong format \'%c\'\n", line [0]);
+ continue;
+ }
+ break;
+
+ case 'E': /* set objectid : used to simulate objectid sharing problem */
+ if (sscanf (line, "%c %s %u %d\n", &code, name, &objectid, &new_objectid) != 4) {
+ printf ("Wrong format \'%c\'\n", line [0]);
+ continue;
+ }
+ break;
+
+ case 'I': /* break unformatted node pointer */
+ if (sscanf (line, "%c %d %d\n", &code, &item_num, &pos_in_item) != 3) {
+ printf ("Wrong format \'%c\'\n", line [0]);
+ continue;
+ }
+ break;
+
+ case 'D': /* delete item */
+ case 'O': /* make item out of order */
+ if (sscanf (line, "%c %d\n", &code, &item_num) != 2) {
+ printf ("Wrong format \'%c\'\n", line [0]);
+ continue;
+ }
+ break;
+
+ case 'S': /* corrupt st_size */
+ case 'F': /* st_first_direct_byte */
+ if (sscanf (line, "%c %d %d\n", &code, &item_num, &value) != 3) {
+ printf ("Wrong format \'%c\'\n", line [0]);
+ continue;
+ }
+ break;
+ }
+
+ if (code == 'A') {
+ reiserfs_warning (stderr, "Changing %s to %s\n", code2name (get_sb_hash_code (fs->fs_ondisk_sb)),
+ code2name (hash_code));
+ set_sb_hash_code (fs->fs_ondisk_sb, hash_code);
+ mark_buffer_dirty (fs->fs_super_bh);
+ continue;
+ }
+
+ ih = B_N_PITEM_HEAD (bh, 0);
+ for (i = 0; i < get_blkh_nr_items (B_BLK_HEAD (bh)); i ++, ih ++) {
+ struct reiserfs_de_head * deh;
+
+ if (code == 'T' && i == item_num) {
+ set_ih_key_format (ih, format);
+ set_type (format, &ih->ih_key, type);
+ mark_buffer_dirty (bh);
+ goto cont;
+ }
+
+ if (code == 'I' && i == item_num) {
+ if (!is_indirect_ih (ih) || pos_in_item >= I_UNFM_NUM (ih)) {
+ reiserfs_warning (stderr, "Not an indirect item or there is "
+ "not so many unfm ptrs in it\n");
+ continue;
+ }
+ * ((__u32 *)B_I_PITEM (bh, ih) + pos_in_item) = get_sb_block_count (fs->fs_ondisk_sb) + 100;
+ mark_buffer_dirty (bh);
+ goto cont;
+ }
+
+ if (code == 'J' && i == item_num) {
+ set_key_objectid (&ih->ih_key, objectid);
+ mark_buffer_dirty (bh);
+ goto cont;
+ }
+
+ if (code == 'S' && i == item_num) {
+ /* fixme: old stat data only */
+ struct stat_data_v1 * sd;
+
+ sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih);
+ reiserfs_warning (stderr, "Changing sd_size of %k from %d to %d\n",
+ &ih->ih_key, sd_v1_size(sd), value);
+ set_sd_v1_size( sd, value );
+ mark_buffer_dirty (bh);
+ goto cont;
+ }
+
+ if (code == 'F' && i == item_num) {
+ /* fixme: old stat data only */
+ struct stat_data_v1 * sd;
+
+ sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih);
+ reiserfs_warning (stderr, "Changing sd_first_direct_byte of %k from %d to %d\n",
+ &ih->ih_key, sd_v1_first_direct_byte(sd), value);
+ set_sd_v1_first_direct_byte( sd, value );
+ mark_buffer_dirty (bh);
+ goto cont;
+ }
+
+ if (code == 'D' && i == item_num) {
+ delete_item (fs, bh, item_num);
+ mark_buffer_dirty (bh);
+ goto cont;
+ }
+
+ if (code == 'O' && i == item_num) {
+ /* destroy item order */
+ struct key * key;
+ if (i == get_blkh_nr_items (B_BLK_HEAD (bh)) - 1) {
+ printf ("can not destroy order\n");
+ continue;
+ }
+ key = &(ih + 1)->ih_key;
+ set_key_dirid (&ih->ih_key, get_key_dirid (key) + 1);
+ mark_buffer_dirty (bh);
+ }
+
+ if (get_key_objectid (&ih->ih_key) != objectid || !is_direntry_ih (ih))
+ continue;
+
+ deh = B_I_DEH (bh, ih);
+
+ for (j = 0; j < get_ih_entry_count (ih); j ++, deh ++) {
+ /* look for proper entry */
+ if (name_in_entry_length (ih, deh, j) != strlen (name) ||
+ strncmp (name, name_in_entry (deh, j), strlen (name)))
+ continue;
+
+ /* ok, required entry found, make a corruption */
+ switch (code) {
+ case 'C': /* cut entry */
+ cut_entry (fs, bh, i, j, 1);
+ mark_buffer_dirty (bh);
+
+ if (!B_IS_IN_TREE (bh)) {
+ printf ("NOTE: block is deleted from the tree\n");
+ exit (0);
+ }
+ goto cont;
+ break;
+
+ case 'H': /* clobber hash */
+ corrupt_clobber_hash (name, ih, deh);
+ goto cont;
+ break;
+
+ case 'E': /* change entry's deh_objectid */
+ set_deh_objectid (deh, new_objectid);
+ break;
+
+ default:
+ printf ("Unknown command found\n");
+ }
+ mark_buffer_dirty (bh);
+ }
+ }
+ cont:
+ }
+ free (line);
+ printf ("Done\n");
+ brelse (bh);
+ return;
+}
+
+
diff --git a/debugreiserfs/debugreiserfs.8 b/debugreiserfs/debugreiserfs.8
index 9de473f..78541f7 100644
--- a/debugreiserfs/debugreiserfs.8
+++ b/debugreiserfs/debugreiserfs.8
@@ -1,20 +1,22 @@
.\" -*- nroff -*-
-.\" Copyright 1996-2001 Hans Reiser.
+.\" Copyright 1996-2002 Hans Reiser.
.\"
-.TH DEBUGREISERFS 8 "March 2001" "Reiserfsprogs 3.x.0j"
+.TH DEBUGREISERFS 8 "January 2002" "Reiserfsprogs 3.6.2"
.SH NAME
debugreiserfs
.SH SYNOPSIS
.B debugreiserfs
[
-.B -jdcmos
+.B -dJmoqpS
] [
-.B -b \fIblocknumber
+.B -j \fIdevice
] [
-.B -p \fIfilename.bmp
-] [
-.B -P \fIfilename.bmp
+.B -B \fIblocknumber
]
+
+.\" ] [
+.\" .B -s
+.\" ] [
.I device
.SH DESCRIPTION
It helps sometimes to solve problems with reiserfs filesystems. Being
@@ -26,43 +28,54 @@ is the special file corresponding to the device (e.g /dev/hdXX for
IDE disk partition or /dev/sdXX for SCSI disk partition).
.SH OPTIONS
.TP
-\fB-j
-print contents of journal
+\fB-j\fR \fIdevice\fR
+print contents of journal. Also with the option -p it allows to pack
+journal into archive with other metadata
.TP
-\fB-d
-print formatted nodes of the filesystem
+\fB-J\fR
+print journal header.
.TP
-\fB-c
-print contents of direct items
+.B -d
+print formatted nodes of the filesystem
.TP
-\fB-m
+.B -m
print contents of bitmap (not very useful)
.TP
-\fB-o
+.B -o
print objectid map (not very useful)
.TP
-\fB-s
-scans the partition and prints a line when any kind of reiserfs formatted nodes found
-.TP
-\fB-b \fIblocknumber
+\fB-1\fR \fIblocknumber\fR
print specified block of the filesystem
.TP
-\fB-p \fIfilename
-\fB-P \fIfilename
-
-Makes \fBdebugreiserfs\fR to find filesystem metadata
-These exist to help reiserfsck debugging. If reiserfsck fails -
-you may extract filesystem metadata with \fBdebugreiserfs\fR -p filename /dev/xxx |gzip
--c > xxx.gz. We download that data and make the filesystem similar
-to your with gunzip -c xxx.gz | unpack /dev/xxx (unpack is included
-into reiserfsprogs package). This usually allows to reproduce and
-debug the problem quickly. When data file is not too large.
--P will cause \fBdebugreiserfs\fR to find and pack metadata from all the device whereas with -p it will only go through blocks marked used in filesystem bitmaps
-
+.\" \fB-s
+.\" scans the partition and prints a line when any kind of reiserfs
+.\" formatted nodes found. Can be used to find specific key in the filesystem.
+.\" .TP
+.B -p
+Makes \fBdebugreiserfs\fR to find filesystem metadata This option
+exists to help reiserfsck debugging. If reiserfsck fails - you may
+extract filesystem metadata with \fBdebugreiserfs\fR -p
+/dev/xxx |gzip -c > xxx.gz. We download that data and make the
+filesystem similar to your with gunzip -c xxx.gz | unpack /dev/xxx
+(unpack is included into reiserfsprogs package). This usually allows
+to reproduce and debug the problem quickly. When data file is not too
+large.
+.TP
+.B -S
+When -S is not specified -p
+.\" and -s
+deals with blocks marked used in the
+filesystem bitmap. With this option set they will work with whole
+device.
+.TP
+.B -q
+Suppress showing speed of progress when
+.\" -s or
+-p is in use
.SH AUTHOR
This version of \fBdebugreiserfs\fR has been written by Hans Reiser <reiser@idiom.com>.
.SH BUGS
-There are probably few of them. Please, report bugs to Hans Reiser <reiser@idiom.com>.
+There are probably few of them. Please, report bugs to ReiserFS mail-list <reiserfs-list@namesys.com>.
.SH SEE ALSO
.BR reiserfsck (8),
.BR mkreiserfs (8)
diff --git a/debugreiserfs/debugreiserfs.c b/debugreiserfs/debugreiserfs.c
index ad6abf8..d22e3ea 100644
--- a/debugreiserfs/debugreiserfs.c
+++ b/debugreiserfs/debugreiserfs.c
@@ -1,24 +1,46 @@
/*
- * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
+ * Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
*/
+
#include "debugreiserfs.h"
-reiserfs_filsys_t fs;
-#define print_usage_and_exit() die ("Usage: %s [-b block-to-print][-idc] device\n\
--i Causes to print all items of a leaf\n\
--d content of directory items\n\
--c content of direct items\n\
--m bitmap blocks\n\
--t\n\
--C\n\
--p\n\
--s \n\
--n scan for name\n\
--p [filename]\n\
--P [filename]\n\
-..etc\n", argv[0]);
+reiserfs_filsys_t * fs;
+
+
+#define print_usage_and_exit() {\
+fprintf (stderr, "Usage: %s [options] device\n\n\
+Options:\n\
+ -d\t\tprint blocks details\n\
+ -m\t\tprint bitmap blocks\n\
+ -o\t\tprint objectid map\n\n\
+ -J\t\tprint journal header\n\
+ -j journal_device\n\t\tprint journal\n\
+ -p\t\tsend filesystem metadata to stdout\n\
+ -S\t\tgo through whole device when running -p\n\
+ -1 block\tblock to print\n\
+ -q\t\tno speed info (for -p, -s and -n)\n\n", argv[0]);\
+ exit (16);\
+}
+
+/*
+ -B file\textract list of badblocks\n\
+
+ Undocumented options:
+ -a map_file\n\tstore to the file the map of file. Is used with -n, -N, -r\n
+ -S\t\tgo through whole device when running -p, -s or -n\n\
+ -U\t\tgo through unused blocks only when running -p, -s or -n\n\
+ -D\t\tprint blocks details scanning the device, not the tree as -d does\n\
+ -b bitmap_file\n\t\trunning -p, -s or -n read blocks marked in this bitmap only\n\
+ -n\tscan device for specific name in reiserfs directories\n\
+ -N\tscan tree for specific name in reiserfs directories\n\
+ -s\tscan device either for specific key or for any metadata\n\
+ -C\tallow to change reiserfs metadata\n\
+ -r\tprint map file content.\n\
+ -J\tsearch block numbers in the journal\n\
+ -t\tstat the device\n\
+*/
#if 1
@@ -32,475 +54,136 @@ struct reiserfs_fsstat {
#endif
-int mode = DO_DUMP;
-
-/*
- * options
- */
-int opt_print_regular_file_content = 0;/* -c */
-int opt_print_details = 0; /* -d */
-int opt_print_leaf_items = 0; /* -i */
-int opt_print_objectid_map = 0; /* -o */
-int opt_print_block_map = 0; /* -m */
-int opt_print_journal; /* -j */
-
-/* when you want print one block specify -b # */
-int opt_block_to_print = -1;
-
-/* when you want to corrupt block specify -C # */
-int opt_block_to_corrupt = -1;
-
-int opt_pack = 0;
-int opt_quiet = 0;
-
-int print_mode (void)
-{
- int mode = 0;
-
- if (opt_print_leaf_items == 1)
- mode |= PRINT_LEAF_ITEMS;
- if (opt_print_details == 1)
- mode |= (PRINT_LEAF_ITEMS | PRINT_ITEM_DETAILS);
- if (opt_print_regular_file_content == 1)
- mode |= (PRINT_LEAF_ITEMS | PRINT_DIRECT_ITEMS);
- return mode;
-}
-
-
-static void print_disk_tree (reiserfs_filsys_t fs, int block_nr)
+static void print_disk_tree (reiserfs_filsys_t * fs, unsigned long block_nr)
{
struct buffer_head * bh;
+ static int level = -1;
- bh = bread (fs->s_dev, block_nr, fs->s_blocksize);
+ if (level == -1)
+ level = get_sb_tree_height (fs->fs_ondisk_sb);
+
+ bh = bread (fs->fs_dev, block_nr, fs->fs_blocksize);
if (!bh) {
- die ("Could not read block %d\n", block_nr);
+ die ("Could not read block %lu\n", block_nr);
+ }
+ level --;
+
+ if (level < 1)
+ die ("level too small");
+
+ if (level != get_blkh_level (B_BLK_HEAD (bh))) {
+ printf ("%d expected, %d found in %lu\n", level, get_blkh_level (B_BLK_HEAD (bh)),
+ bh->b_blocknr);
}
+
if (is_internal_node (bh)) {
int i;
struct disk_child * dc;
g_stat_info.nr_internals ++;
- print_block (stdout, fs, bh, print_mode (), -1, -1);
+ print_block (stdout, fs, bh, data (fs)->options & PRINT_TREE_DETAILS, -1, -1);
dc = B_N_CHILD (bh, 0);
for (i = 0; i <= B_NR_ITEMS (bh); i ++, dc ++)
- print_disk_tree (fs, dc->dc_block_number);
+ print_disk_tree (fs, get_dc_child_blocknr (dc));
} else if (is_leaf_node (bh)) {
g_stat_info.nr_leaves ++;
- print_block (stdout, fs, bh, print_mode (), -1, -1);
+ print_block (stdout, fs, bh, data (fs)->options & PRINT_TREE_DETAILS, -1, -1);
} else {
- print_block (stdout, fs, bh, print_mode (), -1, -1);
- die ("print_disk_tree: bad block type");
+ print_block (stdout, fs, bh, data (fs)->options & PRINT_TREE_DETAILS, -1, -1);
+ reiserfs_warning (stdout, "print_disk_tree: bad block type (%b)\n", bh);
}
brelse (bh);
+ level ++;
}
-
-
-void pack_one_block (reiserfs_filsys_t fs, unsigned long block);
-static void print_one_block (reiserfs_filsys_t fs, int block)
+static void print_disk_blocks (reiserfs_filsys_t * fs)
{
+ int j;
+ unsigned long done = 0, total;
struct buffer_head * bh;
-
- if (test_bit (block % (fs->s_blocksize * 8),
- SB_AP_BITMAP (fs)[block / (fs->s_blocksize * 8)]->b_data))
- fprintf (stderr, "%d is used in true bitmap\n", block);
- else
- fprintf (stderr, "%d is free in true bitmap\n", block);
-
- bh = bread (fs->s_dev, block, fs->s_blocksize);
- if (!bh) {
- printf ("print_one_block: bread fialed\n");
- return;
- }
- if (opt_pack) {
- pack_one_block (fs, bh->b_blocknr);
- brelse (bh);
- return;
- }
+ total = reiserfs_bitmap_ones (input_bitmap(fs));
- if (who_is_this (bh->b_data, fs->s_blocksize) != THE_UNKNOWN)
- print_block (stdout, fs, bh, PRINT_LEAF_ITEMS | PRINT_ITEM_DETAILS |
- (opt_print_regular_file_content == 1 ? PRINT_DIRECT_ITEMS : 0), -1, -1);
- else
- printf ("Looks like unformatted\n");
- brelse (bh);
- return;
-}
+ for (j = 0; j < get_sb_block_count (fs->fs_ondisk_sb); j ++) {
+ if (!reiserfs_bitmap_test_bit (input_bitmap (fs), j))
+ continue;
+
+ print_how_far (stderr, &done, total, 1, be_quiet (fs));
+ bh = bread (fs->fs_dev, j, fs->fs_blocksize);
+ if (!bh) {
+ reiserfs_warning (stderr, "could not read block %lu\n", j);
+ continue;
+ }
-static void corrupt_clobber_hash (char * name, struct item_head * ih,
- struct reiserfs_de_head * deh)
-{
- printf ("\tCorrupting deh_offset of entry \"%s\" of [%u %u]\n", name,
- ih->ih_key.k_dir_id, ih->ih_key.k_objectid);
- deh->deh_offset = 700;
+ if (who_is_this (bh->b_data, bh->b_size) != THE_UNKNOWN)
+ print_block (stdout, fs, bh, PRINT_TREE_DETAILS | PRINT_DIRECT_ITEMS, -1, -1);
+ if (is_internal_node (bh))
+ g_stat_info.nr_internals ++;
+ else if (is_leaf_node (bh))
+ g_stat_info.nr_leaves ++;
+
+ brelse (bh);
+ }
+ fprintf (stderr, "\n");
}
-/* this reads list of desired corruptions from stdin and perform the
- corruptions. Format of that list:
- A hash_code
- C name objectid - 'C'ut entry 'name' from directory item with 'objectid'
- H name objectid - clobber 'H'hash of entry 'name' of directory 'objectid'
- I item_num pos_in_item make pos_in_item-th slot of indirect item to point out of device
- O item_num - destroy item 'O'rder - make 'item_num'-th to have key bigger than 'item_num' + 1-th item
- D item_num - 'D'elete item_num-th item
- S item_num value - change file size (item_num-th item must be stat data)
- F item_num value - change sd_first_direct_byte of stat data
- J item_num objectid
- E name objectid new - change entry's deh_objectid to new
- P - print the block
-*/
-static void do_corrupt_one_block (reiserfs_filsys_t fs, int block)
+void pack_one_block (reiserfs_filsys_t * fs, unsigned long block);
+static void print_one_block (reiserfs_filsys_t * fs, unsigned long block)
{
struct buffer_head * bh;
- int i, j;
- struct item_head * ih;
- int item_num;
- char * line = 0;
- int n = 0;
- char code, name [100];
- __u32 objectid, new_objectid;
- int value;
- int hash_code;
- int pos_in_item;
-
- if (test_bit (block % (fs->s_blocksize * 8),
- SB_AP_BITMAP (fs)[block / (fs->s_blocksize * 8)]->b_data))
- fprintf (stderr, "%d is used in true bitmap\n", block);
- else
- fprintf (stderr, "%d is free in true bitmap\n", block);
- bh = bread (fs->s_dev, block, fs->s_blocksize);
+ if (!fs->fs_bitmap2) {
+ struct buffer_head * bm_bh;
+ unsigned long bm_block;
+
+ if (spread_bitmaps (fs))
+ bm_block = ( block / (fs->fs_blocksize * 8) ) ?
+ (block / (fs->fs_blocksize * 8)) * (fs->fs_blocksize * 8) :
+ fs->fs_super_bh->b_blocknr + 1;
+ else
+ bm_block = fs->fs_super_bh->b_blocknr + 1 + (block / (fs->fs_blocksize * 8));
+
+ bm_bh = bread (fs->fs_dev, bm_block, fs->fs_blocksize);
+ if (bm_bh) {
+ if ( test_bit((block % (fs->fs_blocksize * 8)), bm_bh->b_data) )
+ fprintf (stderr, "%lu is used in ondisk bitmap\n", block);
+ else
+ fprintf (stderr, "%lu is free in ondisk bitmap\n", block);
+
+ brelse (bm_bh);
+ }
+ } else {
+ if (reiserfs_bitmap_test_bit (fs->fs_bitmap2, block))
+ fprintf (stderr, "%lu is used in ondisk bitmap\n", block);
+ else
+ fprintf (stderr, "%lu is free in ondisk bitmap\n", block);
+ }
+
+ bh = bread (fs->fs_dev, block, fs->fs_blocksize);
if (!bh) {
- printf ("corrupt_one_block: bread fialed\n");
+ printf ("print_one_block: bread failed\n");
return;
}
- if (who_is_this (bh->b_data, fs->s_blocksize) != THE_LEAF) {
- printf ("Can not corrupt not a leaf node\n");
+ if (debug_mode (fs) == DO_PACK) {
+ pack_one_block (fs, bh->b_blocknr);
brelse (bh);
return;
}
- printf ("Corrupting block %lu..\n", bh->b_blocknr);
-
- while (getline (&line, &n, stdin) != -1) {
- switch (line[0]) {
- case '#':
- case '\n':
- continue;
- case '?':
- printf ("A hash_code - reset hAsh code in super block\n"
- "C name objectid - Cut entry 'name' from directory item with 'objectid'\n"
- "H name objectid - clobber Hash of entry 'name' of directory 'objectid'\n"
- "I item_num pos_in_item make pos_in_tem-th slot of Indirect item to point out of device\n"
- "O item_num - destroy item Order - make 'item_num'-th to have key bigger than 'item_num' + 1-th item\n"
- "D item_num - Delete item_num-th item\n"
- "S item_num value - change file Size (item_num-th item must be stat data)\n"
- "F item_num value - change sd_First_direct_byte of stat data\n"
- "J item_num objectid - set 'obJectid' of 'item_num'-th item\n"
- "E name objectid objectid - set deh_objectid of an entry to objectid\n");
-
- continue;
-
- case 'P':
- print_block (stderr, fs, bh, 3, -1, -1);
- break;
-
- case 'A':
- /* corrupt hash record in super block */
- if (sscanf (line, "%c %d\n", &code, &hash_code) != 2) {
- printf ("Wrong format \'%c\'\n", line [0]);
- continue;
- }
- break;
-
- case 'C': /* cut entry */
- case 'H': /* make hash wrong */
- if (sscanf (line, "%c %s %u\n", &code, name, &objectid) != 3) {
- printf ("Wrong format \'%c\'\n", line [0]);
- continue;
- }
- break;
-
- case 'J': /* set objectid : used to simulate objectid sharing problem */
- if (sscanf (line, "%c %d %d\n", &code, &item_num, &objectid) != 3) {
- printf ("Wrong format \'%c\'\n", line [0]);
- continue;
- }
- break;
-
- case 'E': /* set objectid : used to simulate objectid sharing problem */
- if (sscanf (line, "%c %s %u %d\n", &code, name, &objectid, &new_objectid) != 4) {
- printf ("Wrong format \'%c\'\n", line [0]);
- continue;
- }
- break;
-
- case 'I': /* break unformatted node pointer */
- if (sscanf (line, "%c %d %d\n", &code, &item_num, &pos_in_item) != 3) {
- printf ("Wrong format \'%c\'\n", line [0]);
- continue;
- }
- break;
-
- case 'D': /* delete item */
- case 'O': /* make item out of order */
- if (sscanf (line, "%c %d\n", &code, &item_num) != 2) {
- printf ("Wrong format \'%c\'\n", line [0]);
- continue;
- }
- break;
-
- case 'S': /* corrupt st_size */
- case 'F': /* st_first_direct_byte */
- if (sscanf (line, "%c %d %d\n", &code, &item_num, &value) != 3) {
- printf ("Wrong format \'%c\'\n", line [0]);
- continue;
- }
- break;
- }
-
- if (code == 'A') {
- reiserfs_warning (stderr, "Changing %s to %s\n", code2name (rs_hash (fs->s_rs)),
- code2name (hash_code));
- set_hash (fs->s_rs, hash_code);
- mark_buffer_dirty (fs->s_sbh);
- continue;
- }
-
- ih = B_N_PITEM_HEAD (bh, 0);
- for (i = 0; i < node_item_number (bh); i ++, ih ++) {
- struct reiserfs_de_head * deh;
-
- if (code == 'I' && i == item_num) {
- if (!is_indirect_ih (ih) || pos_in_item >= I_UNFM_NUM (ih)) {
- reiserfs_warning (stderr, "Not an indirect item or there is "
- "not so many unfm ptrs in it\n");
- continue;
- }
- * ((__u32 *)B_I_PITEM (bh, ih) + pos_in_item) = SB_BLOCK_COUNT(fs) + 100;
- mark_buffer_dirty (bh);
- goto cont;
- }
-
- if (code == 'J' && i == item_num) {
- ih->ih_key.k_objectid = objectid;
- mark_buffer_dirty (bh);
- goto cont;
- }
-
- if (code == 'S' && i == item_num) {
- /* fixme: old stat data only */
- struct stat_data_v1 * sd;
-
- sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih);
- reiserfs_warning (stderr, "Changing sd_size of %k from %d to %d\n",
- &ih->ih_key, sd->sd_size, value);
- sd->sd_size = value;
- mark_buffer_dirty (bh);
- goto cont;
- }
-
- if (code == 'F' && i == item_num) {
- /* fixme: old stat data only */
- struct stat_data_v1 * sd;
-
- sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih);
- reiserfs_warning (stderr, "Changing sd_first_direct_byte of %k from %d to %d\n",
- &ih->ih_key, sd->sd_first_direct_byte, value);
- sd->sd_first_direct_byte = value;
- mark_buffer_dirty (bh);
- goto cont;
- }
-
- if (code == 'D' && i == item_num) {
- delete_item (fs, bh, item_num);
- mark_buffer_dirty (bh);
- goto cont;
- }
-
- if (code == 'O' && i == item_num) {
- /* destroy item order */
- struct key * key;
- if (i == node_item_number (bh) - 1) {
- printf ("can not destroy order\n");
- continue;
- }
- key = &(ih + 1)->ih_key;
- ih->ih_key.k_dir_id = key->k_dir_id + 1;
- mark_buffer_dirty (bh);
- }
-
- if (ih->ih_key.k_objectid != objectid || !is_direntry_ih (ih))
- continue;
-
- deh = B_I_DEH (bh, ih);
-
- for (j = 0; j < ih_entry_count (ih); j ++, deh ++) {
- /* look for proper entry */
- if (name_length (ih, deh, j) != strlen (name) ||
- strncmp (name, name_in_entry (deh, j), strlen (name)))
- continue;
-
- /* ok, required entry found, make a corruption */
- switch (code) {
- case 'C': /* cut entry */
- cut_entry (fs, bh, i, j, 1);
- mark_buffer_dirty (bh);
-
- if (!B_IS_IN_TREE (bh)) {
- printf ("NOTE: block is deleted from the tree\n");
- exit (0);
- }
- goto cont;
- break;
-
- case 'H': /* clobber hash */
- corrupt_clobber_hash (name, ih, deh);
- goto cont;
- break;
-
- case 'E': /* change entry's deh_objectid */
- deh->deh_objectid = new_objectid;
- break;
-
- default:
- printf ("Unknown command found\n");
- }
- mark_buffer_dirty (bh);
- }
- }
- cont:
- }
- free (line);
- printf ("Done\n");
+ if (who_is_this (bh->b_data, bh->b_size) != THE_UNKNOWN)
+ print_block (stdout, fs, bh, PRINT_TREE_DETAILS, -1, -1);
+ else
+ printf ("Looks like unformatted\n");
brelse (bh);
return;
}
-/* this reads stdin and recover file of given key: */
-/* the input has to be in the follwong format:
- K dirid objectid
- N name
- B blocknumber
- ..
- then recover_file will read every block, look there specified file and put it into
-*/
-static void do_recover (reiserfs_filsys_t fs)
-{
- char name [100];
- char * line = 0;
- int n = 0;
- int fd;
- struct key key = {0, 0, };
- struct buffer_head * bh;
- struct item_head * ih;
- unsigned long block;
- char code;
- loff_t recovered = 0;
- int i, j;
- reiserfs_bitmap_t bitmap;
- int used, not_used;
-
- bitmap = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
- reiserfs_fetch_disk_bitmap (bitmap, fs);
- /* we check how many blocks recoverd items point to are free or used */
- used = 0;
- not_used = 0;
-
- fd = 0;
- while (getline (&line, &n, stdin) != -1) {
- if (line [0] == '#' || line [0] == '\n')
- continue;
- switch (line [0]) {
- case 'K':
- /* get a key of file which is to be recovered */
- if (sscanf (line, "%c %u %u\n", &code, &key.k_dir_id, &key.k_objectid) != 3) {
- die ("recover_file: wrong input K format");
- }
- printf ("Recovering file (%u, %u)\n", key.k_dir_id, key.k_objectid);
- break;
-
- case 'N':
- /* get a file name */
- recovered = 0;
- if (sscanf (line, "%c %s\n", &code, name) != 2) {
- die ("recover_file: wrong input N format");
- }
- fd = open (name, O_RDWR | O_CREAT | O_EXCL, 0644);
- if (fd == -1)
- die ("recover_file: could not create file %s: %s",
- name,strerror (errno));
- printf ("Recovering file %s..\n", name);
- break;
-
- case 'B':
- if (!fd)
- die ("recover_file: file name is not specified");
- if (sscanf (line, "%c %lu\n", &code, &block) != 2) {
- die ("recover_file: wrong input B format");
- }
- bh = bread (fs->s_dev, block, fs->s_blocksize);
- if (!bh) {
- printf ("reading block %lu failed\n", block);
- continue;
- }
-
- printf ("working with block %lu..\n", block);
-
- ih = B_N_PITEM_HEAD (bh, 0);
- for (i = 0; i < node_item_number (bh); i ++, ih ++) {
- __u32 * indirect;
- struct buffer_head * tmp_bh;
-
- if (!is_indirect_ih (ih) || key.k_dir_id != ih->ih_key.k_dir_id ||
- key.k_objectid != ih->ih_key.k_objectid)
- continue;
-
- indirect = (__u32 *)B_I_PITEM (bh, ih);
- for (j = 0; j < I_UNFM_NUM (ih); j ++) {
- block = le32_to_cpu (indirect [j]);
- if (!block)
- continue;
- tmp_bh = bread (fs->s_dev, block, fs->s_blocksize);
- if (!tmp_bh) {
- printf ("reading block %Lu failed\n", (loff_t)block * fs->s_blocksize);
- continue;
- }
- if (lseek64 (fd, get_offset (&ih->ih_key) + j * fs->s_blocksize - 1,
- SEEK_SET) == (loff_t)-1) {
- printf ("llseek failed to pos %Ld\n", (loff_t)block * fs->s_blocksize);
- brelse (tmp_bh);
- continue;
- }
- if (reiserfs_bitmap_test_bit (bitmap, block))
- used ++;
- else
- not_used ++;
- /*printf ("block of file %Ld gets block %lu\n",
- (get_offset (&ih->ih_key) - 1) / fs->s_blocksize + j, block);*/
- if (write (fd, tmp_bh->b_data, tmp_bh->b_size) != tmp_bh->b_size) {
- printf ("write failed to pos %Ld\n", (loff_t)block * fs->s_blocksize);
- brelse (tmp_bh);
- continue;
- }
- recovered += fs->s_blocksize;
- brelse (tmp_bh);
- }
- }
- brelse (bh);
- break;
- }
- }
- printf ("recover_file: %Ld bytes recovered of file %s, key %u %u, %d blocks are free and %d are used\n",
- recovered, name, key.k_dir_id, key.k_objectid, not_used, used);
-}
/* debugreiserfs -p or -P compresses reiserfs meta data: super block, journal,
@@ -509,462 +192,358 @@ static void do_recover (reiserfs_filsys_t fs)
"bitmap" saved in that file and build the tree of blocks marked used in
that "bitmap" */
char * where_to_save;
+char * badblocks_file;
-
-static char * parse_options (int argc, char * argv [])
+static char * parse_options (struct debugreiserfs_data * data, int argc, char * argv [])
{
int c;
char * tmp;
- while ((c = getopt (argc, argv, "b:C:icdmoMp:P:l:jsnrtu:q")) != EOF) {
+
+ data->scan_area = USED_BLOCKS;
+ data->mode = DO_DUMP;
+
+ while ((c = getopt (argc, argv, "a:b:C:SU1:psn:NrdDomj:J:qt")) != EOF) {
switch (c) {
- case 'b': /* print a single node */
- opt_block_to_print = strtol (optarg, &tmp, 0);
+ case 'a': /* -r will read this, -n and -N will write to it */
+ asprintf (&data->map_file, "%s", optarg);
+ break;
+
+ case 'b':
+ /* will load bitmap from a file and read only blocks
+ marked in it. This is for -p and -s */
+ asprintf (&data->input_bitmap, "%s", optarg);
+ data->scan_area = EXTERN_BITMAP;
+ break;
+
+ case 'S':
+ /* have debugreiserfs -p or -s to read all the device */
+ data->scan_area = ALL_BLOCKS;
+ break;
+
+ case 'U':
+ /* have debugreiserfs -p or -s to read unused blocks only */
+ data->scan_area = UNUSED_BLOCKS;
+ break;
+
+ case '1': /* print a single node */
+ data->block = strtol (optarg, &tmp, 0);
if (*tmp)
die ("parse_options: bad block number");
break;
+
case 'C':
- mode = DO_CORRUPT;
- opt_block_to_corrupt = strtol (optarg, &tmp, 0);
+ data->mode = DO_CORRUPT;
+
+ data->block = strtol (optarg, &tmp, 0);
if (*tmp)
die ("parse_options: bad block number");
+
break;
case 'p':
- mode = DO_PACK;
- if (optarg)
- /* save bitmap of packed blocks in the file 'optarg' */
- asprintf (&where_to_save, "%s", optarg);
+ data->mode = DO_PACK;
break;
- case 'P':
- /* scan whole device and pack all blocks looking like a leaf */
- mode = DO_PACK_ALL;
- fprintf (stderr, "optarg %s\n", optarg);
- if (optarg)
- /* save bitmap of packed blocks in the file 'optarg' */
- asprintf (&where_to_save, "%s", optarg);
+ case 't':
+ data->mode = DO_STAT;
break;
- case 'i': /* print items of a leaf */
- opt_print_leaf_items = 1; break;
-
- case 'd': /* print directories */
- opt_print_details = 1; break;
-
- case 'c': /* print contents of a regular file */
- opt_print_regular_file_content = 1; break;
+ case 's':
+ /* read the device and print reiserfs blocks which contain defined key */
+ data->mode = DO_SCAN;
+ break;
- case 'o': /* print a objectid map */
- opt_print_objectid_map = 1; break;
+ case 'n': /* scan for names matching a specified pattern */
+ data->mode = DO_SCAN_FOR_NAME;
+ data->pattern = optarg;
+ /*asprintf (&data->pattern, "%s", optarg);*/
+ break;
- case 'm': /* print a block map */
- opt_print_block_map = 1; break;
+ case 'N': /* search name in the tree */
+ data->mode = DO_LOOK_FOR_NAME;
+ break;
- case 'M': /* print a block map with details */
- opt_print_block_map = 2; break;
+ case 'r':
+ data->mode = DO_RECOVER;
+ break;
- case 'j':
- opt_print_journal = 1; break; /* print journal */
-
- case 's':
- mode = DO_SCAN; break; /* read the device and print what reiserfs blocks were found */
+ case 'd':
+ /* print leaf details from internal tree */
+ data->options |= PRINT_TREE_DETAILS;
+ break;
- case 'n':
- mode = DO_SCAN_FOR_NAME; break;
+ case 'D':
+ /* print leaf details accordingly the bitmap - can be used with -S */
+ data->options |= PRINT_DETAILS;
+ break;
+
+ case 'o':
+ /* print objectid map */
+ data->options |= PRINT_OBJECTID_MAP;
+ break;
- case 'r':
- mode = DO_RECOVER; break;
+ case 'm': /* print a block map */
+ case 'M': /* print a block map with details */
+ data->options |= PRINT_BITMAP;
+ break;
- case 't':
- mode = DO_TEST; break;
+ case 'j': /* -j must have a parameter */
+ data->options |= PRINT_JOURNAL;
+ data->journal_device_name = optarg;
+ break;
+ case 'J':
+ data->options |= PRINT_JOURNAL_HEADER;
+ data->journal_device_name = optarg;
+ break;
+
+ case 'R': /* read block numbers from stdin and look for them in the
+ journal */
+ data->mode = DO_SCAN_JOURNAL;
+ data->JJ ++;
+ break;
+
+ case 'B': /*disabled for a while*/
+ asprintf (&badblocks_file, "%s", optarg);
+ data->mode = DO_EXTRACT_BADBLOCKS;
+ break;
case 'q':
/* this makes packing to not show speed info during -p or -P */
- opt_quiet = 1;
+ data->options |= BE_QUIET;
break;
}
}
+
if (optind != argc - 1)
/* only one non-option argument is permitted */
print_usage_and_exit();
+ data->device_name = argv[optind];
return argv[optind];
}
+void pack_partition (reiserfs_filsys_t * fs);
-/* print all valid transactions and found dec blocks */
-static void print_journal (struct super_block * s)
+static void do_pack (reiserfs_filsys_t * fs)
{
- struct buffer_head * d_bh, * c_bh;
- struct reiserfs_journal_desc * desc ;
- struct reiserfs_journal_commit *commit ;
- int end_journal;
- int start_journal;
- int i, j;
- int first_desc_block = 0;
- int wrapped = 0;
- int valid_transactions = 0;
-
- start_journal = SB_JOURNAL_BLOCK (s);
- end_journal = start_journal + JOURNAL_BLOCK_COUNT;
- reiserfs_warning (stdout, "Start scanning from %d\n", start_journal);
-
- d_bh = 0;
- desc = 0;
- for (i = start_journal; i < end_journal; i ++) {
- d_bh = bread (s->s_dev, i, s->s_blocksize);
- if (who_is_this (d_bh->b_data, d_bh->b_size) == THE_JDESC) {
- int commit_block;
-
- if (first_desc_block == 0)
- /* store where first desc block found */
- first_desc_block = i;
-
- print_block (stdout, s, d_bh); /* reiserfs_journal_desc structure will be printed */
- desc = (struct reiserfs_journal_desc *)(d_bh->b_data);
-
- commit_block = d_bh->b_blocknr + desc->j_len + 1;
- if (commit_block >= end_journal) {
- reiserfs_warning (stdout, "-- wrapped?");
- wrapped = 1;
- break;
- }
-
- c_bh = bread (s->s_dev, commit_block, s->s_blocksize);
- commit = bh_commit (c_bh);
- if (does_desc_match_commit (desc, commit)) {
- reiserfs_warning (stdout, "commit block %d (trans_id %ld, j_len %ld) does not match\n", commit_block,
- commit->j_trans_id, commit->j_len);
- brelse (c_bh) ;
- brelse (d_bh);
- continue;
- }
-
- valid_transactions ++;
- reiserfs_warning (stdout, "(commit block %d) - logged blocks (", commit_block);
-#if 1
- for (j = 0; j < desc->j_len; j ++) {
- unsigned long block;
-
- if (j < JOURNAL_TRANS_HALF)
- block = le32_to_cpu (desc->j_realblock[j]);
- else
- block = le32_to_cpu (commit->j_realblock[i - JOURNAL_TRANS_HALF]);
-
- if (not_journalable (s, block))
- reiserfs_warning (stdout, " xxxx");
- else {
- reiserfs_warning (stdout, " %ld", desc->j_realblock[j]);
- if (block_of_bitmap (s, desc->j_realblock[j]))
- reiserfs_warning (stdout, "(bmp)");
- }
- if (j && (j + 1) % 10 == 0)
- reiserfs_warning (stdout, "\n");
- }
-#endif
- reiserfs_warning (stdout, ")\n");
- i += desc->j_len + 1;
- brelse (c_bh);
- }
- brelse (d_bh);
- }
-
- if (wrapped) {
- c_bh = bread (s->s_dev, first_desc_block - 1, s->s_blocksize);
- commit = bh_commit (c_bh);
- if (does_desc_match_commit (desc, commit)) {
- reiserfs_warning (stdout, "No! commit block %d (trans_id %ld, j_len %ld) does not match\n",
- first_desc_block - 1, commit->j_trans_id, commit->j_len);
- } else {
- reiserfs_warning (stdout, "Yes! (commit block %d) - logged blocks (\n", first_desc_block - 1);
-#if 1
- for (j = 0; j < desc->j_len; j ++) {
- unsigned long block;
-
- if (j < JOURNAL_TRANS_HALF)
- block = le32_to_cpu (desc->j_realblock[j]);
- else
- block = le32_to_cpu (commit->j_realblock[i - JOURNAL_TRANS_HALF]);
-
- if (not_journalable (s, block))
- reiserfs_warning (stdout, " xxxx");
- else {
- reiserfs_warning (stdout, " %ld", desc->j_realblock[j]);
- if (block_of_bitmap (s, desc->j_realblock[j]))
- reiserfs_warning (stdout, "(bmp)");
- }
- }
-#endif
- reiserfs_warning (stdout, "\n");
- }
- brelse (c_bh) ;
- brelse (d_bh);
- }
-
- reiserfs_warning (stdout, "%d valid transactions found\n", valid_transactions);
+ if (certain_block (fs))
+ pack_one_block (fs, certain_block (fs));
+ else
+ pack_partition (fs);
+
+}
- {
- struct buffer_head * bh;
- struct reiserfs_journal_header * j_head;
+/*
+static int comp (const void * vp1, const void * vp2)
+{
+ const int * p1, * p2;
- bh = bread (s->s_dev, SB_JOURNAL_BLOCK (s) + rs_journal_size (s->s_rs),
- s->s_blocksize);
- j_head = (struct reiserfs_journal_header *)(bh->b_data);
+ p1 = vp1; p2 = vp2;
- reiserfs_warning (stdout, "#######################\nJournal header:\n"
- "j_last_flush_trans_id %ld\n"
- "j_first_unflushed_offset %ld\n"
- "j_mount_id %ld\n", j_head->j_last_flush_trans_id, j_head->j_first_unflushed_offset,
- j_head->j_mount_id);
- brelse (bh);
- }
+ if (*p1 < *p2)
+ return -1;
+ if (*p1 > *p2)
+ return 1;
+ return 0;
}
+*/
+
+static void init_bitmap (reiserfs_filsys_t * fs)
+{
+ FILE * fp;
+ unsigned long block_count;
-void pack_partition (reiserfs_filsys_t fs);
+ if (!reiserfs_open_ondisk_bitmap (fs))
+ reiserfs_panic ("Could not open ondisk bitmap");
-static void do_pack (reiserfs_filsys_t fs)
-{
- if (opt_block_to_print != -1)
- pack_one_block (fs, opt_block_to_print);
- else
- pack_partition (fs);
+ block_count = get_sb_block_count (fs->fs_ondisk_sb);
+
+ switch (scan_area (fs)) {
+ case ALL_BLOCKS:
+ input_bitmap (fs) = reiserfs_create_bitmap (block_count);
+ reiserfs_bitmap_fill (input_bitmap (fs));
+ reiserfs_warning (stderr, "Whole device (%d blocks) is to be scanned\n",
+ reiserfs_bitmap_ones (input_bitmap (fs)));
+ break;
+
+ case USED_BLOCKS:
+ reiserfs_warning (stderr, "Loading on-disk bitmap .. ");
+ input_bitmap (fs) = reiserfs_create_bitmap (block_count);
+ reiserfs_bitmap_copy (input_bitmap (fs), fs->fs_bitmap2);
+ reiserfs_warning (stderr, "%d bits set - done\n",
+ reiserfs_bitmap_ones (input_bitmap (fs)));
+ break;
+
+ case UNUSED_BLOCKS:
+ reiserfs_warning (stderr, "Loading on-disk bitmap .. ");
+ input_bitmap (fs) = reiserfs_create_bitmap (block_count);
+ reiserfs_bitmap_copy (input_bitmap (fs), fs->fs_bitmap2);
+ reiserfs_bitmap_invert (input_bitmap (fs));
+ reiserfs_warning (stderr, "%d bits set - done\n",
+ reiserfs_bitmap_ones (input_bitmap (fs)));
+ break;
+ case EXTERN_BITMAP:
+ fp = fopen (input_bitmap_file_name(fs), "r");
+ if (!fp)
+ reiserfs_panic ("init_bitmap: could not load bitmap: %m\n");
+
+ input_bitmap (fs) = reiserfs_bitmap_load (fp);
+ if (!input_bitmap (fs))
+ reiserfs_panic ("could not load fitmap from \"%s\"",
+ input_bitmap_file_name(fs));
+ reiserfs_warning (stderr, "%d blocks marked in the given bitmap\n",
+ reiserfs_bitmap_ones (input_bitmap (fs)));
+ fclose (fp);
+ break;
+
+ default:
+ reiserfs_panic ("No area to scan specified");
+ }
}
/* FIXME: statistics does not work */
-static void do_dump_tree (reiserfs_filsys_t fs)
+static void do_dump_tree (reiserfs_filsys_t * fs)
{
- if (opt_block_to_print != -1) {
- print_one_block (fs, opt_block_to_print);
+ if (certain_block (fs)) {
+ print_one_block (fs, certain_block (fs));
return;
}
- print_block (stdout, fs, SB_BUFFER_WITH_SB (fs));
-
- if (opt_print_journal)
+ if (data (fs)->options & PRINT_JOURNAL || data (fs)->options & PRINT_JOURNAL_HEADER) {
+ if (!reiserfs_journal_opened (fs) && !reiserfs_open_journal (fs, data (fs)->journal_device_name, O_RDONLY)) {
+ printf ("Could not open journal\n");
+ return;
+ }
+ }
+
+ print_filesystem_state (stdout, fs);
+ print_block (stdout, fs, fs->fs_super_bh);
+
+ if (data (fs)->options & PRINT_JOURNAL)
print_journal (fs);
-
- if (opt_print_objectid_map == 1)
+
+ if (data (fs)->options & PRINT_JOURNAL_HEADER)
+ print_journal_header (fs);
+
+ if (data (fs)->options & PRINT_OBJECTID_MAP)
print_objectid_map (stdout, fs);
-
- if (opt_print_block_map)
- print_bmap (stdout, fs, opt_print_block_map == 1 ? 1 : 0);
-
- if (opt_print_regular_file_content || opt_print_details ||
- opt_print_leaf_items) {
- print_disk_tree (fs, SB_ROOT_BLOCK (fs));
+
+ if (data (fs)->options & PRINT_BITMAP)
+ print_bmap (stdout, fs, 0/*opt_print_block_map == 1 ? 1 : 0*/);
+
+ if (data (fs)->options & PRINT_DETAILS)
+ init_bitmap (fs);
+
+ if (data (fs)->options & PRINT_DETAILS || data (fs)->options & PRINT_TREE_DETAILS) {
+ if (data (fs)->options & PRINT_DETAILS)
+ print_disk_blocks (fs);
+ else
+ print_disk_tree (fs, get_sb_root_block (fs->fs_ondisk_sb));
/* print the statistic */
printf ("File system uses %d internal + %d leaves + %d unformatted nodes = %d blocks\n",
- g_stat_info.nr_internals, g_stat_info.nr_leaves, g_stat_info.nr_unformatted,
+ g_stat_info.nr_internals, g_stat_info.nr_leaves, g_stat_info.nr_unformatted,
g_stat_info.nr_internals + g_stat_info.nr_leaves + g_stat_info.nr_unformatted);
}
}
-FILE * log;
-
-static void look_for_key (struct buffer_head * bh, struct key * key)
+void extract_badblock_list ()
{
- int i, j;
- struct item_head * ih;
- struct reiserfs_de_head * deh;
+ FILE * fd;
+ struct key badblock_key = {-1, -1, {{0, 0}}};
+ struct key * rdkey;
+ struct path badblock_path;
+ struct item_head * tmp_ih;
+ __u32 i;
+ __u32 * ind_item;
- ih = B_N_PITEM_HEAD (bh, 0);
- for (i = 0; i < B_NR_ITEMS (bh); i ++, ih ++) {
- if ((ih->ih_key.k_dir_id == key->k_dir_id || (int)key->k_dir_id == -1) &&
- ih->ih_key.k_objectid == key->k_objectid) {
- reiserfs_warning (log, "%d-th item of block %lu is item of file %K: %H\n",
- i, bh->b_blocknr, key, ih);
- }
- if (!is_direntry_ih (ih))
- continue;
- deh = B_I_DEH (bh, ih);
- for (j = 0; j < ih_entry_count (ih); j ++, deh ++) {
- if ((deh->deh_dir_id == key->k_dir_id || (int)key->k_dir_id == -1) &&
- deh->deh_objectid == key->k_objectid) {
- reiserfs_warning (log, "dir item %d (%H) of block %lu has "
- "entry (%d-th) %.*s pointing to %K\n",
- i, ih, bh->b_blocknr, j,
- name_length (ih, deh, j), name_in_entry (deh, j), key);
- }
- }
- }
- return;
-}
-
+ fd = fopen (badblocks_file, "w");
-static void look_for_name (struct buffer_head * bh, char * name)
-{
- int i, j;
- struct item_head * ih;
- struct reiserfs_de_head * deh;
- int namelen;
- char * p;
-
- ih = B_N_PITEM_HEAD (bh, 0);
- for (i = 0; i < B_NR_ITEMS (bh); i ++, ih ++) {
- if (!is_direntry_ih (ih))
- continue;
- deh = B_I_DEH (bh, ih);
- for (j = 0; j < ih_entry_count (ih); j ++, deh ++) {
- p = name_in_entry (deh, j);
- namelen = name_length (ih, deh, j);
- if (namelen == strlen (name) && !strncmp (name, p, namelen)) {
- fprintf (log, "block %lu, item %d, entry %d is %s\n", bh->b_blocknr, i, j, name);fflush (log);
- }
- }
+ if (fd == NULL) {
+ reiserfs_warning (stderr, "debugreiserfs: could not open badblock file %s\n",
+ badblocks_file);
+ exit (1);
}
- return;
-}
-
+ badblock_path.path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
+ set_type_and_offset (KEY_FORMAT_2, &badblock_key, 1, TYPE_INDIRECT);
-static void do_scan (reiserfs_filsys_t fs)
-{
- unsigned long i;
- struct buffer_head * bh;
- int type;
- char * answer = 0;
- size_t n = 0;
- struct key key = {0, 0, };
- unsigned long done, total;
- reiserfs_bitmap_t bitmap;
-
-
- bitmap = reiserfs_bitmap_load (".bitmap");
- total = reiserfs_bitmap_ones (bitmap);
-/*
- bitmap = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
- reiserfs_fetch_disk_bitmap (bitmap, fs);
-*/
-
- log = fopen ("scan.log", "w+");
-
- if (mode == DO_SCAN_FOR_NAME) {
- printf ("What name do you want to look for?");
- getline (&answer, &n, stdin);
- answer [strlen (answer) - 1] = 0;
- printf ("Looking for name \"%s\"..\n", answer);
- key.k_dir_id = 1;
- } else {
- printf ("What key do you want to find: dirid?");
- getline (&answer, &n, stdin);
- key.k_dir_id = atoi (answer);
- printf ("objectid?");
- getline (&answer, &n, stdin);
- key.k_objectid = atoi (answer);
- printf ("looking for (%u %u)\n", key.k_dir_id, key.k_objectid);
- }
+ while (1) {
+ reiserfs_search_by_key_4 (fs, &badblock_key, &badblock_path);
- done = 0;
- for (i = 0; i < SB_BLOCK_COUNT (fs); i ++) {
- if (!reiserfs_bitmap_test_bit (bitmap, i))
- continue;
- bh = bread (fs->s_dev, i, fs->s_blocksize);
- if (!bh) {
- printf ("could not read block %lu\n", i);
- continue;
+ if (get_blkh_nr_items ( B_BLK_HEAD (get_bh(&badblock_path))) <= PATH_LAST_POSITION (&badblock_path)) {
+ break;
}
- type = who_is_this (bh->b_data, bh->b_size);
- switch (type) {
- case THE_JDESC:
- if (!key.k_dir_id)
- printf ("block %lu is journal descriptor\n", i);
- break;
- case THE_SUPER:
- if (!key.k_dir_id)
- printf ("block %lu is reiserfs super block\n", i);
- break;
- case THE_INTERNAL:
- if (!key.k_dir_id)
- printf ("block %lu is reiserfs internal node\n", i);
- break;
- case THE_LEAF:
- if (mode == DO_SCAN_FOR_NAME) {
- look_for_name (bh, answer);
- } else if (key.k_dir_id) {
- look_for_key (bh, &key);
- } else {
- printf ("block %lu is reiserfs leaf node\n", i);
- }
+
+ tmp_ih = get_ih(&badblock_path);
+
+ if (get_key_dirid(&tmp_ih->ih_key) != (__u32)-1 ||
+ get_key_objectid(&tmp_ih->ih_key) != (__u32)-1) {
break;
}
- brelse (bh);
- print_how_far (&done, total, 1, 0);
+
+ /* even if offset or type are corrupted it could be a badblock list */
+ if (!is_indirect_ih (tmp_ih)) {
+ reiserfs_warning (stderr, "$s: a badblock item which was found has a wrong type.\n"
+ " It probable contains not correct bad block list, check it.\n", __FUNCTION__);
+ }
+
+ ind_item = (__u32 *)B_I_PITEM (get_bh (&badblock_path), tmp_ih);
+ for (i = 0; i < get_ih_item_len (tmp_ih) / UNFM_P_SIZE; i++, ind_item++)
+ fprintf (fd, "%u\n", le32_to_cpu (*ind_item));
+
+ if ((rdkey = get_next_key_2 (&badblock_path)) == NULL)
+ break;
+ else
+ badblock_key = *rdkey;
+
+ pathrelse (&badblock_path);
}
-}
-
-
-
-#if 0
-static void do_test (reiserfs_filsys_t fs, unsigned long block)
-{
- struct buffer_head * bh;
-
- fprintf (stderr, "=========== BLock %lu ============\n", block);
- bh = bread (fs->s_dev, block, fs->s_blocksize);
- if (!bh)
- die ("do_test: bread failed");
- if (is_leaf_bad (bh))
- fprintf (stderr, "\n######### BAD before repairing ############\n");
- else
- fprintf (stderr, "\n========= OK before repairing ==================\n");
- print_block (fs, bh, 3, -1, -1);
-
- fprintf (stderr, "\n>>> repairing >>>>........\n\n");
-
- /* function to test */pass0_correct_leaf (fs, bh);
- if (is_leaf_bad (bh))
- fprintf (stderr, "\n######### still BAD after repairing ############\n");
- else
- fprintf (stderr, "\n========= OK after repairing ==================\n");
- print_block (fs, bh, 3, -1, -1);
- brelse (bh);
-}
-#endif
-
-static void do_test (reiserfs_filsys_t fs)
-{
- struct key root_dir_key = {REISERFS_ROOT_PARENT_OBJECTID,
- REISERFS_ROOT_OBJECTID, {{0, 0},}};
- int gen_counter;
- if (reiserfs_find_entry (fs, &root_dir_key, "lost+found", &gen_counter))
- reiserfs_add_entry (fs, &root_dir_key, "lost+found", &root_dir_key, 0);
+ pathrelse (&badblock_path);
+ fclose (fd);
}
-
/* FIXME: need to open reiserfs filesystem first */
int main (int argc, char * argv[])
{
char * file_name;
int error;
+ struct debugreiserfs_data * data;
+
print_banner ("debugreiserfs");
- file_name = parse_options (argc, argv);
-
- fs = reiserfs_open (file_name, O_RDONLY, &error, 0);
- if (!fs) {
+ data = getmem (sizeof (struct debugreiserfs_data));
+ file_name = parse_options (data, argc, argv);
+ fs = reiserfs_open (file_name, O_RDONLY, &error, data);
+ if (no_reiserfs_found (fs)) {
fprintf (stderr, "\n\ndumpreiserfs: can not open reiserfs on \"%s\": %s\n\n",
- file_name, error ? strerror (error) : "there is no one");
- return 0;
+ file_name, error ? strerror (error) : "no filesystem found");
+ exit(1) ;
}
+ reiserfs_open_journal (fs, data (fs)->journal_device_name, O_RDONLY);
+
+ switch (debug_mode (fs)) {
+ case DO_STAT:
+ init_bitmap (fs);
+ do_stat (fs);
+ break;
- switch (mode) {
case DO_PACK:
- case DO_PACK_ALL:
+ init_bitmap (fs);
do_pack (fs);
break;
case DO_CORRUPT:
reiserfs_reopen (fs, O_RDWR);
- do_corrupt_one_block (fs, opt_block_to_corrupt);
+ do_corrupt_one_block (fs);
break;
case DO_DUMP:
@@ -973,6 +552,9 @@ int main (int argc, char * argv[])
case DO_SCAN:
case DO_SCAN_FOR_NAME:
+ case DO_LOOK_FOR_NAME:
+ case DO_SCAN_JOURNAL:
+ init_bitmap (fs);
do_scan (fs);
break;
@@ -981,64 +563,15 @@ int main (int argc, char * argv[])
break;
case DO_TEST:
- {
- do_test (fs);
-
-#if 0
- int i;
- int arr[] = {53033};
-
- if (opt_block_to_print != -1) {
- do_test (fs, opt_block_to_print);
- break;
- }
-
-bad blocks found on Joop partition
-
-53033,
-179201,
-844702,
-844913,
-877768,
-879067,
-907631,
-925323,
-2241275,
-2241343,
-2241397,
-2241511,
-2241553,
-2241635,
-2241644,
-2241654,
-2241711,
-2241721,
-2241727,
-2241740,
-2241762,
-2241766,
-2241770,
-2241812,
-2241820,
-2241827,
-2241831,
-2241878,
-2241886,
-2241971
- };
- /* blocks containing broken directory items on Joop's filesystem */
- int arr[] = {/*53033,*/ 838396/*, 1597036*//*, 1919589, 2715962*/};
-
-
-
- for (i = 0; i < sizeof (arr) / sizeof (arr[0]); i ++)
- do_test (fs, arr[i]);
+ /*do_test (fs);*/
break;
-#endif
-
- }
+ case DO_EXTRACT_BADBLOCKS:
+ reiserfs_warning (stderr, "Will try to extract list of bad blocks and save it to '%s' file\n", badblocks_file);
+ extract_badblock_list ();
+ reiserfs_warning (stderr, "Done\n\n");
+ break;
}
- reiserfs_close (fs);
+ reiserfs_free (fs);
return 0;
}
diff --git a/debugreiserfs/debugreiserfs.h b/debugreiserfs/debugreiserfs.h
index 2d754b5..1ee70da 100644
--- a/debugreiserfs/debugreiserfs.h
+++ b/debugreiserfs/debugreiserfs.h
@@ -1,8 +1,9 @@
/*
- * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
+ * Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
*/
#define _GNU_SOURCE
+
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
@@ -18,28 +19,43 @@
#include "io.h"
#include "misc.h"
#include "reiserfs_lib.h"
+#include "../include/config.h"
#include "../version.h"
+extern reiserfs_filsys_t * fs;
/*
* modes
*/
-#define DO_DUMP 1 /* not a real dump, just printing to stdout contents of
- tree nodes */
-#define DO_CORRUPT 2 /* used to make filesystem corruption and then test fsck */
-#define DO_SCAN 3
-#define DO_SCAN_FOR_NAME 4
-#define DO_RECOVER 5
-#define DO_TEST 6
-#define DO_PACK 7 /* -p extract meta data of reiserfs filesystem */
-#define DO_PACK_ALL 8 /* -p */
+#define DO_DUMP 1 /* not a real dump, just printing to stdout contents of
+ tree nodes */
+#define DO_CORRUPT 2 /* used to make filesystem corruption and then test fsck */
+#define DO_SCAN 3
+#define DO_RECOVER 4
+#define DO_TEST 6
+#define DO_PACK 7 /* -p extract meta data of reiserfs filesystem */
+#define DO_STAT 8
+#define DO_SCAN_FOR_NAME 9 /* -n */
+#define DO_LOOK_FOR_NAME 10 /* -N */
+#define DO_SCAN_JOURNAL 11 /* -J */
+#define DO_EXTRACT_BADBLOCKS 12
+
+/*first bits are in reiserfs_fs.b*/
+#define PRINT_JOURNAL 0x10
+#define PRINT_JOURNAL_HEADER 0x20
+#define PRINT_BITMAP 0x40
+#define PRINT_OBJECTID_MAP 0x80
+#define BE_QUIET 0x100
-extern int opt_quiet;
-extern int mode;
+/* these moved to reiserfs_fs.h */
+//#define PRINT_TREE_DETAILS
+//#define PRINT_DETAILS
+//#define PRINT_ITEM_DETAILS
+//#define PRINT_DIRECT_ITEMS
-// the leaf is stored in compact form:
+// the leaf is stored in compact form:
// start magic number
// block number __u32
// item number __u16
@@ -48,7 +64,7 @@ extern int mode;
// end magic number
/* we store hash code in high byte of 16 bits */
-#define LEAF_START_MAGIC 0xa5
+#define LEAF_START_MAGIC 0xa6
#define LEAF_END_MAGIC 0x5a
@@ -60,76 +76,183 @@ extern int mode;
#define END_MAGIC 0x8d
#define INTERNAL_START_MAGIC
#define INTERNAL_START_MAGIC
-
+#define SEPARATED_JOURNAL_START_MAGIC 0xf8
+#define SEPARATED_JOURNAL_END_MAGIC 0x8f
#define ITEM_START_MAGIC 0x476576
#define ITEM_END_MAGIC 0x2906504
-/* flags in packed item mask */
-#define NEW_FORMAT 1 // 0 here means - old format, 1 - new format
-#define DIR_ID 2
-#define OBJECT_ID 4
-#define OFFSET_BITS_32 8
-#define OFFSET_BITS_64 16
-#define ENTRY_COUNT 32 // shows whether ih_free_space/ih_entry_count is stored
-
-#define INDIRECT_ITEM 64
-#define DIRENTRY_ITEM 128
-#define DIRECT_ITEM 256
-#define STAT_DATA_ITEM 512
-
-#define ITEM_BODY 1024
-#define WHOLE_INDIRECT 128
-#define WITH_SD_FIRST_DIRECT_BYTE 8192 /* for old stat data first_direct_byte
- is stored */
-#define NLINK_BITS_32 8192 /* nlinks stored in 32 bits */
-#define SIZE_BITS_64 16384 /* size has to be stored in 64 bit */
+#define MAP_MAGIC 0xe9
+#define MAP_END_MAGIC 0x9e
+
+
+/* 12 bits of mask are used to define */
+#define NEW_FORMAT 0x01 /* 1. 0 here means - old format, 1 - new format */
+#define DIR_ID 0x02 /* 2. dir_id is stored */
+#define OBJECT_ID 0x04 /* 3. objectid is stored */
+#define OFFSET_BITS_32 0x08 /* 4. offset is stored as 32 bit */
+#define OFFSET_BITS_64 0x10 /* 5. offset is stored as 64 bit */
+#define IH_ENTRY_COUNT 0x20 /* 6. ih_free_space/ih_entry_count is stored */
+#define IH_FREE_SPACE 0x20
+#define IH_FORMAT 0x40 /* 7. ih_format is stored */
+#define WITH_SD_FIRST_DIRECT_BYTE 0x80 /* 8. for old stat data first_direct_byte is stored */
+#define NLINK_BITS_32 0x0100 /* 9. nlinks stored in 32 bits */
+#define SIZE_BITS_64 0x0200 /* 10. size has to be stored in 64 bit */
+#define WHOLE_INDIRECT 0x0400 /* 11. indirect item is stored with compression */
+#define SAFE_LINK 0x0800 /* 11. indirect item is stored with compression */
+
+
+#define TYPE_MASK 0x3 /* two lowest bits are used to store item type */
+//#define MASK_MASK 0xffffc /* what is packed: dirid, objectid, etc */
+#define ITEM_LEN_MASK 0xfff00000 /* contents of ih_item_len of item_head */
struct packed_item {
- /*__u16 length;*/ // length of the area we store item in
- __u16 mask; // what is stored: dirid, objectid, 32 bit offset or 64 bit offset, type
- __u16 item_len;
+ __u32 type_2_mask_18_len_12;
};
-#define HAS_DIR_ID 1
-#define HAS_GEN_COUNTER 2
-#define HAS_STATE 4
-#define YURA 8
-#define TEA 16
-#define R5 32
+
+/* defined as inlines in both pack.c and unpack.c */
+inline void set_pi_type( struct packed_item *pi, __u32 val );
+inline __u32 get_pi_type( const struct packed_item *pi );
+inline void set_pi_mask( struct packed_item *pi, __u32 val );
+inline __u32 get_pi_mask( const struct packed_item *pi );
+inline void set_pi_item_len( struct packed_item *pi, __u32 val );
+inline __u32 get_pi_item_len( const struct packed_item *pi );
+
+
+#define HAS_DIR_ID 0x01
+#define HAS_GEN_COUNTER 0x02
+#define HAS_STATE 0x04
+#define YURA 0x08
+#define TEA 0x10
+#define R5 0x20
+
struct packed_dir_entry {
__u8 mask;
__u16 entrylen;
};
+/* packed_dir_entry.mask is *always* endian safe, since it's 8 bit */
+#define get_pe_entrylen(pe) (le16_to_cpu((pe)->entrylen))
+#define set_pe_entrylen(pe,v) ((pe)->entrylen = cpu_to_le16(v))
+
+
+#define fread8(pv) fread (pv, sizeof (__u8), 1, stdin)
+
+#define fread_le16(pv)\
+{\
+ __u16 tmp; \
+ fread16(&tmp); \
+ *pv = le16_to_cpu(tmp); \
+}
+
+#define fread_le32(pv)\
+{\
+ __u32 tmp; \
+ fread32(&tmp); \
+ *pv = le32_to_cpu(tmp); \
+}
+
+#define fread_le64(pv)\
+{\
+ __u64 tmp; \
+ fread64(&tmp); \
+ *pv = le64_to_cpu(tmp); \
+}
+
#define fread8(pv) fread (pv, sizeof (__u8), 1, stdin)
#define fread16(pv) fread (pv, sizeof (__u16), 1, stdin)
#define fread32(pv) fread (pv, sizeof (__u32), 1, stdin)
#define fread64(pv) fread (pv, sizeof (__u64), 1, stdin)
+
+#define fwrite_le16(pv)\
+{\
+ __u16 tmp = cpu_to_le16(*(pv));\
+ fwrite16(&tmp);\
+}
+
+#define fwrite_le32(pv)\
+{\
+ __u32 tmp = cpu_to_le32(*(pv));\
+ fwrite32(&tmp);\
+}
+
+#define fwrite_le64(pv)\
+{\
+ __u64 tmp = cpu_to_le64(*(pv));\
+ fwrite64(&tmp);\
+}
+
#define fwrite8(pv) {\
if (fwrite (pv, sizeof (__u8), 1, stdout) != 1)\
reiserfs_panic ("fwrite8 failed: %m");\
+sent_bytes ++;\
}
#define fwrite16(pv) {\
if (fwrite (pv, sizeof (__u16), 1, stdout) != 1)\
reiserfs_panic ("fwrite16 failed: %m");\
+sent_bytes += 2;\
}
#define fwrite32(pv) {\
if (fwrite (pv, sizeof (__u32), 1, stdout) != 1)\
reiserfs_panic ("fwrite32 failed: %m");\
+sent_bytes += 4;\
}
#define fwrite64(pv) {\
if (fwrite (pv, sizeof (__u64), 1, stdout) != 1)\
reiserfs_panic ("fwrite64 failed: %m");\
+sent_bytes += 8;\
}
-/*
-#define fwrite16(pv) fwrite (pv, sizeof (__u16), 1, stdout)
-#define fwrite32(pv) fwrite (pv, sizeof (__u32), 1, stdout)
-#define fwrite64(pv) fwrite (pv, sizeof (__u64), 1, stdout)
-*/
-#define BLOCKS_PER_READ 8
-extern char * where_to_save;
+struct debugreiserfs_data {
+ int mode; /* DO_DUMP | DO_PACK | DO_CORRUPT... */
+#define USED_BLOCKS 1
+#define EXTERN_BITMAP 2
+#define ALL_BLOCKS 3
+#define UNUSED_BLOCKS 4
+
+ int scan_area; /* for -p, -s and -n */
+ char * input_bitmap; /* when ->scan_area is set to EXTERN_BITMAP */
+ reiserfs_bitmap_t * bitmap; /* bitmap is read from ->input_bitmap */
+ unsigned long block; /* set by -B. this is a must for -C, option for -p and -d */
+ char * pattern; /* for -n */
+ char * device_name;
+ char * journal_device_name; /* for -j */
+ char * map_file; /* for -n, -N and -r */
+
+ unsigned long options; /* -q only yet*/
+ int JJ;
+};
+
+#define data(fs) ((struct debugreiserfs_data *)((fs)->fs_vp))
+
+#define debug_mode(fs) (data(fs)->mode)
+#define certain_block(fs) (data(fs)->block)
+#define input_bitmap(fs) (data(fs)->bitmap)
+#define input_bitmap_file_name(fs) (data(fs)->input_bitmap)
+#define scan_area(fs) (data(fs)->scan_area)
+#define name_pattern(fs) (data(fs)->pattern)
+#define device_name(fs) (data(fs)->device_name)
+#define journal_device_name(fs) (data(fs)->journal_device_name)
+#define map_file(fs) (data(fs)->map_file)
+
+
+#define be_quiet(fs) (data(fs)->options & BE_QUIET)
+
+/* stat.c */
+void do_stat (reiserfs_filsys_t * fs);
+
+/* corruption.c */
+void do_corrupt_one_block (reiserfs_filsys_t * fs);
+
+/* recover.c */
+void do_recover (reiserfs_filsys_t * fs);
+
+/* scan.c */
+void do_scan (reiserfs_filsys_t * fs);
+
+/* journal.c */
+void scan_journal (reiserfs_filsys_t * fs);
diff --git a/debugreiserfs/journal.c b/debugreiserfs/journal.c
new file mode 100644
index 0000000..a2bf6c8
--- /dev/null
+++ b/debugreiserfs/journal.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2002 Hans Reiser
+ */
+
+#include "debugreiserfs.h"
+
+
+extern unsigned long * badblocks;
+extern int badblocks_nr;
+
+#if 0
+static void look_in_transaction (reiserfs_filsys_t * fs,
+ reiserfs_trans_t * trans)
+{
+ struct buffer_head * d_bh, * c_bh, * logged, * in_place;
+ struct reiserfs_journal_desc * desc;
+ struct reiserfs_journal_commit * commit;
+ int i, j;
+ int who;
+
+
+ d_bh = bread (fs->fs_dev, trans->desc_blocknr, fs->fs_blocksize);
+ if (!d_bh) {
+ reiserfs_warning (stdout, "reading descriptor block %lu failed\n",
+ trans->desc_blocknr);
+ return;
+ }
+
+ c_bh = bread (fs->fs_dev, trans->commit_blocknr, fs->fs_blocksize);
+ if (!c_bh) {
+ reiserfs_warning (stdout, "reading commit block %lu failed\n",
+ trans->commit_blocknr);
+ brelse (d_bh);
+ return;
+ }
+
+// desc = (struct reiserfs_journal_desc *)(d_bh->b_data);
+// commit = (struct reiserfs_journal_commit *)(c_bh->b_data);
+
+ reiserfs_warning (stdout, "Transaction %lu\n", trans->trans_id);
+
+ for (i = 0; i < badblocks_nr; i ++) {
+ for (j = 0; j < get_jd_len (d_bh); j ++) {
+ if ((j < JOURNAL_TRANS_HALF && badblocks [i] == le32_to_cpu (desc->j2_realblock[j])) ||
+ (j >= JOURNAL_TRANS_HALF && badblocks [i] == le32_to_cpu (commit->j3_realblock[j - JOURNAL_TRANS_HALF]))) {
+ reiserfs_warning (stdout,
+ "\tblock %lu is logged in it (block of journal area %lu - ",
+ badblocks [i], d_bh->b_blocknr + j + 1);
+
+ logged = 0;
+ in_place = 0;
+
+ logged = bread (fs->fs_dev, d_bh->b_blocknr + j + 1, fs->fs_blocksize);
+ in_place = bread (fs->fs_dev, badblocks [i], fs->fs_blocksize);
+ if (!logged || !in_place) {
+ reiserfs_warning (stdout, "Could not read blocks\n");
+ brelse (logged);
+ brelse (in_place);
+ continue;
+ }
+
+ who = who_is_this (logged->b_data, logged->b_size);
+ if (who != THE_LEAF && who != HAS_IH_ARRAY) {
+ brelse (logged);
+ brelse (in_place);
+ continue;
+ }
+
+ reiserfs_warning (stdout, "%s\n", which_block (who));
+ if (data (fs)->JJ > 1) {
+ /* overwrite in-place block with a logged version */
+ if (who_is_this (in_place->b_data, in_place->b_size) == THE_LEAF)
+ reiserfs_warning (stderr, "Block %d is leaf already, skip it\n",
+ in_place->b_blocknr);
+ else {
+ memcpy (in_place->b_data, logged->b_data, fs->fs_blocksize);
+ mark_buffer_dirty (in_place);
+ bwrite (in_place);
+ if (input_bitmap (fs))
+ reiserfs_bitmap_set_bit (input_bitmap (fs), in_place->b_blocknr);
+ }
+ }
+
+ brelse (logged);
+ brelse (in_place);
+ }
+ }
+ }
+
+ brelse (d_bh);
+ brelse (c_bh);
+}
+
+/* go through all transactions in the journal to check whether block is there */
+static void find_in_journal (reiserfs_filsys_t * fs)
+{
+ for_each_transaction (fs, look_in_transaction);
+}
+#endif
+
+#define BLOCK_IN_Q 12762
+
+static void check_block_9555 (reiserfs_filsys_t * fs, reiserfs_trans_t * trans,
+ int index,
+ unsigned long in_journal, unsigned long in_place)
+{
+ struct buffer_head * bh;
+
+
+ if (in_place == 17) {
+ /* read block of journal which contains block 17 abd check whether bit
+ BLOCK_IN_Q is set */
+ bh = bread (fs->fs_journal_dev, in_journal, fs->fs_blocksize);
+ if (!bh) {
+ reiserfs_warning (stderr, "could not read block %lu (of journal area)\n",
+ in_journal);
+ return;
+ }
+
+ if (test_bit (BLOCK_IN_Q, bh->b_data))
+ reiserfs_warning (stdout, "trans %lu, pos %d - block 17: block %d is marked used in it\n",
+ trans->trans_id, index, BLOCK_IN_Q);
+ else
+ reiserfs_warning (stdout, "trans %lu, pos %d - block 17: block %d is marked free in it\n",
+ trans->trans_id, index, BLOCK_IN_Q);
+ brelse (bh);
+ }
+
+ if (in_place == BLOCK_IN_Q) {
+ reiserfs_warning (stdout, "trans %lu, block %d is logged at pos %d\n",
+ trans->trans_id, BLOCK_IN_Q, index);
+ }
+}
+
+
+/* remove when the problem is found */
+static void check_transaction (reiserfs_filsys_t * fs, reiserfs_trans_t * trans)
+{
+ for_each_block (fs, trans, check_block_9555);
+}
+
+
+void scan_journal (reiserfs_filsys_t * fs)
+{
+ for_each_transaction (fs, check_transaction);
+}
+
+
+
+#if 0
+/* read block numbers from stdin, look for them in the journal, and (if -JJ is
+ given) write then "in-place" amd mark overwritten blocks used in the bitmap
+ specified with -b */
+void scan_journal (reiserfs_filsys_t * fs)
+{
+ char * str = 0;
+ size_t n = 0;
+
+
+ /* store all blocks which come from stdin */
+ while (1) {
+ if (getline (&str, &n, stdin) == -1)
+ break;
+ if (!strcmp (str, "\n"))
+ break;
+ str [strlen (str) - 1] = 0;
+
+ badblocks = realloc (badblocks, (badblocks_nr + 1) * 4);
+ if (!badblocks)
+ reiserfs_panic ("realloc failed");
+ badblocks [badblocks_nr ++] = atol (str);
+
+ free (str);
+ str = 0;
+ n = 0;
+ }
+
+ if (data (fs)->JJ > 1)
+ reiserfs_reopen (fs, O_RDWR);
+ reiserfs_warning (stdout, "%d blocks given\n", badblocks_nr); fflush (stdout);
+ find_in_journal (fs);
+
+ if (data (fs)->JJ > 1 && input_bitmap (fs)) {
+ FILE * fp;
+
+ fp = fopen (input_bitmap_file_name (fs), "w+");
+ if (!fp) {
+ reiserfs_warning (stderr, "reiserfs_bitmap_save: could not save bitmap in %s: %m",
+ input_bitmap_file_name (fs));
+ return;
+ }
+ reiserfs_bitmap_save (fp, input_bitmap (fs));
+ fclose (fp);
+ }
+}
+#endif
diff --git a/debugreiserfs/pack.c b/debugreiserfs/pack.c
index e40b204..87f0051 100644
--- a/debugreiserfs/pack.c
+++ b/debugreiserfs/pack.c
@@ -1,66 +1,123 @@
+
/*
- * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
+ * Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
*/
#include "debugreiserfs.h"
+/* counters for each kind of blocks */
+int packed,
+ packed_leaves,
+ full_blocks,
+ having_ih_array, /* blocks with broken block head */
+ bad_leaves, /* failed to compress */
+ internals,
+ descs,
+ others;
+
+reiserfs_bitmap_t * what_to_pack;
+/* these are to calculate compression */
+unsigned long sent_bytes; /* how many bytes sent to stdout */
+unsigned long had_to_be_sent; /* how many bytes were to be sent */
-reiserfs_bitmap_t what_to_pack;
-reiserfs_bitmap_t what_packed;
-int packed_leaves, bad_leaves, full_blocks, internals, descs, full_of_journal;
+inline void set_pi_type( struct packed_item *pi, __u32 val )
+{
+ set_bit_field_XX (32, pi, val, 0, 2);
+}
-/* these are to calculate compression */
-unsigned long sent; /* how many bytes sent to stdout */
-unsigned long had_to_be_sent; /* how many bytes were to be sent */
+inline __u32 get_pi_type( const struct packed_item *pi )
+{
+ get_bit_field_XX (32, pi, 0, 2);
+}
+
+
+inline void set_pi_mask( struct packed_item *pi, __u32 val )
+{
+ set_bit_field_XX (32, pi, val, 2, 18);
+}
+
+
+__u32 get_pi_mask( const struct packed_item *pi )
+{
+ get_bit_field_XX (32, pi, 2, 18);
+}
+
+
+inline void set_pi_item_len( struct packed_item *pi, __u32 val )
+{
+ set_bit_field_XX (32, pi, val, 20, 12);
+}
+inline __u32 get_pi_item_len( const struct packed_item *pi )
+{
+ get_bit_field_XX (32, pi, 20, 12);
+}
+
-static void pack_key (struct packed_item * pi, struct item_head * ih)
+static void pack_ih (struct packed_item * pi, struct item_head * ih)
{
- if (pi->mask & DIR_ID) {
- fwrite32 (&ih->ih_key.k_dir_id);
- sent += sizeof (__u32);
+ __u32 v32;
+ __u16 v16;
+
+ /* send packed item head first */
+ fwrite (pi, sizeof (*pi), 1, stdout);
+ sent_bytes += sizeof (*pi);
+
+ /* sen key components which are to be sent */
+ if (get_pi_mask(pi) & DIR_ID) {
+ v32 = get_key_dirid (&ih->ih_key);
+ fwrite_le32 (&v32);
}
- if (pi->mask & OBJECT_ID) {
- fwrite32 (&ih->ih_key.k_objectid);
- sent += sizeof (__u32);
+ if (get_pi_mask(pi) & OBJECT_ID) {
+ v32 = get_key_objectid (&ih->ih_key);
+ fwrite_le32 (&v32);
}
- if (pi->mask & OFFSET_BITS_64) {
+ if (get_pi_mask(pi) & OFFSET_BITS_64) {
__u64 offset;
offset = get_offset (&ih->ih_key);
- fwrite64 (&offset);
- sent += sizeof (__u64);
+ fwrite_le64 (&offset);
}
- if (pi->mask & OFFSET_BITS_32) {
+ if (get_pi_mask(pi) & OFFSET_BITS_32) {
__u32 offset;
offset = get_offset (&ih->ih_key);
- fwrite32 (&offset);
- sent += sizeof (__u32);
+ fwrite_le32 (&offset);
+ }
+
+ if (get_pi_mask(pi) & IH_FREE_SPACE) {
+ v16 = get_ih_entry_count (ih);
+ fwrite_le16 (&v16);
+ }
+
+ if (get_pi_mask(pi) & IH_FORMAT) {
+ /* fixme */
+ fwrite16 (&ih->ih_format);
}
}
static void pack_direct (struct packed_item * pi, struct buffer_head * bh,
- struct item_head * ih)
+ struct item_head * ih)
{
- pi->mask |= DIRECT_ITEM;
+ if (get_ih_free_space (ih) != 0xffff)
+ /* ih_free_space has unexpected value */
+ set_pi_mask (pi, get_pi_mask (pi) | IH_FREE_SPACE);
+
+ if (get_pi_mask(pi) & SAFE_LINK)
+ set_key_dirid(&ih->ih_key, le32_to_cpu(*(__u32 *)B_I_PITEM (bh, ih)) );
- /* send packed item header to stdout */
- fwrite (pi, sizeof (*pi), 1, stdout);
- sent += sizeof (*pi);
-
/* send key components which are to be sent */
- pack_key (pi, ih);
+ pack_ih (pi, ih);
}
@@ -70,8 +127,8 @@ static int should_pack_indirect (__u32 * ind_item, int unfm_num)
int i, len;
for (i = 1, len = 1; i < unfm_num; i ++) {
- if ((!ind_item [i] && !ind_item [i - 1]) || /* hole continues */
- ind_item [i] == ind_item [i - 1] + 1) { /* subsequent blocks */
+ if ((ind_item [i] == 0 && ind_item [i - 1] == 0) || /* hole continues */
+ le32_to_cpu (ind_item [i]) == le32_to_cpu (ind_item [i - 1]) + 1) { /* subsequent blocks */
len ++;
if (len > 2)
return 1;
@@ -94,50 +151,42 @@ static void pack_indirect (struct packed_item * pi, struct buffer_head * bh,
__u32 * ind_item;
__u16 len;
- pi->mask |= INDIRECT_ITEM;
- if (ih_entry_count (ih))
- pi->mask |= ENTRY_COUNT;
-
+
+ if (get_ih_entry_count (ih))
+ set_pi_mask (pi, get_pi_mask (pi) | IH_FREE_SPACE);
+
ind_item = (__u32 *)B_I_PITEM (bh, ih);
if (!should_pack_indirect (ind_item, I_UNFM_NUM (ih)))
- pi->mask |= WHOLE_INDIRECT;
-
- /* send packed item header to stdout */
- fwrite (pi, sizeof (*pi), 1, stdout);
- sent += sizeof (*pi);
+ set_pi_mask (pi, get_pi_mask (pi) | WHOLE_INDIRECT);
- /* send key components which are to be sent */
- pack_key (pi, ih);
- if (pi->mask & ENTRY_COUNT) {
- __u16 ih_free_space;
+ if (get_pi_mask(pi) & SAFE_LINK)
+ set_key_dirid(&ih->ih_key, le32_to_cpu(*ind_item) );
- ih_free_space = ih_entry_count (ih);
- fwrite16 (&ih_free_space);
- sent += sizeof (__u16);
- }
+ pack_ih (pi, ih);
+
+ if (get_pi_mask(pi) & SAFE_LINK)
+ return;
- if (pi->mask & WHOLE_INDIRECT) {
- fwrite (ind_item, ih_item_len (ih), 1, stdout);
- sent += ih_item_len (ih);
+ if (get_pi_mask(pi) & WHOLE_INDIRECT) {
+ fwrite (ind_item, get_ih_item_len (ih), 1, stdout);
+ sent_bytes += get_ih_item_len (ih);
return;
}
fwrite32 (&ind_item [0]);
- sent += sizeof (__u32);
+
for (i = 1, len = 1; i < I_UNFM_NUM (ih); i ++) {
- if ((!ind_item [i] && !ind_item [i - 1]) || /* hole continues */
+ if ((ind_item [i] == 0 && ind_item [i - 1] == 0) || /* hole continues */
ind_item [i] == ind_item[ i - 1] + 1) { /* subsequent blocks */
len ++;
} else {
- fwrite16 (&len);
+ fwrite_le16 (&len);
fwrite32 (&ind_item[i]);
- sent += (sizeof (__u32) + sizeof (__u16));
len = 1;
}
}
- fwrite16 (&len);
- sent += sizeof (__u16);
+ fwrite_le16 (&len);
return;
}
@@ -154,7 +203,7 @@ static void pack_indirect (struct packed_item * pi, struct buffer_head * bh,
maybe gencounter (16)
maybe deh_state (16)
*/
-static void pack_direntry (reiserfs_filsys_t fs, struct packed_item * pi,
+static void pack_direntry (reiserfs_filsys_t * fs, struct packed_item * pi,
struct buffer_head * bh,
struct item_head * ih)
{
@@ -164,56 +213,45 @@ static void pack_direntry (reiserfs_filsys_t fs, struct packed_item * pi,
__u16 entry_count, gen_counter;
- pi->mask |= (DIRENTRY_ITEM | ENTRY_COUNT);
-
- /* send packed item header to stdout */
- fwrite (pi, sizeof (*pi), 1, stdout);
- sent += sizeof (*pi);
+ set_pi_mask (pi, get_pi_mask (pi) | IH_ENTRY_COUNT);
- /* send key components which are to be sent */
- pack_key (pi, ih);
+ /* send item_head components which are to be sent */
+ pack_ih (pi, ih);
/* entry count is sent unconditionally */
- entry_count = ih_entry_count (ih);
- fwrite16 (&entry_count);
+ entry_count = get_ih_entry_count (ih);
deh = B_I_DEH (bh, ih);
for (i = 0; i < entry_count; i ++, deh ++) {
pe.entrylen = entry_length (ih, deh, i);
pe.mask = 0;
- if (deh_dir_id (deh) != le32_to_cpu (ih->ih_key.k_objectid))
+ if (get_deh_dirid (deh) != get_key_objectid (&ih->ih_key))
/* entry points to name of another directory, store deh_dir_id */
pe.mask |= HAS_DIR_ID;
- gen_counter = GET_GENERATION_NUMBER (deh_offset (deh));
+ gen_counter = GET_GENERATION_NUMBER (get_deh_offset (deh));
if (gen_counter != 0)
/* store generation counter if it is != 0 */
pe.mask |= HAS_GEN_COUNTER;
- if (le16_to_cpu (deh->deh_state) != 4)
+ if (get_deh_state (deh) != 4)
/* something unusual in deh_state. Store it */
pe.mask |= HAS_STATE;
fwrite8 (&pe.mask);
- fwrite16 (&pe.entrylen);
+ fwrite_le16 (&pe.entrylen);
fwrite (name_in_entry (deh, i), pe.entrylen, 1, stdout);
- fwrite32 (&(deh->deh_objectid));
- sent += (sizeof (__u8) + sizeof (__u16) + pe.entrylen + sizeof (__u32));
+ sent_bytes += pe.entrylen;
+ fwrite32 (&(deh->deh2_objectid));
- if (pe.mask & HAS_DIR_ID) {
- fwrite32 (&deh->deh_dir_id);
- sent += sizeof (__u32);
- }
+ if (pe.mask & HAS_DIR_ID)
+ fwrite32 (&deh->deh2_dir_id);
- if (pe.mask & HAS_GEN_COUNTER) {
- fwrite16 (&gen_counter);
- sent += sizeof (__u16);
- }
+ if (pe.mask & HAS_GEN_COUNTER)
+ fwrite_le16 (&gen_counter);
- if (pe.mask & HAS_STATE) {
- fwrite16 (&deh->deh_state);
- sent += sizeof (__u16);
- }
+ if (pe.mask & HAS_STATE)
+ fwrite16 (&deh->deh2_state);
}
}
@@ -221,7 +259,9 @@ static void pack_direntry (reiserfs_filsys_t fs, struct packed_item * pi,
static void pack_stat_data (struct packed_item * pi, struct buffer_head * bh,
struct item_head * ih)
{
- pi->mask |= STAT_DATA_ITEM;
+ if (get_ih_free_space (ih) != 0xffff)
+ /* ih_free_space has unexpected value */
+ set_pi_mask (pi, get_pi_mask (pi) | IH_FREE_SPACE);
if (stat_data_v1 (ih)) {
/* for old stat data: we take
@@ -234,25 +274,19 @@ static void pack_stat_data (struct packed_item * pi, struct buffer_head * bh,
struct stat_data_v1 * sd_v1;
sd_v1 = (struct stat_data_v1 *)B_I_PITEM (bh, ih);
- if (sd_v1->sd_first_direct_byte != 0xffffffff)
- pi->mask |= WITH_SD_FIRST_DIRECT_BYTE;
+ if (sd_v1->sd_first_direct_byte != 0xffffffff) /* ok if -1 */
+ set_pi_mask (pi, get_pi_mask (pi) | WITH_SD_FIRST_DIRECT_BYTE);
- /* we are done with packed_item send packed it to stdout */
- fwrite (pi, sizeof (*pi), 1, stdout);
- sent += sizeof (*pi);
-
- /* send key components which are to be sent */
- pack_key (pi, ih);
+
+ pack_ih (pi, ih);
fwrite16 (&sd_v1->sd_mode);
fwrite16 (&sd_v1->sd_nlink);
fwrite32 (&sd_v1->sd_size);
fwrite32 (&sd_v1->u.sd_blocks);
- sent += (sizeof (__u16) * 2 + sizeof (__u32) * 2);
- if (pi->mask & WITH_SD_FIRST_DIRECT_BYTE) {
+
+ if (get_pi_mask(pi) & WITH_SD_FIRST_DIRECT_BYTE)
fwrite32 (&sd_v1->sd_first_direct_byte);
- sent += sizeof (__u32);
- }
} else {
/* for new stat data
mode - 16 bits
@@ -261,85 +295,75 @@ static void pack_stat_data (struct packed_item * pi, struct buffer_head * bh,
blocks - 32 bits
*/
struct stat_data * sd;
+ /* these will maintain disk-order values */
__u16 nlink16;
__u32 nlink32, size32;
__u64 size64;
sd = (struct stat_data *)B_I_PITEM (bh, ih);
- if (sd->sd_nlink > 0xffff) {
- pi->mask |= NLINK_BITS_32;
+ if (sd_v2_nlink (sd) > 0xffff) {
+ set_pi_mask (pi, get_pi_mask (pi) | NLINK_BITS_32);
nlink32 = sd->sd_nlink;
} else {
- nlink16 = sd->sd_nlink;
+ /* This is required to deal w/ big endian systems */
+ nlink16 = cpu_to_le16 ((__u16)sd_v2_nlink (sd));
}
- if (sd->sd_size > 0xffffffff) {
- pi->mask |= SIZE_BITS_64;
+ if (sd_v2_size (sd) > 0xffffffff) {
+ set_pi_mask (pi, get_pi_mask (pi) | SIZE_BITS_64);
size64 = sd->sd_size;
} else {
- size32 = sd->sd_size;
+ /* This is required to deal w/ big endian systems */
+ size32 = cpu_to_le32 ((__u32)sd_v2_size (sd));
}
- /* we are done with packed_item send packed it to stdout */
- fwrite (pi, sizeof (*pi), 1, stdout);
- sent += sizeof (*pi);
- /* send key components which are to be sent */
- pack_key (pi, ih);
+ pack_ih (pi, ih);
fwrite16 (&sd->sd_mode);
- sent += sizeof (__u16);
- if (pi->mask & NLINK_BITS_32) {
+
+ if (get_pi_mask (pi) & NLINK_BITS_32) {
fwrite32 (&nlink32);
- sent += sizeof (__u32);
} else {
fwrite16 (&nlink16);
- sent += sizeof (__u16);
}
- if (pi->mask & SIZE_BITS_64) {
+ if (get_pi_mask (pi) & SIZE_BITS_64) {
fwrite64 (&size64);
- sent += sizeof (__u64);
} else {
fwrite32 (&size32);
- sent += sizeof (__u32);
}
fwrite32 (&sd->sd_blocks);
- sent += sizeof (__u32);
}
}
-static void pack_full_block (reiserfs_filsys_t fs, struct buffer_head * bh)
+static void pack_full_block (reiserfs_filsys_t * fs, struct buffer_head * bh)
{
__u16 magic;
__u32 block;
+
magic = FULL_BLOCK_START_MAGIC;
- fwrite16 (&magic);
+ fwrite_le16 (&magic);
block = bh->b_blocknr;
- fwrite32 (&block);
+ fwrite_le32 (&block);
- fwrite (bh->b_data, 4096, 1, stdout);
- sent += 4096;
- had_to_be_sent += 4096;
+ fwrite (bh->b_data, fs->fs_blocksize, 1, stdout);
+
+ sent_bytes += fs->fs_blocksize;
+ had_to_be_sent += fs->fs_blocksize;
full_blocks ++;
-
- if (who_is_this (bh->b_data, bh->b_size) == THE_JDESC)
- descs ++;
- if (who_is_this (bh->b_data, bh->b_size) == THE_INTERNAL)
- internals ++;
- if (block_of_journal (fs, bh->b_blocknr))
- full_of_journal ++;
}
+#if 0
/* unformatted node pointer is considered bad when it points either to blocks
of journal, bitmap blocks, super block or is transparently out of range of
disk block numbers */
-static int check_unfm_ptr (reiserfs_filsys_t fs, __u32 block)
+static int check_unfm_ptr (reiserfs_filsys_t * fs, __u32 block)
{
if (block >= SB_BLOCK_COUNT (fs))
return 1;
@@ -349,17 +373,17 @@ static int check_unfm_ptr (reiserfs_filsys_t fs, __u32 block)
return 0;
}
-
+#endif
/* we only pack leaves which do not have any corruptions */
-static int can_pack_leaf (reiserfs_filsys_t fs, struct buffer_head * bh)
+static int can_pack_leaf (reiserfs_filsys_t * fs, struct buffer_head * bh)
{
int i;
struct item_head * ih;
ih = B_N_PITEM_HEAD (bh, 0);
- for (i = 0; i < node_item_number (bh); i ++, ih ++) {
- if (is_it_bad_item (fs, ih, B_I_PITEM (bh, ih), check_unfm_ptr, 1/*bad dir*/))
+ for (i = 0; i < get_blkh_nr_items (B_BLK_HEAD (bh)); i ++, ih ++) {
+ if (is_it_bad_item (fs, ih, B_I_PITEM (bh, ih), 0/*check_unfm_ptr*/, 1/*bad dir*/))
return 0;
}
return 1;
@@ -369,7 +393,7 @@ static int can_pack_leaf (reiserfs_filsys_t fs, struct buffer_head * bh)
/* pack leaf only if all its items are correct: keys are correct,
direntries are hashed properly and hash function is defined,
indirect items are correct, stat data ?, */
-static void pack_leaf (reiserfs_filsys_t fs, struct buffer_head * bh)
+static void pack_leaf (reiserfs_filsys_t * fs, struct buffer_head * bh)
{
int i;
struct item_head * ih;
@@ -377,60 +401,81 @@ static void pack_leaf (reiserfs_filsys_t fs, struct buffer_head * bh)
__u16 v16;
if (!can_pack_leaf (fs, bh)) {
- /* if something looks suspicious in this leaf - pack whole block */
- pack_full_block (fs, bh);
- fprintf (stderr, "leaf %lu is bad\n", bh->b_blocknr);
+ /* something looks suspicious in this leaf - pack whole block */
bad_leaves ++;
+ pack_full_block (fs, bh);
return;
}
+
/* start magic in low 8 bits, hash code in high 8 bits */
- v16 = (LEAF_START_MAGIC | (func2code (fs->s_hash_function) << 8));
- fwrite16 (&v16);
+ v16 = (LEAF_START_MAGIC | (func2code (fs->fs_hash_function) << 8));
+ fwrite_le16 (&v16);
/* block number */
- fwrite32 (&bh->b_blocknr);
+ fwrite_le32 (&bh->b_blocknr);
/* item number */
- v16 = node_item_number (bh);
- fwrite16 (&v16);
+ v16 = get_blkh_nr_items (B_BLK_HEAD (bh));
+ fwrite_le16 (&v16);
ih = B_N_PITEM_HEAD (bh, 0);
- for (i = 0; i < node_item_number (bh); i ++, ih ++) {
+ for (i = 0; i < v16; i ++, ih ++) {
#if 0
v32 = ITEM_START_MAGIC;
fwrite32 (&v32);
#endif
- pi.mask = 0;
- pi.item_len = ih_item_len (ih);
+ set_pi_mask (&pi, 0);
+ set_pi_item_len (&pi, get_ih_item_len (ih));
+ set_pi_type (&pi, get_type (&ih->ih_key));
// format
- if (ih_key_format (ih) == KEY_FORMAT_2)
- pi.mask |= NEW_FORMAT;
+ if (get_ih_key_format (ih) == KEY_FORMAT_2)
+ set_pi_mask( &pi, get_pi_mask(&pi) | NEW_FORMAT );
// k_dir_id
- if (!i || (i && ih->ih_key.k_dir_id != (ih - 1)->ih_key.k_dir_id)) {
+ if (!i || (i && get_key_dirid (&ih->ih_key) != get_key_dirid (&(ih - 1)->ih_key))) {
/* if item is first in the leaf or if previous item has different
k_dir_id - store it */
- pi.mask |= DIR_ID;
+ set_pi_mask (&pi, get_pi_mask (&pi) | DIR_ID);
}
// k_object_id
- if (!i || (i && ih->ih_key.k_objectid != (ih - 1)->ih_key.k_objectid)) {
+ if (!i || (i && get_key_objectid (&ih->ih_key) != get_key_objectid (&(ih - 1)->ih_key))) {
/* if item is first in the leaf or if previous item has different
k_objectid - store it */
- pi.mask |= OBJECT_ID;
+ set_pi_mask (&pi, get_pi_mask (&pi) | OBJECT_ID);
}
/* store offset if it is != 0 in 32 or 64 bits */
if (get_offset (&ih->ih_key)) {
- if (get_offset (&ih->ih_key) > 0xffffffffULL)
- pi.mask |= OFFSET_BITS_64;
- else
- pi.mask |= OFFSET_BITS_32;
+ int send_offset = 1;
+
+ if ((get_pi_mask (&pi) & DIR_ID) == 0 && (get_pi_mask (&pi) & OBJECT_ID) == 0) {
+ /* previous item is of the same object, so try to avoid
+ sending k_offset */
+ if ((is_stat_data_ih (ih - 1) && get_offset (&ih->ih_key) == 1) ||
+ (is_indirect_ih (ih - 1) && is_direct_ih (ih) &&
+ get_offset (&(ih - 1)->ih_key) + get_bytes_number (ih - 1, fs->fs_blocksize) == get_offset (&ih->ih_key)))
+ /* unpack can calculate offset itself */
+ send_offset = 0;
+ }
+ if (send_offset) {
+ if (get_offset (&ih->ih_key) > 0xffffffffULL)
+ set_pi_mask (&pi, get_pi_mask (&pi) | OFFSET_BITS_64);
+ else
+ set_pi_mask (&pi, get_pi_mask (&pi) | OFFSET_BITS_32);
+ }
}
+ /* ih key format is correct, check fsck_need field */
+ if (get_ih_flags (ih))
+ set_pi_mask (&pi, get_pi_mask (&pi) | IH_FORMAT);
+
+ if ((get_key_dirid (&ih->ih_key) == (__u32)-1) && (get_ih_item_len (ih) == 4))
+ set_pi_mask (&pi, get_pi_mask (&pi) | SAFE_LINK);
+
if (is_direct_ih (ih)) {
pack_direct (&pi, bh, ih);
} else if (is_indirect_ih (ih))
@@ -448,24 +493,26 @@ static void pack_leaf (reiserfs_filsys_t fs, struct buffer_head * bh)
}
v16 = LEAF_END_MAGIC;
- fwrite16 (&v16);
+ fwrite_le16 (&v16);
+
+ had_to_be_sent += fs->fs_blocksize;
packed_leaves ++;
- had_to_be_sent += 4096;
return;
}
-static int can_pack_internal (reiserfs_filsys_t fs, struct buffer_head * bh)
+static int can_pack_internal (reiserfs_filsys_t * fs, struct buffer_head * bh)
{
return 0;
}
/* pack internal node as a full block */
-static void pack_internal (reiserfs_filsys_t fs, struct buffer_head * bh)
+static void pack_internal (reiserfs_filsys_t * fs, struct buffer_head * bh)
{
+ internals ++;
if (!can_pack_internal (fs, bh)) {
pack_full_block (fs, bh);
return;
@@ -475,83 +522,132 @@ static void pack_internal (reiserfs_filsys_t fs, struct buffer_head * bh)
}
-static int how_many_to_pack (reiserfs_filsys_t fs, unsigned long first, int count)
-{
- int i;
- int used;
-
- used = 0;
- for (i = 0; i < count; i ++) {
- if ((SB_BLOCK_COUNT (fs) > (first + i)) &&
- reiserfs_bitmap_test_bit (what_to_pack, first + i))
- used ++;
- }
- return used;
-}
-
-
/* packed blocks are marked free in the bitmap*/
-static void send_block (reiserfs_filsys_t fs, struct buffer_head * bh)
+static void send_block (reiserfs_filsys_t * fs, struct buffer_head * bh, int send_unknown)
{
int type;
+ packed ++;
+ type = who_is_this (bh->b_data, bh->b_size);
+ switch (type) {
+ case THE_LEAF:
+ pack_leaf (fs, bh);
+ break;
- if ((type = who_is_this (bh->b_data, bh->b_size)) != THE_LEAF) {
- if (type == THE_INTERNAL) {
- pack_internal (fs, bh);
- } else if (!not_data_block (fs, bh->b_blocknr)) {
- /* unformatted */
- return;
- } else
- /* bitmaps, super block, blocks of journal - not leaves */
+ case HAS_IH_ARRAY:
+ having_ih_array ++;
+ fprintf (stderr, "BROKEN BLOCK HEAD %lu\n", bh->b_blocknr);
+ pack_full_block (fs, bh);
+ break;
+
+ case THE_INTERNAL:
+ pack_internal (fs, bh);
+ break;
+
+ default:
+ if (send_unknown)
pack_full_block (fs, bh);
- } else
- pack_leaf (fs, bh);
+ else
+ packed --;
+ break;
+ }
+
- reiserfs_bitmap_set_bit (what_packed, bh->b_blocknr);
+ /* do not send one block twice */
reiserfs_bitmap_clear_bit (what_to_pack, bh->b_blocknr);
}
/* super block, journal, bitmaps */
-static void pack_frozen_data (reiserfs_filsys_t fs)
+static void pack_frozen_data (reiserfs_filsys_t * fs)
{
int i;
struct buffer_head * bh;
-
+ unsigned long block;
+ __u16 magic16;
+ int sent_journal_start_magic = 0;
+
+ if (is_reiserfs_jr_magic_string(fs->fs_ondisk_sb) &&
+ get_jp_journal_dev(sb_jp(fs->fs_ondisk_sb)) &&
+ !journal_device_name(fs)) {
+ if (!user_confirmed (stderr,
+ "\n File system has non-standard journal "
+ "that hasn't been specified.\n"
+ "Continue packing without journal? [N/Yes] (note need to type Yes):", "Yes\n"))
+ exit (0);
+ }
+
/* super block */
reiserfs_warning (stderr, "super block..");fflush (stderr);
- send_block (fs, fs->s_sbh);
- reiserfs_warning (stderr, "ok\nbitmaps..(%d).. ", SB_BMAP_NR (fs));
+ send_block (fs, fs->fs_super_bh, 1/*send block even if its format is not determined */);
+ reiserfs_warning (stderr, "ok\nbitmaps..(%d).. ",
+ get_sb_bmap_nr (fs->fs_ondisk_sb));
fflush (stderr);
- /* bitmaps */
- for (i = 0; i < SB_BMAP_NR (fs); i ++) {
- send_block (fs, SB_AP_BITMAP (fs)[i]);
+ /* bitmaps */
+ block = fs->fs_super_bh->b_blocknr + 1;
+ for (i = 0; i < get_sb_bmap_nr (fs->fs_ondisk_sb); i ++) {
+ bh = bread (fs->fs_dev, block, fs->fs_blocksize);
+ if (!bh) {
+ fprintf (stderr, "pack_frozen_data: bread failed: %lu\n", block);
+ continue;
+ }
+ send_block (fs, bh, 1);
+ if (spread_bitmaps (fs))
+ block = (block / (fs->fs_blocksize * 8) + 1) * (fs->fs_blocksize * 8);
+ else
+ block ++;
+ brelse (bh);
}
+ /* journal */
+
+ if (get_jp_journal_dev (sb_jp (fs->fs_ondisk_sb))) {
+ /* non-standard journal is on a separate device */
+
+ if (journal_device_name (fs) && !reiserfs_journal_opened (fs))
+ die ("Specified journal is not available. Specify it correctly or "
+ "don't specify at all");
+ else if (!journal_device_name(fs))
+ /* non-standard journal was not specified (that confirmed by user) -
+ skipped packing journal */
+ return;
+ else {
+ magic16 = SEPARATED_JOURNAL_START_MAGIC;
+ fwrite_le16 (&magic16);
+ sent_journal_start_magic = 1;
+ }
+ }
+ block = get_jp_journal_1st_block (sb_jp (fs->fs_ondisk_sb));
reiserfs_warning (stderr, "ok\njournal (from %lu to %lu)..",
- rs_journal_start (fs->s_rs),
- rs_journal_start (fs->s_rs) + rs_journal_size (fs->s_rs));
+ block, block + get_jp_journal_size (sb_jp (fs->fs_ondisk_sb)));
fflush (stderr);
- /* journal */
- for (i = rs_journal_start (fs->s_rs);
- i <= rs_journal_start (fs->s_rs) + rs_journal_size (fs->s_rs);
- i ++) {
- bh = bread (fs->s_dev, i, fs->s_blocksize);
- send_block (fs, bh);
+ for (i = 0; i <= get_jp_journal_size (sb_jp (fs->fs_ondisk_sb)); i ++) {
+ bh = bread (fs->fs_journal_dev, block + i, fs->fs_blocksize);
+ if (!bh) {
+ reiserfs_warning (stderr, "could not read %lu, skipped\n", i);
+ continue;
+ }
+
+ send_block (fs, bh, 1);
brelse (bh);
}
+ if (sent_journal_start_magic) {
+ magic16 = SEPARATED_JOURNAL_END_MAGIC;
+ fwrite_le16 (&magic16);
+ }
reiserfs_warning (stderr, "ok\n");fflush (stderr);
+ reiserfs_warning (stderr,
+ "Super block, bitmaps, journal - %d blocks - done, %d blocks left\n",
+ packed, reiserfs_bitmap_ones (what_to_pack));
}
/* pack all "not data blocks" and correct leaf */
-void pack_partition (reiserfs_filsys_t fs)
+void pack_partition (reiserfs_filsys_t * fs)
{
- int i, j;
- struct buffer_head tmp, * bh;
- int nr_to_read = BLOCKS_PER_READ;
+ int i;
+ struct buffer_head * bh;
__u32 magic32;
__u16 blocksize;
__u16 magic16;
@@ -559,94 +655,61 @@ void pack_partition (reiserfs_filsys_t fs)
magic32 = REISERFS_SUPER_MAGIC;
- fwrite32 (&magic32);
-
- blocksize = fs->s_blocksize;
- fwrite16 (&blocksize);
+ fwrite_le32 (&magic32);
- tmp.b_size = blocksize;
+ blocksize = fs->fs_blocksize;
+ fwrite_le16 (&blocksize);
- /* will save information about what packed here */
- what_packed = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
-
- /* will get information about what is to be packed */
- what_to_pack = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
- if (!what_to_pack)
- die ("pack_partition: could not create bitmap");
- if (mode == DO_PACK) {
- /* read blocks marked used and pack them */
- reiserfs_fetch_disk_bitmap (what_to_pack, fs);
- reiserfs_warning (stderr, "Packing blocks marked used on the device %d\n",
- reiserfs_bitmap_ones (what_to_pack));
- } else {
- reiserfs_bitmap_fill (what_to_pack);
- reiserfs_warning (stderr, "Packing all blocks of the device %d\n",
- reiserfs_bitmap_ones (what_to_pack));
- }
+
+ /* will get information about what is to be packed. Bits corresponding to
+ packed blocks will be cleared */
+ what_to_pack = input_bitmap(fs);
/* super block, journal, bitmaps */
pack_frozen_data (fs);
- reiserfs_warning (stderr,
- "Super block, bitmaps, journal - %d blocks - done, %d blocks left\n",
- reiserfs_bitmap_ones (what_packed), reiserfs_bitmap_ones (what_to_pack));
+
+ /* what's left */
total = reiserfs_bitmap_ones (what_to_pack);
- for (i = 0; i < SB_BLOCK_COUNT (fs); i += nr_to_read) {
- int to_pack;
-
- to_pack = how_many_to_pack (fs, i, nr_to_read);
- if (to_pack) {
- print_how_far (&done, total, to_pack, opt_quiet);
-
- bh = bread (fs->s_dev, i / nr_to_read, blocksize * nr_to_read);
- if (bh) {
- for (j = 0; j < nr_to_read; j ++) {
- if (reiserfs_bitmap_test_bit (what_to_pack, i + j)) {
- tmp.b_data = bh->b_data + j * tmp.b_size;
- tmp.b_blocknr = i + j;
- send_block (fs, &tmp);
- }
- }
- brelse (bh);
- } else {
- /* bread failed */
- if (nr_to_read != 1) {
- /* we tryied to read bunch of blocks. Try to read them by one */
- nr_to_read = 1;
- i --;
- continue;
- } else {
- /* we were reading one block at time, and failed, so mark
- block bad */
- reiserfs_warning (stderr, "could not read block %lu\n", i);
- }
- }
+ for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) {
+ if (!reiserfs_bitmap_test_bit (what_to_pack, i))
+ continue;
+
+ print_how_far (stderr, &done, total, 1, be_quiet (fs));
+
+ bh = bread (fs->fs_dev, i, blocksize);
+ if (!bh) {
+ reiserfs_warning (stderr, "could not read block %lu\n", i);
+ continue;
}
+
+ send_block (fs, bh, 0/*do not send block of not determined format */);
+ brelse (bh);
}
-
+
magic16 = END_MAGIC;
- fwrite16 (&magic16);
-
- fprintf (stderr, "Packed\n\tleaves %d\n"
+ fwrite_le16 (&magic16);
+
+ fprintf (stderr, "\nPacked %d blocks:\n"
+ "\tcompessed %d\n"
"\tfull blocks %d\n"
- "\t\tof journal %d\n"
+ "\t\tleaves with broken block head %d\n"
"\t\tcorrupted leaves %d\n"
"\t\tinternals %d\n"
"\t\tdescriptors %d\n",
- packed_leaves, full_blocks, full_of_journal, bad_leaves, internals, descs);
- fprintf (stderr, "data packed with ratio %.2f\n", (double)sent / had_to_be_sent);
+ packed,
+ packed_leaves, full_blocks, having_ih_array,
+ bad_leaves, internals, descs);
- if (where_to_save)
- reiserfs_bitmap_save (where_to_save, what_packed);
+ fprintf (stderr, "data packed with ratio %.2f\n", (double)sent_bytes / had_to_be_sent);
}
-
-void pack_one_block (reiserfs_filsys_t fs, unsigned long block)
+void pack_one_block (reiserfs_filsys_t * fs, unsigned long block)
{
__u32 magic32;
__u16 magic16;
@@ -654,12 +717,12 @@ void pack_one_block (reiserfs_filsys_t fs, unsigned long block)
// reiserfs magic
magic32 = REISERFS_SUPER_MAGIC;
- fwrite32 (&magic32);
+ fwrite_le32 (&magic32);
// blocksize
- fwrite16 (&fs->s_blocksize);
+ fwrite_le16 (&fs->fs_blocksize);
- bh = bread (fs->s_dev, block, fs->s_blocksize);
+ bh = bread (fs->fs_dev, block, fs->fs_blocksize);
if (who_is_this (bh->b_data, bh->b_size) == THE_LEAF)
pack_leaf (fs, bh);
@@ -670,10 +733,9 @@ void pack_one_block (reiserfs_filsys_t fs, unsigned long block)
// end magic
magic16 = END_MAGIC;
- fwrite16 (&magic16);
+ fwrite_le16 (&magic16);
- fprintf (stderr, "Packed\n\tleaves %d\n\tfull block %d\n\tcorrupted leaves %d\n",
- packed_leaves, full_blocks, bad_leaves);
+ fprintf (stderr, "Done\n");
}
@@ -682,7 +744,7 @@ void pack_one_block (reiserfs_filsys_t fs, unsigned long block)
// this test program has two modes: 'pack file blocknr'
// and 'unpack file'
// in the first mode blocknr-th 4k block of the 'file' will be packed out to stdout
-// the the second mode standart input will be converted to the reiserfs leaf on 'file'
+// the the second mode standard input will be converted to the reiserfs leaf on 'file'
//
static int do_unpack (char * file)
{
@@ -714,7 +776,7 @@ static int do_unpack (char * file)
return 0;
}
-static int do_pack (char * file, int block)
+static int do_pack (char * file, unsigned long block)
{
int fd;
struct buffer_head * bh;
@@ -762,4 +824,7 @@ int main (int argc, char ** argv)
return 0;
}
-#endif
+#endif /* 0 */
+
+
+
diff --git a/debugreiserfs/recover.c b/debugreiserfs/recover.c
new file mode 100644
index 0000000..ce476b9
--- /dev/null
+++ b/debugreiserfs/recover.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
+ */
+
+#include "debugreiserfs.h"
+
+
+#if 0
+
+/* this reads stdin and recover file of given key: */
+/* the input has to be in the follwong format:
+ K dirid objectid
+ N name
+ B blocknumber
+ ..
+ then recover_file will read every block, look there specified file and put it into
+*/
+void do_recover (reiserfs_filsys_t fs)
+{
+ char name [100];
+ char * line = 0;
+ int n = 0;
+ int fd;
+ struct key key = {0, 0, };
+ struct buffer_head * bh;
+ struct item_head * ih;
+ unsigned long block;
+ char code;
+ loff_t recovered = 0;
+ int i, j;
+ reiserfs_bitmap_t bitmap;
+ int used, not_used;
+
+ bitmap = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
+ reiserfs_fetch_disk_bitmap (bitmap, fs);
+ /* we check how many blocks recoverd items point to are free or used */
+ used = 0;
+ not_used = 0;
+
+ fd = 0;
+ while (getline (&line, &n, stdin) != -1) {
+ if (line [0] == '#' || line [0] == '\n')
+ continue;
+ switch (line [0]) {
+ case 'K':
+ /* get a key of file which is to be recovered */
+ if (sscanf (line, "%c %u %u\n", &code, &key.k_dir_id, &key.k_objectid) != 3) {
+ die ("recover_file: wrong input K format");
+ }
+ printf ("Recovering file (%u, %u)\n", key.k_dir_id, key.k_objectid);
+ break;
+
+ case 'N':
+ /* get a file name */
+ recovered = 0;
+ if (sscanf (line, "%c %s\n", &code, name) != 2) {
+ die ("recover_file: wrong input N format");
+ }
+ fd = open (name, O_RDWR | O_CREAT | O_EXCL, 0644);
+ if (fd == -1)
+ die ("recover_file: could not create file %s: %s",
+ name,strerror (errno));
+ printf ("Recovering file %s..\n", name);
+ break;
+
+ case 'B':
+ if (!fd)
+ die ("recover_file: file name is not specified");
+ if (sscanf (line, "%c %lu\n", &code, &block) != 2) {
+ die ("recover_file: wrong input B format");
+ }
+ bh = bread (fs->s_dev, block, fs->s_blocksize);
+ if (!bh) {
+ printf ("reading block %lu failed\n", block);
+ continue;
+ }
+
+ printf ("working with block %lu..\n", block);
+
+ ih = B_N_PITEM_HEAD (bh, 0);
+ for (i = 0; i < node_item_number (bh); i ++, ih ++) {
+ __u32 * indirect;
+ struct buffer_head * tmp_bh;
+
+ if (!is_indirect_ih (ih) || key.k_dir_id != ih->ih_key.k_dir_id ||
+ key.k_objectid != ih->ih_key.k_objectid)
+ continue;
+
+ indirect = (__u32 *)B_I_PITEM (bh, ih);
+ for (j = 0; j < I_UNFM_NUM (ih); j ++) {
+ block = le32_to_cpu (indirect [j]);
+ if (!block)
+ continue;
+ tmp_bh = bread (fs->s_dev, block, fs->s_blocksize);
+ if (!tmp_bh) {
+ printf ("reading block %Lu failed\n", (loff_t)block * fs->s_blocksize);
+ continue;
+ }
+ if (lseek64 (fd, get_offset (&ih->ih_key) + j * fs->s_blocksize - 1,
+ SEEK_SET) == (loff_t)-1) {
+ printf ("llseek failed to pos %Ld\n", (loff_t)block * fs->s_blocksize);
+ brelse (tmp_bh);
+ continue;
+ }
+ if (reiserfs_bitmap_test_bit (bitmap, block))
+ used ++;
+ else
+ not_used ++;
+ /*printf ("block of file %Ld gets block %lu\n",
+ (get_offset (&ih->ih_key) - 1) / fs->s_blocksize + j, block);*/
+ if (write (fd, tmp_bh->b_data, tmp_bh->b_size) != tmp_bh->b_size) {
+ printf ("write failed to pos %Ld\n", (loff_t)block * fs->s_blocksize);
+ brelse (tmp_bh);
+ continue;
+ }
+ recovered += fs->s_blocksize;
+ brelse (tmp_bh);
+ }
+ }
+ brelse (bh);
+ break;
+ }
+ }
+ printf ("recover_file: %Ld bytes recovered of file %s, key %u %u, %d blocks are free and %d are used\n",
+ recovered, name, key.k_dir_id, key.k_objectid, not_used, used);
+}
+#endif
+
+
+
+/* read a file containing map of one or more files and either recover
+ them or just print info */
+static void read_map (FILE * fp)
+{
+ int i;
+ __u32 v32;
+ char * buf;
+ __u32 ids [4];
+ int do_recover = 0;
+
+
+ buf = 0;
+ while (1) {
+ if (fread (&v32, sizeof (v32), 1, fp) != 1)
+ break;
+ if (v32 != MAP_MAGIC)
+ reiserfs_panic ("read_map: no magic found");
+
+ /* device name length and name itself */
+ fread (&v32, sizeof (v32), 1, fp);
+ buf = realloc (buf, v32);
+ if (!buf)
+ reiserfs_panic ("realloc failed");
+ fread (buf, v32, 1, fp);
+ reiserfs_warning (stdout, "\"%s\": ", buf);
+
+ /* file name length and name itself*/
+ fread (&v32, sizeof (v32), 1, fp);
+ buf = realloc (buf, v32);
+ if (!buf)
+ reiserfs_panic ("realloc failed");
+ fread (buf, v32, 1, fp);
+
+ /* read directory key and poined object key */
+ fread (ids, sizeof (ids), 1, fp);
+ reiserfs_warning (stdout, "[%K]:\"%s\"-->[%K]\n",
+ &ids[0], buf, &ids[2]);
+
+ /*
+ do_recover = user_confirmed (stdout, "recover? (Y):", "Y\n");
+ if (do_recover)
+ reiserfs_warning (stderr, "recovering not ready\n");
+ */
+
+ /* how many data blocks are there */
+ fread (&v32, sizeof (v32), 1, fp);
+ if (v32) {
+ buf = realloc (buf, v32 * 4);
+ if (!buf)
+ reiserfs_panic ("realloc failed (%u)", v32);
+
+ /* read list of data block numbers */
+ fread (buf, 4, v32, fp);
+
+ if (!do_recover) {
+ for (i = 0; i < v32; i ++)
+ reiserfs_warning (stdout, "%d ", ((__u32 *)buf)[i]);
+ reiserfs_warning (stdout, "\n");
+ }
+ }
+
+ /* main tail length */
+ fread (&v32, sizeof (v32), 1, fp);
+ if (v32) {
+ /* there is tail */
+ buf = realloc (buf, v32);
+ if (!buf)
+ reiserfs_panic ("realloc failed");
+ fread (buf, v32, 1, fp);
+ if (!do_recover)
+ reiserfs_warning (stdout, "%d bytes long tail\n", v32);
+ } else {
+ if (!do_recover)
+ reiserfs_warning (stdout, "No tail\n");
+ }
+
+ if (fread (&v32, sizeof (v32), 1, fp) != 1)
+ break;
+ if (v32 != MAP_END_MAGIC)
+ reiserfs_panic ("read_map: no magic found");
+ }
+
+ free (buf);
+}
+
+
+void do_recover (reiserfs_filsys_t * fs)
+{
+ FILE * fp;
+
+ if (map_file (fs)) {
+ fp = fopen (map_file (fs), "r");
+ if (fp == 0) {
+ reiserfs_warning (stderr, "do_recover: fopen failed: %m");
+ return;
+ }
+ } else {
+ reiserfs_warning (stderr, "Reading file map from stdin..\n");
+ fflush (stderr);
+ fp = stdin;
+ }
+
+ read_map (fp);
+
+ if (fp != stdin)
+ fclose (fp);
+
+}
diff --git a/debugreiserfs/scan.c b/debugreiserfs/scan.c
new file mode 100644
index 0000000..3c34b53
--- /dev/null
+++ b/debugreiserfs/scan.c
@@ -0,0 +1,941 @@
+/*
+ * Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
+ */
+
+#include "debugreiserfs.h"
+#include <regex.h>
+#include <obstack.h>
+#include <search.h>
+
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+
+
+/* -n pattern scans the area (on-disk bitmap, or all the device or extern
+ bitmap) and looks for every name matching the pattern. All those names get
+ stored in 'name_store' and are indexed by name (name_index) and by a key
+ they point to (key_index) */
+
+struct obstack name_store;
+struct obstack item_store;
+
+int saved_names;
+int saved_items;
+int skipped_names;
+void * key_index;
+void * name_index;
+
+regex_t pattern;
+
+
+struct saved_item {
+ struct item_head si_ih;
+ unsigned long si_block;
+ int si_item_num;
+ struct saved_item * si_next; /* list of items having the same key */
+};
+
+
+struct saved_name {
+ unsigned int dirid; /* pointed object */
+ unsigned int objectid;
+ struct saved_name * first_name; /* pointer to name which points to the
+ same object and contains list of file
+ items */
+
+ unsigned int parent_dirid; /* parent directory */
+ unsigned int parent_objectid;
+ unsigned long block; /* where we saw the name for the first time */
+ unsigned short count; /* how many times the name appeared */
+
+ void * items;
+ struct saved_name * name_next; /* list of identical names */
+
+ unsigned short name_len;
+ char name[1];
+};
+
+
+
+/* attach item to every name in the list */
+static void store_item (struct saved_name * name, struct buffer_head * bh,
+ struct item_head * ih)
+{
+ struct saved_item * new;
+ void * vp;
+ struct saved_item * item_in;
+
+ new = obstack_alloc (&item_store, sizeof (struct saved_item));
+ new->si_ih = *ih;
+ new->si_block = bh->b_blocknr;
+ new->si_item_num = ih - B_N_PITEM_HEAD (bh, 0);
+ new->si_next = 0;
+
+ vp = tfind (new, &name->items, comp_keys);
+ if (vp) {
+ item_in = *(void **)vp;
+ /* add item to the end of list of items having this key */
+ while (1) {
+ if (!item_in->si_next) {
+ item_in->si_next = new;
+ break;
+ }
+ item_in = item_in->si_next;
+ }
+ } else
+ tsearch (new, &name->items, comp_keys);
+
+ saved_items ++;
+}
+
+
+static int comp_names (const void * p1, const void * p2)
+{
+ struct saved_name * name1, * name2;
+
+ name1 = (struct saved_name *)p1;
+ name2 = (struct saved_name *)p2;
+
+ return strcmp (name1->name, name2->name);
+}
+
+
+static int comp_pointed (const void * p1, const void * p2)
+{
+ struct saved_name * name1, * name2;
+
+ name1 = (struct saved_name *)p1;
+ name2 = (struct saved_name *)p2;
+
+ return comp_short_keys (&name1->dirid, &name2->dirid);
+}
+
+
+/* we consider name found only if it points to the same object and from the
+ same directory */
+static int name_found (struct saved_name * name, struct saved_name ** name_in)
+{
+ void * vp;
+ struct saved_name * cur;
+
+ vp = tfind (name, &name_index, comp_names);
+ if (!vp) {
+ *name_in = 0;
+ return 0;
+ }
+
+ *name_in = *(void **)vp;
+
+ /* check every name in the list */
+ cur = *name_in;
+ while (cur) {
+ if (!not_of_one_file (&name->dirid, &cur->dirid) &&
+ !not_of_one_file (&name->parent_dirid, &cur->parent_dirid)) {
+ cur->count ++;
+ return 1;
+ }
+ cur = cur->name_next;
+ }
+
+ return 0;
+}
+
+
+/* add key name is pointing to to the index of keys. If there was already name
+ pointing to this key - add pointer to that name */
+static void add_key (struct saved_name * name)
+{
+ void * vp;
+
+ vp = tfind (name, &key_index, comp_pointed);
+ if (vp) {
+ /* */
+ name->first_name = *(void **)vp;
+ } else {
+ tsearch (name, &key_index, comp_pointed);
+ }
+}
+
+
+static void add_name (struct saved_name * name, struct saved_name * name_in)
+{
+ if (name_in) {
+ /* add name to the end of list of identical names */
+ while (1) {
+ if (!name_in->name_next) {
+ name_in->name_next = name;
+ break;
+ }
+ name_in = name_in->name_next;
+ }
+ } else {
+ /* add name into name index */
+ tsearch (name, &name_index, comp_names);
+ }
+}
+
+
+/* take each name matching to a given pattern, */
+static void scan_for_name (struct buffer_head * bh)
+{
+ int i, j;
+ struct item_head * ih;
+ struct reiserfs_de_head * deh;
+ int namelen;
+ char * name;
+ struct saved_name * new, *name_in;
+ char ch;
+ int retval;
+ int min_entry_size = 1;
+ int ih_entry_count = 0;
+
+ ih = B_N_PITEM_HEAD (bh, 0);
+ for (i = 0; i < B_NR_ITEMS (bh); i ++, ih ++) {
+ if (!is_direntry_ih (ih))
+ continue;
+ if (is_it_bad_item (fs, ih, B_I_PITEM (bh, ih), 0, 1))
+ continue;
+
+ deh = B_I_DEH (bh, ih);
+
+ if ( (get_ih_entry_count (ih) > (get_ih_item_len(ih) / (DEH_SIZE + min_entry_size))) ||
+ (get_ih_entry_count (ih) == 0))
+ ih_entry_count = get_ih_item_len(ih) / (DEH_SIZE + min_entry_size);
+ else
+ ih_entry_count = get_ih_entry_count (ih);
+
+ for (j = 0; j < ih_entry_count; j ++, deh ++) {
+ name = name_in_entry (deh, j);
+ namelen = name_in_entry_length (ih, deh, j);
+ ch = name[namelen];
+ name[namelen] = 0;
+ retval = regexec (&pattern, name, 0, NULL, 0);
+ name[namelen] = ch;
+ if (retval != 0)
+ continue;
+
+ /* name matching given pattern found */
+
+ new = obstack_alloc (&name_store, sizeof (struct saved_name) + namelen);
+
+ /* pointed object */
+ new->dirid = get_deh_dirid (deh);
+ new->objectid = get_deh_objectid (deh);
+
+ /* pointer to first name which points the same key */
+ new->first_name = 0;
+
+ /* where this name is from */
+ new->parent_dirid = get_key_dirid (&ih->ih_key);
+ new->parent_objectid = get_key_objectid (&ih->ih_key);
+ new->block = bh->b_blocknr;
+
+ new->count = 1;
+ new->items = 0;
+
+ /* name */
+ new->name_len = namelen;
+ memcpy (new->name, name, namelen);
+ new->name [namelen] = 0;
+ new->name_next = 0;
+
+ /*
+ reiserfs_warning (stdout, "\n(%K):%s-->(%K) - ", &new->parent_dirid,
+ new->name, &new->dirid);
+ */
+ if (name_found (new, &name_in)) {
+ /* there was already exactly this name */
+ obstack_free (&name_store, new);
+ continue;
+ }
+
+ saved_names ++;
+ add_name (new, name_in);
+ add_key (new);
+ } /* for each entry */
+ } /* for each item */
+
+ return;
+}
+
+
+/* take every item, look for its key in the key index, if it is found - store
+ item in the sorted list of items of a file */
+static void scan_items (struct buffer_head * bh)
+{
+ int i;
+ struct item_head * ih;
+ struct saved_name * name_in_store;
+ void * res;
+
+
+ ih = B_N_PITEM_HEAD (bh, 0);
+ for (i = 0; i < B_NR_ITEMS (bh); i ++, ih ++) {
+ res = tfind (&ih->ih_key, &key_index, comp_pointed);
+ if (!res)
+ /* there were no names pointing to this key */
+ continue;
+
+ /* name pointing to this key found */
+ name_in_store = *(struct saved_name **)res;
+
+ store_item (name_in_store, bh, ih);
+ }
+}
+
+
+/* FIXME: does not work for long files */
+struct version {
+ int flag; /* direct or indirect */
+ int len;
+ __u32 from;
+ int count;
+ void * data;
+};
+
+
+struct tail {
+ __u32 offset;
+ int len;
+ char * data;
+};
+
+
+struct file_map {
+ int head_len; /* number of unfm pointers */
+ void * head;
+
+ int tail_nr; /* number of tails found */
+ struct tail * tails;
+
+ int version_nr;
+ void * versions; /* list of range versions */
+};
+
+
+struct file_map map;
+
+
+static int have_to_append (struct item_head * ih)
+{
+ loff_t off = get_offset (&ih->ih_key);
+
+ if (is_indirect_ih (ih)) {
+ if (map.head_len * fs->fs_blocksize + 1 <= off)
+ return 1;
+ return 0;
+ } else if (is_direct_ih (ih)) {
+ int i;
+ __u32 tail_start;
+
+ tail_start = (off & ~(fs->fs_blocksize - 1)) + 1;
+
+ /* find correct tail first */
+ for (i = 0; i < map.tail_nr; i ++) {
+ if (map.tails[i].offset == tail_start) {
+ if (map.tails[i].offset + map.tails[i].len <= off)
+ return 1;
+ return 0;
+ }
+ }
+ /* there was no this tail yet */
+ return 1;
+ }
+ return 0;
+}
+
+
+static void do_append (struct item_head * ih, void * data)
+{
+ int i;
+ int padd;
+ loff_t off = get_offset (&ih->ih_key);
+
+ if (is_indirect_ih (ih)) {
+
+ padd = (off - 1) / fs->fs_blocksize - map.head_len;
+ map.head = realloc (map.head, (map.head_len + padd + I_UNFM_NUM (ih)) * 4);
+ if (!map.head)
+ reiserfs_panic ("realloc failed");
+ memset ((char *)map.head + map.head_len * 4, 0, padd * 4);
+ memcpy ((char *)map.head + (map.head_len + padd) * 4, data,
+ get_ih_item_len (ih));
+ map.head_len += (padd + I_UNFM_NUM (ih));
+
+ } else if (is_direct_ih (ih)) {
+ int tail_start;
+ int skip;
+
+ /* find correct tail first */
+ tail_start = (off & ~(fs->fs_blocksize - 1)) + 1;
+ skip = (off - 1) & (fs->fs_blocksize - 1);
+ for (i = 0; i < map.tail_nr; i ++) {
+ if (map.tails[i].offset == tail_start) {
+ map.tails[i].data = realloc (map.tails[i].data,
+ off - tail_start + get_ih_item_len (ih));
+ if (!map.tails[i].data)
+ reiserfs_panic ("realloc failed");
+ padd = skip - map.tails[i].len;
+ memset (map.tails[i].data + map.tails[i].len, 0, padd);
+ memcpy (map.tails[i].data + map.tails[i].len + padd, data, get_ih_item_len (ih));
+ map.tails[i].len += (padd + get_ih_item_len (ih));
+ return;
+ }
+ }
+ /* allocate memory for new tail */
+ map.tails = realloc (map.tails, (map.tail_nr + 1) * sizeof (struct tail));
+ if (!map.tails)
+ reiserfs_panic ("realloc failed");
+
+ map.tails[map.tail_nr].offset = off;
+ map.tails[map.tail_nr].len = skip + get_ih_item_len (ih);
+ map.tails[map.tail_nr].data = malloc (map.tails[map.tail_nr].len);
+ memset (map.tails[map.tail_nr].data, 0, skip);
+ memcpy (map.tails[map.tail_nr].data + skip, data, get_ih_item_len (ih));
+ map.tail_nr ++;
+ }
+}
+
+
+/* map contains */
+static void do_overwrite (struct item_head * ih, void * data)
+{
+ int skip; /* now may bytes/pointers to skip */
+ int to_compare;
+ int to_append;
+ loff_t off = get_offset (&ih->ih_key);
+ char * p;
+ struct item_head tmp_ih;
+
+ if (is_indirect_ih (ih)) {
+
+ skip = (off - 1) / fs->fs_blocksize;
+ to_compare = (map.head_len - skip > I_UNFM_NUM (ih)) ? I_UNFM_NUM (ih) :
+ (map.head_len - skip);
+ to_append = I_UNFM_NUM (ih) - to_compare;
+
+ p = (char *)map.head + skip * 4;
+
+ if (memcmp (p, data, to_compare * 4))
+ reiserfs_warning (stderr, "overwrite (indirect): %H contains different data\n", ih);
+
+ if (to_append) {
+ tmp_ih = *ih;
+ set_ih_item_len (&tmp_ih, get_ih_item_len (ih) - to_compare * 4);
+ set_offset (key_format (&ih->ih_key), &tmp_ih.ih_key, off + to_compare * fs->fs_blocksize);
+ do_append (&tmp_ih, (char *)data + to_compare * 4);
+ }
+
+ } else if (is_direct_ih (ih)) {
+ int tail_start;
+ int i;
+
+ /* find correct tail first */
+ tail_start = (off & ~(fs->fs_blocksize - 1)) + 1;
+ for (i = 0; i < map.tail_nr; i ++) {
+ if (map.tails[i].offset == tail_start) {
+ /* ih is a part of this tail */
+ skip = (off - 1) & (fs->fs_blocksize - 1);
+ to_compare = (map.tails[i].len - skip > get_ih_item_len (ih) ? get_ih_item_len (ih) :
+ map.tails[i].len - skip);
+ to_append = get_ih_item_len (ih) - to_compare;
+
+ p = (char *)map.tails[i].data + skip;
+
+ if (memcmp (p, data, to_compare))
+ reiserfs_warning (stderr, "overwrite (direct): %H contains different data\n", ih);
+
+ if (to_append) {
+ tmp_ih = *ih;
+ set_ih_item_len (&tmp_ih, get_ih_item_len (ih) - to_compare);
+ set_offset (key_format (&ih->ih_key), &tmp_ih.ih_key, off + to_compare);
+ do_append (&tmp_ih, (char *)data + to_compare);
+ }
+ return;
+ }
+ }
+ reiserfs_panic ("no appropriate tail found");
+ }
+}
+
+
+static void map_one_item (struct saved_item * item)
+{
+ struct buffer_head * bh;
+ struct item_head * ih;
+ void * data;
+
+ /* read the block containing the item */
+ bh = bread (fs->fs_dev, item->si_block, fs->fs_blocksize);
+ if (!bh) {
+ reiserfs_warning (stderr, "bread failed\n");
+ return;
+ }
+
+ ih = B_N_PITEM_HEAD (bh, item->si_item_num);
+ data = B_I_PITEM (bh, ih);
+ if (memcmp (&item->si_ih, ih, sizeof (*ih)))
+ reiserfs_panic ("wrong item");
+
+ if (have_to_append (ih)) {
+ do_append (ih, data);
+ } else
+ do_overwrite (ih, data);
+
+ brelse (bh);
+}
+
+
+static void map_item_list (const void *nodep, VISIT value, int level)
+{
+ struct saved_item * item, * longest;
+ int bytes, max_bytes;
+
+ if (value != leaf && value != postorder)
+ return;
+
+ item = *(struct saved_item **)nodep;
+
+ /* 1. find the longest item */
+ max_bytes = get_bytes_number (&item->si_ih, fs->fs_blocksize);
+ longest = item;
+ while (item->si_next) {
+ item = item->si_next;
+ bytes = get_bytes_number (&item->si_ih, fs->fs_blocksize);
+ if (bytes > max_bytes) {
+ longest = item;
+ max_bytes = bytes;
+ }
+ }
+
+ map_one_item (longest);
+
+ /* map other items */
+ item = *(struct saved_item **)nodep;
+ while (item) {
+ if (item != longest)
+ map_one_item (item);
+ item = item->si_next;
+ }
+}
+
+
+/* flush map which is in variable map */
+static void flush_map (reiserfs_filsys_t * fs,
+ struct key * dir,
+ char * name,
+ struct key * key)
+{
+ int i;
+ FILE * fp;
+ __u32 v32;
+
+
+ if (!map_file (fs))
+ asprintf (&map_file (fs), "%s", ".map");
+
+ /*reiserfs_warning (stderr, "Saving maps into %s\n", map_file (fs));*/
+ fp = fopen (map_file (fs), "a");
+ if (fp == 0) {
+ reiserfs_warning (stderr, "flush_map: fopen failed: %m");
+ return;
+ }
+
+ v32 = MAP_MAGIC;
+ fwrite (&v32, sizeof (v32), 1, fp);
+
+ /* device name */
+ v32 = strlen (device_name (fs)) + 1;
+ fwrite (&v32, sizeof (v32), 1, fp);
+ fwrite (device_name (fs), v32, 1, fp);
+
+ /* name length and the name itself */
+ v32 = strlen (name) + 1;
+ fwrite (&v32, sizeof (v32), 1, fp);
+ fwrite (name, v32, 1, fp);
+
+ /* short key of a directory */
+ fwrite (dir, SHORT_KEY_SIZE, 1, fp);
+
+ /* short key of file */
+ fwrite (key, SHORT_KEY_SIZE, 1, fp);
+
+ /* list of data block pointers */
+ fwrite (&map.head_len, sizeof (map.head_len), 1, fp);
+ fwrite (map.head, map.head_len * 4, 1, fp);
+
+
+ /* find correct tail first */
+ for (i = 0; i < map.tail_nr; i ++) {
+ if (map.tails [i].offset == map.head_len * fs->fs_blocksize) {
+ /* tail length and the tail itself */
+ fwrite (&map.tails [i].len, sizeof (map.tails [i].len), 1, fp);
+ fwrite (map.tails [i].data, map.tails [i].len, 1, fp);
+ break;
+ }
+ }
+ if (i == map.tail_nr) {
+ /* no tail */
+ v32 = 0;
+ fwrite (&v32, sizeof (v32), 1, fp);
+ }
+
+ v32 = MAP_END_MAGIC;
+ fwrite (&v32, sizeof (v32), 1, fp);
+
+ fclose (fp);
+}
+
+
+/* write map of file to a map file */
+static void make_file_map (const void *nodep, VISIT value, int level)
+{
+ struct saved_name * name;
+ static int nr = 0;
+
+ name = *(struct saved_name **)nodep;
+
+ if (value == leaf || value == postorder) {
+ while (name) {
+ reiserfs_warning (stdout, "%d - (%d): [%K]:\"%s\":\n", ++nr, name->count,
+ &name->parent_dirid, name->name);
+
+ if (name->items) {
+ /* initialize the map */
+ memset (&map, 0, sizeof (struct file_map));
+
+ /* make a map of file */
+ twalk (name->items, map_item_list);
+
+ /* write map to a file */
+ flush_map (fs, (struct key *)&name->parent_dirid, name->name,
+ (struct key *)&name->dirid);
+
+ } else if (name->first_name)
+ reiserfs_warning (stdout, "[%K]:\"%s\" has item list\n",
+ &name->first_name->parent_dirid,
+ name->first_name->name);
+ else {
+ reiserfs_warning (stdout, "No items of the file [%K] found\n",
+ &name->dirid);
+ }
+
+ name = name->name_next;
+ }
+ }
+}
+
+/* file.list will contain list of names such that it can be used as
+ input for -N */
+static void print_name (const void *nodep, VISIT value, int level)
+{
+ struct saved_name * name;
+ static FILE * fp = 0;
+
+ if (fp == 0) {
+ fp = fopen ("file.list", "w+");
+ if (!fp)
+ reiserfs_panic ("could open file.list: %m");
+ }
+ name = *(struct saved_name **)nodep;
+ if (value == leaf || value == postorder) {
+ while (name) {
+ if (name->items)
+ /* we have found items of this file */
+ reiserfs_warning (fp, "%u %u %s\n",
+ name->parent_dirid, name->parent_objectid,
+ name->name);
+ name = name->name_next;
+ }
+ }
+}
+
+
+
+/* store map if it is a regular file */
+static void locate_file (reiserfs_filsys_t * fs, struct key * key)
+{
+ INITIALIZE_PATH (path);
+ struct key * next_key;
+ int retval;
+
+ do {
+ retval = reiserfs_search_by_key_4 (fs, key, &path);
+ if (retval != ITEM_FOUND)
+ break;
+
+ if (!is_stat_data_key (key) && !is_direntry_key (key)) {
+ struct saved_item si;
+
+ si.si_block = get_bh (&path)->b_blocknr;
+ si.si_item_num = get_item_pos (&path);
+ si.si_ih = *get_ih (&path);
+ map_one_item (&si);
+ }
+
+ /*reiserfs_warning (stdout, "\t");
+ reiserfs_print_item (stdout, get_bh (&path), get_ih (&path));*/
+
+ next_key = reiserfs_next_key (&path);
+ if (!next_key || not_of_one_file (next_key, key))
+ break;
+
+ *key = *next_key;
+ pathrelse (&path);
+ } while (1);
+
+ pathrelse (&path);
+}
+
+
+/* read stdin and look for specified name in the specified directory */
+static void look_for_name (reiserfs_filsys_t * fs)
+{
+ INITIALIZE_PATH (path);
+ char * name, * objectid, * dirid;
+ size_t n;
+ struct key key = {0, };
+
+ reiserfs_warning (stderr,
+ "Enter dirid objectid \"name\" or press ^D to quit\n");
+ while (1) {
+ reiserfs_warning (stderr, ">");
+ n = 0; dirid = 0;
+ if (getdelim (&dirid, &n, ' ', stdin) == -1)
+ break;
+ if (!strcmp (dirid, "\n"))
+ break;
+ set_key_dirid (&key, atol (dirid));
+
+ n = 0; objectid = 0;
+ if (getdelim (&objectid, &n, ' ', stdin) == -1)
+ break;
+ set_key_objectid (&key, atol (objectid));
+
+ n = 0; name = 0;
+ if (getdelim (&name, &n, '\n', stdin) == -1)
+ break;
+
+ name [strlen (name) - 1] = 0;
+ reiserfs_warning (stdout, "looking for file \"%s\" in (%K) - ",
+ name, &key);
+
+ if (reiserfs_locate_entry (fs, &key, name, &path)) {
+ struct key fkey = {0, };
+ struct reiserfs_de_head * deh;
+
+ reiserfs_warning (stdout, "name is found in block %lu (item %d, entry %d)\n",
+ get_bh (&path)->b_blocknr, get_item_pos (&path),
+ path.pos_in_item);
+ deh = B_I_DEH (get_bh (&path), get_ih (&path)) + path.pos_in_item;
+ set_key_dirid (&fkey, get_deh_dirid (deh));
+ set_key_objectid (&fkey, get_deh_objectid (deh));
+
+ pathrelse (&path);
+
+ /* look for file and print its layout */
+ memset (&map, 0, sizeof (struct file_map));
+
+ locate_file (fs, &fkey);
+
+ flush_map (fs, &key, name, &fkey);
+
+ } else {
+ reiserfs_warning (stdout, "name not found\n");
+ }
+
+ free (dirid);
+ free (objectid);
+ free (name);
+ }
+}
+
+
+FILE * log;
+
+static void scan_for_key (struct buffer_head * bh, struct key * key)
+{
+ int i, j;
+ struct item_head * ih;
+ struct reiserfs_de_head * deh;
+ int min_entry_size = 1;
+ int ih_entry_count = 0;
+
+
+ ih = B_N_PITEM_HEAD (bh, 0);
+ for (i = 0; i < B_NR_ITEMS (bh); i ++, ih ++) {
+ if ((get_key_dirid (&ih->ih_key) == get_key_dirid (key) ||
+ (int)get_key_dirid (key) == -1) &&
+ (get_key_objectid (&ih->ih_key) == get_key_objectid (key) ||
+ (int)get_key_objectid (key) == -1)) {
+ reiserfs_warning (log, "%d-th item of block %lu is item of file %K: %H\n",
+ i, bh->b_blocknr, key, ih);
+ }
+ if (!is_direntry_ih (ih))
+ continue;
+ deh = B_I_DEH (bh, ih);
+
+ if ( (get_ih_entry_count (ih) > (get_ih_item_len(ih) / (DEH_SIZE + min_entry_size))) ||
+ (get_ih_entry_count (ih) == 0))
+ ih_entry_count = get_ih_item_len(ih) / (DEH_SIZE + min_entry_size);
+ else
+ ih_entry_count = get_ih_entry_count (ih);
+
+
+ for (j = 0; j < ih_entry_count; j ++, deh ++) {
+ if ((get_deh_dirid (deh) == get_key_dirid (key) || (int)get_key_dirid (key) == -1) &&
+ (get_deh_objectid (deh) == get_key_objectid (key) || (int)get_key_objectid (key) == -1)) {
+ reiserfs_warning (log, "dir item %d (%H) of block %lu has "
+ "entry (%d-th) %.*s pointing to %K\n",
+ i, ih, bh->b_blocknr, j,
+ name_in_entry_length (ih, deh, j), name_in_entry (deh, j), key);
+ }
+ }
+ }
+ return;
+}
+
+
+
+void do_scan (reiserfs_filsys_t * fs)
+{
+ unsigned long i;
+ struct buffer_head * bh;
+ int type;
+ char * answer = 0;
+ size_t n = 0;
+ struct key key = {0, 0, };
+ unsigned long done, total;
+
+
+ if (debug_mode (fs) == DO_SCAN_JOURNAL) {
+ scan_journal (fs);
+ return;
+ }
+
+ if (debug_mode (fs) == DO_LOOK_FOR_NAME) {
+ /* look for a file in using tree algorithms */
+ look_for_name (fs);
+ return;
+ }
+
+ /* scan area of disk and store all names matching the pattern */
+
+ /* initialize storage and two indexes */
+ obstack_init (&name_store);
+ obstack_init (&item_store);
+ key_index = 0;
+ name_index = 0;
+
+ total = reiserfs_bitmap_ones (input_bitmap (fs));
+
+ log = fopen ("scan.log", "w+");
+ printf ("Log file 'scan.log' is opened\n");
+
+ if (debug_mode (fs) == DO_SCAN_FOR_NAME) {
+ if (regcomp (&pattern, name_pattern (fs), 0)) {
+ printf ("regcomp failed");
+ return;
+ }
+
+ printf ("Looking for names matching %s\n", name_pattern (fs));
+ set_key_dirid (&key, 1);
+ } else {
+ printf ("What key do you want to find: dirid?");
+ getline (&answer, &n, stdin);
+ set_key_dirid (&key, atoi (answer));
+
+ printf ("objectid?");
+ getline (&answer, &n, stdin);
+ set_key_objectid (&key, atoi (answer));
+ reiserfs_warning (stderr, "looking for (%K)\n", &key);
+ }
+
+ done = 0;
+ for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) {
+ if (!reiserfs_bitmap_test_bit (input_bitmap (fs), i))
+ continue;
+ bh = bread (fs->fs_dev, i, fs->fs_blocksize);
+ if (!bh) {
+ printf ("could not read block %lu\n", i);
+ continue;
+ }
+ type = who_is_this (bh->b_data, bh->b_size);
+ switch (type) {
+ case THE_JDESC:
+ if (!get_key_dirid (&key))
+ printf ("block %lu is journal descriptor\n", i);
+ reiserfs_bitmap_clear_bit (input_bitmap (fs), i);
+ break;
+ case THE_SUPER:
+ if (!get_key_dirid (&key))
+ printf ("block %lu is reiserfs super block\n", i);
+ reiserfs_bitmap_clear_bit (input_bitmap (fs), i);
+ break;
+ case THE_INTERNAL:
+ if (!get_key_dirid (&key))
+ printf ("block %lu is reiserfs internal node\n", i);
+ reiserfs_bitmap_clear_bit (input_bitmap (fs), i);
+ break;
+ case THE_LEAF:
+ if (debug_mode (fs) == DO_SCAN_FOR_NAME) {
+ scan_for_name (bh);
+ } else if (get_key_dirid (&key)) {
+ scan_for_key (bh, &key);
+ } else {
+ printf ("block %lu is reiserfs leaf node\n", i);
+ }
+ break;
+ default:
+ reiserfs_bitmap_clear_bit (input_bitmap (fs), i);
+ break;
+ }
+ brelse (bh);
+ print_how_far (stderr, &done, total, 1, be_quiet (fs));
+ }
+
+ fprintf (stderr, "\n");
+ if (debug_mode (fs) == DO_SCAN_FOR_NAME)
+ fprintf (stderr, "There were found %d names matching the pattern \"%s\", %d names skipped\n",
+ saved_names, name_pattern (fs), skipped_names);
+ fflush (stderr);
+
+
+ if (debug_mode (fs) != DO_SCAN_FOR_NAME)
+ return;
+
+ /* step 2: */
+ done = 0;
+ total = reiserfs_bitmap_ones (input_bitmap (fs));
+ printf ("%ld bits set in bitmap\n", total);
+ for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) {
+ if (!reiserfs_bitmap_test_bit (input_bitmap (fs), i))
+ continue;
+ bh = bread (fs->fs_dev, i, fs->fs_blocksize);
+ if (!bh) {
+ printf ("could not read block %lu\n", i);
+ continue;
+ }
+ if (who_is_this (bh->b_data, bh->b_size) != THE_LEAF) {
+ brelse (bh);
+ continue;
+ }
+
+ scan_items (bh);
+
+ brelse (bh);
+ print_how_far (stderr, &done, total, 1, be_quiet (fs));
+ }
+ fprintf (stderr, "\nThere were %d items saved\n", saved_items);
+
+ /* ok, print what we found */
+ /*twalk (name_index, print_file);*/
+
+ /* create map for every file in */
+ twalk (name_index, make_file_map);
+
+ /* print names of files we have map of in a file 'file.list' */
+ twalk (name_index, print_name);
+}
+
+
diff --git a/debugreiserfs/stat.c b/debugreiserfs/stat.c
new file mode 100644
index 0000000..81e5125
--- /dev/null
+++ b/debugreiserfs/stat.c
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2002 by Hans Reiser, licensing governed by reiserfs/README
+ */
+
+#include "debugreiserfs.h"
+#include <search.h>
+#include <obstack.h>
+
+#define obstack_chunk_alloc malloc
+#define obstack_chunk_free free
+
+
+/* try to find blocks which contain only items which are */
+
+
+/* read blocks marked in debug_bitmap and collect statistic of it:
+ number of stat data */
+struct {
+ unsigned long all;
+ unsigned long items [5];
+ unsigned long unique_keys; /* keys of stat datas */
+ unsigned long unique_entry_keys; /* keys which appear in directory entries */
+ unsigned long names; /* dir entries but "." and ".." */
+ unsigned long dir_blocks; /* block containing only one directory item */
+ unsigned long unique_items;
+ unsigned long leaves;
+ unsigned long blocks_to_skip;
+} fs_stat;
+
+
+/* store unique item heads */
+struct obstack items;
+
+/* tree sorting item heades by comp_items_1 */
+void * items_tree;
+
+
+static int comp_items_1 (const void * p1, const void * p2)
+{
+ int retval;
+ struct item_head * ih1, * ih2;
+
+ /*
+ if (*(int *)p1 != *(int *)p2)
+ retval = 1;
+ else
+ retval = 0;
+ */
+ retval = comp_keys (p1, p2);
+ /*retval = comp_short_keys (p1, p2);*/
+ if (retval)
+ return retval;
+
+
+ ih1 = (struct item_head *)p1;
+ ih2 = (struct item_head *)p2;
+
+ if (get_ih_item_len (ih1) < get_ih_item_len (ih2))
+ return -1;
+ if (get_ih_item_len (ih1) > get_ih_item_len (ih2))
+ return 1;
+ if (get_ih_entry_count (ih1) < get_ih_entry_count (ih2))
+ return -1;
+ if (get_ih_entry_count (ih1) > get_ih_entry_count (ih2))
+ return 1;
+
+ return 0;
+}
+
+
+/*
+static void print_node (const void *nodep, VISIT value, int level)
+{
+ int i;
+
+ if (value == leaf) {
+ for (i = 0; i < level; i ++)
+ reiserfs_warning (stdout, "\t");
+ reiserfs_warning (stdout, "%H\n", *(struct item_head **)nodep);
+ return;
+ }
+ if (value == postorder) {
+ for (i = 0; i < level; i ++)
+ reiserfs_warning (stdout, "\t");
+ reiserfs_warning (stdout, "%H\n", *(struct item_head **)nodep);
+ }
+}
+*/
+
+
+static int is_unique_item (struct obstack * ostack, void ** tree, void * ih)
+{
+ void * res;
+ void * key1;
+
+ key1 = obstack_copy (ostack, ih, IH_SIZE);
+ res = tsearch (key1, tree, comp_items_1);
+ if (!res)
+ reiserfs_panic ("Too many keys found");
+
+/* twalk (*tree, print_node);*/
+/* reiserfs_warning (stderr, "\n\n");*/
+ if (*(void **)res != key1) {
+ /* key is in tree already, remove it from obstack */
+ /*reiserfs_warning (stdout, "%H is skipped\n", ih);fflush (stdout);*/
+ obstack_free (ostack, key1);
+ return 0;
+ }
+
+ /*reiserfs_warning (stdout, "%k is added\n", ih);fflush (stdout);*/
+ return 1;
+}
+
+
+static void stat1_the_leaf (reiserfs_filsys_t * fs, struct buffer_head * bh)
+{
+ int i;
+ struct item_head * ih;
+ int is_there_unique_item;
+
+
+ ih = B_N_PITEM_HEAD (bh, 0);
+ is_there_unique_item = 0;
+ for (i = 0; i < get_blkh_nr_items (B_BLK_HEAD (bh)); i ++, ih ++) {
+ /* count all items */
+ fs_stat.all ++;
+
+ if (is_unique_item (&items, &items_tree, ih)) {
+ /* this is item we have not seen yet */
+ fs_stat.unique_items ++;
+ is_there_unique_item ++;
+ }
+ }
+
+ if (!is_there_unique_item) {
+ /* the node contains only items we have seen already. so we will skip
+ it */
+ fs_stat.blocks_to_skip ++;
+ reiserfs_bitmap_clear_bit (input_bitmap (fs), bh->b_blocknr);
+ } else {
+ ih = B_N_PITEM_HEAD (bh, 0);
+ /* node contains at least one unique item. We will put it in, count items of each type */
+ for (i = 0; i < get_blkh_nr_items (B_BLK_HEAD (bh)); i ++, ih ++) {
+ fs_stat.items [get_type (&ih->ih_key)] ++;
+ }
+ }
+}
+
+/*
+static void stat2_the_leaf (struct buffer_head * bh)
+{
+ int i;
+ struct item_head * ih;
+
+ ih = B_N_PITEM_HEAD (bh, 0);
+ for (i = 0; i < node_item_number (bh); i ++, ih ++) {
+
+ }
+}
+*/
+
+void do_stat (reiserfs_filsys_t * fs)
+{
+ unsigned long i;
+ unsigned long done, total;
+ struct buffer_head * bh;
+ int type;
+ FILE * fp;
+
+
+ obstack_init (&items);
+ items_tree = 0;
+
+/*
+ bh = bread (fs->s_dev, 8211, fs->s_blocksize);
+ stat1_the_leaf (fs, bh);
+
+ return;
+*/
+
+
+
+ total = reiserfs_bitmap_ones (input_bitmap (fs));
+
+ /* pass 0 of stating */
+ total = reiserfs_bitmap_ones (input_bitmap (fs));
+ done = 0;
+ for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) {
+ if (!reiserfs_bitmap_test_bit (input_bitmap (fs), i))
+ continue;
+
+ print_how_far (stderr, &done, total, 1, be_quiet (fs));
+
+ bh = bread (fs->fs_dev, i, fs->fs_blocksize);
+ if (!bh) {
+ printf ("could not read block %lu\n", i);
+ continue;
+ }
+ type = who_is_this (bh->b_data, bh->b_size);
+ if (type != THE_LEAF) {
+ reiserfs_bitmap_clear_bit (input_bitmap (fs), i);
+ brelse (bh);
+ continue;
+ }
+ fs_stat.leaves ++;
+ stat1_the_leaf (fs, bh);
+ brelse (bh);
+ }
+
+ reiserfs_warning (stderr, "\nThere were %lu leaves\n"
+ "\ttotal number of items %lu there\n"
+ "\tblocks containing at least one unique item %lu\n"
+ "\tblocks which can be skipped %lu\n"
+ "\t\tstat data %lu\n"
+ "\t\tindirect %lu\n"
+ "\t\tdirect %lu\n"
+ "\t\tdirectory items %lu\n"
+ "\tunique items %lu\n",
+ /*
+ "\tnames there (but \".\" and \"..\") %lu\n"
+ "\tpointing to unique keys %lu\n"
+ "other items %lu\n"
+ "blocks containing only 1 dir item %lu\n",
+ */
+ fs_stat.leaves,
+ fs_stat.all,
+ fs_stat.leaves - fs_stat.blocks_to_skip,
+ fs_stat.blocks_to_skip,
+ fs_stat.items [TYPE_STAT_DATA],
+ fs_stat.items [TYPE_INDIRECT],
+ fs_stat.items [TYPE_DIRECT],
+ fs_stat.items [TYPE_DIRENTRY],
+ fs_stat.unique_items);
+/*
+ fs_stat.names,
+ fs_stat.unique_keys,
+ fs_stat.items [4],
+ fs_stat.dir_blocks);
+*/
+ if (!input_bitmap_file_name(fs))
+ return;
+
+ fp = fopen (input_bitmap_file_name(fs), "w");
+ if (!fp)
+ reiserfs_panic ("stat: could not open %s to save bitmap: %m\n",
+ input_bitmap_file_name(fs));
+ reiserfs_warning (stderr, "Updated bitmap contains %d blocks marked\n",
+ reiserfs_bitmap_ones (input_bitmap (fs)));
+ reiserfs_bitmap_save (fp, input_bitmap (fs));
+ fclose (fp);
+ return;
+
+
+ /* pass 2 of stating */
+ reiserfs_warning (stderr, "Looking for blocks containing only keys not pointed by any of entries\n");
+ total = reiserfs_bitmap_ones (input_bitmap (fs));
+ done = 0;
+ for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) {
+ if (!reiserfs_bitmap_test_bit (input_bitmap (fs), i))
+ continue;
+
+ print_how_far (stderr, &done, total, 1, be_quiet (fs));
+
+ bh = bread (fs->fs_dev, i, fs->fs_blocksize);
+ if (!bh) {
+ printf ("could not read block %lu\n", i);
+ continue;
+ }
+ /*stat2_the_leaf (bh);*/
+ }
+
+}
diff --git a/debugreiserfs/unpack.c b/debugreiserfs/unpack.c
index c83bae6..9f2028c 100644
--- a/debugreiserfs/unpack.c
+++ b/debugreiserfs/unpack.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
+ * Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
*/
#include "debugreiserfs.h"
@@ -8,41 +8,52 @@
#define print_usage_and_exit() die ("Usage: %s [-v] [-b filename] device\n\
-v prints blocks number of every block unpacked\n\
--b filename makes unpack to save bitmap of blocks unpacked\n", argv[0]);
-
+-b filename makes unpack to save bitmap of blocks unpacked\n\
+-j filename makes unpack to store journal in specified file\n", argv[0]);
/* when super block gets unpacked for the first time - create a bitmap
and mark in it what have been unpacked. Save that bitmap at the end */
-reiserfs_bitmap_t what_unpacked = 0;
+reiserfs_bitmap_t * what_unpacked = 0;
-int unpacked, data_blocks_unpacked;
+int leaves, full;
int verbose = 0;
+int Default_journal = 1;
-
-static void unpack_offset (struct packed_item * pi, struct item_head * ih)
+static void unpack_offset (struct packed_item * pi, struct item_head * ih, int blocksize)
{
- if (pi->mask & OFFSET_BITS_64) {
+
+ if (get_pi_mask(pi) & OFFSET_BITS_64) {
__u64 v64;
- if (ih_key_format (ih) != KEY_FORMAT_2)
+ if (get_ih_key_format (ih) != KEY_FORMAT_2)
die ("unpack_offset: key format is not set or wrong");
- fread64 (&v64);
+ fread_le64 (&v64);
set_offset (KEY_FORMAT_2, &ih->ih_key, v64);
return;
}
- if (pi->mask & OFFSET_BITS_32) {
+ if (get_pi_mask(pi) & OFFSET_BITS_32) {
__u32 v32;
- fread32 (&v32);
- set_offset (ih_key_format (ih), &ih->ih_key, v32);
+ fread_le32 (&v32);
+ set_offset (get_ih_key_format (ih), &ih->ih_key, v32);
return;
}
+ if ((get_pi_mask(pi) & DIR_ID) == 0 && (get_pi_mask(pi) & OBJECT_ID) == 0) {
+ /* offset was not sent, as it can be calculated looking at the
+ previous item */
+ if (is_stat_data_ih (ih - 1))
+ set_offset (get_ih_key_format (ih), &ih->ih_key, 1);
+ if (is_indirect_ih (ih - 1))
+ set_offset (get_ih_key_format (ih), &ih->ih_key,
+ get_offset (&(ih - 1)->ih_key) + get_bytes_number (ih - 1, blocksize));
+ }
+
// offset is 0
return;
}
@@ -50,21 +61,14 @@ static void unpack_offset (struct packed_item * pi, struct item_head * ih)
static void unpack_type (struct packed_item * pi, struct item_head * ih)
{
- if (pi->mask & DIRECT_ITEM)
- set_type (ih_key_format (ih), &ih->ih_key, TYPE_DIRECT);
- else if (pi->mask & STAT_DATA_ITEM)
- set_type (ih_key_format (ih), &ih->ih_key, TYPE_STAT_DATA);
- else if (pi->mask & INDIRECT_ITEM)
- set_type (ih_key_format (ih), &ih->ih_key, TYPE_INDIRECT);
- else if (pi->mask & DIRENTRY_ITEM)
- set_type (ih_key_format (ih), &ih->ih_key, TYPE_DIRENTRY);
- else
- reiserfs_panic (0, "%h, mask 0%o\n", ih, pi->mask);
+ set_type (get_ih_key_format (ih), &ih->ih_key, get_pi_type(pi));
+ if (type_unknown (&ih->ih_key))
+ reiserfs_panic ("unpack_type: unknown type %d unpacked for %H\n",
+ get_pi_type(pi), ih);
}
/* direntry item comes in the following format:
- entry count - 16 bits
for each entry
mask - 8 bits
entry length - 16 bits
@@ -87,17 +91,21 @@ static void unpack_direntry (struct packed_item * pi, struct buffer_head * bh,
if (!hash_func)
die ("unpack_direntry: hash function is not set");
- fread16 (&entry_count);
- set_entry_count (ih, entry_count);
+ if (!(get_pi_mask(pi) & IH_FREE_SPACE))
+ die ("ih_entry_count must be packed for directory items");
+
+ entry_count = get_ih_entry_count (ih);
+/* if (!entry_count)
+ reiserfs_panic ("unpack_direntry: entry count should be set already");*/
- item = bh->b_data + ih_location (ih);
+ item = bh->b_data + get_ih_location (ih);
deh = (struct reiserfs_de_head *)item;
- location = pi->item_len;
+ location = get_pi_item_len(pi);
for (i = 0; i < entry_count; i ++, deh ++) {
fread8 (&mask);
- fread16 (&entry_len);
+ fread_le16 (&entry_len);
location -= entry_len;
- deh->deh_location = location;
+ set_deh_location (deh, location);
fread (item + location, entry_len, 1, stdin);
/* find name length */
@@ -106,29 +114,30 @@ static void unpack_direntry (struct packed_item * pi, struct buffer_head * bh,
else
namelen = strlen (item + location);
- fread32 (&deh->deh_objectid);
+ fread32 (&deh->deh2_objectid);
if (mask & HAS_DIR_ID)
- fread32 (&deh->deh_dir_id);
+ fread32 (&deh->deh2_dir_id);
else
- deh->deh_dir_id = ih->ih_key.k_objectid;
+ set_deh_dirid (deh, get_key_objectid (&ih->ih_key));
+
if (*(item + location) == '.' && namelen == 1)
/* old or new "." */
- deh->deh_offset = DOT_OFFSET;
+ set_deh_offset (deh, DOT_OFFSET);
else if (*(item + location) == '.' && *(item + location + 1) == '.' && namelen == 2)
/* old or new ".." */
- deh->deh_offset = DOT_DOT_OFFSET;
+ set_deh_offset (deh, DOT_DOT_OFFSET);
else
- deh->deh_offset = GET_HASH_VALUE (hash_func (item + location,
- namelen));
+ set_deh_offset (deh, GET_HASH_VALUE (hash_func (item + location,
+ namelen)));
if (mask & HAS_GEN_COUNTER) {
- fread16 (&gen_counter);
- deh->deh_offset |= gen_counter;
+ fread_le16 (&gen_counter);
+ set_deh_offset (deh, get_deh_offset (deh) | gen_counter);
}
if (mask & HAS_STATE)
- fread16 (&deh->deh_state);
+ fread16 (&deh->deh2_state);
else
- deh->deh_state = (1 << DEH_Visible);
+ set_deh_state (deh, (1 << DEH_Visible2));
}
return;
@@ -139,9 +148,12 @@ static void unpack_direntry (struct packed_item * pi, struct buffer_head * bh,
static void unpack_stat_data (struct packed_item * pi, struct buffer_head * bh,
struct item_head * ih)
{
- set_entry_count (ih, 0xffff);
+ if (!(get_pi_mask(pi) & IH_FREE_SPACE)) {
+ /* ih_free_space was not packed - set default */
+ set_ih_entry_count (ih, 0xffff);
+ }
- if (ih_key_format (ih) == KEY_FORMAT_1) {
+ if (get_ih_key_format (ih) == KEY_FORMAT_1) {
/* stat data comes in the following format:
if this is old stat data:
mode - 16 bits
@@ -160,7 +172,7 @@ static void unpack_stat_data (struct packed_item * pi, struct buffer_head * bh,
fread32 (&sd->sd_size);
fread32 (&sd->u.sd_blocks);
- if (pi->mask & WITH_SD_FIRST_DIRECT_BYTE) {
+ if (get_pi_mask(pi) & WITH_SD_FIRST_DIRECT_BYTE) {
fread32 (&sd->sd_first_direct_byte);
} else {
sd->sd_first_direct_byte = 0xffffffff;
@@ -179,22 +191,23 @@ static void unpack_stat_data (struct packed_item * pi, struct buffer_head * bh,
fread16 (&sd->sd_mode);
- if (pi->mask & NLINK_BITS_32) {
+ if (get_pi_mask(pi) & NLINK_BITS_32) {
fread32 (&sd->sd_nlink);
} else {
__u16 nlink16;
fread16 (&nlink16);
- sd->sd_nlink = nlink16;
+ set_sd_v2_nlink (sd, le16_to_cpu(nlink16));
}
- if (pi->mask & SIZE_BITS_64) {
+ if (get_pi_mask(pi) & SIZE_BITS_64) {
fread64 (&sd->sd_size);
} else {
__u32 size32;
- fread32 (&size32);
- sd->sd_size = size32;
+ /* We need the endian conversions since sd->sd_size is 64 bit */
+ fread_le32 (&size32);
+ set_sd_v2_size (sd, size32 );
}
fread32 (&sd->sd_blocks);
@@ -213,25 +226,33 @@ static void unpack_indirect (struct packed_item * pi, struct buffer_head * bh,
int i;
__u16 v16;
- v16 = 0;
- if (pi->mask & ENTRY_COUNT)
- fread16 (&v16);
-
- set_entry_count (ih, v16);
+ if (!(get_pi_mask(pi) & IH_FREE_SPACE)) {
+ /* ih_free_space was not packed - set default */
+ set_ih_entry_count (ih, 0);
+ }
ind_item = (__u32 *)B_I_PITEM (bh, ih);
- if (pi->mask & WHOLE_INDIRECT) {
- fread (ind_item, pi->item_len, 1, stdin);
+
+ if (get_pi_mask(pi) & SAFE_LINK) {
+ *ind_item = cpu_to_le32(get_key_dirid(&ih->ih_key));
+ set_key_dirid(&ih->ih_key, (__u32)-1);
+ return;
+ }
+
+ if (get_pi_mask(pi) & WHOLE_INDIRECT) {
+ fread (ind_item, get_pi_item_len(pi), 1, stdin);
return;
}
end = ind_item + I_UNFM_NUM (ih);
while (ind_item < end) {
+ __u32 base;
fread32 (ind_item);
- fread16 (&v16);
+ fread_le16 (&v16);
+ base = le32_to_cpu(ind_item[0]);
for (i = 1; i < v16; i ++) {
- if (ind_item[0])
- ind_item [i] = ind_item[0] + i;
+ if (ind_item[0] != 0)
+ ind_item [i] = cpu_to_le32(base + i);
else
ind_item [i] = 0;
}
@@ -245,13 +266,23 @@ static void unpack_indirect (struct packed_item * pi, struct buffer_head * bh,
static void unpack_direct (struct packed_item * pi, struct buffer_head * bh,
struct item_head * ih)
{
- set_entry_count (ih, 0xffff);
- memset (bh->b_data + ih_location (ih), 'a', pi->item_len);
+ __u32 * d_item = (__u32 *)B_I_PITEM (bh, ih);
+
+ if (!(get_pi_mask(pi) & IH_FREE_SPACE))
+ /* ih_free_space was not packed - set default */
+ set_ih_entry_count (ih, 0xffff);
+
+ if (get_pi_mask(pi) & SAFE_LINK) {
+ *d_item = cpu_to_le32(get_key_dirid(&ih->ih_key));
+ set_key_dirid(&ih->ih_key, (__u32)-1);
+ } else {
+ memset (d_item, 'a', get_pi_item_len(pi));
+ }
return;
}
-static void unpack_leaf (int dev, hashf_t hash_func)
+static void unpack_leaf (int dev, hashf_t hash_func, __u16 blocksize)
{
static int unpacked_leaves = 0;
struct buffer_head * bh;
@@ -262,28 +293,26 @@ static void unpack_leaf (int dev, hashf_t hash_func)
__u32 v32;
/* block number */
- fread32 (&v32);
+ fread_le32 (&v32);
/* item number */
- fread16 (&v16);
+ fread_le16 (&v16);
if (verbose)
- fprintf (stderr, "leaf %d\n", v32);
+ reiserfs_warning (stderr, "leaf %d: %d items\n", v32, v16);
-
-
- bh = getblk (dev, v32, 4096);
+ bh = getblk (dev, v32, blocksize);
if (!bh)
die ("unpack_leaf: getblk failed");
- set_node_item_number (bh, v16);
- set_node_level (bh, DISK_LEAF_NODE_LEVEL);
- set_node_free_space (bh, bh->b_size - BLKH_SIZE);
+ set_blkh_nr_items (B_BLK_HEAD (bh), v16);
+ set_blkh_level (B_BLK_HEAD (bh), DISK_LEAF_NODE_LEVEL);
+ set_blkh_free_space (B_BLK_HEAD (bh), MAX_FREE_SPACE (bh->b_size));
ih = B_N_PITEM_HEAD (bh, 0);
- for (i = 0; i < v16; i ++, ih ++) {
+ for (i = 0; i < get_blkh_nr_items (B_BLK_HEAD (bh)); i ++, ih ++) {
#if 0
fread32 (&v32);
if (v32 != ITEM_START_MAGIC)
@@ -294,37 +323,46 @@ static void unpack_leaf (int dev, hashf_t hash_func)
fread (&pi, sizeof (struct packed_item), 1, stdin);
/* dir_id - if it is there */
- if (pi.mask & DIR_ID) {
+ if (get_pi_mask(&pi) & DIR_ID) {
fread32 (&v32);
- ih->ih_key.k_dir_id = v32;
+ set_key_dirid (&ih->ih_key, le32_to_cpu(v32));
} else {
if (!i)
die ("unpack_leaf: dir_id is not set");
- ih->ih_key.k_dir_id = (ih - 1)->ih_key.k_dir_id;
+ set_key_dirid (&ih->ih_key, get_key_dirid (&(ih - 1)->ih_key));
}
/* object_id - if it is there */
- if (pi.mask & OBJECT_ID) {
+ if (get_pi_mask(&pi) & OBJECT_ID) {
fread32 (&v32);
- ih->ih_key.k_objectid = v32;
+ set_key_objectid (&ih->ih_key, le32_to_cpu(v32));
} else {
if (!i)
die ("unpack_leaf: object_id is not set");
- ih->ih_key.k_objectid = (ih - 1)->ih_key.k_objectid;
+ set_key_objectid (&ih->ih_key, get_key_objectid (&(ih - 1)->ih_key));
}
// we need to set item format before offset unpacking
- set_key_format (ih, (pi.mask & NEW_FORMAT) ? KEY_FORMAT_2 : KEY_FORMAT_1);
+ set_ih_key_format (ih, (get_pi_mask(&pi) & NEW_FORMAT) ? KEY_FORMAT_2 : KEY_FORMAT_1);
// offset
- unpack_offset (&pi, ih);
+ unpack_offset (&pi, ih, bh->b_size);
/* type */
unpack_type (&pi, ih);
+ /* ih_free_space and ih_format */
+ if (get_pi_mask(&pi) & IH_FREE_SPACE) {
+ fread16 (&v16);
+ set_ih_entry_count (ih, le16_to_cpu(v16));
+ }
+
+ if (get_pi_mask(&pi) & IH_FORMAT)
+ fread16 (&ih->ih_format);
+
/* item length and item location */
- set_ih_item_len (ih, pi.item_len);
- set_ih_location (ih, (i ? ih_location (ih - 1) : bh->b_size) - pi.item_len);
+ set_ih_item_len (ih, get_pi_item_len(&pi));
+ set_ih_location (ih, (i ? get_ih_location (ih - 1) : bh->b_size) - get_pi_item_len(&pi));
// item itself
if (is_direct_ih (ih)) {
@@ -336,16 +374,20 @@ static void unpack_leaf (int dev, hashf_t hash_func)
} else if (is_stat_data_ih (ih)) {
unpack_stat_data (&pi, bh, ih);
}
- set_node_free_space (bh, node_free_space (bh) - (IH_SIZE + ih_item_len (ih)));
+ set_blkh_free_space (B_BLK_HEAD (bh), get_blkh_free_space (B_BLK_HEAD (bh)) -
+ (IH_SIZE + get_ih_item_len (ih)));
+
#if 0
fread32 (&v32);
if (v32 != ITEM_END_MAGIC)
die ("unpack_leaf: no end item magic found: block %lu, item %i",
bh->b_blocknr, i);
+ if (verbose)
+ reiserfs_warning (stderr, "%d: %H\n", i, ih);
#endif
}
- fread16 (&v16);
+ fread_le16 (&v16);
if (v16 != LEAF_END_MAGIC)
die ("unpack_leaf: wrong end signature found - %x, block %lu",
v16, bh->b_blocknr);
@@ -361,7 +403,7 @@ static void unpack_leaf (int dev, hashf_t hash_func)
if (what_unpacked)
reiserfs_bitmap_set_bit (what_unpacked, bh->b_blocknr);
- unpacked ++;
+ /*unpacked ++;*/
if (!(++ unpacked_leaves % 10))
fprintf (stderr, "#");
@@ -374,7 +416,7 @@ static void unpack_full_block (int dev, int blocksize)
__u32 block;
struct buffer_head * bh;
- fread32 (&block);
+ fread_le32 (&block);
if (verbose)
fprintf (stderr, "full #%d\n", block);
@@ -387,10 +429,18 @@ static void unpack_full_block (int dev, int blocksize)
if (who_is_this (bh->b_data, bh->b_size) == THE_SUPER && !what_unpacked) {
unsigned long blocks;
+ struct buffer_head * tmp;
- blocks = rs_block_count ((struct reiserfs_super_block *)(bh->b_data));
+ blocks = get_sb_block_count ((struct reiserfs_super_block *)(bh->b_data));
fprintf (stderr, "There were %lu blocks on the device\n", blocks);
what_unpacked = reiserfs_create_bitmap (blocks);
+
+ /* make file as long as filesystem is */
+ tmp = getblk (dev, blocks - 1, blocksize);
+ mark_buffer_dirty (tmp);
+ mark_buffer_uptodate (tmp, 0);
+ bwrite (tmp);
+ brelse (tmp);
}
mark_buffer_uptodate (bh, 1);
@@ -404,7 +454,7 @@ static void unpack_full_block (int dev, int blocksize)
if (what_unpacked)
reiserfs_bitmap_set_bit (what_unpacked, block);
- unpacked ++;
+ /*unpacked ++;*/
if (!(++ full_blocks_unpacked % 50))
fprintf (stderr, ".");
@@ -419,8 +469,8 @@ static void unpack_unformatted_bitmap (int dev, int blocksize)
int i;
char * buf;
- fread16 (&bmap_num);
- fread32 (&block_count);
+ fread_le16 (&bmap_num);
+ fread_le32 (&block_count);
buf = malloc (blocksize);
if (!buf)
@@ -436,17 +486,19 @@ static void unpack_unformatted_bitmap (int dev, int blocksize)
// read packed reiserfs partition metadata from stdin
-void unpack_partition (int dev)
+void unpack_partition (int fd, int jfd)
{
__u32 magic32;
__u16 magic16;
__u16 blocksize;
+ int dev = fd;
- fread32 (&magic32);
+ fread_le32 (&magic32);
if (magic32 != REISERFS_SUPER_MAGIC)
- die ("unpack_partition: reiserfs magic number not found");
+ die ("unpack_partition: reiserfs magic number (0x%x) not found - %x\n",
+ REISERFS_SUPER_MAGIC, magic32);
- fread16 (&blocksize);
+ fread_le16 (&blocksize);
if (verbose)
fprintf (stderr, "Blocksize %d\n", blocksize);
@@ -480,15 +532,27 @@ void unpack_partition (int dev)
}
fread (c + 1, 1, 1, stdin);
- magic16 = *(__u16 *)c;
+ magic16 = le16_to_cpu(*(__u16 *)c);
/*fread16 (&magic16);*/
switch (magic16 & 0xff) {
case LEAF_START_MAGIC:
- unpack_leaf (dev, code2func (magic16 >> 8));
+ leaves ++;
+ unpack_leaf (dev, code2func (magic16 >> 8), blocksize);
+ break;
+
+ case SEPARATED_JOURNAL_START_MAGIC:
+ if (Default_journal)
+ die ("file name for separated journal has to be specified");
+ dev = jfd;
+ break;
+
+ case SEPARATED_JOURNAL_END_MAGIC:
+ dev = fd;
break;
case FULL_BLOCK_START_MAGIC:
+ full ++;
unpack_full_block (dev, blocksize);
break;
@@ -505,7 +569,7 @@ void unpack_partition (int dev)
}
}
- fprintf (stderr, "Unpacked %d (%d) blocks\n", unpacked, what_unpacked ? reiserfs_bitmap_ones (what_unpacked) : 0);
+ fprintf (stderr, "Unpacked %d leaves, %d full blocks\n", leaves, full);
/* fclose (block_list);*/
@@ -514,8 +578,9 @@ void unpack_partition (int dev)
int main (int argc, char ** argv)
{
- int fd;
+ int fd, fdj = -2;
int c;
+ char * j_filename;
char * filename = ".bitmap";
struct rlimit lim = {0xffffffff, 0xffffffff};
@@ -526,13 +591,18 @@ int main (int argc, char ** argv)
fprintf (stderr, "sertlimit failed: %m\n");
}
- while ((c = getopt (argc, argv, "vb:")) != EOF) {
+ while ((c = getopt (argc, argv, "vb:j:")) != EOF) {
switch (c) {
case 'v':
verbose = 1;
+ break;
case 'b':
asprintf (&filename, "%s", optarg);
break;
+ case 'j':
+ Default_journal = 0;
+ asprintf (&j_filename, "%s", optarg);
+ break;
}
}
if (optind != argc - 1)
@@ -548,11 +618,24 @@ int main (int argc, char ** argv)
return 0;
}
- unpack_partition (fd);
+ if (!Default_journal) {
+ fdj = open (j_filename, O_RDWR | O_LARGEFILE);
+ if (fdj == -1) {
+ perror ("open failed");
+ return 0;
+ }
+ }
- if (what_unpacked && filename)
- reiserfs_bitmap_save (filename, what_unpacked);
+ unpack_partition (fd, fdj);
+
+ if (what_unpacked && filename) {
+ FILE * file = open_file(filename, "w+");
+ reiserfs_bitmap_save (file, what_unpacked);
+ close_file(file);
+ }
close (fd);
+ if (!Default_journal)
+ close (fdj);
return 0;
}
diff --git a/fsck/Makefile.am b/fsck/Makefile.am
index a64e913..8b72d3f 100644
--- a/fsck/Makefile.am
+++ b/fsck/Makefile.am
@@ -1,11 +1,11 @@
sbin_PROGRAMS = reiserfsck
-reiserfsck_SOURCES = main.c pass0.c pass1.c pass2.c semantic.c pass4.c lost+found.c \
-ubitmap.c uobjectid.c ustree.c ufile.c check.c check_tree.c journal.c info.c segments.c\
-fsck.h
+reiserfsck_SOURCES = main.c pass0.c pass1.c pass2.c semantic_check.c \
+semantic_rebuild.c pass4.c lost+found.c ubitmap.c uobjectid.c ustree.c \
+ufile.c check.c check_tree.c info.c super.c fsck.h
+
man_MANS = reiserfsck.8
EXTRA_DIST = $(man_MANS)
-LDADD = ../lib/libmisc.a ../reiserfscore/libcore.a
+LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a
-INCLUDES = -I../include -I.
diff --git a/fsck/Makefile.in b/fsck/Makefile.in
index 1d26e75..1e4174f 100644
--- a/fsck/Makefile.in
+++ b/fsck/Makefile.in
@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -62,31 +62,33 @@ MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
+sbindir = @sbindir@
sbin_PROGRAMS = reiserfsck
-reiserfsck_SOURCES = main.c pass0.c pass1.c pass2.c semantic.c pass4.c lost+found.c ubitmap.c uobjectid.c ustree.c ufile.c check.c check_tree.c journal.c info.c segments.c fsck.h
+reiserfsck_SOURCES = main.c pass0.c pass1.c pass2.c semantic_check.c semantic_rebuild.c pass4.c lost+found.c ubitmap.c uobjectid.c ustree.c ufile.c check.c check_tree.c info.c super.c fsck.h
+
man_MANS = reiserfsck.8
EXTRA_DIST = $(man_MANS)
-LDADD = ../lib/libmisc.a ../reiserfscore/libcore.a
-
-INCLUDES = -I../include -I.
+LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../include/config.h
CONFIG_CLEAN_FILES =
PROGRAMS = $(sbin_PROGRAMS)
-DEFS = @DEFS@ -I. -I$(srcdir)
+DEFS = @DEFS@ -I. -I$(srcdir) -I../include
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
-reiserfsck_OBJECTS = main.o pass0.o pass1.o pass2.o semantic.o pass4.o \
-lost+found.o ubitmap.o uobjectid.o ustree.o ufile.o check.o \
-check_tree.o journal.o info.o segments.o
+reiserfsck_OBJECTS = main.o pass0.o pass1.o pass2.o semantic_check.o \
+semantic_rebuild.o pass4.o lost+found.o ubitmap.o uobjectid.o ustree.o \
+ufile.o check.o check_tree.o info.o super.o
reiserfsck_LDADD = $(LDADD)
-reiserfsck_DEPENDENCIES = ../lib/libmisc.a ../reiserfscore/libcore.a
+reiserfsck_DEPENDENCIES = $(top_srcdir)/lib/libmisc.a \
+$(top_srcdir)/reiserfscore/libcore.a
reiserfsck_LDFLAGS =
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -241,7 +243,7 @@ distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
- cp -pr $$/$$file $(distdir)/$$file; \
+ cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
@@ -249,37 +251,53 @@ distdir: $(DISTFILES)
fi; \
done
check.o: check.c fsck.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
check_tree.o: check_tree.c fsck.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
info.o: info.c fsck.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
-journal.o: journal.c fsck.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
lost+found.o: lost+found.c fsck.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
main.o: main.c fsck.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h ../version.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h ../include/config.h ../version.h
pass0.o: pass0.c fsck.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
pass1.o: pass1.c fsck.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
pass2.o: pass2.c fsck.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
pass4.o: pass4.c fsck.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
-segments.o: segments.c fsck.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
-semantic.o: semantic.c fsck.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
+semantic_check.o: semantic_check.c fsck.h ../include/io.h \
+ ../include/misc.h ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
+semantic_rebuild.o: semantic_rebuild.c fsck.h ../include/io.h \
+ ../include/misc.h ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
+super.o: super.c fsck.h ../include/io.h ../include/misc.h \
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
ubitmap.o: ubitmap.c fsck.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
ufile.o: ufile.c fsck.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
uobjectid.o: uobjectid.c fsck.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
ustree.o: ustree.c fsck.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
info-am:
info: info-am
diff --git a/fsck/check.c b/fsck/check.c
index 37dacdd..bbd178e 100644
--- a/fsck/check.c
+++ b/fsck/check.c
@@ -18,8 +18,8 @@ static void check_directory_item (struct item_head * ih, struct buffer_head * bh
int i;
struct reiserfs_de_head * deh;
- for (i = 0, deh = B_I_DEH (bh, ih); i < ih_entry_count (ih) - 1; i ++)
- if (deh_offset(&deh[i]) > deh_offset(&deh[i + 1]))
+ for (i = 0, deh = B_I_DEH (bh, ih); i < get_ih_entry_count (ih) - 1; i ++)
+ if (get_deh_offset(&deh[i]) > get_deh_offset(&deh[i + 1]))
die ("check_directory_item: entries are not sorted properly");
}
@@ -74,8 +74,9 @@ static void is_there_unaccessed_items (struct buffer_head * bh)
ih = B_N_PITEM_HEAD (bh, 0);
for (i = 0; i < B_NR_ITEMS (bh); i ++, ih ++) {
- if (is_objectid_used (fs, ih->ih_key.k_objectid) == 0)
- die ("is_there_unaccessed_items: %lu is not marked as used", ih->ih_key.k_objectid);
+ if (is_objectid_used (fs, get_key_objectid (&ih->ih_key)) == 0)
+ die ("is_there_unaccessed_items: %lu is not marked as used",
+ ( long unsigned ) get_key_objectid (&ih->ih_key));
if (!is_item_reachable (ih)) {
die ("is_there_unaccessed_items: block %lu - unaccessed item found",
@@ -136,7 +137,7 @@ static int is_leaf_bad_xx (struct buffer_head * bh)
}
-static void reiserfsck_check_tree (int dev, int block, int size, check_function_t comp_func)
+static void reiserfsck_check_tree (int dev, unsigned long block, int size, check_function_t comp_func)
{
struct buffer_head * bh;
int what_node;
@@ -158,7 +159,7 @@ static void reiserfsck_check_tree (int dev, int block, int size, check_function_
die ("Not marked as used");
if (is_leaf_node (bh) && is_leaf_bad_xx (bh))
- die ("Bad leaf");
+ die ("Bad leaf %lu", bh->b_blocknr);
if (is_internal_node(bh) && is_internal_bad (bh))
die ("bad internal");
@@ -169,7 +170,7 @@ static void reiserfsck_check_tree (int dev, int block, int size, check_function_
dc = B_N_CHILD (bh, 0);
for (i = 0; i <= B_NR_ITEMS (bh); i ++, dc ++) {
- reiserfsck_check_tree (dev, dc->dc_block_number, size, comp_func);
+ reiserfsck_check_tree (dev, get_dc_child_blocknr (dc), size, comp_func);
g_dkey = B_N_PDELIM_KEY (bh, i);
}
} else if (is_leaf_node (bh)) {
@@ -187,7 +188,7 @@ static void reiserfsck_check_tree (int dev, int block, int size, check_function_
brelse (bh);
}
-static void reiserfsck_check_cached_tree (int dev, int block, int size)
+static void reiserfsck_check_cached_tree (int dev, unsigned long block, int size)
{
struct buffer_head * bh;
int what_node;
@@ -202,7 +203,7 @@ static void reiserfsck_check_cached_tree (int dev, int block, int size)
bh->b_count ++;
if (!B_IS_IN_TREE (bh)) {
- die ("reiserfsck_check_cached_tree: buffer (%b %z) not in tree", bh, bh);
+ reiserfs_panic ("reiserfsck_check_cached_tree: buffer (%b %z) not in tree", bh, bh);
}
what_node = who_is_this (bh->b_data, bh->b_size);
@@ -217,7 +218,7 @@ static void reiserfsck_check_cached_tree (int dev, int block, int size)
dc = B_N_CHILD (bh, 0);
for (i = 0; i <= B_NR_ITEMS (bh); i ++, dc ++) {
- reiserfsck_check_cached_tree (dev, dc->dc_block_number, size);
+ reiserfsck_check_cached_tree (dev, get_dc_child_blocknr (dc), size);
g_dkey = B_N_PDELIM_KEY (bh, i);
}
} else if (is_leaf_node (bh)) {
@@ -235,7 +236,8 @@ void reiserfsck_tree_check (check_function_t how_to_compare_neighbors)
{
g_left = 0;
g_dkey = 0;
- reiserfsck_check_tree (fs->s_dev, SB_ROOT_BLOCK(fs), fs->s_blocksize, how_to_compare_neighbors);
+ reiserfsck_check_tree (fs->fs_dev, get_sb_root_block (fs->fs_ondisk_sb),
+ fs->fs_blocksize, how_to_compare_neighbors);
brelse (g_right);
}
@@ -248,7 +250,8 @@ void reiserfsck_check_pass1 ()
void check_cached_tree ()
{
- reiserfsck_check_cached_tree (fs->s_dev, SB_ROOT_BLOCK (fs), fs->s_blocksize);
+ reiserfsck_check_cached_tree (fs->fs_dev, get_sb_root_block (fs->fs_ondisk_sb),
+ fs->fs_blocksize);
}
void reiserfsck_check_after_all ()
@@ -277,9 +280,9 @@ static int is_bad_sd (struct item_head * ih, char * item)
#include <sys/mount.h>
-int blocks_on_device (int dev, int blocksize)
+unsigned long blocks_on_device (int dev, int blocksize)
{
- int size;
+ unsigned long size;
if (ioctl (dev, BLKGETSIZE, &size) >= 0) {
return size / (blocksize / 512);
@@ -309,21 +312,12 @@ int is_internal_bad (struct buffer_head * bh)
return 0;
for (i = 0; i < B_NR_ITEMS (bh); i ++) {
key = B_N_PDELIM_KEY (bh, i);
- if (//key->k_dir_id >= key->k_objectid ||
- key->u.k_offset_v1.k_uniqueness != V1_DIRENTRY_UNIQUENESS && key->u.k_offset_v1.k_uniqueness != V1_DIRECT_UNIQUENESS &&
- key->u.k_offset_v1.k_uniqueness != V1_INDIRECT_UNIQUENESS && key->u.k_offset_v1.k_uniqueness != V1_SD_UNIQUENESS &&
- key->u.k_offset_v2.k_type != TYPE_DIRENTRY && key->u.k_offset_v2.k_type != TYPE_DIRECT &&
- key->u.k_offset_v2.k_type != TYPE_INDIRECT && key->u.k_offset_v2.k_type != TYPE_STAT_DATA //&&
- // key->u.k_offset_v1.k_uniqueness != V1_ANY_UNIQUENESS && key->u.k_offset_v2.k_type != TYPE_ANY
- )
+ if (!KEY_IS_STAT_DATA_KEY (key) && !KEY_IS_DIRECTORY_KEY (key) &&
+ !KEY_IS_DIRECT_KEY (key) && !KEY_IS_INDIRECT_KEY (key))
+ /* key of unknown item */
return 1;
}
return 0;
}
-
-
-
-
-
diff --git a/fsck/check_tree.c b/fsck/check_tree.c
index 6615409..621afb6 100644
--- a/fsck/check_tree.c
+++ b/fsck/check_tree.c
@@ -4,6 +4,63 @@
#include "fsck.h"
+struct check_relocated {
+ __u32 old_dir_id;
+ __u32 old_objectid;
+ /*mode_t mode;*/
+ struct check_relocated * next;
+};
+
+struct check_relocated * relocated_list;
+
+void to_be_relocated (struct key * key)
+{
+ struct check_relocated * cur, * prev, * new_relocated;
+
+ cur = relocated_list;
+ prev = 0;
+
+ while (cur && comp_short_keys(key, (struct key *)cur) != 1) {
+ if (comp_short_keys (key, (struct key *)cur) == 0)
+ return;
+ prev = cur;
+ cur = cur->next;
+ }
+
+ new_relocated = getmem (sizeof (struct check_relocated));
+ copy_short_key ((struct key *)new_relocated, key);
+
+ if (prev) {
+ new_relocated->next = prev->next;
+ prev->next = new_relocated;
+ } else {
+ new_relocated->next = 0;
+ relocated_list = new_relocated;
+ }
+}
+
+int should_be_relocated (struct key * key)
+{
+ struct check_relocated * cur, * next;
+ int ret = 0;
+
+ cur = relocated_list;
+
+ while (cur && comp_short_keys(key, (struct key *)cur) != 1) {
+ if (comp_short_keys (key, (struct key *)cur) == 0) {
+ ret = 1;
+ break;
+ }
+ cur = cur->next;
+ }
+
+ while (relocated_list != cur) {
+ next = relocated_list->next;
+ freemem (relocated_list);
+ relocated_list = next;
+ }
+ return ret;
+}
//
//
@@ -27,23 +84,27 @@
sure, that no blocks are pointed to from more than one place we use
additional bitmap (control_bitmap). If we see pointer to a block we set
corresponding bit to 1. If it is set already - run fsck with --rebuild-tree */
-static reiserfs_bitmap_t control_bitmap;
+static reiserfs_bitmap_t * control_bitmap;
+static reiserfs_bitmap_t * source_bitmap;
static int tree_scanning_failed = 0;
/* 1 if block is not marked as used in the bitmap */
-static int is_block_free (reiserfs_filsys_t fs, unsigned long block)
+static int is_block_free (reiserfs_filsys_t * fs, unsigned long block)
{
- return !reiserfs_bitmap_test_bit (fsck_disk_bitmap (fs), block);
+ return !reiserfs_bitmap_test_bit (source_bitmap, block);
}
+/*static int hits = 0;*/
+
/* we have seen this block in the tree, mark corresponding bit in the
control bitmap */
static void we_met_it (unsigned long block)
{
reiserfs_bitmap_set_bit (control_bitmap, block);
+ /*hits ++;*/
}
@@ -54,85 +115,69 @@ static int did_we_meet_it (unsigned long block)
}
-static void init_control_bitmap (reiserfs_filsys_t fs)
+static void init_control_bitmap (reiserfs_filsys_t * fs)
{
int i;
+ unsigned long block;
+ unsigned long reserved;
+
- control_bitmap = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
+ control_bitmap = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb));
if (!control_bitmap)
die ("init_control_bitmap: could not create control bitmap");
+ /*printf ("Initially number of zeros in control bitmap %d\n", reiserfs_bitmap_zeros (control_bitmap));*/
+
/* skipped and super block */
- for (i = 0; i <= SB_BUFFER_WITH_SB (fs)->b_blocknr; i ++)
+ for (i = 0; i <= fs->fs_super_bh->b_blocknr; i ++)
we_met_it (i);
+ /*printf ("SKIPPED: %d blocks marked used (%d)\n", hits, reiserfs_bitmap_zeros (control_bitmap));
+ hits = 0;*/
+
/* bitmaps */
- for (i = 0; i < SB_BMAP_NR (fs); i ++)
- we_met_it (SB_AP_BITMAP (fs)[i]->b_blocknr);
+ block = fs->fs_super_bh->b_blocknr + 1;
+ for (i = 0; i < get_sb_bmap_nr (fs->fs_ondisk_sb); i ++) {
+ we_met_it (block);
- for (i = 0; i < rs_journal_size (fs->s_rs) + 1; i ++)
- we_met_it (i + SB_JOURNAL_BLOCK (fs));
+ if (spread_bitmaps (fs))
+ block = (block / (fs->fs_blocksize * 8) + 1) * (fs->fs_blocksize * 8);
+ else
+ block ++;
+ }
+ /*printf ("BITMAPS: %d blocks marked used (%d)\n", hits, reiserfs_bitmap_zeros (control_bitmap));
+ hits = 0;*/
+
+ /* mark as used area of the main device either containing a journal or
+ reserved to hold it */
-}
+ reserved = get_size_of_journal_or_reserved_area (fs->fs_ondisk_sb);
+
+ /* where does journal area (or reserved journal area) start from */
+ if (!is_new_sb_location (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) &&
+ !is_old_sb_location (fs->fs_super_bh->b_blocknr, fs->fs_blocksize))
+ die ("init_control_bitmap: wrong super block");
-#if 0
-static void show_diff (int n, char * disk, char * control, int bits)
-{
- int i;
- int last_diff = 0;
- int from, num;
-
- fsck_log ("bitmap %d does not match to the correct one\n", n);
-
- from = 0;
- num = 0;
- for (i = 0; i < bits; i ++) {
- if (test_bit (i, disk) && !test_bit (i, control)) {
- if (last_diff == 1) {
- num ++;
- continue;
- } else if (last_diff == 2) {
- fsck_log ("Block [%d-%d] free in disk bitmap, used in control\n", from, from + num - 1);
- }
- num = 1;
- from = n * bits + i;
- last_diff = 1;
- continue;
- }
- if (!test_bit (i, disk) && test_bit (i, control)) {
- if (last_diff == 2) {
- num ++;
- continue;
- } else if (last_diff == 1) {
- fsck_log ("Block [%d-%d] used in disk bitmap, free in control\n", from, from + num - 1);
- }
- num = 1;
- from = n * bits + i;
- last_diff = 2;
- continue;
+ block = get_journal_start_must (fs);
+
+ for (i = block; i < reserved + block; i ++)
+ we_met_it (i);
+
+ if (fs->fs_badblocks_bm)
+ for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) {
+ if (reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, i))
+ we_met_it (i);
}
- /* the same bits */
- if (last_diff == 1)
- fsck_log ("Block [%d-%d] used in disk bitmap, free in control\n", from, from + num - 1);
- if (last_diff == 2)
- fsck_log ("Block [%d-%d] free in disk bitmap, used in control\n", from, from + num - 1);
-
- num = 0;
- from = 0;
- last_diff = 0;
- continue;
- }
}
-#endif
/* if we managed to complete tree scanning and if control bitmap and/or proper
amount of free blocks mismatch with bitmap on disk and super block's
s_free_blocks - we can fix that */
-static void compare_bitmaps (reiserfs_filsys_t fs)
+static void handle_bitmaps (reiserfs_filsys_t * fs)
{
- int diff;
+ int diff, problem = 0;
if (tree_scanning_failed) {
fsck_progress ("Could not scan whole tree. "
@@ -143,195 +188,350 @@ static void compare_bitmaps (reiserfs_filsys_t fs)
fsck_progress ("Comparing bitmaps..");
/* check free block counter */
- if (SB_FREE_BLOCKS (fs) != reiserfs_bitmap_zeros (control_bitmap)) {
+ if (get_sb_free_blocks (fs->fs_ondisk_sb) != reiserfs_bitmap_zeros (control_bitmap)) {
fsck_log ("free block count %lu mismatches with a correct one %lu. \n",
- SB_FREE_BLOCKS (fs), reiserfs_bitmap_zeros (control_bitmap));
-#if 0
- if (fsck_fix_fixable (fs)) {
- set_free_blocks (fs->s_rs, reiserfs_bitmap_zeros (control_bitmap));
- mark_buffer_dirty (fs->s_sbh);
- mark_filesystem_dirty (fs);
- fsck_log ("Fixed\n");
- } else {
- fsck_log ("Can be fixed by --fix-fixable\n");
- }
-#endif
+ get_sb_free_blocks (fs->fs_ondisk_sb),
+ reiserfs_bitmap_zeros (control_bitmap));
+ problem++;
+// one_more_corruption (fs, fatal); /* for now */
}
- diff = reiserfs_bitmap_compare (fsck_disk_bitmap (fs), control_bitmap);
+ diff = reiserfs_bitmap_compare (source_bitmap, control_bitmap);
if (diff) {
- fsck_log ("on-disk bitmap does not match to the correct one. %d bytes differ\n", diff);
-#if 0
- if (fsck_fix_fixable (fs)) {
- reiserfs_flush_bitmap (control_bitmap, fs);
- mark_filesystem_dirty (fs);
- fsck_log ("Fixed\n");
- } else {
- fsck_log ("Can be fixed by --fix-fixable\n");
- }
-#endif
+ fsck_log ("on-disk bitmap does not match to the correct one. \n", diff);
+ problem++;
}
- fsck_progress ("ok\n");
+ if (problem) {
+ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) {
+ fsck_progress ("Trying to fix bitmap ..\n", diff);
+ /* mark blocks as used in source bitmap if they are used in control bitmap */
+ reiserfs_bitmap_disjunction (source_bitmap, control_bitmap);
+ /* change used blocks count accordinly source bitmap,
+ copy bitmap changes to on_disk bitmap */
+ set_sb_free_blocks (fs->fs_ondisk_sb, reiserfs_bitmap_zeros (source_bitmap));
+ reiserfs_bitmap_copy (fs->fs_bitmap2, source_bitmap);
+ mark_buffer_dirty (fs->fs_super_bh);
+ /* check again */
+ if ((diff = reiserfs_bitmap_compare (source_bitmap, control_bitmap)) != 0) {
+ /* do not mark them as fatal or fixable because one can live with leaked space.
+ So this is not a fatal corruption, and fix-fixable cannot fix it */
+// one_more_corruption (fs, fatal);
+ fsck_progress (" bitmaps were not recovered. \n"
+ "\tYou can either run rebuild-tree or live with %d leaked blocks\n", diff);
+ } else {
+ fsck_progress ("ok\n");
+ }
+ } else {
+ while (problem) {
+ /* fixable corruptions because we can try to recover them w/out rebuilding the tree */
+ one_more_corruption (fs, fixable);
+ problem --;
+ }
+ }
+ } else
+ fsck_progress ("ok\n");
+
return;
}
-
/* is this block legal to be pointed to by some place of the tree? */
-static int bad_block_number (struct super_block * s, unsigned long block)
+static int bad_block_number (reiserfs_filsys_t * fs, unsigned long block)
{
- if (block >= SB_BLOCK_COUNT (s)) {
- /*reiserfs_warning ("block out of filesystem boundary found\n");*/
- return 1;
- }
+ if (block >= get_sb_block_count (fs->fs_ondisk_sb) ||
+ not_data_block (fs, block)) {
+ /* block has value which can not be used as a pointer in a tree */
+
+ return 1;
+/*
+ if (is_unfm_pointer) {
+ // unformatted node pointer will be zeroed
+ one_more_corruption (fs, fixable);
+ return 1;
+ }
+
+ // internal nodes can not have wrong pointer
+ one_more_corruption (fs, fatal);
+ return 1;
+*/
- if (not_data_block (s, block)) {
- /*reiserfs_warning ("not data block (%lu) is used in the tree\n",
- block);*/
- return 1;
}
- if (is_block_free (s, block)) {
- fsck_log ("block %lu is not marked as used in the disk bitmap\n", block);
- return 0;
+ if (is_block_free (fs, block)) {
+ /* block is marked free - bitmap problems will be handled later */
+ //one_more_corruption (fs, fixable);
}
return 0;
}
-static int got_already (struct super_block * s, unsigned long block)
+static int got_already (reiserfs_filsys_t * fs, unsigned long block)
{
+#if 0
if (0/*opt_fsck_mode == FSCK_FAST_REBUILD*/){
if (is_block_used(block)){
fsck_log ("block %lu is in tree already\n", block);
return 1;
}
} else {
- if (did_we_meet_it (block)) {
- /*fsck_log ("block %lu is in tree already\n", block);*/
- return 1;
- }
- we_met_it (block);
+#endif
+
+ if (did_we_meet_it (block)) {
+ /* block is in tree at least twice */
+ return 1;
}
+ we_met_it (block);
return 0;
}
/* 1 if some of fields in the block head of bh look bad */
-static int bad_block_head (struct buffer_head * bh)
+static int bad_block_head (reiserfs_filsys_t * fs, struct buffer_head * bh)
{
struct block_head * blkh;
+ int sum_length = 0;
blkh = B_BLK_HEAD (bh);
- if (le16_to_cpu (blkh->blk_nr_item) > (bh->b_size - BLKH_SIZE) / IH_SIZE) {
- fsck_log ("block %lu has wrong blk_nr_items (%z)\n",
+ if (get_blkh_nr_items (blkh) > (bh->b_size - BLKH_SIZE) / IH_SIZE) {
+ fsck_log ("block %lu has wrong blk_nr_items (%z)\n",
bh->b_blocknr, bh);
+ one_more_corruption (fs, fatal);
return 1;
}
- if (le16_to_cpu (blkh->blk_free_space) >
- bh->b_size - BLKH_SIZE - IH_SIZE * le16_to_cpu (blkh->blk_nr_item)) {
- fsck_log ("block %lu has wrong blk_free_space %z\n",
- bh->b_blocknr, bh);
+
+ if (who_is_this (bh->b_data, bh->b_size) != THE_LEAF) {
+ fsck_log ("leaf %lu has wrong structure\n", bh->b_blocknr);
+ one_more_corruption (fs, fatal);
return 1;
}
+
+ sum_length = (get_blkh_nr_items (blkh) > 0) ?
+ get_ih_location (B_N_PITEM_HEAD (bh, get_blkh_nr_items (blkh) - 1)) : bh->b_size;
+
+ if (get_blkh_free_space (blkh) !=
+ sum_length - BLKH_SIZE - IH_SIZE * get_blkh_nr_items (blkh))
+ {
+ fsck_log ("block (%lu) has wrong blk_free_space (%lu) should be (%lu)",
+ bh->b_blocknr, get_blkh_free_space (blkh), sum_length - BLKH_SIZE - IH_SIZE * get_blkh_nr_items (blkh) );
+ if (fsck_mode(fs) == FSCK_FIX_FIXABLE) {
+ set_blkh_free_space (blkh, sum_length - BLKH_SIZE - IH_SIZE * get_blkh_nr_items (blkh));
+ fsck_log (" - fixed on (%lu)\n", get_blkh_free_space (blkh));
+ mark_buffer_dirty (bh);
+ } else {
+ fsck_log ("\n");
+ one_more_corruption (fs, fixable);
+ return 1;
+ }
+ }
+
return 0;
}
-
/* 1 if it does not look like reasonable stat data */
-static int bad_stat_data (struct buffer_head * bh, struct item_head * ih)
+static int bad_stat_data (reiserfs_filsys_t * fs, struct buffer_head * bh, struct item_head * ih)
{
unsigned long objectid;
- int pos;
+ __u32 pos;
+ __u32 links;
+ struct stat_data * sd;
/*
if (opt_fsck_mode == FSCK_FAST_REBUILD)
return 0;
*/
- objectid = le32_to_cpu (ih->ih_key.k_objectid);
+ objectid = get_key_objectid (&ih->ih_key);
if (!is_objectid_used (fs, objectid)) {
/* FIXME: this could be cured right here */
fsck_log ("\nbad_stat_data: %lu is marked free, but used by an object %k\n",
- objectid, &ih->ih_key);
+ objectid, &ih->ih_key);
+
+ /* if it is FIX_FIXABLE we flush objectid map at the end
+ no way to call one_less_corruption later
+ */
+ if (fsck_mode (fs) != FSCK_FIX_FIXABLE)
+ one_more_corruption (fs, fixable);
}
if (is_objectid_really_used (proper_id_map (fs), objectid, &pos)) {
fsck_log ("\nbad_stat_data: %lu is shared by at least two files\n",
objectid);
+ if (fsck_mode (fs) == FSCK_FIX_FIXABLE)
+ to_be_relocated (&ih->ih_key);
+
+ one_more_corruption (fs, fixable);
+
return 0;
}
- mark_objectid_really_used (proper_id_map (fs), objectid);
+
+ sd = (struct stat_data *)B_I_PITEM(bh,ih);
+ if (fsck_mode (fs) == FSCK_CHECK) {
+ get_sd_nlink (ih, sd, &links);
+ if (S_ISDIR(sd->sd_mode)) {
+ if (links < 2) {
+ fsck_log ("%s: block %lu, [%k], directory SD has bad nlink number\n",
+ __FUNCTION__, bh->b_blocknr, &ih->ih_key);
+ one_more_corruption (fs, fixable);
+ }
+ } else {
+ if (links == 0) {
+ fsck_log ("%s: block %lu, [%k], SD has bad nlink number\n",
+ __FUNCTION__, bh->b_blocknr, &ih->ih_key);
+ one_more_corruption (fs, fixable);
+ }
+ }
+ } else {
+ links = 0;
+ set_sd_nlink (ih, sd, &links);
+ mark_buffer_dirty (bh);
+ }
+
+ __mark_objectid_really_used (proper_id_map (fs), objectid, pos);
return 0;
}
/* it looks like we can check item length only */
-static int bad_direct_item (struct buffer_head * bh, struct item_head * ih)
+static int bad_direct_item (reiserfs_filsys_t * fs, struct buffer_head * bh, struct item_head * ih)
{
return 0;
}
+inline void handle_one_pointer (reiserfs_filsys_t * fs, struct buffer_head * bh, __u32 * ptr) {
+ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) {
+ fsck_log (" - fixed");
+ *ptr = 0;
+ mark_buffer_dirty (bh);
+ } else {
+ one_more_corruption (fs, fixable);
+ }
+}
+
+/*
+static int bad_badblocks_item (reiserfs_filsys_t * fs, struct buffer_head * bh,
+ struct item_head * ih) {
+ int i;
+ __u32 * ind = (__u32 *)B_I_PITEM (bh, ih);
+
+ if (get_ih_item_len (ih) % 4) {
+ fsck_log ("%s: block %lu: item (%H) has bad length\n", __FUNCTION__,
+ bh->b_blocknr, ih);
+ one_more_corruption (fs, fatal);
+ return 1;
+ }
+
+ for (i = 0; i < I_UNFM_NUM (ih); i ++) {
+// __u32 unfm_ptr;
+
+// unfm_ptr = le32_to_cpu (ind [i]);
+ if (!le32_to_cpu (ind [i])) {
+ fsck_log ("%s: block %lu: badblocks item (%H) has zero pointer.");
+ fsck_log ("Not an error, but could be deleted with --fix-fixable\n",
+ __FUNCTION__, bh->b_blocknr, ih);
+ continue;
+ }
+
+ // check list of badblocks pointers
+ if (le32_to_cpu (ind [i]) >= get_sb_block_count (fs->fs_ondisk_sb)) {
+ fsck_log ("%s: badblock pointer (block %lu) points out of disk spase (%lu)",
+ __FUNCTION__, bh->b_blocknr, le32_to_cpu (ind [i]));
+ handle_one_pointer (fs, bh, &ind[i]);
+ fsck_log ("\n");
+ }
+
+ if (did_we_meet_it (le32_to_cpu (ind [i]))) {
+ // it can be
+ // 1. not_data_block
+ // delete pointer
+ // 2. ind [i] or internal/leaf
+ // advice to run fix-fixable if there is no fatal errors
+ // with list of badblocks, say that it could fix it.
+
+ if (not_data_block (fs, le32_to_cpu (ind [i]))) {
+ fsck_log ("%s: badblock pointer (block %lu) points on fs metadata (%lu)",
+ __FUNCTION__, bh->b_blocknr, le32_to_cpu (ind [i]));
+ handle_one_pointer (fs, bh, &ind[i]);
+ fsck_log ("\n");
+ } else {
+ one_more_corruption (fs, badblocks);
+ fsck_log ("%s: badblock item points to a block"
+ " which in the tree already. Use --badblock-file option"
+ " to fix the problem\n", __FUNCTION__);
+ }
+ } else {
+ we_met_it (le32_to_cpu (ind [i]));
+ }
+ }
+
+ return 0;
+}
+*/
+
/* for each unformatted node pointer: make sure it points to data area and
that it is not in the tree yet */
-static int bad_indirect_item (reiserfs_filsys_t fs, struct buffer_head * bh,
+static int bad_indirect_item (reiserfs_filsys_t * fs, struct buffer_head * bh,
struct item_head * ih)
{
int i;
__u32 * ind = (__u32 *)B_I_PITEM (bh, ih);
- if (ih_item_len (ih) % 4) {
- fsck_log ("bad_indirect_item: block %lu: item (%H) has bad length\n",
- bh->b_blocknr, ih);
+ if (get_ih_item_len (ih) % 4) {
+ fsck_log ("%s: block %lu: item (%H) has bad length\n",
+ __FUNCTION__, bh->b_blocknr, ih);
+ one_more_corruption (fs, fatal);
return 1;
}
for (i = 0; i < I_UNFM_NUM (ih); i ++) {
- __u32 unfm_ptr;
+// __u32 unfm_ptr;
- unfm_ptr = le32_to_cpu (ind [i]);
- if (!unfm_ptr)
+ fsck_check_stat (fs)->unfm_pointers ++;
+// unfm_ptr = le32_to_cpu (ind [i]);
+ if (!le32_to_cpu (ind [i])) {
+ fsck_check_stat (fs)->zero_unfm_pointers ++;
continue;
+ }
/* check unformatted node pointer and mark it used in the
control bitmap */
- if (bad_block_number (fs, unfm_ptr)) {
- fsck_log ("bad_indirect_item: block %lu: item %H has bad pointer %d: %lu",
- bh->b_blocknr, ih, i, unfm_ptr);
- if (fsck_fix_fixable (fs)) {
- fsck_log (" - fixed");
- ind [i] = 0;
- mark_buffer_dirty (bh);
- }
+ if (bad_block_number (fs, le32_to_cpu (ind [i]))) {
+ fsck_log ("%s: block %lu: item %H has bad pointer %d: %lu",
+ __FUNCTION__, bh->b_blocknr, ih, i, le32_to_cpu (ind [i]));
+ handle_one_pointer (fs, bh, &ind[i]);
fsck_log ("\n");
continue;
}
- if (got_already (fs, unfm_ptr)) {
- fsck_log ("bad_indirect_item: block %lu: item %H has a pointer %d "
+ if (got_already (fs, le32_to_cpu (ind [i]))) {
+ fsck_log ("%s: block %lu: item %H has a pointer %d "
"to the block %lu which is in tree already",
- bh->b_blocknr, ih, i, unfm_ptr);
- if (fsck_fix_fixable (fs)) {
- fsck_log (" - fixed");
- ind [i] = 0;
- mark_buffer_dirty (bh);
- }
+ __FUNCTION__, bh->b_blocknr, ih, i, le32_to_cpu (ind [i]));
+ handle_one_pointer (fs, bh, &ind [i]);
fsck_log ("\n");
continue;
}
}
+#if 0
/* delete this check for 3.6 */
- if (ih_free_space (ih) > fs->s_blocksize - 1)
- fsck_log ("bad_indirect_item: %H has wrong ih_free_space\n", ih);
+ if (get_ih_free_space (ih) > fs->fs_blocksize - 1) {
+ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) {
+ /*FIXME: fix it if needed*/
+ } else {
+ fsck_log ("bad_indirect_item: %H has wrong ih_free_space\n", ih);
+ one_more_corruption (fs, fixable);
+ }
+ }
+#endif
+
return 0;
}
/* FIXME: this was is_bad_directory from pass0.c */
-static int bad_directory_item (struct buffer_head * bh, struct item_head * ih)
+static int bad_directory_item (reiserfs_filsys_t * fs, struct buffer_head * bh, struct item_head * ih)
{
int i;
char * name;
@@ -345,39 +545,50 @@ static int bad_directory_item (struct buffer_head * bh, struct item_head * ih)
/* make sure item looks like a directory */
- if (ih_item_len (ih) / (DEH_SIZE + min_entry_size) < ih_entry_count (ih))
+ if (get_ih_item_len (ih) / (DEH_SIZE + min_entry_size) < get_ih_entry_count (ih)) {
/* entry count can not be that big */
+ fsck_log ("%s: block %lu: directory item %H has corrupted structure\n",
+ __FUNCTION__, bh->b_blocknr, ih);
+ one_more_corruption (fs, fatal);
return 1;
+ }
- if (deh[ih_entry_count (ih) - 1].deh_location != DEH_SIZE * ih_entry_count (ih))
+ if (get_deh_location (&deh[get_ih_entry_count (ih) - 1]) != DEH_SIZE * get_ih_entry_count (ih)) {
/* last entry should start right after array of dir entry headers */
+ fsck_log ("%s: block %lu: directory item %H has corrupted structure\n",
+ __FUNCTION__, bh->b_blocknr, ih);
+ one_more_corruption (fs, fatal);
return 1;
+ }
/* check name hashing */
- for (i = 0; i < ih_entry_count (ih); i ++, deh ++) {
- namelen = name_length (ih, deh, i);
+ for (i = 0; i < get_ih_entry_count (ih); i ++, deh ++) {
+ namelen = name_in_entry_length (ih, deh, i);
name = name_in_entry (deh, i);
- if (!is_properly_hashed (fs, name, namelen, deh_offset (deh))) {
+ if (!is_properly_hashed (fs, name, namelen, get_deh_offset (deh))) {
+ fsck_log ("%s: block %lu: directory item %H has hashed bad entry\n",
+ __FUNCTION__, bh->b_blocknr, ih);
+ one_more_corruption (fs, fatal);
return 1;
}
}
deh = B_I_DEH (bh, ih);
- state = 0;
- set_bit (DEH_Visible, &state);
+ state = (1 << DEH_Visible2);
/* ok, items looks like a directory */
- for (i = 0; i < ih_entry_count (ih); i ++, deh ++) {
- if (deh_state (deh) != state) {
+ for (i = 0; i < get_ih_entry_count (ih); i ++, deh ++) {
+ if (get_deh_state (deh) != state) {
fsck_log ("bad_directory_item: block %lu: item %H has entry "
- "\"%.*s\" with wrong deh_state %o",
- bh->b_blocknr, ih, name_length (ih, deh, i),
- name_in_entry (deh, i), deh_state (deh));
- if (fsck_fix_fixable (fs)) {
- deh->deh_state = 0;
- mark_de_visible (deh);
+ "\"%.*s\" with wrong deh_state %o - expected %o",
+ bh->b_blocknr, ih, name_in_entry_length (ih, deh, i),
+ name_in_entry (deh, i), get_deh_state (deh), state );
+ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) {
+ set_deh_state (deh, 1 << DEH_Visible2);
mark_buffer_dirty (bh);
fsck_log (" - fixed");
- }
+ } else
+ one_more_corruption (fs, fixable);
+
fsck_log ("\n");
}
}
@@ -386,155 +597,240 @@ static int bad_directory_item (struct buffer_head * bh, struct item_head * ih)
}
-static int bad_item (struct super_block * s, struct buffer_head * bh, int i)
+static int bad_item (reiserfs_filsys_t * fs, struct buffer_head * bh, int num)
{
struct item_head * ih;
- ih = B_N_PITEM_HEAD (bh, i);
+ ih = B_N_PITEM_HEAD (bh, num);
+
+ if (get_key_dirid (&ih->ih_key) == (__u32)-1) {
+ if (get_key_objectid (&ih->ih_key) != (__u32)-1) {
+ /* safe link can be
+ -1 object_id 0x1 -2 (truncate) or
+ -1 object_id blocksize+1 -1 (unlink)
+ */
+
+ if (is_direct_ih(ih))
+ if (get_offset(&ih->ih_key) == fs->fs_blocksize + 1)
+ if (get_ih_item_len (ih) == 4) {
+ /*fsck_log("vpf-00010: safe link found [%k]\n", &ih->ih_key);*/
+ fsck_check_stat(fs)->safe ++;
+ return 0;
+ }
+
+ if (is_indirect_ih(ih))
+ if(get_offset(&ih->ih_key) == 0x1)
+ if (get_ih_item_len (ih) == 4) {
+ /*fsck_log("vpf-00020: safe link found [%k]\n", &ih->ih_key);*/
+ fsck_check_stat(fs)->safe ++;
+ return 0;
+ }
+
+ /* it does not look like safe link */
+
+ /* dir_id == -1 can be used only by safe links */
+ one_more_corruption (fs, fatal);
+ fsck_log ("%s: vpf-10290: block %lu item with wrong key (%k) found\n", __FUNCTION__, bh->b_blocknr, &ih->ih_key);
+ return 1;
+ } else {
+
+/* BAD BLOCK LIST SUPPORT
+ if (is_indirect_ih (ih)) {
+ // it looks like badblocks item
+ if (fs->fs_badblocks_bm)
+ return 0;
+ else
+ return bad_badblocks_item (fs, bh, ih);
+ } else {*/
+
+ one_more_corruption (fs, fatal);
+ fsck_log ("%s: vpf-10300: block %lu item with wrong key (%k) found\n", __FUNCTION__, bh->b_blocknr, &ih->ih_key);
+ return 1;
+ }
+ } else if (get_key_objectid (&ih->ih_key) == (__u32)-1) {
+ one_more_corruption (fs, fatal);
+ fsck_log ("%s: vpf-10310: block %lu item with wrong key (%k) found\n", __FUNCTION__, bh->b_blocknr, &ih->ih_key);
+ return 1;
+ }
+
if (is_stat_data_ih (ih))
- return bad_stat_data (bh, ih);
+ return bad_stat_data (fs, bh, ih);
if (is_direct_ih (ih))
- return bad_direct_item (bh, ih);
+ return bad_direct_item (fs, bh, ih);
if (is_indirect_ih(ih))
- return bad_indirect_item (s, bh, ih);
+ return bad_indirect_item (fs, bh, ih);
- return bad_directory_item (bh, ih);
+ return bad_directory_item (fs, bh, ih);
}
/* 1 if i-th and (i-1)-th items can not be neighbors in a leaf */
-int bad_pair (struct super_block * s, struct buffer_head * bh, int i)
+int bad_pair (reiserfs_filsys_t * fs, struct buffer_head * bh, int pos)
{
struct item_head * ih;
- ih = B_N_PITEM_HEAD (bh, i);
+ ih = B_N_PITEM_HEAD (bh, pos);
-
- if (comp_keys (&((ih - 1)->ih_key), &ih->ih_key) != -1)
+ if (comp_keys (&((ih - 1)->ih_key), &ih->ih_key) != -1) {
+ if (fsck_mode (fs) != FSCK_REBUILD)
+ one_more_corruption (fs, fatal);
return 1;
+ }
if (is_stat_data_ih (ih))
/* left item must be of another object */
- if (comp_short_keys (&((ih - 1)->ih_key), &ih->ih_key) != -1)
+ if (comp_short_keys (&((ih - 1)->ih_key), &ih->ih_key) != -1) {
+ if (fsck_mode (fs) != FSCK_REBUILD)
+ one_more_corruption (fs, fatal);
return 1;
+ }
+
+ if (get_key_dirid (&ih->ih_key) == (__u32)-1) {
+ if (get_key_objectid (&ih->ih_key) == (__u32)-1) {
+/* BAD BLOCK LIST SUPPORT
+ if (is_indirect_ih (ih) && comp_short_keys (&((ih - 1)->ih_key), &ih->ih_key) != 0)
+ return 0; // badblocks item
+*/
+ /* it does not look like badblocks item */
+ } else {
+ /* safe link ? */
+ if (comp_short_keys (&((ih - 1)->ih_key), &ih->ih_key) == 0) {
+ if (is_indirect_ih (ih - 1) && is_direct_ih(ih))
+ return 0; /* safe link */
+ /* they do not look like safe links */
+ } else {
+ if (is_indirect_ih (ih) || is_direct_ih(ih))
+ return 0; /* safe link */
+ /* it does not look like safe link */
+ }
+ }
+ }
if (is_direct_ih(ih)) {
/* left item must be indirect or stat data item of the same
file */
- if (not_of_one_file (&((ih - 1)->ih_key), &ih->ih_key))
+ if (not_of_one_file (&((ih - 1)->ih_key), &ih->ih_key)) {
+ if (fsck_mode (fs) != FSCK_REBUILD)
+ one_more_corruption (fs, fatal);
return 1;
+ }
if (!((is_stat_data_ih (ih - 1) && get_offset (&ih->ih_key) == 1) ||
(is_indirect_ih (ih - 1) &&
- get_offset (&(ih - 1)->ih_key) + get_bytes_number (ih-1, bh->b_size) == //get_bytes_number (bh, ih - 1, 0, CHECK_FREE_BYTES) ==
- get_offset (&ih->ih_key))))
+ get_offset (&(ih - 1)->ih_key) + get_bytes_number (ih-1, bh->b_size) ==
+ get_offset (&ih->ih_key)))) {
+ if (fsck_mode (fs) != FSCK_REBUILD)
+ one_more_corruption (fs, fatal);
return 1;
-
+ }
}
if (is_indirect_ih (ih) || is_direntry_ih (ih)) {
/* left item must be stat data of the same object */
- if (not_of_one_file (&((ih - 1)->ih_key), &ih->ih_key))
- return 1;
-
- if (!is_stat_data_ih (ih - 1))
- return 1;
- }
-
- return 0;
-}
-
-int bad_leaf_2 (struct super_block * s, struct buffer_head * bh)
-{
- int i;
-
- if (bad_block_head (bh))
- return 1;
-
- for (i = 0; i < B_NR_ITEMS (bh); i ++) {
- if (i && bad_pair (s, bh, i)) {
- fsck_log ("bad_leaf_2: block %lu has wrong order of items\n",
- bh->b_blocknr);
+ if (not_of_one_file (&((ih - 1)->ih_key), &ih->ih_key) ||
+ !is_stat_data_ih (ih - 1)) {
+ if (fsck_mode (fs) != FSCK_REBUILD)
+ one_more_corruption (fs, fatal);
return 1;
}
}
+
return 0;
}
-
/* 1 if block head or any of items is bad */
-static int bad_leaf (struct super_block * s, struct buffer_head * bh)
+static int bad_leaf (reiserfs_filsys_t * fs, struct buffer_head * bh)
{
int i;
- if (bad_block_head (bh))
+ if (bad_block_head (fs, bh)) {
return 1;
+ }
for (i = 0; i < B_NR_ITEMS (bh); i ++) {
- if (bad_item (s, bh, i)) {
+ if (bad_item (fs, bh, i)) {
fsck_log ("bad_leaf: block %lu has invalid item %d: %H\n",
bh->b_blocknr, i, B_N_PITEM_HEAD (bh, i));
}
- if (i && bad_pair (s, bh, i)) {
- fsck_log ("bad_leaf: block %lu has wrong order of items\n",
- bh->b_blocknr);
+ if (i && bad_pair (fs, bh, i)) {
+ fsck_log ("bad_leaf: block %lu has wrong order of items [%d, %d]: %k %k\n",
+ bh->b_blocknr, i-1, i, &B_N_PITEM_HEAD (bh, i-1)->ih_key, &B_N_PITEM_HEAD (bh, i)->ih_key);
}
}
return 0;
}
-
/* 1 if bh does not look like internal node */
-static int bad_internal (struct super_block * s, struct buffer_head * bh)
+static int bad_internal (reiserfs_filsys_t * fs, struct buffer_head * bh)
{
int i;
- for (i = 0; i <= B_NR_ITEMS (bh); i ++)
- {
+ for (i = 0; i <= B_NR_ITEMS (bh); i ++) {
if (i != B_NR_ITEMS (bh) && i != B_NR_ITEMS (bh) - 1)
- if (comp_keys (B_N_PDELIM_KEY (bh, i), B_N_PDELIM_KEY (bh, i + 1)) != -1)
+ /* make sure that keys are in increasing order */
+ if (comp_keys (B_N_PDELIM_KEY (bh, i), B_N_PDELIM_KEY (bh, i + 1)) != -1) {
+ fsck_log ("%s: vpf-10320: block %lu has wrong order of keys %k, %k\n",
+ __FUNCTION__, bh->b_blocknr, B_N_PDELIM_KEY (bh, i), B_N_PDELIM_KEY (bh, i + 1));
+ one_more_corruption (fs, fatal);
return 1;
- if (bad_block_number(s, child_block_number(bh,i))){
+ }
+
+ /* make sure that the child is correct */
+ if (bad_block_number (fs, get_dc_child_blocknr (B_N_CHILD (bh,i)))) {
+ fsck_log ("%s: vpf-10330: block %lu: has bad pointer %d: %lu\n",
+ __FUNCTION__, bh->b_blocknr, i, get_dc_child_blocknr (B_N_CHILD (bh,i)));
+ one_more_corruption (fs, fatal);
return 1;
- }
+ }
}
return 0;
}
/* h == 0 for root level. block head's level == 1 for leaf level */
-static inline int h_to_level (struct super_block * s, int h)
+static inline int h_to_level (reiserfs_filsys_t * fs, int h)
{
- return SB_TREE_HEIGHT (s) - h - 1;
+ return get_sb_tree_height (fs->fs_ondisk_sb) - h - 1;
}
/* bh must be formatted node. blk_level must be tree_height - h + 1 */
-static int bad_node (struct super_block * s, struct buffer_head ** path,
+static int bad_node (reiserfs_filsys_t * fs, struct buffer_head ** path,
int h)
{
struct buffer_head ** pbh = &path[h];
- if (B_LEVEL (*pbh) != h_to_level (s, h)) {
+ if (B_LEVEL (*pbh) != h_to_level (fs, h)) {
fsck_log ("node (%lu) with wrong level (%d) found in the tree (should be %d)\n",
- (*pbh)->b_blocknr, B_LEVEL (*pbh), h_to_level (s, h));
+ (*pbh)->b_blocknr, B_LEVEL (*pbh), h_to_level (fs, h));
+ one_more_corruption (fs, fatal);
return 1;
}
- if (bad_block_number (s, (*pbh)->b_blocknr)) {
+ if (bad_block_number (fs, (*pbh)->b_blocknr)) {
+ one_more_corruption (fs, fatal);
+ fsck_log ("%s: vpf-10340: wrong block number %lu found in the tree\n",
+ __FUNCTION__, (*pbh)->b_blocknr);
return 1;
}
- if (got_already (s, (*pbh)->b_blocknr))
+ if (got_already (fs, (*pbh)->b_blocknr)) {
+ fsck_log ("%s: vpf-10350: block number %lu is already in the tree\n",
+ __FUNCTION__, (*pbh)->b_blocknr);
+ one_more_corruption (fs, fatal);
return 1;
+ }
- if (is_leaf_node (*pbh))
- return bad_leaf (s, *pbh);
+ if (is_leaf_node (*pbh)) {
+ fsck_check_stat (fs)->leaves ++;
+ return bad_leaf (fs, *pbh);
+ }
- return bad_internal (s, *pbh);
+ fsck_check_stat (fs)->internals ++;
+ return bad_internal (fs, *pbh);
}
@@ -544,7 +840,7 @@ static int get_pos (struct buffer_head * bh, unsigned long block)
int i;
for (i = 0; i <= B_NR_ITEMS (bh); i ++) {
- if (child_block_number (bh, i) == block)
+ if (get_dc_child_blocknr (B_N_CHILD (bh, i)) == block)
return i;
}
die ("get_pos: position for block %lu not found", block);
@@ -583,11 +879,12 @@ static struct key * rkey (struct buffer_head ** path, int h)
/* are all delimiting keys correct */
-static int bad_path (struct super_block * s, struct buffer_head ** path, int h1)
+static int bad_path (reiserfs_filsys_t * fs, struct buffer_head ** path, int h1)
{
int h = 0;
struct key * dk;
-
+ int pos = 0;
+
while (path[h])
h ++;
@@ -597,41 +894,122 @@ static int bad_path (struct super_block * s, struct buffer_head ** path, int h1)
if (h != h1)
die ("bad_path: wrong path");
+ if (h)
+ pos = get_pos (path[h - 1], path[h]->b_blocknr);
+
dk = lkey (path, h);
- if (dk && comp_keys (dk, B_N_PKEY (path[h], 0)))
- // left delimiting key must be equal to the key of 0-th item in the
- // node
+ if (dk && comp_keys (dk, B_N_PKEY (path[h], 0))) {
+ /* left delimiting key must be equal to the key of 0-th item in the
+ node */
+ fsck_log ("bad_path: left delimiting key %k must be equal to %k (block %lu, pos %d)\n",
+ dk, B_N_PKEY (path[h], 0), path[h]->b_blocknr, 0);
+ one_more_corruption (fs, fatal);
return 1;
+ }
dk = rkey (path, h);
- if (dk && comp_keys (dk, B_N_PKEY (path[h], node_item_number (path[h]) - 1)) != 1)
- // right delimiting key must be bigger than the key of the last item
- // in the node
+ if (dk && comp_keys (dk, B_N_PKEY (path[h],
+ get_blkh_nr_items (B_BLK_HEAD (path[h])) - 1)) != 1) {
+ /* right delimiting key must be bigger than the key of the last item
+ in the node */
+ fsck_log ("bad_path: right delimiting key %k must be equal to %k (block %lu, pos %d)\n",
+ dk, B_N_PKEY (path[h], get_blkh_nr_items (B_BLK_HEAD (path[h])) - 1),
+ path[h]->b_blocknr, get_blkh_nr_items (B_BLK_HEAD (path[h])) - 1);
+ one_more_corruption (fs, fatal);
return 1;
-
+ }
+
+ if (h && (get_dc_child_size (B_N_CHILD(path[h-1],pos)) +
+ get_blkh_free_space ((struct block_head *)path[h]->b_data) +
+ BLKH_SIZE != path[h]->b_size))
+ {
+ /* wrong dc_size */
+
+ fsck_log ("bad_path: wrong sum of dc_size %d (block %lu, pos %d) ",
+ get_dc_child_size (B_N_CHILD(path[h-1],pos)), path[h-1]->b_blocknr, pos);
+ fsck_log ("free space %d (block %lu) and BLKH_SIZE %lu",
+ get_blkh_free_space ((struct block_head *)path[h]->b_data),
+ path[h]->b_blocknr, BLKH_SIZE);
+
+ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) {
+ set_dc_child_size (B_N_CHILD(path[h-1],pos), path[h]->b_size -
+ get_blkh_free_space ((struct block_head *)path[h]->b_data) - BLKH_SIZE);
+ fsck_log (" - fixed (%lu)\n", get_dc_child_size (B_N_CHILD(path[h-1],pos)));
+ mark_buffer_dirty (path[h-1]);
+ } else {
+ one_more_corruption (fs, fixable);
+ fsck_log ("\n");
+ return 1;
+ }
+ }
+
return 0;
}
+static void before_check_fs_tree (reiserfs_filsys_t * fs) {
+ init_control_bitmap (fs);
-/* pass the S+ tree of filesystem */
-void check_fs_tree (struct super_block * s)
-{
- init_control_bitmap (s);
+ source_bitmap = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb));
+ reiserfs_bitmap_copy (source_bitmap, fs->fs_bitmap2);
- proper_id_map (s) = init_id_map ();
-
- fsck_progress ("Checking S+tree..");
+ proper_id_map (fs) = init_id_map ();
+}
- pass_through_tree (s, bad_node, bad_path);
+static void after_check_fs_tree (reiserfs_filsys_t * fs) {
+ if (fsck_mode(fs) == FSCK_FIX_FIXABLE) {
+ fs->fs_dirt = 1;
+ reiserfs_flush_to_ondisk_bitmap (fs->fs_bitmap2, fs);
+ reiserfs_flush (fs);
+ }
+ reiserfs_delete_bitmap (source_bitmap);
+ reiserfs_delete_bitmap (control_bitmap);
+ flush_buffers (fs->fs_dev);
+}
+/* pass the S+ tree of filesystem */
+void check_fs_tree (reiserfs_filsys_t * fs)
+{
+ before_check_fs_tree (fs);
+
+ fsck_progress ("Checking S+tree..");
+ pass_through_tree (fs, bad_node, bad_path);
/* S+ tree is correct (including all objects have correct
sequences of items) */
fsck_progress ("ok\n");
/* compare created bitmap with the original */
- compare_bitmaps (s);
+ handle_bitmaps (fs);
+
+ after_check_fs_tree (fs);
+}
+
+static int clean_attributes_handler (reiserfs_filsys_t * fs, struct buffer_head ** path, int h) {
+ struct buffer_head * bh = path[h];
+ int i;
+
+ if (B_LEVEL (bh) != h_to_level (fs, h)) {
+ reiserfs_panic ("node (%lu) with wrong level (%d) found in the tree (should be %d)\n",
+ bh->b_blocknr, B_LEVEL (bh), h_to_level (fs, h));
+ }
- free_id_map (&proper_id_map (s));
+ if (!is_leaf_node (bh))
+ return 0;
+
+ for (i = 0; i < B_NR_ITEMS (bh); i ++) {
+ if (is_stat_data_ih (B_N_PITEM_HEAD (bh, i)) &&
+ get_ih_item_len (B_N_PITEM_HEAD (bh, i)) == SD_SIZE) {
+ set_sd_v2_sd_attrs((struct stat_data *)B_N_PITEM(bh, i), 0);
+ mark_buffer_dirty (bh);
+ }
+ }
+
+ return 0;
+}
+
+void do_clean_attributes (reiserfs_filsys_t * fs) {
+ pass_through_tree (fs, clean_attributes_handler, NULL);
+ set_sb_v2_flag (fs->fs_ondisk_sb, reiserfs_attrs_cleared);
+ mark_buffer_dirty (fs->fs_super_bh);
}
#if 0
@@ -773,28 +1151,35 @@ void check_internal_structure(struct super_block * s)
}
#endif
-
-int check_sb (struct super_block * s)
+/*
+int check_sb (reiserfs_filsys_t * fs)
{
+
+
+ reiserfs_panic ("Not ready");
+ return 0;
+#if 0
int format_sb = 0;
int problem = 0;
- struct reiserfs_super_block * rs;
+ struct reiserfs_super_block * sb;
__u32 block_count;
+ unsigned long j_1st_block;
+ int sb_version;
+
+ sb = fs->fs_ondisk_sb;
+ j_1st_block = get_jp_journal_1st_block (sb_jp (sb));
- rs = s->s_rs;
// in (REISERFS_DISK_OFFSET_IN_BYTES / 4096) block
- if (is_reiser2fs_magic_string (rs) &&
- SB_JOURNAL_BLOCK(s) == get_journal_start_must (rs_blocksize (rs)))
- {
+ if ((is_reiser2fs_magic_string (sb) || is_reiser2fs_jr_magic_string (sb) )&&
+ j_1st_block == get_journal_new_start_must (fs)) {
// 3.6 or >=3.5.22
printf("\t 3.6.x format SB found\n");
format_sb = 1;
goto good_format;
}
- if (is_reiserfs_magic_string (rs) &&
- SB_JOURNAL_BLOCK(s) == get_journal_start_must (rs_blocksize (rs)))
- {
+ if ( (is_reiserfs_magic_string (sb) ||is_reiser2fs_jr_magic_string (sb) ) &&
+ j_1st_block == get_journal_new_start_must (fs)) {
// >3.5.9(10) and <=3.5.21
printf("\t>=3.5.9 format SB found\n");
format_sb = 2;
@@ -802,105 +1187,110 @@ int check_sb (struct super_block * s)
}
// in 2 block
- if (is_reiser2fs_magic_string (rs) &&
- SB_JOURNAL_BLOCK(s) == get_journal_old_start_must (rs))
- {
+ if ( (is_reiser2fs_magic_string (sb) || is_reiser2fs_jr_magic_string (sb) ) &&
+ j_1st_block == get_journal_old_start_must (sb)) {
// <3.5.9(10) converted to new format
printf("\t< 3.5.9(10) SB converted to new format found \n");
format_sb = 3;
goto good_format;
}
- if (is_reiserfs_magic_string (rs) &&
- SB_JOURNAL_BLOCK(s) == get_journal_old_start_must (rs))
- {
+ if ( (is_reiserfs_magic_string (sb) ||is_reiser2fs_jr_magic_string (sb) ) &&
+ j_1st_block == get_journal_old_start_must (sb)) {
// <3.5.9(10)
printf("\t< 3.5.9(10) format SB found\n");
format_sb = 4;
goto good_format;
}
- else
+ else
die("check SB: wrong SB format found\n");
good_format:
- printf("\n\t%d-%d\n", SB_BLOCK_COUNT (s), SB_FREE_BLOCKS (s));
- if (s->s_blocksize != 4096) {
- fsck_log("check SB: specified block size (%d) is not correct must be 4096\n", s->s_blocksize);
+ printf("\n\t%d-%d\n", get_sb_block_count (sb), get_sb_free_blocks (sb));
+ if (fs->fs_blocksize != 4096) {
+ //???
+ fsck_log("check SB: specified block size (%d) is not correct must be 4096\n",
+ fs->fs_blocksize);
problem++;
}
-
+
//for 4096 blocksize only
- if ((rs_tree_height(rs) < DISK_LEAF_NODE_LEVEL) || (rs_tree_height(rs) > MAX_HEIGHT)){
- fsck_log ("check SB: wrong tree height (%d)\n", rs_tree_height(rs));
+ if ((get_sb_tree_height (sb) < DISK_LEAF_NODE_LEVEL + 1) ||
+ (get_sb_tree_height (sb) > MAX_HEIGHT)){
+ fsck_log ("check SB: wrong tree height (%d)\n", get_sb_tree_height (sb));
problem++;
}
- block_count = count_blocks ("", s->s_blocksize, s->s_dev);
+ block_count = count_blocks (fs->fs_file_name, fs->fs_blocksize);
- if (SB_BLOCK_COUNT(s) > block_count){
- fsck_log ("check SB: specified block number (%d) is too high\n", SB_BLOCK_COUNT(s));
+ if (get_sb_block_count (sb) > block_count){
+ fsck_log ("check SB: specified block number (%d) is too high\n",
+ get_sb_block_count (sb));
problem++;
}
- if ((rs_root_block(rs) >= block_count) || (rs_root_block(rs) < 0)){
- fsck_log ("check SB: specified root block number (%d) is too high\n", rs_root_block(rs));
+ if ((get_sb_root_block (sb) >= block_count)) {
+ fsck_log ("check SB: specified root block number (%d) is too high\n",
+ get_sb_root_block (sb));
problem++;
}
- if (SB_FREE_BLOCKS(s) > SB_BLOCK_COUNT(s)){
- fsck_log ("check SB: specified free block number (%d) is too high\n", SB_FREE_BLOCKS(s));
+ if (get_sb_free_blocks (sb) > get_sb_block_count (sb)) {
+ fsck_log ("check SB: specified free block number (%d) is too high\n",
+ get_sb_free_blocks (sb));
problem++;
}
-
- if (SB_REISERFS_STATE(s) != REISERFS_VALID_FS){
- fsck_log ("check SB: wrong (%d) state\n", SB_REISERFS_STATE(s));
+
+ if (get_sb_state (sb) != REISERFS_VALID_FS && get_sb_state (sb) != REISERFS_ERROR_FS){
+ fsck_log ("check SB: unknown (%d) state\n", get_sb_state (sb));
problem++;
}
- if ( SB_BMAP_NR(s) != SB_BLOCK_COUNT(s) / (s->s_blocksize * 8) +
- ((SB_BLOCK_COUNT(s) % (s->s_blocksize * 8)) ? 1 : 0)){
- fsck_log("check SB: wrong bitmap number (%d)\n", SB_BMAP_NR(s));
+ if (get_sb_bmap_nr (sb) != (get_sb_block_count (sb) + (fs->fs_blocksize * 8 - 1)) / (fs->fs_blocksize * 8)) {
+ fsck_log("check SB: wrong bitmap number (%d)\n", get_sb_bmap_nr (sb));
problem++;
}
- if (SB_VERSION(s) == REISERFS_VERSION_2 || SB_VERSION(s) == REISERFS_VERSION_1)
- {
- if (!(SB_VERSION(s) == REISERFS_VERSION_2 && (format_sb == 1 || format_sb == 3)) &&
- !(SB_VERSION(s) == REISERFS_VERSION_1 && (format_sb == 2 || format_sb == 4))){
- fsck_log("check SB: wrong SB version == %d, format == %d\n", SB_VERSION(s), format_sb);
+ sb_version = get_sb_version (sb);
+ if (sb_version == REISERFS_VERSION_3 || sb_version == REISERFS_VERSION_2 || sb_version == REISERFS_VERSION_1) {
+ if (!((sb_version == REISERFS_VERSION_3 ||sb_version == REISERFS_VERSION_2) && (format_sb == 1 || format_sb == 3)) &&
+ !(sb_version == REISERFS_VERSION_1 && (format_sb == 2 || format_sb == 4))) {
+ fsck_log("check SB: wrong SB version == %d, format == %d\n",
+ sb_version, format_sb);
problem++;
}
- }
- else{
- fsck_log ("check SB: wrong SB version (%d)\n", SB_VERSION(s));
+ } else {
+ fsck_log ("check SB: wrong SB version (%d)\n", sb_version);
problem++;
}
- if (SB_VERSION(s) == REISERFS_VERSION_2 &&
- (rs_hash (rs) < 1 || rs_hash (rs) > 3)) {
- /* FIXME: */
- fsck_log("check SB: wrong hash (%d)\n", rs_hash (rs));
+ if ((sb_version == REISERFS_VERSION_3 ||sb_version == REISERFS_VERSION_2) &&
+ // FIXME:
+ (get_sb_hash_code (sb) < 1 || get_sb_hash_code (sb) > 3)) {
+ fsck_log("check SB: wrong hash (%d)\n", get_sb_hash_code (sb));
problem++;
}
- if ((SB_VERSION(s) == REISERFS_VERSION_2) ?
- (rs_objectid_map_max_size (rs) != ((s->s_blocksize - SB_SIZE) / sizeof(__u32) / 2 * 2)) :
- (rs_objectid_map_max_size (rs) != ((s->s_blocksize - SB_SIZE_V1) / sizeof(__u32) / 2 * 2))) {
- fsck_log("check SB: objectid map corrupted max_size == %d\n", rs_objectid_map_max_size (rs));
+ if ((sb_version == REISERFS_VERSION_3 ||sb_version == REISERFS_VERSION_2) ?
+ (get_sb_oid_maxsize (sb) != ((fs->fs_blocksize - SB_SIZE) / sizeof(__u32) / 2 * 2)) :
+ (get_sb_oid_maxsize (sb) != ((fs->fs_blocksize - SB_SIZE_V1) / sizeof(__u32) / 2 * 2))) {
+ fsck_log("check SB: objectid map corrupted max_size == %d\n",
+ get_sb_oid_maxsize (sb));
problem++;
}
- if (rs_objectid_map_size (rs) < 2 ||
- rs_objectid_map_size (rs) > rs_objectid_map_max_size (rs)) {
- fsck_log("check SB: objectid map corrupted cur_size == %d\n", rs_objectid_map_size (rs));
+ if (get_sb_oid_cursize (sb) < 2 ||
+ get_sb_oid_cursize (sb) > get_sb_oid_maxsize (sb)) {
+ fsck_log("check SB: objectid map corrupted cur_size == %d\n",
+ get_sb_oid_cursize (sb));
problem++;
}
- if (rs_journal_size(rs) != JOURNAL_BLOCK_COUNT){
- fsck_log("check SB: specified journal size (%d) is not correct must be %d\n",
- rs_journal_size(rs), JOURNAL_BLOCK_COUNT);
+ if (get_jp_journal_size (sb_jp (sb)) < JOURNAL_DEFAULT_SIZE/32 ){
+ fsck_log("check SB: specified journal size (%d) is not correct must be not less that %d\n",
+ get_jp_journal_size (sb_jp (sb)), JOURNAL_DEFAULT_SIZE/32);
problem++;
}
@@ -910,6 +1300,8 @@ good_format:
fsck_progress ("Look for super block corruptions in the log file\n");
return format_sb;
-}
+#endif
+}
+*/
diff --git a/fsck/fsck.h b/fsck/fsck.h
index ac0c7ce..fd2099e 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -1,5 +1,5 @@
/*
- * Copyright 1996-2001 Hans Reiser
+ * Copyright 1996-2002 Hans Reiser
*/
#define _GNU_SOURCE
@@ -23,54 +23,54 @@
#include "reiserfs_lib.h"
-
-
/* main.c */
-extern reiserfs_filsys_t fs;
-extern reiserfs_bitmap_t uninsertable_leaf_bitmap;
+extern reiserfs_filsys_t * fs;
int main (int argc, char * argv []);
/*
* modes
*/
-#define DO_NOTHING 0 /* -a specified */
-#define FSCK_CHECK 1
-#define FSCK_SB 2
-#define FSCK_REBUILD 3
+#define DO_NOTHING 0 /* -a specified */
+#define FSCK_CHECK 1
+#define FSCK_FIX_FIXABLE 2
+#define FSCK_SB 3
+#define FSCK_REBUILD 4
+#define FSCK_ROLLBACK_CHANGES 5
+#define FSCK_FAST_REBUILD 6
+#define FSCK_CLEAN_ATTRIBUTES 7
+#define AUTO 8 /* -p specified */
/* temporary */
-#define FSCK_ZERO_FILES 4
-#define DO_TEST 5
+#define DO_TEST 9
/*
-#define FSCK_FAST_REBUILD 4
-*/
-
-
-/*
* options
*/
-#define OPT_INTERACTIVE 1
-#define OPT_FIX_FIXABLE 2 /* not default yet */
-#define OPT_FIX_NON_CRITICAL 4 /* not default yet */
-#define OPT_QUIET 8
-#define OPT_SAVE_EXTERN_BITMAP 16
-#define OPT_SILENT 32
-
-extern int g_blocks_to_read;
+#define OPT_INTERACTIVE 0x1
+//#define OPT_FIX_FIXABLE 0x2 /* not default yet */
+#define OPT_ADJUST_FILE_SIZE 0x4 /* not default yet */
+#define OPT_QUIET 0x8 /* no "speed" info */
+/*#define OPT_SAVE_EXTERN_BITMAP 0x10*/
+#define OPT_SILENT 0x20 /* no complains about found corruptions */
+#define OPT_BACKGROUND 0x40
+#define OPT_SKIP_JOURNAL 0x80
+#define OPT_HASH_DEFINED 0x100
+#define OPT_SAVE_PASSES_DUMP 0x200
+#define BADBLOCKS_FILE 0x400
+#define OPT_SAVE_ROLLBACK 0x800
-/* pass 0 and 1 read the device NR_TO_READ block in time */
-#define NR_TO_READ 8
/* pass0.c */
-int pass_0 (reiserfs_filsys_t);
-int are_there_used_leaves (unsigned long from, int count);
+void pass_0 (reiserfs_filsys_t *);
+void load_pass_0_result (FILE *, reiserfs_filsys_t *);
+
int is_used_leaf (unsigned long block);
int how_many_leaves_were_there (void);
-int is_bad_unformatted (unsigned long block);
int is_good_unformatted (unsigned long block);
void mark_good_unformatted (unsigned long block);
+int is_bad_unformatted (unsigned long block);
+
int are_there_allocable_blocks (int amout_needed);
unsigned long alloc_block (void);
void make_allocable (unsigned long block);
@@ -80,32 +80,40 @@ void register_saved_item (void);
unsigned long how_many_items_were_saved (void);
int still_bad_unfm_ptr_1 (unsigned long block);
int still_bad_unfm_ptr_2 (unsigned long block);
-void make_alloc_bitmap (struct super_block * s);
+void make_alloc_bitmap (reiserfs_filsys_t *);
+
+void delete_aux_bitmaps ();
+void set_aux_bitmaps(reiserfs_bitmap_t * leaves, reiserfs_bitmap_t * good, reiserfs_bitmap_t * bad);
#define __is_marked(name,block) reiserfs_bitmap_test_bit (name##_bitmap, block)
#define __mark(name,block) reiserfs_bitmap_set_bit (name##_bitmap, block)
#define __unmark(name,block) reiserfs_bitmap_clear_bit (name##_bitmap, block)
/* unformatted in tree */
-extern reiserfs_bitmap_t bad_unfm_in_tree_once_bitmap;
+extern reiserfs_bitmap_t * bad_unfm_in_tree_once_bitmap;
#define is_bad_unfm_in_tree_once(block) __is_marked (bad_unfm_in_tree_once, block)
#define mark_bad_unfm_in_tree_once(block) __mark (bad_unfm_in_tree_once, block)
/* pass1.c */
-void pass_1_pass_2_build_the_tree (void);
-struct buffer_head * make_buffer (int dev, int blocknr, int size, char * data);
+void pass_1 (reiserfs_filsys_t *);
+void load_pass_1_result (FILE *, reiserfs_filsys_t *);
+struct buffer_head * make_buffer (int dev, unsigned long blocknr, int size, char * data);
void build_the_tree (void);
extern int g_unaccessed_items;
int is_item_reachable (struct item_head * ih);
void mark_item_reachable (struct item_head * ih, struct buffer_head * bh);
void mark_item_unreachable (struct item_head * ih);
-void rebuild_sb (reiserfs_filsys_t fs);
+
struct si * remove_saved_item (struct si * si);
+int tree_is_empty (void);
+void make_single_leaf_tree (struct buffer_head * bh);
/* pass2.c */
+void pass_2 (reiserfs_filsys_t *);
+void load_pass_2_result (reiserfs_filsys_t *);
void insert_item_separately (struct item_head * ih, char * item,
int was_in_tree);
struct si * save_and_delete_file_item (struct si * si, struct path * path);
@@ -115,8 +123,10 @@ void pass_2_take_bad_blocks_put_into_tree (void);
/*int is_remapped (struct item_head * ih);*/
void link_relocated_files (void);
void relocate_file (struct item_head * ih, int change_ih);
+int should_relocate (struct item_head * ih);
void relocate_dir (struct item_head * ih, int change_ih);
__u32 objectid_for_relocation (struct key * key);
+int should_be_relocated (struct key * key);
/* file.c */
struct si {
@@ -130,62 +140,48 @@ struct si {
};
void put_saved_items_into_tree (struct si *);
int reiserfsck_file_write (struct item_head * ih, char * item, int);
-int are_file_items_correct (struct key * key, int key_version, __u64 * size, __u32 * blocks, int mark_passed_items,
- int symlink, __u64 symlink_size);
+int are_file_items_correct (struct item_head * sd_ih, void * sd, __u64 * size, __u32 * blocks, int mark_passed_items, int * symlink);
+
/* semantic.c */
-extern struct key root_dir_key;
-extern struct key parent_root_dir_key;
-extern struct key lost_found_dir_key;
-void pass_3_semantic (void);
+
+/* return values for check_regular_file and check_semantic_tree */
+#define OK 0
+#define STAT_DATA_NOT_FOUND -1
+#define DIRECTORY_HAS_NO_ITEMS -2
+#define RELOCATED -3
+#define LOOP_FOUND -4
+
+void load_semantic_result (FILE *, reiserfs_filsys_t *);
+
+void pass_3_semantic (reiserfs_filsys_t *);
void semantic_check (void);
int check_semantic_tree (struct key * key, struct key * parent, int is_dot_dot, int lost_found, struct item_head * new_ih);
void zero_nlink (struct item_head * ih, void * sd);
int not_a_directory (void * sd);
+int not_a_regfile (void * sd);
+int fix_obviously_wrong_sd_mode (struct path * path);
int is_dot_dot (char * name, int namelen);
int is_dot (char * name, int namelen);
-void create_dir_sd (reiserfs_filsys_t fs,
- struct path * path, struct key * key);
+/*void create_dir_sd (reiserfs_filsys_t * fs,
+ struct path * path, struct key * key);*/
int rebuild_check_regular_file (struct path * path, void * sd,
struct item_head * new_ih);
int rebuild_semantic_pass (struct key * key, struct key * parent, int is_dot_dot,
struct item_head * new_ih);
-/* access to stat data fields */
-void get_set_sd_field (int field, struct item_head * ih, void * sd,
- void * value, int set);
-#define GET_SD_MODE 0
-#define GET_SD_SIZE 1
-#define GET_SD_NLINK 2
-#define GET_SD_BLOCKS 3
-#define GET_SD_FIRST_DIRECT_BYTE 4
-
-#define get_sd_mode(ih,sd,pmode) get_set_sd_field (GET_SD_MODE, ih, sd, pmode, 0/*get*/)
-#define set_sd_mode(ih,sd,pmode) get_set_sd_field (GET_SD_MODE, ih, sd, pmode, 1/*set*/)
-
-#define get_sd_size(ih,sd,psize) get_set_sd_field (GET_SD_SIZE, ih, sd, psize, 0/*get*/)
-#define set_sd_size(ih,sd,psize) get_set_sd_field (GET_SD_SIZE, ih, sd, psize, 1/*set*/)
-
-#define get_sd_blocks(ih,sd,pblocks) get_set_sd_field (GET_SD_BLOCKS, ih, sd, pblocks, 0/*get*/)
-#define set_sd_blocks(ih,sd,pblocks) get_set_sd_field (GET_SD_BLOCKS, ih, sd, pblocks, 1/*set*/)
-
-#define get_sd_nlink(ih,sd,pnlink) get_set_sd_field (GET_SD_NLINK, ih, sd, pnlink, 0/*get*/)
-#define set_sd_nlink(ih,sd,pnlink) get_set_sd_field (GET_SD_NLINK, ih, sd, pnlink, 1/*set*/)
-
-#define get_sd_first_direct_byte(ih,sd,pfdb) get_set_sd_field (GET_SD_FIRST_DIRECT_BYTE, ih, sd, pfdb, 0/*get*/)
-#define set_sd_first_direct_byte(ih,sd,pfdb) get_set_sd_field (GET_SD_FIRST_DIRECT_BYTE, ih, sd, pfdb, 1/*set*/)
/* lost+found.c */
-void pass_3a_look_for_lost (reiserfs_filsys_t s);
+void pass_3a_look_for_lost (reiserfs_filsys_t *);
+void load_lost_found_result (reiserfs_filsys_t *);
/* pass4.c */
-void get_next_key (struct path * path, int i, struct key * key);
-int pass_4_check_unaccessed_items (void);
-
+//void get_next_key (struct path * path, int i, struct key * key);
+void pass_4_check_unaccessed_items (void);
/* check.c */
int is_leaf_bad (struct buffer_head * bh);
@@ -202,69 +198,66 @@ int is_bad_directory (struct item_head * ih, char * item, int dev, int blocksize
//extern int bad_block_number (struct super_block * s, blocknr_t block);
/* check_tree.c */
-void check_fs_tree (struct super_block * s);
-int check_sb (struct super_block * s);
-int bad_pair (struct super_block * s, struct buffer_head * bh, int i);
-int bad_leaf_2 (struct super_block * s, struct buffer_head * bh);
+void check_fs_tree (reiserfs_filsys_t *);
+void do_clean_attributes (reiserfs_filsys_t * fs);
+//int check_sb (reiserfs_filsys_t *);
+int bad_pair (reiserfs_filsys_t *, struct buffer_head * bh, int i);
+int bad_leaf_2 (reiserfs_filsys_t *, struct buffer_head * bh);
/* ustree.c */
-void init_tb_struct (struct tree_balance * tb, struct super_block * s, struct path * path, int size);
void reiserfsck_paste_into_item (struct path * path, const char * body, int size);
void reiserfsck_insert_item (struct path * path, struct item_head * ih, const char * body);
void reiserfsck_delete_item (struct path * path, int temporary);
void reiserfsck_cut_from_item (struct path * path, int cut_size);
-typedef int (comp_function_t)(void * key1, void * key2);
-typedef int (comp3_function_t)(void * key1, void * key2, int version);
+/*typedef int (comp3_function_t)(void * key1, void * key2, int version);*/
/*typedef int (comp_function_t)(struct key * key1, struct key * key2);*/
-int ubin_search_id(__u32 * id, __u32 * base, __u32 number, __u32 * pos);
-int usearch_by_key (struct super_block * s, struct key * key, struct path * path);
-int usearch_by_key_3 (struct super_block * s, struct key * key, struct path * path, int * repeat, int stop_level,
+/*int ubin_search_id(__u32 * id, __u32 * base, __u32 number, __u32 * pos);*/
+/*int usearch_by_key (struct super_block * s, struct key * key, struct path * path);*/
+/*int usearch_by_key_3 (struct super_block * s, struct key * key, struct path * path, int * repeat, int stop_level,
comp3_function_t comp_func, int version);
-int usearch_by_entry_key (struct super_block * s, struct key * key, struct path * path);
-int usearch_by_position (struct super_block * s, struct key * key, int version, struct path * path);
-struct key * uget_lkey (struct path * path);
-struct key * uget_rkey (struct path * path);
+ int usearch_by_entry_key (struct super_block * s, struct key * key, struct path * path);*/
-typedef int do_after_read_t (struct super_block * s, struct buffer_head **, int h);
-typedef int do_on_full_path_t (struct super_block * s, struct buffer_head **, int);
-void pass_through_tree (struct super_block *, do_after_read_t, do_on_full_path_t);
+typedef int do_after_read_t (reiserfs_filsys_t *, struct buffer_head **, int h);
+typedef int do_on_full_path_t (reiserfs_filsys_t *, struct buffer_head **, int);
+void pass_through_tree (reiserfs_filsys_t *, do_after_read_t, do_on_full_path_t);
//int comp_keys_3 (void * key1, void * key2);
//int comp_dir_entries (void * key1, void * key2);
-inline int ubin_search (void * key, void * base, int num, int width, __u32 *ppos, comp_function_t comp_func);
/* bitmap.c */
-int reiserfsck_reiserfs_new_blocknrs (reiserfs_filsys_t fs,
+int reiserfsck_reiserfs_new_blocknrs (reiserfs_filsys_t * fs,
unsigned long * pblocknrs,
unsigned long start_from,
int amount_needed);
-int reiserfsck_reiserfs_free_block (reiserfs_filsys_t fs, unsigned long block);
+int reiserfsck_reiserfs_free_block (reiserfs_filsys_t * fs, unsigned long block);
struct buffer_head * reiserfsck_get_new_buffer (unsigned long start);
int is_block_used (unsigned long block);
-int is_to_be_read (reiserfs_filsys_t fs, unsigned long block);
-void mark_block_used (unsigned long block);
+void mark_block_used (unsigned long block, int check_hardware);
void mark_block_uninsertable (unsigned long block);
int is_block_uninsertable (unsigned long block);
/* objectid.c */
-int is_objectid_used (struct super_block * s, __u32 objectid);
-void mark_objectid_as_used (struct super_block * s, __u32 objectid);
-void mark_objectid_as_free (struct super_block * s, __u32 objectid);
-__u32 get_unused_objectid (struct super_block * s);
+int comp_ids(const void *p1, const void *p2);
+int is_objectid_used (reiserfs_filsys_t *, __u32 objectid);
+__u32 get_unused_objectid (reiserfs_filsys_t *);
struct id_map * init_id_map (void);
-void free_id_map (struct id_map **);
-int is_objectid_really_used (struct id_map *, __u32 id, int * ppos);
+void free_id_map (struct id_map *);
+int is_objectid_really_used (struct id_map *, __u32 id, __u32 * ppos);
int mark_objectid_really_used (struct id_map *, __u32 id);
-void flush_objectid_map (struct id_map * map, reiserfs_filsys_t fs);
-void fetch_objectid_map (struct id_map * map, reiserfs_filsys_t fs);
+int __mark_objectid_really_used (struct id_map *, __u32 id, __u32 pos);
+void flush_objectid_map (struct id_map * map, reiserfs_filsys_t * fs);
+void fetch_objectid_map (struct id_map * map, reiserfs_filsys_t * fs);
+void reiserfs_objectid_map_save (FILE * fp, struct id_map * id_map);
+struct id_map * reiserfs_objectid_map_load (FILE * fp);
/* segments.c */
+/*
struct overwritten_unfm_segment {
int ous_begin;
int ous_end;
@@ -275,14 +268,18 @@ struct overwritten_unfm_segment * find_overwritten_unfm (unsigned long unfm, int
int get_unoverwritten_segment (struct overwritten_unfm_segment * list_head, struct overwritten_unfm_segment * unoverwritten_segment);
void save_unfm_overwriting (unsigned long unfm, struct item_head * direct_ih);
void free_overwritten_unfms (void);
+*/
+
void mark_formatted_pointed_by_indirect (__u32);
int is_formatted_pointed_by_indirect (__u32);
+/* size of 1 piece of in-memory map */
+#define MAP_SIZE 4096
struct id_map {
__u32 * m_begin; /* pointer to map area */
- unsigned long m_used_slots_count;
+ __u32 m_used_slots_count;
int m_page_count; /* objectid map expands by one page at
time. This is size of objectid map size in
pages */
@@ -291,125 +288,214 @@ struct id_map {
};
-struct fsck_data {
- unsigned long all_blocks; /* super block's block count */
-
- /* pass 0 */
- unsigned long analyzed; /* blocks marked used (not data not included) */
- unsigned long free; /* free blocks */
- unsigned long not_data; /* super block, bitmap, journal */
- unsigned long leaves; /* blocks looking like reiserfs leaves */
- unsigned long pointed_leaves;
- unsigned long pointed; /* by indirect items */
- unsigned long pointed_once;
- unsigned long pointed_more_than_once;
- unsigned long allocable;
- unsigned long wrong_pointers; /* out of range or pointers to free
- area */
+struct pass0_stat {
+ unsigned long dealt_with; /* number of blocks read during pass 0 */
+ unsigned long leaves; /* blocks looking like reiserfs leaves found */
unsigned long leaves_corrected;
unsigned long all_contents_removed;
+ unsigned long too_old_leaves; /* these are leaves which contains
+ direntries with different hash from the
+ one specified with -h */
+ unsigned long wrong_pointers; /* pointers in indirect items pointing to
+ wrong area */
+ unsigned long pointed; /* pointers blocks of device pointed by all
+ indirect items */
+};
+
- /* pass 1, 2 */
- unsigned long read_leaves;
+struct pass1_stat {
+ unsigned long leaves; /* leaves found in pass0 to build tree off */
+ unsigned long inserted_leaves; /* number of leaves inserted by pointers */
+ unsigned long pointed_leaves; /* pointers in indirect items which pointed
+ to leaves (zeroed) */
unsigned long uninsertable_leaves;
- unsigned long inserted_leaves;
- unsigned long shared_objectids;
- unsigned long saved_on_pass1;
+ unsigned long non_unique_pointers; /* pointers to already pointed unformatted nodes */
+ unsigned long correct_pointers;
+ unsigned long saved_items; /* items saved on pass1: should be 0 */
+ unsigned long allocable_blocks; /* allocable blocks before pass 1 starts */
+};
+
+
+struct pass2_stat {
+ unsigned long leaves; /* leaves inserted item by item */
+ unsigned long safe_non_unique_pointers; /* these are just the same pointers */
unsigned long relocated;
+ unsigned long shared_objectids;
unsigned long rewritten;
+};
- /* stat of semantic pass */
+
+struct semantic_stat {
+ unsigned long oid_sharing_files_relocated;
unsigned long regular_files;
- unsigned long broken_files; /* files having stat data and broken body */
unsigned long directories;
unsigned long symlinks;
+ unsigned long broken_files;
unsigned long others;
unsigned long fixed_sizes;
- unsigned long deleted_entries; /* entries pointing to nowhere */
- unsigned long oid_sharing; /* files relocated due to objectid sharing */
- unsigned long oid_sharing_files_relocated; /* relocated files */
- unsigned long oid_sharing_dirs_relocated; /* relocated dirs */
- unsigned long lost_found;
- unsigned long empty_lost_dirs;
- unsigned long lost_found_dirs;
+ unsigned long oid_sharing;
+ unsigned long oid_sharing_dirs_relocated;
+ unsigned long deleted_entries;
+};
+
+
+struct lost_found_stat {
unsigned long dir_recovered;
+ unsigned long empty_lost_dirs;
+ unsigned long lost_found;
unsigned long lost_found_files;
+ unsigned long lost_found_dirs;
+ unsigned long oid_sharing;
+ unsigned long oid_sharing_dirs_relocated;
+ unsigned long oid_sharing_files_relocated;
+};
- /* pass 4 */
- unsigned long deleted_items; /* items which were not touched by
- semantic pass */
-
- /* objectid maps */
- struct id_map * proper_id_map;
- struct id_map * semantic_id_map; /* this objectid map is used to
- cure objectid sharing problem */
+
+struct pass_4_stat {
+ unsigned long deleted_items;
+};
+
+
+struct rebuild_info {
+ union {
+ struct pass0_stat pass0;
+ struct pass1_stat pass1;
+ struct pass2_stat pass2;
+ struct semantic_stat semantic;
+ struct lost_found_stat lost_found;
+ struct pass_4_stat pass4;
+ } pass_u;
/* bitmaps */
- reiserfs_bitmap_t on_disk_bitmap;
- reiserfs_bitmap_t new_bitmap;
- reiserfs_bitmap_t allocable_bitmap;
+ reiserfs_bitmap_t * source_bitmap;
+ reiserfs_bitmap_t * new_bitmap;
+ reiserfs_bitmap_t * allocable_bitmap;
+ reiserfs_bitmap_t * uninsertables;
char * bitmap_file_name;
- char * new_bitmap_file_name;
+ /*char * new_bitmap_file_name;*/
+ char * passes_dump_file_name; /* after pass 0, 1 or 2 reiserfsck can store
+ data with which it will be able to start
+ from the point it stopped last time at */
unsigned short mode;
unsigned long options;
- /* log file name and handle */
- char * log_file_name;
- FILE * log;
-
+ /* rollback file */
+ char * rollback_file;
+
/* hash hits stat */
int hash_amount;
unsigned long * hash_hits;
+ char * defined_hash;
#define USED_BLOCKS 1
#define EXTERN_BITMAP 2
#define ALL_BLOCKS 3
int scan_area;
+ int use_journal_area;
int test;
};
-#define stats(s) ((struct fsck_data *)((s)->s_vp))
+struct check_info {
+ unsigned long bad_nodes;
+ unsigned long fatal_corruptions;
+ unsigned long fixable_corruptions;
+// unsigned long badblocks_corruptions;
+ unsigned long leaves;
+ unsigned long internals;
+ unsigned long dirs;
+ unsigned long files;
+ unsigned long safe;
+ unsigned long unfm_pointers;
+ unsigned long zero_unfm_pointers;
+};
-#define proper_id_map(s) stats(s)->proper_id_map
-#define semantic_id_map(s) stats(s)->semantic_id_map
-#define fsck_disk_bitmap(s) stats(s)->on_disk_bitmap
-#define fsck_new_bitmap(s) stats(s)->new_bitmap
-#define fsck_allocable_bitmap(s) stats(s)->allocable_bitmap
+struct fsck_data {
+ unsigned short mode; /* check, rebuild, etc*/
+ unsigned long options;
-#define fsck_interactive(fs) (stats(fs)->options & OPT_INTERACTIVE)
-#define fsck_fix_fixable(fs) (stats(fs)->options & OPT_FIX_FIXABLE)
+ struct rebuild_info rebuild;
+ struct check_info check;
+
+ char * journal_dev_name;
+ /* log file name and handle */
+ char * log_file_name;
+ FILE * log;
+
+ /* this is a file where reiserfsck will explain what it is doing. This is
+ usually stderr. But when -g is specified - reiserfsck runs in the
+ background and append progress information into 'fsck.run' */
+ FILE * progress;
+
+ /* objectid maps */
+ struct id_map * proper_id_map;
+ struct id_map * semantic_id_map; /* this objectid map is used to
+ cure objectid sharing problem */
+};
+
+
+#define fsck_data(fs) ((struct fsck_data *)((fs)->fs_vp))
+#define pass_0_stat(fs) (&(fsck_data(fs)->rebuild.pass_u.pass0))
+#define pass_1_stat(fs) (&(fsck_data(fs)->rebuild.pass_u.pass1))
+#define pass_2_stat(fs) (&(fsck_data(fs)->rebuild.pass_u.pass2))
+#define sem_pass_stat(fs) (&(fsck_data(fs)->rebuild.pass_u.semantic))
+#define lost_found_pass_stat(fs) (&(fsck_data(fs)->rebuild.pass_u.lost_found))
+#define pass_4_stat(fs) (&(fsck_data(fs)->rebuild.pass_u.pass4))
+
+#define fsck_check_stat(fs) (&(fsck_data(fs)->check))
+
+
+#define proper_id_map(s) fsck_data(s)->proper_id_map
+#define semantic_id_map(s) fsck_data(s)->semantic_id_map
+
+#define fsck_source_bitmap(fs) fsck_data(fs)->rebuild.source_bitmap
+#define fsck_new_bitmap(fs) fsck_data(fs)->rebuild.new_bitmap
+#define fsck_allocable_bitmap(fs) fsck_data(fs)->rebuild.allocable_bitmap
+#define fsck_uninsertables(fs) fsck_data(fs)->rebuild.uninsertables
+
+
+#define fsck_interactive(fs) (fsck_data(fs)->options & OPT_INTERACTIVE)
+//#define fsck_fix_fixable(fs) (fsck_data(fs)->options & OPT_FIX_FIXABLE)
+
+#define fsck_run_one_step(fs) (fsck_data(fs)->options & OPT_SAVE_PASSES_DUMP)
+
+#define fsck_save_rollback(fs) (fsck_data(fs)->options & OPT_SAVE_ROLLBACK)
/* change unknown modes (corrupted) to mode of regular files, fix file
sizes which are bigger than a real file size, relocate files with
shared objectids (this slows fsck down (when there are too many
files sharing the same objectid), it will also remove other names
pointing to this file */
-#define fsck_fix_non_critical(fs) (stats(fs)->options & OPT_FIX_NON_CRITICAL)
-#define fsck_quiet(fs) (stats(fs)->options & OPT_QUIET)
-#define fsck_silent(fs) (stats(fs)->options & OPT_SILENT)
-
-#define fsck_save_leaf_bitmap(fs) (stats(fs)->options & OPT_SAVE_EXTERN_BITMAP)
+#define fsck_adjust_file_size(fs) (fsck_data(fs)->options & OPT_ADJUST_FILE_SIZE)
+#define fsck_quiet(fs) (fsck_data(fs)->options & OPT_QUIET)
+#define fsck_silent(fs) (fsck_data(fs)->options & OPT_SILENT)
+#define fsck_save_leaf_bitmap(fs) (fsck_data(fs)->options & OPT_SAVE_EXTERN_BITMAP)
+#define fsck_in_background(fs) (fsck_data(fs)->options & OPT_BACKGROUND)
+#define fsck_hash_defined(fs) (fsck_data(fs)->options & OPT_HASH_DEFINED)
+#define fsck_skip_journal(fs) (fsck_data(fs)->options & OPT_SKIP_JOURNAL)
-#define fsck_mode(fs) (stats(fs)->mode)
-#define fsck_log_file(fs) (stats(fs)->log)
+#define fsck_mode(fs) (fsck_data(fs)->mode)
+#define fsck_log_file(fs) (fsck_data(fs)->log)
+#define fsck_progress_file(fs) ((fs && fsck_data(fs)->progress) ? fsck_data(fs)->progress : stderr)
-/* ?? */
-extern inline int change_version (int version)
-{
- return (version == 1)?0:1;
-}
+/* name of file where we store information for continuing */
+#define state_dump_file(fs) fsck_data(fs)->rebuild.passes_dump_file_name
+/* name of file where we store rollback data */
+#define state_rollback_file(fs) fsck_data(fs)->rebuild.rollback_file
-int fsck_user_confirmed (reiserfs_filsys_t fs, char * q, char * a, int default_answer);
-void stage_report (int, reiserfs_filsys_t fs);
+int fsck_user_confirmed (reiserfs_filsys_t * fs, char * q, char * a, int default_answer);
+void stage_report (int, reiserfs_filsys_t *);
/* journal.c */
-int reiserfs_replay_journal (struct super_block * s);
+int replay_journal (reiserfs_filsys_t *);
+
+/*pass1: rebuild super block*/
+void rebuild_sb (reiserfs_filsys_t * fs, char * filename, struct fsck_data * data);
#define fsck_log(fmt, list...) \
@@ -420,6 +506,15 @@ if (!fsck_silent (fs))\
#define fsck_progress(fmt, list...) \
{\
-reiserfs_warning (stderr, fmt, ## list);\
-fflush (stderr);\
+reiserfs_warning (fsck_progress_file(fs), fmt, ## list);\
+fflush (fsck_progress_file(fs));\
+}
+
+#define one_more_corruption(fs,kind) fsck_check_stat (fs)->kind##_corruptions++
+#define one_less_corruption(fs,kind) fsck_check_stat (fs)->kind##_corruptions--
+
+#define fsck_exit(fmt, list...) \
+{\
+reiserfs_warning (fsck_progress_file(fs), fmt, ## list);\
+exit (4);\
}
diff --git a/fsck/info.c b/fsck/info.c
index cd591d8..37a48d2 100644
--- a/fsck/info.c
+++ b/fsck/info.c
@@ -1,99 +1,119 @@
-
/*
- * Copyright 1996-1999 Hans Reiser
+ * Copyright 1996-2002 Hans Reiser
*/
+
#include "fsck.h"
-#include <stdarg.h>
-int fsck_user_confirmed (reiserfs_filsys_t fs, char * q, char * a, int default_answer)
+int fsck_user_confirmed (reiserfs_filsys_t * fs, char * q, char * a, int default_answer)
{
if (!fsck_interactive (fs))
return default_answer;
- return user_confirmed (q, a);
+ return user_confirmed (fsck_progress_file (fs), q, a);
}
-void stage_report (int pass, reiserfs_filsys_t fs)
+void stage_report (int pass, reiserfs_filsys_t * fs)
{
- FILE * fp;
- struct fsck_data * stat;
-
- stat = stats (fs);
- fp = stderr;
-
switch (pass) {
- case 0:
- fsck_progress ("\tRead blocks (but not data blocks) %lu\n", stat->analyzed);
- stat->analyzed = 0;
+ case 0:
+ {
+ struct pass0_stat * stat;
+
+ /* what has been done on pass 0 */
+ stat = pass_0_stat (fs);
+ fsck_progress ("\tRead blocks (but not data blocks) %lu\n", stat->dealt_with);
fsck_progress ("\t\tLeaves among those %lu\n", stat->leaves);
if (stat->leaves_corrected)
fsck_progress ("\t\t\t- corrected leaves %lu\n", stat->leaves_corrected);
if (stat->all_contents_removed)
- fsck_progress ("\t\t\t- eaves all contents of which could not be saved and deleted %lu\n", stat->all_contents_removed);
- if (stat->pointed_leaves)
- fsck_progress ("\t\t\t- leaves pointed by indirect items %lu\n", stat->pointed_leaves);
- if (stat->pointed)
- fsck_progress ("\t\tBlocks pointed by indirect items %lu\n", stat->pointed);
- if (stat->pointed_once)
- fsck_progress ("\t\t\t- once %lu\n", stat->pointed_once);
- if (stat->pointed_more_than_once)
- fsck_progress ("\t\t\t- more than once %lu\n", stat->pointed_more_than_once);
+ fsck_progress ("\t\t\t- leaves all contents of which could not be saved and deleted %lu\n",
+ stat->all_contents_removed);
+ if (stat->too_old_leaves)
+ fsck_progress ("\t\t\t- too old leaves %lu (skipped)\n", stat->too_old_leaves);
if (stat->wrong_pointers)
- fsck_progress ("\t\t\t- pointers to wrong area of filesystem (zeroed) %lu\n", stat->wrong_pointers);
- /* pass1 will calculate how many pointers were zeeros there */
- stat->wrong_pointers = 0;
+ fsck_progress ("\t\tpointers in indirect items to wrong area %lu (zeroed)\n",
+ stat->wrong_pointers);
fsck_progress ("\t\tObjectids found %lu\n", proper_id_map (fs)->objectids_marked);
-
- /*fsck_progress ("\tblocks marked free %lu\n", stat->free);*/
- fsck_progress ("\tallocable %lu blocks\n", stat->allocable);
- break;
-
+ }
+ break;
+
case 1:
- fsck_progress ("\t%lu leaves read\n", stat->analyzed);
+ {
+ struct pass1_stat * stat;
+
+ /* what has been done on pass 1 */
+ stat = pass_1_stat (fs);
+ fsck_progress ("\t%lu leaves read\n", stat->leaves);
fsck_progress ("\t\t%lu inserted\n", stat->inserted_leaves);
+ if (stat->pointed_leaves)
+ fsck_progress ("\t\t\t- pointers in indirect items pointing to metadata %lu (zeroed)\n",
+ stat->pointed_leaves);
+ if (stat->saved_items)
+ fsck_progress ("\tSaved %lu items\n", stat->saved_items);
if (stat->uninsertable_leaves)
fsck_progress ("\t\t%lu not inserted\n", stat->uninsertable_leaves);
- if (stat->saved_on_pass1)
- fsck_progress ("\tSaved %lu items\n", stat->saved_on_pass1);
- if (stat->wrong_pointers)
- fsck_progress ("\tPointers to leaves or non-unique (zeroed) %lu\n",
- stat->wrong_pointers);
- break;
+ if (stat->non_unique_pointers)
+ fsck_progress ("\tnon-unique pointers in indirect items (zeroed) %lu\n",
+ stat->non_unique_pointers);
+ }
+ break;
case 2:
+ {
+ struct pass2_stat * stat;
+
+ /* what has been done on pass 2 */
+ stat = pass_2_stat (fs);
+ if (stat->leaves)
+ fsck_progress ("\tLeaves inserted item by item %lu\n", stat->leaves);
+ if (stat->safe_non_unique_pointers)
+ fsck_progress ("\t%lu \n",
+ stat->safe_non_unique_pointers);
if (stat->shared_objectids)
fsck_progress ("\t%lu shared objectids\n", stat->shared_objectids);
if (stat->relocated)
fsck_progress ("\tFiles relocated because of key conflicts w/ a directory %lu\n",
stat->relocated);
if (stat->rewritten)
- fsck_progress ("\tFiles rewritten %lu\n",
- stat->rewritten);
- return;
+ fsck_progress ("\tFiles rewritten %lu\n", stat->rewritten);
+ }
+ break;
+
+ case 3: /* semantic */
+ {
+ struct semantic_stat * stat;
- case 3: /* semantic pass */
+ /* what has been done on the semantic pass */
+ stat = sem_pass_stat (fs);
fsck_progress ("\tFiles found: %ld\n", stat->regular_files);
fsck_progress ("\tDirectories found: %ld\n", stat->directories);
if (stat->symlinks)
fsck_progress ("\tSymlinks found: %ld\n", stat->symlinks);
if (stat->others)
fsck_progress ("\tOthers: %ld\n", stat->others);
+ if (stat->broken_files)
+ fsck_progress ("\tBroken (of files/symlinks/others): %ld\n", stat->broken_files);
if (stat->fixed_sizes)
fsck_progress ("\tFiles with fixed size: %ld\n", stat->fixed_sizes);
+ if (stat->deleted_entries)
+ fsck_progress ("\tNames pointing to nowhere (removed): %ld\n", stat->deleted_entries);
if (stat->oid_sharing)
fsck_progress ("\tObjects having used objectids: %lu\n", stat->oid_sharing);
if (stat->oid_sharing_files_relocated)
fsck_progress ("\t\tfiles fixed %lu\n", stat->oid_sharing_files_relocated);
if (stat->oid_sharing_dirs_relocated)
fsck_progress ("\t\tdirs fixed %lu\n", stat->oid_sharing_dirs_relocated);
- stat->oid_sharing = 0;
- stat->oid_sharing_files_relocated = 0;
- stat->oid_sharing_dirs_relocated = 0;
- break;
+ }
+ break;
+
+ case 0x3a: /* lost+found pass */
+ {
+ struct lost_found_stat * stat;
- case 0x3a: /* looking for lost files */
+ /* what has been done on the semantic pass */
+ stat = lost_found_pass_stat (fs);
if (stat->lost_found)
fsck_progress ("\tObjects without names %lu\n",
stat->lost_found);
@@ -116,19 +136,40 @@ void stage_report (int pass, reiserfs_filsys_t fs)
fsck_progress ("\t\tfiles fixed %lu\n", stat->oid_sharing_files_relocated);
if (stat->oid_sharing_dirs_relocated)
fsck_progress ("\t\tdirs fixed %lu\n", stat->oid_sharing_dirs_relocated);
- break;
+ }
+ break;
case 4: /* removing of unreachable */
+ {
+ struct pass_4_stat * stat;
+
+ /* what has been done on the semantic pass */
+ stat = pass_4_stat (fs);
if (stat->deleted_items)
fsck_progress ("\tDeleted unreachable items %lu\n",
stat->deleted_items);
- break;
}
+ break;
+
+ case 5:
+ fsck_progress ("There are on the filesystem:\n"
+ "\tLeaves %lu\n\tInternal nodes %lu\n"
+ "\tDirectories %lu\n\tOther files %lu\n"
+ "\tData block pointers %lu (%lu of them are zero)\n"
+ "\tSafe links %lu\n",
+ fsck_check_stat (fs)->leaves,
+ fsck_check_stat (fs)->internals,
+ fsck_check_stat (fs)->dirs,
+ fsck_check_stat (fs)->files,
+ fsck_check_stat (fs)->unfm_pointers,
+ fsck_check_stat (fs)->zero_unfm_pointers,
+ fsck_check_stat (fs)->safe);
+
+
+ } /* switch */
+
+ memset (&fsck_data (fs)->rebuild.pass_u, 0, sizeof (fsck_data (fs)->rebuild.pass_u));
- if (!fsck_user_confirmed (fs, "Continue? (Yes):", "Yes\n", 1)) {
- reiserfs_close (fs);
- exit (0);
- }
}
diff --git a/fsck/journal.c b/fsck/journal.c
deleted file mode 100644
index 656dc4d..0000000
--- a/fsck/journal.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright 2000 Hans Reiser
- */
-
-#include "fsck.h"
-#include <limits.h>
-/*#include <stdlib.h>*/
-
-
-
-
-
-#define bh_desc(bh) ((struct reiserfs_journal_desc *)((bh)->b_data))
-#define bh_commit(bh) ((struct reiserfs_journal_commit *)((bh)->b_data))
-
-
-
-
-
-
-
-static int next_expected_desc (struct super_block * s, struct buffer_head * d_bh)
-{
- int offset;
- struct reiserfs_journal_desc * desc;
-
- desc = (struct reiserfs_journal_desc *)d_bh->b_data;
- offset = d_bh->b_blocknr - SB_JOURNAL_BLOCK (s);
- return SB_JOURNAL_BLOCK (s) + ((offset + desc->j_len + 1 + 1) % JOURNAL_BLOCK_COUNT);
-}
-
-
-static int is_valid_transaction (struct super_block * s, struct buffer_head * d_bh)
-{
- struct buffer_head * c_bh;
- int offset;
- struct reiserfs_journal_desc *desc = (struct reiserfs_journal_desc *)d_bh->b_data;
- struct reiserfs_journal_commit *commit ;
- __u32 block, start_block;
-
-
- offset = d_bh->b_blocknr - SB_JOURNAL_BLOCK (s);
-
- /* ok, we have a journal description block, lets see if the transaction was valid */
- block = next_expected_desc (s, d_bh) - 1;
- start_block = d_bh->b_blocknr;
- while(!(c_bh = bread (s->s_dev, block, s->s_blocksize))){
- if (++block == SB_JOURNAL_BLOCK (s) + JOURNAL_BLOCK_COUNT)
- block = SB_JOURNAL_BLOCK (s);
- if (block == start_block)
- return 0;
- }
-
- commit = (struct reiserfs_journal_commit *)c_bh->b_data ;
- if (does_desc_match_commit (desc, commit)) {
- // if (journal_compare_desc_commit (s, desc, commit)) {
-/* printf ("desc and commit block do not match\n");*/
- brelse (c_bh) ;
- return 0;
- }
- brelse (c_bh);
- return 1;
-}
-
-
-int reiserfs_replay_journal (struct super_block * s)
-{
- struct buffer_head * d_bh, * c_bh, * jh_bh;
- struct reiserfs_journal_header * j_head;
- struct reiserfs_journal_desc * j_desc;
- struct reiserfs_journal_commit * j_commit;
- unsigned long latest_mount_id;
- unsigned long j_cur;
- unsigned long j_start;
- unsigned long j_size;
- unsigned long mount_id, trans_id;
- unsigned long t_first, t_last, t_count, t_flushed;
- unsigned long t_offset;
- int i;
-
- fsck_progress ("Analyzing journal..");
-
- j_start = SB_JOURNAL_BLOCK (s);
- j_cur = 0;
- j_size = rs_journal_size (s->s_rs);
- t_first = 0;
- t_last = 0;
- latest_mount_id = 0;
-
- /* look for the transactions with the most recent mount_id */
- for (j_cur = 0; j_cur < j_size; ) {
- d_bh = bread (s->s_dev, j_start + j_cur, s->s_blocksize);
- if (d_bh && who_is_this (d_bh->b_data, d_bh->b_size) == THE_JDESC && is_valid_transaction (s, d_bh)) {
- j_desc = (struct reiserfs_journal_desc *)d_bh->b_data;
-
- mount_id = le32_to_cpu (j_desc->j_mount_id);
- trans_id = le32_to_cpu (j_desc->j_trans_id);
-
- if (mount_id > latest_mount_id) {
- /* more recent mount_id found */
- latest_mount_id = mount_id;
- t_first = t_last = trans_id;
- t_offset = j_cur;
- t_count = 1;
- } else if (mount_id == latest_mount_id) {
- t_count ++;
- if (trans_id > t_last)
- t_last = trans_id;
- if (trans_id < t_first) {
- t_first = trans_id;
- t_offset = j_cur;
- }
- }
- j_cur += le32_to_cpu (j_desc->j_len) + 1;
- }
- j_cur ++;
- brelse (d_bh);
- }
-
- /* replay only if journal header looks resonable */
- jh_bh = bread (s->s_dev, j_start + j_size, s->s_blocksize);
- j_head = (struct reiserfs_journal_header *)(jh_bh->b_data);
-
- if (latest_mount_id != le32_to_cpu (j_head->j_mount_id)) {
- fsck_progress ("nothing to replay (no transactions match to latest mount id)\n");
- brelse (jh_bh);
- return 0;
- }
- /* last transaction flushed - which should not be replayed */
- t_flushed = le32_to_cpu (j_head->j_last_flush_trans_id);
- if (t_flushed >= t_last) {
- fsck_progress ("nothing to replay (no transactions older than last flushed one found)\n");
- brelse (jh_bh);
- return 0;
- }
- if (t_first > t_flushed + 1) {
- if (t_flushed)
- fsck_progress ("last flushed trans %lu, the oldest but newer is %lu\n",
- t_flushed, t_first);
- } else {
- /* start replaying with first not flushed transaction */
- t_first = t_flushed + 1;
- t_offset = le32_to_cpu (j_head->j_first_unflushed_offset);
- }
-
- fsck_progress ("last flushed trans %lu, mount_id %lu, "
- "will replay from %lu up to %lu:Yes?",
- t_flushed, latest_mount_id, t_first, t_last);
- if (!fsck_user_confirmed (fs, "", "Yes\n", 1))
- die ("");
-
- /* replay transactions we have found */
- for (j_cur = t_offset; t_first <= t_last; t_first ++) {
- unsigned long offset;
-
- d_bh = bread (s->s_dev, j_start + j_cur, s->s_blocksize);
- j_desc = (struct reiserfs_journal_desc *)d_bh->b_data;
- if (who_is_this (d_bh->b_data, d_bh->b_size) != THE_JDESC ||
- le32_to_cpu (j_desc->j_mount_id) != latest_mount_id ||
- le32_to_cpu (j_desc->j_trans_id) != t_first)
- die ("reiserfs_replay_journal: desc block not found");
-
- offset = j_cur + 1;
- j_cur += le32_to_cpu (j_desc->j_len) + 1;
- j_cur %= j_size;
- c_bh = bread (s->s_dev, j_start + j_cur, s->s_blocksize);
- j_commit = (struct reiserfs_journal_commit *)c_bh->b_data;
- if (does_desc_match_commit (j_desc, j_commit))
- die ("reiserfs_replay_journal: commit block not found");
-
- fsck_log ("Mount_id %lu, transaction %lu, desc block %lu, commit block %lu: (",
- latest_mount_id, t_first, d_bh->b_blocknr, c_bh->b_blocknr);
-
- /* replay one transaction */
- for (i = 0; i < le32_to_cpu (j_desc->j_len); i ++) {
- struct buffer_head * in_place, * log;
- unsigned long block;
-
- log = bread (s->s_dev, j_start + ((offset + i) % j_size), s->s_blocksize);
-
- if (i < JOURNAL_TRANS_HALF) {
- block = le32_to_cpu (j_desc->j_realblock[i]);
- } else {
- block = le32_to_cpu (j_commit->j_realblock[i - JOURNAL_TRANS_HALF]);
- }
-
- if (not_journalable (s, block)) {
- fsck_log ("transaction %lu, block %d could not be replayed (%lu)\n",
- t_first, i, block);
- } else {
- fsck_log (" %lu", block);
-
- in_place = getblk (s->s_dev, block, s->s_blocksize) ;
- memcpy (in_place->b_data, log->b_data, s->s_blocksize);
- mark_buffer_dirty (in_place);
- mark_buffer_uptodate (in_place, 1);
- bwrite (in_place);
- brelse (in_place);
- }
- brelse (log);
-
- }
- fsck_log (")\n");
-
- brelse (d_bh);
- brelse (c_bh);
- j_cur ++;
- j_cur %= j_size;
-
- /* update journal header */
- j_head->j_last_flush_trans_id = cpu_to_le32 (t_first);
- mark_buffer_dirty (jh_bh);
- bwrite (jh_bh);
- }
-
- brelse (jh_bh);
- fsck_progress ("Journal replaied\n");
- return 0;
-}
diff --git a/fsck/lost+found.c b/fsck/lost+found.c
index 83e77e7..17fdb1a 100644
--- a/fsck/lost+found.c
+++ b/fsck/lost+found.c
@@ -1,12 +1,17 @@
/*
- * Copyright 2000-2001 Hans Reiser
+ * Copyright 2000-2002 Hans Reiser
*/
#include "fsck.h"
+void erase_name (int len);
+void print_name (char * name, int len);
+
+void modify_item (struct item_head * ih, void * item);
+
/* fixme: search_by_key is not needed after any add_entry */
-static __u64 _look_for_lost (reiserfs_filsys_t fs, int link_lost_dirs)
+static __u64 _look_for_lost (reiserfs_filsys_t * fs, int link_lost_dirs)
{
struct key key, prev_key, * rdkey;
INITIALIZE_PATH (path);
@@ -36,12 +41,12 @@ static __u64 _look_for_lost (reiserfs_filsys_t fs, int link_lost_dirs)
/* total size of added entries */
size = 0;
while (1) {
- retval = usearch_by_key (fs, &key, &path);
+ retval = reiserfs_search_by_key_4 (fs, &key, &path);
/* fixme: we assume path ends up with a leaf */
bh = get_bh (&path);
item_pos = get_item_pos (&path);
if (retval != ITEM_FOUND) {
- if (item_pos == node_item_number (bh)) {
+ if (item_pos == get_blkh_nr_items (B_BLK_HEAD (bh))) {
rdkey = uget_rkey (&path);
if (!rdkey) {
pathrelse (&path);
@@ -56,9 +61,9 @@ static __u64 _look_for_lost (reiserfs_filsys_t fs, int link_lost_dirs)
/* print ~ how many leaves were scanned and how fast it was */
if (!fsck_quiet (fs))
- print_how_fast (0, leaves++, 50);
+ print_how_fast (leaves++, 0, 50, 0);
- for (ih = get_ih (&path); item_pos < node_item_number (bh); item_pos ++, ih ++) {
+ for (ih = get_ih (&path); item_pos < get_blkh_nr_items (B_BLK_HEAD (bh)); item_pos ++, ih ++, PATH_LAST_POSITION(&path)++) {
if (is_item_reachable (ih))
continue;
@@ -74,14 +79,15 @@ static __u64 _look_for_lost (reiserfs_filsys_t fs, int link_lost_dirs)
sd = ih->ih_key;
set_type_and_offset (KEY_FORMAT_1, &sd, SD_OFFSET, TYPE_STAT_DATA);
- if (usearch_by_key (fs, &sd, &tmp) == ITEM_FOUND) {
+ if (reiserfs_search_by_key_4 (fs, &sd, &tmp) == ITEM_FOUND) {
/* should not happen - because if there were a stat data -
we would have done with the whole directory */
pathrelse (&tmp);
continue;
}
- stats(fs)->dir_recovered ++;
- create_dir_sd (fs, &tmp, &sd);
+ lost_found_pass_stat (fs)->dir_recovered ++;
+ create_dir_sd (fs, &tmp, &sd, modify_item);
+ mark_objectid_really_used (proper_id_map (fs), get_key_objectid (&sd));
key = sd;
pathrelse (&path);
goto cont;
@@ -89,7 +95,10 @@ static __u64 _look_for_lost (reiserfs_filsys_t fs, int link_lost_dirs)
/* stat data marked "not having name" found */
- is_it_dir = ((not_a_directory (B_I_PITEM (bh,ih))) ? 0 : 1);
+ if (is_stat_data_ih (get_ih(&path)))
+ fix_obviously_wrong_sd_mode (&path);
+
+ is_it_dir = ((not_a_directory (B_I_PITEM (bh,ih))) ? 0 : 1);
if (is_it_dir) {
struct key tmp_key;
@@ -99,17 +108,17 @@ static __u64 _look_for_lost (reiserfs_filsys_t fs, int link_lost_dirs)
/* there is no need to link empty lost directories into /lost+found */
tmp_key = ih->ih_key;
set_type_and_offset (KEY_FORMAT_1, &tmp_key, 0xffffffff, TYPE_DIRENTRY);
- usearch_by_key (fs, &tmp_key, &tmp_path);
+ reiserfs_search_by_key_4 (fs, &tmp_key, &tmp_path);
tmp_ih = get_ih (&tmp_path);
tmp_ih --;
if (not_of_one_file (&tmp_key, tmp_ih))
reiserfs_panic ("not directory found");
if (!is_direntry_ih (tmp_ih) ||
- (deh_offset (B_I_DEH (get_bh (&tmp_path), ih) +
- ih_entry_count (tmp_ih) - 1) == DOT_DOT_OFFSET)) {
+ (get_deh_offset (B_I_DEH (get_bh (&tmp_path), tmp_ih) +
+ get_ih_entry_count (tmp_ih) - 1) == DOT_DOT_OFFSET)) {
/* last directory item is either stat data or empty
directory item - do not link this dir into lost+found */
- stats(fs)->empty_lost_dirs ++;
+ lost_found_pass_stat (fs)->empty_lost_dirs ++;
pathrelse (&tmp_path);
continue;
}
@@ -122,72 +131,75 @@ static __u64 _look_for_lost (reiserfs_filsys_t fs, int link_lost_dirs)
continue;
}
- stats(fs)->lost_found ++;
+ lost_found_pass_stat (fs)->lost_found ++;
{
struct key obj_key = {0, 0, {{0, 0},}};
char * lost_name;
struct item_head tmp_ih;
- int pos_in_map;
+ __u32 pos_in_map;
/* key to continue */
key = ih->ih_key;
- key.k_objectid ++;
+ set_key_objectid (&key, get_key_objectid (&key) + 1);
tmp_ih = *ih;
- if (is_objectid_really_used (semantic_id_map (fs), ih->ih_key.k_objectid,
+ if (is_objectid_really_used (semantic_id_map (fs),
+ get_key_objectid (&ih->ih_key),
&pos_in_map)) {
/* objectid is used, relocate an object */
- stats(fs)->oid_sharing ++;
- if (fsck_fix_non_critical (fs)) {
+ lost_found_pass_stat (fs)->oid_sharing ++;
+ if (1/*fsck_adjust_file_size (fs)*/) {
if (is_it_dir) {
relocate_dir (&tmp_ih, 1);
- stats(fs)->oid_sharing_dirs_relocated ++;
+ lost_found_pass_stat (fs)->oid_sharing_dirs_relocated ++;
} else {
relocate_file (&tmp_ih, 1);
- stats(fs)->oid_sharing_files_relocated ++;
+ lost_found_pass_stat (fs)->oid_sharing_files_relocated ++;
}
}
} else {
if (!is_it_dir)
- mark_objectid_really_used (semantic_id_map (fs), ih->ih_key.k_objectid);
+ mark_objectid_really_used (semantic_id_map (fs), get_key_objectid (&ih->ih_key));
}
- asprintf (&lost_name, "%u_%u", le32_to_cpu (tmp_ih.ih_key.k_dir_id),
- le32_to_cpu (tmp_ih.ih_key.k_objectid));
+ asprintf (&lost_name, "%u_%u", get_key_dirid (&tmp_ih.ih_key),
+ get_key_objectid (&tmp_ih.ih_key));
/* entry in lost+found directory will point to this key */
- obj_key.k_dir_id = tmp_ih.ih_key.k_dir_id;
- obj_key.k_objectid = tmp_ih.ih_key.k_objectid;
-
+ set_key_dirid (&obj_key, get_key_dirid (&tmp_ih.ih_key));
+ set_key_objectid (&obj_key, get_key_objectid (&tmp_ih.ih_key));
pathrelse (&path);
/* 0 does not mean anyting - item w/ "." and ".." already
exists and reached, so only name will be added */
- size += reiserfs_add_entry (fs, &lost_found_dir_key, lost_name, &obj_key, 0/*fsck_need*/);
+ size += reiserfs_add_entry (fs, &lost_found_dir_key, lost_name,
+ name_length (lost_name, lost_found_dir_format), &obj_key, 0/*fsck_need*/);
if (is_it_dir) {
/* fixme: we hope that if we will try to pull all the
directory right now - then there will be less
lost_found things */
- fsck_progress ("\tChecking lost dir \"%s\":", lost_name);
+ print_name (lost_name, strlen (lost_name));
+ /*fsck_progress ("\tChecking lost dir \"%s\":", lost_name);*/
rebuild_semantic_pass (&obj_key, &lost_found_dir_key, /*dot_dot*/0, /*reloc_ih*/0);
- fsck_progress ("ok\n");
- stats(fs)->lost_found_dirs ++;
+ erase_name (strlen (lost_name));
+ /*fsck_progress ("ok\n");*/
+
+ lost_found_pass_stat (fs)->lost_found_dirs ++;
} else {
- if (usearch_by_key (fs, &obj_key, &path) != ITEM_FOUND)
+ if (reiserfs_search_by_key_4 (fs, &obj_key, &path) != ITEM_FOUND)
reiserfs_panic ("look_for_lost: lost file stat data %K not found",
&obj_key);
/* check_regular_file does not mark stat data reachable */
mark_item_reachable (get_ih (&path), get_bh (&path));
- mark_buffer_dirty (get_bh (&path));
rebuild_check_regular_file (&path, get_item (&path), 0/*reloc_ih*/);
pathrelse (&path);
- stats(fs)->lost_found_files ++;
+ lost_found_pass_stat (fs)->lost_found_files ++;
lost_files --;
}
@@ -197,7 +209,14 @@ static __u64 _look_for_lost (reiserfs_filsys_t fs, int link_lost_dirs)
} /* for */
prev_key = key;
- get_next_key (&path, item_pos - 1, &key);
+
+ PATH_LAST_POSITION(&path) = item_pos - 1;
+ rdkey = reiserfs_next_key (&path);
+ if (rdkey)
+ key = *rdkey;
+ else
+ break;
+
if (comp_keys (&prev_key, &key) != -1)
reiserfs_panic ("pass_3a: key must grow 2: prev=%k next=%k",
&prev_key, &key);
@@ -227,16 +246,90 @@ static __u64 _look_for_lost (reiserfs_filsys_t fs, int link_lost_dirs)
}
+static void save_lost_found_result (reiserfs_filsys_t * fs)
+{
+ FILE * file;
+ int retval;
+
+ /* save bitmaps with which we will be able start reiserfs from
+ pass 1 */
+ file = open_file ("temp_fsck_file.deleteme", "w+");
+ if (!file)
+ return;
+
+ reiserfs_begin_stage_info_save (file, LOST_FOUND_DONE);
+ reiserfs_end_stage_info_save (file);
+ close_file (file);
+
+ retval = unlink (state_dump_file (fs));
+ retval = rename ("temp_fsck_file.deleteme", state_dump_file (fs));
+ if (retval != 0)
+ fsck_progress ("pass 0: could not rename temp file temp_fsck_file.deleteme to %s",
+ state_dump_file (fs));
+}
+
+/* we have nothing to load from a state file, but we have to fetch
+ on-disk bitmap, copy it to allocable bitmap, and fetch objectid
+ map */
+void load_lost_found_result (reiserfs_filsys_t * fs)
+{
+ fsck_new_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb));
+ reiserfs_bitmap_copy (fsck_new_bitmap (fs), fs->fs_bitmap2);
+
+ fsck_allocable_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb));
+ reiserfs_bitmap_copy (fsck_allocable_bitmap (fs), fs->fs_bitmap2);
+
+ fs->block_allocator = reiserfsck_reiserfs_new_blocknrs;
+ fs->block_deallocator = reiserfsck_reiserfs_free_block;
-void pass_3a_look_for_lost (reiserfs_filsys_t fs)
+ /* we need objectid map on semantic pass to be able to relocate files */
+ proper_id_map (fs) = init_id_map ();
+ fetch_objectid_map (proper_id_map (fs), fs);
+}
+
+void after_lost_found (reiserfs_filsys_t * fs)
+{
+ /* update super block: objectid map, fsck state */
+ set_sb_fs_state (fs->fs_ondisk_sb, LOST_FOUND_DONE);
+ mark_buffer_dirty (fs->fs_super_bh);
+
+ /* write all dirty blocks */
+ fsck_progress ("Flushing..");
+ flush_objectid_map (proper_id_map (fs), fs);
+ fs->fs_dirt = 1;
+ reiserfs_flush_to_ondisk_bitmap (fsck_new_bitmap(fs), fs);
+ reiserfs_flush (fs);
+ fsck_progress ("done\n");
+
+ stage_report (0x3a, fs);
+
+ if (!fsck_run_one_step (fs)) {
+ if (fsck_user_confirmed (fs, "Continue? (Yes):", "Yes\n", 1))
+ /* reiserfsck continues */
+ return;
+ }
+
+ save_lost_found_result (fs);
+
+ free_id_map (proper_id_map (fs));
+ proper_id_map (fs) = 0;
+
+ fs->fs_dirt = 1;
+ reiserfs_close (fs);
+ exit (4);
+}
+
+void pass_3a_look_for_lost (reiserfs_filsys_t * fs)
{
INITIALIZE_PATH (path);
struct item_head * ih;
void * sd;
__u64 size, sd_size;
__u32 blocks;
-
- fsck_progress ("Pass 3a (looking for lost files):\n");
+ __u16 mode;
+ __u32 objectid;
+ int gen_counter;
+ fsck_progress ("Pass 3a (looking for lost dir/files):\n");
/* when warnings go not to stderr - separate then in the log */
if (fsck_log_file (fs) != stderr)
@@ -250,20 +343,33 @@ void pass_3a_look_for_lost (reiserfs_filsys_t fs)
size += _look_for_lost (fs, 0);
/* update /lost+found sd_size and sd_blocks (nlink is correct already) */
- if (usearch_by_key (fs, &lost_found_dir_key, &path) != ITEM_FOUND)
+
+ objectid = reiserfs_find_entry (fs, &root_dir_key, "lost+found",
+ &gen_counter, &lost_found_dir_key);
+
+ if (!objectid) {
+ reiserfs_panic ("look_for_lost: 'lost+found' direntry not found");
+ }
+
+ if (reiserfs_search_by_key_4 (fs, &lost_found_dir_key, &path) != ITEM_FOUND)
reiserfs_panic ("look_for_lost: /lost+found stat data %K not found",
&lost_found_dir_key);
ih = get_ih (&path);
sd = get_item (&path);
get_sd_size (ih, sd, &sd_size);
size += sd_size;
- blocks = dir_size2st_blocks (fs->s_blocksize, size);
+ blocks = dir_size2st_blocks (size);
set_sd_size (ih, sd, &size);
set_sd_blocks (ih, sd, &blocks);
+
+ /* make lost+found to be drwx------ */
+ mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR;
+ set_sd_mode (ih, sd, &mode);
+
mark_buffer_dirty (get_bh (&path));
pathrelse (&path);
-
- stage_report (0x3a, fs);
+
+ after_lost_found (fs);
}
diff --git a/fsck/main.c b/fsck/main.c
index 9f9575e..7850acb 100644
--- a/fsck/main.c
+++ b/fsck/main.c
@@ -1,40 +1,82 @@
/*
- * Copyright 1996-2000 Hans Reiser
+ * Copyright 1996-2002 Hans Reiser
*/
#include "fsck.h"
#include <getopt.h>
+#include <sys/resource.h>
+#include "../include/config.h"
#include "../version.h"
+extern int screen_width;
+extern int screen_savebuffer_len;
+extern char *screen_savebuffer;
+reiserfs_filsys_t * fs;
+char * badblocks_file;
-#define print_usage_and_exit() die ("Usage: %s [options] "\
+#define print_usage_and_exit() {\
+fsck_progress ("Usage: %s [mode] [options] "\
" device\n"\
"\n"\
-"Options:\n\n"\
+"Modes:\n"\
" --check\t\tconsistency checking (default)\n"\
+" --fix-fixable\t\tfix corruptions which can be fixed w/o --rebuild-tree\n"\
" --rebuild-sb\t\tsuper block checking and rebuilding if needed\n"\
+" \t\t\t(require rebuild-tree afterwards)\n"\
" --rebuild-tree\tforce fsck to rebuild filesystem from scratch\n"\
" \t\t\t(takes a long time)\n"\
-" --interactive, -i\tmake fsck to stop after every stage\n"\
+" --clean-attributes\tclean garbage in reserved fields in StatDatas on fs\n"\
+"Options:\n"\
+" -j | --journal-device device\n"\
+" \t\t\tspecify journal if relocated\n"\
" -l | --logfile logfile\n"\
" \t\t\tmake fsck to complain to specifed file\n"\
-" -b | --scan-marked-in-bitmap file\n"\
-" \t\t\tbuild tree of blocks marked in the bitmapfile\n"\
-" -c | --create-bitmap-file\n"\
-" \t\t\tsave bitmap of found leaves\n"\
-" -x | --fix-fixable\tfix corruptions which can be fixed w/o --rebuild-tree\n"\
-" -o | --fix-non-critical\n"\
-" \t\t\tfix strange modes, file sizes to real size and\n"\
-" \t\t\trelocate files using busy objectids\n"\
+" -n | --nolog\t\tmake fsck to not complain\n"\
+" -z | --adjust-file-size\n"\
+" \t\t\tfix file sizes to real size\n"\
+" \t\t\tlist of all bad blocks on the fs\n"\
" -q | --quiet\t\tno speed info\n"\
-" -n | --nolog\t\t suppresses all logs\n"\
" -V\t\t\tprints version and exits\n"\
-" -a\t\t\tmakes fsck to do nothing\n"\
-" -p\t\t\tdo nothing, exist for compatibility with fsck(8)\n"\
-" -r\n", argv[0]);
+" -a and -p\t\tprint fs info and exits\n"\
+" -f, -r and -y\t\tignored\n"\
+"Expert options:\n"\
+" --no-journal-available\n"\
+" \t\t\tdo not open nor replay journal\n"\
+" -S | --scan-whole-partition\n"\
+" \t\t\tbuild tree of all blocks of the device\n", argv[0]);\
+ exit (16);\
+}
+/*
+" -B badblocks-file\n"\
+
+ -B works with --fix-fixable
+ fixes indirect pointers pointed to
+ badblocks, adds badblocks to badblock list in fs.
+ and with --rebuild
+ builds the tree w/out pointers to badblocks (internal,
+ indirect), adds badblocks to badblock list in fs.
+*/
+/*
+Hidden usage:
+Modes:
+" --rollback-fsck-changes\n\t\t\trollback all changes made by fsck\n"\
+Options:
+" -b | --scan-marked-in-bitmap file\n"\
+" \t\t\tbuild tree of blocks marked in the bitmapfile\n"\
+" -R | --rollback-data file\n"\
+" \t\t\tback up all changes to this file or rollback from this file\n"\
+" \t\t\tpreviously backed up changes with --rollback-fsck-changes\n"\
+" -d dumpfile\n\"\
+" \t\t\tto test fsck pass by pass - dump into dumpfile all needed\n"\
+" \t\t\tinfo for the next pass and load on the start of the next pass\n"\
+" -i | --interactive\tmake fsck to stop after every stage\n"\
+" -h | --hash hashname\n"\
+" -g | --background\n"\
+" -t \t\tdo test\n"\
+*/
/* fsck is called with one non-optional argument - file name of device
@@ -44,23 +86,26 @@ static char * parse_options (struct fsck_data * data, int argc, char * argv [])
{
int c;
static int mode = FSCK_CHECK;
+ static int flag;
- data->scan_area = USED_BLOCKS;
+ data->rebuild.scan_area = USED_BLOCKS;
while (1) {
static struct option options[] = {
/* modes */
{"check", no_argument, &mode, FSCK_CHECK},
+ {"fix-fixable", no_argument, &mode, FSCK_FIX_FIXABLE},
{"rebuild-sb", no_argument, &mode, FSCK_SB},
{"rebuild-tree", no_argument, &mode, FSCK_REBUILD},
+ {"rollback-fsck-changes", no_argument, &mode, FSCK_ROLLBACK_CHANGES},
+ {"clean-attributes", no_argument, &mode, FSCK_CLEAN_ATTRIBUTES},
/*
- {"fast-rebuild", no_argument, &opt_fsck_mode, FSCK_FAST_REBUILD},
+ {"fast-rebuild", no_argument, &opt_fsck_mode, FSCK_FAST_REBUILD},
*/
/* options */
{"logfile", required_argument, 0, 'l'},
{"interactive", no_argument, 0, 'i'},
- {"fix-fixable", no_argument, 0, 'x'},
- {"fix-non-critical", no_argument, 0, 'o'},
+ {"adjust-file-size", no_argument, 0, 'z'},
{"quiet", no_argument, 0, 'q'},
{"nolog", no_argument, 0, 'n'},
@@ -68,28 +113,42 @@ static char * parse_options (struct fsck_data * data, int argc, char * argv [])
blocks marked used in that bitmap will be read */
{"scan-marked-in-bitmap", required_argument, 0, 'b'},
- /* */
- {"create-leaf-bitmap", required_argument, 0, 'c'},
-
+ {"create-passes-dump", required_argument, 0, 'd'},
+
/* all blocks will be read */
{"scan-whole-partition", no_argument, 0, 'S'},
+ /* useful for -S */
+ {"hash", required_argument, 0, 'h'},
+
+ /* preparing rollback data*/
+ {"rollback-data", required_argument, 0, 'R'},
- /* special option: will mark free blocks used, zero all
- unformatted node pointers and mark them free */
- {"zero-files", no_argument, &mode, FSCK_ZERO_FILES},
+ {"journal-device", required_argument, 0, 'j'},
+ {"no-journal-available", no_argument, &flag, OPT_SKIP_JOURNAL},
+
+// {"bad-block-file", required_argument, 0, 'B'},
+
+ /* start reiserfsck in background and exit */
+ {"background", no_argument, 0, 'g'},
+
{0, 0, 0, 0}
};
int option_index;
- c = getopt_long (argc, argv, "iql:b:Sc:xoVaprt:n",
+ c = getopt_long (argc, argv, "iql:nb:Szd:R:h:j:gafVrpyt:",
options, &option_index);
if (c == -1)
break;
switch (c) {
case 0:
- /* long option specifying fsck mode is found */
- break;
+ /* long-only options */
+ if (flag == OPT_SKIP_JOURNAL) {
+ /* no journal available */
+ data->options |= OPT_SKIP_JOURNAL;
+ flag = 0;
+ }
+ break;
case 'i': /* --interactive */
data->options |= OPT_INTERACTIVE;
@@ -100,54 +159,92 @@ static char * parse_options (struct fsck_data * data, int argc, char * argv [])
break;
case 'l': /* --logfile */
- asprintf (&data->log_file_name, "%s", optarg);
+ data->log_file_name = optarg;
+ /*asprintf (&data->log_file_name, "%s", optarg);*/
data->log = fopen (optarg, "w");
if (!data->log)
fprintf (stderr, "reiserfsck: could not open \'%s\': %m", optarg);
+ break;
+ case 'n': /* --nolog */
+ data->options |= OPT_SILENT;
break;
case 'b': /* --scan-marked-in-bitmap */
/* will try to load a bitmap from a file and read only
blocks marked in it. That bitmap could be created by
previous run of reiserfsck with -c */
- asprintf (&data->bitmap_file_name, "%s", optarg);
- data->scan_area = EXTERN_BITMAP;
+ data->rebuild.bitmap_file_name = optarg;
+ /*asprintf (&data->rebuild.bitmap_file_name, "%s", optarg);*/
+ data->rebuild.scan_area = EXTERN_BITMAP;
break;
case 'S': /* --scan-whole-partition */
- data->scan_area = ALL_BLOCKS;
+ data->rebuild.scan_area = ALL_BLOCKS;
break;
- case 'c': /* --create-leaf-bitmap */
- asprintf (&data->new_bitmap_file_name, "%s", optarg);
- data->options |= OPT_SAVE_EXTERN_BITMAP;
+#if 0
+ case 'J': /* take all blocks which are leaves in journal area and put
+ them into tree item by item (DO NOT USE IT UNTIL YOU KNOW
+ WHAT ARE YOU DOING) */
+ data->rebuild.use_journal_area = 1;
break;
-
- case 'x': /* --fix-fixable */
- data->options |= OPT_FIX_FIXABLE;
+#endif
+ case 'd': /* --create-passes-dump */
+ asprintf (&data->rebuild.passes_dump_file_name, "%s", optarg);
+ data->options |= OPT_SAVE_PASSES_DUMP;
+ break;
+
+ case 'z': /* --adjust-file-size */
+ data->options |= OPT_ADJUST_FILE_SIZE;
break;
- case 'o': /* --fix-non-critical */
- data->options |= OPT_FIX_NON_CRITICAL;
+ case 'h': /* --hash: suppose that this hash was used on a filesystem */
+ asprintf (&data->rebuild.defined_hash, "%s", optarg);
+ if (name2func (data->rebuild.defined_hash) == 0)
+ reiserfs_panic ("reiserfsck: unknown hash is defined: %s",
+ data->rebuild.defined_hash);
+ data->options |= OPT_HASH_DEFINED;
break;
- case 'n': /* --nolog */
- data->options |= OPT_SILENT;
+ case 'j': /* specified relocated journal device */
+ data->journal_dev_name = optarg;
+ break;
+
+ case 'R': /* preparing rollback data */
+ asprintf (&data->rebuild.rollback_file, "%s", optarg);
+ data->options |= OPT_SAVE_ROLLBACK;
+ break;
+
+ case 'B': /* list of phisically corrupted blocks */
+ asprintf (&badblocks_file, "%s", optarg);
+ data->options |= BADBLOCKS_FILE;
+ break;
+
+ case 'g': /* --background */
+ data->options |= OPT_BACKGROUND;
break;
- case 'V':
- case 'p': /* these say reiserfsck to do nothing */
- case 'r':
case 'a':
+ case 'p':
+ mode = AUTO;
+ break;
+
+ case 'f':
+ case 'r': /* ignored */
+ case 'y':
+ break;
+
+ case 'V': /* cause fsck to do nothing */
mode = DO_NOTHING;
break;
-
+
case 't':
mode = DO_TEST;
- data->test = atoi (optarg);
+ data->rebuild.test = atoi (optarg);
break;
+
default:
print_usage_and_exit();
}
@@ -156,516 +253,656 @@ static char * parse_options (struct fsck_data * data, int argc, char * argv [])
if (optind != argc - 1 && mode != DO_NOTHING)
/* only one non-option argument is permitted */
print_usage_and_exit();
+
+
+ if (mode != FSCK_REBUILD &&
+ (data->rebuild.scan_area == EXTERN_BITMAP ||
+ data->rebuild.scan_area == ALL_BLOCKS ||
+ data->options & OPT_SAVE_PASSES_DUMP))
+ /* wrong options for this mode */
+ print_usage_and_exit();
+
+ if (data->options & OPT_ADJUST_FILE_SIZE) {
+ if ((mode != FSCK_REBUILD) && (mode != FSCK_FIX_FIXABLE))
+ print_usage_and_exit();
+ }
+
+ if (data->options & OPT_SAVE_ROLLBACK) {
+ if (mode == FSCK_SB)
+ print_usage_and_exit();
+ }
+
+ if (mode == FSCK_ROLLBACK_CHANGES) {
+ if ((data->options & OPT_SAVE_ROLLBACK) == 0)
+ print_usage_and_exit();
+ }
+
+ if ((data->options & BADBLOCKS_FILE) && ((mode == FSCK_SB)
+ || (mode == FSCK_CLEAN_ATTRIBUTES) || (mode == FSCK_CHECK)))
+ print_usage_and_exit();
+
data->mode = mode;
if (!data->log)
- data->log = stderr;
+ data->log = stdout;
return argv[optind];
}
-reiserfs_filsys_t fs;
+#define REBUILD_WARNING \
+" **********************************************************\n\
+ ** This is an experimental version of reiserfsck, **\n\
+ ** !! MAKE A BACKUP FIRST !! **\n\
+ ** Don't run this program unless something is broken. **\n\
+ ** Some types of random FS damage can be recovered from **\n\
+ ** by this program, which basically throws away **\n\
+ ** the internal nodes of the tree and then reconstructs **\n\
+ ** them. This program is for use only by the desperate, **\n\
+ ** and is of only beta quality. If you are using the **\n\
+ ** latest reiserfsprogs and it fails please email **\n\
+ ** bug reports to reiserfs-list@namesys.com. **\n\
+ **********************************************************\n\
+\nWill rebuild the filesystem (%s) tree\n"
+
+#define AUTO_WARNING \
+" **********************************************************\n\
+ ** WARNING: You seem to be running this automatically. **\n\
+ ** You are almost certainly doing it by mistake as **\n\
+ ** a result of some script that doesn't know what it **\n\
+ ** does. Doing nothing, rerun without -a and -p if you **\n\
+ ** really intend to do this. **\n\
+ **********************************************************\n\n"
+
+void warn_what_will_be_done (char * file_name, struct fsck_data * data)
+{
+ FILE * warn_to;
+ warn_to = (data->progress ?: stderr);
+// reiserfs_warning (warn_to, START_WARNING);
-static void reset_super_block (reiserfs_filsys_t fs)
-{
- set_free_blocks (fs->s_rs, SB_BLOCK_COUNT (fs));
- set_root_block (fs->s_rs, ~0);
- set_tree_height (fs->s_rs, ~0);
+ /* warn about fsck mode */
+ switch (data->mode) {
+ case FSCK_CHECK:
+ reiserfs_warning (warn_to,
+ "Will read-only check consistency of the filesystem on %s\n",
+ file_name);
+ break;
- /* make file system invalid unless fsck done () */
- set_state (fs->s_rs, REISERFS_ERROR_FS);
+ case FSCK_FIX_FIXABLE:
+
+ reiserfs_warning (warn_to,
+ "Will check consistency of the filesystem on %s\n", file_name);
+ reiserfs_warning (fsck_progress_file(fs),
+ "Will fix what can be fixed w/o --rebuild-tree\n");
+ break;
+ case FSCK_SB:
+ reiserfs_warning (warn_to,
+ "Will check superblock and rebuild it if needed\n");
+ break;
- if (is_reiser2fs_magic_string (fs->s_rs)) {
- set_version (fs->s_rs, REISERFS_VERSION_2);
- }
- if (is_reiserfs_magic_string (fs->s_rs)) {
- set_version (fs->s_rs, REISERFS_VERSION_1);
+ case FSCK_REBUILD:
+ reiserfs_warning (warn_to, REBUILD_WARNING, file_name);
+ if (data->options & OPT_SAVE_PASSES_DUMP) {
+ reiserfs_warning (warn_to,
+ "Will run only 1 step of rebuilding, write state file '%s' and exit\n",
+ data->rebuild.passes_dump_file_name);
+ } else if (data->options & OPT_INTERACTIVE)
+ reiserfs_warning (warn_to,
+ "Will stop after every stage and ask for "
+ "confirmation before continuing\n");
+
+ if (data->rebuild.bitmap_file_name)
+ reiserfs_warning (warn_to,
+ "Will try to load bitmap of leaves from file '%s'\n",
+ data->rebuild.bitmap_file_name);
+
+ if (data->options & OPT_ADJUST_FILE_SIZE)
+ reiserfs_warning (warn_to,
+ "\tWill fix following non-critical things:\n"
+ "\t\tunknown file modes will be set to regular files\n"
+ "\t\tfile sizes will be set to real file size\n"
+ "\t\tfiles sharing busy inode number will be relocated\n");
+
+ if (data->options & OPT_HASH_DEFINED)
+ reiserfs_warning (warn_to,
+ "\tSuppose \"%s\" hash is in use\n",
+ data->rebuild.defined_hash);
+ break;
+
+ case FSCK_ROLLBACK_CHANGES:
+ reiserfs_warning (warn_to,
+ "Will rollback all data saved in %s into %s\n",
+ data->rebuild.rollback_file, file_name);
+ break;
+ case FSCK_CLEAN_ATTRIBUTES:
+ reiserfs_warning (warn_to,
+ "Will clean file attributes on %s\n", file_name);
+ break;
+ case AUTO:
+ reiserfs_warning (warn_to, AUTO_WARNING);
+ exit(0);
}
- /* can be not set yet. If so, hash function will be set when first dir
- entry will be found */
- fs->s_hash_function = code2func (rs_hash (fs->s_rs));
+ if (data->options & OPT_SAVE_ROLLBACK && data->mode != FSCK_ROLLBACK_CHANGES)
+ reiserfs_warning (warn_to,
+ "Will save all blocks to be changed into file '%s'\n",
+ data->rebuild.rollback_file);
- /* objectid map is not touched */
+ if (data->options & BADBLOCKS_FILE)
+ reiserfs_warning (warn_to,
+ "Bad block list will contain only blocks specified in '%s' file\n",
+ badblocks_file);
- mark_buffer_dirty (fs->s_sbh);
- bwrite (fs->s_sbh);
+ reiserfs_warning (warn_to,
+ "Will put log info to '%s'\n",
+ (data->log == stdout) ? "stdout" : (data->log_file_name ?: "fsck.run"));
+ if (!user_confirmed (warn_to,
+ "\nDo you want to run this program?[N/Yes] (note need to type Yes):", "Yes\n"))
+ exit (0);
}
-reiserfs_bitmap_t uninsertable_leaf_bitmap;
-
-int g_blocks_to_read;
-
-
-/* on-disk bitmap is read, fetch it. create new bitmap, mark used blocks which
- are always used (skipped, super block, journal area, bitmaps), create other
- auxiliary bitmaps */
-static void init_bitmaps (reiserfs_filsys_t fs)
+static void reset_super_block (reiserfs_filsys_t * fs)
{
- unsigned long i;
- unsigned long block_count;
- unsigned long tmp;
-
- block_count = SB_BLOCK_COUNT (fs);
-
- switch (stats (fs)->scan_area) {
- case ALL_BLOCKS:
- fsck_disk_bitmap (fs) = reiserfs_create_bitmap (block_count);
- reiserfs_bitmap_fill (fsck_disk_bitmap (fs));
- fsck_progress ("Whole device (%d blocks) is to be scanned\n",
- reiserfs_bitmap_ones (fsck_disk_bitmap (fs)));
- break;
+ struct reiserfs_super_block * sb;
- case USED_BLOCKS:
- fsck_progress ("Loading on-disk bitmap .. ");
- fsck_disk_bitmap (fs) = reiserfs_create_bitmap (block_count);
- reiserfs_fetch_disk_bitmap (fsck_disk_bitmap (fs), fs);
- fsck_progress ("%d bits set - done\n",
- reiserfs_bitmap_ones (fsck_disk_bitmap (fs)));
- break;
+ sb = fs->fs_ondisk_sb;
- case EXTERN_BITMAP:
- fsck_disk_bitmap (fs) = reiserfs_bitmap_load (stats (fs)->bitmap_file_name);
- if (!fsck_disk_bitmap (fs))
- reiserfs_panic ("could not load fitmap from \"%s\"",
- stats (fs)->bitmap_file_name);
- break;
-
- default:
- reiserfs_panic ("No area to scan specified");
- }
+ set_sb_free_blocks (sb, get_sb_block_count (sb));
+ set_sb_root_block (sb, ~0);
+ set_sb_tree_height (sb, ~0);
+ /* make file system invalid unless fsck done () */
+ set_sb_fs_state (sb, get_sb_fs_state (sb) || REISERFS_CORRUPTED);
- /* pass 0 will skip super block and journal areas and bitmap blocks, find
- how many blocks have to be read */
- tmp = 0;
- for (i = 0; i <= fs->s_sbh->b_blocknr; i ++) {
- if (!reiserfs_bitmap_test_bit (fsck_disk_bitmap (fs), i))
- continue;
- reiserfs_bitmap_clear_bit (fsck_disk_bitmap (fs), i);
- tmp ++;
+/*
+ if ( is_reiser2fs_jr_magic_string (sb) ) {???
+ set_sb_version (sb, REISERFS_VERSION_3);
}
-
- /* unmark bitmaps */
- for (i = 0; i < rs_bmap_nr (fs->s_rs); i ++) {
- unsigned long block;
-
- block = SB_AP_BITMAP (fs)[i]->b_blocknr;
- if (!reiserfs_bitmap_test_bit (fsck_disk_bitmap (fs), block))
- continue;
- reiserfs_bitmap_clear_bit (fsck_disk_bitmap (fs), block);
- tmp ++;
+ if (is_reiser2fs_magic_string (sb)) {
+ set_sb_version (sb, REISERFS_FORMAT_3_6);
}
-
- /* unmark journal area */
- for (i = rs_journal_start (fs->s_rs);
- i <= rs_journal_start (fs->s_rs) + rs_journal_size (fs->s_rs); i ++) {
- if (!reiserfs_bitmap_test_bit (fsck_disk_bitmap (fs), i))
- continue;
- reiserfs_bitmap_clear_bit (fsck_disk_bitmap (fs), i);
- tmp ++;
+ if (is_reiserfs_magic_string (sb)) {
+ set_sb_version (sb, REISERFS_FORMAT_3_5);
}
- reiserfs_warning (stderr, "Skipping %d blocks (super block, journal, "
- "bitmaps) %d blocks will be read\n",
- tmp, reiserfs_bitmap_ones (fsck_disk_bitmap (fs)));
-
-#if 0
- {
- int tmp = 0;
- int tmp2 = 0;
- int tmp3 = 0;
- int j;
-
- for (i = 0; i < block_count; i += 32) {
- if (i + 32 < block_count && !*(int *)&(fsck_disk_bitmap (fs)->bm_map[i/8])) {
- tmp2 ++;
- continue;
- }
- tmp3 ++;
- for (j = 0; j < 32 && ((i + j) < block_count); j ++) {
- if (!reiserfs_bitmap_test_bit (fsck_disk_bitmap (fs), i + j))
- continue;
- if (not_data_block (fs, i + j)) {
- reiserfs_bitmap_clear_bit (fsck_disk_bitmap (fs), i + j);
- tmp ++;
- continue;
- }
- }
- }
- /*
- for (i = 0; i < block_count; i ++) {
- if (!fsck_disk_bitmap (fs)->bm_map[i / 8])
- continue;
- if (!reiserfs_bitmap_test_bit (fsck_disk_bitmap (fs), i))
- continue;
- if (not_data_block (fs, i)) {
-
- if (reiserfs_bitmap_test_bit (fsck_disk_bitmap (fs), i))
- tmp ++;
- reiserfs_bitmap_clear_bit (fsck_disk_bitmap (fs), i);
- continue;
- }
- }
*/
- reiserfs_warning (stderr, "%d not data blocks cleared (skipped %d checked %d)\n", tmp, tmp2, tmp3);
- }
-#endif
-
-
- fsck_new_bitmap (fs) = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
-
- /* mark_block_used skips 0, ste the bit explicitly */
- reiserfs_bitmap_set_bit (fsck_new_bitmap (fs), 0);
-
- /* mark other skipped blocks and super block used */
- for (i = 1; i <= SB_BUFFER_WITH_SB (fs)->b_blocknr; i ++)
- mark_block_used (i);
-
- /* mark bitmap blocks as used */
- for (i = 0; i < SB_BMAP_NR (fs); i ++)
- mark_block_used (SB_AP_BITMAP (fs)[i]->b_blocknr);
-
- /* mark journal area as used */
- for (i = 0; i < JOURNAL_BLOCK_COUNT + 1; i ++)
- mark_block_used (i + SB_JOURNAL_BLOCK (fs));
-
-
- uninsertable_leaf_bitmap = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
- reiserfs_bitmap_fill (uninsertable_leaf_bitmap);
+ /* make sure that hash code in super block match to set hash function */
+ set_sb_hash_code (sb, func2code (fs->fs_hash_function));
- fsck_allocable_bitmap (fs) = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
- reiserfs_bitmap_fill (fsck_allocable_bitmap (fs));
+ if (fsck_hash_defined (fs)) {
+ /* --hash was specifed */
+ fs->fs_hash_function = name2func (fsck_data (fs)->rebuild.defined_hash);
+ set_sb_hash_code (sb, func2code (fs->fs_hash_function));
+ }
+
+ /* reset journal params */
+ if (!fsck_skip_journal(fs)) {
+ if (is_reiserfs_jr_magic_string (sb)) {
+ struct reiserfs_journal_header * jh;
+
+ jh = (struct reiserfs_journal_header *)fs->fs_jh_bh->b_data;
+ memcpy (sb_jp(sb), &jh->jh_journal, sizeof (struct journal_params));
+ /* FIXME: copy reserved from jheader to SB */
+ } else {
+ /* standard journal */
+ set_jp_journal_dev (sb_jp(sb), 0);
+ set_jp_journal_magic (sb_jp(sb) ,0);
+ set_sb_reserved_for_journal (sb, 0);
+ set_jp_journal_max_trans_len (sb_jp(sb),
+ advise_journal_max_trans_len( get_jp_journal_max_trans_len (sb_jp(sb)),
+ get_jp_journal_size (sb_jp(sb)),
+ fs->fs_blocksize));
+ set_jp_journal_max_batch (sb_jp(sb), advise_journal_max_batch(get_jp_journal_max_trans_len (sb_jp(sb))));
+ set_jp_journal_max_commit_age (sb_jp(sb), advise_journal_max_commit_age());
+ set_jp_journal_max_trans_age (sb_jp(sb), advise_journal_max_trans_age());
+ }
+ }
+ /* objectid map is not touched */
+ mark_buffer_dirty (fs->fs_super_bh);
+ bwrite (fs->fs_super_bh);
+ if (!(fsck_data(fs)->options & OPT_SAVE_PASSES_DUMP))
+ mark_buffer_do_not_flush (fs->fs_super_bh);
}
+#define START_FROM_THE_BEGINNING 1
+#define START_FROM_PASS_1 2
+#define START_FROM_PASS_2 3
+#define START_FROM_SEMANTIC 4
+#define START_FROM_LOST_FOUND 5
+#define START_FROM_PASS_4 6
-#define REBUILD_WARNING \
-"\nThis is an experimental version of reiserfsck, MAKE A BACKUP FIRST!\n\
-Don't run this program unless something is broken. \n\
-Some types of random FS damage can be recovered\n\
-from by this program, which basically throws away the internal nodes\n\
-of the tree and then reconstructs them. This program is for use only\n\
-by the desperate, and is of only beta quality. Email\n\
-reiserfs@devlinux.com with bug reports. \nWill rebuild the filesystem tree\n"
-
-/*
- warning #2
- you seem to be running this automatically. you are almost
- certainly doing it by mistake as a result of some script that
- doesn't know what it does. doing nothing, rerun without -p if you
- really intend to do this. */
-
-void warn_what_will_be_done (struct fsck_data * data)
+/* this decides where to start from */
+static int where_to_start_from (reiserfs_filsys_t * fs)
{
- fsck_progress ("\n");
-
- /* warn about fsck mode */
- switch (data->mode) {
- case FSCK_CHECK:
- fsck_progress ("Will read-only check consistency of the partition\n");
- if (data->options & OPT_FIX_FIXABLE)
- fsck_progress ("\tWill fix what can be fixed w/o --rebuild-tree\n");
- break;
-
- case FSCK_SB:
- fsck_progress ("Will check SB and rebuild if it is needed\n");
- break;
-
- case FSCK_REBUILD:
- {
- fsck_progress (REBUILD_WARNING);
- if (data->options & OPT_INTERACTIVE)
- fsck_progress ("\tWill stop after every stage and ask for "
- "confirmation before continuing\n");
- if (data->options & OPT_SAVE_EXTERN_BITMAP)
- fsck_progress ("Will save list of found leaves in '%s'\n",
- data->new_bitmap_file_name);
- if (data->bitmap_file_name)
- fsck_progress ("\tWill try to load bitmap of leaves from file '%s'\n",
- data->bitmap_file_name);
- if (data->options & OPT_FIX_NON_CRITICAL)
- fsck_progress ("\tWill fix following non-critical things:\n"
- "\t\tunknown file modes will be set to regular files\n"
- "\t\tfile sizes will be set to real file size\n"
- "\t\tfiles sharing busy inode number will be relocated\n");
- break;
- }
-
- case FSCK_ZERO_FILES:
- fsck_progress ("Will zero existing files and mark free blocks as used\n");
+ int ret;
+ FILE * fp = 0;
+ int last_run_state;
+
+ last_run_state = get_sb_fs_state (fs->fs_ondisk_sb);
+ if (last_run_state == 0 || !fsck_run_one_step (fs))
+ /**/
+ return START_FROM_THE_BEGINNING;
+
+ /* ok, we asked to restart - we can only do that if there is file saved
+ during previous runs */
+ fp = open_file (state_dump_file (fs), "r");
+ if (fp == 0) {
+ set_sb_fs_state (fs->fs_ondisk_sb, 0);
+ return START_FROM_THE_BEGINNING;
}
- fsck_progress ("Will put log info to '%s'\n", (data->log != stderr) ?
- data->log_file_name : "stderr");
-
- if (!user_confirmed ("Do you want to run this program?[N/Yes] (note need to type Yes):", "Yes\n"))
- exit (0);
-}
-
+ /* check start and end magics of dump file */
+ ret = is_stage_magic_correct (fp);
+
+ if (ret <= 0 || ret != last_run_state)
+ return START_FROM_THE_BEGINNING;
-static void start_rebuild (reiserfs_filsys_t fs)
-{
- reset_super_block (fs);
- init_bitmaps (fs);
- proper_id_map (fs) = init_id_map ();
- semantic_id_map (fs) = init_id_map ();
+ switch (last_run_state) {
+ case PASS_0_DONE:
+ /* skip pass 0 */
+ if (!fsck_user_confirmed (fs, "Pass 0 seems done. Start from pass 1?(Yes)",
+ "Yes\n", 1))
+ fsck_exit ("Run without -d then\n");
+
+ load_pass_0_result (fp, fs);
+ fclose (fp);
+ return START_FROM_PASS_1;
+
+ case PASS_1_DONE:
+ /* skip pass 1 */
+ if (!fsck_user_confirmed (fs, "Passes 0 and 1 seems done. Start from pass 2?(Yes)",
+ "Yes\n", 1))
+ fsck_exit ("Run without -d then\n");
+
+ load_pass_1_result (fp, fs);
+ fclose (fp);
+ return START_FROM_PASS_2;
+
+ case TREE_IS_BUILT:
+ if (!fsck_user_confirmed (fs, "S+ tree of filesystem looks built. Skip rebuilding?(Yes)",
+ "Yes\n", 1))
+ fsck_exit ("Run without -d then\n");
+
+ load_pass_2_result (fs);
+ fclose (fp);
+ return START_FROM_SEMANTIC;
+ case SEMANTIC_DONE:
+ if (!fsck_user_confirmed (fs, "Passes 0 and 1 seems done. Start from pass 2?(Yes)",
+ "Yes\n", 1))
+ fsck_exit ("Run without -d then\n");
+ load_semantic_result (fp, fs);
+ fclose (fp);
+ return START_FROM_LOST_FOUND;
+ case LOST_FOUND_DONE:
+ if (!fsck_user_confirmed (fs, "Passes 0 and 1 seems done. Start from pass 2?(Yes)",
+ "Yes\n", 1))
+ fsck_exit ("Run without -d then\n");
+ load_lost_found_result (fs);
+ fclose (fp);
+ return START_FROM_PASS_4;
+ }
+
+ return START_FROM_THE_BEGINNING;
}
-/* called before semantic pass starts */
-static void end_rebuilding (reiserfs_filsys_t fs)
+static void mark_filesystem_consistent (reiserfs_filsys_t * fs)
{
- reiserfs_flush_bitmap (fsck_new_bitmap (fs), fs);
- flush_objectid_map (proper_id_map (fs), fs);
- set_fsck_state (fs->s_rs, TREE_IS_BUILT);
- set_free_blocks (fs->s_rs, reiserfs_bitmap_zeros (fsck_new_bitmap (fs)));
+ if (!is_opened_rw (fs))
+ return;
+
+ if (!reiserfs_journal_opened (fs)) {
+ /* make sure journal is not standard */
+ if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb))
+ die ("File system with standard journal that has to be open");
+ /* mark filesystem such that it is not mountable until new journal
+ device is defined */
+ fsck_progress ("WARNING: You must use reiserfstune to specify new journal\n");
+ set_jp_journal_magic (sb_jp (fs->fs_ondisk_sb), NEED_TUNE);
+ }
- mark_buffer_dirty (SB_BUFFER_WITH_SB (fs));
+ set_sb_umount_state (fs->fs_ondisk_sb, REISERFS_CLEANLY_UMOUNTED);
+ set_sb_fs_state (fs->fs_ondisk_sb, REISERFS_CONSISTENT);
- /* write all dirty blocks */
- fsck_progress ("Syncing.."); fflush (stdout);
- reiserfs_flush (fs);
- fsck_progress ("done\n"); fflush (stdout);
-
- /* release what will not be needed */
- reiserfs_delete_bitmap (fsck_disk_bitmap (fs));
- reiserfs_delete_bitmap (fsck_allocable_bitmap (fs));
-
- /* FIXME: could be not a bitmap */
- reiserfs_delete_bitmap (uninsertable_leaf_bitmap);
-
- if (fsck_user_confirmed (fs, "Tree building completed. "
- "You can stop now and restart from this point later "
- "(this is probably not what you need). Do you want to stop? ",
- "Yes\n", 0/*default*/)) {
- reiserfs_close (fs);
- exit (4);
- }
+ mark_buffer_dirty (fs->fs_super_bh);
}
+static void reiserfsck_replay_journal () {
+ /* keep the super_block in the separate memory to avoid problems with replayed broken parameters */
+ fs->fs_ondisk_sb = getmem (fs->fs_blocksize);
+ memcpy (fs->fs_ondisk_sb, fs->fs_super_bh->b_data, sizeof (fs->fs_blocksize));
-static int skip_rebuilding (reiserfs_filsys_t fs)
-{
- if (fsck_state (fs->s_rs) == TREE_IS_BUILT) {
- if (fsck_user_confirmed (fs, "S+ tree of filesystem looks built. Skip rebuilding? ", "Yes\n", 0/*default*/)) {
-
- fsck_new_bitmap (fs) = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
- reiserfs_fetch_disk_bitmap (fsck_new_bitmap (fs), fs);
+ replay_journal (fs);
- proper_id_map (fs) = init_id_map ();
- fetch_objectid_map (proper_id_map (fs), fs);
+ /* get rid of SB copy */
+ freemem (fs->fs_ondisk_sb);
+ fs->fs_ondisk_sb = (struct reiserfs_super_block *)fs->fs_super_bh->b_data;
- semantic_id_map (fs) = init_id_map ();
-
- return 1;
- }
- }
- return 0;
}
-
-static void start_continuing (reiserfs_filsys_t fs)
+static void the_end (reiserfs_filsys_t * fs)
{
- fsck_allocable_bitmap (fs) = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
- reiserfs_bitmap_copy (fsck_allocable_bitmap (fs), fsck_new_bitmap (fs));
-}
+ struct reiserfs_super_block * sb;
+ sb = fs->fs_ondisk_sb;
+
+ /* put bitmap and objectid map on place */
+ reiserfs_delete_bitmap (fs->fs_bitmap2);
+ fs->fs_bitmap2 = fsck_new_bitmap (fs);
+ if (!fs->fs_bitmap2->bm_dirty)
+ die ("Bitmap not dirty");
-static void the_end (reiserfs_filsys_t fs)
-{
- reiserfs_flush_bitmap (fsck_new_bitmap (fs), fs);
flush_objectid_map (proper_id_map (fs), fs);
- set_fsck_state (fs->s_rs, 0);
- set_free_blocks (fs->s_rs, reiserfs_bitmap_zeros (fsck_new_bitmap (fs)));
- set_state (fs->s_rs, REISERFS_VALID_FS);
- mark_buffer_dirty (SB_BUFFER_WITH_SB (fs));
+ free_id_map(proper_id_map (fs));
+ free_id_map(semantic_id_map (fs));
- /* write all dirty blocks */
- fsck_progress ("Syncing.."); fflush (stderr);
- reiserfs_flush (fs);
- sync ();
- fsck_progress ("done\n"); fflush (stderr);
+/* set_sb_free_blocks (sb, reiserfs_bitmap_zeros (fsck_new_bitmap (fs)));*/
- reiserfs_delete_bitmap (fsck_new_bitmap (fs));
+ mark_filesystem_consistent (fs);
+ clear_buffer_do_not_flush (fs->fs_super_bh);
- free_id_map (&proper_id_map(fs));
- if (semantic_id_map(fs))
- free_id_map (&semantic_id_map(fs));
-
+ /* write all dirty blocks */
+ fsck_progress ("Syncing..");
+ fs->fs_dirt = 1;
reiserfs_close (fs);
- fsck_progress ("Done\n"); fflush (stderr);
+// sync ();
+ fsck_progress ("done\n");
}
-static void rebuild_tree (reiserfs_filsys_t fs)
+static void rebuild_tree (reiserfs_filsys_t * fs)
{
- if (is_mounted (fs->file_name)) {
+ time_t t;
+
+
+ if (is_mounted (fs->fs_file_name)) {
fsck_progress ("rebuild_tree: can not rebuild tree of mounted filesystem\n");
return;
}
+ init_rollback_file (state_rollback_file(fs), &fs->fs_blocksize, fsck_data(fs)->log);
reiserfs_reopen (fs, O_RDWR);
/* FIXME: for regular file take care of of file size */
- /* rebuild starts with journal replaying */
- reiserfs_replay_journal (fs);
+ if (!reiserfs_open_ondisk_bitmap (fs)) {
+ fsck_progress ("reiserfsck: could not open bitmap\n");
+ reiserfs_close (fs);
+ exit(0);
+ }
+ /* rebuild starts with journal replaying */
+ if (!fsck_skip_journal (fs))
+ reiserfsck_replay_journal ();
- if (!skip_rebuilding (fs)) {
- fsck_progress ("Rebuilding..\n");
- start_rebuild (fs);
+ time (&t);
+ fsck_progress ("###########\n"
+ "reiserfsck --rebuild-tree started at %s"
+ "###########\n", ctime (&t));
+ switch (where_to_start_from (fs)) {
+ case START_FROM_THE_BEGINNING:
+ reset_super_block (fs);
pass_0 (fs);
-
- /* passes 1 and 2. building of the tree */
- pass_1_pass_2_build_the_tree ();
-
- end_rebuilding (fs);
- }
-
- /* re-building of filesystem tree is now separated of sematic pass of the
- fsck */
- start_continuing (fs);
- /* 3. semantic pass */
- pass_3_semantic ();
-
- /* if --lost+found is set - link unaccessed directories to lost+found
- directory */
- pass_3a_look_for_lost (fs);
-
- /* 4. look for unaccessed items in the leaves */
- pass_4_check_unaccessed_items ();
-
- the_end (fs);
+ case START_FROM_PASS_1:
+ reset_super_block (fs);
+ pass_1 (fs);
+
+ case START_FROM_PASS_2:
+ pass_2 (fs);
-}
+ case START_FROM_SEMANTIC:
+ pass_3_semantic (fs);
+ /* if --lost+found is set - link unaccessed directories to lost+found
+ directory */
+ case START_FROM_LOST_FOUND:
+ pass_3a_look_for_lost (fs);
+
+ case START_FROM_PASS_4:
+ /* 4. look for unaccessed items in the leaves */
+ pass_4_check_unaccessed_items ();
+
+ the_end (fs);
+ }
-static void zero_files (reiserfs_filsys_t fs)
-{
- init_bitmaps (fs);
- reiserfs_reopen (fs, O_RDWR);
- pass_0 (fs);
+ close_rollback_file ();
+
+ time (&t);
+ fsck_progress ("###########\n"
+ "reiserfsck finished at %s"
+ "###########\n", ctime (&t));
+ exit (0);
}
/* check umounted or read-only mounted filesystems only */
-static void check_fs (reiserfs_filsys_t fs)
+static void prepare_fs_for_pass_through_tree (reiserfs_filsys_t * fs)
{
- if (!is_mounted (fs->file_name)) {
- /* filesystem is not mounted, replay journal before checking */
- reiserfs_reopen (fs, O_RDWR);
-
- reiserfs_replay_journal (fs);
+ if (is_mounted (fs->fs_file_name)) {
+ /* filesystem seems mounted. */
+ if (fsck_mode (fs) == FSCK_CLEAN_ATTRIBUTES) {
+ fsck_progress ("Device %s is mounted, cannot clean attributes on mounted device\n",
+ fs->fs_file_name);
+ reiserfs_close (fs);
+ exit (0);
+ }
- reiserfs_reopen (fs, O_RDONLY);
- } else {
- /* filesystem seems mounted. we do not check filesystems mounted with
- r/w permissions */
- if (!is_mounted_read_only (fs->file_name)) {
+ if (!is_mounted_read_only (fs->fs_file_name)) {
fsck_progress ("Device %s is mounted w/ write permissions, can not check it\n",
- fs->file_name);
+ fs->fs_file_name);
reiserfs_close (fs);
exit (0);
}
+ if (!reiserfs_journal_opened (fs))
+ /* just to make sure */
+ reiserfs_panic ("Journal is not opened");
+
fsck_progress ("Filesystem seems mounted read-only. Skipping journal replay..\n");
- if (fsck_fix_fixable (fs)) {
+ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) {
fsck_progress ("--fix-fixable ignored\n");
- stats(fs)->options &= ~OPT_FIX_FIXABLE;
+ fsck_mode (fs) = FSCK_CHECK;
}
+ } else {
+ reiserfs_reopen (fs, O_RDWR);
+ if (!fsck_skip_journal (fs))
+ /* filesystem is not mounted, replay journal before checking */
+ reiserfsck_replay_journal ();
}
+}
- fsck_disk_bitmap (fs) = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
- reiserfs_fetch_disk_bitmap (fsck_disk_bitmap (fs), fs);
+static void clean_attributes (reiserfs_filsys_t * fs) {
+ time_t t;
- if (fsck_fix_fixable (fs))
- reiserfs_reopen (fs, O_RDWR);
+ time (&t);
- /*proper_id_map (fs) = init_id_map ();*/
- semantic_id_map (fs) = init_id_map ();
+ if (get_sb_umount_state (fs->fs_ondisk_sb) != REISERFS_CLEANLY_UMOUNTED) {
+ fsck_progress ("Filesystem does not look like cleanly umounted\n"
+ "Check consistency of the partition first.\n");
+ exit(0);
+ }
+ if (get_sb_fs_state (fs->fs_ondisk_sb) != REISERFS_CONSISTENT) {
+ fsck_progress ("Filesystem seems to be in unconsistent state.\n"
+ "Check consistency of the partition first.\n");
+ exit(0);
+ }
- check_fs_tree (fs);
+ if (get_reiserfs_format (fs->fs_ondisk_sb) != REISERFS_FORMAT_3_6) {
+ fsck_progress ("Filesystems of 3_5 format do not support extended attributes.\n");
+ exit(0);
+ }
+ fsck_progress ("###########\n"
+ "reiserfsck --clean-attributes started at %s"
+ "###########\n", ctime (&t));
- semantic_check ();
+ init_rollback_file (state_rollback_file(fs), &fs->fs_blocksize, fsck_data(fs)->log);
+
+ prepare_fs_for_pass_through_tree (fs);
+
+ do_clean_attributes (fs);
- reiserfs_delete_bitmap (fsck_disk_bitmap (fs));
- /*free_id_map (proper_id_map (fs));*/
- free_id_map (&semantic_id_map (fs));
reiserfs_close (fs);
-}
+ close_rollback_file ();
+ fsck_progress ("###########\n"
+ "reiserfsck finished at %s"
+ "###########\n", ctime (&t));
-#include <sys/resource.h>
+ exit (0);
-int main (int argc, char * argv [])
+}
+
+/* check umounted or read-only mounted filesystems only */
+static void check_fs (reiserfs_filsys_t * fs)
{
- char * file_name;
- struct fsck_data * data;
- struct rlimit rlim = {0xffffffff, 0xffffffff};
+ int retval;
+ time_t t;
- print_banner ("reiserfsck");
+ time (&t);
- /* this is only needed (and works) when running under 2.4 on regural files */
- if (setrlimit (RLIMIT_FSIZE, &rlim) == -1) {
- reiserfs_warning (stderr, "could not setrlimit: %m");
+ if (fsck_mode (fs) != FSCK_FIX_FIXABLE) {
+ fsck_progress ("###########\n"
+ "reiserfsck --check started at %s"
+ "###########\n", ctime (&t));
+ } else {
+ fsck_progress ("###########\n"
+ "reiserfsck --fix-fixable started at %s"
+ "###########\n", ctime (&t));
}
- data = getmem (sizeof (struct fsck_data));
+ init_rollback_file (state_rollback_file(fs), &fs->fs_blocksize, fsck_data(fs)->log);
+
+ if (!reiserfs_open_ondisk_bitmap (fs)) {
+ fsck_progress ("reiserfsck: could not open bitmap\n");
+ reiserfs_close (fs);
+ exit(0);
+ }
- file_name = parse_options (data, argc, argv);
+ prepare_fs_for_pass_through_tree (fs);
- if (data->mode == DO_NOTHING) {
- freemem (data);
- return 0;
- }
+ check_fs_tree (fs);
- warn_what_will_be_done (data); /* and ask confirmation Yes */
- fs = reiserfs_open (file_name, O_RDONLY, 0, data);
- if (!fs)
- die ("reiserfsck: could not open filesystem on \"%s\"", file_name);
+ semantic_check ();
+ if (fsck_data (fs)->check.fatal_corruptions) {
+ fsck_progress ("There were found %d corruptions which can be fixed only during --rebuild-tree\n",
+ fsck_data (fs)->check.fatal_corruptions);
+ set_sb_fs_state (fs->fs_ondisk_sb, REISERFS_CORRUPTED);
+ mark_buffer_dirty (fs->fs_super_bh);
+ retval = 2;
+ } else if (fsck_data (fs)->check.fixable_corruptions) {
+ /* fixable corruptions found */
+ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) {
+ /* fixable corruptions found and fix-fixable has not fixed them, do rebuild-tree */
+ fsck_log ("Fatal error occured: %d fixable corruptions found after fix-fixable.\n",
+ fsck_data (fs)->check.fixable_corruptions);
+ retval = 2;
+ } else {
+ fsck_progress ("There were found %d corruptions which can be fixed with --fix-fixable\n",
+ fsck_data (fs)->check.fixable_corruptions);
+ retval = 1;
+ }
+ set_sb_fs_state (fs->fs_ondisk_sb, REISERFS_CORRUPTED);
+ mark_buffer_dirty (fs->fs_super_bh);
+ } else {
+ fsck_progress ("No corruptions found\n");
+ stage_report (5, fs);
+ retval = 0;
- if (fsck_mode (fs) == FSCK_SB) {
- reiserfs_reopen (fs, O_RDWR);
- rebuild_sb (fs);
- reiserfs_close (fs);
- return 0;
+ mark_filesystem_consistent (fs);
}
- if (no_reiserfs_found (fs)) {
- fsck_progress ("reiserfsck: --rebuild-sb may restore reiserfs super block\n");
- reiserfs_close (fs);
- return 0;
+ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) {
+ flush_objectid_map (proper_id_map (fs), fs);
+
+ fs->fs_dirt = 1;
}
+
+ free_id_map (proper_id_map (fs));
+ reiserfs_close (fs);
+ close_rollback_file ();
+// sync();
+
+ time (&t);
+ fsck_progress ("###########\n"
+ "reiserfsck finished at %s"
+ "###########\n", ctime (&t));
+ exit (retval);
+}
- fs->block_allocator = reiserfsck_reiserfs_new_blocknrs;
- fs->block_deallocator = reiserfsck_reiserfs_free_block;
+static int open_devices_for_rollback (char * file_name, struct fsck_data * data) {
+ int fd;
+ fd = open (file_name, O_RDWR | O_LARGEFILE);
+ if (fd == -1) {
+ reiserfs_warning (stderr, "reiserfsck: could not open device %s\"", file_name);
+ return -1;
+ }
- if (fsck_mode (fs) == FSCK_CHECK) {
- check_fs (fs);
- return 0;
+ fs = getmem (sizeof (*fs));
+ fs->fs_dev = fd;
+ fs->fs_vp = data;
+ asprintf (&fs->fs_file_name, "%s", file_name);
+
+ if (data->journal_dev_name && strcmp (data->journal_dev_name, file_name)) {
+ fs->fs_journal_dev = open (data->journal_dev_name, O_RDWR | O_LARGEFILE);
+ if (fs->fs_journal_dev == -1) {
+ reiserfs_warning (stderr, "cannot open journal device\n");
+ return -1;
+ }
}
+ if (open_rollback_file (state_rollback_file(fs), fsck_data(fs)->log))
+ return -1;
+
+ return 0;
+}
+
+static void fsck_rollback (reiserfs_filsys_t * fs) {
+ time_t t;
+
+ time (&t);
+ fsck_progress ("###########\n"
+ "reiserfsck --rollback-fsck-changes started at %s"
+ "###########\n", ctime (&t));
+
+ do_fsck_rollback (fs->fs_dev, fs->fs_journal_dev, fsck_progress_file (fs));
+ close_rollback_file ();
+
+ close (fs->fs_journal_dev);
+ free (fs->fs_file_name);
+ fs->fs_file_name = 0;
+ close (fs->fs_dev);
+ freemem (fs);
+
+ time (&t);
+ fsck_progress ("###########\n"
+ "reiserfsck finished at %s"
+ "###########\n", ctime (&t));
+
+ exit (0);
+}
+
+static void fast_rebuild (reiserfs_filsys_t * fs)
+{
#ifdef FAST_REBUILD_READY /* and tested */
if (opt_fsck_mode == FSCK_FAST_REBUILD) {
__u32 root_block = SB_ROOT_BLOCK(fs);
reopen_read_write (file_name);
printf ("Replaying log..");
- reiserfs_replay_journal (fs);
+ if (fsck_skip_journal (fs))
+ reiserfsck_replay_journal ();
printf ("done\n");
if (opt_fsck == 1)
printf ("ReiserFS : checking %s\n",file_name);
@@ -685,7 +922,7 @@ int main (int argc, char * argv [])
/* if --lost+found is set - link unaccessed directories to
lost+found directory */
- look_for_lost (fs);
+ look_for_lost (fs);
/* 4. look for unaccessed items in the leaves */
pass4_check_unaccessed_items ();
@@ -694,16 +931,151 @@ int main (int argc, char * argv [])
}
#endif /* FAST REBUILD READY */
+ reiserfs_panic ("Fast rebuild is not ready");
+
+}
- if (fsck_mode (fs) == FSCK_ZERO_FILES)
- zero_files (fs);
- if (fsck_mode (fs) != FSCK_REBUILD && fsck_mode (fs) != DO_TEST)
+
+int main (int argc, char * argv [])
+{
+ char * file_name;
+ struct fsck_data * data;
+ struct rlimit rlim = {0xffffffff, 0xffffffff};
+ int retval;
+ char *width;
+
+ width = getenv("COLUMNS");
+ if ( width )
+ screen_width = atoi(width);
+
+ if (screen_width == 0)
+ screen_width = 80; // We default to 80 characters wide screen
+ screen_width--;
+ screen_savebuffer_len=screen_width;
+ screen_savebuffer=getmem(screen_width+1);
+ memset(screen_savebuffer,0,screen_savebuffer_len+1);
+
+ /* initially assigned in semantic.c, but non-constant initializers are
+ * illegal - jdm */
+/*
+ root_dir_key.k2_dir_id = cpu_to_le32(root_dir_key.k2_dir_id);
+ root_dir_key.k2_objectid = cpu_to_le32(root_dir_key.k2_objectid);
+ parent_root_dir_key.k2_dir_id = cpu_to_le32(parent_root_dir_key.k2_dir_id);
+ parent_root_dir_key.k2_objectid = cpu_to_le32(parent_root_dir_key.k2_objectid);
+*/
+ lost_found_dir_key.k2_dir_id = cpu_to_le32(lost_found_dir_key.k2_dir_id);
+ lost_found_dir_key.k2_objectid = cpu_to_le32(lost_found_dir_key.k2_objectid);
+ /* this is only needed (and works) when running under 2.4 on regural files */
+ if (setrlimit (RLIMIT_FSIZE, &rlim) == -1) {
+ reiserfs_warning (stderr, "could not setrlimit: %m\n");
+ }
+
+ data = getmem (sizeof (struct fsck_data));
+
+ file_name = parse_options (data, argc, argv);
+
+ if (data->mode != AUTO)
+ print_banner ("reiserfsck");
+
+ if (data->mode == DO_NOTHING) {
+ freemem (data);
return 0;
+ }
+
+ if (data->options & OPT_BACKGROUND) {
+ /* running in background reiserfsck appends progress information into
+ 'fsck.run'. Logs get there if log file was not specified*/
+ data->options |= OPT_QUIET;
+ data->progress = fopen ("fsck.run", "a+");
+ if (!data->progress)
+ reiserfs_panic ("reiserfsck: could not open \"fsck.run\"");
+
+ if (data->log == stdout)
+ /* no log file specifed - redirect log into 'fsck.run' */
+ data->log = data->progress;
+
+ retval = fork ();
+ if (retval == -1)
+ reiserfs_panic ("reiserfsck: fork failed: %m");
+ if (retval != 0) {
+ return 0;
+ }
+ reiserfs_warning (stderr, "\nreiserfsck is running in background as [%d],\n"
+ "make sure that it get enough confirmation from stdin\n\n",
+ getpid ());
+ }
+
+
+ if (data->mode != AUTO)
+ warn_what_will_be_done (file_name, data); /* and ask confirmation Yes */
+
+ if (data->mode == FSCK_ROLLBACK_CHANGES) {
+ if (open_devices_for_rollback (file_name, data) == -1)
+ exit (1);
+ } else {
+ fs = reiserfs_open (file_name, O_RDONLY, 0, data);
+
+ if (data->mode != FSCK_SB) {
+ if (no_reiserfs_found (fs))
+ die ("reiserfsck: could not open filesystem on \"%s\"", file_name);
+
+ if (data->mode == AUTO) {
+ print_super_block (stdout, fs, fs->fs_file_name, fs->fs_super_bh, 1);
+ reiserfs_close(fs);
+
+ exit (0);
+ }
+
+ if (fsck_skip_journal (fs) && !is_reiserfs_jr_magic_string (fs->fs_ondisk_sb)) {
+ reiserfs_warning (stderr, "Filesystem with standard journal found, "
+ "--no-journal-availabel is ignored\n");
+ fsck_data(fs)->options &= ~OPT_SKIP_JOURNAL;
+ }
+
+ if (!fsck_skip_journal (fs)) {
+ if (!reiserfs_open_journal (fs, data->journal_dev_name, O_RDONLY)) {
+ fsck_progress ("reiserfsck: either make journal device available or use --no-journal-available\n");
+ fsck_progress (" if you have the standard journal or if your device is available\n");
+ fsck_progress (" and you specified it correctly, you have to run rebuild-sb\n");
+ reiserfs_close (fs);
+ return 0;
+ }
+ }
+
+ if (data->options & BADBLOCKS_FILE) {
+ if (create_badblock_bitmap (fs, badblocks_file) != 0) {
+ badblocks_file = NULL;
+ data->options &= ~BADBLOCKS_FILE;
+ }
+ }
+ }
+ }
+ switch (data->mode) {
+ case FSCK_SB:
+ rebuild_sb (fs, file_name, data);
+ break;
+
+ case FSCK_CHECK:
+ case FSCK_FIX_FIXABLE:
+ check_fs (fs);
+ break;
- /* the --rebuild-tree is here */
- rebuild_tree (fs);
- return 0;
+ case FSCK_REBUILD:
+ case DO_TEST:
+ rebuild_tree (fs);
+ break;
+ case FSCK_FAST_REBUILD:
+ fast_rebuild (fs);
+ break;
+ case FSCK_ROLLBACK_CHANGES:
+ fsck_rollback (fs);
+ break;
+ case FSCK_CLEAN_ATTRIBUTES:
+ clean_attributes (fs);
+ }
+ return 16;
}
+
diff --git a/fsck/pass0.c b/fsck/pass0.c
index 8b7b065..fcf27c2 100644
--- a/fsck/pass0.c
+++ b/fsck/pass0.c
@@ -1,49 +1,57 @@
/*
- * Copyright 1996-2001 Hans Reiser
+ * Copyright 1996-2002 Hans Reiser
*/
#include "fsck.h"
-static unsigned long tmp_zeroed;
-
/* pass 0 scans the partition (used part). It creates two maps which will be
used on the pass 1. These are a map of nodes looking like leaves and a map
- of "bad" unformatted nodes. */
+ of "bad" unformatted nodes. After pass 0 we can detect unformatted node
+ pointers pointing to leaves.*/
/* leaves */
-reiserfs_bitmap_t leaves_bitmap;
+reiserfs_bitmap_t * leaves_bitmap;
#define pass0_is_leaf(block) __is_marked (leaves, block)
#define pass0_mark_leaf(block) __mark (leaves, block)
/* nodes which are referred to from only one indirect item */
-reiserfs_bitmap_t good_unfm_bitmap;
+reiserfs_bitmap_t * good_unfm_bitmap;
#define pass0_is_good_unfm(block) __is_marked (good_unfm, block)
#define pass0_mark_good_unfm(block) __mark (good_unfm, block)
#define pass0_unmark_good_unfm(block) __unmark (good_unfm, block)
/* nodes which are referred to from more than one indirect item */
-reiserfs_bitmap_t bad_unfm_bitmap;
+reiserfs_bitmap_t * bad_unfm_bitmap;
#define pass0_is_bad_unfm(block) __is_marked (bad_unfm, block)
#define pass0_mark_bad_unfm(block) __mark (bad_unfm, block)
#define pass0_unmark_bad_unfm(block) __unmark (bad_unfm, block)
-/* there are three way to say of which blocks the tree should be built off:
- default - */
-static void make_aux_bitmaps (reiserfs_filsys_t fs)
+/* bitmaps which are built on pass 0 and are used on pass 1 */
+static void make_aux_bitmaps (reiserfs_filsys_t * fs)
{
+ struct reiserfs_super_block * sb;
- /* bitmap of leaves found on the device. It will be saved if -c specified */
- leaves_bitmap = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
+ sb = fs->fs_ondisk_sb;
- good_unfm_bitmap = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
+ /* bitmap of leaves found on the device */
+ leaves_bitmap = reiserfs_create_bitmap (get_sb_block_count (sb));
- bad_unfm_bitmap = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
+ good_unfm_bitmap = reiserfs_create_bitmap (get_sb_block_count (sb));
+ bad_unfm_bitmap = reiserfs_create_bitmap (get_sb_block_count (sb));
+}
+
+
+void delete_aux_bitmaps (void)
+{
+ reiserfs_delete_bitmap (leaves_bitmap);
+ reiserfs_delete_bitmap (good_unfm_bitmap);
+ reiserfs_delete_bitmap (bad_unfm_bitmap);
}
@@ -107,20 +115,20 @@ static int correct_key_format (struct item_head * ih)
if (is_stat_data_ih (ih)) {
/* for stat data we have no way to check whether key format in item
head matches to the key format found from the key directly */
- if (ih_item_len (ih) == SD_V1_SIZE) {
- if (ih_key_format (ih) != KEY_FORMAT_1) {
- fsck_log ("correct_key_format: ih_key_format of (%H) is set to format 1\n",
- ih);
- set_key_format (ih, KEY_FORMAT_1);
+ if (get_ih_item_len (ih) == SD_V1_SIZE) {
+ if (get_ih_key_format (ih) != KEY_FORMAT_1) {
+ /*fsck_log ("correct_key_format: ih_key_format of (%H) is set to format 1\n",
+ ih);*/
+ set_ih_key_format (ih, KEY_FORMAT_1);
return 1;
- }
+ }
return 0;
}
- if (ih_item_len (ih) == SD_SIZE) {
- if (ih_key_format (ih) != KEY_FORMAT_2) {
- fsck_log ("correct_key_format: ih_key_format of (%H) is set to format 2\n",
- ih);
- set_key_format (ih, KEY_FORMAT_2);
+ if (get_ih_item_len (ih) == SD_SIZE) {
+ if (get_ih_key_format (ih) != KEY_FORMAT_2) {
+ /*fsck_log ("correct_key_format: ih_key_format of (%H) is set to format 2\n",
+ ih);*/
+ set_ih_key_format (ih, KEY_FORMAT_2);
return 1;
}
return 0;
@@ -129,17 +137,19 @@ static int correct_key_format (struct item_head * ih)
die ("stat data of wrong length");
}
- if (key_format (&ih->ih_key) != ih_key_format (ih)) {
- fsck_log ("correct_key_format: ih_key_format of (%H) is set to format found in the key\n",
- ih);
- set_key_format (ih, key_format (&ih->ih_key));
+ if (key_format (&ih->ih_key) != get_ih_key_format (ih)) {
+ /*fsck_log ("correct_key_format: ih_key_format of (%H) is set to format found in the key\n",
+ ih);*/
+ set_ih_key_format (ih, key_format (&ih->ih_key));
dirty = 1;
}
- if (type_unknown (&ih->ih_key)) {
- /* FIXME: */
- set_type (key_format (&ih->ih_key), &ih->ih_key, TYPE_DIRECT);
- dirty = 1;
+ if (is_direct_ih (ih) && get_offset (&ih->ih_key) > fs->fs_blocksize * 4) {
+ /*fsck_log ("correct_key_format: %H made of indirect type\n", ih);*/
+ set_type (key_format (&ih->ih_key), &ih->ih_key, TYPE_INDIRECT);
+ if (get_offset (&ih->ih_key) % fs->fs_blocksize != 1)
+ fsck_log ("correct_key_format: %H wrong offset of in indirect item\n", ih);
+ dirty = 1;
}
return dirty;
@@ -147,7 +157,7 @@ static int correct_key_format (struct item_head * ih)
#if 0
/* fixme: we might try all available hashes */
-static int prob_name (reiserfs_filsys_t fs,
+static int prob_name (reiserfs_filsys_t * fs,
char ** name, int max_len, __u32 deh_offset)
{
int start; /* */
@@ -166,17 +176,17 @@ static int prob_name (reiserfs_filsys_t fs,
#endif
-static void hash_hits_init (reiserfs_filsys_t fs)
+static void hash_hits_init (reiserfs_filsys_t * fs)
{
- stats (fs)->hash_amount = known_hashes ();
- stats (fs)->hash_hits = getmem (sizeof (unsigned long) * stats (fs)->hash_amount);
+ fsck_data (fs)->rebuild.hash_amount = known_hashes ();
+ fsck_data (fs)->rebuild.hash_hits = getmem (sizeof (unsigned long) * fsck_data (fs)->rebuild.hash_amount);
return;
}
-static void add_hash_hit (reiserfs_filsys_t fs, int hash_code)
+static void add_hash_hit (reiserfs_filsys_t * fs, int hash_code)
{
- stats (fs)->hash_hits [hash_code] ++;
+ fsck_data (fs)->rebuild.hash_hits [hash_code] ++;
}
@@ -187,9 +197,10 @@ static int try_to_get_name_length (struct item_head * ih, struct reiserfs_de_hea
{
int len;
- len = name_length (ih, deh, i);
- if (i == 0 || !de_bad_location (deh - 1))
+ if (i == 0 || !de_bad_location (deh - 1)) {
+ len = name_in_entry_length (ih, deh, i);
return (len > 0) ? len : 0;
+ }
/* previous entry had bad location so we had no way to find
name length */
@@ -205,7 +216,7 @@ static int try_to_get_name_length (struct item_head * ih, struct reiserfs_de_hea
/* check directory item and try to recover something */
-static int verify_directory_item (reiserfs_filsys_t fs, struct buffer_head * bh,
+static int verify_directory_item (reiserfs_filsys_t * fs, struct buffer_head * bh,
int item_num)
{
struct item_head * ih;
@@ -216,15 +227,11 @@ static int verify_directory_item (reiserfs_filsys_t fs, struct buffer_head * bh,
int name_len;
int bad;
int i, j;
-#if 0
- int bad_entries; /* how many bad neighboring entries */
- int total_entry_len;
- char * entries, * end;
-#endif
+ char buf[4096];
int dirty;
- int entry_count;
int hash_code;
int bad_locations;
+ int min_entry_size = 1;
#ifdef DEBUG_VERIFY_DENTRY
char * direntries;
@@ -237,19 +244,27 @@ static int verify_directory_item (reiserfs_filsys_t fs, struct buffer_head * bh,
dirty = 0;
bad_locations = 0;
- entry_count = ih_entry_count (ih);
+
+ if ( (get_ih_entry_count (ih) > (get_ih_item_len(ih) / (DEH_SIZE + min_entry_size))) ||
+ (get_ih_entry_count (ih) == 0))
+ set_ih_entry_count (ih, (int)get_ih_item_len(ih) / (DEH_SIZE + min_entry_size));
+
+ if (get_ih_entry_count (ih) == 0) {
+ delete_item (fs, bh, item_num);
+ return -1;
+ }
/* check deh_location */
- for (i = 0; i < ih_entry_count (ih); i ++) {
+ for (i = 0; i < get_ih_entry_count (ih); i ++) {
/* silently fix deh_state */
- if (deh [i].deh_state != (1 << DEH_Visible)) {
- deh [i].deh_state = cpu_to_le16 (1 << DEH_Visible);
+ if (get_deh_state (deh + i) != (1 << DEH_Visible2)) {
+ set_deh_state (deh + i, (1 << DEH_Visible2));
mark_buffer_dirty (bh);
}
if (dir_entry_bad_location (deh + i, ih, !i))
mark_de_bad_location (deh + i);
- }
+ }
#ifdef DEBUG_VERIFY_DENTRY
direntries = getmem (ih_entry_count (ih) * sizeof (int));
@@ -264,13 +279,13 @@ static int verify_directory_item (reiserfs_filsys_t fs, struct buffer_head * bh,
/* find entries names in which have mismatching deh_offset */
- for (i = ih_entry_count (ih) - 1; i >= 0; i --) {
+ for (i = get_ih_entry_count (ih) - 1; i >= 0; i --) {
if (de_bad (deh + i))
/* bad location */
continue;
if (i) {
- if (deh_location (deh + i - 1) < deh_location (deh + i))
+ if (get_deh_location (deh + i - 1) < get_deh_location (deh + i))
mark_de_bad_location (deh + i - 1);
}
@@ -289,28 +304,32 @@ static int verify_directory_item (reiserfs_filsys_t fs, struct buffer_head * bh,
bh->b_blocknr, item_num, i);
/* check and fix "." */
- if (deh_offset (deh + i) != DOT_OFFSET) {
- deh[i].deh_offset = cpu_to_le32 (DOT_OFFSET);
+ if (get_deh_offset (deh + i) != DOT_OFFSET) {
+ set_deh_offset (deh + i, DOT_OFFSET);
mark_buffer_dirty (bh);
}
/* "." must point to the directory it is in */
- if (not_of_one_file (&(deh[i].deh_dir_id), &(ih->ih_key))) {
+/*
+ if (not_of_one_file (&(deh[i].deh2_dir_id), &(ih->ih_key))) {
fsck_log ("verify_direntry: block %lu, item %H has entry \".\" "
"pointing to (%K) instead of (%K)\n",
bh->b_blocknr, ih,
- &(deh[i].deh_dir_id), &(ih->ih_key));
- deh[i].deh_dir_id = key_dir_id (&ih->ih_key);
- deh[i].deh_objectid = key_objectid (&ih->ih_key);
+ &(deh[i].deh2_dir_id), &(ih->ih_key));
+ set_deh_dirid (deh + i, get_key_dirid (&ih->ih_key));
+ set_deh_objectid (deh + i, get_key_objectid (&ih->ih_key));
mark_buffer_dirty (bh);
}
+*/
} else if (is_dot_dot (name, name_len)) {
if (i != 1)
fsck_log ("block %lu: item %d: \"..\" is %d-th entry\n",
bh->b_blocknr, item_num, i);
/* check and fix ".." */
- if (deh_offset (deh + i) != DOT_DOT_OFFSET)
- deh[i].deh_offset = cpu_to_le32 (DOT_DOT_OFFSET);
+ if (get_deh_offset (deh + i) != DOT_DOT_OFFSET) {
+ set_deh_offset (deh + i, DOT_DOT_OFFSET);
+ mark_buffer_dirty (bh);
+ }
} else {
int min_length, max_length;
@@ -319,27 +338,40 @@ static int verify_directory_item (reiserfs_filsys_t fs, struct buffer_head * bh,
if (name_len == 0) {
/* we do not know the length of name - we will try to find it */
min_length = 1;
- max_length = item + ih_item_len (ih) - name;
+ max_length = item + get_ih_item_len (ih) - name;
} else
/* we kow name length, so we will try only one name length */
min_length = max_length = name_len;
+ hash_code = 0;
+
for (j = min_length; j <= max_length; j ++) {
hash_code = find_hash_in_use (name, j,
- GET_HASH_VALUE (deh_offset (deh + i)),
- rs_hash (fs->s_rs));
- add_hash_hit (fs, hash_code);
+ GET_HASH_VALUE (get_deh_offset (deh + i)),
+ get_sb_hash_code (fs->fs_ondisk_sb));
+/* add_hash_hit (fs, hash_code);*/
if (code2func (hash_code) != 0) {
/* deh_offset matches to some hash of the name */
+ if (fsck_hash_defined (fs) &&
+ hash_code != func2code (fs->fs_hash_function)) {
+ /* wrong hash selected - so we can skip this leaf */
+ return 1;
+ }
+
+
+
if (!name_len) {
fsck_log ("pass0: block %lu, item %H: entry %d. found a name \"%.*s\" "
"matching to deh_offset %u. FIXME: should set deh_location "
"of previous entry (not ready)\n",
- bh->b_blocknr, ih, i, j, name, deh_offset (deh + i));
+ bh->b_blocknr, ih, i, j, name, get_deh_offset (deh + i));
/* FIXME: if next byte is 0 we think that the name is aligned to 8 byte boundary */
if (i) {
+ set_deh_offset (&deh[i - 1], get_deh_location (deh + i) +
+ ((name[j] || fs->fs_format == REISERFS_FORMAT_3_5) ? j : ROUND_UP (j)));
+ /*
deh[i - 1].deh_location = cpu_to_le16 (deh_location (deh + i) +
- ((name[j] || SB_VERSION (fs) == REISERFS_VERSION_1) ? j : ROUND_UP (j)));
+ ((name[j] || fs->s_version == REISERFS_VERSION_1) ? j : ROUND_UP (j)));*/
mark_de_good_location (deh + i - 1);
mark_buffer_dirty (bh);
}
@@ -347,85 +379,9 @@ static int verify_directory_item (reiserfs_filsys_t fs, struct buffer_head * bh,
break;
}
}
- if (j == max_length + 1) {
- /* deh_offset does not match to anything. it will be
- deleted for now, but maybe we could just fix a
- deh_offset if it is in ordeer */
- mark_de_bad_offset (deh + i);
- }
- }
- } /* for */
-
-
-
-#if 0
- /* find entries names in which have mismatching deh_offset */
- for (i = 0; i < ih_entry_count (ih); i ++) {
- if (de_bad (deh + i))
- /* bad location */
- continue;
-
- name = name_in_entry (deh + i, i);
- /* we found a name, but we not always we can get its length as
- it depends on deh_location of previous entry */
- name_len = try_to_get_name_length (ih, deh + i, i);
-
- if (i == 0 && is_dot (name, name_len)) {
-
- /* check and fix "." */
-
- if (deh_offset (deh + i) != DOT_OFFSET) {
- deh[i].deh_offset = cpu_to_le32 (DOT_OFFSET);
- mark_buffer_dirty (bh);
- }
- /* "." must point to the directory it is in */
- if (not_of_one_file (&(deh[i].deh_dir_id), &(ih->ih_key))) {
- fsck_log ("verify_direntry: block %lu, item %H has entry \".\" "
- "pointing to (%K) instead of (%K)\n",
- bh->b_blocknr, ih,
- &(deh[i].deh_dir_id), &(ih->ih_key));
- deh[i].deh_dir_id = key_dir_id (&ih->ih_key);
- deh[i].deh_objectid = key_objectid (&ih->ih_key);
- mark_buffer_dirty (bh);
- }
- } else if (i == 1 && is_dot_dot (name, name_len)) {
-
- /* check and fix ".." */
- if (deh_offset (deh + i) != DOT_DOT_OFFSET)
- deh[i].deh_offset = cpu_to_le32 (DOT_DOT_OFFSET);
- } else {
- int min_length, max_length;
-
- /* check other name */
-
- if (name_len == 0) {
- /* we do not know the length of name - we will try to find it */
- min_length = 1;
- max_length = item + ih_item_len (ih) - name;
- } else
- /* we kow name length, so we will try only one name length */
- min_length = max_length = name_len;
+ add_hash_hit (fs, hash_code);
- for (j = min_length; j <= max_length; j ++) {
- hash_code = find_hash_in_use (name, j,
- GET_HASH_VALUE (deh_offset (deh + i)),
- rs_hash (fs->s_rs));
- add_hash_hit (fs, hash_code);
- if (code2func (hash_code) != 0) {
- /* deh_offset matches to some hash of the name */
- if (!name_len) {
- fsck_log ("pass0: block %lu, item %H: entry %d. found a name \"%.*s\" "
- "matching to deh_offset %u. FIXME: should set deh_location "
- "of previous entry (not ready)\n",
- bh->b_blocknr, ih, i, j, name, deh_offset (deh + i));
- /* FIXME: if next byte is 0 we think that the name is aligned to 8 byte boundary */
- deh[i - 1].deh_location = cpu_to_le16 (deh_location (deh + i) +
- ((name[j] || SB_VERSION (fs) == REISERFS_VERSION_1) ? j : ROUND_UP (j)));
- }
- break;
- }
- }
if (j == max_length + 1) {
/* deh_offset does not match to anything. it will be
deleted for now, but maybe we could just fix a
@@ -433,8 +389,7 @@ static int verify_directory_item (reiserfs_filsys_t fs, struct buffer_head * bh,
mark_de_bad_offset (deh + i);
}
}
- }
-#endif
+ } /* for */
#ifdef DEBUG_VERIFY_DENTRY
printf ("entries with mismatching deh_offsets: ");
@@ -453,34 +408,34 @@ static int verify_directory_item (reiserfs_filsys_t fs, struct buffer_head * bh,
int loc_fixed;
- prev_loc = ih_item_len (ih);
- for (i = 0; i < ih_entry_count (ih); i ++) {
+ prev_loc = get_ih_item_len (ih);
+ for (i = 0; i < get_ih_entry_count (ih); i ++) {
loc_fixed = 0;
if (de_bad_location (deh + i)) {
- deh[i].deh_location = cpu_to_le16 (prev_loc/* - 1*/);
+ set_deh_location (deh + i, prev_loc/* - 1*/);
mark_buffer_dirty (bh);
loc_fixed = 1;
} else {
- if (deh_location (deh + i) >= prev_loc) {
- deh[i].deh_location = cpu_to_le16 (prev_loc/* - 1*/);
+ if (get_deh_location (deh + i) >= prev_loc) {
+ set_deh_location (deh + i, prev_loc/* - 1*/);
mark_buffer_dirty (bh);
loc_fixed = 1;
}
}
- prev_loc = deh_location (deh + i);
+ prev_loc = get_deh_location (deh + i);
- if (i == ih_entry_count (ih) - 1) {
+ if (i == get_ih_entry_count (ih) - 1) {
/* last entry starts right after an array of dir entry headers */
if (!de_bad (deh + i) &&
- deh_location (deh + i) != (DEH_SIZE * ih_entry_count (ih))) {
+ get_deh_location (deh + i) != (DEH_SIZE * get_ih_entry_count (ih))) {
/* free space in the directory item */
fsck_log ("verify_direntry: block %lu, item %H has free space\n",
bh->b_blocknr, ih);
- cut_entry (fs, bh, item_num, ih_entry_count (ih), 0);
+ cut_entry (fs, bh, item_num, get_ih_entry_count (ih), 0);
}
- if (deh_location (deh + i) != (DEH_SIZE * ih_entry_count (ih))) {
- deh[i].deh_location = cpu_to_le16 (DEH_SIZE * ih_entry_count (ih));
+ if (get_deh_location (deh + i) != (DEH_SIZE * get_ih_entry_count (ih))) {
+ set_deh_location (&deh[i], (DEH_SIZE * get_ih_entry_count (ih)));
loc_fixed = 1;
mark_buffer_dirty (bh);
}
@@ -514,7 +469,7 @@ static int verify_directory_item (reiserfs_filsys_t fs, struct buffer_head * bh,
if (de_bad (deh + i))
printf ("will be deleted\n");
else
- printf ("\"%.*s\"\n", name_length (ih, deh + i, i),
+ printf ("\"%.*s\"\n", name_in_entry_length (ih, deh + i, i),
name_in_entry (deh + i, i));
}
}
@@ -523,12 +478,34 @@ static int verify_directory_item (reiserfs_filsys_t fs, struct buffer_head * bh,
bad = 0;
tmp = *ih;
+#if 1
+ /* mark enries of /lost+found as bad */
+ deh = B_I_DEH (bh, ih);
+ for (i = 0; i < get_ih_entry_count (ih); i ++, deh ++) {
+ unsigned int dirid, objectid;
+
+ if (de_bad (deh))
+ continue;
+
+ sprintf (buf, "%.*s", name_in_entry_length (ih, deh, i), name_in_entry (deh, i));
+ if (sscanf (buf, "%d_%d", &dirid, &objectid) != 2)
+ continue;
+
+ if (get_deh_dirid (deh) != dirid || get_deh_objectid (deh) != objectid)
+ continue;
+
+ /* entry in lost+found */
+ printf ("%s - will be deleted\n", buf);
+ mark_de_bad_offset (deh);
+ }
+#endif
+
/* delete entries which are marked bad */
- for (i = 0; i < ih_entry_count (ih); i ++) {
+ for (i = 0; i < get_ih_entry_count (ih); i ++) {
deh = B_I_DEH (bh, ih) + i;
if (de_bad (deh)) {
bad ++;
- if (ih_entry_count (ih) == 1) {
+ if (get_ih_entry_count (ih) == 1) {
delete_item (fs, bh, item_num);
break;
} else {
@@ -538,16 +515,16 @@ static int verify_directory_item (reiserfs_filsys_t fs, struct buffer_head * bh,
}
}
- if (bad == ih_entry_count (&tmp)) {
+ if (bad == get_ih_entry_count (&tmp)) {
fsck_log ("pass0: block %lu, item %H - all entries were deleted\n", bh->b_blocknr, &tmp);
- return 0;
+ return -1;
}
deh = B_I_DEH (bh, ih);
- if (get_offset (&ih->ih_key) != deh_offset (deh)) {
+ if (get_offset (&ih->ih_key) != get_deh_offset (deh)) {
fsck_log ("verify_direntry: block %lu, item %H: k_offset and deh_offset %u mismatched\n",
- bh->b_blocknr, ih, deh_offset (deh));
- set_offset (KEY_FORMAT_1, &ih->ih_key, deh_offset (deh));
+ bh->b_blocknr, ih, get_deh_offset (deh));
+ set_offset (key_format (&ih->ih_key), &ih->ih_key, get_deh_offset (deh));
mark_buffer_dirty (bh);
}
@@ -557,197 +534,369 @@ static int verify_directory_item (reiserfs_filsys_t fs, struct buffer_head * bh,
return 0;
-#if 0
-
- /* FIXME: temporary */
- if (bad_locations > ih_entry_count (ih) / 2) {
- fsck_log ("pass0: block %u: item %d (%H) had too bad directory - deleted\n",
- bh->b_blocknr, item_num, ih);
- delete_item (fs, bh, item_num);
- return 0;
- }
-
- if (!dirty)
- return 0;
-
- /* something is broken */
-
- fsck_log ("pass0: block %lu: %d-th item (%H) has %d bad entries..",
- bh->b_blocknr, item_num, ih, dirty);
+}
- if (get_offset (&ih->ih_key) == DOT_OFFSET) {
- /* first item of directory - make sure that "." and ".." are in place */
- if (deh_offset (deh) != DOT_OFFSET || name_in_entry (deh, 0)[0] != '.') {
- deh->deh_offset = cpu_to_le32 (DOT_OFFSET);
- name_in_entry (deh, 0)[0] = '.';
- }
- if (deh_offset (deh + 1) != DOT_DOT_OFFSET ||
- name_in_entry (deh + 1, 1)[0] != '.' || name_in_entry (deh + 1, 1)[1] != '.') {
- (deh + 1)->deh_offset = cpu_to_le32 (DOT_DOT_OFFSET);
- name_in_entry (deh + 1, 1)[0] = '.';
- name_in_entry (deh + 1, 1)[1] = '.';
- }
- }
- end = item + ih_item_len (ih);
- deh += ih_entry_count (ih);
- entries = (char *)deh;
- total_entry_len = ih_item_len (ih) - DEH_SIZE * ih_entry_count (ih);
- i = ih_entry_count (ih);
-
- bad_entries = 0;
- do {
- i --;
- deh --;
- name_len = prob_name (fs, &entries, total_entry_len, deh_offset (deh));
- if (!name_len) {
- if (!bad_entries) {
- deh->deh_location = cpu_to_le16 (entries - item);
- } else {
- deh->deh_location = cpu_to_le16 (deh_location (deh + 1) + 1);
- }
- bad_entries ++;
-
- /*fsck_log ("verify_directory_item: entry %d: in string \'%s\' there is no substring matching hash %ld\n",
- i, bad_name (entries, total_entry_len), masked_offset);*/
- mark_de_bad (deh);
- continue;
- }
- bad_entries = 0;
- /*fsck_log ("verify_directory_item: entry %d: found \"%s\" name matching hash %ld\n",
- i, bad_name (entries, name_len), masked_offset);*/
-
- /* 'entries' points now to the name which match given offset -
- so, set deh_location */
- deh->deh_location = cpu_to_le16 (entries - item);
- deh->deh_state = 0;
- mark_de_visible (deh);
-
- entries += name_len;
- total_entry_len = end - entries;
- /* skip padding zeros */
- while (!*entries) {
- entries ++;
- total_entry_len --;
- }
- /* 'entries' points now at the place where next (previous)
- entry should start */
- } while ((char *)deh != item);
-
-
- /* fixme: this will not work if all entries are to be deleted */
- for (i = 0; i < ih_entry_count (ih); i ++, deh ++) {
- deh = (struct reiserfs_de_head *)B_I_PITEM (bh, ih) + i;
- if (de_bad (deh)) {
- if (ih_entry_count (ih) == 1) {
- delete_item (fs, bh, i);
- break;
- } else {
- cut_entry (fs, bh, item_num, i);
- }
- i --;
- }
+static int does_it_fit_into_dev (__u64 offset) {
+ return ( UNFM_P_SIZE * offset / MAX_ITEM_LEN(fs->fs_blocksize) < fs->fs_blocksize * get_sb_block_count (fs->fs_ondisk_sb)) ?
+ 1 : 0;
/*
- fsck_log ("verify_directory_item: %d-th entry is to be deleted: "
- "\"%s\" does not match to hash %lu\n",
- i, bad_name (name_in_entry (deh, i), name_length (ih, deh, i)),
- deh_offset (deh));
+ offset / blocksize - unfp count
+ UNFM_P_SIZE * offset / blocksize / MAX_ITEM_LEN - count of blocks to store it
+ blocksize * UNFM_P_SIZE * offset / blocksize / MAX_ITEM_LEN - size to store it
*/
- }
-
- fsck_log ("%d entries were deleted\n", entry_count - ih_entry_count (ih));
- mark_buffer_dirty (bh);
+}
-
- return 0;
-#endif
-}
+static int is_wrong_short_key (struct key * key) {
+ if (get_key_dirid (key) == 0 || get_key_objectid (key) == 0 || get_key_objectid (key) == 1 ||
+ get_key_dirid (key) == -1 || get_key_objectid (key) == -1 ||
+ get_key_dirid (key) == get_key_objectid (key) ||
+ (get_key_dirid (key) == 1 && get_key_objectid (key) != 2) ||
+ (get_key_dirid (key) != 1 && get_key_objectid (key) == 2) )
+ return 1;
+ return 0;
+}
/* do this on pass 0 with every leaf marked used */
/* FIXME: we can improve fixing of broken keys: we can ssfe direct items which
go after stat data and have broken keys */
-static void pass0_correct_leaf (reiserfs_filsys_t fs,
+static void pass0_correct_leaf (reiserfs_filsys_t * fs,
struct buffer_head * bh)
{
int i, j;
struct item_head * ih;
__u32 * ind_item;
+ __u64 offset;
unsigned long unfm_ptr;
int dirty = 0;
+ int nr_items;
+ int file_format = KEY_FORMAT_UNDEFINED;
+ int symlnk = 0;
+ int bad_order;
+
+
+ /* delete all safe links and */
+ for (i = get_blkh_nr_items (B_BLK_HEAD (bh)) - 1; i >= 0; i--) {
+ if (get_key_dirid (&B_N_PITEM_HEAD (bh, i)->ih_key) == -1) {
+ delete_item (fs, bh, i);
+ }
+ }
start_again:
ih = B_N_PITEM_HEAD (bh, 0);
- for (i = 0; i < node_item_number (bh); i ++, ih ++) {
- if (ih->ih_key.k_dir_id == 0 || ih->ih_key.k_objectid == 0) {
+ bad_order = 0;
+ for (i = 0; i < (nr_items = get_blkh_nr_items (B_BLK_HEAD (bh))); i ++, ih ++) {
+
+ if (type_unknown (&ih->ih_key)) {
+ if ((get_ih_item_len (ih) == SD_SIZE) || (get_ih_item_len (ih) == SD_V1_SIZE)) {
+ set_type_and_offset (KEY_FORMAT_1, &ih->ih_key, SD_OFFSET, TYPE_STAT_DATA);
+ dirty = 1;
+ fsck_log("pass0: vpf-10100: block %lu, item (%d), unknown type of item of SD size," \
+ " type set to TYPE_STAT_DATA (%k)\n",
+ bh->b_blocknr, i, &ih->ih_key);
+ } else {
+ fsck_log("pass0: vpf-10110: block %lu, item (%d), unknown item type found (%k) - delete\n",
+ bh->b_blocknr, i, &ih->ih_key);
+ delete_item (fs, bh, i);
+ goto start_again;
+ }
+ }
+
+
+ if (is_wrong_short_key (&ih->ih_key)) {
/* sometimes stat datas get k_objectid==0 or k_dir_id==0 */
- if (i == (node_item_number (bh) - 1)) {
- /* */
+
+/* if (i == (nr_items - 1)) {
+
if (i == 0) {
- fsck_log ("block %lu: item %d: (%H) is alone in the block\n",
+ fsck_log ("block %lu: item %d: (%H) id equals 0\n",
bh->b_blocknr, i, ih);
return;
}
- /* delete last item */
+ // delete last item
+ fsck_log ("block %lu: item %d: (%H) id equals 0\n",
+ bh->b_blocknr, i, ih);
delete_item (fs, bh, i - 1);
return;
}
+*/
+ /* FIXME:
+ 18842 19034 0x1 IND (2)
+ 19035 19035 0x0 SD (0)
+ 18842 1 0x1 IND (1)
+ 18842 1 0x1001 DRCT (2)
+ */
/* there is next item: if it is not stat data - take its k_dir_id
and k_objectid. if key order will be still wrong - the changed
item will be deleted */
- if (!is_stat_data_ih (ih + 1)) {
- fsck_log ("block %lu: item %d: (%H) fixed to ", bh->b_blocknr, i, ih);
- ih->ih_key.k_dir_id = (ih + 1)->ih_key.k_dir_id;
- ih->ih_key.k_objectid = (ih + 1)->ih_key.k_objectid;
- set_offset (KEY_FORMAT_1, &ih->ih_key, 0);
- set_type (KEY_FORMAT_1, &ih->ih_key, TYPE_STAT_DATA);
- fsck_log ("(%H)\n", ih);
+
+ if (i && !is_stat_data_ih (ih)) {
+ /* previous item has not a wrong short_key */
+ fsck_log ("pass0: vpf-10120: block %lu: item %d: (%k) fixed to ", bh->b_blocknr, i, &ih->ih_key);
+ set_key_dirid (&ih->ih_key, get_key_dirid (&(ih - 1)->ih_key));
+ set_key_objectid (&ih->ih_key, get_key_objectid (&(ih - 1)->ih_key));
+ fsck_log ("(%k)\n", &ih->ih_key);
dirty = 1;
- } else if (i == 0) {
+ } else if ((i < nr_items - 1) && !is_stat_data_ih (ih + 1)) {
+ if (!is_wrong_short_key(&(ih + 1)->ih_key)) {
+ fsck_log ("pass0: vpf-10130: block %lu: item %d: (%k) fixed to ", bh->b_blocknr, i, &ih->ih_key);
+ set_key_dirid (&ih->ih_key, get_key_dirid (&(ih + 1)->ih_key));
+ set_key_objectid (&ih->ih_key, get_key_objectid (&(ih + 1)->ih_key));
+/* set_offset (KEY_FORMAT_1, &ih->ih_key, 0);
+ set_type (KEY_FORMAT_1, &ih->ih_key, TYPE_STAT_DATA);*/
+ fsck_log ("(%k)\n", &ih->ih_key);
+ dirty = 1;
+ goto start_again;
+ } else {
+ fsck_log ("pass0: vpf-10140: block %lu: items %d and %d have bad short keys (%k), (%k), both deleted\n",
+ bh->b_blocknr, i, i+1, &ih->ih_key, &(ih + 1)->ih_key);
+ delete_item (fs, bh, i);
+ delete_item (fs, bh, i);
+ goto start_again;
+ }
+ } else {
+ fsck_log ("pass0: vpf-10150: block %lu: item %d with wrong id (%k) - deleted\n",
+ bh->b_blocknr, i, &ih->ih_key);
delete_item (fs, bh, i);
goto start_again;
+ }
+ }
+
+
+ if (i && i + 1 < nr_items) {
+ if (is_stat_data_ih (ih - 1) && !is_stat_data_ih (ih) &&
+ !is_direct_ih (ih + 1) && !is_stat_data_ih (ih + 1)) {
+ /* i or i+1 item should be SD or i+1 should be direct item */
+ if ((get_ih_item_len (ih) == SD_SIZE) || (get_ih_item_len (ih) == SD_V1_SIZE)) {
+ /* make i as SD */
+ fsck_log("pass0: vpf-10400: block %lu, item (%d), make %k fixed to SD\n",
+ bh->b_blocknr, i, &ih->ih_key);
+ set_type_and_offset (KEY_FORMAT_1, &ih->ih_key, SD_OFFSET, TYPE_STAT_DATA);
+ dirty = 1;
+ } else if ((get_ih_item_len (ih+1) == SD_SIZE) || (get_ih_item_len (ih+1) == SD_V1_SIZE)) {
+ /* make i+1 as SD */
+ fsck_log("pass0: vpf-10410: block %lu, item (%d), make %k fixed to SD\n",
+ bh->b_blocknr, i + 1, &(ih + 1)->ih_key);
+ set_type_and_offset (KEY_FORMAT_1, &(ih + 1)->ih_key, SD_OFFSET, TYPE_STAT_DATA);
+ dirty = 1;
+ } else {
+ fsck_log("pass0: vpf-10420: block %lu, item (%d), make %k fixed to DIRECT\n",
+ bh->b_blocknr, i+1, &ih->ih_key);
+ set_type (get_ih_key_format(ih+1), &(ih + 1)->ih_key, TYPE_DIRECT);
+ dirty = 1;
+ }
+ }
+ }
+
+ if (i && ((is_stat_data_ih (ih - 1) &&
+ !is_stat_data_ih (ih) &&
+ (get_key_dirid (&(ih - 1)->ih_key) != get_key_dirid (&ih->ih_key))) ||
+ (is_stat_data_ih (ih) &&
+ (get_key_dirid (&(ih - 1)->ih_key) > get_key_dirid (&ih->ih_key)))))
+ {
+ /* not the same dir_id of the same file or not increasing dir_id of different files */
+ if ((i > 1) && get_key_dirid (&(ih - 2)->ih_key) == get_key_dirid (&(ih - 1)->ih_key)) {
+ /* fix i-th */
+ if (!is_stat_data_ih (ih)) {
+ fsck_log("pass0: vpf-10430: block %lu, item (%d), wrong order of items dir_id of %k fixed to %lu\n",
+ bh->b_blocknr, i, &ih->ih_key, get_key_dirid (&(ih - 1)->ih_key));
+ set_key_dirid (&ih->ih_key, get_key_dirid (&(ih - 1)->ih_key));
+ dirty = 1;
+ } else if (i + 1 < nr_items) {
+ fsck_log("pass0: vpf-10440: block %lu, item (%d), wrong order of items dir_id of %k fixed to %lu\n",
+ bh->b_blocknr, i, &ih->ih_key, get_key_dirid (&(ih + 1)->ih_key));
+ set_key_dirid (&ih->ih_key, get_key_dirid (&(ih + 1)->ih_key));
+ dirty = 1;
+ }
+ } else
+ if ((i + 1 < nr_items) && get_key_dirid (&ih->ih_key) == get_key_dirid (&(ih + 1)->ih_key)) {
+ fsck_log("pass0: vpf-10450: block %lu, item (%d), wrong order of items dir_id of %k fixed to %lu\n",
+ bh->b_blocknr, i - 1, &(ih - 1)->ih_key, get_key_dirid (&ih->ih_key));
+ /* fix (i - 1)-th */
+ set_key_dirid (&(ih - 1)->ih_key, get_key_dirid (&ih->ih_key));
+ dirty = 1;
+ }
+ }
+
+ if (i && i + 1 < nr_items) {
+ /* there is a previous and a next items */
+ if ((get_key_dirid (&(ih - 1)->ih_key) == get_key_dirid (&(ih + 1)->ih_key)) &&
+ (get_key_dirid (&(ih - 1)->ih_key) != get_key_dirid (&ih->ih_key)))
+ {
+ fsck_log("pass0: vpf-10460: block %lu, item (%d), wrong order of items dir_id of %k fixed to %lu\n",
+ bh->b_blocknr, i, &ih->ih_key, get_key_dirid (&(ih - 1)->ih_key));
+ set_key_dirid (&ih->ih_key, get_key_dirid (&(ih - 1)->ih_key));
+ dirty = 1;
+ }
+ if (is_stat_data_ih (ih - 1) && is_indirect_ih (ih) && is_direct_ih (ih + 1)) {
+ if ((get_key_objectid (&(ih - 1)->ih_key) == get_key_objectid (&(ih + 1)->ih_key)) &&
+ (get_key_objectid (&(ih - 1)->ih_key) != get_key_objectid (&ih->ih_key)))
+ {
+ fsck_log("pass0: vpf-10470: block %lu, item (%d), wrong order of items object_id of %k fixed to %lu\n",
+ bh->b_blocknr, i, &ih->ih_key, get_key_objectid (&(ih - 1)->ih_key));
+ set_key_objectid (&ih->ih_key, get_key_objectid (&(ih - 1)->ih_key));
+ dirty = 1;
+ }
+ if ((get_key_objectid (&(ih - 1)->ih_key) == get_key_objectid (&ih->ih_key)) &&
+ (get_key_objectid (&(ih - 1)->ih_key) != get_key_objectid (&(ih + 1)->ih_key)))
+ {
+ fsck_log("pass0: vpf-10480: block %lu, item (%d), wrong order of items object_id of %k fixed to %lu\n",
+ bh->b_blocknr, i + 1, &(ih+1)->ih_key, get_key_objectid (&(ih - 1)->ih_key));
+ set_key_objectid (&(ih + 1)->ih_key, get_key_objectid (&(ih - 1)->ih_key));
+ dirty = 1;
+ }
+ if ((get_key_objectid (&ih->ih_key) == get_key_objectid (&(ih + 1)->ih_key)) &&
+ (get_key_objectid (&(ih - 1)->ih_key) != get_key_objectid (&(ih + 1)->ih_key)))
+ {
+ fsck_log("pass0: vpf-10490: block %lu, item (%d), wrong order of items object_id of %k fixed to %lu\n",
+ bh->b_blocknr, i - 1, &(ih-1)->ih_key, &(ih + 1)->ih_key);
+ set_key_objectid (&(ih - 1)->ih_key, get_key_objectid (&(ih + 1)->ih_key));
+ dirty = 1;
+ }
+ if ((get_key_dirid (&(ih - 1)->ih_key) == get_key_dirid (&ih->ih_key)) &&
+ (get_key_dirid (&(ih - 1)->ih_key) != get_key_dirid (&(ih + 1)->ih_key)))
+ {
+ fsck_log("pass0: vpf-10500: block %lu, item (%d), wrong order of items dir_id of %k fixed to %lu\n",
+ bh->b_blocknr, i + 1, &(ih+1)->ih_key, get_key_dirid (&(ih - 1)->ih_key));
+ set_key_dirid (&(ih + 1)->ih_key, get_key_dirid (&(ih - 1)->ih_key));
+ dirty = 1;
+ }
+ if ((get_key_dirid (&ih->ih_key) == get_key_dirid (&(ih + 1)->ih_key)) &&
+ (get_key_dirid (&(ih - 1)->ih_key) != get_key_dirid (&(ih + 1)->ih_key)))
+ {
+ fsck_log("pass0: vpf-10510: block %lu, item (%d), wrong order of items dir_id of %k fixed to %lu\n",
+ bh->b_blocknr, i - 1, &(ih-1)->ih_key, get_key_dirid (&(ih + 1)->ih_key));
+ set_key_dirid (&(ih - 1)->ih_key, get_key_dirid (&(ih + 1)->ih_key));
+ dirty = 1;
+ }
+ }
+ }
+
+ if (i && is_stat_data_ih (ih) &&
+ get_key_dirid (&(ih - 1)->ih_key) == get_key_dirid (&ih->ih_key) &&
+ get_key_objectid (&(ih - 1)->ih_key) >= get_key_objectid (&ih->ih_key)) {
+ if ((i + 1 < nr_items) && !is_stat_data_ih (ih + 1)) {
+ if (get_key_objectid (&(ih - 1)->ih_key) < get_key_objectid (&(ih + 1)->ih_key)) {
+ fsck_log("pass0: vpf-10520: block %lu, item (%d), wrong order of items object_id of %k fixed to %lu\n",
+ bh->b_blocknr, i - 1, &(ih-1)->ih_key, get_key_objectid (&(ih + 1)->ih_key));
+ set_key_objectid (&ih->ih_key, get_key_objectid (&(ih + 1)->ih_key));
+ dirty = 1;
+ }
}
}
+ if (i && is_stat_data_ih (ih - 1) && !is_stat_data_ih (ih) &&
+ (get_key_objectid (&(ih - 1)->ih_key) != get_key_objectid (&ih->ih_key)))
+ {
+ int err = 0;
+ if (i > 1) {
+ if (comp_short_keys (&(ih - 2)->ih_key, &(ih - 1)->ih_key) != -1)
+ set_bit (1, &err);
+ if (comp_short_keys (&(ih - 2)->ih_key, &ih->ih_key) != -1)
+ set_bit (2, &err);
+ }
+ if (i + 1 < nr_items) {
+ if (comp_short_keys (&(ih - 1)->ih_key, &(ih + 1)->ih_key) != -1)
+ set_bit (3, &err);
+ if (comp_short_keys (&ih->ih_key, &(ih + 1)->ih_key) != -1)
+ set_bit (4, &err);
+ }
+/*
+ if ((test_bit (1, err) || test_bit (3, err)) &&
+ (test_bit (2, err) || test_bit (4, err))) {
+ // thera are no problem-free keys, delete them both
+ delete_item (fs, bh, i - 1);
+ delete_item (fs, bh, i - 1);
+ goto start_again;
+ }
+*/
+ if (!test_bit (1, &err) && !test_bit (3, &err) &&
+ !test_bit (2, &err) && !test_bit (4, &err)) {
+ if (i <= 1) {
+ /* take bigger */
+ if (comp_short_keys (&(ih - 1)->ih_key, &ih->ih_key) == 1) {
+ fsck_log("pass0: vpf-10530: block %lu, item (%d), wrong order of items object_id of %k fixed to %lu\n",
+ bh->b_blocknr, i, &ih->ih_key, get_key_objectid (&(ih - 1)->ih_key));
+ set_key_objectid (&ih->ih_key, get_key_objectid (&(ih - 1)->ih_key));
+ } else {
+ fsck_log("pass0: vpf-10540: block %lu, item (%d), wrong order of items object_id of %k fixed to %lu\n",
+ bh->b_blocknr, i - 1, &(ih - 1)->ih_key, get_key_objectid (&ih->ih_key));
+ set_key_objectid (&(ih - 1)->ih_key, get_key_objectid (&ih->ih_key));
+ }
+ } else {
+ /* take smaller */
+ if (comp_short_keys (&(ih - 1)->ih_key, &ih->ih_key) == 1) {
+ fsck_log("pass0: vpf-10550: block %lu, item (%d), wrong order of items object_id of %k fixed to %lu\n",
+ bh->b_blocknr, i - 1, &(ih - 1)->ih_key, get_key_objectid (&ih->ih_key));
+ set_key_objectid (&(ih - 1)->ih_key, get_key_objectid (&ih->ih_key));
+ } else {
+ fsck_log("pass0: vpf-10560: block %lu, item (%d), wrong order of items object_id of %k fixed to %lu\n",
+ bh->b_blocknr, i, &ih->ih_key, get_key_objectid (&(ih - 1)->ih_key));
+ set_key_objectid (&ih->ih_key, get_key_objectid (&(ih - 1)->ih_key));
+ }
+ }
+ dirty = 1;
+ } else if (!test_bit (1, &err) && !test_bit (3, &err)) {
+ /* take i - 1 */
+ fsck_log("pass0: vpf-10570: block %lu, item (%d), wrong order of items object_id of %k fixed to %lu\n",
+ bh->b_blocknr, i, &ih->ih_key, get_key_objectid (&(ih - 1)->ih_key));
+ set_key_objectid (&ih->ih_key, get_key_objectid (&(ih - 1)->ih_key));
+ dirty = 1;
+ } else if (!test_bit (2, &err) && !test_bit (4, &err)) {
+ /* take i */
+ fsck_log("pass0: vpf-10580: block %lu, item (%d), wrong order of items object_id of %k fixed to %lu\n",
+ bh->b_blocknr, i - 1, &(ih - 1)->ih_key, get_key_objectid (&ih->ih_key));
+ set_key_objectid (&(ih - 1)->ih_key, get_key_objectid (&ih->ih_key));
+ dirty = 1;
+ }
+ }
+
/* this recovers corruptions like the below:
1774 1732 0 0
116262638 1732 1 3
1774 1736 0 0 */
if (i && is_stat_data_ih (ih - 1) && !is_stat_data_ih (ih)) {
- if (ih->ih_key.k_objectid != (ih - 1)->ih_key.k_objectid ||
- ih->ih_key.k_dir_id != (ih - 1)->ih_key.k_dir_id ||
+ if (get_key_objectid (&ih->ih_key) != get_key_objectid (&(ih - 1)->ih_key) ||
+ get_key_dirid (&ih->ih_key) != get_key_dirid (&(ih - 1)->ih_key) ||
get_offset (&ih->ih_key) != 1) {
if (is_direntry_ih (ih)) {
- fsck_log ("block %lu: item %d: no \".\" entry found in "
+ fsck_log ("pass0: vpf-10160: block %lu: item %d: no \".\" entry found in "
"the first item of a directory\n", bh->b_blocknr, i);
+ set_key_dirid (&ih->ih_key, get_key_dirid (&(ih - 1)->ih_key));
+ set_key_objectid (&ih->ih_key, get_key_objectid (&(ih - 1)->ih_key));
+ dirty = 1;
} else {
- fsck_log ("block %lu: item %d: (%H) fixed to ",
- bh->b_blocknr, i, ih);
- ih->ih_key.k_dir_id = (ih - 1)->ih_key.k_dir_id;
- ih->ih_key.k_objectid = (ih - 1)->ih_key.k_objectid;
+ fsck_log ("pass0: vpf-10170: block %lu: item %d: (%k) fixed to ",
+ bh->b_blocknr, i, &ih->ih_key);
+
+ set_key_dirid (&ih->ih_key, get_key_dirid (&(ih - 1)->ih_key));
+ set_key_objectid (&ih->ih_key, get_key_objectid (&(ih - 1)->ih_key));
- if (ih_item_len (ih - 1) == SD_SIZE) {
+ if (get_ih_item_len (ih - 1) == SD_SIZE) {
/* stat data is new, therefore this item is new too */
set_offset (KEY_FORMAT_2, &(ih->ih_key), 1);
- if (ih_entry_count (ih) != 0xffff)
+ if (get_ih_entry_count (ih) != 0xffff)
set_type (KEY_FORMAT_2, &(ih->ih_key), TYPE_INDIRECT);
else
set_type (KEY_FORMAT_2, &(ih->ih_key), TYPE_DIRECT);
- set_key_format (ih, KEY_FORMAT_2);
+ set_ih_key_format (ih, KEY_FORMAT_2);
} else {
/* stat data is old, therefore this item is old too */
set_offset (KEY_FORMAT_1, &(ih->ih_key), 1);
- if (ih_entry_count (ih) != 0xffff)
+ if (get_ih_entry_count (ih) != 0xffff && (get_ih_item_len (ih) % 4 == 0))
set_type (KEY_FORMAT_1, &(ih->ih_key), TYPE_INDIRECT);
- else
+ else {
set_type (KEY_FORMAT_1, &(ih->ih_key), TYPE_DIRECT);
- set_key_format (ih, KEY_FORMAT_1);
+ set_ih_free_space (ih, 0xffff);
+ }
+ set_ih_key_format (ih, KEY_FORMAT_1);
}
- fsck_log ("%H\n", ih);
+ fsck_log ("%k\n", &ih->ih_key);
dirty = 1;
}
}
@@ -761,20 +910,92 @@ static void pass0_correct_leaf (reiserfs_filsys_t fs,
/* delete item if it is not in correct order of object items */
if (i && not_of_one_file (&ih->ih_key, &(ih - 1)->ih_key) &&
!is_stat_data_ih (ih)) {
- fsck_log ("block %lu: item %d: %H follows non stat item %H - deleted\n",
- bh->b_blocknr, i, ih, ih - 1);
+ fsck_log ("pass0: vpf-10180: block %lu: item %d: %k follows non stat item %k - deleted\n",
+ bh->b_blocknr, i, &ih->ih_key, &(ih - 1)->ih_key);
delete_item (fs, bh, i);
goto start_again;
}
+
+ if (is_stat_data_ih (ih)) {
+ if (get_offset (&ih->ih_key) != 0) {
+ set_offset(KEY_FORMAT_1, &ih->ih_key, 0);
+ dirty = 1;
+ }
+ } else if (!is_direntry_ih (ih)) {
+ /* not SD, not direntry */
+ if (i && comp_short_keys (&(ih - 1)->ih_key, &ih->ih_key) == 0) {
+ if (is_stat_data_ih (ih - 1)) {
+ if (get_offset (&ih->ih_key) != 1) {
+ set_offset(key_format(&ih->ih_key), &ih->ih_key, 1);
+ dirty = 1;
+ }
+ } else if (is_indirect_ih (ih - 1) && is_direct_ih (ih)) {
+ if (get_offset (&ih->ih_key) !=
+ get_offset(&(ih - 1)->ih_key) + I_UNFM_NUM (ih - 1) * fs->fs_blocksize)
+ {
+ set_offset(key_format(&ih->ih_key), &ih->ih_key,
+ get_offset(&(ih - 1)->ih_key) + I_UNFM_NUM (ih - 1) * fs->fs_blocksize);
+ dirty = 1;
+ }
+ } else {
+ /* not first item in the leaf after neither stat data nor indirect */
+ fsck_log("pass0: vpf-10250: block %lu, item (%d), wrong order of items (%k, %k) - delete\n",
+ bh->b_blocknr, i, &(ih - 1)->ih_key, &ih->ih_key);
+ delete_item (fs, bh, i);
+ goto start_again;
+ }
+ } else {
+ /*first item in the node or first item of the file */
+
+ if (i) {
+ /* first item of the file, but not SD - delete */
+ fsck_log("pass0: vpf-10190: block %lu, item (%d), item without stat data found (%k) - delete\n",
+ bh->b_blocknr, i, &ih->ih_key);
+ delete_item (fs, bh, i);
+ goto start_again;
+ }
+
+ /* indirect or direct is the first in the leaf */
+ offset = (__u64)get_offset (&ih->ih_key);
+ if (is_indirect_ih (ih)) {
+ if (offset % fs->fs_blocksize != 1) {
+ fsck_log("pass0: vpf-10200: block %lu, item (%d), wrong item offset (%k) - delete\n",
+ bh->b_blocknr, i, &ih->ih_key);
+ delete_item (fs, bh, i);
+ goto start_again;
+ }
+ }
+
+ if (is_direct_ih (ih)) {
+ if (!correct_direct_item_offset (get_offset (&ih->ih_key), key_format (&ih->ih_key)) ||
+ STORE_TAIL_IN_UNFM (offset + get_ih_item_len (ih) - 1, get_ih_item_len (ih), bh->b_size)) {
+ fsck_log("pass0: vpf-10210: block %lu, item (%d), wrong item offset (%k) - delete\n",
+ bh->b_blocknr, i, &ih->ih_key);
+ delete_item (fs, bh, i);
+ goto start_again;
+ }
+ }
+
+ offset += get_bytes_number (ih, fs->fs_blocksize);
+ if (!does_it_fit_into_dev (offset)) {
+ fsck_log("pass0: vpf-10230: block %lu, item (%d) offset is too big (%k) - delete\n",
+ bh->b_blocknr, i, &ih->ih_key);
+ delete_item (fs, bh, i);
+ goto start_again;
+ }
+ }
+ }
+
+
if (i && comp_keys (&(ih - 1)->ih_key, &ih->ih_key) != -1) {
/* previous item has key not smaller than the key of currect item */
if (is_stat_data_ih (ih - 1) && !is_stat_data_ih (ih)) {
/* fix key of stat data such as if it was stat data of that item */
fsck_log ("pass0: block %lu: %d-th item %k is out of order, made a stat data of %d-th (%k)\n",
bh->b_blocknr, i - 1, &(ih - 1)->ih_key, i, &ih->ih_key);
- (ih - 1)->ih_key.k_dir_id = ih->ih_key.k_dir_id;
- (ih - 1)->ih_key.k_objectid = ih->ih_key.k_objectid;
+ set_key_dirid (&(ih - 1)->ih_key, get_key_dirid (&ih->ih_key));
+ set_key_objectid (&(ih - 1)->ih_key, get_key_objectid (&ih->ih_key));
set_offset (KEY_FORMAT_1, &(ih - 1)->ih_key, 0);
set_type (KEY_FORMAT_1, &(ih - 1)->ih_key, TYPE_STAT_DATA);
dirty = 1;
@@ -824,8 +1045,8 @@ static void pass0_correct_leaf (reiserfs_filsys_t fs,
/* there wer only two items in a node, so we could not
decide what to delete, go and ask user */
}
- fsck_log ("pass0: which of these items looks better (other will be deleted)?\n"
- "%H\n%H\n", ih - 1, ih);
+ fsck_log ("pass0: block %lu, items %d,%d, which of these items looks better (other will be deleted)?\n"
+ "%k\n%k\n", bh->b_blocknr, i-1, i, &(ih - 1)->ih_key, &ih->ih_key);
if (fsck_user_confirmed (fs, "1 or 2?", "1\n", 1))
delete_item (fs, bh, i - 1);
else
@@ -834,34 +1055,133 @@ static void pass0_correct_leaf (reiserfs_filsys_t fs,
}
}
- if (is_stat_data_ih (ih) && (ih_item_len (ih) != SD_SIZE &&
- ih_item_len (ih) != SD_V1_SIZE)) {
- fsck_log ("pass0: block %lu, stat data of wrong length %H - deleted\n",
- bh, ih);
+ if (is_stat_data_ih (ih) && (get_ih_item_len (ih) != SD_SIZE &&
+ get_ih_item_len (ih) != SD_V1_SIZE)) {
+ fsck_log ("pass0: block %lu, item %d, stat data of wrong length %k - deleted\n",
+ bh->b_blocknr, i, &ih->ih_key);
delete_item (fs, bh, i);
goto start_again;
}
dirty += correct_key_format (ih);
-
+
if (is_stat_data_ih (ih)) {
+ __u16 mode;
+
+ file_format = get_ih_key_format (ih);
+
+ get_sd_mode (ih, B_N_PITEM(bh,i), &mode);
+ symlnk = ( S_ISLNK(mode) ? 1 : 0);
;/*correct_stat_data (fs, bh, i);*/
+ } else if ( !is_direntry_ih(ih) &&
+ !(symlnk && is_direct_ih(ih)) &&
+ (file_format != KEY_FORMAT_UNDEFINED) &&
+ (file_format != get_ih_key_format (ih)))
+ {
+ fsck_log("pass0: vpf-10240: block %lu, item (%d), item format (%H) is not equal to SD format (%d) - delete\n",
+ bh->b_blocknr, i, ih, file_format);
+ delete_item (fs, bh, i);
+ file_format = KEY_FORMAT_UNDEFINED;
+ goto start_again;
+ }
+
+
+ if (i && is_stat_data_ih (ih - 1) && !not_of_one_file (&ih->ih_key, &(ih - 1)->ih_key)) {
+ __u16 mode;
+
+ get_sd_mode (ih - 1, B_I_PITEM (bh, ih - 1), &mode);
+ if (not_a_directory (B_I_PITEM (bh, ih - 1)) && is_direntry_ih (ih)) {
+ /* make SD mode SD of dir */
+ fsck_log ("pass0: block %lu, item %d: directory %K with wrong mode (%M), fixed to ",
+ bh->b_blocknr, i, &ih->ih_key, mode);
+ mode &= ~S_IFMT;
+ mode |= S_IFDIR;
+ fsck_log ("(%M)\n", mode);
+ set_sd_mode (ih - 1, B_I_PITEM (bh, ih - 1), &mode);
+ dirty = 1;
+ } else if (!not_a_directory (B_I_PITEM (bh, ih - 1)) && !is_direntry_ih (ih)) {
+ /* make SD mode SD of regular file */
+ fsck_log ("pass0: block %lu, item %d: not directory %K with wrong mode (%M), fixed to ",
+ bh->b_blocknr, i, &ih->ih_key, mode);
+ mode &= ~S_IFMT;
+ mode |= S_IFREG;
+ fsck_log ("(%M)\n", mode);
+ set_sd_mode (ih - 1, B_I_PITEM (bh, ih - 1), &mode);
+ dirty = 1;
+ }
+ if (not_a_regfile (B_I_PITEM (bh, ih - 1)) && is_indirect_ih (ih)) {
+ fsck_log ("pass0: block %lu, item %d: file %K having indirect item with wrong mode (%M), fixed to ",
+ bh->b_blocknr, i, &ih->ih_key, mode);
+ mode &= ~S_IFMT;
+ mode |= S_IFREG;
+ fsck_log ("(%M)\n", mode);
+ set_sd_mode (ih - 1, B_I_PITEM (bh, ih - 1), &mode);
+ dirty = 1;
+ }
}
if (is_direntry_ih (ih)) {
- verify_directory_item (fs, bh, i);
+ j = verify_directory_item (fs, bh, i);
+
+ if (j == 1) {
+ /* wrong hash, skip the leaf */
+ pass_0_stat (fs)->too_old_leaves ++;
+ mark_buffer_clean (bh);
+ return;
+ } else if (j == -1) {
+ /* item was deleted */
+ goto start_again;
+ }
continue;
}
+ /*DEBUG*/
+ if (!is_stat_data_ih (ih) && get_offset (&ih->ih_key) == 0)
+ reiserfs_panic ("block %lu: item %d, zero offset found %k (%d)\n", bh->b_blocknr, i, &ih->ih_key);
+
+
if (!is_indirect_ih (ih))
continue;
+
+ /* Darko Palic's filesystem had item: [20079 17328 0xfffb1001 IND, len 4048], format old */
+ {
+ struct key tmp_key;
+
+ tmp_key = ih->ih_key;
+ set_offset (key_format (&tmp_key), &tmp_key,
+ get_offset (&tmp_key) + get_bytes_number (ih, bh->b_size) - 1);
+
+ if (get_offset (&tmp_key) < get_offset (&ih->ih_key)) {
+ fsck_log ("pass0: block %lu, item %d, %k is wrong - deleted\n",
+ bh->b_blocknr, i, &ih->ih_key);
+ delete_item (fs, bh, i);
+ goto start_again;
+ }
+ }
+ /* temporary ugly fix */
+/*
+ if (i && is_stat_data_ih (ih - 1) && !not_of_one_file (&ih->ih_key, &(ih - 1)->ih_key)) {
+ __u16 mode;
+
+ get_sd_mode (ih - 1, B_I_PITEM (bh, ih - 1), &mode);
+ if (!S_ISREG (mode)) {
+ fsck_log ("pass0: block %lu: mode (%M) of file %K having indirect item is fixed to ",
+ bh->b_blocknr, mode, &ih->ih_key);
+ mode &= ~S_IFMT;
+ mode |= S_IFREG;
+ set_sd_mode (ih - 1, B_I_PITEM (bh, ih - 1), &mode);
+ fsck_log ("(%M)\n", mode);
+ dirty = 1;
+ }
+ }
+*/
ind_item = (__u32 *)B_I_PITEM (bh, ih);
for (j = 0; j < I_UNFM_NUM (ih); j ++) {
unfm_ptr = le32_to_cpu (ind_item [j]);
if (!unfm_ptr)
continue;
-
+#if 0
if (fsck_mode (fs) == FSCK_ZERO_FILES) {
/* FIXME: this is temporary mode of fsck */
ind_item [j] = 0;
@@ -870,11 +1190,14 @@ static void pass0_correct_leaf (reiserfs_filsys_t fs,
dirty = 1;
continue;
}
+#endif
if (not_data_block (fs, unfm_ptr) || /* journal area or bitmap or super block */
- unfm_ptr >= SB_BLOCK_COUNT (fs)) {/* garbage in pointer */
+ unfm_ptr >= get_sb_block_count (fs->fs_ondisk_sb) || /* garbage in pointer */
+ (fs->fs_badblocks_bm && /* bad block */
+ reiserfs_bitmap_test_bit(fs->fs_badblocks_bm, unfm_ptr))) {
- stats (fs)->wrong_pointers ++;
+ pass_0_stat (fs)->wrong_pointers ++;
/*
fsck_log ("pass0: %d-th pointer (%lu) in item %k (leaf block %lu) is wrong\n",
j, unfm_ptr, &ih->ih_key, bh->b_blocknr);
@@ -883,15 +1206,6 @@ static void pass0_correct_leaf (reiserfs_filsys_t fs,
dirty = 1;
continue;
}
-#if 0
- if (!was_block_used (unfm_ptr)) {
- /* this will get to a pool of allocable blocks */
- ind_item [j] = 0;
- dirty = 1;
- stat_wrong_pointer_found (fs);
- continue;
- }
-#endif
/* mark block in bitmaps of unformatted nodes */
register_unfm (unfm_ptr);
}
@@ -899,23 +1213,23 @@ static void pass0_correct_leaf (reiserfs_filsys_t fs,
/* mark all objectids in use */
ih = B_N_PITEM_HEAD (bh, 0);
- for (i = 0; i < node_item_number (bh); i ++, ih ++) {
- mark_objectid_really_used (proper_id_map (fs), le32_to_cpu (ih->ih_key.k_dir_id));
- mark_objectid_really_used (proper_id_map (fs), le32_to_cpu (ih->ih_key.k_objectid));
+ for (i = 0; i < get_blkh_nr_items (B_BLK_HEAD (bh)); i ++, ih ++) {
+ mark_objectid_really_used (proper_id_map (fs), get_key_dirid (&ih->ih_key));
+ mark_objectid_really_used (proper_id_map (fs), get_key_objectid (&ih->ih_key));
}
- if (node_item_number (bh) < 1) {
+ if (get_blkh_nr_items (B_BLK_HEAD (bh)) < 1) {
/* pass 1 will skip this */
- stats(fs)->all_contents_removed ++;
+ pass_0_stat (fs)->all_contents_removed ++;
fsck_log ("pass0: block %lu got all items deleted\n",
bh->b_blocknr);
} else {
/* pass1 will use this bitmap */
pass0_mark_leaf (bh->b_blocknr);
-
+ /*fsck_data (fs)->rebuild.leaves ++;*/
}
if (dirty) {
- stats(fs)->leaves_corrected ++;
+ pass_0_stat (fs)->leaves_corrected ++;
mark_buffer_dirty (bh);
}
}
@@ -925,23 +1239,23 @@ static int is_bad_sd (struct item_head * ih, char * item)
{
struct stat_data * sd = (struct stat_data *)item;
- if (ih->ih_key.u.k_offset_v1.k_offset || ih->ih_key.u.k_offset_v1.k_uniqueness) {
- reiserfs_warning (stderr, "Bad SD? %H\n", ih);
+ if (get_key_offset_v1 (&ih->ih_key) || get_key_uniqueness (&ih->ih_key)) {
+ reiserfs_warning (stderr, "Bad SD? %k\n", &ih->ih_key);
return 1;
}
- if (ih_item_len (ih) == SD_V1_SIZE) {
+ if (get_ih_item_len (ih) == SD_V1_SIZE) {
/* looks like old stat data */
- if (ih_key_format (ih) != KEY_FORMAT_1)
+ if (get_ih_key_format (ih) != KEY_FORMAT_1)
fsck_log ("item %H has wrong format\n", ih);
return 0;
}
- if (!S_ISDIR (sd->sd_mode) && !S_ISREG(sd->sd_mode) &&
- !S_ISCHR (sd->sd_mode) && !S_ISBLK(sd->sd_mode) &&
- !S_ISLNK (sd->sd_mode) && !S_ISFIFO(sd->sd_mode) &&
- !S_ISSOCK(sd->sd_mode)) {
- /*fsck_log ("file %k unexpected mode encountered 0%o\n", &ih->ih_key, sd->sd_mode)*/;
+ if (!S_ISDIR (sd_v2_mode(sd)) && !S_ISREG(sd_v2_mode(sd)) &&
+ !S_ISCHR (sd_v2_mode(sd)) && !S_ISBLK(sd_v2_mode(sd)) &&
+ !S_ISLNK (sd_v2_mode(sd)) && !S_ISFIFO(sd_v2_mode(sd)) &&
+ !S_ISSOCK(sd_v2_mode(sd))) {
+ /*fsck_log ("file %k unexpected mode encountered 0%o\n", &ih->ih_key, sd_v2_mode(sd))*/;
}
return 0;
}
@@ -954,34 +1268,34 @@ int is_bad_directory (struct item_head * ih, char * item, int dev, int blocksize
int namelen, entrylen;
struct reiserfs_de_head * deh = (struct reiserfs_de_head *)item;
__u32 prev_offset = 0;
- __u16 prev_location = ih_item_len (ih);
+ __u16 prev_location = get_ih_item_len (ih);
int min_entry_size = 1;/* we have no way to understand whether the
filesystem were created in 3.6 format or
converted to it. So, we assume that minimal name
length is 1 */
- if (ih_item_len (ih) / (DEH_SIZE + min_entry_size) < ih_entry_count (ih))
+ if (get_ih_item_len (ih) / (DEH_SIZE + min_entry_size) < get_ih_entry_count (ih))
/* entry count is too big */
return 1;
- for (i = 0; i < ih_entry_count (ih); i ++, deh ++) {
+ for (i = 0; i < get_ih_entry_count (ih); i ++, deh ++) {
entrylen = entry_length(ih, deh, i);
if (entrylen > REISERFS_MAX_NAME_LEN (blocksize)) {
return 1;
}
- if (deh_offset (deh) <= prev_offset) {
+ if (get_deh_offset (deh) <= prev_offset) {
return 1;
}
- prev_offset = deh_offset (deh);
+ prev_offset = get_deh_offset (deh);
- if (deh_location(deh) + entrylen != prev_location) {
+ if (get_deh_location(deh) + entrylen != prev_location) {
return 1;
}
- prev_location = deh_location (deh);
+ prev_location = get_deh_location (deh);
- namelen = name_length (ih, deh, i);
+ namelen = name_in_entry_length (ih, deh, i);
name = name_in_entry (deh, i);
- if (!is_properly_hashed (fs, name, namelen, deh_offset (deh))) {
+ if (!is_properly_hashed (fs, name, namelen, get_deh_offset (deh))) {
return 1;
}
}
@@ -994,14 +1308,14 @@ static int is_bad_indirect (struct item_head * ih, char * item, int dev, int blo
{
int i;
int bad = 0;
- int blocks;
+ unsigned long blocks;
- if (ih_item_len(ih) % UNFM_P_SIZE) {
+ if (get_ih_item_len(ih) % UNFM_P_SIZE) {
fsck_log ("is_bad_indirect: indirect item of %H of invalid length\n", ih);
return 1;
}
- blocks = SB_BLOCK_COUNT (fs);
+ blocks = get_sb_block_count (fs->fs_ondisk_sb);
for (i = 0; i < I_UNFM_NUM (ih); i ++) {
__u32 * ind = (__u32 *)item;
@@ -1026,9 +1340,9 @@ int is_bad_item (struct buffer_head * bh, struct item_head * ih, char * item)
dev = bh->b_dev;
// FIXME: refuse transparently bad items
- if (ih->ih_key.k_dir_id == ih->ih_key.k_objectid)
+ if (get_key_dirid (&ih->ih_key) == get_key_objectid (&ih->ih_key))
return 1;
- if (!ih->ih_key.k_dir_id || !ih->ih_key.k_objectid)
+ if (!get_key_dirid (&ih->ih_key) || !get_key_objectid (&ih->ih_key))
return 1;
if (is_stat_data_ih(ih))
@@ -1075,16 +1389,24 @@ int is_leaf_bad (struct buffer_head * bh)
}
-static void go_through (reiserfs_filsys_t fs)
+static int is_to_be_read (reiserfs_filsys_t * fs, unsigned long block)
+{
+ return reiserfs_bitmap_test_bit (fsck_source_bitmap (fs), block);
+}
+
+
+
+static void do_pass_0 (reiserfs_filsys_t * fs)
{
struct buffer_head * bh;
int i;
int what_node;
unsigned long done = 0, total;
+
if (fsck_mode (fs) == DO_TEST) {
/* just to test pass0_correct_leaf */
- bh = bread (fs->s_dev, stats(fs)->test, fs->s_blocksize);
+ bh = bread (fs->fs_dev, fsck_data (fs)->rebuild.test, fs->fs_blocksize);
/*
if (is_leaf_bad (bh)) {
@@ -1104,18 +1426,15 @@ static void go_through (reiserfs_filsys_t fs)
}
- total = reiserfs_bitmap_ones (fsck_disk_bitmap (fs));
- fsck_progress ("\nPass 0 (%lu (of %lu) blocks will be read):\n",
- total, SB_BLOCK_COUNT (fs));
-
-
- for (i = 0; i < SB_BLOCK_COUNT (fs); i ++) {
+ total = reiserfs_bitmap_ones (fsck_source_bitmap (fs));
+
+ for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) {
if (!is_to_be_read (fs, i))
continue;
- print_how_far (&done, total, 1, fsck_quiet (fs));
+ print_how_far (fsck_progress_file (fs), &done, total, 1, fsck_quiet (fs));
- bh = bread (fs->s_dev, i, fs->s_blocksize);
+ bh = bread (fs->fs_dev, i, fs->fs_blocksize);
if (!bh) {
/* we were reading one block at time, and failed, so mark
block bad */
@@ -1123,179 +1442,47 @@ static void go_through (reiserfs_filsys_t fs)
continue;
}
- if (not_data_block (fs, i))
- reiserfs_panic ("not data block found");
+ if (fs->fs_badblocks_bm && reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, i))
+ reiserfs_panic ("%s: Should not read bad block\n", __FUNCTION__);
- stats (fs)->analyzed ++;
- what_node = who_is_this (bh->b_data, fs->s_blocksize);
+ if (not_data_block (fs, i)) {
+ /* blck which could not be pointed by indirect item */
+ if (!(block_of_journal (fs, i) && fsck_data(fs)->rebuild.use_journal_area))
+ reiserfs_panic ("not data block found, %lu", i);
+ }
+
+ pass_0_stat (fs)->dealt_with ++;
+ what_node = who_is_this (bh->b_data, bh->b_size);
if ( what_node != THE_LEAF ) {
brelse (bh);
continue;
}
+
+ pass_0_stat (fs)->leaves ++;
pass0_correct_leaf (fs, bh);
brelse (bh);
}
-
-
-#if 0
- for (i = 0; i < SB_BLOCK_COUNT (fs); i += nr_to_read) {
- to_scan = how_many_to_scan (fs, i, nr_to_read);
- if (to_scan) {
- print_how_far (&done, total, to_scan, fsck_quiet (fs));
-
- /* at least one of nr_to_read blocks is to be checked */
- bbh = bread (fs->s_dev, i / nr_to_read, fs->s_blocksize * nr_to_read);
- if (bbh) {
- for (j = 0; j < nr_to_read; j ++) {
- if (!is_to_be_read (fs, i + j))
- continue;
-
- if (not_data_block (fs, i + j))
- reiserfs_panic ("not data block found");
-
- stats (fs)->analyzed ++;
-
- data = bbh->b_data + j * fs->s_blocksize;
- what_node = who_is_this (data, fs->s_blocksize);
- if ( what_node != THE_LEAF ) {
- continue;
- }
-
- /* the node looks like a leaf, but it still can be
- not perfect */
- bh = make_buffer (fs->s_dev, i + j, fs->s_blocksize, data);
-
- /*printf ("block %lu .. ", bh->b_blocknr);fflush(stdout);*/
- pass0_correct_leaf (fs, bh);
- /*printf ("ok\n");fflush(stdout);*/
-
- brelse (bh);
- }
-
- if (buffer_dirty (bbh))
- bwrite (bbh);
- bforget (bbh);
- } else {
- done -= to_scan;
- /* bread failed */
- if (nr_to_read != 1) {
- /* we tryied to read bunch of blocks. Try to read them by one */
- nr_to_read = 1;
- i --;
- continue;
- } else {
- /* we were reading one block at time, and failed, so mark
- block bad */
- fsck_progress ("pass0: block %lu is bad, marked used\n", i);
- }
- }
- }
-
- if (nr_to_read == 1 && ((i + 1) % NR_TO_READ) == 0) {
- /* we have read NR_TO_READ blocks one at time, switch back to
- reading NR_TO_READ blocks at time */
- i -= (NR_TO_READ - 1);
- nr_to_read = NR_TO_READ;
- }
- }
-#endif
+ fsck_progress ("\n");
/* just in case */
mark_objectid_really_used (proper_id_map (fs), REISERFS_ROOT_OBJECTID);
- fsck_progress ("\n");
-
- if (fsck_save_leaf_bitmap (fs)) {
- reiserfs_bitmap_save (stats (fs)->new_bitmap_file_name, leaves_bitmap);
- }
}
-/* this makes a map of blocks which can be allocated when fsck will continue: */
-static void find_allocable_blocks (reiserfs_filsys_t fs)
-{
- int i;
-
-
- fsck_progress ("Looking for allocable blocks .. ");
- stats (fs)->all_blocks = SB_BLOCK_COUNT (fs);
-
- /* find how many leaves are not pointed by any indirect items */
- for (i = 0; i < SB_BLOCK_COUNT (fs); i ++) {
- if (not_data_block (fs, i))
- continue;
-
-#if 0
- if (!was_block_used (i)) {
- /* marked free in the on-disk bitmap - so it is allocable */
- make_allocable (i);
- stat_allocable_found (fs);
- continue;
- }
-#endif
-
- if (pass0_is_leaf (i)) {
- /* block looks like a reiserfs leaf */
- stats(fs)->leaves ++;
- if (pass0_is_good_unfm (i) || pass0_is_bad_unfm (i))
- /* leaf to which one or more indirect items point to */
- stats(fs)->pointed_leaves ++;
- }
-
- if (pass0_is_good_unfm (i) && pass0_is_bad_unfm (i))
- die ("find_allocable_blocks: bad and good unformatted");
-
- if (pass0_is_good_unfm (i)) {
- /* blocks which were pointed only once */
- stats(fs)->pointed ++;
- stats(fs)->pointed_once ++;
- continue;
- }
- if (pass0_is_bad_unfm (i)) {
- /* blocks pointed more than once */
- stats(fs)->pointed ++;
- stats(fs)->pointed_more_than_once ++;
- continue;
- }
-
- /* blocks which marked used but are not leaves and are not
- pointed (internals in short) get into bitmap of allocable
- blocks */
- if (!pass0_is_leaf (i)) {
- make_allocable (i);
- stats(fs)->allocable ++;
- }
- }
- fsck_progress ("ok\n");
-}
-
-#if 0
-int are_there_used_leaves (unsigned long from, int count)
-{
- int i;
- int used;
-
- used = 0;
- for (i = 0; i < count; i ++) {
- if ((SB_BLOCK_COUNT (fs) > from + i) &&
- pass0_is_leaf (from + i))
- used ++;
- }
- return used;
-}
-#endif
int is_used_leaf (unsigned long block)
{
return pass0_is_leaf (block);
}
-
+/*
int how_many_leaves_were_there (void)
{
- return stats (fs)->leaves;
+ return fsck_data (fs)->rebuild.leaves;
}
+*/
/* these are used to correct uformatted node pointers */
int is_bad_unformatted (unsigned long block)
@@ -1303,6 +1490,12 @@ int is_bad_unformatted (unsigned long block)
return pass0_is_bad_unfm (block);
}
+/* these are used to correct uformatted node pointers */
+int is_good_unformatted (unsigned long block)
+{
+ return pass0_is_good_unfm (block);
+}
+
/* this is for check only. With this we make sure that all pointers we
put into tree on pass 1 do not point to leaves (FIXME), do not
@@ -1322,7 +1515,7 @@ int still_bad_unfm_ptr_1 (unsigned long block)
if (!was_block_used (block))
return 1;
*/
- if (block >= stats (fs)->all_blocks)
+ if (block >= get_sb_block_count (fs->fs_ondisk_sb))
return 1;
return 0;
@@ -1336,7 +1529,7 @@ int still_bad_unfm_ptr_2 (unsigned long block)
return 0;
if (is_block_used (block))
return 1;
- if (block >= stats (fs)->all_blocks)
+ if (block >= get_sb_block_count (fs->fs_ondisk_sb))
return 1;
return 0;
}
@@ -1348,7 +1541,7 @@ int are_there_allocable_blocks (int amout_needed)
if (reiserfs_bitmap_zeros (fsck_allocable_bitmap (fs)) < amout_needed) {
int zeros = 0, i;
- fsck_progress ("Hmm, there are not enough allocable blocks, checking bitmap...");fflush (stdout);
+ fsck_progress ("Hmm, there are not enough allocable blocks, checking bitmap...");
for (i = 0; i < fsck_allocable_bitmap (fs)->bm_bit_size; i ++)
if (!reiserfs_bitmap_test_bit (fsck_allocable_bitmap (fs), i))
zeros ++;
@@ -1377,111 +1570,318 @@ void make_allocable (unsigned long block)
reiserfs_bitmap_clear_bit (fsck_allocable_bitmap (fs), block);
}
-
+/*
unsigned long how_many_uninsertables_were_there (void)
{
- return stats (fs)->uninsertable_leaves;
+ return fsck_data (fs)->rebuild.uninsertable_leaves;
}
unsigned long how_many_items_were_saved (void)
{
- return stats (fs)->saved_on_pass1;
+ return fsck_data (fs)->rebuild.saved_on_pass1;
}
+*/
-
-static void choose_hash_function (reiserfs_filsys_t fs)
+static void choose_hash_function (reiserfs_filsys_t * fs)
{
unsigned long max;
int hash_code;
int i;
+ if (fsck_hash_defined (fs))
+ return;
+
max = 0;
hash_code = func2code (0);
- for (i = 0; i < stats (fs)->hash_amount; i ++) {
+ for (i = 0; i < fsck_data (fs)->rebuild.hash_amount; i ++) {
/* remember hash whihc got more hits */
- if (stats (fs)->hash_hits [i] > max) {
+ if (fsck_data (fs)->rebuild.hash_hits [i] > max) {
hash_code = i;
- max = stats (fs)->hash_hits [i];
+ max = fsck_data (fs)->rebuild.hash_hits [i];
}
- if (stats (fs)->hash_hits [i])
+ if (fsck_data (fs)->rebuild.hash_hits [i])
fsck_log ("%s got %lu hits\n", code2name (i),
- stats (fs)->hash_hits [i]);
+ fsck_data (fs)->rebuild.hash_hits [i]);
}
- if (max == 0) {
+
+ if (max == 0 || hash_code == 0) {
/* no names were found. take either super block value or
default */
- reiserfs_hash (fs) = code2func (rs_hash (fs->s_rs));
- if (!reiserfs_hash (fs))
- reiserfs_hash (fs) = code2func (DEFAULT_HASH);
- return;
+ hash_code = get_sb_hash_code (fs->fs_ondisk_sb);
+ if (!hash_code)
+ hash_code = DEFAULT_HASH;
+ fsck_log ("Could not find hash in use. Using %s\n",
+ code2name (hash_code));
}
-
/* compare the most appropriate hash with the hash set in super block */
- if (hash_code != rs_hash (fs->s_rs)) {
- fsck_progress ("Selected hash (%s) does not match to one set in super block (%s).\n",
- code2name (hash_code), code2name (rs_hash (fs->s_rs)));
- /*
- if (!fsck_user_confirmed (fs, "Overwrite?(Yes)", "Yes", 1)) {
- fsck_progress ("Not confirmed\n");
- exit (4);
- }
- */
- set_hash (fs->s_rs, hash_code);
+ if (hash_code != get_sb_hash_code (fs->fs_ondisk_sb)) {
+ set_sb_hash_code (fs->fs_ondisk_sb, hash_code);
+ fsck_progress ("Selected hash (%s) does not match to one set in super block (%s).\n",
+ code2name (hash_code), code2name (get_sb_hash_code (fs->fs_ondisk_sb)));
} else {
fsck_progress ("\t%s hash is selected\n", code2name (hash_code));
}
-
reiserfs_hash (fs) = code2func (hash_code);
}
-
-int pass_0 (reiserfs_filsys_t fs)
+/* create bitmap of blocks the tree is to be built off */
+/* debugreiserfs and pass0 should share this code -s should show
+the same as we could recover - test: zero first 32M */
+static void init_source_bitmap (reiserfs_filsys_t * fs)
{
- if (fsck_log_file (fs) != stderr)
- /* this is just to separate warnings in the log file */
- fsck_log ("####### Pass 0 #######\n");
+ FILE * fp;
+ unsigned long block_count = get_sb_block_count (fs->fs_ondisk_sb);
+ unsigned long i, j;
+ unsigned long tmp;
+ unsigned long block, reserved, bits_amount;
+
+
+ switch (fsck_data (fs)->rebuild.scan_area) {
+ case ALL_BLOCKS:
+ fsck_source_bitmap (fs) = reiserfs_create_bitmap (block_count);
+ reiserfs_bitmap_fill (fsck_source_bitmap (fs));
+ fsck_progress ("Whole device (%d blocks) is to be scanned\n",
+ reiserfs_bitmap_ones (fsck_source_bitmap (fs)));
+ break;
+
+ case USED_BLOCKS:
+ fsck_progress ("Loading on-disk bitmap .. ");
+ fsck_source_bitmap (fs) = reiserfs_create_bitmap (block_count);
+ reiserfs_bitmap_copy (fsck_source_bitmap (fs), fs->fs_bitmap2);
+
+ fsck_progress ("ok, %d blocks marked used\n",
+ reiserfs_bitmap_ones (fsck_source_bitmap (fs)));
+ break;
+
+ case EXTERN_BITMAP:
+ fp = fopen (fsck_data (fs)->rebuild.bitmap_file_name, "r");
+ if (!fp)
+ reiserfs_panic ("init_bitmap: could not load bitmap: %m\n");
+ fsck_source_bitmap (fs) = reiserfs_bitmap_load (fp);
+ if (!fsck_source_bitmap (fs))
+ reiserfs_panic ("could not load fitmap from \"%s\"",
+ fsck_data (fs)->rebuild.bitmap_file_name);
+ fsck_progress ("%d blocks marked used in extern bitmap\n",
+ reiserfs_bitmap_ones (fsck_source_bitmap (fs)));
+ fclose (fp);
+ break;
+
+ default:
+ reiserfs_panic ("No area to scan specified");
+ }
+
+ tmp = 0;
+
+ /* unmark bitmaps */
+ block = fs->fs_super_bh->b_blocknr + 1;
+
+ reserved = fsck_source_bitmap(fs)->bm_bit_size;
+ for (i = 0; i < get_sb_bmap_nr (fs->fs_ondisk_sb); i ++) {
+ if (!reiserfs_bitmap_test_bit (fsck_source_bitmap (fs), block)) {
+ /* bitmap is definitely broken, mark all blocks of this bitmap block as used */
+
+ bits_amount = (reserved < fs->fs_blocksize * 8) ? reserved : fs->fs_blocksize * 8;
+ fsck_log("%s: bitmap %lu (of %lu bits) is wrong - make all blocks [%lu - %lu] as used\n",
+ __FUNCTION__, i, bits_amount, i * fs->fs_blocksize * 8,
+ fs->fs_blocksize * 8 * i + bits_amount);
+
+ for (j = i * fs->fs_blocksize * 8; j < i * fs->fs_blocksize * 8 + bits_amount; j++) {
+ if (!reiserfs_bitmap_test_bit (fsck_source_bitmap(fs), j))
+ reiserfs_bitmap_set_bit (fsck_source_bitmap(fs), j);
+ }
+ }
+ reiserfs_bitmap_clear_bit (fsck_source_bitmap (fs), block);
+
+ reserved -= fs->fs_blocksize * 8;
+ tmp ++;
+ /* next block fo bitmap */
+ if (spread_bitmaps (fs))
+ block = (block / (fs->fs_blocksize * 8) + 1) * (fs->fs_blocksize * 8);
+ else
+ block ++;
+ }
+
+ /* pass 0 will skip super block and journal areas and bitmap blocks, find
+ how many blocks have to be read */
+ for (i = 0; i <= fs->fs_super_bh->b_blocknr; i ++) {
+ if (!reiserfs_bitmap_test_bit (fsck_source_bitmap (fs), i))
+ continue;
+ reiserfs_bitmap_clear_bit (fsck_source_bitmap (fs), i);
+ tmp ++;
+ }
- if (fsck_mode (fs) == FSCK_ZERO_FILES) {
- reiserfs_bitmap_fill (fsck_new_bitmap (fs));
- fsck_progress ("Zeroing existing files - all blocks marked used\n");
+ /* unmark journal area as used if journal is standard or it is non standard
+ and initialy has been created on a main device */
+
+ reserved = get_size_of_journal_or_reserved_area (fs->fs_ondisk_sb);
+ /* where does journal area (or reserved journal area) start from */
+
+ if (!is_new_sb_location (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) &&
+ !is_old_sb_location (fs->fs_super_bh->b_blocknr, fs->fs_blocksize))
+ die ("init_source_bitmap: wrong super block");
+
+ block = get_journal_start_must (fs);
+
+ for (i = block; i < reserved + block; i ++) {
+ if (!reiserfs_bitmap_test_bit (fsck_source_bitmap (fs), i))
+ continue;
+ reiserfs_bitmap_clear_bit (fsck_source_bitmap (fs), i);
+ tmp ++;
}
+ if (fs->fs_badblocks_bm)
+ for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) {
+ if (reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, i))
+ reiserfs_bitmap_clear_bit (fsck_source_bitmap (fs), i);
+ }
+
+ fsck_source_bitmap (fs)->bm_set_bits = reiserfs_bitmap_ones (fsck_source_bitmap (fs));
+
+ fsck_progress ("Skipping %d blocks (super block, journal, "
+ "bitmaps) %d blocks will be read\n", tmp, fsck_source_bitmap (fs)->bm_set_bits);
+
+}
+
+
+static void before_pass_0 (reiserfs_filsys_t * fs)
+{
+ /* bitmap of blocks to be read */
+ init_source_bitmap (fs);
+
+ /* bitmap of leaves, good and bad unformatted */
make_aux_bitmaps (fs);
+ /* on pass0 all objectids will be marked here as used */
+ proper_id_map (fs) = init_id_map ();
+
/* pass0 gathers statistics about hash hits */
hash_hits_init (fs);
-
- /* scan the partition */
- go_through (fs);
-
- /* find blocks which can be allocated */
- find_allocable_blocks (fs);
-
- if (fsck_mode (fs) == FSCK_ZERO_FILES) {
- /* flush bitmaps and exit */
- fsck_progress ("Zeroing existing files - zeroed %lu blocks\n", tmp_zeroed);
- reiserfs_flush_bitmap (fsck_new_bitmap (fs), fs);
- reiserfs_close (fs);
- exit (0);
- }
+}
+
+
+static void save_pass_0_result (reiserfs_filsys_t * fs)
+{
+ FILE * file;
+ int retval;
+
+ /* save bitmaps with which we will be able start reiserfs from
+ pass 1 */
+ file = open_file ("temp_fsck_file.deleteme", "w+");
+ if (!file)
+ return;
+
+ reiserfs_begin_stage_info_save (file, PASS_0_DONE);
+ reiserfs_bitmap_save (file, leaves_bitmap);
+ reiserfs_bitmap_save (file, good_unfm_bitmap);
+ reiserfs_bitmap_save (file, bad_unfm_bitmap);
+ reiserfs_end_stage_info_save (file);
+ close_file (file);
+ retval = unlink (state_dump_file (fs));
+ retval = rename ("temp_fsck_file.deleteme", state_dump_file (fs));
+ if (retval != 0)
+ fsck_progress ("pass 0: could not rename temp file temp_fsck_file.deleteme to %s",
+ state_dump_file (fs));
+}
+
+
+/* file 'fp' must contain 3 bitmaps saved during last pass 0: bitmap
+ of leaves, bitmaps of good and bad unfms*/
+void load_pass_0_result (FILE * fp, reiserfs_filsys_t * fs)
+{
+ leaves_bitmap = reiserfs_bitmap_load (fp);
+ good_unfm_bitmap = reiserfs_bitmap_load (fp);
+ bad_unfm_bitmap = reiserfs_bitmap_load (fp);
+ if (!leaves_bitmap || !good_unfm_bitmap || !bad_unfm_bitmap)
+ fsck_exit ("State dump file seems corrupted. Run without -d");
+
+ fsck_source_bitmap (fs) = leaves_bitmap;
+
+ /* on pass 1 we do not need proper objectid map */
+
+ fsck_progress ("Pass 0 result loaded. %d leaves, %d/%d good/bad data blocks\n",
+ reiserfs_bitmap_ones (leaves_bitmap),
+ reiserfs_bitmap_ones (good_unfm_bitmap),
+ reiserfs_bitmap_ones (bad_unfm_bitmap));
+}
+static void after_pass_0 (reiserfs_filsys_t * fs)
+{
+ time_t t;
+
+ /* update super block: hash, objectid map, fsck state */
choose_hash_function (fs);
+ flush_objectid_map (proper_id_map (fs), fs);
+ set_sb_fs_state (fs->fs_ondisk_sb, PASS_0_DONE);
+ mark_buffer_dirty (fs->fs_super_bh);
+
+ /* write all dirty blocks */
+ fsck_progress ("Flushing..");
+ fs->fs_dirt = 1;
+ reiserfs_flush (fs);
+ fsck_progress ("done\n");
stage_report (0, fs);
- return 0;
+
+ /* free what we do not need anymore */
+ reiserfs_delete_bitmap (fsck_source_bitmap (fs));
+ fsck_source_bitmap (fs) = 0;
+
+ if (!fsck_run_one_step (fs)) {
+ if (fsck_user_confirmed (fs, "Continue? (Yes):", "Yes\n", 1)) {
+ /* reiserfsck continues */
+ fsck_source_bitmap (fs) = leaves_bitmap;
+ return;
+ }
+ } else
+ save_pass_0_result (fs);
+
+ free_id_map (proper_id_map (fs));
+ proper_id_map (fs) = 0;
+
+ time (&t);
+ fsck_progress ("###########\n"
+ "reiserfsck finished pass 0 at %s"
+ "###########\n", ctime (&t));
+ fs->fs_dirt = 1;
+ reiserfs_close (fs);
+ exit (4);
+}
+
+
+void pass_0 (reiserfs_filsys_t * fs)
+{
+ if (get_reiserfs_format (fs->fs_ondisk_sb) != fs->fs_format ||
+ get_reiserfs_format (fs->fs_ondisk_sb) == REISERFS_FORMAT_UNKNOWN)
+ reiserfs_panic ("pass 0: version mismatch found, you should run --rebuild-sb");
+
+ fsck_progress ("\nPass 0:\n");
+ if (fsck_log_file (fs) != stderr)
+ /* this is just to separate warnings in the log file */
+ fsck_log ("####### Pass 0 #######\n");
+
+
+ before_pass_0 (fs);
+
+ /* scan the partition, find leaves and correct them */
+ do_pass_0 (fs);
+
+ after_pass_0 (fs);
}
+
+
+
#if 0
/* node looks like a leaf (block head and ih_item_length & ih_location
of item_head array are correct. This function recovers (tries to) node's key
table and directory items. */
-static void recover_leaf (reiserfs_filsys_t fs, struct buffer_head * bh)
+static void recover_leaf (reiserfs_filsys_t * fs, struct buffer_head * bh)
{
int i;
struct item_head * ih;
diff --git a/fsck/pass1.c b/fsck/pass1.c
index d6b29e9..58fc609 100644
--- a/fsck/pass1.c
+++ b/fsck/pass1.c
@@ -1,17 +1,17 @@
/*
- * Copyright 1996-1999 Hans Reiser
+ * Copyright 1996-2002 Hans Reiser
*/
#include "fsck.h"
#include <stdlib.h>
+reiserfs_bitmap_t * bad_unfm_in_tree_once_bitmap;
-reiserfs_bitmap_t bad_unfm_in_tree_once_bitmap;
//int step = 0; // 0 - find stat_data or any item ; 1 - find item ; 2 - already found
/* allocates buffer head and copy buffer content */
-struct buffer_head * make_buffer (int dev, int blocknr, int size, char * data)
+struct buffer_head * make_buffer (int dev, unsigned long blocknr, int size, char * data)
{
struct buffer_head * bh;
@@ -27,11 +27,11 @@ struct buffer_head * make_buffer (int dev, int blocknr, int size, char * data)
int find_not_of_one_file(struct key * to_find, struct key * key)
{
- if ((to_find->k_objectid != -1) &&
- (to_find->k_objectid != key->k_objectid))
+ if ((get_key_objectid (to_find) != -1) &&
+ (get_key_objectid (to_find) != get_key_objectid (key)))
return 1;
- if ((to_find->k_dir_id != -1) &&
- (to_find->k_dir_id != key->k_dir_id))
+ if ((get_key_dirid (to_find) != -1) &&
+ (get_key_dirid (to_find) != get_key_dirid (key)))
return 1;
return 0;
}
@@ -45,27 +45,27 @@ int is_item_reachable (struct item_head * ih)
void mark_item_unreachable (struct item_head * ih)
{
+ clean_ih_flags (ih);
mark_ih_unreachable (ih);
if (is_indirect_ih (ih))
- set_free_space (ih, 0);
+ set_ih_free_space (ih, 0);
}
void mark_item_reachable (struct item_head * ih, struct buffer_head * bh)
{
- mark_ih_ok (ih);
+ mark_ih_reachable (ih);
mark_buffer_dirty (bh);
}
-
static void stat_data_in_tree (struct buffer_head *bh,
struct item_head * ih)
{
#if 0
__u32 objectid;
- objectid = le32_to_cpu (ih->ih_key.k_objectid);
+ objectid = get_key_objectid (&ih->ih_key);
if (mark_objectid_really_used (proper_id_map (fs), objectid)) {
stat_shared_objectid_found (fs);
@@ -84,7 +84,7 @@ static void indirect_in_tree (struct buffer_head * bh,
{
int i;
__u32 * unp;
- unsigned long unfm_ptr;
+ __u32 unfm_ptr;
unp = (__u32 *)B_I_PITEM (bh, ih);
@@ -92,13 +92,12 @@ static void indirect_in_tree (struct buffer_head * bh,
unfm_ptr = le32_to_cpu (unp[i]);
if (unfm_ptr == 0)
continue;
-
if (still_bad_unfm_ptr_1 (unfm_ptr))
reiserfs_panic ("mark_unformatted_used: (%lu: %k) "
"still has bad pointer %lu",
bh->b_blocknr, &ih->ih_key, unfm_ptr);
- mark_block_used (unfm_ptr);
+ mark_block_used (unfm_ptr, 1);
}
}
@@ -107,11 +106,11 @@ static void leaf_is_in_tree_now (struct buffer_head * bh)
{
item_action_t actions[] = {stat_data_in_tree, indirect_in_tree, 0, 0};
- mark_block_used ((bh)->b_blocknr);
+ mark_block_used ((bh)->b_blocknr, 1);
for_every_item (bh, mark_item_unreachable, actions);
- stats(fs)->inserted_leaves ++;
+ pass_1_stat (fs)->inserted_leaves ++;
mark_buffer_dirty (bh);
}
@@ -194,18 +193,18 @@ int balance_condition_2_fails (struct buffer_head * new, struct path * path)
call search_by_key, which will read right neighbor as well */
INITIALIZE_PATH(path_to_right_neighbor);
- if (usearch_by_key (fs, right_dkey, &path_to_right_neighbor) != ITEM_FOUND)
+ if (reiserfs_search_by_key_4 (fs, right_dkey, &path_to_right_neighbor) != ITEM_FOUND)
die ("get_right_neighbor_free_space: invalid right delimiting key");
used_space = B_CHILD_SIZE (PATH_PLAST_BUFFER (&path_to_right_neighbor));
pathrelse (&path_to_right_neighbor);
}
else
- used_space = B_N_CHILD (bh, pos + 1)->dc_size;
+ used_space = get_dc_child_size (B_N_CHILD (bh, pos + 1));
if (B_FREE_SPACE (new) >= used_space -
(are_items_mergeable (B_N_PITEM_HEAD (new, B_NR_ITEMS (new) - 1), (struct item_head *)right_dkey, new->b_size) ? IH_SIZE : 0))
return 1;
-
+
return 0;
}
@@ -218,32 +217,28 @@ static void get_max_buffer_key (struct buffer_head * bh, struct key * key)
copy_key (key, &(ih->ih_key));
if (is_direntry_key (key)) {
- /* copy 3-rd and 4-th key components of the last entry */
- //set_le_key_k_offset (ih_version(ih), key, B_I_DEH (bh, ih)[I_ENTRY_COUNT (ih) - 1].deh_offset);
- //set_le_key_k_type (ih_version(ih), key, TYPE_DIRENTRY);
+ /* copy deh_offset 3-rd and 4-th key components of the last entry */
set_offset (KEY_FORMAT_1, key,
- le32_to_cpu (B_I_DEH (bh, ih)[ih_entry_count (ih) - 1].deh_offset));
+ get_deh_offset (B_I_DEH (bh, ih) + get_ih_entry_count (ih) - 1));
} else if (!is_stat_data_key (key))
/* get key of the last byte, which is contained in the item */
set_offset (key_format (key), key, get_offset (key) + get_bytes_number (ih, bh->b_size) - 1);
- //set_le_key_k_offset(ih_version(ih), key,
- // le_key_k_offset(ih_version(ih), key) + get_bytes_number (bh, ih, 0, CHECK_FREE_BYTES) - 1 );
}
-static int tree_is_empty (void)
+int tree_is_empty (void)
{
- return (SB_ROOT_BLOCK (fs) == ~0) ? 1 : 0;
+ return (get_sb_root_block (fs->fs_ondisk_sb) == ~0) ? 1 : 0;
}
-static void make_single_leaf_tree (struct buffer_head * bh)
+void make_single_leaf_tree (struct buffer_head * bh)
{
/* tree is empty, make tree root */
- set_root_block (fs->s_rs, bh->b_blocknr);
- set_tree_height (fs->s_rs, 2);
- mark_buffer_dirty (fs->s_sbh);
+ set_sb_root_block (fs->fs_ondisk_sb, bh->b_blocknr);
+ set_sb_tree_height (fs->fs_ondisk_sb, 2);
+ mark_buffer_dirty (fs->fs_super_bh);
leaf_is_in_tree_now (bh);
}
@@ -263,11 +258,10 @@ static void try_to_insert_pointer_to_leaf (struct buffer_head * new_bh)
return;
}
-
first_bh_key = B_N_PKEY (new_bh, 0);
/* try to find place in the tree for the first key of the coming node */
- ret_value = usearch_by_key (fs, first_bh_key, &path);
+ ret_value = reiserfs_search_by_key_4 (fs, first_bh_key, &path);
if (ret_value == ITEM_FOUND)
goto cannot_insert;
@@ -299,14 +293,14 @@ static void try_to_insert_pointer_to_leaf (struct buffer_head * new_bh)
if (balance_condition_2_fails (new_bh, &path))
goto cannot_insert;
-
+
+
insert:
insert_pointer (new_bh, &path);
goto out;
cannot_insert:
/* statistic */
- stats (fs)->uninsertable_leaves ++;
mark_block_uninsertable (new_bh->b_blocknr);
@@ -324,7 +318,7 @@ static void try_to_insert_pointer_to_leaf (struct buffer_head * new_bh)
3. what we should do with directory entries hashed by another hash?
they are deleted for now
*/
-static void pass1_correct_leaf (reiserfs_filsys_t s,
+static void pass1_correct_leaf (reiserfs_filsys_t * fs,
struct buffer_head * bh)
{
int i, j;
@@ -343,9 +337,9 @@ static void pass1_correct_leaf (reiserfs_filsys_t s,
int hash_code;
deh = B_I_DEH (bh, ih);
- for (j = 0; j < ih_entry_count (ih); j ++) {
+ for (j = 0; j < get_ih_entry_count (ih); j ++) {
name = name_in_entry (deh + j, j);
- name_len = name_length (ih, deh + j, j);
+ name_len = name_in_entry_length (ih, deh + j, j);
if ((j == 0 && is_dot (name, name_len)) ||
(j == 1 && is_dot_dot (name, name_len))) {
@@ -353,14 +347,14 @@ static void pass1_correct_leaf (reiserfs_filsys_t s,
}
hash_code = find_hash_in_use (name, name_len,
- GET_HASH_VALUE (deh_offset (deh + j)),
- rs_hash (fs->s_rs));
- if (hash_code != rs_hash (fs->s_rs)) {
+ GET_HASH_VALUE (get_deh_offset (deh + j)),
+ get_sb_hash_code (fs->fs_ondisk_sb));
+ if (hash_code != get_sb_hash_code (fs->fs_ondisk_sb)) {
fsck_log ("pass1: block %lu, %H, entry \"%.*s\" "
"hashed with %s whereas proper hash is %s\n",
bh->b_blocknr, ih, name_len, name,
- code2name (hash_code), code2name (rs_hash (fs->s_rs)));
- if (ih_entry_count (ih) == 1) {
+ code2name (hash_code), code2name (get_sb_hash_code (fs->fs_ondisk_sb)));
+ if (get_ih_entry_count (ih) == 1) {
delete_item (fs, bh, i);
i --;
ih --;
@@ -389,7 +383,7 @@ static void pass1_correct_leaf (reiserfs_filsys_t s,
continue;
/* this corruption of indirect item had to be fixed in pass0 */
- if (not_data_block (s, unfm_ptr) || unfm_ptr >= SB_BLOCK_COUNT (s))
+ if (not_data_block (fs, unfm_ptr) || unfm_ptr >= get_sb_block_count (fs->fs_ondisk_sb))
/*!was_block_used (unfm_ptr))*/
reiserfs_panic ("pass1_correct_leaf: (%lu: %k), %d-th slot is not fixed",
bh->b_blocknr, &ih->ih_key, j);
@@ -398,7 +392,7 @@ static void pass1_correct_leaf (reiserfs_filsys_t s,
if (is_used_leaf (unfm_ptr)) {
dirty ++;
*ind_item = 0;
- stats(fs)->wrong_pointers ++;
+ pass_1_stat (fs)->pointed_leaves ++;
continue;
}
@@ -410,13 +404,14 @@ static void pass1_correct_leaf (reiserfs_filsys_t s,
special bitmap */
mark_bad_unfm_in_tree_once (unfm_ptr);
else {
- /* Yes, we have seen this pointer already, zero other pointers to it */
+ /* Yes, we have seen this pointer already, zero other pointers to it. */
dirty ++;
*ind_item = 0;
- stats(fs)->wrong_pointers ++;
+ pass_1_stat (fs)->non_unique_pointers ++;
continue;
}
- }
+ } else
+ pass_1_stat (fs)->correct_pointers ++;
}
}
@@ -437,16 +432,16 @@ void save_item (struct si ** head, struct buffer_head * bh, struct item_head * i
}
if (is_indirect_ih (ih)) {
- fsck_progress ("save_item: %H (should not happen)\n", ih);
+ fsck_progress ("save_item (block %lu: %H (should not happen)\n", ih);
}
- stats(fs)->saved_on_pass1 ++;
+ pass_1_stat (fs)->saved_items ++;
si = getmem (sizeof (*si));
- si->si_dnm_data = getmem (ih_item_len(ih));
+ si->si_dnm_data = getmem (get_ih_item_len(ih));
/*si->si_blocknr = blocknr;*/
memcpy (&(si->si_ih), ih, IH_SIZE);
- memcpy (si->si_dnm_data, item, ih_item_len(ih));
+ memcpy (si->si_dnm_data, item, get_ih_item_len(ih));
// changed by XB
si->last_known = NULL;
@@ -483,6 +478,17 @@ void save_item (struct si ** head, struct buffer_head * bh, struct item_head * i
}
+struct si * remove_saved_item (struct si * si)
+{
+ struct si * tmp = si->si_next;
+
+ freemem (si->si_dnm_data);
+ freemem (si);
+ return tmp;
+}
+
+
+#if 0
static void save_items (struct si ** head, struct buffer_head * bh)
{
int i;
@@ -494,17 +500,6 @@ static void save_items (struct si ** head, struct buffer_head * bh)
}
}
-
-struct si * remove_saved_item (struct si * si)
-{
- struct si * tmp = si->si_next;
-
- freemem (si->si_dnm_data);
- freemem (si);
- return tmp;
-}
-
-
/* insert_item_separately */
static void put_saved_items_into_tree_1 (struct si * si)
{
@@ -514,38 +509,222 @@ static void put_saved_items_into_tree_1 (struct si * si)
si = remove_saved_item (si);
}
}
+#endif
+
+
+/* fsck starts creating of this bitmap on pass 1. It will then become
+ on-disk bitmap */
+static void init_new_bitmap (reiserfs_filsys_t * fs)
+{
+ int i;
+ unsigned long block;
+ unsigned long reserved;
+
+
+ fsck_new_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb));
+
+ /* mark_block_used skips 0, set the bit explicitly */
+ reiserfs_bitmap_set_bit (fsck_new_bitmap (fs), 0);
+
+ /* mark other skipped blocks and super block used */
+ for (i = 1; i <= fs->fs_super_bh->b_blocknr; i ++)
+ mark_block_used (i, 1);
+
+ /* mark bitmap blocks as used */
+ block = fs->fs_super_bh->b_blocknr + 1;
+ for (i = 0; i < get_sb_bmap_nr (fs->fs_ondisk_sb); i ++) {
+ mark_block_used (block, 1);
+ if (spread_bitmaps (fs))
+ block = (block / (fs->fs_blocksize * 8) + 1) * (fs->fs_blocksize * 8);
+ else
+ block ++;
+ }
+
+ reserved = get_size_of_journal_or_reserved_area (fs->fs_ondisk_sb);
+ /* where does journal area (or reserved journal area) start from */
+
+ if (!is_new_sb_location (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) &&
+ !is_old_sb_location (fs->fs_super_bh->b_blocknr, fs->fs_blocksize))
+ die ("init_new_bitmap: wrong super block");
+
+ block = get_journal_start_must (fs);
+
+ for (i = block; i < reserved + block; i ++)
+ mark_block_used (i, 1);
+
+
+ if (fs->fs_badblocks_bm)
+ for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) {
+ if (reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, i)) {
+ if (reiserfs_bitmap_test_bit (fsck_new_bitmap (fs), i))
+ reiserfs_panic ("%s: bad block pointer to not data area, cannot happen\n",
+ __FUNCTION__);
+ reiserfs_bitmap_set_bit (fsck_new_bitmap (fs), i);
+ }
+ }
+
+#if 0
+ /* mark journal area as used if journal is standard or it is non standard
+ and initialy has been created on a main device */
+ reserved = 0;
+ if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb))
+ reserved = get_jp_journal_size (sb_jp (fs->fs_ondisk_sb));
+ if (get_sb_reserved_for_journal (fs->fs_ondisk_sb))
+ reserved = get_sb_reserved_for_journal (fs->fs_ondisk_sb);
+ if (reserved) {
+ for (i = 0; i <= reserved; i ++)
+ mark_block_used (i + get_jp_journal_1st_block (sb_jp
+ (fs->fs_ondisk_sb)));
+ }
+#endif
+}
+
+
+/* this makes a map of blocks which can be allocated when fsck will
+ continue */
+static void find_allocable_blocks (reiserfs_filsys_t * fs)
+{
+ int i;
+
+ fsck_progress ("Looking for allocable blocks .. ");
+
+ fsck_allocable_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb));
+ reiserfs_bitmap_fill (fsck_allocable_bitmap (fs));
+
+
+ /* find how many leaves are not pointed by any indirect items */
+ for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) {
+ if (not_data_block (fs, i))
+ /* journal (or reserved for it area), bitmaps, super block and
+ blocks before it */
+ continue;
+
+ if (is_good_unformatted (i) && is_bad_unformatted (i))
+ die ("find_allocable_blocks: bad and good unformatted");
+
+ if (is_good_unformatted (i) || is_bad_unformatted (i)) {
+ /* blocks which were pointed once or more thn onec from indirect
+ items - they will not be allocated */
+ continue;
+ }
+
+ /* make allocable not leaves, not bad blocks */
+ if (!is_used_leaf (i) &&
+ (!fs->fs_badblocks_bm || !reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, i))) {
+ /* this is not leaf and it is not pointed by found indirect items,
+ so it does not contains anything valuable */
+ make_allocable (i);
+ pass_1_stat (fs)->allocable_blocks ++;
+ }
+ }
+ fsck_progress ("ok\n");
+
+ fs->block_allocator = reiserfsck_reiserfs_new_blocknrs;
+ fs->block_deallocator = reiserfsck_reiserfs_free_block;
+}
+
+
+static void before_pass_1 (reiserfs_filsys_t * fs)
+{
+ /* this will become an on-disk bitmap */
+ init_new_bitmap (fs);
+
+ /* bitmap of leaves which could not be inserted on pass 1. FIXME:
+ no need to have 1 bit per block */
+ fsck_uninsertables (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb));
+ reiserfs_bitmap_fill (fsck_uninsertables (fs));
+
+ /* find blocks which can be allocated */
+ find_allocable_blocks (fs);
+
+ /* bitmap of bad unformatted nodes which are in the tree already */
+ bad_unfm_in_tree_once_bitmap = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb));
+
+ /* pass 1 does not deal with objectid */
+}
+
+
+static void save_pass_1_result (reiserfs_filsys_t * fs)
+{
+ FILE * file;
+ int retval;
+
+ file = open_file("temp_fsck_file.deleteme", "w+");
+ if (!file)
+ return;
+
+ /* to be able to get a new bitmap on pass2 we should flush it on disk
+ new_bitmap should not be flushed on disk if run w/out -d option, as
+ if fsck fails on pass1 we get wrong bitmap on the next fsck start */
+ reiserfs_flush_to_ondisk_bitmap (fsck_new_bitmap (fs), fs);
+
+ /* to be able to restart with pass 2 we need bitmap of
+ uninsertable blocks and bitmap of alocable blocks */
+ reiserfs_begin_stage_info_save(file, PASS_1_DONE);
+ reiserfs_bitmap_save (file, fsck_uninsertables (fs));
+ reiserfs_bitmap_save (file, fsck_allocable_bitmap(fs));
+ reiserfs_end_stage_info_save (file);
+ close_file (file);
+ retval = unlink (state_dump_file (fs));
+ retval = rename ("temp_fsck_file.deleteme", state_dump_file (fs));
+ if (retval != 0)
+ fsck_progress ("pass 1: could not rename temp file temp_fsck_file.deleteme to %s",
+ state_dump_file (fs));
+}
+
+
+void load_pass_1_result (FILE * fp, reiserfs_filsys_t * fs)
+{
+ fsck_new_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb));
+ reiserfs_bitmap_copy (fsck_new_bitmap (fs), fs->fs_bitmap2);
+
+ fsck_uninsertables (fs) = reiserfs_bitmap_load (fp);
+ fsck_allocable_bitmap (fs) = reiserfs_bitmap_load (fp);
+
+ fs->block_allocator = reiserfsck_reiserfs_new_blocknrs;
+ fs->block_deallocator = reiserfsck_reiserfs_free_block;
+
+ if (!fsck_new_bitmap (fs) || !fsck_allocable_bitmap (fs) ||
+ !fsck_allocable_bitmap (fs))
+ fsck_exit ("State dump file seems corrupted. Run without -d");
+
+
+ /* we need objectid map on pass 2 to be able to relocate files */
+ proper_id_map (fs) = init_id_map ();
+ fetch_objectid_map (proper_id_map (fs), fs);
+
+ fsck_progress ("Pass 1 result loaded. %d blocks used, %d allocable, "
+ "still to be inserted %d\n",
+ reiserfs_bitmap_ones (fsck_new_bitmap (fs)),
+ reiserfs_bitmap_zeros (fsck_allocable_bitmap (fs)),
+ reiserfs_bitmap_zeros (fsck_uninsertables (fs)));
+}
+
+extern reiserfs_bitmap_t * leaves_bitmap;
-/* reads the device by set of 8 blocks, takes leaves and tries to
- insert them into tree */
-void pass_1_pass_2_build_the_tree (void)
+/* reads blocks marked in leaves_bitmap and tries to insert them into
+ tree */
+static void do_pass_1 (reiserfs_filsys_t * fs)
{
struct buffer_head * bh;
int i;
int what_node;
unsigned long done = 0, total;
- struct si * saved_items = 0;
-
- if (fsck_log_file (fs) != stderr)
- fsck_log ("####### Pass 1 #######\n");
-
- bad_unfm_in_tree_once_bitmap = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
/* on pass0 we have found that amount of leaves */
- total = how_many_leaves_were_there ();
-
- fsck_progress ("\nPass1:\n");
+ total = reiserfs_bitmap_ones (leaves_bitmap);
/* read all leaves found on the pass 0 */
- for (i = 0; i < SB_BLOCK_COUNT (fs); i ++) {
+ for (i = 0; i < get_sb_block_count (fs->fs_ondisk_sb); i ++) {
if (!is_used_leaf (i))
continue;
- print_how_far (&done, total, 1, fsck_quiet (fs));
+ print_how_far (fsck_progress_file (fs), &done, total, 1, fsck_quiet (fs));
/* at least one of nr_to_read blocks is to be checked */
- bh = bread (fs->s_dev, i, fs->s_blocksize);
+ bh = bread (fs->fs_dev, i, fs->fs_blocksize);
if (!bh) {
/* we were reading one block at time, and failed, so mark
block bad */
@@ -553,7 +732,7 @@ void pass_1_pass_2_build_the_tree (void)
continue;
}
- what_node = who_is_this (bh->b_data, fs->s_blocksize);
+ what_node = who_is_this (bh->b_data, bh->b_size);
if ( what_node != THE_LEAF ) {
fsck_progress ("build_the_tree: nothing but leaves are expected. "
"Block %lu - %s\n", i,
@@ -562,18 +741,19 @@ void pass_1_pass_2_build_the_tree (void)
continue;
}
- if (is_block_used (i))
+ if (is_block_used (i) && !(block_of_journal (fs, i) &&
+ fsck_data(fs)->rebuild.use_journal_area))
/* block is in new tree already */
- die ("build_the_tree: leaf (%lu) is in tree already\n", i);
+ die ("build_the_tree: leaf (%u) is in tree already\n", i);
/* fprintf (block_list, "leaf %d\n", i + j);*/
- stats(fs)->analyzed ++;
+ pass_1_stat (fs)->leaves ++;
/* the leaf may still contain indirect items with wrong
slots. Fix that */
pass1_correct_leaf (fs, bh);
- if (node_item_number (bh) == 0) {
+ if (get_blkh_nr_items (B_BLK_HEAD (bh)) == 0) {
/* all items were deleted on pass 0 or pass 1 */
mark_buffer_clean (bh);
brelse (bh);
@@ -586,8 +766,34 @@ void pass_1_pass_2_build_the_tree (void)
/* Save good items only to put them into tree at the
end of this pass */
- save_items (&saved_items, bh);
+ //save_items (&saved_items, bh);
+ mark_block_uninsertable (bh->b_blocknr);
+ brelse (bh);
+ continue;
+ }
+
+ if (block_of_journal (fs, i) && fsck_data(fs)->rebuild.use_journal_area) {
+ /* FIXME: temporary thing */
+ if (tree_is_empty ()) {
+ /* we insert inot tree only first leaf of journal */
+ unsigned long block;
+ struct buffer_head * new_bh;
+
+ block = alloc_block ();
+ if (!block)
+ die ("could not allocate block");
+ new_bh = getblk (bh->b_dev, block, bh->b_size);
+ memcpy (new_bh->b_data, bh->b_data, bh->b_size);
+ mark_buffer_uptodate (new_bh, 1);
+ mark_buffer_dirty (new_bh);
+ make_single_leaf_tree (new_bh);
+ brelse (new_bh);
+ brelse (bh);
+ continue;
+ }
+ /* other blocks of journal will be inserted in pass 2 */
+ mark_block_uninsertable (bh->b_blocknr);
brelse (bh);
continue;
}
@@ -596,131 +802,76 @@ void pass_1_pass_2_build_the_tree (void)
brelse (bh);
}
+ fsck_progress ("\n");
-#if 0
- /* read all leaves found on the pass 0 */
- for (i = 0; i < SB_BLOCK_COUNT (fs); i += nr_to_read) {
- to_scan = how_many_to_scan (fs, i, nr_to_read);
- if (to_scan) {
- print_how_far (&done, total, to_scan, fsck_quiet (fs));
-
- /* at least one of nr_to_read blocks is to be checked */
- bbh = bread (fs->s_dev, i / nr_to_read, fs->s_blocksize * nr_to_read);
- if (bbh) {
- for (j = 0; j < nr_to_read; j ++) {
- if (!is_used_leaf (i + j))
- continue;
-
- data = bbh->b_data + j * fs->s_blocksize;
-
- what_node = who_is_this (data, fs->s_blocksize);
- if ( what_node != THE_LEAF ) {
- fsck_progress ("build_the_tree: nothing but leaves are expected. "
- "Block %lu - %s\n", i + j,
- (what_node == THE_INTERNAL) ? "internal" : "??");
- continue;
- }
-
- if (is_block_used (i + j))
- /* block is in new tree already */
- die ("build_the_tree: leaf (%lu) is in tree already\n",
- i + j);
-
- /* fprintf (block_list, "leaf %d\n", i + j);*/
-
- bh = make_buffer (fs->s_dev, i + j, fs->s_blocksize, data);
- stats(fs)->analyzed ++;
-
- /* the leaf may still contain indirect items with wrong
- slots. Fix that */
- pass1_correct_leaf (fs, bh);
-
- if (node_item_number (bh) == 0) {
- /* all items were deleted on pass 0 or pass 1 */
- mark_buffer_clean (bh);
- brelse (bh);
- continue;
- }
+}
- if (is_leaf_bad (bh)) {
- /* FIXME: will die */
- fsck_log ("pass1: (is_leaf_bad) bad leaf (%lu)\n", bh->b_blocknr);
- /* Save good items only to put them into tree at the
- end of this pass */
- save_items (&saved_items, bh);
+static void after_pass_1 (reiserfs_filsys_t * fs)
+{
+ time_t t;
- brelse (bh);
- continue;
- }
-
- try_to_insert_pointer_to_leaf (bh);
- brelse (bh);
- }
+ /* update fsck_state */
+
+ /* we should not flush bitmaps on disk after pass1, because
+ new_bitmap contains only those blocks which are good leaves or
+ just allocated internal blocks. */
+
+ set_sb_fs_state (fs->fs_ondisk_sb, PASS_1_DONE);
+ mark_buffer_dirty (fs->fs_super_bh);
+
+ /* write all dirty blocks */
+ fsck_progress ("Flushing..");
+ fs->fs_dirt = 1;
+ reiserfs_flush (fs);
+ fsck_progress ("done\n");
- bforget (bbh);
- } else {
- done -= to_scan;
+ stage_report (1, fs);
- /* bread failed */
- if (nr_to_read != 1) {
- /* we tryied to read bunch of blocks. Try to read them by one */
- nr_to_read = 1;
- i --;
- continue;
- } else {
- /* we were reading one block at time, and failed, so mark
- block bad */
- fsck_progress ("pass0: block %lu is bad, marked used\n", i);
- }
- }
- }
+ /* we do not need this anymore */
+ delete_aux_bitmaps ();
+ reiserfs_delete_bitmap (bad_unfm_in_tree_once_bitmap);
- if (nr_to_read == 1 && ((i + 1) % NR_TO_READ) == 0) {
- /* we have read NR_TO_READ blocks one at time, switch back to
- reading NR_TO_READ blocks at time */
- i -= (NR_TO_READ - 1);
- nr_to_read = NR_TO_READ;
- }
- }
-#endif
- fsck_progress ("\n");
+ if (!fsck_run_one_step (fs)) {
+ if (fsck_user_confirmed (fs, "Continue? (Yes):", "Yes\n", 1))
+ /* reiserfsck continues */
+ return;
+ } else
+ save_pass_1_result (fs);
- /* Pass 1a (this should die) */
-
- /* put saved items into tree. These items were in leaves, those could not
- be inserted into tree because some indirect items point to those
- leaves. Rather than lookup for corresponding unfm pointers in the tree,
- we save items of those leaves and put them into tree separately */
- if (how_many_items_were_saved ()) {
- fsck_progress ("There were %lu saved items\nPass 1a - ",
- how_many_items_were_saved ());
- fflush (stdout);
- put_saved_items_into_tree_1 (saved_items);
+ if (proper_id_map (fs)) {
+ /* when we run pass 1 only - we do not have proper_id_map */
+ free_id_map (proper_id_map (fs));
+ proper_id_map (fs) = 0;
}
+
+ time (&t);
+ fsck_progress ("###########\n"
+ "reiserfsck finished pass 1 at %s"
+ "###########\n", ctime (&t));
+ fs->fs_dirt = 1;
+ reiserfs_close (fs);
+ exit (4);
+}
- stage_report (1, fs);
- /* end of pass 1 */
-
-
- if (SB_ROOT_BLOCK(fs) == -1)
- die ("\n\nNo reiserfs metadata found");
-
- /* pass 2 */
- pass_2_take_bad_blocks_put_into_tree ();
- flush_buffers ();
+void pass_1 (reiserfs_filsys_t * fs)
+{
+ fsck_progress ("\nPass 1 (will try to insert %lu leaves):\n",
+ reiserfs_bitmap_ones (fsck_source_bitmap (fs)));
+ if (fsck_log_file (fs) != stderr)
+ fsck_log ("####### Pass 1 #######\n");
- stage_report (2, fs);
- fsck_progress ("Tree is built. Checking it - "); fflush (stdout);
- reiserfsck_check_pass1 ();
- fsck_progress ("done\n"); fflush (stdout);
+ before_pass_1 (fs);
- reiserfs_delete_bitmap (bad_unfm_in_tree_once_bitmap);
+ /* try to insert leaves found during pass 0 */
+ do_pass_1 (fs);
+ after_pass_1 (fs);
}
+
#if 0
/* pass the S+ tree of filesystem */
@@ -730,152 +881,3 @@ void recover_internal_tree (struct super_block * s)
build_the_tree();
}
#endif
-
-
-void rebuild_sb (reiserfs_filsys_t fs)
-{
- int version;
- struct buffer_head * bh;
- struct reiserfs_super_block * rs;
- __u32 blocks;
-
-
- if (no_reiserfs_found (fs)) {
- char * answer = 0;
- size_t n = 0;
- printf("\nwhat is version of ReiserFS you use[1-4]\n"
- "\t(1) 3.6.x\n"
- "\t(2) >=3.5.9\n"
- "\t(3) < 3.5.9 converted to new format\n"
- "\t(4) < 3.5.9\n"
- "\t(X) exit\n");
- getline (&answer, &n, stdin);
- version = atoi (answer);
- if (version < 1 || version > 4)
- die ("rebuild_sb: wrong version");
-
- fs->s_blocksize = 4096;
-
- switch(version){
- case 1:
- case 2:
- bh = getblk (fs->s_dev, (REISERFS_DISK_OFFSET_IN_BYTES / fs->s_blocksize),
- fs->s_blocksize);
- break;
- case 3:
- case 4:
- bh = getblk (fs->s_dev, (2), fs->s_blocksize);
- break;
- default:
- exit(0);
- }
- if (!bh)
- die ("rebuild_sb: can't bread");
- rs = (struct reiserfs_super_block *)bh->b_data;
- fs->s_rs = rs;
- }
- else
- {
- /* reiserfs super block is found */
- version = check_sb(fs);
- if (!user_confirmed ("\nDo you want to remake your super block\n"
- "(say no if you use resizer)[Yes/no]: ", "Yes\n"))
- return;
- rs = fs->s_rs;
- bh = fs->s_sbh;
- }
-
- // set block number on the device and number of bitmap blocks needed to
- // address all blocks
- blocks = (count_blocks ("", fs->s_blocksize, fs->s_dev) / 8) * 8;
- set_block_count (rs, blocks);
- //rs->s_block_count = cpu_to_le32(blocks);
-
- set_bmap_nr (rs, (blocks + (fs->s_blocksize * 8 - 1)) / (fs->s_blocksize * 8));
- set_journal_size(rs, JOURNAL_BLOCK_COUNT);
-
- //rs->s_bmap_nr = cpu_to_le16( blocks / (g_sb.s_blocksize * 8) +
- // ((blocks % (g_sb.s_blocksize * 8)) ? 1 : 0) );
-
- switch (version){
- case 1:
- // super block v2 at 64k offset
- set_blocksize (rs, fs->s_blocksize);
- strncpy (rs->s_v1.s_magic, REISER2FS_SUPER_MAGIC_STRING,
- strlen(REISER2FS_SUPER_MAGIC_STRING));
- set_journal_start (rs, get_journal_start_must (fs->s_blocksize));
- set_version (rs, REISERFS_VERSION_2);
- set_objectid_map_max_size (rs, (fs->s_blocksize - SB_SIZE) / sizeof(__u32) / 2 * 2);
- break;
-
- case 2:
- // super block v1 at 64k offset
- set_blocksize (rs, fs->s_blocksize);
- strncpy (rs->s_v1.s_magic, REISERFS_SUPER_MAGIC_STRING,
- strlen(REISERFS_SUPER_MAGIC_STRING));
- set_journal_start (rs, get_journal_start_must (fs->s_blocksize));
- set_version (rs, REISERFS_VERSION_1);
- set_objectid_map_max_size (rs, (fs->s_blocksize - SB_SIZE_V1) / sizeof(__u32) / 2 * 2);
- break;
-
- case 3:
- // super block v2 at 8k offset
- set_blocksize (rs, fs->s_blocksize);
- strncpy (rs->s_v1.s_magic, REISER2FS_SUPER_MAGIC_STRING,
- strlen(REISER2FS_SUPER_MAGIC_STRING));
- set_journal_start (rs, get_journal_old_start_must (rs));
- set_version (rs, REISERFS_VERSION_2);
- set_objectid_map_max_size (rs, (fs->s_blocksize - SB_SIZE) / sizeof(__u32) / 2 * 2);
- break;
-
- case 4:
- // super block v1 at 8k offset
- set_blocksize (rs, fs->s_blocksize);
- strncpy (rs->s_v1.s_magic, REISERFS_SUPER_MAGIC_STRING,
- strlen(REISERFS_SUPER_MAGIC_STRING));
- set_journal_start (rs, get_journal_old_start_must (rs));
- set_version (rs, REISERFS_VERSION_1);
- set_objectid_map_max_size (rs, (fs->s_blocksize - SB_SIZE_V1) / sizeof(__u32) / 2 * 2);
- break;
- }
-
- print_block (stderr, fs, bh);
- if (user_confirmed ("Is this ok ? [N/Yes]: ", "Yes\n")) {
- mark_buffer_uptodate (bh, 1);
- mark_buffer_dirty (bh);
- bwrite (bh);
- fsck_progress ("\nDo not forget to run reiserfsck --rebuild-tree\n\n");
- } else
- fsck_progress ("Super block was not written\n");
- brelse (bh);
-}
-
-/*
- check_sb and rebuild-sb don't touch these fields:
- __u32 s_journal_dev;
- __u32 s_journal_trans_max ;
- __u32 s_journal_block_count ;
- __u32 s_journal_max_batch ;
- __u32 s_journal_max_commit_age ;
- __u32 s_journal_max_trans_age ;
-
- others are checked and set in either rebuild_sb or rebuild-tree
-*/
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/fsck/pass2.c b/fsck/pass2.c
index c598a9f..023f036 100644
--- a/fsck/pass2.c
+++ b/fsck/pass2.c
@@ -1,5 +1,5 @@
/*
- * Copyright 1996-2001 Hans Reiser
+ * Copyright 1996-2002 Hans Reiser
*/
#include "fsck.h"
@@ -44,21 +44,21 @@ __u32 objectid_for_relocation (struct key * key)
cur = relocated_list;
while (cur) {
- if (cur->old_dir_id == key->k_dir_id &&
- cur->old_objectid == key->k_objectid)
+ if (cur->old_dir_id == get_key_dirid (key) &&
+ cur->old_objectid == get_key_objectid (key))
/* object is relocated already */
return cur->new_objectid;
cur = cur->next;
}
cur = getmem (sizeof (struct relocated));
- cur->old_dir_id = key->k_dir_id;
- cur->old_objectid = key->k_objectid;
+ cur->old_dir_id = get_key_dirid (key);
+ cur->old_objectid = get_key_objectid (key);
cur->new_objectid = get_unused_objectid (fs);
cur->next = relocated_list;
relocated_list = cur;
fsck_log ("relocation: (%K) is relocated to (%lu, %lu)\n",
- key, key->k_dir_id, cur->new_objectid);
+ key, get_key_dirid (key), cur->new_objectid);
return cur->new_objectid;
}
@@ -71,10 +71,10 @@ static void save_item_2 (struct si ** head, struct item_head * ih,
struct si * si, * cur;
si = getmem (sizeof (*si));
- si->si_dnm_data = getmem (ih_item_len(ih));
+ si->si_dnm_data = getmem (get_ih_item_len(ih));
/*si->si_blocknr = blocknr;*/
memcpy (&(si->si_ih), ih, IH_SIZE);
- memcpy (si->si_dnm_data, item, ih_item_len(ih));
+ memcpy (si->si_dnm_data, item, get_ih_item_len(ih));
if (*head == 0)
*head = si;
@@ -102,7 +102,7 @@ struct si * save_and_delete_file_item (struct si * si, struct path * path)
/* check whether there are any directory items with this key */
-static int should_relocate (struct item_head * ih)
+int should_relocate (struct item_head * ih)
{
struct key key;
struct key * rkey;
@@ -115,7 +115,8 @@ static int should_relocate (struct item_head * ih)
set_type_and_offset (KEY_FORMAT_1, &key, SD_OFFSET, TYPE_STAT_DATA);
while (1) {
- usearch_by_key (fs, &key, &path);
+ reiserfs_search_by_key_4 (fs, &key, &path);
+
if (get_item_pos (&path) == B_NR_ITEMS (get_bh (&path))) {
rkey = uget_rkey (&path);
if (rkey && !not_of_one_file (&key, rkey)) {
@@ -129,6 +130,9 @@ static int should_relocate (struct item_head * ih)
break;
}
+ if (is_stat_data_ih (get_ih(&path)))
+ fix_obviously_wrong_sd_mode (&path);
+
path_ih = get_ih (&path);
if (not_of_one_file (&key, &(path_ih->ih_key))) {
/* there are no more item with this key */
@@ -171,7 +175,8 @@ void relocate_file (struct item_head * ih, int change_ih)
si = 0;
while (1) {
- usearch_by_key (fs, &key, &path);
+ reiserfs_search_by_key_4 (fs, &key, &path);
+
if (get_item_pos (&path) == B_NR_ITEMS (get_bh (&path))) {
rkey = uget_rkey (&path);
if (rkey && !not_of_one_file (&key, rkey)) {
@@ -185,6 +190,9 @@ void relocate_file (struct item_head * ih, int change_ih)
break;
}
+ if (is_stat_data_ih (get_ih(&path)))
+ fix_obviously_wrong_sd_mode (&path);
+
path_ih = get_ih (&path);
if (not_of_one_file (&key, &(path_ih->ih_key))) {
/* there are no more item with this key */
@@ -214,15 +222,15 @@ void relocate_file (struct item_head * ih, int change_ih)
was relocated already */
new_objectid = objectid_for_relocation (&ih->ih_key);
if (change_ih)
- ih->ih_key.k_objectid = new_objectid;
+ set_key_objectid (&ih->ih_key, new_objectid);
moved_items = 0;
-
+
/* put all items removed back into tree */
while (si) {
/*fsck_log ("relocate_file: move %H to ", &si->si_ih);*/
old = si->si_ih.ih_key;
- si->si_ih.ih_key.k_objectid = new_objectid;
+ set_key_objectid (&(si->si_ih.ih_key), new_objectid);
new = si->si_ih.ih_key;
/*fsck_log ("%H\n", &si->si_ih);*/
insert_item_separately (&(si->si_ih), si->si_dnm_data, 1/*was in tree*/);
@@ -242,10 +250,33 @@ void relocate_file (struct item_head * ih, int change_ih)
#define st_mtime_v1(sd) le32_to_cpu(((struct stat_data_v1 *)(sd))->sd_mtime)
#define st_mtime_v2(sd) le32_to_cpu(((struct stat_data *)(sd))->sd_mtime)
+
+/* either both sd-s are new of both are old */
static void overwrite_stat_data (struct item_head * new_ih,
void * new_item, struct path * path)
{
- if (stat_data_v1 (new_ih)) {
+ __u16 new_mode, old_mode;
+
+ get_sd_mode (new_ih, new_item, &new_mode);
+ get_sd_mode (get_ih (path), get_item (path), &old_mode);
+
+
+ if (S_ISREG (new_mode) && !S_ISREG (old_mode)) {
+ /* in tree we have not regular file - overwrite its stat data
+ with stat data of regular file */
+ memcpy (get_item (path), new_item, get_ih_item_len (get_ih (path)));
+ mark_buffer_dirty (get_bh (path));
+ return;
+ }
+
+ if (S_ISREG (old_mode) && !S_ISREG (new_mode)) {
+ /* new stat data is not a stat data of regular file, keep
+ regular file stat data in tree */
+ return;
+ }
+
+ /* if coming stat data has newer mtime - use that */
+ if (stat_data_v1 (new_ih)) {
if (st_mtime_v1 (new_item) > st_mtime_v1 (get_item (path))) {
memcpy (get_item (path), new_item, SD_V1_SIZE);
mark_buffer_dirty (get_bh (path));
@@ -264,7 +295,7 @@ static void overwrite_stat_data (struct item_head * new_ih,
static void put_sd_into_tree (struct item_head * new_ih, char * new_item)
{
struct path path;
-
+
if (!not_a_directory (new_item)) {
/* new item is a stat data of a directory. So we have to
relocate all items which have the same short key and are of
@@ -286,9 +317,9 @@ static void put_sd_into_tree (struct item_head * new_ih, char * new_item)
items of a directory, and that if we are inserting stat data is
of not a directory - it either has new key already or there are
no items with this key which are items of a directory */
- if (usearch_by_key (fs, &(new_ih->ih_key), &path) == ITEM_FOUND) {
+ if (reiserfs_search_by_key_4 (fs, &(new_ih->ih_key), &path) == ITEM_FOUND) {
/* this stat data is found */
- if (ih_key_format (get_ih(&path)) != ih_key_format (new_ih)) {
+ if (get_ih_key_format (get_ih(&path)) != get_ih_key_format (new_ih)) {
/* in tree stat data and a new one are of different
formats */
fsck_log ("put_sd_into_tree: inserting stat data %K (%M)..",
@@ -298,13 +329,14 @@ static void put_sd_into_tree (struct item_head * new_ih, char * new_item)
is of V2 */
fsck_log ("found newer in the tree (%M), skip inserting\n",
st_mode (get_item (&path)));
+ pathrelse (&path);
} else {
/* the stat data in the tree is sd_v1 */
fsck_log ("older sd (%M) is replaced with it\n",
st_mode (get_item (&path)));
reiserfsck_delete_item (&path, 0/*not temporary*/);
- usearch_by_key (fs, &new_ih->ih_key, &path);
+ reiserfs_search_by_key_4 (fs, &new_ih->ih_key, &path);
reiserfsck_insert_item (&path, new_ih, new_item);
}
} else {
@@ -330,28 +362,27 @@ static void put_directory_item_into_tree (struct item_head * comingih, char * it
char * name;
int namelen;
- /* if there are anything ith this key but a directory - move it
+ /* if there are anything with this key but a directory - move it
somewhere else */
relocate_file (comingih, 0/* do not change ih */);
deh = (struct reiserfs_de_head *)item;
- for (i = 0; i < ih_entry_count (comingih); i ++, deh ++) {
+ for (i = 0; i < get_ih_entry_count (comingih); i ++, deh ++) {
name = name_in_entry (deh, i);
- namelen = name_length (comingih, deh, i);
+ namelen = name_in_entry_length (comingih, deh, i);
- if (!is_properly_hashed (fs, name, namelen, deh_offset (deh)))
- reiserfs_panic ("put_directory_item_into_tree: should be hashed properly ()");
+ if (!is_properly_hashed (fs, name, namelen, get_deh_offset (deh)))
+ reiserfs_panic ("put_directory_item_into_tree: should be hashed properly (%k)", &comingih->ih_key);
asprintf (&buf, "%.*s", namelen, name);
/* 1 for fsck is important: if there is no any items of this
directory in the tree yet - new item will be inserted
marked not reached */
- reiserfs_add_entry (fs, &(comingih->ih_key), buf, (struct key *)&(deh->deh_dir_id), 1/*fsck_need*/);
+ reiserfs_add_entry (fs, &(comingih->ih_key), buf, entry_length (comingih, deh, i),
+ (struct key *)&(deh->deh2_dir_id), 1 << IH_Unreachable);
free (buf);
}
-
- /* make a directory */
}
@@ -362,14 +393,16 @@ static void link_one (struct relocated * file)
struct key obj_key;
asprintf (&name, "%lu,%lu", file->old_dir_id, file->new_objectid);
- obj_key.k_dir_id = file->old_dir_id;
- obj_key.k_objectid = file->new_objectid;
+ set_key_dirid (&obj_key, file->old_dir_id);
+ set_key_objectid (&obj_key, file->new_objectid);
+
/* 0 for fsck_need does not mean too much - it would make effect
if there were no this directory yet. But /lost_found is there
already */
- reiserfs_add_entry (fs, &lost_found_dir_key, name, &obj_key, 0/*fsck_need*/);
- stats(fs)->relocated ++;
+ reiserfs_add_entry (fs, &lost_found_dir_key, name, name_length (name, lost_found_dir_format),
+ &obj_key, 0/*fsck_need*/);
+ pass_2_stat (fs)->relocated ++;
free (name);
}
@@ -393,7 +426,7 @@ void link_relocated_files (void)
void insert_item_separately (struct item_head * ih,
char * item, int was_in_tree)
{
- if (ih->ih_key.k_dir_id == ih->ih_key.k_objectid)
+ if (get_key_dirid (&ih->ih_key) == get_key_objectid (&ih->ih_key))
reiserfs_panic ("insert_item_separately: can not insert bad item %H", ih);
if (is_stat_data_ih (ih)) {
@@ -401,7 +434,7 @@ void insert_item_separately (struct item_head * ih,
} else if (is_direntry_ih (ih)) {
put_directory_item_into_tree (ih, item);
} else {
- if (should_relocate (ih))
+ if (!was_in_tree && should_relocate (ih))
relocate_file (ih, 1/*change new_ih*/);
reiserfsck_file_write (ih, item, was_in_tree);
@@ -409,15 +442,32 @@ void insert_item_separately (struct item_head * ih,
}
-static void put_items (struct buffer_head * bh)
+static void put_stat_data_items (struct buffer_head * bh)
+{
+ int i;
+ struct item_head * ih;
+
+
+ ih = B_N_PITEM_HEAD (bh, 0);
+ for (i = 0; i < B_NR_ITEMS (bh); i ++, ih ++) {
+
+ /* this check instead of saved_items */
+ if (!is_stat_data_ih (ih) || is_bad_item (bh, ih, B_I_PITEM (bh, ih))) {
+ continue;
+ }
+ insert_item_separately (ih, B_I_PITEM (bh, ih), 0/*was in tree*/);
+ }
+}
+
+static void put_not_stat_data_items (struct buffer_head * bh)
{
int i;
struct item_head * ih;
ih = B_N_PITEM_HEAD (bh, 0);
for (i = 0; i < B_NR_ITEMS (bh); i ++, ih ++) {
- if (i && bad_pair (fs, bh, i)) {
- /* skip item if it is in wrong order */
+
+ if (is_stat_data_ih (ih) || is_bad_item (bh, ih, B_I_PITEM (bh, ih))) {
continue;
}
insert_item_separately (ih, B_I_PITEM (bh, ih), 0/*was in tree*/);
@@ -425,61 +475,204 @@ static void put_items (struct buffer_head * bh)
}
+static void before_pass_2 (reiserfs_filsys_t * fs)
+{
+ /* anything specific for pass 2 ? */
+}
+
+
+static void save_pass_2_result (reiserfs_filsys_t * fs)
+{
+ FILE * file;
+ int retval;
+
+ file = open_file("temp_fsck_file.deleteme", "w+");
+ if (!file)
+ return;
+
+ /* to be able to restart from semantic we do not need to save
+ anything here, but two magic values */
+ reiserfs_begin_stage_info_save(file, TREE_IS_BUILT);
+ reiserfs_end_stage_info_save (file);
+ close_file (file);
+ retval = unlink (state_dump_file (fs));
+ retval = rename ("temp_fsck_file.deleteme", state_dump_file (fs));
+ if (retval != 0)
+ fsck_progress ("pass 2: could not rename temp file temp_fsck_file.deleteme to %s",
+ state_dump_file (fs));
+}
+
+
+/* we have nothing to load from a state file, but we have to fetch
+ on-disk bitmap, copy it to allocable bitmap, and fetch objectid
+ map */
+void load_pass_2_result (reiserfs_filsys_t * fs)
+{
+ fsck_new_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb));
+ reiserfs_bitmap_copy (fsck_new_bitmap (fs), fs->fs_bitmap2);
+
+ fsck_allocable_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb));
+ reiserfs_bitmap_copy (fsck_allocable_bitmap (fs), fs->fs_bitmap2);
+
+ fs->block_allocator = reiserfsck_reiserfs_new_blocknrs;
+ fs->block_deallocator = reiserfsck_reiserfs_free_block;
+
+ /* we need objectid map on semantic pass to be able to relocate files */
+ proper_id_map (fs) = init_id_map ();
+ fetch_objectid_map (proper_id_map (fs), fs);
+}
+
+
/* uninsertable blocks are marked by 0s in uninsertable_leaf_bitmap
during the pass 1. They must be not in the tree */
-void pass_2_take_bad_blocks_put_into_tree (void)
-{
+static void do_pass_2 (reiserfs_filsys_t * fs) {
+
struct buffer_head * bh;
unsigned long j;
- unsigned long bb_counter = 0;
- int what_node;
+ int i, what_node;
+ unsigned long done = 0, total;
- if (!stats(fs)->uninsertable_leaves)
+ total = reiserfs_bitmap_zeros (fsck_uninsertables (fs)) * 2;
+ if (!total)
return;
- if (fsck_log_file (fs) != stderr)
- fsck_log ("####### Pass 2 #######\n");
-
fsck_progress ("\nPass2:\n");
- j = 0;
- while (reiserfs_bitmap_find_zero_bit (uninsertable_leaf_bitmap, &j) == 0) {
- bh = bread (fs->s_dev, j, fs->s_blocksize);
- if (bh == 0) {
- fsck_log ("pass_2_take_bad_blocks_put_into_tree: "
+ for (i = 0; i < 2; i++) {
+ j = 0;
+ while (reiserfs_bitmap_find_zero_bit (fsck_uninsertables (fs), &j) == 0) {
+ bh = bread (fs->fs_dev, j, fs->fs_blocksize);
+ if (bh == 0) {
+ fsck_log ("pass_2_take_bad_blocks_put_into_tree: "
"unable to read %lu block on device 0x%x\n",
- j, fs->s_dev);
- goto next;
- }
+ j, fs->fs_dev);
+ goto next;
+ }
- if (is_block_used (bh->b_blocknr)) {
- fsck_log ("pass_2_take_bad_blocks_put_into_tree: "
- "block %d can not be in tree\n", bh->b_blocknr);
- goto next;
- }
- /* this must be leaf */
- what_node = who_is_this (bh->b_data, fs->s_blocksize);
- if (what_node != THE_LEAF) { // || B_IS_KEYS_LEVEL(bh)) {
- fsck_log ("take_bad_blocks_put_into_tree: buffer (%b %z) must contain leaf\n", bh, bh);
- goto next;
- }
+ if (is_block_used (bh->b_blocknr) && !(block_of_journal (fs, bh->b_blocknr) &&
+ fsck_data(fs)->rebuild.use_journal_area)) {
+ fsck_log ("pass_2_take_bad_blocks_put_into_tree: "
+ "block %d can not be in tree\n", bh->b_blocknr);
+ goto next;
+ }
+ /* this must be leaf */
+ what_node = who_is_this (bh->b_data, bh->b_size);
+ if (what_node != THE_LEAF) { // || B_IS_KEYS_LEVEL(bh)) {
+ fsck_log ("take_bad_blocks_put_into_tree: buffer (%b %z) must contain leaf\n", bh, bh);
+ goto next;
+ }
- /*fsck_log ("block %lu is being inserted\n", bh->b_blocknr);*/
- put_items (bh);
+
+// fsck_log ("block %lu is being inserted\n", bh->b_blocknr);
+// fflush(fsck_log_file (fs));
- print_how_far (&bb_counter, stats(fs)->uninsertable_leaves, 1, fsck_quiet (fs));
-
- next:
- brelse (bh);
- j ++;
+ if (i) {
+ /* insert all not SD items */
+ put_not_stat_data_items (bh);
+ pass_2_stat (fs)->leaves ++;
+ make_allocable (j);
+ } else
+ /* insert SD items only */
+ put_stat_data_items (bh);
+
+ print_how_far (fsck_progress_file (fs), &done, total, 1, fsck_quiet (fs));
+ next:
+ brelse (bh);
+ j ++;
+ }
}
fsck_progress ("\n");
+}
+
+
+static void after_pass_2 (reiserfs_filsys_t * fs)
+{
+ time_t t;
+
+ /* we can now flush new_bitmap on disk as tree is built and
+ contains all data, which were found on dik at start in
+ used bitmaps */
+ reiserfs_bitmap_copy (fs->fs_bitmap2, fsck_new_bitmap (fs));
+
+ /* we should copy new_bitmap to allocable bitmap, becuase evth what is used
+ for now (marked as used in new_bitmap) should not be allocablel;
+ and what is not in tree for now should be allocable.
+ these bitmaps differ because on pass2 we skip those blocks, whose SD's
+ are not in the tree, and therefore indirect items of such bad leaves points
+ to not used and not allocable blocks.
+ */
+
+
+ /* DEBUG only */
+ if (reiserfs_bitmap_compare (fsck_allocable_bitmap (fs), fsck_new_bitmap(fs))) {
+ reiserfs_warning (fsck_log_file (fs), "allocable bitmap differs from new bitmap after pass2\n");
+ reiserfs_bitmap_copy (fsck_allocable_bitmap(fs), fsck_new_bitmap (fs));
+ }
+
+ /* update super block: objectid map, fsck state */
+ set_sb_fs_state (fs->fs_ondisk_sb, TREE_IS_BUILT);
+ mark_buffer_dirty (fs->fs_super_bh);
+
+ /* write all dirty blocks */
+ fsck_progress ("Flushing..");
+ flush_objectid_map (proper_id_map (fs), fs);
+ fs->fs_dirt = 1;
+ reiserfs_flush_to_ondisk_bitmap (fs->fs_bitmap2, fs);
+ reiserfs_flush (fs);
+ fsck_progress ("done\n");
+
+ /* fixme: should be optional */
+/* fsck_progress ("Tree is built. Checking it - ");
+ reiserfsck_check_pass1 ();
+ fsck_progress ("done\n");*/
+
+ stage_report (2, fs);
+
+ /* free what we do not need anymore */
+ reiserfs_delete_bitmap (fsck_uninsertables (fs));
+
+ if (!fsck_run_one_step (fs)) {
+ if (fsck_user_confirmed (fs, "Continue? (Yes):", "Yes\n", 1))
+ /* reiserfsck continues */
+ return;
+ } else
+ save_pass_2_result (fs);
+
+
+ free_id_map (proper_id_map (fs));
+ proper_id_map (fs) = 0;
+
+ reiserfs_delete_bitmap (fsck_new_bitmap (fs));
+ reiserfs_delete_bitmap (fsck_allocable_bitmap (fs));
+
+ time (&t);
+ fsck_progress ("###########\n"
+ "reiserfsck finished pass 2 at %s"
+ "###########\n", ctime (&t));
+ fs->fs_dirt = 1;
+ reiserfs_close (fs);
+ exit (4);
+}
- if (bb_counter != stats(fs)->uninsertable_leaves)
- die ("take_bad_blocks_put_into_tree: found bad block %d, must be %d",
- bb_counter, stats(fs)->uninsertable_leaves);
+void pass_2 (reiserfs_filsys_t * fs)
+{
+ if (fsck_log_file (fs) != stderr)
+ fsck_log ("####### Pass 2 #######\n");
+
+ before_pass_2 (fs);
+
+ /* take blocks which were not inserted into tree yet and put each
+ item separately */
+ do_pass_2 (fs);
+
+ after_pass_2 (fs);
+
+ if (get_sb_root_block (fs->fs_ondisk_sb) == -1)
+ die ("\n\nNo reiserfs metadata found");
}
+
+
diff --git a/fsck/pass4.c b/fsck/pass4.c
index acbdffe..a724517 100644
--- a/fsck/pass4.c
+++ b/fsck/pass4.c
@@ -1,9 +1,9 @@
/*
- * Copyright 1996, 1997, 1998 Hans Reiser
+ * Copyright 1996-2002 Hans Reiser
*/
#include "fsck.h"
-
+/*
void get_next_key (struct path * path, int i, struct key * key)
{
struct buffer_head * bh = PATH_PLAST_BUFFER (path);
@@ -11,23 +11,23 @@ void get_next_key (struct path * path, int i, struct key * key)
if (i < B_NR_ITEMS (bh) - 1) {
- /* next item is in this block */
+ // next item is in this block
copy_key (key, B_N_PKEY (bh, i + 1));
return;
}
rkey = uget_rkey (path);
if (rkey) {
- /* got next item key from right delimiting key */
+ // got next item key from right delimiting key
copy_key (key, rkey);
} else {
- /* there is no next item */
+ // there is no next item
memset (key, 0xff, KEY_SIZE);
}
}
+*/
-
-int pass_4_check_unaccessed_items (void)
+void pass_4_check_unaccessed_items (void)
{
struct key key;
struct path path;
@@ -35,6 +35,7 @@ int pass_4_check_unaccessed_items (void)
struct buffer_head * bh;
struct item_head * ih;
unsigned long items;
+ struct key * rdkey;
path.path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
key = root_dir_key;
@@ -42,29 +43,38 @@ int pass_4_check_unaccessed_items (void)
fsck_progress ("Pass 4 - ");
items = 0;
- while (usearch_by_key (fs, &key, &path) == ITEM_FOUND) {
+ while (reiserfs_search_by_key_4 (fs, &key, &path) == ITEM_FOUND) {
bh = PATH_PLAST_BUFFER (&path);
/* print ~ how many leaves were scanned and how fast it was */
if (!fsck_quiet (fs))
- print_how_fast (0, items++, 50);
+ print_how_fast (items++, 0, 50, 0);
for (i = get_item_pos (&path), ih = get_ih (&path); i < B_NR_ITEMS (bh); i ++, ih ++) {
if (!is_item_reachable (ih)) {
-
- get_next_key (&path, i, &key);
-
- stats(fs)->deleted_items ++;
-
PATH_LAST_POSITION (&path) = i;
+ rdkey = get_next_key_2 (&path);
+ if (rdkey)
+ key = *rdkey;
+ else
+ memset (&key, 0xff, KEY_SIZE);
+
+ pass_4_stat (fs)->deleted_items ++;
+
reiserfsck_delete_item (&path, 0);
goto cont;
}
}
- get_next_key (&path, i - 1, &key);
+ PATH_LAST_POSITION(&path) = i - 1;
+ rdkey = reiserfs_next_key (&path);
+ if (rdkey)
+ key = *rdkey;
+ else
+ memset (&key, 0xff, KEY_SIZE);
+
pathrelse (&path);
cont:
@@ -75,5 +85,21 @@ int pass_4_check_unaccessed_items (void)
fsck_progress ("done\n");
stage_report (4, fs);
- return 0;
+ /* after pass 4 */
+
+ /* put bitmap on place */
+ reiserfs_bitmap_copy (fs->fs_bitmap2, fsck_new_bitmap (fs));
+
+ /* update super block */
+ set_sb_free_blocks (fs->fs_ondisk_sb, reiserfs_bitmap_zeros (fsck_new_bitmap (fs)));
+ mark_buffer_dirty (fs->fs_super_bh);
+
+ /* write all dirty blocks */
+ fsck_progress ("Flushing..");
+ fs->fs_dirt = 1;
+ flush_objectid_map (proper_id_map (fs), fs);
+ reiserfs_flush_to_ondisk_bitmap (fs->fs_bitmap2, fs);
+ reiserfs_flush (fs);
+ fsck_progress ("done\n");
+ return;
}
diff --git a/fsck/reiserfsck.8 b/fsck/reiserfsck.8
index bec3c9a..5a8bdd7 100644
--- a/fsck/reiserfsck.8
+++ b/fsck/reiserfsck.8
@@ -1,91 +1,156 @@
.\" -*- nroff -*-
-.\" Copyright 1996-2001 Hans Reiser.
+.\" Copyright 1996-2002 Hans Reiser.
.\"
-.TH REISERFSCK 8 "March 2001" "Reiserfsprogs-3.x.0j"
+.TH REISERFSCK 8 "January 2002" "Reiserfsprogs-3.6.2"
.SH NAME
reiserfsck \- check a Linux Reiserfs file system
.SH SYNOPSIS
.B reiserfsck
-[
-.B -arvixoV
-] [
-.B -l logfilename
-] [
-.B --rebuild-tree
-] [
-.B --check
-] [
-.B --rebuild-sb
-] [
-.B --interactive
-] [
-\fB --logfile \fI logfilename
-] [
-.B --fix-fixable
-]
+[ \fB-afprVy\fR ]
+[ \fB--check\fR | \fB--fix-fixable\fR | \fB--rebuild-sb\fR
+| \fB--rebuild-tree\fR | \fB--clean-attributes\fR ]
+.\" [ \fB-i\fR | \fB--interactive\fR ]
+[ \fB-j\fR | \fB--journal-device\fR \fIdevice\fR ]
+[ \fB--no-journal-available\fR ]
+[ \fB-z\fR | \fB--adjust-file-size\fR ]
+[ \fB-S\fR | \fB--scan-whole-partition\fR ]
+[ \fB-l\fR | \fB--logfile \fIfilename\fR ]
+[ \fB-n\fR | \fB--nolog\fR ]
+[ \fB-q\fR | \fB--quiet\fR ]
+.\" [ \fB-b\fR | \fB--scan-marked-in-bitmap \fIbitmap-filename\fR ]
+.\" [ \fB-h\fR | \fB--hash \fIhash-name\fR ]
+.\" [ \fB-g\fR | \fB--background\fR ]
.I device
.SH DESCRIPTION
-It looks for reiserfs filesystem on a device, replays transactions
-which are to be replayed and either check or repair the filesystem
+\fBReiserfsck\fR searches for a Reiserfs filesystem on a device, replays
+any necessary transactions, and either checks or repairs the file system.
.TP
.I device
-is the special file corresponding to the device (e.g /dev/hdXX for
-IDE disk partition or /dev/sdXX for SCSI disk partition).
+is the special file corresponding to the device or partition (e.g /dev/hdXX
+for IDE disk partition or /dev/sdXX for SCSI disk partition).
.SH OPTIONS
.TP
.B --check
-This checks filesystem consistency. This is a default action. It may
-be used on a filesystem mounted read-only
+This default action checks file system consistency and reports but
+does not repair any corruption that it finds. This option may be
+used on a read-only file system mount. The \fB--check\fR option exits
+with status 0 to indicate that no corruption was found. Otherwise,
+\fBreiserfsck\fR returns 1 to indicate corruption that can be fixed with
+\fB--fix-fixable\fR and 2 to indicate corruption that requires
+\fB--rebuild-tree\fR.
.TP
-.B --rebuild-tree
-This rebuilds filesystem tree using leaf nodes found on the
-device. Normally, you do not need this, but if you have to rebuild
-tree - please backup whole partition first or at least the most
-important data if you can mount the partition.
+.B --fix-fixable
+This option recovers certain kinds of corruption that do not require
+rebuilding the entire file system tree (\fB--rebuild-tree\fR). Normally
+you only need this option if the \fB--check\fR option reports
+"corruption that can be fixed with \fB--fix-fixable\fR". This includes:
+zeroing invalid data-block pointers, correcting st_size and st_blocks
+for directories, and deleting invalid directory entries.
.TP
.B --rebuild-sb
+This option recovers the superblock on a Reiserfs partition. Normally you
+only need this option if mount reports "read_super_block: can't find
+a reiserfs file system" and you are sure that a Reiserfs file system is
+there.
+.TP
+.B --rebuild-tree
+This option rebuilds the entire file system tree using leaf nodes found
+on the device. Normally you only need this option if the \fB--check\fR
+option reports "corruption that can be fixed only during \fB--rebuild-tree\fR".
+You are strongly encouraged to make a backup copy of the whole partition
+before attempting the \fB--rebuild-tree\fR option.
.TP
-.B --interactive, -i
-This makes \fBreiserfsck\fR to stop after each pass completed.
+.B --clean-attributes
+This option cleans reserved fields of Stat-Data items.
.TP
-.B --quiet, -q
-have \fBreiserfsck\fR to not reflect its progress
+.B \fB--journal-device \fIdevice \fR, \fB-j \fIdevice \fR
+This option supplies the device name of the current file system journal.
+This option is required when the journal resides on a separate device
+from the main data device (although it can be avoided with the expert
+option \fB--no-journal-available\fR).
+.TP
+.\" .B --interactive, -i
+.\" This makes \fBreiserfsck\fR to stop after each pass completed.
+.\" .TP
+.B --adjust-file-size, -z
+This option causes \fBreiserfsck\fR to correct file sizes that
+are larger than the offset of the last discovered byte. This
+implies that holes at the end of a file will be removed. File
+sizes that are smaller than the offset of the last discovered
+byte are corrected by --fix-fixable.
+.TP
+\fB--logfile \fIfilename\fR, \fB-l \fI filename\fR
+This option causes \fBreiserfsck\fR to report any corruption it finds
+to the specified log file rather than stderr.
.TP
.B --nolog, -n
-have \fBreiserfsck\fR to not log anything
+This option prevents \fBreiserfsck\fR from reporting any kinds of corruption.
.TP
-\fB--logfile \fIfilename\fR, \fB-l \fI filename
-have \fBreiserfsck\fR to put info about found corruptions in logfile
-rather than on stderr
+.B --quiet, -q
+This option prevents \fBreiserfsck\fR from reporting its rate of progress.
.TP
-.B --fix-fixable, -x
-have \fBreiserfsck\fR to recover corruptions which can be fixed w/o
---rebuild-tree when it is runnig in check mode. Corruptions which can
-be fixed so far: bad pointers to data blocks, wrong directory's
-st_size and st_blocks, directories entries pointing to nowhere can be
-deleted
+\fB-a\fR, \fB-p\fR
+These options are usually passed by fsck -A during the automatic
+checking of /etc/fstab partitions. For compatibility, these options
+simply cause reiserfsck to print information about the specified file
+system. No checks are performed.
+When it is set - \fBreiserfsck\fR assumes that it is called by \fBfsck\fR -A,
+provides some information about the specified filesystem and exits.
.TP
-.B --fix-non-critical, -o
-have \fBreiserfsck\fR to fix: file sizes when they are bigger than
-real file size, set file mode to regular file when mode looks wrong
-and to try to recover "objectid sharing" problem
+.B -V
+This option prints the reiserfsprogs version and exit.
.TP
-.B -a
-When it is set - \fBreiserfsck\fR assumes that it is called by fsck -A
-and just returns even if filesystem seems not umounted cleanly
+\fB-r\fR, \fB-p\fR, \fB-y\fR
+These options are ignored.
.TP
-.B -r
-ignored
+.B -V\fR, \fB-f\fR
+prints version and exits
+.SH EXPERT OPTIONS
+DO NOT USE THESE OPTIONS UNLESS YOU KNOW WHAT YOU ARE DOING.
+WE ARE NOT RESPONSIBLE IF YOU LOSE DATA AS A RESULT OF THESE
+OPTIONS.
.TP
-.B -V
-Prints version and exits
+.B \fB\--no-journal-available\fR
+This option allows \fBreiserfsck\fR to proceed when the journal device is
+not available. This option has no effect when the journal is located on
+the main data device. NOTE: after this operation you must use \fBreiserfstune\fR
+to specify a new journal device.
+.TP
+.B --scan-whole-partition, -S
+This option causes \fB--rebuild-tree\fR to scan the whole partition, not only
+used space on the partition.
+.SH EXAMPLE OF USING
+1. You think something may be wrong with a reiserfs partition on /dev/hda1
+or you would just like to perform a periodic disk check.
+
+2. Run \fBreiserfsck --check --logfile check.log /dev/hda1\fR. If \fBreiserfsck
+--check\fR exits with status 0 it means no errors were discovered.
+
+3. If \fBreiserfsck --check\fR exits with status 1 (and reports about fixable
+corruptions) it means that you should run \fBreiserfsck --fix-fixable --logfile
+fixable.log /dev/hda1\fR.
+
+4. If \fBreiserfsck --check\fR exits with status 2 (and reports about fatal
+corruptions) it means that you need to run \fBreiserfsck --rebuild-tree\fR.
+If \fBreiserfsck --check\fR fails in some way you should also run \fBreiserfsck
+--rebuild-tree\fR, but we also encourage you to submit this as a bug report.
+
+5. Before running \fBreiserfsck --rebuild-tree\fR, please make a backup of
+the whole partition before proceeding. Then run \fBreiserfsck --rebuild-tree
+--logfile rebuild.log /dev/hda1\fR.
+
+6. If the \fB--rebuild-tree\fR step fails or does not recover what you expected,
+please submit this as a bug report. Try to provide as much information as
+possible and we will try to help solve the problem.
.SH AUTHOR
-This version of \fBreiserfsck\fR has been written by Hans Reiser
-<reiser@idiom.com>.
+This version of \fBreiserfsck\fR has been written by Vitaly Fertman <vitaly@namesys.com>
+and Vladimir Saveliev <vs@namesys.com>.
.SH BUGS
-There are probably few of them. Please, report bugs to Hans Reiser <reiser@idiom.com>.
+There are likely to be some bugs. Please report bugs to the ReiserFS mail-list
+<reiserfs-list@namesys.com>.
.SH TODO
-Faster recovering, signal handling, i/o error handling, etc.
+Faster recovering, signal handling, i/o error handling, return reasonable exit codes, etc.
.SH SEE ALSO
.BR mkreiserfs (8),
-.BR debugreiserfs (8)
+.BR debugreiserfs (8),
+.BR reiserfstune (8)
diff --git a/fsck/segments.c b/fsck/segments.c
deleted file mode 100644
index 73a2173..0000000
--- a/fsck/segments.c
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright 1998 Hans Reiser
- */
-/*#include <stdio.h>
-#include <string.h>*/
-/*#include <asm/bitops.h>
-#include "../include/reiserfs_fs.h"
-#include "../include/reiserfs_fs_sb.h"
-#include "../include/reiserfslib.h"*/
-#include "fsck.h"
-
-
-/* there is a situation, when we overwrite contents of unformatted
- node with direct item. One unformatted node can be overwritten
- several times by direct items */
-/*
-struct overwritten_unfm_segment {
- int ous_begin;
- int ous_end;
- struct overwritten_unfm_segment * ous_next;
-};
-*/
-struct overwritten_unfm {
- unsigned long ou_unfm_ptr; /* block number of unfm node */
- unsigned long ou_dir_id;
- unsigned long ou_objectid; /* key corresponding to an unfm node */
- unsigned long ou_offset;
-
- struct overwritten_unfm_segment * ou_segments; /* list of segmens, than have been overwritten in ths unfm node */
-};
-
-struct overwritten_unfm ** g_overwritten_unfms;
-int g_overwritten_unfms_amount; /* number of unformatted nodes, which contain direct items */
-
-
-/* adds segment to the single linked list of segments sorted by begin
- field. Retuns pointer to first element of list */
-static struct overwritten_unfm_segment * add_segment (struct overwritten_unfm_segment * first, int begin, int end)
-{
- struct overwritten_unfm_segment * new, * next, * prev;
-
- new = getmem (sizeof (struct overwritten_unfm_segment));
- new->ous_begin = begin;
- new->ous_end = end;
- new->ous_next = 0;
-
- next = first;
- prev = 0;
- while (next) {
- if (next->ous_begin > begin)
- break;
- prev = next;
- next = next->ous_next;
- }
-
- if (prev == 0) {
- /* insert into head of list */
- first = new;
- } else {
- prev->ous_next = new;
- }
- new->ous_next = next;
- return first;
-}
-
-
-/* input parameter
- `list_head` - first element of overlapping segments sorted by left edge
- `unoverwritten_segment` - returned by previous call of get_unoverwritten_segment or (-2,-2) if called first time
- */
-/* returns
- 1 and segment unoverwritten by elements of list `list_head`
- 0 if there isno such segment
- */
-int get_unoverwritten_segment (struct overwritten_unfm_segment * list_head, struct overwritten_unfm_segment * unoverwritten_segment)
-{
- int end;
-
- /* look for segment, which has begin field greater than end of previous interval */
- while (list_head->ous_begin <= unoverwritten_segment->ous_end) {
- list_head = list_head->ous_next;
- }
- /* look for the end of the continuous region covered by otrezkami */
- end = list_head->ous_end;
- while (list_head->ous_next) {
- if (list_head->ous_next->ous_begin > end + 1)
- /* intreval found */
- break;
- if (list_head->ous_next->ous_end > end)
- end = list_head->ous_next->ous_end;
- list_head = list_head->ous_next;
- }
- /* ok, between segment and segment->next we have an interval (segment->next != 0) */
- if (list_head->ous_next != 0) {
- unoverwritten_segment->ous_begin = end + 1;
- unoverwritten_segment->ous_end = list_head->ous_next->ous_begin - 1;
- return 1;
- }
- return 0;
-}
-
-
-void print_segments (struct overwritten_unfm_segment * list_head)
-{
- struct overwritten_unfm_segment * cur;
-
- cur = list_head;
- while (cur) {
- printf ("%s%d %d%s", cur == list_head ? "(" : "", cur->ous_begin, cur->ous_end, cur->ous_next ? ", " : ")\n");
- cur = cur->ous_next;
- }
-}
-
-
-/* this prepare list of segments to extracting of unoverwritten segments */
-struct overwritten_unfm_segment * find_overwritten_unfm (unsigned long unfm, int length, struct overwritten_unfm_segment * segment_to_init)
-{
- int i;
-
- for (i = 0; i < g_overwritten_unfms_amount && g_overwritten_unfms[i] != 0; i ++)
- if (g_overwritten_unfms[i]->ou_unfm_ptr == unfm) {
- if (g_overwritten_unfms[i]->ou_segments == 0)
- die ("find_overwritten_unfm: no segment found");
- g_overwritten_unfms[i]->ou_segments = add_segment (g_overwritten_unfms[i]->ou_segments, -1, -1);
- add_segment (g_overwritten_unfms[i]->ou_segments, length, length);
- segment_to_init->ous_begin = -2;
- segment_to_init->ous_end = -2;
- return g_overwritten_unfms[i]->ou_segments;
- }
- return 0;
-}
-
-struct overwritten_unfm * look_for_overwritten_unfm (__u32 unfm)
-{
- int i;
-
- for (i = 0; i < g_overwritten_unfms_amount && g_overwritten_unfms[i] != 0; i ++)
- if (g_overwritten_unfms[i]->ou_unfm_ptr == unfm)
- return g_overwritten_unfms[i];
- return 0;
-}
-
-#define GROW_BY 10
-struct overwritten_unfm * add_overwritten_unfm (unsigned long unfm, struct item_head * direct_ih)
-{
- int i;
-
- for (i = 0; i < g_overwritten_unfms_amount && g_overwritten_unfms[i] != 0; i ++) {
- if (g_overwritten_unfms[i]->ou_unfm_ptr == unfm)
- return g_overwritten_unfms[i];
- }
-
- if (i == g_overwritten_unfms_amount) {
- g_overwritten_unfms = expandmem (g_overwritten_unfms, sizeof (struct overwritten_unfm *) * i,
- sizeof (struct overwritten_unfm *) * GROW_BY);
- g_overwritten_unfms_amount += GROW_BY;
- }
- g_overwritten_unfms[i] = getmem (sizeof (struct overwritten_unfm));
- g_overwritten_unfms[i]->ou_unfm_ptr = unfm;
- g_overwritten_unfms[i]->ou_dir_id = direct_ih->ih_key.k_dir_id;
- g_overwritten_unfms[i]->ou_objectid = direct_ih->ih_key.k_objectid;
- g_overwritten_unfms[i]->ou_offset = get_offset(&direct_ih->ih_key) - (get_offset(&direct_ih->ih_key) - 1) % fs->s_blocksize;
- return g_overwritten_unfms[i];
-}
-
-
-void save_unfm_overwriting (unsigned long unfm, struct item_head * direct_ih)
-{
- struct overwritten_unfm * ov_unfm;
-
- /* add new overwritten unfm or return existing one */
- ov_unfm = add_overwritten_unfm (unfm, direct_ih);
- ov_unfm->ou_segments = add_segment (ov_unfm->ou_segments, (get_offset(&direct_ih->ih_key) - 1) % fs->s_blocksize,
- (get_offset(&direct_ih->ih_key) - 1) % fs->s_blocksize + ih_item_len (direct_ih) - 1);
-}
-
-
-void free_overwritten_unfms (void)
-{
- int i;
-
- for (i = 0; i < g_overwritten_unfms_amount && g_overwritten_unfms[i]; i ++) {
- /* free all segments */
- while (g_overwritten_unfms[i]->ou_segments) {
- struct overwritten_unfm_segment * tmp;
-
- tmp = g_overwritten_unfms[i]->ou_segments->ous_next;
- freemem (g_overwritten_unfms[i]->ou_segments);
- g_overwritten_unfms[i]->ou_segments = tmp;
- }
- /* free struct overwritten_unfm */
- freemem (g_overwritten_unfms[i]);
- }
-
- /* free array of pointers to overwritten unfms */
- if (g_overwritten_unfms)
- freemem (g_overwritten_unfms);
-}
-
-
-
-
diff --git a/fsck/semantic.c b/fsck/semantic.c
deleted file mode 100644
index a541e3b..0000000
--- a/fsck/semantic.c
+++ /dev/null
@@ -1,1346 +0,0 @@
-/*
- * Copyright 1996-1999 Hans Reiser
- */
-#include "fsck.h"
-
-
-struct key root_dir_key = {REISERFS_ROOT_PARENT_OBJECTID,
- REISERFS_ROOT_OBJECTID, {{0, 0},}};
-struct key parent_root_dir_key = {0, REISERFS_ROOT_PARENT_OBJECTID, {{0, 0},}};
-struct key lost_found_dir_key = {REISERFS_ROOT_OBJECTID, 0, {{0, 0}, }};
-
-
-struct path_key
-{
- struct short_key
- {
- __u32 k_dir_id;
- __u32 k_objectid;
- } key;
- struct path_key * next, * prev;
-};
-
-struct path_key * head_key = NULL;
-struct path_key * tail_key = NULL;
-
-void check_path_key(struct key * key)
-{
- struct path_key * cur = head_key;
-
- while(cur != NULL)
- {
- if (!comp_short_keys(&cur->key, key))
- die("\nsemantic check: loop found %k", key);
- cur = cur->next;
- }
-}
-
-void add_path_key(struct key * key)
-{
- check_path_key(key);
-
- if (tail_key == NULL)
- {
- tail_key = getmem(sizeof(struct path_key));
- head_key = tail_key;
- tail_key->prev = NULL;
- }else{
- tail_key->next = getmem(sizeof(struct path_key));
- tail_key->next->prev = tail_key;
- tail_key = tail_key->next;
- }
- copy_short_key (&tail_key->key, key);
- tail_key->next = NULL;
-}
-
-void del_path_key()
-{
- if (tail_key == NULL)
- die("wrong path_key structure");
-
- if (tail_key->prev == NULL)
- {
- freemem(tail_key);
- tail_key = head_key = NULL;
- }else{
- tail_key = tail_key->prev;
- freemem(tail_key->next);
- tail_key->next = NULL;
- }
-}
-
-/* semantic pass progress */
-static void print_name (char * dir_name, int len)
-{
- int i;
-
- if (fsck_quiet (fs))
- return;
- printf("/");
- for (i = 0; i<len; i++, dir_name++)
- printf ("%c", *dir_name);
- fflush (stdout);
-}
-
-static void erase_name (int len)
-{
- int i;
-
- if (fsck_quiet (fs))
- return;
- for (i = 0; i<=len; i++)
- printf("\b");
- for (i = 0; i<=len; i++)
- printf(" ");
- for (i = 0; i<=len; i++)
- printf("\b");
- fflush (stdout);
-}
-
-
-void get_set_sd_field (int field, struct item_head * ih, void * sd,
- void * value, int set)
-{
- if (ih_key_format (ih) == KEY_FORMAT_1) {
- struct stat_data_v1 * sd_v1 = sd;
-
- switch (field) {
- case GET_SD_MODE:
- if (set)
- sd_v1->sd_mode = cpu_to_le16 (*(__u16 *)value);
- else
- *(__u16 *)value = le16_to_cpu (sd_v1->sd_mode);
- break;
-
- case GET_SD_SIZE:
- /* value must point to 64 bit int */
- if (set)
- sd_v1->sd_size = cpu_to_le32 (*(__u64 *)value);
- else
- *(__u64 *)value = le32_to_cpu (sd_v1->sd_size);
- break;
-
- case GET_SD_BLOCKS:
- if (set)
- sd_v1->u.sd_blocks = cpu_to_le32 (*(__u32 *)value);
- else
- *(__u32 *)value = le32_to_cpu (sd_v1->u.sd_blocks);
- break;
-
- case GET_SD_NLINK:
- /* value must point to 32 bit int */
- if (set)
- sd_v1->sd_nlink = cpu_to_le16 (*(__u32 *)value);
- else
- *(__u32 *)value = le16_to_cpu (sd_v1->sd_nlink);
- break;
-
- case GET_SD_FIRST_DIRECT_BYTE:
- if (set)
- sd_v1->sd_first_direct_byte = cpu_to_le32 (*(__u32 *)value);
- else
- *(__u32 *)value = le32_to_cpu (sd_v1->sd_first_direct_byte);
- break;
-
- default:
- reiserfs_panic ("get_set_sd_field: unknown field of old stat data");
- }
- } else {
- struct stat_data * sd_v2 = sd;
-
- switch (field) {
- case GET_SD_MODE:
- if (set)
- sd_v2->sd_mode = cpu_to_le16 (*(__u16 *)value);
- else
- *(__u16 *)value = le16_to_cpu (sd_v2->sd_mode);
- break;
-
- case GET_SD_SIZE:
- if (set)
- sd_v2->sd_size = cpu_to_le64 (*(__u64 *)value);
- else
- *(__u64 *)value = le64_to_cpu (sd_v2->sd_size);
- break;
-
- case GET_SD_BLOCKS:
- if (set)
- sd_v2->sd_blocks = cpu_to_le32 (*(__u32 *)value);
- else
- *(__u32 *)value = le32_to_cpu (sd_v2->sd_blocks);
- break;
-
- case GET_SD_NLINK:
- if (set)
- sd_v2->sd_nlink = cpu_to_le32 (*(__u32 *)value);
- else
- *(__u32 *)value = le32_to_cpu (sd_v2->sd_nlink);
- break;
-
- case GET_SD_FIRST_DIRECT_BYTE:
- default:
- reiserfs_panic ("get_set_sd_field: unknown field of new stat data");
- }
- }
-}
-
-
-
-/* *size is "real" file size, sd_size - size from stat data */
-static int wrong_st_size (struct key * key, loff_t max_file_size, int blocksize,
- __u64 * size, __u64 sd_size, int is_dir)
-{
- if (sd_size <= max_file_size) {
- if (sd_size == *size)
- return 0;
-
- if (is_dir) {
- /* directory size must match to the sum of length of its entries */
- fsck_log ("dir %K has wrong sd_size %Ld, has to be %Ld\n",
- key, sd_size, *size);
- return 1;
- }
-
- if (sd_size > *size) {
- /* size in stat data can be bigger than size calculated by items */
- if (fsck_fix_non_critical (fs)) {
- /* but it -o is given - fix that */
- fsck_log ("file %K has too big file size sd_size %Ld - fixed to %Ld\n",
- key, sd_size, *size);
- stats(fs)->fixed_sizes ++;
- return 1;
- }
- *size = sd_size;
- return 0;
- }
-
- if (!(*size % blocksize)) {
- /* last item is indirect */
- if (((sd_size & ~(blocksize - 1)) == (*size - blocksize)) && sd_size % blocksize) {
- /* size in stat data is correct */
- *size = sd_size;
- return 0;
- }
- } else {
- /* last item is a direct one */
- if (!(*size % 8)) {
- if (((sd_size & ~7) == (*size - 8)) && sd_size % 8) {
- /* size in stat data is correct */
- *size = sd_size;
- return 0;
- }
- }
- }
- }
-
- fsck_log ("file %K has wrong sd_size %Ld, has to be %Ld\n",
- key, sd_size, *size);
- stats(fs)->fixed_sizes ++;
- return 1;
-}
-
-
-/* sd_blocks is 32 bit only */
-static int wrong_st_blocks (struct key * key, __u32 blocks, __u32 sd_blocks, int is_dir)
-{
- if (blocks == sd_blocks)
- return 0;
-
- if (!is_dir || blocks != _ROUND_UP (sd_blocks, fs->s_blocksize / 512)) {
- /*fsck_log ("%s %K has wrong sd_blocks %d, has to be %d\n",
- is_dir ? "dir" : "file", key, sd_blocks, blocks);*/
- return 1;
- } else
- return 0;
-}
-
-
-/* only regular files and symlinks may have items but stat
- data. Symlink shold have body */
-static int wrong_mode (struct key * key, mode_t * mode, __u64 real_size)
-{
- if (!fsck_fix_non_critical (fs))
- return 0;
-
- if (ftypelet (*mode) != '?') {
- /* mode looks reasonable */
- if (S_ISREG (*mode) || S_ISLNK (*mode))
- return 0;
-
- /* device, pipe, socket have no items */
- if (!real_size)
- return 0 ;
- }
- /* there are items, so change file mode to regular file. Otherwise
- - file bodies do not get deleted */
- fsck_log ("file %K (%M) has body, mode fixed to %M\n",
- key, *mode, (S_IFREG | 0600));
- *mode = (S_IFREG | 0600);
- return 1;
-}
-
-
-/* key is a key of last file item */
-static int wrong_first_direct_byte (struct key * key, int blocksize,
- __u32 * first_direct_byte,
- __u32 sd_first_direct_byte, __u32 size)
-{
- if (!size || is_indirect_key (key)) {
- /* there is no direct item */
- *first_direct_byte = NO_BYTES_IN_DIRECT_ITEM;
- if (sd_first_direct_byte != NO_BYTES_IN_DIRECT_ITEM) {
- return 1;
- }
- return 0;
- }
-
- /* there is direct item */
- *first_direct_byte = (get_offset (key) & ~(blocksize - 1)) + 1;
- if (*first_direct_byte != sd_first_direct_byte) {
- fsck_log ("file %k has wrong first direct byte %d, has to be %d\n",
- key, sd_first_direct_byte, *first_direct_byte);
- return 1;
- }
- return 0;
-}
-
-
-/* return values for check_regular_file and check_semantic_tree */
-#define OK 0
-#define STAT_DATA_NOT_FOUND -1
-#define DIRECTORY_HAS_NO_ITEMS -2
-#define RELOCATED -3
-
-
-
-/* delete all items (but directory ones) with the same key 'ih' has
- (including stat data of not a directory) and put them back at the
- other place */
-void relocate_dir (struct item_head * ih, int change_ih)
-{
- struct key key;
- struct key * rkey;
- struct path path;
- struct item_head * path_ih;
- struct si * si;
- __u32 new_objectid;
-
-
- /* starting with the leftmost one - look for all items of file,
- store them and delete */
- key = ih->ih_key;
- set_type_and_offset (KEY_FORMAT_1, &key, SD_OFFSET, TYPE_STAT_DATA);
-
- si = 0;
- while (1) {
- usearch_by_key (fs, &key, &path);
- if (get_item_pos (&path) == B_NR_ITEMS (get_bh (&path))) {
- rkey = uget_rkey (&path);
- if (rkey && !not_of_one_file (&key, rkey)) {
- /* file continues in the right neighbor */
- key = *rkey;
- pathrelse (&path);
- continue;
- }
- /* there is no more items of a directory */
- pathrelse (&path);
- break;
- }
-
- path_ih = get_ih (&path);
- if (not_of_one_file (&key, &(path_ih->ih_key))) {
- /* there are no more item with this key */
- pathrelse (&path);
- break;
- }
-
- /* ok, item found, but make sure that it is not a directory one */
- if ((is_stat_data_ih (path_ih) && not_a_directory (get_item (&path))) ||
- is_direct_ih (path_ih) || is_indirect_ih (path_ih)) {
- /* item of not a directory found. Leave it in the
- tree. FIXME: should not happen */
- key = path_ih->ih_key;
- set_offset (KEY_FORMAT_1, &key, get_offset (&key) + 1);
- pathrelse (&path);
- continue;
- }
-
- /* directory stat data ro directory item */
- si = save_and_delete_file_item (si, &path);
- }
-
-
- if (!si) {
- fsck_progress ("relocate_dir: no directory %K items found\n", &key);
- return;
- }
-
-
- /* get new objectid for relocation or get objectid with which file
- was relocated already */
- new_objectid = objectid_for_relocation (&ih->ih_key);
- ih->ih_key.k_objectid = new_objectid;
-
- /* put all items removed back into tree */
- while (si) {
- fsck_log ("relocate_dir: move %H to ", &si->si_ih);
- si->si_ih.ih_key.k_objectid = new_objectid;
- fsck_log ("%H\n", &si->si_ih);
- if (get_offset (&(si->si_ih.ih_key)) == DOT_OFFSET) {
- /* fix "." entry to point to a directtory properly */
- struct reiserfs_de_head * deh;
-
- deh = (struct reiserfs_de_head *)si->si_dnm_data;
- deh->deh_objectid = new_objectid;
- }
- insert_item_separately (&(si->si_ih), si->si_dnm_data, 1/*was in tree*/);
- si = remove_saved_item (si);
- }
-}
-
-
-
-/* path is path to stat data. If file will be relocated - new_ih will contain
- a key file was relocated with */
-int rebuild_check_regular_file (struct path * path, void * sd,
- struct item_head * new_ih)
-{
- int is_new_file;
- struct key key, sd_key;
- mode_t mode;
- __u32 nlink;
- __u64 real_size, saved_size;
- __u32 blocks, saved_blocks; /* proper values and value in stat data */
- __u32 first_direct_byte, saved_first_direct_byte;
-
- struct buffer_head * bh;
- struct item_head * ih;
- int fix_sd;
- int symlnk = 0;
- int retval;
-
- retval = OK;
-
- /* stat data of a file */
- ih = get_ih (path);
- bh = get_bh (path);
-
- if (new_ih) {
- /* this objectid is used already */
- *new_ih = *ih;
- pathrelse (path);
- relocate_file (new_ih, 1);
- stats(fs)->oid_sharing_files_relocated ++;
- retval = RELOCATED;
- if (usearch_by_key (fs, &(new_ih->ih_key), path) == ITEM_NOT_FOUND)
- reiserfs_panic ("rebuild_check_regular_file: could not find stat data of relocated file");
- /* stat data is marked unreachable again due to relocation, fix that */
- ih = get_ih (path);
- bh = get_bh (path);
- mark_item_reachable (ih, bh);
- sd = get_item (path);
- }
-
- /* check and set nlink first */
- get_sd_nlink (ih, sd, &nlink);
- nlink ++;
- set_sd_nlink (ih, sd, &nlink);
- mark_buffer_dirty (bh);
-
- if (nlink > 1)
- return OK;
-
- /* firts name of a file found */
- if (ih_item_len (ih) == SD_SIZE)
- is_new_file = 1;
- else
- is_new_file = 0;
-
- get_sd_mode (ih, sd, &mode);
- get_sd_size (ih, sd, &saved_size);
- get_sd_blocks (ih, sd, &saved_blocks);
- if (!is_new_file)
- get_sd_first_direct_byte (ih, sd, &saved_first_direct_byte);
-
- /* we met this file first time */
- if (S_ISREG (mode)) {
- stats(fs)->regular_files ++;
- } else if (S_ISLNK (mode)) {
- symlnk = 1;
- stats(fs)->symlinks ++;
- } else {
- stats(fs)->others ++;
- }
-
-
- key = ih->ih_key; /*??*/
- sd_key = key; /*??*/
- pathrelse (path);
-
- if (are_file_items_correct (&key, is_new_file ? KEY_FORMAT_2 : KEY_FORMAT_1,
- &real_size, &blocks, 1/*mark items reachable*/,
- symlnk, saved_size) != 1) {
- /* unpassed items will be deleted in pass 4 as they left unaccessed */
- stats(fs)->broken_files ++;
- }
-
- fix_sd = 0;
-
- fix_sd += wrong_mode (&sd_key, &mode, real_size);
- if (!is_new_file)
- fix_sd += wrong_first_direct_byte (&key, fs->s_blocksize,
- &first_direct_byte, saved_first_direct_byte, real_size);
- fix_sd += wrong_st_size (&sd_key, is_new_file ? MAX_FILE_SIZE_V2 : MAX_FILE_SIZE_V1,
- fs->s_blocksize, &real_size, saved_size, 0/*not dir*/);
- if (!is_new_file && (S_ISREG (mode) || S_ISLNK (mode)))
- /* old stat data shares sd_block and sd_dev. We do not want to wipe
- put sd_dev for device files */
- fix_sd += wrong_st_blocks (&sd_key, blocks, saved_blocks, 0/*not dir*/);
-
- if (fix_sd) {
- /* find stat data and correct it */
- if (usearch_by_key (fs, &sd_key, path) != ITEM_FOUND)
- die ("check_regular_file: stat data not found");
-
- bh = get_bh (path);
- ih = get_ih (path);
- sd = get_item (path);
- set_sd_size (ih, sd, &real_size);
- set_sd_blocks (ih, sd, &blocks);
- set_sd_mode (ih, sd, &mode);
- if (!is_new_file)
- set_sd_first_direct_byte (ih, sd, &first_direct_byte);
- mark_buffer_dirty (bh);
- }
-
- return retval;
-}
-
-
-static int is_rootdir_key (struct key * key)
-{
- if (comp_keys (key, &root_dir_key))
- return 0;
- return 1;
-}
-
-
-/* returns buffer, containing found directory item.*/
-static char * get_next_directory_item (struct key * key, /* on return this
- will contain key
- of next item in
- the tree */
- struct key * parent,
- struct item_head * ih,/*not in tree*/
- int * pos_in_item)
-{
- INITIALIZE_PATH (path);
- char * dir_item;
- struct key * rdkey;
- struct buffer_head * bh;
- struct reiserfs_de_head * deh;
- int i;
- int retval;
-
-
- if ((retval = usearch_by_entry_key (fs, key, &path)) != POSITION_FOUND) {
- die ("get_next_directory_item: %k is not found", key);
- }
-#if 0
- if (get_offset (key) != DOT_OFFSET)
- /* we always search for existing key, but "." */
- die ("get_next_directory_item: %k is not found", key);
-
- pathrelse (&path);
-
- if (fsck_mode (fs) == FSCK_CHECK) {
- fsck_log ("get_next_directory_item: directory has no \".\" entry %k\n",
- key);
- pathrelse (&path);
- return 0;
- }
-
- fsck_log ("making \".\" and/or \"..\" for %K\n", key);
- reiserfs_add_entry (fs, key, ".", key, 1 << IH_Unreachable);
- reiserfs_add_entry (fs, key, "..", parent, 1 << IH_Unreachable);
-
-
- /* we have fixed a directory, search its first item again */
- usearch_by_entry_key (fs, key, &path);
- }
-#endif
-
- /* leaf containing directory item */
- bh = PATH_PLAST_BUFFER (&path);
- *pos_in_item = path.pos_in_item;
- *ih = *get_ih (&path);
- deh = B_I_DEH (bh, ih);
-
- /* make sure, that ".." exists as well */
- if (get_offset (key) == DOT_OFFSET) {
- if (ih_entry_count (ih) < 2) {
- fsck_progress ("1. Does this ever happen?\n");
- pathrelse (&path);
- return 0;
- }
- if (name_length (ih, deh + 1, 1) != 2 ||
- strncmp (name_in_entry (deh + 1, 1), "..", 2)) {
- fsck_progress ("2. Does this ever happen?\n");
- fsck_log ("get_next_directory_item: \"..\" not found in %H\n", ih);
- pathrelse (&path);
- return 0;
- }
- }
-
- /* mark hidden entries as visible, set "." and ".." correctly */
- deh += *pos_in_item;
- for (i = *pos_in_item; i < ih_entry_count (ih); i ++, deh ++) {
- int namelen;
- char * name;
-
- name = name_in_entry (deh, i);
- namelen = name_length (ih, deh, i);
- if (de_hidden (deh))
- reiserfs_panic ("get_next_directory_item: item %k: hidden entry %d \'%.*s\'\n",
- key, i, namelen, name);
-
- if (deh->deh_offset == DOT_OFFSET) {
- if (not_of_one_file (&(deh->deh_dir_id), key))
- //deh->deh_objectid != REISERFS_ROOT_PARENT_OBJECTID)/*????*/ {
- reiserfs_panic ("get_next_directory_item: wrong \".\" found %k\n", key);
- }
-
- if (deh->deh_offset == DOT_DOT_OFFSET) {
- /* set ".." so that it points to the correct parent directory */
- if (comp_short_keys (&(deh->deh_dir_id), parent) &&
- deh->deh_objectid != REISERFS_ROOT_PARENT_OBJECTID)/*???*/ {
- /* FIXME */
- fsck_log ("get_next_directory_item: %k: \"..\" pointes to [%K], "
- "should point to [%K]",
- key, (struct key *)(&(deh->deh_dir_id)), parent);
- if (fsck_mode (fs) == FSCK_REBUILD) {
- deh->deh_dir_id = parent->k_dir_id;
- deh->deh_objectid = parent->k_objectid;
- mark_buffer_dirty (bh);
- fsck_log (" - fixed\n");
- } else
- fsck_log ("\n");
-
- }
- }
- }
-
- /* copy directory item to the temporary buffer */
- dir_item = getmem (ih_item_len (ih));
- memcpy (dir_item, B_I_PITEM (bh, ih), ih_item_len (ih));
-
-
- /* next item key */
- if (PATH_LAST_POSITION (&path) == (B_NR_ITEMS (bh) - 1) &&
- (rdkey = uget_rkey (&path)))
- copy_key (key, rdkey);
- else {
- key->k_dir_id = 0;
- key->k_objectid = 0;
- }
-
- if (fsck_mode (fs) != FSCK_CHECK)
- mark_item_reachable (get_ih (&path), bh);
- pathrelse (&path);
-
- return dir_item;
-}
-
-
-// get key of an object pointed by direntry and the key of the entry itself
-static void get_object_key (struct reiserfs_de_head * deh, struct key * key,
- struct key * entry_key, struct item_head * ih)
-{
- key->k_dir_id = deh->deh_dir_id;
- key->k_objectid = deh->deh_objectid;
- key->u.k_offset_v1.k_offset = SD_OFFSET;
- key->u.k_offset_v1.k_uniqueness = V1_SD_UNIQUENESS;
-
- entry_key->k_dir_id = ih->ih_key.k_dir_id;
- entry_key->k_objectid = ih->ih_key.k_objectid;
- entry_key->u.k_offset_v1.k_offset = deh->deh_offset;
- entry_key->u.k_offset_v1.k_uniqueness = DIRENTRY_UNIQUENESS;
-}
-
-
-/* check recursively the semantic tree. Returns OK if entry points to good
- object, STAT_DATA_NOT_FOUND if stat data was not found or RELOCATED when
- file was relocated because its objectid was already marked as used by
- another file */
-int rebuild_semantic_pass (struct key * key, struct key * parent, int dot_dot,
- struct item_head * new_ih)
-{
- struct path path;
- void * sd;
- int is_new_dir;
- __u32 nlink;
- struct buffer_head * bh;
- struct item_head * ih;
- int retval, retval1;
- char * dir_item;
- int pos_in_item;
- struct item_head tmp_ih;
- struct key item_key, entry_key, object_key;
- __u64 dir_size;
- __u32 blocks;
- __u64 saved_size;
- __u32 saved_blocks;
- int fix_sd;
- int relocate;
-
-
- retval = OK;
-
- start_again: /* when directory was relocated */
-
- if (!KEY_IS_STAT_DATA_KEY (key))
- reiserfs_panic ("rebuild_semantic_pass: key %k must be key of a stat data",
- key);
-
- /* look for stat data of an object */
- if (usearch_by_key (fs, key, &path) == ITEM_NOT_FOUND) {
- pathrelse (&path);
- if (is_rootdir_key (key))
- /* root directory has to exist at this point */
- reiserfs_panic ("rebuild_semantic_pass: root directory not found");
-
- return STAT_DATA_NOT_FOUND;
- }
-
-
- /* stat data has been found */
- bh = get_bh (&path);
- ih = get_ih (&path);
- sd = get_item(&path);
-
- /* */
- get_sd_nlink (ih, sd, &nlink);
-
- relocate = 0;
- if (!nlink) {
- /* we reached the stat data for the first time */
- if (is_objectid_really_used (semantic_id_map (fs), ih->ih_key.k_objectid, &pos_in_item)) {
- /* calculate number of found files/dirs who are using objectid
- which is used by another file */
- stats(fs)->oid_sharing ++;
- if (fsck_fix_non_critical (fs))
- /* this works for files only */
- relocate = 1;
- } else
- mark_objectid_really_used (semantic_id_map (fs), ih->ih_key.k_objectid);
-
- mark_item_reachable (ih, bh);
- }
-
-
- if (not_a_directory (sd)) {
- retval = rebuild_check_regular_file (&path, sd, relocate ? new_ih : 0);
- pathrelse (&path);
- return retval;
- }
-
- if (relocate) {
- if (!new_ih)
- reiserfs_panic ("rebuild_semantic_pass: can not relocate %K",
- &ih->ih_key);
- *new_ih = *ih;
- pathrelse (&path);
- stats(fs)->oid_sharing_dirs_relocated ++;
- relocate_dir (new_ih, 1);
- *key = new_ih->ih_key;
- retval = RELOCATED;
- goto start_again;
- }
-
- /* stat data of a directory found */
- if (nlink) {
- /* we saw this directory already */
- if (!dot_dot) {
- /* this name is not ".." - and hard links are not allowed on
- directories */
- pathrelse (&path);
- return STAT_DATA_NOT_FOUND;
- } else {
- /* ".." found */
- nlink ++;
- set_sd_nlink (ih, sd, &nlink);
- mark_buffer_dirty (bh);
- pathrelse (&path);
- return OK;
- }
- }
-
-
- /* we see the directory first time */
- stats(fs)->directories ++;
- nlink = 2;
- if (key->k_objectid == REISERFS_ROOT_OBJECTID)
- nlink ++;
- set_sd_nlink (ih, sd, &nlink);
- mark_buffer_dirty (bh);
-
- if (ih_item_len (ih) == SD_SIZE)
- is_new_dir = 1;
- else
- is_new_dir = 0;
-
- /* release path pointing to stat data */
- pathrelse (&path);
-
-
- /* make sure that "." and ".." exist */
- reiserfs_add_entry (fs, key, ".", key, 1 << IH_Unreachable);
- reiserfs_add_entry (fs, key, "..", parent, 1 << IH_Unreachable);
-
- item_key = *key;
- item_key.u.k_offset_v1.k_offset = DOT_OFFSET;
- item_key.u.k_offset_v1.k_uniqueness = DIRENTRY_UNIQUENESS;
-
- /* save stat data's size and st_blocks */
- get_sd_size (ih, sd, &saved_size);
- get_sd_blocks (ih, sd, &saved_blocks);
-
- dir_size = 0;
- while ((dir_item = get_next_directory_item (&item_key, parent, &tmp_ih, &pos_in_item)) != 0) {
- /* dir_item is copy of the item in separately allocated memory,
- item_key is a key of next item in the tree */
- int i;
- struct reiserfs_de_head * deh = (struct reiserfs_de_head *)dir_item + pos_in_item;
-
-
- for (i = pos_in_item; i < ih_entry_count (&tmp_ih); i ++, deh ++) {
- char * name;
- int namelen;
- struct item_head relocated_ih;
-
- name = name_in_entry (deh, i);
- namelen = name_length (&tmp_ih, deh, i);
-
- if (is_dot (name, namelen)) {
- dir_size += DEH_SIZE + entry_length (&tmp_ih, deh, i);
- continue;
- }
-
- print_name (name, namelen);
-
- if (!is_properly_hashed (fs, name, namelen, deh_offset (deh)))
- reiserfs_panic ("rebuild_semantic_pass: name has to be hashed properly");
-
- get_object_key (deh, &object_key, &entry_key, &tmp_ih);
-
- retval1 = rebuild_semantic_pass (&object_key, key, is_dot_dot (name, namelen), &relocated_ih);
-
- erase_name (namelen);
-
- switch (retval1) {
- case OK:
- dir_size += DEH_SIZE + entry_length (&tmp_ih, deh, i);
- break;
-
- case STAT_DATA_NOT_FOUND:
- case DIRECTORY_HAS_NO_ITEMS:
- if (get_offset (&entry_key) == DOT_DOT_OFFSET && object_key.k_objectid == REISERFS_ROOT_PARENT_OBJECTID) {
- /* ".." of root directory can not be found */
- dir_size += DEH_SIZE + entry_length (&tmp_ih, deh, i);
- continue;
- }
- fsck_log ("name \"%.*s\" in directory %K points to nowhere %K - removed\n",
- namelen, name, &tmp_ih.ih_key, (struct key *)&(deh->deh_dir_id));
- reiserfs_remove_entry (fs, &entry_key);
- stats(fs)->deleted_entries ++;
- break;
-
- case RELOCATED:
- /* file was relocated, update key in corresponding directory entry */
- if (_search_by_entry_key (fs, &entry_key, &path) != POSITION_FOUND) {
- fsck_progress ("could not find name of relocated file\n");
- } else {
- /* update key dir entry points to */
- struct reiserfs_de_head * tmp_deh;
-
- tmp_deh = B_I_DEH (get_bh (&path), get_ih (&path)) + path.pos_in_item;
- fsck_log ("name \"%.*s\" of dir %K pointing to %K updated to point to ",
- namelen, name, &tmp_ih.ih_key, &tmp_deh->deh_dir_id);
- tmp_deh->deh_dir_id = cpu_to_le32 (relocated_ih.ih_key.k_dir_id);
- tmp_deh->deh_objectid = cpu_to_le32 (relocated_ih.ih_key.k_objectid);
- fsck_log ("%K\n", &tmp_deh->deh_dir_id);
- mark_buffer_dirty (get_bh (&path));
- }
- dir_size += DEH_SIZE + entry_length (&tmp_ih, deh, i);
- pathrelse (&path);
- break;
- }
- } /* for */
-
- freemem (dir_item);
-
- if (not_of_one_file (&item_key, key))
- /* next key is not of this directory */
- break;
-
- } /* while (dir_item) */
-
-
- if (dir_size == 0)
- /* FIXME: is it possible? */
- return DIRECTORY_HAS_NO_ITEMS;
-
- /* calc correct value of sd_blocks field of stat data */
- blocks = dir_size2st_blocks (fs->s_blocksize, dir_size);
-
- fix_sd = 0;
- fix_sd += wrong_st_blocks (key, blocks, saved_blocks, 1/*dir*/);
- fix_sd += wrong_st_size (key, is_new_dir ? MAX_FILE_SIZE_V2 : MAX_FILE_SIZE_V1,
- fs->s_blocksize, &dir_size, saved_size, 1/*dir*/);
-
- if (fix_sd) {
- /* we have to fix either sd_size or sd_blocks, so look for stat data again */
- if (usearch_by_key (fs, key, &path) != ITEM_FOUND)
- die ("rebuild_semantic_pass: stat data not found");
-
- bh = get_bh (&path);
- ih = get_ih (&path);
- sd = get_item (&path);
-
- set_sd_size (ih, sd, &dir_size);
- set_sd_blocks (ih, sd, &blocks);
- mark_buffer_dirty (bh);
- pathrelse (&path);
- }
-
- return retval;
-}
-
-
-int is_dot (char * name, int namelen)
-{
- return (namelen == 1 && name[0] == '.') ? 1 : 0;
-}
-
-
-int is_dot_dot (char * name, int namelen)
-{
- return (namelen == 2 && name[0] == '.' && name[1] == '.') ? 1 : 0;
-}
-
-
-int not_a_directory (void * sd)
-{
- /* mode is at the same place and of the same size in both stat
- datas (v1 and v2) */
- struct stat_data_v1 * sd_v1 = sd;
-
- return !(S_ISDIR (le16_to_cpu (sd_v1->sd_mode)));
-}
-
-
-
-
-void zero_nlink (struct item_head * ih, void * sd)
-{
- int zero = 0;
-
- if (ih_item_len (ih) == SD_V1_SIZE && ih_key_format (ih) != KEY_FORMAT_1) {
- fsck_log ("zero_nlink: %H had wrong keys format %d, fixed to %d",
- ih, ih_key_format (ih), KEY_FORMAT_1);
- set_key_format (ih, KEY_FORMAT_1);
- }
- if (ih_item_len (ih) == SD_SIZE && ih_key_format (ih) != KEY_FORMAT_2) {
- fsck_log ("zero_nlink: %H had wrong keys format %d, fixed to %d",
- ih, ih_key_format (ih), KEY_FORMAT_2);
- set_key_format (ih, KEY_FORMAT_2);
- }
-
- set_sd_nlink (ih, sd, &zero);
-}
-
-
-/* inserts new or old stat data of a directory (unreachable, nlinks == 0) */
-void create_dir_sd (reiserfs_filsys_t fs,
- struct path * path, struct key * key)
-{
- struct item_head ih;
- struct stat_data sd;
- int key_format;
-
- if (SB_VERSION(fs) == REISERFS_VERSION_2)
- key_format = KEY_FORMAT_2;
- else
- key_format = KEY_FORMAT_1;
-
- make_dir_stat_data (fs->s_blocksize, key_format, key->k_dir_id,
- key->k_objectid, &ih, &sd);
-
- /* set nlink count to 0 and make the item unreachable */
- zero_nlink (&ih, &sd);
- mark_item_unreachable (&ih);
-
- reiserfs_insert_item (fs, path, &ih, &sd);
-}
-
-
-static void make_sure_root_dir_exists (reiserfs_filsys_t fs)
-{
- INITIALIZE_PATH (path);
-
- /* is there root's stat data */
- if (usearch_by_key (fs, &root_dir_key, &path) == ITEM_NOT_FOUND) {
- create_dir_sd (fs, &path, &root_dir_key);
- mark_objectid_really_used (proper_id_map (fs), REISERFS_ROOT_OBJECTID);
- } else
- pathrelse (&path);
-
- /* add "." and ".." if any of them do not exist. Last two
- parameters say: 0 - entry is not added on lost_found pass and 1
- - mark item unreachable */
- reiserfs_add_entry (fs, &root_dir_key, ".", &root_dir_key,
- 1 << IH_Unreachable);
- reiserfs_add_entry (fs, &root_dir_key, "..", &parent_root_dir_key,
- 1 << IH_Unreachable);
-}
-
-
-/* mkreiserfs should have created this */
-static void make_sure_lost_found_exists (reiserfs_filsys_t fs)
-{
- int retval;
- INITIALIZE_PATH (path);
- int gen_counter;
-
- /* look for "lost+found" in the root directory */
- lost_found_dir_key.k_objectid = reiserfs_find_entry (fs, &root_dir_key,
- "lost+found", &gen_counter);
- if (!lost_found_dir_key.k_objectid) {
- lost_found_dir_key.k_objectid = get_unused_objectid (fs);
- if (!lost_found_dir_key.k_objectid) {
- fsck_progress ("make_sure_lost_found_exists: could not get objectid"
- " for \"/lost+found\", will not link lost files\n");
- return;
- }
- }
-
- /* look for stat data of "lost+found" */
- retval = usearch_by_key (fs, &lost_found_dir_key, &path);
- if (retval == ITEM_NOT_FOUND)
- create_dir_sd (fs, &path, &lost_found_dir_key);
- else {
- if (not_a_directory (get_item (&path))) {
- fsck_progress ("make_sure_lost_found_exists: \"/lost+found\" is "
- "not a directory, will not link lost files\n");
- lost_found_dir_key.k_objectid = 0;
- pathrelse (&path);
- return;
- }
- pathrelse (&path);
- }
-
- /* add "." and ".." if any of them do not exist */
- reiserfs_add_entry (fs, &lost_found_dir_key, ".", &lost_found_dir_key,
- 1 << IH_Unreachable);
- reiserfs_add_entry (fs, &lost_found_dir_key, "..", &root_dir_key,
- 1 << IH_Unreachable);
-
- reiserfs_add_entry (fs, &root_dir_key, "lost+found", &lost_found_dir_key,
- 1 << IH_Unreachable);
-
- return;
-}
-
-
-/* this is part of rebuild tree */
-void pass_3_semantic (void)
-{
- fsck_progress ("Pass 3 (semantic):\n");
-
- /* when warnings go not to stderr - separate then in the log */
- if (fsck_log_file (fs) != stderr)
- fsck_log ("####### Pass 3 #########\n");
-
- if (!fs->s_hash_function)
- reiserfs_panic ("Hash function should be selected already");
-
- make_sure_root_dir_exists (fs);
- make_sure_lost_found_exists (fs);
-
- /* link all relocated files into root directory */
- link_relocated_files ();
-
- rebuild_semantic_pass (&root_dir_key, &parent_root_dir_key, 0/*!dot_dot*/, 0/*reloc_ih*/);
- stage_report (3, fs);
-
-}
-
-
-/* path is path to stat data. If file will be relocated - new_ih will contain
- a key file was relocated with */
-static int check_check_regular_file (struct path * path, void * sd)
-{
- int is_new_file;
- struct key key, sd_key;
- mode_t mode;
- __u32 nlink;
- __u64 real_size, saved_size;
- __u32 blocks, saved_blocks; /* proper values and value in stat data */
- __u32 first_direct_byte, saved_first_direct_byte;
-
- struct buffer_head * bh;
- struct item_head * ih;
- int fix_sd;
- int symlnk = 0;
-
-
- ih = get_ih (path);
- bh = get_bh (path);
-
- if (ih_item_len (ih) == SD_SIZE)
- is_new_file = 1;
- else
- is_new_file = 0;
-
-
- get_sd_nlink (ih, sd, &nlink);
- get_sd_mode (ih, sd, &mode);
- get_sd_size (ih, sd, &saved_size);
- get_sd_blocks (ih, sd, &saved_blocks);
- if (!is_new_file)
- get_sd_first_direct_byte (ih, sd, &saved_first_direct_byte);
-
- if (S_ISREG (mode)) {
- /* fixme: this could be wrong due to hard links */
- stats(fs)->regular_files ++;
- } else if (S_ISLNK (mode)) {
- symlnk = 1;
- stats(fs)->symlinks ++;
- } else {
- stats(fs)->others ++;
- }
-
-
- key = ih->ih_key; /*??*/
- sd_key = key; /*??*/
- pathrelse (path);
-
- if (are_file_items_correct (&key, is_new_file ? KEY_FORMAT_2 : KEY_FORMAT_1,
- &real_size, &blocks, 0/*do not mark items reachable*/,
- symlnk, saved_size) != 1) {
- fsck_log ("check_regular_file: broken file found %K\n", key);
- } else {
- fix_sd = 0;
-
- fix_sd += wrong_mode (&sd_key, &mode, real_size);
- if (!is_new_file)
- fix_sd += wrong_first_direct_byte (&key, fs->s_blocksize,
- &first_direct_byte, saved_first_direct_byte, real_size);
- fix_sd += wrong_st_size (&sd_key, is_new_file ? MAX_FILE_SIZE_V2 : MAX_FILE_SIZE_V1,
- fs->s_blocksize, &real_size, saved_size, 0/*not dir*/);
- if (!is_new_file && (S_ISREG (mode) || S_ISLNK (mode)))
- /* old stat data shares sd_block and sd_dev. We do not want to wipe
- put sd_dev for device files */
- fix_sd += wrong_st_blocks (&sd_key, blocks, saved_blocks, 0/*not dir*/);
-
- if (fix_sd && fsck_fix_fixable (fs)) {
- /* find stat data and correct it */
- if (usearch_by_key (fs, &sd_key, path) != ITEM_FOUND)
- die ("check_regular_file: stat data not found");
-
- bh = get_bh (path);
- ih = get_ih (path);
- sd = get_item (path);
- set_sd_size (ih, sd, &real_size);
- set_sd_blocks (ih, sd, &blocks);
- set_sd_mode (ih, sd, &mode);
- if (!is_new_file)
- set_sd_first_direct_byte (ih, sd, &first_direct_byte);
- mark_buffer_dirty (bh);
- }
- }
- return OK;
-}
-
-
-/* semantic pass of --check */
-static int check_semantic_pass (struct key * key, struct key * parent)
-{
- struct path path;
- void * sd;
- int is_new_dir;
- struct buffer_head * bh;
- struct item_head * ih;
- int retval;
- char * dir_item;
- int pos_in_item;
- struct item_head tmp_ih;
- struct key next_item_key, entry_key, object_key;
- __u64 dir_size = 0;
- __u32 blocks;
- __u64 saved_size;
- __u32 saved_blocks;
- int fix_sd;
-
-
- if (!KEY_IS_STAT_DATA_KEY (key))
- die ("check_semantic_pass: key must be key of a stat data");
-
- /* look for stat data of an object */
- if (usearch_by_key (fs, key, &path) == ITEM_NOT_FOUND) {
- pathrelse (&path);
- return STAT_DATA_NOT_FOUND;
- }
-
- /* stat data has been found */
- sd = get_item(&path);
-
- if (not_a_directory (sd)) {
- retval = check_check_regular_file (&path, sd);
- pathrelse (&path);
- return retval;
- }
-
- ih = get_ih (&path);
- /* directory stat data found */
- if (ih_item_len (ih) == SD_SIZE)
- is_new_dir = 1;
- else
- is_new_dir = 0;
-
- /* save stat data's size and st_blocks */
- get_sd_size (ih, sd, &saved_size);
- get_sd_blocks (ih, sd, &saved_blocks);
-
- /* release path pointing to stat data */
- pathrelse (&path);
-
- stats(fs)->directories ++;
- next_item_key = *key;
- next_item_key.u.k_offset_v1.k_offset = DOT_OFFSET;
- next_item_key.u.k_offset_v1.k_uniqueness = DIRENTRY_UNIQUENESS;
-
-
- dir_size = 0;
- while ((dir_item = get_next_directory_item (&next_item_key, parent, &tmp_ih, &pos_in_item)) != 0) {
- /* dir_item is copy of the item in separately allocated memory,
- item_key is a key of next item in the tree */
- int i;
- struct reiserfs_de_head * deh = (struct reiserfs_de_head *)dir_item + pos_in_item;
-
-
- for (i = pos_in_item; i < ih_entry_count (&tmp_ih); i ++, deh ++) {
- char * name;
- int namelen;
-
- name = name_in_entry (deh, i);
- namelen = name_length (&tmp_ih, deh, i);
-
- print_name (name, namelen);
-
- if (!is_properly_hashed (fs, name, namelen, deh_offset (deh))) {
- fsck_log ("check_semantic_pass: hash mismatch detected (%.*s)\n", namelen, name);
- }
- get_object_key (deh, &object_key, &entry_key, &tmp_ih);
-
- if (is_dot (name, namelen) || is_dot_dot (name, namelen)) {
- /* do not go through "." and ".." */
- retval = OK;
- } else {
- add_path_key (&object_key);
- retval = check_semantic_pass (&object_key, key);
- del_path_key ();
- }
-
- erase_name (namelen);
-
- /* check what check_semantic_tree returned */
- switch (retval) {
- case OK:
- dir_size += DEH_SIZE + entry_length (&tmp_ih, deh, i);
- break;
-
- case STAT_DATA_NOT_FOUND:
- fsck_log ("check_semantic_pass: name \"%.*s\" in directory %K points to nowhere",
- namelen, name, &tmp_ih.ih_key);
- if (fsck_fix_fixable (fs)) {
- reiserfs_remove_entry (fs, &entry_key);
- stats(fs)->deleted_entries ++;
- fsck_log (" - removed");
- }
- fsck_log ("\n");
- break;
-
- case DIRECTORY_HAS_NO_ITEMS:
- fsck_log ("check_semantic_pass: name \"%.*s\" in directory %K points dir without body\n",
- namelen, name, &tmp_ih.ih_key);
- /* fixme: stat data should be deleted as well */
- /*
- if (fsck_fix_fixable (fs)) {
- reiserfs_remove_entry (fs, &entry_key);
- stats(fs)->deleted_entries ++;
- fsck_log (" - removed");
- }
- fsck_log ("\n");*/
- break;
-
- case RELOCATED:
- /* fixme: we could also relocate file */
- reiserfs_panic ("check_semantic_pass: relocation in check mode is not ready");
- }
- } /* for */
-
- freemem (dir_item);
-
- if (not_of_one_file (&next_item_key, key))
- /* next key is not of this directory */
- break;
-
- } /* while (dir_item) */
-
-
- if (dir_size == 0)
- /* FIXME: is it possible? */
- return DIRECTORY_HAS_NO_ITEMS;
-
- /* calc correct value of sd_blocks field of stat data */
- blocks = dir_size2st_blocks (fs->s_blocksize, dir_size);
-
- fix_sd = 0;
- fix_sd += wrong_st_blocks (key, blocks, saved_blocks, 1/*dir*/);
- fix_sd += wrong_st_size (key, is_new_dir ? MAX_FILE_SIZE_V2 : MAX_FILE_SIZE_V1,
- fs->s_blocksize, &dir_size, saved_size, 1/*dir*/);
-
- if (fix_sd && fsck_fix_fixable (fs)) {
- /* we have to fix either sd_size or sd_blocks, so look for stat data again */
- if (usearch_by_key (fs, key, &path) != ITEM_FOUND)
- die ("check_semantic_tree: stat data not found");
-
- bh = get_bh (&path);
- ih = get_ih (&path);
- sd = get_item (&path);
-
- set_sd_size (ih, sd, &dir_size);
- set_sd_blocks (ih, sd, &blocks);
- mark_buffer_dirty (bh);
- pathrelse (&path);
- }
-
- return OK;
-}
-
-
-/* called when --check is given */
-void semantic_check (void)
-{
- fsck_progress ("Checking Semantic tree...");
-
- if (check_semantic_pass (&root_dir_key, &parent_root_dir_key) != OK)
- die ("check_semantic_tree: no root directory found");
-
- fsck_progress ("ok\n");
-
-}
-
-
-
diff --git a/fsck/semantic_check.c b/fsck/semantic_check.c
new file mode 100644
index 0000000..47b9f2d
--- /dev/null
+++ b/fsck/semantic_check.c
@@ -0,0 +1,731 @@
+/*
+ * Copyright 1996-2002 Hans Reiser
+ */
+#include "fsck.h"
+
+int wrong_mode (struct key * key, __u16 * mode, __u64 real_size, int symlink);
+int wrong_st_blocks (struct key * key, __u32 * blocks, __u32 sd_blocks, __u16 mode, int new_format);
+int wrong_st_size (struct key * key, loff_t max_file_size, int blocksize,
+ __u64 * size, __u64 sd_size, int is_dir);
+int wrong_first_direct_byte (struct key * key, int blocksize,
+ __u32 * first_direct_byte,
+ __u32 sd_first_direct_byte, __u32 size);
+void get_object_key (struct reiserfs_de_head * deh, struct key * key,
+ struct key * entry_key, struct item_head * ih);
+void print_name (char * name, int len);
+void erase_name (int len);
+
+
+struct path_key
+{
+ struct short_key
+ {
+ __u32 k_dir_id;
+ __u32 k_objectid;
+ } key;
+ struct path_key * next, * prev;
+};
+
+struct path_key * head_key = NULL;
+struct path_key * tail_key = NULL;
+
+static int check_path_key(struct key * key)
+{
+ struct path_key * cur = head_key;
+
+ while(cur != NULL)
+ {
+ if (!comp_short_keys(&cur->key, key)) {
+ fsck_log("\nsemantic check: directory %k has 2 names ", key);
+ return LOOP_FOUND;
+ }
+ cur = cur->next;
+ }
+ return 0;
+}
+
+static int add_path_key(struct key * key, int check)
+{
+ if (check && check_path_key(key))
+ return LOOP_FOUND;
+
+ if (tail_key == NULL)
+ {
+ tail_key = getmem(sizeof(struct path_key));
+ head_key = tail_key;
+ tail_key->prev = NULL;
+ }else{
+ tail_key->next = getmem(sizeof(struct path_key));
+ tail_key->next->prev = tail_key;
+ tail_key = tail_key->next;
+ }
+ copy_short_key (&tail_key->key, key);
+ tail_key->next = NULL;
+
+ return 0;
+}
+
+void del_path_key()
+{
+ if (tail_key == NULL)
+ die("wrong path_key structure");
+
+ if (tail_key->prev == NULL)
+ {
+ freemem(tail_key);
+ tail_key = head_key = NULL;
+ }else{
+ tail_key = tail_key->prev;
+ freemem(tail_key->next);
+ tail_key->next = NULL;
+ }
+}
+
+/* path is path to stat data. If file will be relocated - new_ih will contain
+ a key file was relocated with */
+static int check_check_regular_file (struct path * path, void * sd,
+ struct item_head * new_ih)
+{
+ int is_new_file;
+// struct key key, sd_key;
+ __u16 mode;
+ __u32 nlink;
+ __u64 real_size, saved_size;
+ __u32 blocks, saved_blocks; /* proper values and value in stat data */
+ __u32 first_direct_byte, saved_first_direct_byte;
+
+ struct buffer_head * bh;
+ struct item_head * ih, sd_ih;
+ int fix_sd;
+ int symlnk = 0;
+ int retval = OK;
+
+
+ ih = get_ih (path);
+ bh = get_bh (path);
+
+ if (new_ih) {
+ /* this objectid is used already */
+ *new_ih = *ih;
+ pathrelse (path);
+ relocate_file (new_ih, 1);
+ one_less_corruption (fs, fixable);
+ sem_pass_stat (fs)->oid_sharing_files_relocated ++;
+ retval = RELOCATED;
+ if (reiserfs_search_by_key_4 (fs, &(new_ih->ih_key), path) == ITEM_NOT_FOUND)
+ reiserfs_panic ("check_check_regular_file: could not find stat data of relocated file");
+ /* stat data is marked unreachable again due to relocation, fix that */
+ ih = get_ih (path);
+ bh = get_bh (path);
+ sd = get_item (path);
+ }
+
+
+ if (get_ih_item_len (ih) == SD_SIZE)
+ is_new_file = 1;
+ else
+ is_new_file = 0;
+
+
+ get_sd_nlink (ih, sd, &nlink);
+ get_sd_mode (ih, sd, &mode);
+ get_sd_size (ih, sd, &saved_size);
+ get_sd_blocks (ih, sd, &saved_blocks);
+
+ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) {
+ /* check and set nlink first */
+ nlink ++;
+ set_sd_nlink (ih, sd, &nlink);
+ mark_buffer_dirty (bh);
+
+ if (nlink > 1)
+ return OK;
+ }
+
+ if (!is_new_file)
+ get_sd_first_direct_byte (ih, sd, &saved_first_direct_byte);
+
+ if (S_ISLNK (mode))
+ symlnk = 1;
+
+ sd_ih = *ih;
+// sd_key = sd_ih.ih_key;
+ pathrelse (path);
+
+ if (are_file_items_correct (&sd_ih, sd, &real_size, &blocks, 0/*do not mark items reachable*/, &symlnk) != 1) {
+ one_more_corruption (fs, fatal);
+ fsck_log ("check_regular_file: broken file found %K\n", &sd_ih.ih_key);
+ } else {
+ fix_sd = 0;
+
+ fix_sd += wrong_mode (&sd_ih.ih_key, &mode, real_size, symlnk);
+ if (!is_new_file)
+ fix_sd += wrong_first_direct_byte (&sd_ih.ih_key, fs->fs_blocksize,
+ &first_direct_byte, saved_first_direct_byte, real_size);
+ fix_sd += wrong_st_size (&sd_ih.ih_key, is_new_file ? MAX_FILE_SIZE_V2 : MAX_FILE_SIZE_V1,
+ fs->fs_blocksize, &real_size, saved_size, 0/*not dir*/);
+
+ fix_sd += wrong_st_blocks (&sd_ih.ih_key, &blocks, saved_blocks, mode, is_new_file);
+
+ if (fix_sd) {
+ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) {
+ /* find stat data and correct it */
+ set_type_and_offset (KEY_FORMAT_1, &sd_ih.ih_key, SD_OFFSET, TYPE_STAT_DATA);
+ if (reiserfs_search_by_key_4 (fs, &sd_ih.ih_key, path) != ITEM_FOUND) {
+ fsck_log ("check_regular_file: stat data not found");
+ one_more_corruption (fs, fatal);
+ return STAT_DATA_NOT_FOUND;
+ }
+
+ bh = get_bh (path);
+ ih = get_ih (path);
+ sd = get_item (path);
+ set_sd_size (ih, sd, &real_size);
+ set_sd_blocks (ih, sd, &blocks);
+ set_sd_mode (ih, sd, &mode);
+ if (!is_new_file)
+ set_sd_first_direct_byte (ih, sd, &first_direct_byte);
+ mark_buffer_dirty (bh);
+ } else {
+ fsck_check_stat (fs)->fixable_corruptions += fix_sd;
+ }
+ }
+ }
+ return OK;
+}
+
+/* returns buffer, containing found directory item.*/
+static char * get_next_directory_item (struct key * key, /* on return this will
+ contain key of next item
+ in the tree */
+ struct key * parent,
+ struct item_head * ih,/*not in tree*/
+ __u32 * pos_in_item, int dir_format)
+{
+ INITIALIZE_PATH (path);
+ char * dir_item;
+ struct key * rdkey;
+ struct buffer_head * bh;
+ struct reiserfs_de_head * deh;
+ int i;
+ int retval;
+
+
+start_again:
+
+ retval = reiserfs_search_by_entry_key (fs, key, &path);
+
+ if (retval != POSITION_FOUND && get_offset (key) != DOT_OFFSET)
+ reiserfs_panic ("get_next_directory_item: %k is not found", key);
+
+ /* leaf containing directory item */
+ bh = PATH_PLAST_BUFFER (&path);
+ *pos_in_item = path.pos_in_item;
+ *ih = *get_ih (&path);
+ deh = B_I_DEH (bh, ih);
+
+ /* position was not found for '.' or there is no '..' */
+ if (retval != POSITION_FOUND || ((get_offset (key) == DOT_OFFSET) &&
+ (get_ih_entry_count (ih) < 2 || name_in_entry_length (ih, deh + 1, 1) != 2 ||
+ strncmp (name_in_entry (deh + 1, 1), "..", 2)))) {
+
+ fsck_log ("get_next_directory_item: %k %s is not found", key,
+ (retval == POSITION_NOT_FOUND) ? "entry" : "directory");
+
+ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) {
+ /* add "." and ".." exist */
+ pathrelse (&path);
+ reiserfs_add_entry (fs, key, ".", name_length (".", dir_format), key, 0);
+ reiserfs_add_entry (fs, key, "..", name_length ("..", dir_format), parent, 0);
+ fsck_log (" - fixed\n");
+ goto start_again;
+ } else {
+ one_more_corruption (fs, fixable);
+ fsck_log ("\n");
+ if (retval == DIRECTORY_NOT_FOUND)
+ return 0;
+ }
+ }
+
+ /* make sure, that ".." exists as well */
+/*
+ if (get_offset (key) == DOT_OFFSET) {
+ if (get_ih_entry_count (ih) < 2 ||
+ name_in_entry_length (ih, deh + 1, 1) != 2 ||
+ strncmp (name_in_entry (deh + 1, 1), "..", 2))
+ {
+ fsck_log ("get_next_directory_item: \"..\" not found in %H\n", ih);
+ pathrelse (&path);
+ return 0;
+ }
+ }
+*/
+ /* mark hidden entries as visible, set "." and ".." correctly */
+ deh += *pos_in_item;
+ for (i = *pos_in_item; i < get_ih_entry_count (ih); i ++, deh ++) {
+ int namelen;
+ char * name;
+
+ name = name_in_entry (deh, i);
+ namelen = name_in_entry_length (ih, deh, i);
+/* if (de_hidden (deh)) // handled in check_tree
+ reiserfs_panic ("get_next_directory_item: item %k: hidden entry %d \'%.*s\'\n",
+ key, i, namelen, name);
+*/
+
+ if (get_deh_offset (deh) == DOT_OFFSET) {
+ if (not_of_one_file (&(deh->deh2_dir_id), key)) {
+ /* "." must point to the directory it is in */
+
+ //deh->deh_objectid != REISERFS_ROOT_PARENT_OBJECTID)/*????*/ {
+ fsck_log ("get_next_directory_item: %k: \".\" pointes to [%K], "
+ "should point to [%K]", key, (struct key *)(&(deh->deh2_dir_id)));
+ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) {
+ set_deh_dirid (deh, get_key_dirid (key));
+ set_deh_objectid (deh, get_key_objectid (key));
+ mark_buffer_dirty (bh);
+ fsck_log (" - fixed\n");
+ } else
+ fsck_log ("\n");
+ }
+ }
+
+ if (get_deh_offset (deh) == DOT_DOT_OFFSET) {
+ /* set ".." so that it points to the correct parent directory */
+ if (comp_short_keys (&(deh->deh2_dir_id), parent)) {
+ fsck_log ("get_next_directory_item: %k: \"..\" pointes to [%K], "
+ "should point to [%K]", key, (struct key *)(&(deh->deh2_dir_id)), parent);
+ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) {
+ set_deh_dirid (deh, get_key_dirid (parent));
+ set_deh_objectid (deh, get_key_objectid (parent));
+ mark_buffer_dirty (bh);
+ fsck_log (" - fixed\n");
+ } else
+ fsck_log ("\n");
+ }
+ }
+ }
+
+ /* copy directory item to the temporary buffer */
+ dir_item = getmem (get_ih_item_len (ih));
+ memcpy (dir_item, B_I_PITEM (bh, ih), get_ih_item_len (ih));
+
+
+ /* next item key */
+ if (PATH_LAST_POSITION (&path) == (B_NR_ITEMS (bh) - 1) &&
+ (rdkey = uget_rkey (&path)))
+ copy_key (key, rdkey);
+ else {
+ set_key_dirid (key, 0);
+ set_key_objectid (key, 0);
+ }
+
+ if (fsck_mode (fs) != FSCK_CHECK && fsck_mode (fs) != FSCK_FIX_FIXABLE)
+ mark_item_reachable (get_ih (&path), bh);
+ pathrelse (&path);
+
+ return dir_item;
+}
+
+/* semantic pass of --check */
+static int check_semantic_pass (struct key * key, struct key * parent, int dot_dot, struct item_head * new_ih)
+{
+ struct path path;
+ void * sd;
+ __u32 nlink;
+ int is_new_dir;
+ struct buffer_head * bh;
+ struct item_head * ih;
+ int retval;
+ char * dir_item;
+ __u32 pos_in_item;
+ struct item_head tmp_ih;
+ struct key next_item_key, entry_key, object_key;
+ __u64 dir_size = 0;
+ __u32 blocks;
+ __u64 saved_size;
+ __u32 saved_blocks;
+ int fix_sd;
+ int relocate;
+ int dir_format = 0;
+ __u16 mode;
+
+ retval = OK;
+
+ start_again: /* when directory was relocated */
+
+ if (!KEY_IS_STAT_DATA_KEY (key)) {
+ fsck_log ("check_semantic_pass: key must be key of a stat data");
+ one_more_corruption (fs, fatal);
+ return STAT_DATA_NOT_FOUND;
+ }
+
+ /* look for stat data of an object */
+ if (reiserfs_search_by_key_4 (fs, key, &path) == ITEM_NOT_FOUND) {
+ pathrelse (&path);
+ return STAT_DATA_NOT_FOUND;
+ }
+
+ /* stat data has been found */
+ ih = get_ih (&path);
+ sd = get_item(&path);
+
+ get_sd_nlink (ih, sd, &nlink);
+ relocate = should_be_relocated(&ih->ih_key);
+
+ if (fix_obviously_wrong_sd_mode (&path)) {
+ one_more_corruption (fs, fixable);
+ return OK;
+ }
+
+ if (not_a_directory (sd)) {
+ fsck_check_stat (fs)->files ++;
+ retval = check_check_regular_file (&path, sd, relocate ? new_ih : 0);
+ pathrelse (&path);
+ return retval;
+ }
+
+ if (relocate) {
+ if (!new_ih)
+ reiserfs_panic ("check_semantic_pass: can not relocate %K",
+ &ih->ih_key);
+ *new_ih = *ih;
+ pathrelse (&path);
+ sem_pass_stat (fs)->oid_sharing_dirs_relocated ++;
+ relocate_dir (new_ih, 1);
+ one_less_corruption (fs, fixable);
+ *key = new_ih->ih_key;
+ retval = RELOCATED;
+ goto start_again;
+ }
+
+ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) {
+ /* it looks like stat data of a directory found */
+ if (nlink) {
+ /* we saw this directory already */
+ if (!dot_dot) {
+ /* this name is not ".." - and hard links are not allowed on
+ directories */
+ pathrelse (&path);
+ return STAT_DATA_NOT_FOUND;
+ } else {
+ /* ".." found */
+ nlink ++;
+ set_sd_nlink (ih, sd, &nlink);
+ mark_buffer_dirty (get_bh (&path));
+ pathrelse (&path);
+ return OK;
+ }
+ } /*do not run it for dot_dot on check at all*/
+
+ nlink = 2;
+ if (get_key_objectid (key) == REISERFS_ROOT_OBJECTID)
+ nlink ++;
+ set_sd_nlink (ih, sd, &nlink);
+ mark_buffer_dirty (get_bh (&path));
+ }
+
+ /* directory stat data found */
+ if (get_ih_item_len (ih) == SD_SIZE)
+ is_new_dir = 1;
+ else
+ is_new_dir = 0;
+
+ /* save stat data's size and st_blocks */
+ get_sd_size (ih, sd, &saved_size);
+ get_sd_blocks (ih, sd, &saved_blocks);
+ get_sd_mode (ih, sd, &mode);
+
+ dir_format = (get_ih_item_len (get_ih (&path)) == SD_SIZE) ? KEY_FORMAT_2 : KEY_FORMAT_1;
+
+ /* release path pointing to stat data */
+ pathrelse (&path);
+
+ fsck_check_stat (fs)->dirs ++;
+
+ set_key_dirid (&next_item_key, get_key_dirid (key));
+ set_key_objectid (&next_item_key, get_key_objectid (key));
+ set_key_offset_v1 (&next_item_key, DOT_OFFSET);
+ set_key_uniqueness (&next_item_key, DIRENTRY_UNIQUENESS);
+
+ dir_size = 0;
+ while ((dir_item = get_next_directory_item (&next_item_key, parent, &tmp_ih, &pos_in_item, dir_format)) != 0) {
+ /* dir_item is copy of the item in separately allocated memory,
+ item_key is a key of next item in the tree */
+ int i;
+ char * name = 0;
+ int namelen, entry_len;
+ struct reiserfs_de_head * deh = (struct reiserfs_de_head *)dir_item + pos_in_item;
+
+
+ for (i = pos_in_item; i < get_ih_entry_count (&tmp_ih); i ++, deh ++) {
+ struct item_head relocated_ih;
+
+ if (name) {
+ free (name);
+ name = 0;
+ }
+
+ namelen = name_in_entry_length (&tmp_ih, deh, i);
+ asprintf (&name, "%.*s", namelen, name_in_entry (deh, i));
+ entry_len = entry_length (&tmp_ih, deh, i);
+
+ get_object_key (deh, &object_key, &entry_key, &tmp_ih);
+
+ if ((dir_format == KEY_FORMAT_2) && (entry_len % 8 != 0)) {
+ /* not alighed directory of new format - delete it */
+ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) {
+ fsck_log ("name \"%.*s\" in directory %K of wrong format, %K - deleted\n",
+ namelen, name, &tmp_ih.ih_key, (struct key *)&(deh->deh2_dir_id));
+ reiserfs_remove_entry (fs, &entry_key);
+ entry_len = name_length (name, dir_format);
+ reiserfs_add_entry (fs, key, name, entry_len, (struct key *)&(deh->deh2_dir_id), 0);
+ } else {
+ fsck_log ("name \"%.*s\" in directory %K of wrong format, %K\n",
+ namelen, name, &tmp_ih.ih_key, (struct key *)&(deh->deh2_dir_id));
+ one_more_corruption (fs, fixable);
+ }
+ }
+
+
+ print_name (name, namelen);
+
+ if (!is_properly_hashed (fs, name, namelen, get_deh_offset (deh))) {
+ one_more_corruption (fs, fatal);
+ fsck_log ("check_semantic_pass: hash mismatch detected (%.*s)\n", namelen, name);
+ }
+
+ if (is_dot (name, namelen) || (is_dot_dot (name, namelen) &&
+ (fsck_mode (fs) != FSCK_FIX_FIXABLE || get_key_objectid (&object_key) == REISERFS_ROOT_PARENT_OBJECTID))) {
+ /* do not go through "." and ".." */
+ retval = OK;
+ } else {
+ if ((retval = add_path_key (&object_key, (fsck_mode (fs) != FSCK_FIX_FIXABLE)? 1 : 0)) == 0) {
+ retval = check_semantic_pass (&object_key, key, is_dot_dot(name, namelen), &relocated_ih);
+ del_path_key ();
+ }
+ }
+
+ erase_name (namelen);
+
+ /* check what check_semantic_tree returned */
+ switch (retval) {
+ case OK:
+ dir_size += DEH_SIZE + entry_len;
+ break;
+
+ case STAT_DATA_NOT_FOUND:
+ fsck_log ("check_semantic_pass: name \"%.*s\" in directory %K points to nowhere",
+ namelen, name, &tmp_ih.ih_key);
+ case LOOP_FOUND:
+ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) {
+ reiserfs_remove_entry (fs, &entry_key);
+ fsck_log (" - removed");
+ } else {
+ one_more_corruption (fs, fixable);
+ }
+ fsck_log ("\n");
+ break;
+
+ case DIRECTORY_HAS_NO_ITEMS:
+ fsck_log ("check_semantic_pass: name \"%.*s\" in directory %K points dir without body\n",
+ namelen, name, &tmp_ih.ih_key);
+
+ /* fixme: stat data should be deleted as well */
+ /*
+ if (fsck_fix_fixable (fs)) {
+ reiserfs_remove_entry (fs, &entry_key);
+ fsck_data(fs)->deleted_entries ++;
+ fsck_log (" - removed");
+ }
+ fsck_log ("\n");*/
+ break;
+
+ case RELOCATED:
+ /* file was relocated, update key in corresponding directory entry */
+ if (reiserfs_search_by_entry_key (fs, &entry_key, &path) != POSITION_FOUND) {
+ fsck_progress ("could not find name of relocated file\n");
+ } else {
+ /* update key dir entry points to */
+ struct reiserfs_de_head * tmp_deh;
+
+ tmp_deh = B_I_DEH (get_bh (&path), get_ih (&path)) + path.pos_in_item;
+ fsck_log ("name \"%.*s\" of dir %K pointing to %K updated to point to ",
+ namelen, name, &tmp_ih.ih_key, &tmp_deh->deh2_dir_id);
+ set_deh_dirid (tmp_deh, get_key_dirid (&relocated_ih.ih_key));
+ set_deh_objectid (tmp_deh, get_key_objectid (&relocated_ih.ih_key));
+
+ fsck_log ("%K\n", &tmp_deh->deh2_dir_id);
+ mark_buffer_dirty (get_bh (&path));
+ }
+ dir_size += DEH_SIZE + entry_len;
+ pathrelse (&path);
+ break;
+ }
+ } /* for */
+
+ freemem (dir_item);
+ free (name);
+ name = 0;
+
+ if (not_of_one_file (&next_item_key, key))
+ /* next key is not of this directory */
+ break;
+
+ } /* while (dir_item) */
+
+
+ if (dir_size == 0)
+ /* FIXME: is it possible? */
+ return DIRECTORY_HAS_NO_ITEMS;
+
+ /* calc correct value of sd_blocks field of stat data */
+ blocks = dir_size2st_blocks (dir_size);
+
+ fix_sd = 0;
+ fix_sd += wrong_st_blocks (key, &blocks, saved_blocks, mode, is_new_dir);
+ fix_sd += wrong_st_size (key, is_new_dir ? MAX_FILE_SIZE_V2 : MAX_FILE_SIZE_V1,
+ fs->fs_blocksize, &dir_size, saved_size, 1/*dir*/);
+
+ if (fix_sd) {
+ if (fsck_mode (fs) == FSCK_FIX_FIXABLE) {
+ /* we have to fix either sd_size or sd_blocks, so look for stat data again */
+ if (reiserfs_search_by_key_4 (fs, key, &path) != ITEM_FOUND) {
+ fsck_log ("check_semantic_tree: stat data not found");
+ one_more_corruption(fs, fatal);
+ return STAT_DATA_NOT_FOUND;
+ }
+
+ bh = get_bh (&path);
+ ih = get_ih (&path);
+ sd = get_item (&path);
+
+ set_sd_size (ih, sd, &dir_size);
+ set_sd_blocks (ih, sd, &blocks);
+ mark_buffer_dirty (bh);
+ pathrelse (&path);
+ } else {
+ fsck_check_stat (fs)->fixable_corruptions += fix_sd;
+ }
+ }
+
+ return retval;
+}
+
+int check_safe_links ()
+{
+ struct path safe_link_path, path;
+ struct key safe_link_key = {-1, 0, {{0, 0}}};
+ struct key key = {0, 0, {{0, 0}}};
+ struct key * rkey;
+ struct item_head * tmp_ih;
+
+ while (1) {
+ if (get_key_dirid (&safe_link_key) == 0)
+ break;
+
+ reiserfs_search_by_key_4 (fs, &safe_link_key, &safe_link_path);
+
+ if (get_blkh_nr_items ( B_BLK_HEAD (get_bh(&safe_link_path))) <= PATH_LAST_POSITION (&safe_link_path)) {
+ pathrelse (&safe_link_path);
+ break;
+ }
+
+ tmp_ih = get_ih(&safe_link_path);
+
+ if (get_key_dirid(&tmp_ih->ih_key) != (__u32)-1 ||
+ get_key_objectid(&tmp_ih->ih_key) == (__u32)-1) {
+ pathrelse (&safe_link_path);
+ break;
+ }
+
+ if (get_ih_item_len (tmp_ih) != 4)
+ reiserfs_panic ("safe link cannot be of size %d", get_ih_item_len (tmp_ih));
+
+ set_key_dirid(&key, le32_to_cpu(*(__u32 *)get_item(&safe_link_path)));
+ set_key_objectid(&key, get_key_objectid(&tmp_ih->ih_key));
+ if ( (rkey = get_next_key_2 (&safe_link_path)) == NULL )
+ set_key_dirid (&safe_link_key, 0);
+ else
+ safe_link_key = *rkey;
+
+ if (reiserfs_search_by_key_4 (fs, &key, &path) == ITEM_NOT_FOUND) {
+ /*sware on check, delete on fix-fixable*/
+ if (fsck_mode(fs) == FSCK_CHECK) {
+ fsck_log ("invalid safe link, cannot find a pointed object (%K)\n", &key);
+ one_more_corruption (fs, fixable);
+ } else if (fsck_mode(fs) == FSCK_FIX_FIXABLE) {
+ fsck_log ("invalid safe link, cannot find a pointed object (%K) - delete\n", &key);
+ *(__u32 *)get_item(&safe_link_path) = (__u32)0;
+ pathrelse (&path);
+ reiserfsck_delete_item (&safe_link_path, 0);
+ continue;
+ }
+ } else if (get_offset(&tmp_ih->ih_key) == 0x1) {
+ if (!not_a_directory (get_item(&path))) {
+ /*truncate on directory should not happen*/
+ /*sware on check, delete on fix-fixable*/
+ if (fsck_mode(fs) == FSCK_CHECK) {
+ fsck_log ("invalid truncate safe link, cannot happen for directory (%K)\n", &key);
+ one_more_corruption (fs, fixable);
+ } else if (fsck_mode(fs) == FSCK_FIX_FIXABLE) {
+ fsck_log ("invalid truncate safe link, cannot happen for directory (%K) - delete\n", &key);
+ *(__u32 *)get_item(&safe_link_path) = (__u32)0;
+ pathrelse (&path);
+ reiserfsck_delete_item (&safe_link_path, 0);
+ continue;
+ }
+ }
+ }
+ pathrelse (&path);
+ pathrelse (&safe_link_path);
+ }
+
+ return OK;
+}
+
+/* called when --check is given */
+void semantic_check (void)
+{
+ if (fsck_data (fs)->check.bad_nodes) {
+ fsck_progress ("Bad nodes were found, Semantic pass skipped\n");
+ return;
+ }
+
+ if (fsck_data (fs)->check.fatal_corruptions) {
+ fsck_progress ("Fatal corruptions were found, Semantic pass skipped\n");
+ return;
+ }
+
+
+ fsck_progress ("Checking Semantic tree...\n");
+
+ if (fsck_mode(fs) == FSCK_FIX_FIXABLE) {
+ /*create new_bitmap, and initialize new_bitmap & allocable bitmap*/
+ fsck_new_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb));
+ reiserfs_bitmap_copy (fsck_new_bitmap (fs), fs->fs_bitmap2);
+ fsck_allocable_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb));
+ reiserfs_bitmap_copy (fsck_allocable_bitmap (fs), fs->fs_bitmap2);
+ fs->block_allocator = reiserfsck_reiserfs_new_blocknrs;
+ fs->block_deallocator = reiserfsck_reiserfs_free_block;
+ }
+
+ if (check_semantic_pass (&root_dir_key, &parent_root_dir_key, 0, 0) != OK) {
+ fsck_log ("check_semantic_tree: no root directory found");
+ one_more_corruption (fs, fatal);
+ }
+
+ check_safe_links ();
+
+ if (fsck_mode(fs) == FSCK_FIX_FIXABLE) {
+ reiserfs_delete_bitmap (fs->fs_bitmap2);
+ fs->fs_bitmap2 = fsck_new_bitmap (fs);
+ reiserfs_delete_bitmap (fsck_allocable_bitmap (fs));
+ fsck_allocable_bitmap (fs) = NULL;
+ set_sb_free_blocks (fs->fs_ondisk_sb, reiserfs_bitmap_zeros (fs->fs_bitmap2));
+ mark_buffer_dirty (fs->fs_super_bh);
+ add_badblock_list(fs, 0);
+ }
+
+ fsck_progress ("ok\n");
+}
diff --git a/fsck/semantic_rebuild.c b/fsck/semantic_rebuild.c
new file mode 100644
index 0000000..6f58126
--- /dev/null
+++ b/fsck/semantic_rebuild.c
@@ -0,0 +1,1192 @@
+/*
+ * Copyright 1996-2002 Hans Reiser
+ */
+#include "fsck.h"
+
+int screen_width;
+int screen_curr_pos;
+char *screen_savebuffer;
+int screen_savebuffer_len;
+
+#define MIN(a, b) (((a)>(b))?(b):(a))
+
+/* semantic pass progress */
+void print_name (char * name, int len)
+{
+ int i;
+
+ if (fsck_quiet (fs))
+ return;
+
+ if ( len + screen_curr_pos + 1 > screen_savebuffer_len) {
+ char *t = expandmem(screen_savebuffer, screen_savebuffer_len + 1, len + screen_curr_pos - screen_savebuffer_len + 1);
+ if (!t) {
+ printf("\nNot enough memory\n");
+ return; // ????
+ }
+ screen_savebuffer = t;
+ screen_savebuffer_len = len + screen_curr_pos + 1;
+ }
+ strcat(screen_savebuffer,"/");
+ strncat(screen_savebuffer,name,len);
+ i = screen_curr_pos;
+ screen_curr_pos += len+1;
+ for ( ; i<screen_curr_pos; i++)
+ if ( screen_savebuffer[i] < 32 )
+ screen_savebuffer[i] = '?';
+ screen_savebuffer[screen_curr_pos]=0;
+
+ if ( screen_width < screen_curr_pos ) {
+ printf("\r... %.*s",screen_width - 4, screen_savebuffer + ( screen_curr_pos - (screen_width - 4)));
+ } else
+ printf("/%.*s", len, screen_savebuffer + screen_curr_pos - len);
+
+ fflush (stdout);
+}
+
+
+void erase_name (int len)
+{
+ int i;
+
+ if (fsck_quiet (fs))
+ return;
+
+ if ( screen_curr_pos < screen_width ) {
+
+ screen_curr_pos-=len+1;
+ screen_savebuffer[screen_curr_pos]=0;
+
+ for (i = 0; i<=len; i++)
+ printf("\b");
+ for (i = 0; i<=len+1; i++)
+ printf(" ");
+ for (i = 0; i<=len+1; i++)
+ printf("\b");
+ } else {
+ screen_curr_pos-=len+1;
+ if (screen_curr_pos < 0 )
+ die("semantic_rebuild.c: run out of buffer data in erase_name!\n");
+
+ screen_savebuffer[screen_curr_pos]=0;
+ printf("\r");
+ if (screen_curr_pos >= screen_width ) {
+ int t_preface=MIN(screen_curr_pos-screen_width,4);
+ printf("%.*s%.*s", t_preface, "... ", screen_width-t_preface - 1, screen_savebuffer + ( screen_curr_pos - (screen_width - t_preface)) + 1);
+ } else {
+ int space_used=printf("%s", screen_savebuffer);
+ for ( i=space_used; i < screen_width; i++)
+ printf(" ");
+ for ( i=space_used; i < screen_width; i++)
+ printf("\b");
+ }
+ }
+
+ fflush (stdout);
+}
+
+
+
+/* *size is "real" file size, sd_size - size from stat data */
+int wrong_st_size (struct key * key, loff_t max_file_size, int blocksize,
+ __u64 * size, __u64 sd_size, int is_dir)
+{
+ if (sd_size <= max_file_size) {
+ if (sd_size == *size)
+ return 0;
+
+ if (is_dir) {
+ /* directory size must match to the sum of length of its entries */
+ fsck_log ("dir %K has wrong sd_size %Ld, has to be %Ld\n",
+ key, sd_size, *size);
+ return 1;
+ }
+
+ if (sd_size > *size) {
+ /* size in stat data can be bigger than size calculated by items */
+ if (fsck_adjust_file_size (fs)) {
+ /* but it -o is given - fix that */
+ fsck_log ("file %K has too big file size sd_size %Ld - fixed to %Ld\n",
+ key, sd_size, *size);
+ sem_pass_stat (fs)->fixed_sizes ++;
+ return 1;
+ }
+ *size = sd_size;
+ return 0;
+ }
+
+ if (!(*size % blocksize)) {
+ /* last item is indirect */
+ if (((sd_size & ~(blocksize - 1)) == (*size - blocksize)) && sd_size % blocksize) {
+ /* size in stat data is correct */
+ *size = sd_size;
+ return 0;
+ }
+ } else {
+ /* last item is a direct one */
+ if (!(*size % 8)) {
+ if (((sd_size & ~7) == (*size - 8)) && sd_size % 8) {
+ /* size in stat data is correct */
+ *size = sd_size;
+ return 0;
+ }
+ }
+ }
+ }
+
+ fsck_log ("file %K has wrong sd_size %Ld, has to be %Ld\n",
+ key, sd_size, *size);
+ sem_pass_stat (fs)->fixed_sizes ++;
+ return 1;
+}
+
+
+/* sd_blocks is 32 bit only */
+/* old stat data shares sd_block and sd_dev - do not wipe sd_rdev out */
+/* we should fix it as following:
+|------------------------------------------------------------------|
+| | 3.6 | 3.5 |
+|---------------------------------------------------| |
+| | blocks | r_dev|generation | blocks/r_dev |
+|------------------------------------------------------------------|
+| fifo, sockets | 0 | generation | 0 |
+| chr/blk_dev | 0 | maj:min | maj:min |
+| file, dir, link | blocks | generation | blocks |
+|------------------------------------------------------------------|
+*/
+int wrong_st_blocks (struct key * key, __u32 * blocks, __u32 sd_blocks, __u16 mode, int new_format)
+{
+ int ret = 0;
+
+ if (S_ISREG (mode) || S_ISLNK (mode) || S_ISDIR (mode)) {
+ if (*blocks != sd_blocks) {
+ fsck_log ("%s %K has wrong sd_blocks %u, has to be %u\n",
+ S_ISDIR (mode) ? "dir" : "file", key, sd_blocks, *blocks);
+ ret = 1;
+ }
+ } else if (new_format || (S_ISFIFO (mode) || S_ISSOCK (mode))) {
+ if (sd_blocks != 0) {
+ fsck_log ("node %K has wrong sd_blocks %u, has to be %u\n",
+ key, sd_blocks, 0);
+ *blocks = 0;
+ ret = 1;
+ }
+ }
+
+ return ret;
+}
+/*
+int wrong_st_rdev (struct key * key, __u32 * sd_rdev, __u16 mode, int new_format)
+{
+ int ret = 0;
+
+ if (!new_format)
+ return 0;
+
+ if (!S_ISCHR (mode) && !S_ISBLK (mode)) {
+ if (*sd_rdev != 0) {
+ fsck_log ("%s %K has wrong sd_rdev %u, has to be 0\n",
+ S_ISDIR (mode) ? "dir" : "file", key, *sd_rdev);
+ *sd_rdev = 0;
+ ret = 1;
+ }
+ }
+ return ret;
+}
+*/
+/* only regular files and symlinks may have items but stat
+ data. Symlink shold have body */
+int wrong_mode (struct key * key, __u16 * mode, __u64 real_size, int symlink)
+{
+ int retval = 0;
+ if (S_ISLNK (*mode) && !symlink) {
+ fsck_log ("file %K (%M) is too big to be symlink - try as regfile\n", key, *mode);
+ *mode &= ~S_IFMT;
+ *mode |= S_IFREG;
+ retval = 1;
+ }
+
+ if (ftypelet (*mode) != '?') {
+ /* mode looks reasonable */
+ if (S_ISREG (*mode) || S_ISLNK (*mode))
+ return retval;
+
+ /* device, pipe, socket have no items */
+ if (!real_size)
+ return retval;
+ }
+ /* there are items, so change file mode to regular file. Otherwise
+ - file bodies do not get deleted */
+ fsck_log ("file %K (%M) has body, try mode as %M\n", key, *mode, (S_IFREG | 0600));
+ *mode = (S_IFREG | 0600);
+ return 1;
+}
+
+
+/* key is a key of last file item */
+int wrong_first_direct_byte (struct key * key, int blocksize,
+ __u32 * first_direct_byte,
+ __u32 sd_first_direct_byte, __u32 size)
+{
+ if (!size || is_indirect_key (key)) {
+ /* there is no direct item */
+ *first_direct_byte = NO_BYTES_IN_DIRECT_ITEM;
+ if (sd_first_direct_byte != NO_BYTES_IN_DIRECT_ITEM) {
+ fsck_log ("%K has no direct items and first direct byte in SD == %d\n",
+ key, sd_first_direct_byte);
+ return 1;
+ }
+ return 0;
+ }
+
+ /* there is direct item */
+ *first_direct_byte = (get_offset (key) & ~(blocksize - 1)) + 1;
+ if (*first_direct_byte != sd_first_direct_byte) {
+ fsck_log ("file %k has wrong first direct byte in SD (%d), has to be %d\n",
+ key, sd_first_direct_byte, *first_direct_byte);
+ return 1;
+ }
+ return 0;
+}
+
+
+/* delete all items (but directory ones) with the same key 'ih' has
+ (including stat data of not a directory) and put them back at the
+ other place */
+void relocate_dir (struct item_head * ih, int change_ih)
+{
+ struct key key;
+ struct key * rkey;
+ struct path path;
+ struct item_head * path_ih;
+ struct si * si;
+ __u32 new_objectid;
+
+
+ /* starting with the leftmost one - look for all items of file,
+ store them and delete */
+ key = ih->ih_key;
+ set_type_and_offset (KEY_FORMAT_1, &key, SD_OFFSET, TYPE_STAT_DATA);
+
+ si = 0;
+ while (1) {
+ reiserfs_search_by_key_4 (fs, &key, &path);
+
+ if (get_item_pos (&path) == B_NR_ITEMS (get_bh (&path))) {
+ rkey = uget_rkey (&path);
+ if (rkey && !not_of_one_file (&key, rkey)) {
+ /* file continues in the right neighbor */
+ key = *rkey;
+ pathrelse (&path);
+ continue;
+ }
+ /* there is no more items of a directory */
+ pathrelse (&path);
+ break;
+ }
+
+ if (is_stat_data_ih (get_ih(&path)))
+ fix_obviously_wrong_sd_mode (&path);
+
+ path_ih = get_ih (&path);
+ if (not_of_one_file (&key, &(path_ih->ih_key))) {
+ /* there are no more item with this key */
+ pathrelse (&path);
+ break;
+ }
+
+ /* ok, item found, but make sure that it is not a directory one */
+ if ((is_stat_data_ih (path_ih) && not_a_directory (get_item (&path))) ||
+ is_direct_ih (path_ih) || is_indirect_ih (path_ih)) {
+ /* item of not a directory found. Leave it in the
+ tree. FIXME: should not happen */
+ key = path_ih->ih_key;
+ set_offset (KEY_FORMAT_1, &key, get_offset (&key) + 1);
+ pathrelse (&path);
+ continue;
+ }
+
+ /* directory stat data ro directory item */
+ si = save_and_delete_file_item (si, &path);
+ }
+
+
+ if (!si) {
+ fsck_progress ("relocate_dir: no directory %K items found\n", &key);
+ return;
+ }
+
+
+ /* get new objectid for relocation or get objectid with which file
+ was relocated already */
+ new_objectid = objectid_for_relocation (&ih->ih_key);
+ set_key_objectid (&ih->ih_key, new_objectid);
+
+ /* put all items removed back into tree */
+ while (si) {
+ fsck_log ("relocate_dir: move %H to ", &si->si_ih);
+ set_key_objectid (&si->si_ih.ih_key, new_objectid);
+ fsck_log ("%H\n", &si->si_ih);
+ if (get_offset (&(si->si_ih.ih_key)) == DOT_OFFSET) {
+ /* fix "." entry to point to a directtory properly */
+ struct reiserfs_de_head * deh;
+
+ deh = (struct reiserfs_de_head *)si->si_dnm_data;
+ set_deh_objectid (deh, new_objectid);
+ }
+ insert_item_separately (&(si->si_ih), si->si_dnm_data, 1/*was in tree*/);
+ si = remove_saved_item (si);
+ }
+}
+
+
+
+/* path is path to stat data. If file will be relocated - new_ih will contain
+ a key file was relocated with */
+int rebuild_check_regular_file (struct path * path, void * sd,
+ struct item_head * new_ih)
+{
+ int is_new_file;
+// struct key sd_key;
+ __u16 mode;
+ __u32 nlink;
+ __u64 real_size, saved_size;
+ __u32 blocks, saved_blocks; /* proper values and value in stat data */
+ __u32 first_direct_byte, saved_first_direct_byte;
+
+ struct buffer_head * bh;
+ struct item_head * ih, sd_ih;
+ int fix_sd;
+ int symlnk = 0;
+ int retval;
+
+ retval = OK;
+
+ /* stat data of a file */
+ ih = get_ih (path);
+ bh = get_bh (path);
+
+ if (new_ih) {
+ /* this objectid is used already */
+ *new_ih = *ih;
+ pathrelse (path);
+ relocate_file (new_ih, 1);
+ sem_pass_stat (fs)->oid_sharing_files_relocated ++;
+ retval = RELOCATED;
+ if (reiserfs_search_by_key_4 (fs, &(new_ih->ih_key), path) == ITEM_NOT_FOUND)
+ reiserfs_panic ("rebuild_check_regular_file: could not find stat data of relocated file");
+ /* stat data is marked unreachable again due to relocation, fix that */
+ ih = get_ih (path);
+ bh = get_bh (path);
+ mark_item_reachable (ih, bh);
+ sd = get_item (path);
+ }
+
+ /* check and set nlink first */
+ get_sd_nlink (ih, sd, &nlink);
+ nlink ++;
+ set_sd_nlink (ih, sd, &nlink);
+ mark_buffer_dirty (bh);
+
+ if (nlink > 1)
+ return OK;
+
+ /* firts name of a file found */
+ if (get_ih_item_len (ih) == SD_SIZE)
+ is_new_file = 1;
+ else
+ is_new_file = 0;
+
+ get_sd_mode (ih, sd, &mode);
+ get_sd_size (ih, sd, &saved_size);
+ get_sd_blocks (ih, sd, &saved_blocks);
+ if (!is_new_file)
+ get_sd_first_direct_byte (ih, sd, &saved_first_direct_byte);
+
+ /* we met this file first time */
+ if (S_ISREG (mode)) {
+ sem_pass_stat(fs)->regular_files ++;
+ } else if (S_ISLNK (mode)) {
+ symlnk = 1;
+ sem_pass_stat (fs)->symlinks ++;
+ } else {
+ sem_pass_stat (fs)->others ++;
+ }
+
+
+ sd_ih = *ih;
+// sd_key = sd_ih.ih_key;
+ pathrelse (path);
+
+ if (are_file_items_correct (&sd_ih, sd, &real_size, &blocks, 1/*mark items reachable*/, &symlnk) != 1) {
+ /* unpassed items will be deleted in pass 4 as they left unaccessed */
+ sem_pass_stat (fs)->broken_files ++;
+ }
+
+ fix_sd = 0;
+
+ fix_sd += wrong_mode (/*&sd_key, */ &sd_ih.ih_key, &mode, real_size, symlnk);
+
+ if (!is_new_file)
+ fix_sd += wrong_first_direct_byte (&sd_ih.ih_key, fs->fs_blocksize,
+ &first_direct_byte, saved_first_direct_byte, real_size);
+
+ fix_sd += wrong_st_size (/*&sd_key,*/ &sd_ih.ih_key, is_new_file ? MAX_FILE_SIZE_V2 : MAX_FILE_SIZE_V1,
+ fs->fs_blocksize, &real_size, saved_size, 0/*not dir*/);
+
+ fix_sd += wrong_st_blocks (&sd_ih.ih_key, &blocks, saved_blocks, mode, is_new_file);
+
+ if (fix_sd) {
+ /* find stat data and correct it */
+ set_type_and_offset (KEY_FORMAT_1, &sd_ih.ih_key, SD_OFFSET, TYPE_STAT_DATA);
+ if (reiserfs_search_by_key_4 (fs, &sd_ih.ih_key, path) != ITEM_FOUND)
+ die ("rebuild_check_regular_file: stat data not found");
+
+ bh = get_bh (path);
+ ih = get_ih (path);
+ sd = get_item (path);
+ set_sd_size (ih, sd, &real_size);
+ set_sd_blocks (ih, sd, &blocks);
+ set_sd_mode (ih, sd, &mode);
+ if (!is_new_file)
+ set_sd_first_direct_byte (ih, sd, &first_direct_byte);
+ mark_buffer_dirty (bh);
+ }
+
+ return retval;
+}
+
+
+static int is_rootdir_key (struct key * key)
+{
+ if (comp_keys (key, &root_dir_key))
+ return 0;
+ return 1;
+}
+
+
+/* returns buffer, containing found directory item.*/
+static char * get_next_directory_item (struct key * key, /* on return this will
+ contain key of next item
+ in the tree */
+ struct key * parent,
+ struct item_head * ih,/*not in tree*/
+ __u32 * pos_in_item)
+{
+ INITIALIZE_PATH (path);
+ char * dir_item;
+ struct key * rdkey;
+ struct buffer_head * bh;
+ struct reiserfs_de_head * deh;
+ int i;
+ int retval;
+
+
+ if ((retval = reiserfs_search_by_entry_key (fs, key, &path)) != POSITION_FOUND)
+ reiserfs_panic ("get_next_directory_item: %k is not found", key);
+
+ /* leaf containing directory item */
+ bh = PATH_PLAST_BUFFER (&path);
+ *pos_in_item = path.pos_in_item;
+ *ih = *get_ih (&path);
+ deh = B_I_DEH (bh, ih);
+
+ /* make sure, that ".." exists as well */
+ if (get_offset (key) == DOT_OFFSET) {
+ if (get_ih_entry_count (ih) < 2 ||
+ name_in_entry_length (ih, deh + 1, 1) != 2 ||
+ strncmp (name_in_entry (deh + 1, 1), "..", 2))
+ {
+ fsck_log ("get_next_directory_item: \"..\" not found in %H\n", ih);
+ pathrelse (&path);
+ return 0;
+ }
+ }
+
+ /* mark hidden entries as visible, set "." and ".." correctly */
+ deh += *pos_in_item;
+ for (i = *pos_in_item; i < get_ih_entry_count (ih); i ++, deh ++) {
+ int namelen;
+ char * name;
+
+ name = name_in_entry (deh, i);
+ namelen = name_in_entry_length (ih, deh, i);
+ if (de_hidden (deh))
+ reiserfs_panic ("get_next_directory_item: item %k: hidden entry %d \'%.*s\'\n",
+ key, i, namelen, name);
+
+ if (get_deh_offset (deh) == DOT_OFFSET) {
+ if (not_of_one_file (&(deh->deh2_dir_id), key)) {
+ /* "." must point to the directory it is in */
+
+ //deh->deh_objectid != REISERFS_ROOT_PARENT_OBJECTID)/*????*/ {
+ fsck_log ("get_next_directory_item: %k: \".\" pointes to [%K], "
+ "should point to [%K]", key, (struct key *)(&(deh->deh2_dir_id)));
+ set_deh_dirid (deh, get_key_dirid (key));
+ set_deh_objectid (deh, get_key_objectid (key));
+ mark_buffer_dirty (bh);
+ fsck_log (" - fixed\n");
+ }
+ }
+
+ if (get_deh_offset (deh) == DOT_DOT_OFFSET) {
+ /* set ".." so that it points to the correct parent directory */
+ if (comp_short_keys (&(deh->deh2_dir_id), parent)) {
+ fsck_log ("get_next_directory_item: %k: \"..\" points to [%K], "
+ "should point to [%K]", key, (struct key *)(&(deh->deh2_dir_id)), parent);
+ set_deh_dirid (deh, get_key_dirid (parent));
+ set_deh_objectid (deh, get_key_objectid (parent));
+ mark_buffer_dirty (bh);
+ fsck_log (" - fixed\n");
+ }
+ }
+ }
+
+ /* copy directory item to the temporary buffer */
+ dir_item = getmem (get_ih_item_len (ih));
+ memcpy (dir_item, B_I_PITEM (bh, ih), get_ih_item_len (ih));
+
+
+ /* next item key */
+ if (PATH_LAST_POSITION (&path) == (B_NR_ITEMS (bh) - 1) &&
+ (rdkey = uget_rkey (&path)))
+ copy_key (key, rdkey);
+ else {
+ set_key_dirid (key, 0);
+ set_key_objectid (key, 0);
+ }
+
+ if (fsck_mode (fs) != FSCK_CHECK && fsck_mode (fs) != FSCK_FIX_FIXABLE)
+ mark_item_reachable (get_ih (&path), bh);
+ pathrelse (&path);
+
+ return dir_item;
+}
+
+
+// get key of an object pointed by direntry and the key of the entry itself
+void get_object_key (struct reiserfs_de_head * deh, struct key * key,
+ struct key * entry_key, struct item_head * ih)
+{
+ /* entry points to this key */
+ set_key_dirid (key, get_deh_dirid (deh));
+ set_key_objectid (key, get_deh_objectid (deh));
+ set_key_offset_v1 (key, SD_OFFSET);
+ set_key_uniqueness (key, 0);
+
+ /* key of entry */
+ set_key_dirid (entry_key, get_key_dirid (&ih->ih_key));
+ set_key_objectid (entry_key, get_key_objectid (&ih->ih_key));
+ set_key_offset_v1 (entry_key, get_deh_offset (deh));
+ set_key_uniqueness (entry_key, DIRENTRY_UNIQUENESS);
+}
+
+int fix_obviously_wrong_sd_mode (struct path * path) {
+ struct key * next_key = NULL;
+ __u16 mode;
+ int retval = 0;
+
+ next_key = reiserfs_next_key (path);
+
+ if (!next_key || not_of_one_file (next_key, &get_ih(path)->ih_key))
+ return 0;
+
+ /* next item exists and of the same file. Fix the SD mode */
+
+ if (not_a_directory (get_item (path)) && is_direntry_key (next_key)) {
+ /* make SD mode SD of dir */
+ get_sd_mode (get_ih (path), get_item (path), &mode);
+ fsck_log ("directory %K had broken mode %M, ", &get_ih(path)->ih_key, mode);
+ if (fsck_mode(fs) != FSCK_CHECK) {
+ mode &= ~S_IFMT;
+ mode |= S_IFDIR;
+ fsck_log ("fixed to %M\n", mode);
+ set_sd_mode (get_ih (path), get_item (path), &mode);
+ mark_buffer_dirty (get_bh(path));
+ }
+ retval = 1;
+ } else if (!not_a_directory (get_item (path)) && !is_direntry_key (next_key)) {
+ /* make SD mode SD of regular file */
+ get_sd_mode (get_ih (path), get_item (path), &mode);
+ fsck_log ("file %K had broken mode %M, ", &get_ih(path)->ih_key, mode);
+ if (fsck_mode(fs) != FSCK_CHECK) {
+ mode &= ~S_IFMT;
+ mode |= S_IFREG;
+ fsck_log ("fixed to %M\n", mode);
+ set_sd_mode (get_ih (path), get_item (path), &mode);
+ mark_buffer_dirty (get_bh(path));
+ }
+ retval = 1;
+ }
+
+ return retval;
+}
+
+/* check recursively the semantic tree. Returns OK if entry points to good
+ object, STAT_DATA_NOT_FOUND if stat data was not found or RELOCATED when
+ file was relocated because its objectid was already marked as used by
+ another file */
+int rebuild_semantic_pass (struct key * key, struct key * parent, int dot_dot,
+ struct item_head * new_ih)
+{
+ struct path path;
+ void * sd;
+ int is_new_dir;
+ __u32 nlink;
+ struct buffer_head * bh;
+ struct item_head * ih;
+ int retval, retval1;
+ char * dir_item;
+ __u32 pos_in_item;
+ struct item_head tmp_ih;
+ struct key item_key, entry_key, object_key;
+ __u64 dir_size;
+ __u32 blocks;
+ __u64 saved_size;
+ __u32 saved_blocks;
+ int fix_sd;
+ int relocate;
+ int dir_format = 0;
+ __u16 mode;
+
+
+ retval = OK;
+
+ start_again: /* when directory was relocated */
+
+ if (!KEY_IS_STAT_DATA_KEY (key))
+ reiserfs_panic ("rebuild_semantic_pass: key %k must be key of a stat data",
+ key);
+
+ /* look for stat data of an object */
+ if (reiserfs_search_by_key_4 (fs, key, &path) == ITEM_NOT_FOUND) {
+ pathrelse (&path);
+ if (is_rootdir_key (key))
+ /* root directory has to exist at this point */
+ reiserfs_panic ("rebuild_semantic_pass: root directory not found");
+
+ return STAT_DATA_NOT_FOUND;
+ }
+
+
+ /* stat data has been found */
+ bh = get_bh (&path);
+ ih = get_ih (&path);
+ sd = get_item(&path);
+
+ /* */
+ get_sd_nlink (ih, sd, &nlink);
+
+ relocate = 0;
+ if (!nlink) {
+ /* we reached the stat data for the first time */
+ if (is_objectid_really_used (semantic_id_map (fs), get_key_objectid (&ih->ih_key), &pos_in_item)) {
+ /* calculate number of found files/dirs who are using objectid
+ which is used by another file */
+ sem_pass_stat (fs)->oid_sharing ++;
+ if (1/*fsck_adjust_file_size (fs)*/)
+ /* this works for files only */
+ relocate = 1;
+ } else
+ __mark_objectid_really_used (semantic_id_map (fs), get_key_objectid (&ih->ih_key), pos_in_item);
+
+ mark_item_reachable (ih, bh);
+ }
+
+ fix_obviously_wrong_sd_mode (&path);
+
+ if (not_a_directory (sd)) {
+ retval = rebuild_check_regular_file (&path, sd, relocate ? new_ih : 0);
+ pathrelse (&path);
+ return retval;
+ }
+
+ if (relocate) {
+ if (!new_ih)
+ reiserfs_panic ("rebuild_semantic_pass: can not relocate %K",
+ &ih->ih_key);
+ *new_ih = *ih;
+ pathrelse (&path);
+ sem_pass_stat (fs)->oid_sharing_dirs_relocated ++;
+ relocate_dir (new_ih, 1);
+ *key = new_ih->ih_key;
+ retval = RELOCATED;
+ goto start_again;
+ }
+
+ /* it looks like stat data of a directory found */
+ if (nlink) {
+ /* we saw this directory already */
+ if (!dot_dot) {
+ /* this name is not ".." - and hard links are not allowed on
+ directories */
+ pathrelse (&path);
+ return STAT_DATA_NOT_FOUND;
+ } else {
+ /* ".." found */
+ nlink ++;
+ set_sd_nlink (ih, sd, &nlink);
+ mark_buffer_dirty (bh);
+ pathrelse (&path);
+ return OK;
+ }
+ }
+
+
+ /* we see the directory first time */
+ sem_pass_stat (fs)->directories ++;
+ nlink = 2;
+ if (get_key_objectid (key) == REISERFS_ROOT_OBJECTID)
+ nlink ++;
+ set_sd_nlink (ih, sd, &nlink);
+ mark_buffer_dirty (bh);
+
+ if (get_ih_item_len (ih) == SD_SIZE)
+ is_new_dir = 1;
+ else
+ is_new_dir = 0;
+
+
+/*
+ {
+ struct key * tmp;
+
+ // check next item: if it is not a directory item of the same file
+ // therefore sd_mode is corrupted so we just reset it to regular file
+ // mode
+ tmp = reiserfs_next_key (&path);
+ if (tmp && !not_of_one_file (tmp, key) && !is_direntry_key (tmp)) {
+ __u16 mode;
+
+ get_sd_mode (ih, sd, &mode);
+ fsck_log ("file %K had broken mode %M, ", key, mode);
+ mode &= ~S_IFMT;
+ mode |= S_IFREG;
+ fsck_log ("fixed to %M\n", mode);
+ set_sd_mode (ih, sd, &mode);
+
+ nlink = 0;
+ set_sd_nlink (ih, sd, &nlink);
+
+ retval = rebuild_check_regular_file (&path, sd, 0); //no relocate
+ pathrelse (&path);
+ return retval;
+ }
+ }
+*/
+
+
+ dir_format = (get_ih_item_len (get_ih (&path)) == SD_SIZE) ? KEY_FORMAT_2 : KEY_FORMAT_1;
+ /* save stat data's size and st_blocks */
+ get_sd_size (ih, sd, &saved_size);
+ get_sd_blocks (ih, sd, &saved_blocks);
+ get_sd_mode (ih, sd, &mode);
+
+ /* release path pointing to stat data */
+ pathrelse (&path);
+
+ /* make sure that "." and ".." exist */
+ reiserfs_add_entry (fs, key, ".", name_length (".", dir_format), key, 1 << IH_Unreachable);
+ reiserfs_add_entry (fs, key, "..", name_length ("..", dir_format), parent, 1 << IH_Unreachable);
+
+ set_key_dirid (&item_key, get_key_dirid (key));
+ set_key_objectid (&item_key, get_key_objectid (key));
+ set_key_offset_v1 (&item_key, DOT_OFFSET);
+ set_key_uniqueness (&item_key, DIRENTRY_UNIQUENESS);
+
+
+ dir_size = 0;
+ while ((dir_item = get_next_directory_item (&item_key, parent, &tmp_ih, &pos_in_item)) != 0) {
+ /* dir_item is copy of the item in separately allocated memory,
+ item_key is a key of next item in the tree */
+ int i;
+ char * name = 0;
+ int namelen, entry_len;
+ struct reiserfs_de_head * deh = (struct reiserfs_de_head *)dir_item + pos_in_item;
+
+ for (i = pos_in_item; i < get_ih_entry_count (&tmp_ih); i ++, deh ++) {
+ struct item_head relocated_ih;
+
+ if (name) {
+ free (name);
+ name = 0;
+ }
+
+ namelen = name_in_entry_length (&tmp_ih, deh, i);
+ asprintf (&name, "%.*s", namelen, name_in_entry (deh, i));
+
+ entry_len = entry_length (&tmp_ih, deh, i);
+
+ get_object_key (deh, &object_key, &entry_key, &tmp_ih);
+
+ if ((dir_format == KEY_FORMAT_2) && (entry_len % 8 != 0)) {
+ /* not alighed directory of new format - delete it */
+ fsck_log ("name \"%.*s\" in directory %K of wrong format, %K - fixed\n",
+ namelen, name, &tmp_ih.ih_key, (struct key *)&(deh->deh2_dir_id));
+ reiserfs_remove_entry (fs, &entry_key);
+ entry_len = name_length (name, dir_format);
+ reiserfs_add_entry (fs, key, name, entry_len,
+ (struct key *)&(deh->deh2_dir_id), 0);
+ }
+/*
+ if ((dir_format == KEY_FORMAT_1) && (namelen != entry_len)) {
+ // aligned entry in directory of old format - remove and insert it back
+ fsck_log ("name \"%.*s\" in directory %K of wrong format, %K - fixed\n",
+ namelen, name, &tmp_ih.ih_key, (struct key *)&(deh->deh2_dir_id));
+ reiserfs_remove_entry (fs, &entry_key);
+ entry_len = name_length (name, dir_format);
+ reiserfs_add_entry (fs, key, name, entry_len,
+ (struct key *)&(deh->deh2_dir_id), 0);
+ }
+*/
+ if (is_dot (name, namelen)) {
+ dir_size += DEH_SIZE + entry_len;
+ continue;
+ }
+
+ print_name (name, namelen);
+
+ if (!is_properly_hashed (fs, name, namelen, get_deh_offset (deh)))
+ reiserfs_panic ("rebuild_semantic_pass: name has to be hashed properly");
+
+
+ retval1 = rebuild_semantic_pass (&object_key, key, is_dot_dot (name, namelen), &relocated_ih);
+
+ erase_name (namelen);
+
+ switch (retval1) {
+ case OK:
+ dir_size += DEH_SIZE + entry_len;
+ break;
+
+ case STAT_DATA_NOT_FOUND:
+ case DIRECTORY_HAS_NO_ITEMS:
+ if (get_offset (&entry_key) == DOT_DOT_OFFSET &&
+ get_key_objectid (&object_key) == REISERFS_ROOT_PARENT_OBJECTID) {
+ /* ".." of root directory can not be found */
+ dir_size += DEH_SIZE + entry_len;
+ continue;
+ }
+ fsck_log ("name \"%.*s\" in directory %K points to nowhere %K - removed\n",
+ namelen, name, &tmp_ih.ih_key, (struct key *)&(deh->deh2_dir_id));
+ reiserfs_remove_entry (fs, &entry_key);
+ sem_pass_stat (fs)->deleted_entries ++;
+ break;
+
+ case RELOCATED:
+ /* file was relocated, update key in corresponding directory entry */
+ if (reiserfs_search_by_entry_key (fs, &entry_key, &path) != POSITION_FOUND) {
+ fsck_progress ("could not find name of relocated file\n");
+ } else {
+ /* update key dir entry points to */
+ struct reiserfs_de_head * tmp_deh;
+
+ tmp_deh = B_I_DEH (get_bh (&path), get_ih (&path)) + path.pos_in_item;
+ fsck_log ("name \"%.*s\" of dir %K pointing to %K updated to point to ",
+ namelen, name, &tmp_ih.ih_key, &tmp_deh->deh2_dir_id);
+ set_deh_dirid (tmp_deh, get_key_dirid (&relocated_ih.ih_key));
+ set_deh_objectid (tmp_deh, get_key_objectid (&relocated_ih.ih_key));
+
+ fsck_log ("%K\n", &tmp_deh->deh2_dir_id);
+ mark_buffer_dirty (get_bh (&path));
+ }
+ dir_size += DEH_SIZE + entry_len;
+ pathrelse (&path);
+ break;
+ }
+ } /* for */
+
+ freemem (dir_item);
+ free (name);
+ name = 0;
+
+ if (not_of_one_file (&item_key, key))
+ /* next key is not of this directory */
+ break;
+
+ } /* while (dir_item) */
+
+
+ if (dir_size == 0)
+ /* FIXME: is it possible? */
+ return DIRECTORY_HAS_NO_ITEMS;
+
+ /* calc correct value of sd_blocks field of stat data */
+ blocks = dir_size2st_blocks (dir_size);
+
+ fix_sd = 0;
+ fix_sd += wrong_st_blocks (key, &blocks, saved_blocks, mode, is_new_dir);
+ fix_sd += wrong_st_size (key, is_new_dir ? MAX_FILE_SIZE_V2 : MAX_FILE_SIZE_V1,
+ fs->fs_blocksize, &dir_size, saved_size, 1/*dir*/);
+
+ if (fix_sd) {
+ /* we have to fix either sd_size or sd_blocks, so look for stat data again */
+ if (reiserfs_search_by_key_4 (fs, key, &path) != ITEM_FOUND)
+ die ("rebuild_semantic_pass: stat data not found");
+
+ bh = get_bh (&path);
+ ih = get_ih (&path);
+ sd = get_item (&path);
+
+ set_sd_size (ih, sd, &dir_size);
+ set_sd_blocks (ih, sd, &blocks);
+ mark_buffer_dirty (bh);
+ pathrelse (&path);
+ }
+
+ return retval;
+}
+
+
+int is_dot (char * name, int namelen)
+{
+ return (namelen == 1 && name[0] == '.') ? 1 : 0;
+}
+
+
+int is_dot_dot (char * name, int namelen)
+{
+ return (namelen == 2 && name[0] == '.' && name[1] == '.') ? 1 : 0;
+}
+
+
+int not_a_directory (void * sd)
+{
+ /* mode is at the same place and of the same size in both stat
+ datas (v1 and v2) */
+ struct stat_data_v1 * sd_v1 = sd;
+
+ return !(S_ISDIR (le16_to_cpu (sd_v1->sd_mode)));
+}
+
+int not_a_regfile (void * sd)
+{
+ /* mode is at the same place and of the same size in both stat
+ datas (v1 and v2) */
+ struct stat_data_v1 * sd_v1 = sd;
+
+ return !(S_ISREG (le16_to_cpu (sd_v1->sd_mode)));
+}
+
+
+
+void zero_nlink (struct item_head * ih, void * sd)
+{
+ int zero = 0;
+
+ if (get_ih_item_len (ih) == SD_V1_SIZE && get_ih_key_format (ih) != KEY_FORMAT_1) {
+ fsck_log ("zero_nlink: %H had wrong keys format %d, fixed to %d",
+ ih, get_ih_key_format (ih), KEY_FORMAT_1);
+ set_ih_key_format (ih, KEY_FORMAT_1);
+ }
+ if (get_ih_item_len (ih) == SD_SIZE && get_ih_key_format (ih) != KEY_FORMAT_2) {
+ fsck_log ("zero_nlink: %H had wrong keys format %d, fixed to %d",
+ ih, get_ih_key_format (ih), KEY_FORMAT_2);
+ set_ih_key_format (ih, KEY_FORMAT_2);
+ }
+
+ set_sd_nlink (ih, sd, &zero);
+}
+
+
+
+void modify_item (struct item_head * ih, void * item)
+{
+ zero_nlink (ih, item);
+ mark_item_unreachable (ih);
+}
+
+
+/* mkreiserfs should have created this */
+static void make_sure_lost_found_exists (reiserfs_filsys_t * fs)
+{
+ int retval;
+ INITIALIZE_PATH (path);
+ int gen_counter;
+ __u32 objectid;
+ __u64 sd_size;
+ __u32 sd_blocks;
+ struct buffer_head * bh;
+ struct item_head * ih;
+ void * sd;
+ int item_len;
+
+
+ /* look for "lost+found" in the root directory */
+ retval = reiserfs_find_entry (fs, &root_dir_key,
+ "lost+found", &gen_counter,
+ &lost_found_dir_key);
+ if (!retval) {
+ objectid = get_unused_objectid (fs);
+ if (!objectid) {
+ fsck_progress ("make_sure_lost_found_exists: could not get objectid"
+ " for \"/lost+found\", will not link lost files\n");
+ return;
+ }
+ set_key_dirid (&lost_found_dir_key, REISERFS_ROOT_OBJECTID);
+ set_key_objectid (&lost_found_dir_key, objectid);
+ }
+
+
+ /* look for stat data of "lost+found" */
+ retval = reiserfs_search_by_key_4 (fs, &lost_found_dir_key, &path);
+ if (retval == ITEM_NOT_FOUND)
+ lost_found_dir_format = create_dir_sd (fs, &path, &lost_found_dir_key, modify_item);
+ else {
+ struct item_head * ih = get_ih (&path);
+
+ if (!is_stat_data_ih (ih))
+ reiserfs_panic ("It must be lost+found's stat data %k\n", &ih->ih_key);
+
+ fix_obviously_wrong_sd_mode (&path);
+
+ if (not_a_directory (get_item (&path))) {
+ fsck_progress ("make_sure_lost_found_exists: \"/lost+found\" is "
+ "not a directory, will not link lost files\n");
+ set_key_objectid (&lost_found_dir_key, 0);
+ pathrelse (&path);
+ return;
+ }
+
+ lost_found_dir_format = (get_ih_item_len (get_ih (&path)) == SD_SIZE) ? KEY_FORMAT_2 : KEY_FORMAT_1;
+
+ pathrelse (&path);
+ }
+
+ /* add "." and ".." if any of them do not exist */
+ reiserfs_add_entry (fs, &lost_found_dir_key, ".", name_length (".", lost_found_dir_format),
+ &lost_found_dir_key, 1 << IH_Unreachable);
+ reiserfs_add_entry (fs, &lost_found_dir_key, "..", name_length ("..", lost_found_dir_format),
+ &root_dir_key, 1 << IH_Unreachable);
+
+ item_len = reiserfs_add_entry (fs, &root_dir_key, "lost+found",
+ name_length ("lost+found", root_dir_format), &lost_found_dir_key, 1 << IH_Unreachable);
+
+ if (item_len) {
+ if (reiserfs_search_by_key_4 (fs, &root_dir_key, &path) == ITEM_NOT_FOUND)
+ reiserfs_panic ("make_sure_lost_found_exists: root sd must exists");
+
+ bh = get_bh (&path);
+ ih = get_ih (&path);
+ sd = get_item(&path);
+
+ get_sd_size (ih, sd, &sd_size);
+ sd_size += item_len;
+ set_sd_size (ih, sd, &sd_size);
+ sd_blocks = dir_size2st_blocks (sd_size);
+ set_sd_blocks (ih, sd, &sd_blocks);
+ mark_buffer_dirty (bh);
+ pathrelse (&path);
+ }
+
+ return;
+}
+
+static void save_rebuild_semantic_result (reiserfs_filsys_t * fs) {
+ FILE * file;
+ int retval;
+
+ /* save bitmaps with which we will be able start reiserfs from
+ pass 1 */
+ file = open_file ("temp_fsck_file.deleteme", "w+");
+ if (!file)
+ return;
+
+ reiserfs_begin_stage_info_save (file, SEMANTIC_DONE);
+ reiserfs_objectid_map_save (file, semantic_id_map (fs));
+ reiserfs_end_stage_info_save (file);
+ close_file (file);
+ retval = unlink (state_dump_file (fs));
+ retval = rename ("temp_fsck_file.deleteme", state_dump_file (fs));
+ if (retval != 0)
+ fsck_progress ("pass 0: could not rename temp file temp_fsck_file.deleteme to %s",
+ state_dump_file (fs));
+}
+
+/* we have nothing to load from a state file, but we have to fetch
+ on-disk bitmap, copy it to allocable bitmap, and fetch objectid
+ map */
+void load_semantic_result (FILE * file, reiserfs_filsys_t * fs)
+{
+ fsck_new_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb));
+ reiserfs_bitmap_copy (fsck_new_bitmap (fs), fs->fs_bitmap2);
+
+ fsck_allocable_bitmap (fs) = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb));
+ reiserfs_bitmap_copy (fsck_allocable_bitmap (fs), fs->fs_bitmap2);
+
+ fs->block_allocator = reiserfsck_reiserfs_new_blocknrs;
+ fs->block_deallocator = reiserfsck_reiserfs_free_block;
+
+ /* we need objectid map on semantic pass to be able to relocate files */
+ proper_id_map (fs) = init_id_map ();
+ fetch_objectid_map (proper_id_map (fs), fs);
+ semantic_id_map (fs) = reiserfs_objectid_map_load (file);
+}
+
+static void before_pass_3 (reiserfs_filsys_t * fs)
+{
+ semantic_id_map (fs) = init_id_map ();
+}
+
+static void after_pass_3 (reiserfs_filsys_t * fs)
+{
+ /* update super block: objectid map, fsck state */
+ set_sb_fs_state (fs->fs_ondisk_sb, SEMANTIC_DONE);
+ mark_buffer_dirty (fs->fs_super_bh);
+
+ /* write all dirty blocks */
+ fsck_progress ("Flushing..");
+ flush_objectid_map (proper_id_map (fs), fs);
+ fs->fs_dirt = 1;
+ reiserfs_flush_to_ondisk_bitmap (fsck_new_bitmap(fs), fs);
+ reiserfs_flush (fs);
+ fsck_progress ("done\n");
+
+ stage_report (3, fs);
+
+ if (!fsck_run_one_step (fs)) {
+ if (fsck_user_confirmed (fs, "Continue? (Yes):", "Yes\n", 1))
+ /* reiserfsck continues */
+ return;
+ }
+
+ save_rebuild_semantic_result (fs);
+
+ free_id_map (proper_id_map (fs));
+ proper_id_map (fs) = 0;
+
+ fs->fs_dirt = 1;
+ reiserfs_close (fs);
+ exit (4);
+}
+
+/* this is part of rebuild tree */
+void pass_3_semantic (reiserfs_filsys_t * fs)
+{
+ before_pass_3 (fs);
+
+ fsck_progress ("Pass 3 (semantic):\n");
+
+ /* when warnings go not to stderr - separate then in the log */
+ if (fsck_log_file (fs) != stderr)
+ fsck_log ("####### Pass 3 #########\n");
+
+
+ if (!fs->fs_hash_function)
+ reiserfs_panic ("Hash function should be selected already");
+
+ make_sure_root_dir_exists (fs, modify_item, 1 << IH_Unreachable);
+ make_sure_lost_found_exists (fs);
+
+ mark_objectid_really_used (proper_id_map (fs), get_key_objectid (&root_dir_key));
+ mark_objectid_really_used (proper_id_map (fs), get_key_objectid (&lost_found_dir_key));
+
+ /* link all relocated files into /lost+found directory */
+ link_relocated_files ();
+
+ rebuild_semantic_pass (&root_dir_key, &parent_root_dir_key, 0/*!dot_dot*/, 0/*reloc_ih*/);
+
+ add_badblock_list(fs, 1);
+
+ after_pass_3 (fs);
+}
diff --git a/fsck/super.c b/fsck/super.c
new file mode 100644
index 0000000..c4d4f91
--- /dev/null
+++ b/fsck/super.c
@@ -0,0 +1,552 @@
+#include "fsck.h"
+#include <stdlib.h>
+
+#define fsck_conditional_log(sb_found, fmt, list...) { \
+ if (sb_found) \
+ fsck_log(fmt, ## list); \
+}
+
+int what_fs_version ()
+{
+ size_t n = 0;
+ char * answer = 0;
+ int version;
+ printf("\nwhat is version of ReiserFS you use[1-4]\n"
+ "\t(1) 3.6.x\n"
+ "\t(2) >=3.5.9 (introduced in the middle of 1999) (if you use linux 2.2, choose this one)\n"
+ "\t(3) < 3.5.9 converted to new format (don't choose if unsure)\n"
+ "\t(4) < 3.5.9 (this is very old format, don't choose if unsure)\n"
+ "\t(X) exit\n");
+ getline (&answer, &n, stdin);
+ version = atoi (answer);
+ if (version < 1 || version > 4)
+ die ("rebuild_sb: wrong version");
+ return version;
+}
+
+void rebuild_sb (reiserfs_filsys_t * fs, char * filename, struct fsck_data * data)
+{
+ int version = 0;
+ struct reiserfs_super_block * ondisk_sb = 0;
+ struct reiserfs_super_block * sb = 0;
+
+ int magic_was_found = 0;
+ unsigned long block_count = 0;
+ __u16 p_oid_maxsize;
+ __u16 p_bmap_nr;
+ __u32 p_jp_journal_1st_block = 0;
+ __u32 p_jp_dev_size = 0;
+ int standard_journal = -1;
+ char * journal_dev_name = 0;
+ char * tmp;
+ int sb_size;
+
+ char * answer = 0;
+ size_t n = 0;
+ struct stat stat_buf;
+ int retval;
+
+ if (!no_reiserfs_found (fs)) {
+ sb = getmem (sizeof (*sb));
+ if (!is_opened_rw (fs)) {
+ close (fs->fs_dev);
+ fs->fs_dev = open (fs->fs_file_name, O_RDWR | O_LARGEFILE);
+ }
+
+ if (!is_blocksize_correct (fs->fs_blocksize)) {
+ printf("\nCannot find a proper blocksize, enter block size [4096]: \n");
+ getline (&answer, &n, stdin);
+ if (strcmp(answer, "\n")) {
+ retval = (int) strtol (answer, &tmp, 0);
+ if ((*tmp && strcmp(tmp, "\n")) || retval < 0)
+ reiserfs_exit (1, "rebuild_sb: wrong block size specified\n");
+ if (!is_blocksize_correct (retval))
+ reiserfs_exit (1, "rebuild_sb: wrong block size specified, only divisible by 1024 are supported currently\n");
+ } else
+ retval = 4096;
+
+ fs->fs_blocksize = retval;
+ }
+
+ block_count = count_blocks (filename, fs->fs_blocksize);
+
+ /* save ondisk_sb somewhere and work in temp area */
+ ondisk_sb = fs->fs_ondisk_sb;
+ memcpy (sb, fs->fs_ondisk_sb, sizeof (*sb));
+ fs->fs_ondisk_sb = sb;
+
+ if (is_reiserfs_3_6_magic_string (sb)) {
+ /* 3_6 magic */
+ if (fsck_data (fs)->journal_dev_name)
+ /* journal dev must not be specified with standard journal */
+ reiserfs_exit (1, "Reiserfs with standard journal found, but there was specified a journal dev");
+
+ if (get_jp_journal_1st_block(sb_jp(sb)) == get_journal_new_start_must (fs))
+ version = 1;
+ else if (get_jp_journal_1st_block(sb_jp(sb)) == get_journal_old_start_must (fs))
+ version = 3;
+ magic_was_found = 2;
+ } else if (is_reiserfs_3_5_magic_string (sb)) {
+ if (fsck_data (fs)->journal_dev_name)
+ /* journal dev must not be specified with standard journal */
+ reiserfs_exit (1, "Reiserfs with standard journal found, but there was specified a journal dev");
+
+ /* 3_5 magic */
+ if (get_jp_journal_1st_block(sb_jp(sb)) == get_journal_new_start_must (fs))
+ version = 2;
+ else if (get_jp_journal_1st_block(sb_jp(sb)) == get_journal_old_start_must (fs))
+ version = 4;
+ magic_was_found = 1;
+ } else if (is_reiserfs_jr_magic_string (sb)) {
+ if (!fsck_data (fs)->journal_dev_name)
+ /* journal dev must be specified with non standard journal */
+ reiserfs_exit (1, "Reiserfs with non standard journal found, but there was not specified any journal dev");
+
+ if (get_sb_version (sb) == REISERFS_FORMAT_3_6) {
+ /*non-standard magic + sb_format == 3_6*/
+ if (get_jp_journal_1st_block(sb_jp(sb)) == get_journal_new_start_must (fs))
+ version = 1;
+ else if (get_jp_journal_1st_block(sb_jp(sb)) == get_journal_old_start_must (fs))
+ version = 3;
+ magic_was_found = 3;
+ } else if (get_sb_version (sb) == REISERFS_FORMAT_3_5) {
+ /* non-standard magic + sb_format == 3_5 */
+ if (get_jp_journal_1st_block(sb_jp(sb)) == get_journal_new_start_must (fs))
+ version = 2;
+ else if (get_jp_journal_1st_block(sb_jp(sb)) == get_journal_old_start_must (fs))
+ version = 4;
+ magic_was_found = 3;
+ } else {
+ /* non-standard magic + bad sb_format */
+ version = 0;
+ magic_was_found = 3;
+ }
+ } else
+ reiserfs_exit (1, "we opened device but there is no magic and there is no correct superbblock format found");
+
+ if (magic_was_found == 1 || magic_was_found == 2)
+ standard_journal = 1;
+ else
+ standard_journal = 0;
+
+ if (version == 0)
+ version = what_fs_version ();
+
+ if (get_sb_block_count (sb) != block_count) {
+ do {
+ printf("\nDid you use resiser(y/n)[n]: ");
+ getline (&answer, &n, stdin);
+ } while (strcmp ("y\n", answer) && strcmp ("n\n", answer) && strcmp ("\n", answer));
+ if (!strcmp ("y\n", answer)) {
+ printf("\nEnter partition size [%lu]: ", block_count);
+ getline (&answer, &n, stdin);
+ if (strcmp ("\n", answer))
+ block_count = atoi (answer);
+ set_sb_block_count (sb, block_count);
+ } else {
+ fsck_conditional_log (magic_was_found, "rebuild-sb: wrong block count occured (%lu), fixed (%lu)\n",
+ get_sb_block_count(sb), block_count);
+ set_sb_block_count (sb, block_count);
+ }
+ }
+
+ if (get_sb_block_size (sb) != fs->fs_blocksize) {
+ fsck_log("rebuild-sb: wrong block size occured (%lu), fixed (%lu)\n", get_sb_block_size (sb), fs->fs_blocksize);
+ set_sb_block_size (sb, fs->fs_blocksize);
+ }
+ }
+
+ /* if no reiserfs_found or bad data found in that SB, what was checked in previous clause */
+ if (no_reiserfs_found (fs)) {
+ int fd;
+
+ fd = open (filename, O_RDWR | O_LARGEFILE);
+
+ if (fd == -1)
+ reiserfs_exit (1, "rebuils_sb: cannot open device %s", filename);
+
+ version = what_fs_version ();
+
+ if (version == 3 || version == 4) {
+ retval = 4096;
+ } else {
+ printf("\nEnter block size [4096]: \n");
+ getline (&answer, &n, stdin);
+ if (strcmp(answer, "\n")) {
+ retval = (int) strtol (answer, &tmp, 0);
+ if ((*tmp && strcmp(tmp, "\n")) || retval < 0)
+ reiserfs_exit (1, "rebuild_sb: wrong block size specified\n");
+ if (!is_blocksize_correct (retval))
+ reiserfs_exit (1, "rebuild_sb: wrong block size specified, only divisible by 1024 are supported currently\n");
+ } else
+ retval = 4096;
+ }
+
+ block_count = count_blocks (filename, retval);
+
+ switch(version){
+ case 1:
+ fs = reiserfs_create (filename, REISERFS_FORMAT_3_6, block_count, retval, 1, 1);
+ break;
+ case 2:
+ fs = reiserfs_create (filename, REISERFS_FORMAT_3_5, block_count, retval, 1, 1);
+ break;
+ case 3:
+ fs = reiserfs_create (filename, REISERFS_FORMAT_3_6, block_count, retval, 1, 0);
+ break;
+ case 4:
+ fs = reiserfs_create (filename, REISERFS_FORMAT_3_5, block_count, retval, 1, 0);
+ break;
+ }
+
+ sb = fs->fs_ondisk_sb;
+ fs->fs_vp = data;
+
+ if (!fsck_skip_journal (fs)) {
+ if (!fsck_data (fs)->journal_dev_name) {
+ do {
+ printf("\nNo journal device was specified. (If journal is not available, re-run with --no-journal-available).\n"\
+ "Is journal standard? (y/n)[y]: ");
+ getline (&answer, &n, stdin);
+ } while (strcmp ("y\n", answer) && strcmp ("n\n", answer) && strcmp ("\n", answer));
+ if (!strcmp ("n\n", answer)) {
+ printf("\nSpecify journal device with -j option. Use \n");
+ exit(1);
+ }
+ standard_journal = 1;
+ } else {
+ standard_journal = 0;
+ memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_JR_SUPER_MAGIC_STRING,
+ strlen (REISERFS_JR_SUPER_MAGIC_STRING));
+ }
+ }
+
+ do {
+ printf("\nDid you use resiser(y/n)[n]: ");
+ getline (&answer, &n, stdin);
+ } while (strcmp ("y\n", answer) && strcmp ("n\n", answer) && strcmp ("\n", answer));
+ if (!strcmp ("y\n", answer)) {
+ printf("\nEnter partition size [%lu]: ", block_count);
+ getline (&answer, &n, stdin);
+ if (strcmp ("\n", answer))
+ block_count = atoi (answer);
+ set_sb_block_count (sb, block_count);
+ }
+
+ set_sb_fs_state (sb, REISERFS_CORRUPTED);
+ }
+
+
+ if (version == 1 || version == 3) {
+ if (get_reiserfs_format (sb) != REISERFS_FORMAT_3_6) {
+ fsck_log("rebuild-sb: wrong reiserfs version occured (%lu), fixed (%lu)\n", get_reiserfs_format (sb), REISERFS_FORMAT_3_6);
+ set_sb_version (sb, REISERFS_FORMAT_3_6);
+ }
+ } else if (version == 2 || version == 4) {
+ if (get_reiserfs_format (sb) != REISERFS_FORMAT_3_5) {
+ fsck_log("rebuild-sb: wrong reiserfs version occured (%lu), fixed (%lu)\n", get_reiserfs_format (sb), REISERFS_FORMAT_3_5);
+ set_sb_version (sb, REISERFS_FORMAT_3_5);
+ }
+ }
+
+ p_oid_maxsize = (fs->fs_blocksize - reiserfs_super_block_size (sb)) / sizeof(__u32) / 2 * 2;
+ if (get_sb_oid_maxsize (sb) != p_oid_maxsize) {
+ fsck_log("rebuild-sb: wrong objectid map max size occured (%lu), fixed (%lu)\n", get_sb_oid_maxsize (sb), p_oid_maxsize);
+ set_sb_oid_maxsize (sb, p_oid_maxsize);
+ }
+
+ p_bmap_nr = (block_count + (fs->fs_blocksize * 8 - 1)) / (fs->fs_blocksize * 8);
+ if (get_sb_bmap_nr (sb) != p_bmap_nr) {
+ fsck_log("rebuild-sb: wrong bitmap number occured (%lu), fixed (%lu)\n", get_sb_bmap_nr (sb), p_bmap_nr);
+ set_sb_bmap_nr (sb, (block_count + (fs->fs_blocksize * 8 - 1)) / (fs->fs_blocksize * 8));
+ }
+
+ if (get_sb_root_block (sb) > block_count) {
+ fsck_log("rebuild-sb: wrong root block occured (%lu), zeroed\n", get_sb_root_block (sb));
+ set_sb_root_block (sb, 0);
+ }
+
+ if (get_sb_free_blocks (sb) > block_count) {
+ fsck_log ("rebuild-sb: wrong free block count occured (%lu), zeroed\n", get_sb_free_blocks (sb));
+ set_sb_free_blocks (sb, 0);
+ }
+
+ if (get_sb_umount_state (sb) != REISERFS_CLEANLY_UMOUNTED && get_sb_umount_state (sb) != REISERFS_NOT_CLEANLY_UMOUNTED) {
+ fsck_conditional_log (magic_was_found, "rebuild-sb: wrong umount state, fixed to (REISERFS_NOT_CLEANLY_UMOUNTED)\n",
+ get_sb_umount_state (sb));
+ set_sb_umount_state (sb, REISERFS_NOT_CLEANLY_UMOUNTED);
+ }
+
+ if (get_sb_oid_cursize (sb) == 1 || get_sb_oid_cursize (sb) > get_sb_oid_maxsize (sb)) {
+ fsck_log("rebuild-sb: wrong objectid map occured (%lu), zeroed\n", get_sb_oid_cursize (sb));
+ set_sb_oid_cursize (sb, 0);
+ }
+
+ if ( get_sb_tree_height (sb) &&
+ ((get_sb_tree_height (sb) < DISK_LEAF_NODE_LEVEL + 1) ||
+ (get_sb_tree_height (sb) > MAX_HEIGHT)) ) {
+ fsck_log("rebuild-sb: wrong tree height occured, zeroed\n", get_sb_tree_height (sb));
+ set_sb_tree_height (sb, 0);
+ }
+
+ if (get_sb_hash_code (sb) && code2name (get_sb_hash_code (sb)) == 0) {
+ fsck_log("rebuild-sb: wrong hash occured (%lu), zeroed\n", get_sb_hash_code (sb));
+ set_sb_hash_code (sb, 0);
+ }
+
+ if (version == 1 || version == 3) {
+ if (!uuid_is_correct(sb->s_uuid)) {
+ if (generate_random_uuid (sb->s_uuid)) {
+ fsck_log ("rebuild-sb: no uuid found, failed to genetate UUID\n");
+ } else {
+ fsck_log ("rebuild-sb: no uuid found, a new uuid generated (%U)\n", sb->s_uuid);
+ }
+ }
+ if (sb->s_flags != 0 && sb->s_flags != 1) {
+ fsck_log ("rebuild-sb: super block flags found, zeroed\n",
+ sb->s_flags);
+ sb->s_flags = 0;
+ }
+ }
+
+
+ /*
+ if we have a standard journal
+ reserved = 0
+ dev - same
+ size = journal_default_size(fs->fs_super_bh->b_blocknr, fs)
+ offset = journal_default_size(fs)
+ if we have a non standard journal
+ if we found magic string
+ try to find a jhead and comare dev, size, offset there
+ if params are not equal move to "if we did not find a magic string" clause
+ if we did not find a magic string
+ ask user about his journal
+ try to find a jhead and comare dev, size, offset there
+ if params are not equal exit with error
+ */
+
+
+ p_jp_journal_1st_block = get_journal_start_must (fs);
+
+ if (!fsck_skip_journal (fs) && standard_journal == 1) {
+ if (get_jp_journal_dev (sb_jp(sb)) != 0) {
+ fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal device occured (%lu), fixed (0)\n",
+ get_jp_journal_dev (sb_jp(sb)));
+ set_jp_journal_dev (sb_jp(sb), 0);
+ }
+ if (get_sb_reserved_for_journal (sb) != 0) {
+ fsck_log ("rebuild-sb: wrong size reserved for standard journal occured (%lu), fixed (0)\n",
+ get_sb_reserved_for_journal (sb));
+ set_sb_reserved_for_journal (sb, 0);
+ }
+ if (get_jp_journal_1st_block (sb_jp(sb)) != p_jp_journal_1st_block) {
+ fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal first block occured (%lu), fixed (%lu)\n",
+ get_jp_journal_1st_block (sb_jp(sb)), p_jp_journal_1st_block);
+ set_jp_journal_1st_block (sb_jp(sb) , p_jp_journal_1st_block);
+ }
+ if (get_jp_journal_size (sb_jp(sb)) != journal_default_size(fs->fs_super_bh->b_blocknr, fs->fs_blocksize)) {
+ fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal size occured (%lu), fixed (%lu)\n",
+ get_jp_journal_size (sb_jp(sb)) + 1,
+ journal_default_size (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1);
+ set_jp_journal_size (sb_jp(sb), journal_default_size (fs->fs_super_bh->b_blocknr, fs->fs_blocksize));
+ }
+ if (get_jp_journal_max_trans_len (sb_jp(sb)) !=
+ advise_journal_max_trans_len( get_jp_journal_max_trans_len (sb_jp(sb)),
+ get_jp_journal_size (sb_jp(sb)),
+ fs->fs_blocksize))
+ {
+ fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal max transaction length occured (%lu), fixed (%d)\n",
+ get_jp_journal_max_trans_len (sb_jp(sb)),
+ advise_journal_max_trans_len ( get_jp_journal_max_trans_len (sb_jp(sb)),
+ get_jp_journal_size (sb_jp(sb)),
+ fs->fs_blocksize));
+ set_jp_journal_max_trans_len (sb_jp(sb),
+ advise_journal_max_trans_len( get_jp_journal_max_trans_len (sb_jp(sb)),
+ get_jp_journal_size (sb_jp(sb)),
+ fs->fs_blocksize));
+ }
+/* if (get_jp_journal_magic (sb_jp(sb)) != 0) {
+ fsck_log ("rebuild-sb: wrong journal magic occured (%lu), fixed (0)\n", get_jp_journal_magic (sb_jp(sb)));
+ set_jp_journal_magic (sb_jp(sb), 0);
+ }*/
+ if (get_jp_journal_max_batch (sb_jp(sb)) != advise_journal_max_batch(get_jp_journal_max_trans_len (sb_jp(sb)))) {
+ fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal max batch size occured (%lu), fixed (%d)\n",
+ get_jp_journal_max_batch (sb_jp(sb)), advise_journal_max_batch(get_jp_journal_max_trans_len (sb_jp(sb))));
+ set_jp_journal_max_batch (sb_jp(sb), advise_journal_max_batch(get_jp_journal_max_trans_len (sb_jp(sb))));
+ }
+ if (get_jp_journal_max_commit_age (sb_jp(sb)) != advise_journal_max_commit_age()) {
+ fsck_conditional_log (magic_was_found, "rebuild-sb: wrong journal max commit age occured (%lu), fixed (%d)\n",
+ get_jp_journal_max_commit_age (sb_jp(sb)), advise_journal_max_commit_age());
+ set_jp_journal_max_commit_age (sb_jp(sb), advise_journal_max_commit_age());
+ }
+ if (get_jp_journal_max_trans_age (sb_jp(sb)) != advise_journal_max_trans_age()) {
+ fsck_log ("rebuild-sb: wrong journal max commit age occured (%lu), fixed (0)\n",
+ get_jp_journal_max_trans_age (sb_jp(sb)), advise_journal_max_trans_age());
+ set_jp_journal_max_trans_age (sb_jp(sb), advise_journal_max_trans_age());
+ }
+
+
+
+ } else if (!fsck_skip_journal(fs) && standard_journal == 0) {
+ /* non standard journal */
+ struct reiserfs_journal_header * jh;
+
+ journal_dev_name = fsck_data (fs)->journal_dev_name;
+ retval = stat(journal_dev_name, &stat_buf);
+ if (retval == -1)
+ reiserfs_exit (1, "rebuild_sb: wrong journal device specified\n");
+ if (strcmp (fs->fs_file_name, journal_dev_name))
+ set_jp_journal_dev (sb_jp(sb), stat_buf.st_rdev);
+ else
+ set_jp_journal_dev (sb_jp(sb), 0);
+
+/*
+ if (journal_dev_name == 0) {
+ // ask user about the dev
+ printf("\nEnter dev with journal[%s]: \n", fs->fs_file_name);
+ getline (&answer, &n, stdin);
+ if (strcmp(answer, "\n")) {
+ journal_dev_name = malloc (strlen(answer));
+ strncpy(journal_dev_name, answer, strlen(answer) - 1);
+ retval = stat(journal_dev_name, &stat_buf);
+ if (retval == -1)
+ die ("rebuild_sb: wrong device specified\n");
+ if (strcmp (fs->fs_file_name, journal_dev_name))
+ set_jp_journal_dev (sb_jp(sb), stat_buf.st_rdev);
+ else
+ set_jp_journal_dev (sb_jp(sb), 0);
+ } else {
+ set_jp_journal_dev (sb_jp(sb), 0);
+ journal_dev_name = fs->fs_file_name;
+ }
+ }
+*/
+ retval = -1;
+ if (magic_was_found == 0 || (retval = reiserfs_open_journal (fs, journal_dev_name, O_RDONLY)) == 0) {
+ __u64 default_value;
+ /* journal header was not found or journal cannot be opened -> adjust journal size and offset */
+
+ /* default offset if magic was not found is 0 for relocated journal and get_journal_start_must
+ for any journal on the same device;
+ default offset if magic was found is found value */
+ if (retval == 0)
+ fsck_log ("Journal cannot be opened, assuming specified journal device is correct\n");
+
+ if (magic_was_found == 0)
+ default_value = (!strcmp(fs->fs_file_name, journal_dev_name)) ? p_jp_journal_1st_block : 0;
+ else
+ default_value = get_jp_journal_1st_block (sb_jp(sb));
+
+ printf("\nEnter journal offset on %s in blocks [%Lu]: \n",
+ journal_dev_name, (unsigned long long)default_value);
+
+ getline (&answer, &n, stdin);
+ if (strcmp(answer, "\n")) {
+ retval = (int) strtol (answer, &tmp, 0);
+ if ((*tmp && strcmp(tmp, "\n")) || retval < 0)
+ reiserfs_exit (1, "rebuild_sb: wrong offset specified\n");
+ set_jp_journal_1st_block (sb_jp(sb), retval);
+ } else
+ set_jp_journal_1st_block (sb_jp(sb), default_value);
+
+ p_jp_dev_size = count_blocks (journal_dev_name, fs->fs_blocksize);
+ /* some checks for journal offset */
+ if (strcmp(fs->fs_file_name, journal_dev_name) != 0) {
+ if (p_jp_dev_size < get_jp_journal_1st_block (sb_jp(sb)) + 1)
+ reiserfs_exit (1, "rebuild_sb: offset is much then device size\n");
+ }
+
+ /* default size if magic was not found is device size - journal_1st_block;
+ default size if magic was found is found value + 1 block for journal header */
+ if (magic_was_found == 0)
+ default_value = (!strcmp(fs->fs_file_name, journal_dev_name)) ?
+ journal_default_size (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1 :
+ p_jp_dev_size - get_jp_journal_1st_block (sb_jp(sb));
+ else
+ default_value = get_jp_journal_size (sb_jp(sb)) + 1;
+
+
+ printf("\nEnter journal size (including 1 block for journal header) on %s in blocks [%Lu]: \n",
+ journal_dev_name, (unsigned long long)default_value);
+
+ getline (&answer, &n, stdin);
+ if (strcmp(answer, "\n")) {
+ retval = (int) strtol (answer, &tmp, 0);
+ if ((*tmp && strcmp(tmp, "\n")) || retval < 0)
+ reiserfs_exit (1, "rebuild_sb: wrong offset specified\n");
+ set_jp_journal_size (sb_jp(sb), retval - 1);
+ } else {
+ set_jp_journal_size (sb_jp(sb), default_value - 1);
+ }
+
+ /* some checks for journal size */
+ if (get_jp_journal_size (sb_jp(sb)) +
+ get_jp_journal_1st_block (sb_jp(sb)) + 1 > p_jp_dev_size)
+ reiserfs_exit (1, "rebuild_sb: journal offset + journal size is much then device size\n");
+
+ if (reiserfs_open_journal (fs, journal_dev_name, O_RDONLY) == 0)
+ reiserfs_exit (1, "rebuild-sb: journal header is not found, wrong dev/offset/size configuration\n");
+ }
+
+ jh = (struct reiserfs_journal_header *)fs->fs_jh_bh->b_data;
+ memcpy (sb_jp(sb), &jh->jh_journal, sizeof (struct journal_params));
+ } else {
+ fsck_log ("Journal was specified as not available, zeroing all journal fields in super block..");
+ set_jp_journal_dev (sb_jp(sb), 0);
+ set_sb_reserved_for_journal (sb, 0);
+ set_jp_journal_1st_block (sb_jp(sb) , 0);
+ set_jp_journal_size (sb_jp(sb), 0);
+ set_jp_journal_max_trans_len (sb_jp(sb), 0);
+ set_jp_journal_max_batch (sb_jp(sb), 0);
+ set_jp_journal_max_commit_age (sb_jp(sb), 0);
+ set_jp_journal_max_commit_age (sb_jp(sb), 0);
+ }
+
+ /* whether journal header contains params with the same dev, offset, size will be
+ checked in open_journal */
+
+ if (version == 1 || version == 3)
+ sb_size = SB_SIZE;
+ else
+ sb_size = SB_SIZE_V1;
+
+ if (!magic_was_found || memcmp(ondisk_sb, sb, sb_size -
+ ((sb_size == SB_SIZE) ? sizeof(fs->fs_ondisk_sb->s_unused) : 0)) )
+ {
+ /* smth was changed in SB or a new one has been built */
+ set_sb_fs_state (sb, get_sb_fs_state (sb) || REISERFS_CORRUPTED);
+
+ if (ondisk_sb) {
+ /* if super_block was found, we keep sb in ondisk_sb */
+ fs->fs_ondisk_sb = ondisk_sb;
+ memcpy (ondisk_sb, sb, sb_size);
+ freemem(sb);
+ }
+
+ print_block (stderr, fs, fs->fs_super_bh);
+
+ if (user_confirmed (stderr, "Is this ok ? (y/n)[n]: ", "y\n")) {
+ mark_buffer_uptodate (fs->fs_super_bh, 1);
+ mark_buffer_dirty (fs->fs_super_bh);
+ bwrite (fs->fs_super_bh);
+ fsck_progress ("\nDo not forget to run reiserfsck --rebuild-tree\n\n");
+ } else {
+ mark_buffer_clean (fs->fs_super_bh);
+ fsck_progress ("Super block was not written\n");
+ }
+ } else {
+ print_block (stderr, fs, fs->fs_super_bh);
+
+ mark_buffer_clean (fs->fs_super_bh);
+ fsck_progress ("\nSuper block seems to be correct\n\n");
+ }
+}
+
+/* if (version == 0) {
+ brelse (fs->fs_super_bh);
+ freemem (fs);
+ close (fs->fs_dev);
+ fs = NULL;
+ }
+*/
diff --git a/fsck/ubitmap.c b/fsck/ubitmap.c
index 76e5b78..7342a02 100644
--- a/fsck/ubitmap.c
+++ b/fsck/ubitmap.c
@@ -1,5 +1,5 @@
/*
- * Copyright 1996-1999 Hans Reiser
+ * Copyright 1996-2002 Hans Reiser
*/
#include "fsck.h"
@@ -40,11 +40,6 @@
*/
-int is_to_be_read (reiserfs_filsys_t fs, unsigned long block)
-{
- return reiserfs_bitmap_test_bit (fsck_disk_bitmap (fs), block);
-}
-
/* is blocks used (marked by 1 in new bitmap) in the tree which is being built
(as leaf, internal, bitmap, or unformatted node) */
@@ -54,12 +49,21 @@ int is_block_used (unsigned long block)
}
-void mark_block_used (unsigned long block)
+void check_hardware_msg (void) {
+ fprintf(stderr, "\nThe problem has occured looks like a hardware problem.\n"\
+ "Send us the bug report only if the second run dies at the same place \n"\
+ "with the same block number.\n");
+}
+
+void mark_block_used (unsigned long block, int check_hardware)
{
if (!block)
return;
- if (is_block_used (block))
+ if (is_block_used (block)) {
+ if (check_hardware)
+ check_hardware_msg();
die ("mark_block_used: (%lu) used already", block);
+ }
reiserfs_bitmap_set_bit (fsck_new_bitmap (fs), block);
}
@@ -68,7 +72,7 @@ void mark_block_used (unsigned long block)
void mark_block_free (unsigned long block)
{
if (!is_block_used (block))
- die ("mark_block_used: (%lu) is free", block);
+ die ("mark_block_free: (%lu) is free already", block);
reiserfs_bitmap_clear_bit (fsck_new_bitmap (fs), block);
}
@@ -76,7 +80,7 @@ void mark_block_free (unsigned long block)
int is_block_uninsertable (unsigned long block)
{
- return !reiserfs_bitmap_test_bit (uninsertable_leaf_bitmap, block);
+ return !reiserfs_bitmap_test_bit (fsck_uninsertables (fs), block);
}
@@ -86,11 +90,14 @@ void mark_block_uninsertable (unsigned long block)
if (is_block_uninsertable (block))
die ("mark_block_uninsertable: (%lu) is uninsertable already", block);
- reiserfs_bitmap_clear_bit (uninsertable_leaf_bitmap, block);
+ reiserfs_bitmap_clear_bit (fsck_uninsertables (fs), block);
+ /* we do not need thsi actually */
+ pass_1_stat (fs)->uninsertable_leaves ++;
}
-int reiserfsck_reiserfs_new_blocknrs (reiserfs_filsys_t fs,
+/* FIXME: should be able to work around no disk space */
+int reiserfsck_reiserfs_new_blocknrs (reiserfs_filsys_t * fs,
unsigned long * free_blocknrs,
unsigned long start, int amount_needed)
{
@@ -102,7 +109,7 @@ int reiserfsck_reiserfs_new_blocknrs (reiserfs_filsys_t fs,
free_blocknrs[i] = alloc_block ();
if (!free_blocknrs[i])
die ("reiserfs_new_blocknrs: 0 is allocated");
- mark_block_used (free_blocknrs[i]);
+ mark_block_used (free_blocknrs[i], 0);
}
return CARRY_ON;
}
@@ -119,13 +126,13 @@ struct buffer_head * reiserfsck_get_new_buffer (unsigned long start)
struct buffer_head * bh = NULL;
reiserfs_new_blocknrs (fs, &blocknr, start, 1);
- bh = getblk (fs->s_dev, blocknr, fs->s_blocksize);
+ bh = getblk (fs->fs_dev, blocknr, fs->fs_blocksize);
return bh;
}
/* free block in new bitmap */
-int reiserfsck_reiserfs_free_block (reiserfs_filsys_t fs, unsigned long block)
+int reiserfsck_reiserfs_free_block (reiserfs_filsys_t * fs, unsigned long block)
{
mark_block_free (block);
diff --git a/fsck/ufile.c b/fsck/ufile.c
index 7037c5a..86aa6c7 100644
--- a/fsck/ufile.c
+++ b/fsck/ufile.c
@@ -1,11 +1,8 @@
/*
- * Copyright 1996, 1997, 1998 Hans Reiser
+ * Copyright 1996-2002 Hans Reiser
*/
#include "fsck.h"
-
-
-
static int do_items_have_the_same_type (struct item_head * ih, struct key * key)
{
return (get_type (&ih->ih_key) == get_type (key)) ? 1 : 0;
@@ -17,15 +14,6 @@ static int are_items_in_the_same_node (struct path * path)
}
-/* FIXME: there is get_next_key in pass4.c */
-static struct key * get_next_key_2 (struct path * path)
-{
- if (PATH_LAST_POSITION (path) < B_NR_ITEMS (get_bh (path)) - 1)
- return B_N_PKEY (get_bh (path), PATH_LAST_POSITION (path) + 1);
- return uget_rkey (path);
-}
-
-
int do_make_tails ()
{
return 1;/*SB_MAKE_TAIL_FLAG (&g_sb) == MAKE_TAILS ? YES : NO;*/
@@ -34,68 +22,67 @@ int do_make_tails ()
static void cut_last_unfm_pointer (struct path * path, struct item_head * ih)
{
- set_free_space(ih, 0);
+ set_ih_free_space(ih, 0);
if (I_UNFM_NUM (ih) == 1)
reiserfsck_delete_item (path, 0);
else
- reiserfsck_cut_from_item (path, -UNFM_P_SIZE);
+ reiserfsck_cut_from_item (path, -((int)UNFM_P_SIZE));
}
-
-// we use this to convert symlinks back to direct items if they were
-// direct2indirect converted on tree building
-static unsigned long indirect_to_direct (struct path * path, __u64 *symlink_size)
+/*
+ if this is not a symlink - make it of_this_size;
+ otherwise find a size and return it in symlink_size;
+*/
+static unsigned long indirect_to_direct (struct path * path, __u64 len, int symlink)
{
struct buffer_head * bh = PATH_PLAST_BUFFER (path);
struct item_head * ih = PATH_PITEM_HEAD (path);
- unsigned long unfm_ptr;
+ __u32 unfm_ptr;
struct buffer_head * unfm_bh = 0;
struct item_head ins_ih;
char * buf;
- int len;
__u32 * indirect;
- char bad_link[] = "broken_link";
-
-/* add_event (INDIRECT_TO_DIRECT);*/
-
+ char bad_drct[fs->fs_blocksize];
/* direct item to insert */
- set_key_format (&ins_ih, ih_key_format (ih));
- ins_ih.ih_key.k_dir_id = ih->ih_key.k_dir_id;
- ins_ih.ih_key.k_objectid = ih->ih_key.k_objectid;
- set_type_and_offset (ih_key_format (ih), &ins_ih.ih_key,
+ memset (&ins_ih, 0, sizeof (ins_ih));
+ if (symlink) {
+ set_ih_key_format (&ins_ih, KEY_FORMAT_1);
+ } else {
+ set_ih_key_format (&ins_ih, get_ih_key_format (ih));
+ }
+ set_key_dirid (&ins_ih.ih_key, get_key_dirid (&ih->ih_key));
+ set_key_objectid (&ins_ih.ih_key, get_key_objectid (&ih->ih_key));
+ set_type_and_offset (get_ih_key_format (ih), &ins_ih.ih_key,
get_offset (&ih->ih_key) + (I_UNFM_NUM (ih) - 1) * bh->b_size, TYPE_DIRECT);
// we do not know what length this item should be
indirect = get_item (path);
unfm_ptr = le32_to_cpu (indirect [I_UNFM_NUM (ih) - 1]);
if (unfm_ptr && (unfm_bh = bread (bh->b_dev, unfm_ptr, bh->b_size))) {
+ /* we can read the block */
buf = unfm_bh->b_data;
- // get length of direct item
- for (len = 0; buf[len] && len < bh->b_size; len ++);
} else {
- fsck_log ("indirect_to_direct: could not read block %lu, "
- "making (%K) bad link instead\n", unfm_ptr, &ih->ih_key);
- buf = bad_link;
- len = strlen (bad_link);
+ /* we cannot read the block */
+ if (unfm_ptr)
+ fsck_log ("indirect_to_direct: could not read block %lu (%K)\n", unfm_ptr, &ih->ih_key);
+ memset (bad_drct, 0, fs->fs_blocksize);
+ buf = bad_drct;
}
-
- if (len > MAX_DIRECT_ITEM_LEN (fs->s_blocksize)) {
- fsck_log ("indirect_to_direct: symlink %K seems too long %d, "
- "Cutting it down to %d byte\n",
- &ih->ih_key, len, MAX_DIRECT_ITEM_LEN (fs->s_blocksize) - 8);
- len = MAX_DIRECT_ITEM_LEN (fs->s_blocksize) - 8;
+/*
+ if (len > MAX_DIRECT_ITEM_LEN (fs->fs_blocksize)) {
+ fsck_log ("indirect_to_direct: caanot create such a long item %d (%K), "
+ "Cutting it down to %d byte\n", len, &ih->ih_key, MAX_DIRECT_ITEM_LEN (fs->fs_blocksize) - 8);
+ len = MAX_DIRECT_ITEM_LEN (fs->fs_blocksize) - 8;
}
-
+
if (!len) {
buf = bad_link;
len = strlen (bad_link);
}
-
- *symlink_size = len;
-
- ins_ih.ih_item_len = cpu_to_le16 ((ih_key_format (ih) == KEY_FORMAT_2) ? ROUND_UP(len) : len);
- set_free_space (&ins_ih, MAX_US_INT);
+*/
+ set_ih_item_len (&ins_ih, (get_ih_key_format (ih) == KEY_FORMAT_2) ? ROUND_UP(len) : len);
+ set_ih_free_space (&ins_ih, MAX_US_INT);
// last last unformatted node pointer
@@ -103,7 +90,7 @@ static unsigned long indirect_to_direct (struct path * path, __u64 *symlink_size
cut_last_unfm_pointer (path, ih);
/* insert direct item */
- if (usearch_by_key (fs, &(ins_ih.ih_key), path) == ITEM_FOUND)
+ if (reiserfs_search_by_key_4 (fs, &(ins_ih.ih_key), path) == ITEM_FOUND)
die ("indirect_to_direct: key must be not found");
reiserfsck_insert_item (path, &ins_ih, (const char *)(buf));
@@ -114,14 +101,15 @@ static unsigned long indirect_to_direct (struct path * path, __u64 *symlink_size
}
-extern inline __u64 get_min_bytes_number (struct item_head * ih, int blocksize)
+__u64 get_min_bytes_number (struct item_head * ih, int blocksize)
{
switch (get_type (&ih->ih_key)) {
case TYPE_DIRECT:
- if (SB_VERSION(fs) == REISERFS_VERSION_2)
- return ROUND_UP(ih_item_len (ih) - 8);
+ if (fs->fs_format == REISERFS_FORMAT_3_6)
+ return ROUND_UP(get_ih_item_len (ih) - 8);
else
- return ih_item_len (ih);
+ return get_ih_item_len (ih);
+
case TYPE_INDIRECT:
return (I_UNFM_NUM(ih) - 1) * blocksize;
}
@@ -129,25 +117,85 @@ extern inline __u64 get_min_bytes_number (struct item_head * ih, int blocksize)
return 0;
}
+/* start_key is the key after which all items need to be deleted
+ save_here is a pointer where deleted items need to be saved if save is set.
+ */
+static void delete_file_items_after_key(struct key * start_key, struct si ** save_here) {
+ struct path path;
+ struct key key = *start_key;
+ struct key * rkey;
+
+ while (1) {
+ reiserfs_search_by_key_4 (fs, &key, &path);
+
+ if (get_item_pos (&path) == B_NR_ITEMS (get_bh (&path))) {
+ rkey = uget_rkey (&path);
+ if (rkey && !not_of_one_file (&key, rkey)) {
+ /* file continues in the right neighbor */
+ copy_key (&key, rkey);
+ pathrelse (&path);
+ continue;
+ }
+ /* there is no more items with this key */
+ pathrelse (&path);
+ break;
+ }
+
+ if (is_stat_data_ih (get_ih(&path)))
+ fix_obviously_wrong_sd_mode (&path);
+
+ rkey = &(get_ih (&path))->ih_key;
+ if (not_of_one_file (&key, rkey)) {
+ /* there are no more item with this key */
+ pathrelse (&path);
+ break;
+ }
+
+ /* ok, item found, but make sure that it is not a directory one */
+ if ((is_stat_data_key (rkey) && !not_a_directory (get_item (&path))) ||
+ (is_direntry_key (rkey)))
+ reiserfs_panic ("rewrite_file: no directory items of %K are expected", &key);
+
+ if (save_here != NULL)
+ *save_here = save_and_delete_file_item (*save_here, &path);
+ else
+ reiserfsck_delete_item (&path, 0);
+ }
+}
+
/* returns 1 when file looks correct, -1 if directory items appeared
there, 0 - only holes in the file found */
/* when it returns, key->k_offset is offset of the last item of file */
-int are_file_items_correct (struct key * key, int key_version, __u64 * size,
- /*__u64 * min_size,*/ __u32 * blocks,
- int mark_passed_items, int symlink, __u64 symlink_size)
+/* sd_size is zero if we do not need to convert any indirect to direct */
+int are_file_items_correct (struct item_head * sd_ih, void * sd, __u64 * size, __u32 * blocks,
+ int mark_passed_items, int * symlink)
{
struct path path;
- int retval, i;
struct item_head * ih;
- struct key * next_key;
+ struct key * next_key, * key;
+ __u32 sd_first_direct_byte = 0;
+ __u64 sd_size;
+ int retval, i, was_tail = 0;
int had_direct = 0;
+ int key_version = get_ih_key_format (sd_ih);
+ int next_is_another_object = 0;
+ __u64 last_unfm_offset = 0;
+ int will_convert = 0;
+ int should_convert;
+
+ should_convert = (fsck_mode (fs) != FSCK_REBUILD) || mark_passed_items;
+ key = &sd_ih->ih_key;
+ get_sd_size (sd_ih, sd, &sd_size);
+
+ if (key_version == KEY_FORMAT_1)
+ get_sd_first_direct_byte (sd_ih, sd, &sd_first_direct_byte);
set_offset (key_version, key, 1);
set_type (key_version, key, TYPE_DIRECT);
+ /* correct size and st_blocks */
*size = 0;
- /* *min_size = 0;*/
*blocks = 0;
path.path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
@@ -162,103 +210,139 @@ int are_file_items_correct (struct key * key, int key_version, __u64 * size,
ih = PATH_PITEM_HEAD (&path);
- set_type (ih_key_format (ih), key, get_type (&ih->ih_key));
-
+ if (ih_was_tail (ih)) {
+ was_tail = 1;
+ }
+
+ set_type (key_version, key, get_type (&ih->ih_key));
+
if (mark_passed_items == 1) {
mark_item_reachable (ih, PATH_PLAST_BUFFER (&path));
}
+
// does not change path
next_key = get_next_key_2 (&path);
- if (get_type (&ih->ih_key) == TYPE_INDIRECT)
+ if (next_key == 0 || not_of_one_file (key, next_key) ||
+ (!is_indirect_key (next_key) && !is_direct_key(next_key)))
{
- if (symlink)
- *blocks = 1;
- else
- for (i = 0; i < I_UNFM_NUM (ih); i ++)
- {
- __u32 * ind = (__u32 *)get_item(&path);
-
- if (ind[i] != 0)
- *blocks += (fs->s_blocksize >> 9);
- }
-
- }else if ((get_type (&ih->ih_key) == TYPE_DIRECT) && !(had_direct))
- {
- if (symlink)
- *blocks = (fs->s_blocksize >> 9);
- else
- *blocks += (fs->s_blocksize >> 9);
- had_direct++;
+ next_is_another_object = 1;
+ will_convert = (is_indirect_ih (ih) && sd_size && I_UNFM_NUM (ih) > 0);
+ if (will_convert) {
+ last_unfm_offset = get_offset (key) + fs->fs_blocksize * (I_UNFM_NUM (ih) - 1);
+ /* if symlink or
+ [ 1. sd_size points somewhere into last unfm block
+ 2. one item of the file was direct before for 3_6 || FDB points to the tail correctly for 3_5
+ 3. we can have a tail in the file of a such size ] */
+ will_convert = will_convert && (sd_size >= last_unfm_offset) &&
+ (sd_size < last_unfm_offset + fs->fs_blocksize) &&
+ !STORE_TAIL_IN_UNFM (sd_size, sd_size - last_unfm_offset + 1, fs->fs_blocksize);
+
+ will_convert = will_convert && (*symlink || ((key_version == KEY_FORMAT_1) &&
+ (sd_first_direct_byte == last_unfm_offset)) || ((key_version == KEY_FORMAT_2) && was_tail));
+ }
}
-
- if (next_key == 0 || not_of_one_file (key, next_key) ||
- (!is_indirect_key (next_key) && !is_direct_key(next_key) ) )
+
+ if (should_convert) {
+ *symlink = *symlink && (will_convert || is_direct_key(&ih->ih_key));
+
+ if (!(*symlink) && key_version != get_ih_key_format (ih)) {
+ if (fsck_mode(fs) == FSCK_CHECK) {
+ fsck_log("are_file_items_correct: vpf-10250: block %lu, item (%d), item format (%H)"\
+ " is not equal to SD format (%d)\n",
+ get_bh(&path)->b_blocknr, PATH_LAST_POSITION(&path), ih, key_version);
+ one_more_corruption (fs, fixable);
+ } else {
+ fsck_log("are_file_items_correct: vpf-10280: block %lu, item (%d), item format (%H)"\
+ " is not equal to SD format (%d) - delete\n",
+ get_bh(&path)->b_blocknr, PATH_LAST_POSITION(&path), ih, key_version);
+
+ pathrelse (&path);
+ delete_file_items_after_key (key, NULL);
+ return 1;
+ }
+ }
+
+ if (will_convert)
+ *size = sd_size;
+ else
+ *size = get_offset (&ih->ih_key) + get_bytes_number (ih, fs->fs_blocksize) - 1;
+
+ if (get_type (&ih->ih_key) == TYPE_INDIRECT) {
+ if (*symlink) /* symlinks must be calculated as dirs */
+ *blocks = dir_size2st_blocks (*size);
+ else
+ for (i = 0; i < I_UNFM_NUM (ih); i ++) {
+ __u32 * ind = (__u32 *)get_item(&path);
+
+ if (ind[i] != 0)
+ *blocks += (fs->fs_blocksize >> 9);
+ }
+ } else if (get_type (&ih->ih_key) == TYPE_DIRECT) {
+ if (*symlink) /* symlinks must be calculated as dirs */
+ *blocks = dir_size2st_blocks (*size);
+ else if (!had_direct)
+ *blocks += (fs->fs_blocksize >> 9);
+
+ /* calculate only the first direct byte */
+ had_direct++;
+ }
+ }
+
+ if (next_is_another_object)
{
/* next item does not exists or is of another object,
therefore all items of file are correct */
-
- /* *min_size = get_offset (key) + get_min_bytes_number (ih, fs->s_blocksize);*/
- *size = get_offset (key) + get_bytes_number (ih, fs->s_blocksize) - 1;
-
-
- /* here is a problem: if file system being repaired was full
- enough, then we should avoid indirect_to_direct
- conversions. This is because unformatted node we have to
- free will not get into pool of free blocks, but new direct
- item is very likely of big size, therefore it may require
- allocation of new blocks. So, skip it for now */
- if (symlink && is_indirect_ih (ih)) {
-// struct key sd_key;
- unsigned long first_direct_byte;
-
+ if (will_convert) {
if (fsck_mode (fs) == FSCK_CHECK) {
- fsck_log ("are_file_items_correct: symlink found in indirect item %K\n", &ih->ih_key);
+ /* here it can be symlink only */
+ fsck_log ("are_file_items_correct: the indirect item should be converted back to direct %K\n", &ih->ih_key);
+ one_more_corruption (fs, fixable);
+ pathrelse (&path);
} else {
- first_direct_byte = indirect_to_direct (&path, &symlink_size);
-
- /* last item of the file is direct item */
- set_offset (key_version, key, first_direct_byte);
+ __u32 * ind = (__u32 *)get_item(&path);
+ fsck_log ("are_file_items_correct: convert the indirect item back to direct %K\n", &ih->ih_key);
+ if (ind [I_UNFM_NUM (ih) - 1] == 0)
+ *blocks += (fs->fs_blocksize >> 9);
+ sd_first_direct_byte = indirect_to_direct (&path, sd_size - last_unfm_offset + 1, *symlink);
+ /* last item of the file is direct item */
+ set_offset (key_version, key, sd_first_direct_byte);
set_type (key_version, key, TYPE_DIRECT);
- *size = symlink_size;
}
- } else
+ } else
pathrelse (&path);
+
return 1;
}
/* next item is item of this file */
if ((is_indirect_ih (ih) &&
- (get_offset (&ih->ih_key) + fs->s_blocksize * I_UNFM_NUM (ih) != get_offset (next_key))) ||
+ (get_offset (&ih->ih_key) + fs->fs_blocksize * I_UNFM_NUM (ih) != get_offset (next_key))) ||
(is_direct_ih (ih) &&
- (get_offset (&ih->ih_key) + ih_item_len (ih) != get_offset (next_key))))
+ (get_offset (&ih->ih_key) + get_ih_item_len (ih) != get_offset (next_key))))
{
/* next item has incorrect offset (hole or overlapping) */
- *size = get_offset (&ih->ih_key) + get_bytes_number (ih, fs->s_blocksize) - 1;
- /**min_size = *size;*/
pathrelse (&path);
return 0;
}
if (do_items_have_the_same_type (ih, next_key) == 1 && are_items_in_the_same_node (&path) == 1)
{
/* two indirect items or two direct items in the same leaf. FIXME: Second will be deleted */
- *size = get_offset (&ih->ih_key) + get_bytes_number (ih, fs->s_blocksize) - 1;
- /**min_size = *size;*/
pathrelse (&path);
return 0;
}
/* items are of different types or are in different nodes */
- if (get_offset (&ih->ih_key) + get_bytes_number (ih, fs->s_blocksize) != get_offset (next_key))
+ if (get_offset (&ih->ih_key) + get_bytes_number (ih, fs->fs_blocksize) != get_offset (next_key))
{
/* indirect item free space is not set properly */
if (!is_indirect_ih (ih) ) //|| get_ih_free_space(ih) == 0)
fsck_log ("are_file_items_correct: "
"item must be indirect and must have invalid free space (%H)", ih);
- if (fsck_mode (fs) != FSCK_CHECK)
+ if (fsck_mode (fs) != FSCK_CHECK && fsck_mode (fs) != FSCK_FIX_FIXABLE)
{
- set_free_space(ih, 0);
+ set_ih_free_space(ih, 0);
mark_buffer_dirty (PATH_PLAST_BUFFER (&path));
}
}
@@ -267,7 +351,7 @@ int are_file_items_correct (struct key * key, int key_version, __u64 * size,
set_type_and_offset(key_version, key, get_offset (next_key), get_type(next_key));
if (comp_keys (key, next_key))
- die ("are_file_items_correct: keys do not match %k and %k", key, next_key);
+ reiserfs_panic ("are_file_items_correct: keys do not match %k and %k", key, next_key);
pathrelse (&path);
break;
@@ -276,7 +360,7 @@ int are_file_items_correct (struct key * key, int key_version, __u64 * size,
// byte. It does not have to exist
if (get_offset (key) != 1)
- die ("are_file_items_correct: key not found %byte can be not found only when it is first byte of file");
+ die ("are_file_items_correct: key not found byte can be not found only when it is first byte of file");
pathrelse (&path);
return 0;
@@ -303,9 +387,6 @@ int are_file_items_correct (struct key * key, int key_version, __u64 * size,
static void rewrite_file (struct item_head * ih)
{
struct key key;
- struct key * rkey;
- struct path path;
- struct item_head * path_ih;
struct si * si;
/* starting with the leftmost one - look for all items of file,
@@ -314,36 +395,10 @@ static void rewrite_file (struct item_head * ih)
set_type_and_offset (KEY_FORMAT_1, &key, SD_OFFSET, TYPE_STAT_DATA);
si = 0;
- while (1) {
- usearch_by_key (fs, &key, &path);
- if (get_item_pos (&path) == B_NR_ITEMS (get_bh (&path))) {
- rkey = uget_rkey (&path);
- if (rkey && !not_of_one_file (&key, rkey)) {
- /* file continues in the right neighbor */
- copy_key (&key, rkey);
- pathrelse (&path);
- continue;
- }
- /* there is no more items with this key */
- pathrelse (&path);
- break;
- }
-
- path_ih = get_ih (&path);
- if (not_of_one_file (&key, &(path_ih->ih_key))) {
- /* there are no more item with this key */
- pathrelse (&path);
- break;
- }
+ delete_file_items_after_key (&key, &si);
- /* ok, item found, but make sure that it is not a directory one */
- if ((is_stat_data_ih (path_ih) && !not_a_directory (get_item (&path))) ||
- (is_direntry_ih (path_ih)))
- reiserfs_panic ("rewrite_file: no directory items of %K are expected",
- &key);
-
- si = save_and_delete_file_item (si, &path);
- }
+ if (si && should_relocate (&(si->si_ih)))
+ relocate_file (&(si->si_ih), 1);
/* put all items back into tree */
while (si) {
@@ -355,31 +410,36 @@ static void rewrite_file (struct item_head * ih)
/* file must have correct sequence of items and tail must be stored in
unformatted pointer */
-static int make_file_writeable (struct item_head * ih)
+static int make_file_writeable (struct item_head * sd_ih, void * sd)
{
- struct key key;
- __u64 size;/*, min_size;*/
+ struct item_head sd_ih_copy;
+ struct stat_data sd_copy;
+ __u64 size;
__u32 blocks;
- int retval;
+ int retval, symlink;
+ __u16 mode;
- copy_key (&key, &(ih->ih_key));
+ sd_ih_copy = *sd_ih;
+ memcpy (&sd_copy, sd, get_ih_item_len (sd_ih));
+ get_sd_mode (sd_ih, sd, &mode);
+ symlink = S_ISLNK(mode);
- retval = are_file_items_correct (&key, ih_key_format (ih), &size,/* &min_size, */
- &blocks, 0/*do not mark accessed*/, 0, 0);
+ retval = are_file_items_correct (&sd_ih_copy, &sd_copy, &size, &blocks, 0/*do not mark accessed*/, &symlink);
if (retval == 1)
/* file looks correct */
return 1;
- rewrite_file (ih);
- stats(fs)->rewritten ++;
+ rewrite_file (sd_ih);
+ /*fsck_data (fs)->rebuild.rewritten ++;*/
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
- copy_key (&key, &(ih->ih_key));
+
size = 0;
- if (are_file_items_correct (&key, ih_key_format (ih), &size, &blocks,
- 0/*do not mark accessed*/, 0, 0) == 0) {
- fsck_progress ("file still incorrect %K\n", &key);
+
+ if (are_file_items_correct (&sd_ih_copy, &sd_copy, &size, &blocks, 0/*do not mark accessed*/, &symlink) == 0) {
+ fsck_progress ("file still incorrect %K\n", &sd_ih->ih_key);
}
+
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
return 1;
@@ -388,7 +448,7 @@ static int make_file_writeable (struct item_head * ih)
/* this inserts __first__ indirect item (having k_offset == 1 and only
one unfm pointer) into tree */
-static int create_first_item_of_file (struct item_head * ih, char * item, struct path * path,
+int create_first_item_of_file (struct item_head * ih, char * item, struct path * path,
int *pos_in_coming_item, int was_in_tree)
{
__u32 unfm_ptr;
@@ -397,17 +457,20 @@ static int create_first_item_of_file (struct item_head * ih, char * item, struct
int retval;
__u32 free_sp = 0;
- if (get_offset (&ih->ih_key) > fs->s_blocksize) {
+ mark_item_unreachable (&indih);
+ copy_key (&(indih.ih_key), &(ih->ih_key));
+
+ if (get_offset (&ih->ih_key) > fs->fs_blocksize) {
/* insert indirect item containing 0 unfm pointer */
unfm_ptr = 0;
- set_free_space (&indih, 0);
+ set_ih_free_space (&indih, 0);
free_sp = 0;
retval = 0;
} else {
if (is_direct_ih (ih)) {
/* copy direct item to new unformatted node. Save information about it */
//__u64 len = get_bytes_number(0, ih, item, CHECK_FREE_BYTES);
- __u64 len = get_bytes_number (ih, fs->s_blocksize);
+ __u64 len = get_bytes_number (ih, fs->fs_blocksize);
unbh = reiserfsck_get_new_buffer (PATH_PLAST_BUFFER (path)->b_blocknr);
memset (unbh->b_data, 0, unbh->b_size);
@@ -416,10 +479,12 @@ static int create_first_item_of_file (struct item_head * ih, char * item, struct
/*mark_block_unformatted (le32_to_cpu (unfm_ptr));*/
memcpy (unbh->b_data + get_offset (&ih->ih_key) - 1, item, len);
- save_unfm_overwriting (le32_to_cpu (unfm_ptr), ih);
+// save_unfm_overwriting (le32_to_cpu (unfm_ptr), ih);
- set_free_space (&indih, fs->s_blocksize - len - (get_offset (&ih->ih_key) - 1));
- free_sp = fs->s_blocksize - len - (get_offset (&ih->ih_key) - 1);
+ set_ih_free_space (&indih, fs->fs_blocksize - len - (get_offset (&ih->ih_key) - 1));
+ mark_ih_was_tail (&indih);
+
+ free_sp = fs->fs_blocksize - len - (get_offset (&ih->ih_key) - 1);
mark_buffer_dirty (unbh);
// mark_buffer_uptodate (unbh, 0);
mark_buffer_uptodate (unbh, 1);
@@ -428,33 +493,66 @@ static int create_first_item_of_file (struct item_head * ih, char * item, struct
retval = len;
} else {
/* take first unformatted pointer from an indirect item */
- unfm_ptr = cpu_to_le32 (*(__u32 *)item);/*B_I_POS_UNFM_POINTER (bh, ih, 0);*/
+ unfm_ptr = *(__u32 *)item;/*B_I_POS_UNFM_POINTER (bh, ih, 0);*/
if (!was_in_tree) {
- if (still_bad_unfm_ptr_2 (unfm_ptr))
- die ("create_first_item_of_file: bad unfm pointer %d", unfm_ptr);
- mark_block_used (unfm_ptr);
+ if (still_bad_unfm_ptr_2 (le32_to_cpu (unfm_ptr)))
+ die ("create_first_item_of_file: bad unfm pointer %d", le32_to_cpu (unfm_ptr));
+ mark_block_used (le32_to_cpu (unfm_ptr), 0);
}
//free_sp = ih_get_free_space(0, ih, item);
- free_sp = ih_free_space (ih);
- set_free_space (&indih, ((ih_item_len(ih) == UNFM_P_SIZE) ? free_sp /*get_ih_free_space(ih)*/ : 0));
- if (ih_item_len (ih) != UNFM_P_SIZE)
+/* free_sp = 0;//get_ih_free_space (ih);
+ set_ih_free_space (&indih, ((get_ih_item_len(ih) == UNFM_P_SIZE) ? free_sp : 0));
+ if (get_ih_item_len (ih) != UNFM_P_SIZE)
free_sp = 0;
-// free_sp = ((ih->ih_item_len == UNFM_P_SIZE) ? ih->u.ih_free_space : 0);
- retval = fs->s_blocksize - free_sp;
+*/
+ retval = fs->fs_blocksize - free_sp;
(*pos_in_coming_item) ++;
}
}
- set_key_format (&indih, ih_key_format (ih));
+
+ set_ih_key_format (&indih, get_ih_key_format (ih));
//ih_version(&indih) = ih_version(ih);
- copy_key (&(indih.ih_key), &(ih->ih_key));
set_offset (key_format (&(ih->ih_key)), &indih.ih_key, 1);
set_type (key_format (&(ih->ih_key)), &indih.ih_key, TYPE_INDIRECT);
- indih.ih_item_len = cpu_to_le16 (UNFM_P_SIZE);
- mark_item_unreachable (&indih);
+ set_ih_item_len (&indih, UNFM_P_SIZE);
+
reiserfsck_insert_item (path, &indih, (const char *)&unfm_ptr);
+ /* update sd_first_direct_byte */
+ /*
+ if (get_ih_key_format (&indih) == KEY_FORMAT_1) {
+ struct key sd_key;
+
+ sd_key = indih.ih_key;
+ set_type_and_offset (KEY_FORMAT_1, &sd_key, SD_OFFSET, TYPE_STAT_DATA);
+
+ if (reiserfs_search_by_key_4 (fs, &sd_key, path) == ITEM_FOUND) {
+ struct buffer_head * bh;
+ struct stat_data_v1 * sd;
+ __u32 fdb;
+
+ bh = get_bh (path);
+ ih = get_ih (path);
+ if (get_ih_item_len (ih) != SD_V1_SIZE) {
+ // symlink?
+ if (get_ih_item_len (ih) != SD_SIZE)
+ die ("create_first_item_of_file: wrong stat data found");
+ } else {
+ sd = get_item (path);
+ get_sd_first_direct_byte (ih, sd, &fdb);
+ if (fdb != NO_BYTES_IN_DIRECT_ITEM) {
+ fdb = NO_BYTES_IN_DIRECT_ITEM;
+ set_sd_first_direct_byte (ih, sd, &fdb);
+ mark_buffer_dirty (bh);
+ }
+ }
+ pathrelse (path);
+ }
+ }
+
+*/
return retval;
}
@@ -486,79 +584,119 @@ static void direct2indirect2 (unsigned long unfm, struct path * path, int keep_f
struct buffer_head * unbh;
struct unfm_nodeinfo ni;
int copied = 0;
+ int file_format;
ih = PATH_PITEM_HEAD (path);
copy_key (&key, &(ih->ih_key));
- if (get_offset (&key) % fs->s_blocksize != 1) {
+ file_format = key_format (&key);
+
+ if (get_offset (&key) % fs->fs_blocksize != 1) {
/* look for first part of tail */
pathrelse (path);
- set_offset (key_format (&key), &key, (get_offset (&key) & ~(fs->s_blocksize - 1)) + 1);
- if (usearch_by_key (fs, &key, path) != ITEM_FOUND)
+ set_offset (file_format, &key, (get_offset (&key) & ~(fs->fs_blocksize - 1)) + 1);
+ if (reiserfs_search_by_key_4 (fs, &key, path) != ITEM_FOUND)
die ("direct2indirect: can not find first part of tail");
}
- unbh = reiserfsck_get_new_buffer (unfm ?: block_to_start (path));
+ unbh = reiserfsck_get_new_buffer (le32_to_cpu (unfm) ? le32_to_cpu (unfm) : block_to_start (path));
memset (unbh->b_data, 0, unbh->b_size);
/* delete parts of tail coping their contents to new buffer */
do {
- //__u64 len = get_bytes_number(PATH_PLAST_BUFFER(path), ih, 0, CHECK_FREE_BYTES);
__u64 len;
ih = PATH_PITEM_HEAD (path);
- len = get_bytes_number(ih, fs->s_blocksize);
+ len = get_bytes_number(ih, fs->fs_blocksize);
memcpy (unbh->b_data + copied, B_I_PITEM (PATH_PLAST_BUFFER (path), ih), len);
- save_unfm_overwriting (unbh->b_blocknr, ih);
+// save_unfm_overwriting (unbh->b_blocknr, ih);
copied += len;
- set_offset (key_format (&key), &key, get_offset (&key) + len);
-// set_offset (ih_key_format (ih), &key, get_offset (&key) + len);
+ set_offset (file_format, &key, get_offset (&key) + len);
reiserfsck_delete_item (path, 0);
- } while (usearch_by_key (fs, &key, path) == ITEM_FOUND);
- ih = PATH_PITEM_HEAD (path);
+ } while (reiserfs_search_by_key_4 (fs, &key, path) == ITEM_FOUND);
pathrelse (path);
+
/* paste or insert pointer to the unformatted node */
- set_offset (key_format (&key), &key, get_offset (&key) - copied);
+ set_offset (file_format, &key, get_offset (&key) - copied);
// set_offset (ih_key_format (ih), &key, get_offset (&key) - copied);
// key.k_offset -= copied;
ni.unfm_nodenum = cpu_to_le32 (unbh->b_blocknr);
- ni.unfm_freespace = (keep_free_space == 1) ? (fs->s_blocksize - copied) : 0;
+ ni.unfm_freespace = (keep_free_space == 1) ? cpu_to_le16 (fs->fs_blocksize - copied) : 0;
-/* this is for check only */
- /*mark_block_unformatted (ni.unfm_nodenum);*/
- if (usearch_by_position (fs, &key, key_format (&key), path) == FILE_NOT_FOUND) {
+ if (usearch_by_position (fs, &key, file_format, path) == FILE_NOT_FOUND) {
struct item_head insih;
copy_key (&(insih.ih_key), &key);
- set_key_format (&insih, key_format (&key));
- set_type (ih_key_format (&insih), &insih.ih_key, TYPE_INDIRECT);
- set_free_space (&insih, ni.unfm_freespace);
+ set_ih_key_format (&insih, file_format);
+ set_type (get_ih_key_format (&insih), &insih.ih_key, TYPE_INDIRECT);
+ set_ih_free_space (&insih, le16_to_cpu (ni.unfm_freespace));
// insih.u.ih_free_space = ni.unfm_freespace;
mark_item_unreachable (&insih);
- insih.ih_item_len = cpu_to_le16 (UNFM_P_SIZE);
+ set_ih_item_len (&insih, UNFM_P_SIZE);
+ mark_ih_was_tail (&insih);
reiserfsck_insert_item (path, &insih, (const char *)&(ni.unfm_nodenum));
} else {
ih = PATH_PITEM_HEAD (path);
- if (!is_indirect_ih (ih) || get_offset (&key) != get_bytes_number (ih, fs->s_blocksize) + 1)
- die ("direct2indirect: incorrect item found");
+ if (!is_indirect_ih (ih) || get_offset (&key) != get_bytes_number (ih, fs->fs_blocksize) + get_offset (&ih->ih_key))
+ die ("direct2indirect: incorrect item found in %lu block", PATH_PLAST_BUFFER(path)->b_blocknr);
+
+ mark_ih_was_tail (ih);
+ mark_buffer_dirty (get_bh(path));
reiserfsck_paste_into_item (path, (const char *)&ni, UNFM_P_SIZE);
}
mark_buffer_dirty (unbh);
-// mark_buffer_uptodate (unbh, 0);
mark_buffer_uptodate (unbh, 1);
brelse (unbh);
- if (usearch_by_position (fs, &key, ih_key_format (ih), path) != POSITION_FOUND || !is_indirect_ih (PATH_PITEM_HEAD (path)))
+ /* update sd_first_direct_byte */
+/*
+ while (file_format == KEY_FORMAT_1) {
+ struct key sd_key;
+
+ sd_key = key;
+ set_type_and_offset (KEY_FORMAT_1, &sd_key, SD_OFFSET, TYPE_STAT_DATA);
+
+ if (reiserfs_search_by_key_4 (fs, &sd_key, path) == ITEM_FOUND) {
+ struct buffer_head * bh;
+ struct stat_data_v1 * sd;
+ __u32 fdb;
+ __u16 mode;
+
+ bh = get_bh (path);
+ ih = get_ih (path);
+ get_sd_mode (ih, get_item(path), &mode);
+
+// if (get_ih_item_len (ih) != SD_V1_SIZE)
+ if (get_ih_item_len (ih) != SD_V1_SIZE) {
+ if (S_ISLNK(mode)) {
+ pathrelse (path);
+ break;
+ } else
+ reiserfs_panic ("direct2indirect: wrong stat data found %H", ih);
+ }
+
+ sd = get_item (path);
+ fdb = NO_BYTES_IN_DIRECT_ITEM;
+ set_sd_first_direct_byte (ih, sd, &fdb);
+ mark_buffer_dirty (bh);
+ pathrelse (path);
+ }
+ break;
+ }
+*/
+
+ if (usearch_by_position (fs, &key, file_format, path) != POSITION_FOUND ||
+ !is_indirect_ih (PATH_PITEM_HEAD (path)))
die ("direct2indirect: position not found");
return;
}
@@ -571,7 +709,7 @@ static int append_to_unformatted_node (struct item_head * comingih, struct item_
{
struct buffer_head * bh, * unbh;
__u64 end_of_data; //ih->u.ih_free_space;
- __u64 offset = get_offset (&comingih->ih_key) % fs->s_blocksize - 1;
+ __u64 offset = get_offset (&comingih->ih_key) % fs->fs_blocksize - 1;
int zero_number;
__u32 unfm_ptr;
@@ -579,22 +717,22 @@ static int append_to_unformatted_node (struct item_head * comingih, struct item_
if (*free_sp /*ih->u.ih_free_space*/ < coming_len)
{
- *free_sp = get_offset (&ih->ih_key) + fs->s_blocksize * I_UNFM_NUM (ih) - get_offset (&comingih->ih_key);
+ *free_sp = get_offset (&ih->ih_key) + fs->fs_blocksize * I_UNFM_NUM (ih) - get_offset (&comingih->ih_key);
if (*free_sp < coming_len)
die ("reiserfsck_append_file: there is no enough free space in unformatted node");
}
- end_of_data = fs->s_blocksize - *free_sp;
+ end_of_data = fs->fs_blocksize - *free_sp;
zero_number = offset - end_of_data;
bh = PATH_PLAST_BUFFER (path);
- unfm_ptr = B_I_POS_UNFM_POINTER (bh, ih, I_UNFM_NUM (ih) - 1);
+ unfm_ptr = le32_to_cpu (B_I_POS_UNFM_POINTER (bh, ih, I_UNFM_NUM (ih) - 1));
/*if (unfm_ptr != 0 && unfm_ptr < SB_BLOCK_COUNT (fs))*/
if (unfm_ptr && !not_data_block (fs, unfm_ptr))
{
- unbh = bread (fs->s_dev, unfm_ptr, fs->s_blocksize);
+ unbh = bread (fs->fs_dev, unfm_ptr, fs->fs_blocksize);
if (!is_block_used (unfm_ptr))
die ("append_to_unformatted_node: unused block %d", unfm_ptr);
if (unbh == 0)
@@ -612,10 +750,10 @@ static int append_to_unformatted_node (struct item_head * comingih, struct item_
memset (unbh->b_data + end_of_data, 0, zero_number);
memcpy (unbh->b_data + offset, item, coming_len);
- save_unfm_overwriting (unbh->b_blocknr, comingih);
+// save_unfm_overwriting (unbh->b_blocknr, comingih);
*free_sp /*ih->u.ih_free_space*/ -= (zero_number + coming_len);
- set_free_space(ih, ih_free_space(ih) - (zero_number + coming_len));
+ set_ih_free_space(ih, get_ih_free_space(ih) - (zero_number + coming_len));
memset (unbh->b_data + offset + coming_len, 0, *free_sp);
// mark_buffer_uptodate (unbh, 0);
mark_buffer_uptodate (unbh, 1);
@@ -631,18 +769,18 @@ static void adjust_free_space (struct buffer_head * bh, struct item_head * ih, s
// printf ("adjust_free_space does nothing\n");
return;
if (is_indirect_ih (comingih)) {
- set_free_space(ih, 0);//??
+ set_ih_free_space(ih, 0);//??
*free_sp = (__u16)0;
} else {
- if (get_offset (&comingih->ih_key) < get_offset (&ih->ih_key) + fs->s_blocksize * I_UNFM_NUM (ih))
+ if (get_offset (&comingih->ih_key) < get_offset (&ih->ih_key) + fs->fs_blocksize * I_UNFM_NUM (ih))
{
/* append to the last unformatted node */
- set_free_space (ih, fs->s_blocksize - get_offset(&ih->ih_key) % fs->s_blocksize + 1);//??
- *free_sp = (__u16)fs->s_blocksize - get_offset(&ih->ih_key) % fs->s_blocksize + 1;
+ set_ih_free_space (ih, fs->fs_blocksize - get_offset(&ih->ih_key) % fs->fs_blocksize + 1);//??
+ *free_sp = (__u16)fs->fs_blocksize - get_offset(&ih->ih_key) % fs->fs_blocksize + 1;
}
else
{
- set_free_space(ih,0);//??
+ set_ih_free_space(ih,0);//??
*free_sp =0;
}
}
@@ -667,9 +805,9 @@ int reiserfsck_append_file (struct item_head * comingih, char * item, int pos, s
die ("reiserfsck_append_file: can not append to non-indirect item");
//keep_free_space = ih_get_free_space(PATH_PLAST_BUFFER (path), PATH_PITEM_HEAD(path), 0);
- keep_free_space = ih_free_space (ih);
+ keep_free_space = 0;//get_ih_free_space (ih);
- if (get_offset (&ih->ih_key) + get_bytes_number (ih, fs->s_blocksize)
+ if (get_offset (&ih->ih_key) + get_bytes_number (ih, fs->fs_blocksize)
//get_bytes_number (PATH_PLAST_BUFFER (path), PATH_PITEM_HEAD(path), 0, CHECK_FREE_BYTES)
!= get_offset (&comingih->ih_key)){
adjust_free_space (PATH_PLAST_BUFFER (path), ih, comingih, &keep_free_space);
@@ -677,9 +815,9 @@ int reiserfsck_append_file (struct item_head * comingih, char * item, int pos, s
if (is_direct_ih (comingih)) {
//__u64 coming_len = get_bytes_number (0,comingih, item, CHECK_FREE_BYTES);
- __u64 coming_len = get_bytes_number (comingih, fs->s_blocksize);
+ __u64 coming_len = get_bytes_number (comingih, fs->fs_blocksize);
- if (get_offset (&comingih->ih_key) < get_offset (&ih->ih_key) + fs->s_blocksize * I_UNFM_NUM (ih)) {
+ if (get_offset (&comingih->ih_key) < get_offset (&ih->ih_key) + fs->fs_blocksize * I_UNFM_NUM (ih)) {
/* direct item fits to free space of indirect item */
return append_to_unformatted_node (comingih, ih, item, path, &keep_free_space, coming_len);
}
@@ -690,37 +828,38 @@ int reiserfsck_append_file (struct item_head * comingih, char * item, int pos, s
/*mark_block_unformatted (unbh->b_blocknr);*/
memcpy (unbh->b_data + get_offset (&comingih->ih_key) % unbh->b_size - 1, item, coming_len);
- save_unfm_overwriting (unbh->b_blocknr, comingih);
+// save_unfm_overwriting (unbh->b_blocknr, comingih);
mark_buffer_dirty (unbh);
// mark_buffer_uptodate (unbh, 0);
mark_buffer_uptodate (unbh, 1);
- ni.unfm_nodenum = unbh->b_blocknr;
- ni.unfm_freespace = fs->s_blocksize - coming_len - (get_offset (&comingih->ih_key) % unbh->b_size - 1);
+ ni.unfm_nodenum = cpu_to_le32 (unbh->b_blocknr);
+ ni.unfm_freespace = cpu_to_le16 (fs->fs_blocksize - coming_len - (get_offset (&comingih->ih_key) % unbh->b_size - 1));
brelse (unbh);
retval = coming_len;
} else {
/* coming item is indirect item */
//bytes_number = get_bytes_number (PATH_PLAST_BUFFER (path), PATH_PITEM_HEAD(path), 0, CHECK_FREE_BYTES);
- bytes_number = get_bytes_number (ih, fs->s_blocksize);
- if (get_offset (&comingih->ih_key) + pos * fs->s_blocksize != get_offset (&ih->ih_key) + bytes_number)
- fsck_progress ("reiserfsck_append_file: can not append indirect item (%H) to the %H",
+ bytes_number = get_bytes_number (ih, fs->fs_blocksize);
+ if (get_offset (&comingih->ih_key) + pos * fs->fs_blocksize != get_offset (&ih->ih_key) + bytes_number)
+ fsck_log ("reiserfsck_append_file: can not append indirect item (%H) to the %H\n",
comingih, ih);
/* take unformatted pointer from an indirect item */
ni.unfm_nodenum = *(__u32 *)(item + pos * UNFM_P_SIZE);/*B_I_POS_UNFM_POINTER (bh, ih, pos);*/
if (!was_in_tree) {
- if (still_bad_unfm_ptr_2 (ni.unfm_nodenum))
- die ("reiserfsck_append_file: bad unfm pointer");
- mark_block_used (ni.unfm_nodenum);
+ if (still_bad_unfm_ptr_2 (le32_to_cpu (ni.unfm_nodenum)))
+ die ("reiserfsck_append_file: bad unfm pointer %u", le32_to_cpu (ni.unfm_nodenum));
+ mark_block_used (le32_to_cpu (ni.unfm_nodenum), 0);
}
- ni.unfm_freespace = ((pos == (I_UNFM_NUM (comingih) - 1)) ?
+ ni.unfm_freespace = cpu_to_le16 (((pos == (I_UNFM_NUM (comingih) - 1)) ?
//ih_get_free_space(0, comingih, item) /*comingih->u.ih_free_space*/ : 0);
- ih_free_space (comingih) /*comingih->u.ih_free_space*/ : 0);
- retval = fs->s_blocksize - ni.unfm_freespace;
+ get_ih_free_space (comingih) /*comingih->u.ih_free_space*/ : 0));
+ ni.unfm_freespace = 0;
+ retval = fs->fs_blocksize - le16_to_cpu (ni.unfm_freespace);
}
reiserfsck_paste_into_item (path, (const char *)&ni, UNFM_P_SIZE);
@@ -739,7 +878,7 @@ int must_there_be_a_hole (struct item_head * comingih, struct path * path)
}
path->pos_in_item = I_UNFM_NUM (ih);
- if (get_offset (&ih->ih_key) + (I_UNFM_NUM (ih) + 1) * fs->s_blocksize <= get_offset (&comingih->ih_key))
+ if (get_offset (&ih->ih_key) + (I_UNFM_NUM (ih) + 1) * fs->fs_blocksize <= get_offset (&comingih->ih_key))
return 1;
return 0;
@@ -771,7 +910,7 @@ static int overwrite_by_direct_item (struct item_head * comingih, char * item, s
struct buffer_head * unbh, * bh;
struct item_head * ih;
int offset;
- __u64 coming_len = get_bytes_number (comingih, fs->s_blocksize);
+ __u64 coming_len = get_bytes_number (comingih, fs->fs_blocksize);
bh = PATH_PLAST_BUFFER (path);
@@ -780,16 +919,15 @@ static int overwrite_by_direct_item (struct item_head * comingih, char * item, s
unfm_ptr = le32_to_cpu (B_I_POS_UNFM_POINTER (bh, ih, path->pos_in_item));
unbh = 0;
- if (unfm_ptr != 0 && unfm_ptr < SB_BLOCK_COUNT (fs)) {
+ if (unfm_ptr != 0 && unfm_ptr < get_sb_block_count (fs->fs_ondisk_sb)) {
/**/
- unbh = bread (fs->s_dev, unfm_ptr, bh->b_size);
+ unbh = bread (fs->fs_dev, unfm_ptr, bh->b_size);
if (!is_block_used (unfm_ptr))
die ("overwrite_by_direct_item: unused block %d", unfm_ptr);
if (unbh == 0)
unfm_ptr = 0;
}
- if (unfm_ptr == 0 || unfm_ptr >= SB_BLOCK_COUNT (fs))
- {
+ if (unfm_ptr == 0 || unfm_ptr >= get_sb_block_count (fs->fs_ondisk_sb)) {
unbh = reiserfsck_get_new_buffer (bh->b_blocknr);
memset (unbh->b_data, 0, unbh->b_size);
B_I_POS_UNFM_POINTER (bh, ih, path->pos_in_item) = cpu_to_le32 (unbh->b_blocknr);
@@ -803,15 +941,16 @@ static int overwrite_by_direct_item (struct item_head * comingih, char * item, s
offset = (get_offset (&comingih->ih_key) % bh->b_size) - 1;
if (offset + coming_len > MAX_DIRECT_ITEM_LEN (bh->b_size))
die ("overwrite_by_direct_item: direct item too long (offset=%lu, length=%u)",
- get_offset (&comingih->ih_key), coming_len);
+ ( long unsigned ) get_offset (&comingih->ih_key),
+ ( unsigned ) coming_len);
memcpy (unbh->b_data + offset, item, coming_len);
- save_unfm_overwriting (unbh->b_blocknr, comingih);
+// save_unfm_overwriting (unbh->b_blocknr, comingih);
if ((path->pos_in_item == (I_UNFM_NUM (ih) - 1)) &&
- (bh->b_size - ih_free_space (ih)) < (offset + coming_len)) {
- set_free_space (ih, bh->b_size - (offset + coming_len)) ;
+ (bh->b_size - 0/*ih_free_space (ih)*/) < (offset + coming_len)) {
+ set_ih_free_space (ih, bh->b_size - (offset + coming_len)) ;
mark_buffer_dirty (bh);
}
mark_buffer_dirty (unbh);
@@ -822,45 +961,50 @@ static int overwrite_by_direct_item (struct item_head * comingih, char * item, s
}
+#if 0
void overwrite_unfm_by_unfm (unsigned long unfm_in_tree, unsigned long coming_unfm, int bytes_in_unfm)
{
- struct overwritten_unfm_segment * unfm_os_list;/* list of overwritten segments of the unformatted node */
- struct overwritten_unfm_segment unoverwritten_segment;
- struct buffer_head * bh_in_tree, * coming_bh;
+ struct overwritten_unfm_segment * unfm_os_list;/* list of overwritten segments of the unformatted node */
+ struct overwritten_unfm_segment unoverwritten_segment;
+ struct buffer_head * bh_in_tree, * coming_bh;
- if (!test_bit (coming_unfm % (fs->s_blocksize * 8), SB_AP_BITMAP (fs)[coming_unfm / (fs->s_blocksize * 8)]->b_data))
- /* block (pointed by indirect item) is free, we do not have to keep its contents */
- return;
- /* coming block is marked as used in disk bitmap. Put its contents to block in tree preserving
- everything, what has been overwritten there by direct items */
- unfm_os_list = find_overwritten_unfm (unfm_in_tree, bytes_in_unfm, &unoverwritten_segment);
- if (unfm_os_list) {
- /* add_event (UNFM_OVERWRITING_UNFM);*/
- bh_in_tree = bread (fs->s_dev, unfm_in_tree, fs->s_blocksize);
- coming_bh = bread (fs->s_dev, coming_unfm, fs->s_blocksize);
- if (bh_in_tree == 0 || coming_bh == 0)
- return;
-
- while (get_unoverwritten_segment (unfm_os_list, &unoverwritten_segment)) {
- if (unoverwritten_segment.ous_begin < 0 || unoverwritten_segment.ous_end > bytes_in_unfm - 1 ||
- unoverwritten_segment.ous_begin > unoverwritten_segment.ous_end)
- die ("overwrite_unfm_by_unfm: invalid segment found (%d %d)", unoverwritten_segment.ous_begin, unoverwritten_segment.ous_end);
-
- memcpy (bh_in_tree->b_data + unoverwritten_segment.ous_begin, coming_bh->b_data + unoverwritten_segment.ous_begin,
- unoverwritten_segment.ous_end - unoverwritten_segment.ous_begin + 1);
- mark_buffer_dirty (bh_in_tree);
+ if (!test_bit (coming_unfm % (fs->fs_blocksize * 8), SB_AP_BITMAP (fs)[coming_unfm / (fs->fs_blocksize * 8)]->b_data))
+ /* block (pointed by indirect item) is free, we do not have to keep its contents */
+ return;
+
+ /* coming block is marked as used in disk bitmap. Put its contents to
+ block in tree preserving everything, what has been overwritten there by
+ direct items */
+ unfm_os_list = find_overwritten_unfm (unfm_in_tree, bytes_in_unfm, &unoverwritten_segment);
+ if (unfm_os_list) {
+ /* add_event (UNFM_OVERWRITING_UNFM);*/
+ bh_in_tree = bread (fs->fs_dev, unfm_in_tree, fs->fs_blocksize);
+ coming_bh = bread (fs->fs_dev, coming_unfm, fs->fs_blocksize);
+ if (bh_in_tree == 0 || coming_bh == 0)
+ return;
+
+ while (get_unoverwritten_segment (unfm_os_list, &unoverwritten_segment)) {
+ if (unoverwritten_segment.ous_begin < 0 || unoverwritten_segment.ous_end > bytes_in_unfm - 1 ||
+ unoverwritten_segment.ous_begin > unoverwritten_segment.ous_end)
+ die ("overwrite_unfm_by_unfm: invalid segment found (%d %d)", unoverwritten_segment.ous_begin, unoverwritten_segment.ous_end);
+
+ memcpy (bh_in_tree->b_data + unoverwritten_segment.ous_begin, coming_bh->b_data + unoverwritten_segment.ous_begin,
+ unoverwritten_segment.ous_end - unoverwritten_segment.ous_begin + 1);
+ mark_buffer_dirty (bh_in_tree);
+ }
+
+ brelse (bh_in_tree);
+ brelse (coming_bh);
}
-
- brelse (bh_in_tree);
- brelse (coming_bh);
- }
}
+#endif
/* put unformatted node pointers from incoming item over the in-tree ones */
-static int overwrite_by_indirect_item (struct item_head * comingih, __u32 * coming_item, struct path * path, int * pos_in_coming_item)
+static int overwrite_by_indirect_item (struct item_head * comingih, __u32 * coming_item,
+ struct path * path, int * pos_in_coming_item)
{
struct buffer_head * bh = PATH_PLAST_BUFFER (path);
struct item_head * ih = PATH_PITEM_HEAD (path);
@@ -869,7 +1013,7 @@ static int overwrite_by_indirect_item (struct item_head * comingih, __u32 * comi
int src_unfm_ptrs, dest_unfm_ptrs, to_copy;
int i;
__u16 free_sp;
-
+ int dirty = 0;
item_in_tree = (__u32 *)B_I_PITEM (bh, ih) + path->pos_in_item;
coming_item += *pos_in_coming_item;
@@ -881,35 +1025,47 @@ static int overwrite_by_indirect_item (struct item_head * comingih, __u32 * comi
/* whole coming item (comingih) fits into item in tree (ih) starting with path->pos_in_item */
//free_sp = ih_get_free_space(0, comingih, (char *)coming_item);
- free_sp = ih_free_space (comingih);
+ free_sp = 0;//ih_free_space (comingih);
- written = get_bytes_number (comingih, fs->s_blocksize) -
- free_sp - *pos_in_coming_item * fs->s_blocksize;
+ written = get_bytes_number (comingih, fs->fs_blocksize) -
+ free_sp - *pos_in_coming_item * fs->fs_blocksize;
*pos_in_coming_item = I_UNFM_NUM (comingih);
to_copy = src_unfm_ptrs;
if (dest_unfm_ptrs == src_unfm_ptrs)
- set_free_space(ih, free_sp); //comingih->u.ih_free_space;
+ set_ih_free_space(ih, free_sp); //comingih->u.ih_free_space;
} else {
/* only part of coming item overlaps item in the tree */
*pos_in_coming_item += dest_unfm_ptrs;
- written = dest_unfm_ptrs * fs->s_blocksize;
+ written = dest_unfm_ptrs * fs->fs_blocksize;
to_copy = dest_unfm_ptrs;
- set_free_space(ih, 0);
+ set_ih_free_space(ih, 0);
}
for (i = 0; i < to_copy; i ++) {
+ if (coming_item[i] != 0 && item_in_tree[i] == 0) {
+ /* overwrite holes only by correct a pointer in the coming item
+ which must be correct */
+ item_in_tree[i] = coming_item[i];
+ mark_block_used (le32_to_cpu (coming_item[i]), 0);
+ dirty ++;
+ }
+
+#if 0
+
if (!is_block_used (coming_item[i]) && !is_block_uninsertable (coming_item[i])) {
if (item_in_tree[i]) {
/* do not overwrite unformatted pointer. We must save everything what is there already from
direct items */
- overwrite_unfm_by_unfm (item_in_tree[i], coming_item[i], fs->s_blocksize);
+ overwrite_unfm_by_unfm (item_in_tree[i], coming_item[i], fs->fs_blocksize);
} else {
item_in_tree[i] = coming_item[i];
mark_block_used (coming_item[i]);
}
}
+#endif
}
- mark_buffer_dirty (bh);
+ if (dirty)
+ mark_buffer_dirty (bh);
return written;
}
@@ -925,14 +1081,13 @@ static int reiserfsck_overwrite_file (struct item_head * comingih, char * item,
if (not_of_one_file (ih, &(comingih->ih_key)))
- die ("reiserfsck_overwrite_file: found [%lu %lu], new item [%lu %lu]",
- ih->ih_key.k_dir_id, ih->ih_key.k_objectid,
- comingih->ih_key.k_dir_id, comingih->ih_key.k_objectid);
+ reiserfs_panic ("reiserfsck_overwrite_file: found [%K], new item [%K]",
+ &ih->ih_key, &comingih->ih_key);
if (is_direct_ih (ih)) {
unfm_ptr = 0;
if (is_indirect_ih (comingih)) {
- if (get_offset (&ih->ih_key) % fs->s_blocksize != 1)
+ if (get_offset (&ih->ih_key) % fs->fs_blocksize != 1)
die ("reiserfsck_overwrite_file: second part of tail can not be overwritten by indirect item");
/* use pointer from coming indirect item */
unfm_ptr = le32_to_cpu (*(__u32 *)(item + *pos_in_coming_item * UNFM_P_SIZE));
@@ -942,7 +1097,7 @@ static int reiserfsck_overwrite_file (struct item_head * comingih, char * item,
}
}
/* */
- direct2indirect2 (le32_to_cpu (unfm_ptr), path, keep_free_space = 1);
+ direct2indirect2 (unfm_ptr, path, keep_free_space = 1);
}
if (is_direct_ih (comingih))
{
@@ -962,21 +1117,50 @@ static int reiserfsck_overwrite_file (struct item_head * comingih, char * item,
int reiserfsck_file_write (struct item_head * ih, char * item, int was_in_tree)
{
struct path path;
- struct item_head * path_ih;
int count, pos_in_coming_item;
- int retval;
+ int retval, written;
struct key key;
- int written;
-
+ int file_format = KEY_FORMAT_UNDEFINED;
+ int symlink = 0;
+/* __u64 size;
+ __u32 blocks;*/
+
+ if (!was_in_tree) {
+ __u16 mode;
+
+ // we already inserted all SD items. If we cannot find SD of this item - skip it
+ memset (&key, 0, sizeof (key));
+ copy_short_key (&key, &(ih->ih_key));
+
+ if (reiserfs_search_by_key_4 (fs, &key, &path) != ITEM_FOUND) {
+ fsck_log ("vpf-10260: no SD found, item skipped (%H)\n", ih);
+ pathrelse (&path);
+ return 0;
+ }
+
+ /*SD found*/
+ file_format = get_ih_key_format (get_ih(&path));
+ get_sd_mode (get_ih(&path), get_item(&path), &mode);
+ symlink = S_ISLNK(mode);
+
+ if (!symlink && file_format != get_ih_key_format (ih)) {
+ fsck_log ("vpf-10270: item to be inserted is of different format then found SD,"\
+ " item skipped \n\t(%H)\n\t(%H)\n", ih, get_ih(&path));
+ pathrelse (&path);
+ return 0;
+ }
+
+ if (make_file_writeable (get_ih(&path), get_item (&path)) == -1) {
+ /* write was not completed. Skip that item. Maybe it should be
+ saved to lost_found */
+ fsck_progress ("reiserfsck_file_write: skip writing %H\n", ih);
+ return 0;
+ }
- if (make_file_writeable (ih) == -1) {
- /* write was not completed. Skip that item. Maybe it should be
- saved to lost_found */
- fsck_progress ("reiserfsck_file_write: skip writing %H\n", ih);
- return 0;
+ pathrelse (&path);
}
- count = get_bytes_number (ih, fs->s_blocksize);
+ count = get_bytes_number (ih, fs->fs_blocksize);
pos_in_coming_item = 0;
copy_key (&key, &(ih->ih_key));
@@ -988,7 +1172,6 @@ int reiserfsck_file_write (struct item_head * ih, char * item, int was_in_tree)
if (retval == DIRECTORY_FOUND)
reiserfs_panic ("directory found %k", key);
-
if (retval == POSITION_FOUND) {
written = reiserfsck_overwrite_file (ih, item, &path, &pos_in_coming_item, was_in_tree);
count -= written;
@@ -1002,68 +1185,35 @@ int reiserfsck_file_write (struct item_head * ih, char * item, int was_in_tree)
}
if (retval == POSITION_NOT_FOUND) {
- path_ih = PATH_PITEM_HEAD (&path);
+ if (is_direct_ih (ih)) {
+ mark_ih_was_tail (get_ih(&path));
+ mark_buffer_dirty (get_bh(&path));
+ }
if (must_there_be_a_hole (ih, &path) == 1)
{
reiserfs_append_zero_unfm_ptr (&path);
}else {
count -= reiserfsck_append_file (ih, item, pos_in_coming_item, &path, was_in_tree);
- set_offset (key_format (&key), &key, get_offset (&key) + fs->s_blocksize);
+ set_offset (key_format (&key), &key, get_offset (&key) + fs->fs_blocksize);
pos_in_coming_item ++;
}
}
if (count < 0)
- die ("reiserfsck_file_write: count < 0 (%d)", count);
+ reiserfs_panic ("reiserfsck_file_write: %K: count < 0 (%d)",
+ &key, count);
pathrelse (&path);
}
- return get_bytes_number (ih, fs->s_blocksize);
-}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ /* This is a test for writing into the file. If not sure that file data are consistent after
+ reiserfsck_file_write - uncomment this clause: */
+/* if (!was_in_tree && are_file_items_correct (&ih->ih_key,
+ (file_format == KEY_FORMAT_UNDEFINED) ? get_ih_key_format (ih) : file_format,
+ &size, &blocks, 0, symlink, 0) == 0)
+ reiserfs_panic ("reiserfsck_file_write: item was not inserted properly\n");*/
+ return get_bytes_number (ih, fs->fs_blocksize);
+}
diff --git a/fsck/uobjectid.c b/fsck/uobjectid.c
index ee9a07f..dddf7a2 100644
--- a/fsck/uobjectid.c
+++ b/fsck/uobjectid.c
@@ -1,5 +1,5 @@
/*
- * Copyright 1996-2001 Hans Reiser
+ * Copyright 1996-2002 Hans Reiser
*/
#include "fsck.h"
@@ -10,25 +10,28 @@
*/
-
-/* is it marked used in super block's objectid map */
-int is_objectid_used (reiserfs_filsys_t s, __u32 objectid)
+#if 0
+/* is it marked used in super block's objectid map. fixme: binary search could
+ be used here */
+int is_objectid_used (reiserfs_filsys_t * fs, __u32 objectid)
{
__u32 * objectid_map;
int i = 0;
- objectid_map = (__u32 *)((char *)(s->s_rs) + (sb_size(s)));
+
+ objectid_map = (__u32 *)((char *)(fs->fs_ondisk_sb) + (sb_size(fs)));
- while (i < SB_OBJECTID_MAP_SIZE (s)) {
- if (objectid == objectid_map[i]) {
+ while (i < get_sb_oid_cursize (fs->fs_ondisk_sb)) {
+ if (objectid == le32_to_cpu (objectid_map[i])) {
return 1; /* objectid is used */
}
- if (objectid > objectid_map[i] && objectid < objectid_map[i+1]) {
+ if (objectid > le32_to_cpu(objectid_map[i]) &&
+ objectid < le32_to_cpu(objectid_map[i+1])) {
return 1; /* objectid is used */
}
- if (objectid < objectid_map[i])
+ if (objectid < le32_to_cpu(objectid_map[i]))
break;
i += 2;
@@ -37,25 +40,22 @@ int is_objectid_used (reiserfs_filsys_t s, __u32 objectid)
/* objectid is free */
return 0;
}
+#endif
/* true objectid map */
-/* size of 1 piece of map */
-#define MAP_SIZE 4096 /* must be n * 2 * sizeof(__u32) */
-#define MAX_MAP_SIZE 1 /* % of available memory? */
-
-
-
/* increase area by MAP_SIZE bytes */
static void grow_id_map (struct id_map * map)
{
+/*
if (map->m_page_count && ((map->m_page_count % 5) == 0)) {
fsck_log ("grow_id_map: objectid map expanded: used %lu, %d blocks\n",
map->m_used_slots_count, map->m_page_count);
}
+*/
map->m_begin = expandmem (map->m_begin, map->m_page_count * MAP_SIZE, MAP_SIZE);
map->m_page_count ++;
}
@@ -64,9 +64,11 @@ static void grow_id_map (struct id_map * map)
static void try_to_shrink_id_map (struct id_map * map)
{
if (map->m_used_slots_count * sizeof(__u32) <= (map->m_page_count - 1) * MAP_SIZE) {
+ /*
if (map->m_page_count && ((map->m_page_count % 5) == 0))
fsck_log ("shrink_id_map: objectid map shrinked: used %lu, %d blocks\n",
map->m_used_slots_count, map->m_page_count);
+ */
map->m_begin = expandmem (map->m_begin, map->m_page_count * MAP_SIZE,
-MAP_SIZE);
map->m_page_count--;
@@ -81,42 +83,26 @@ static void try_to_shrink_id_map (struct id_map * map)
static void check_id_search_result(struct id_map * map, int res, __u32 pos,
__u32 id)
{
- if (res != ITEM_FOUND && res != ITEM_NOT_FOUND)
+ if (res != POSITION_FOUND && res != POSITION_NOT_FOUND)
die("check_id_search_result: get wrong result from ubin_search (%d)", res);
- if (res == 1 && *(map->m_begin + pos) != id)
- die("check_id_search_result: wrong id found %u %u", id, *(map->m_begin + pos));
+ if (res == 1 && le32_to_cpu (map->m_begin[pos]) != id)
+ die("check_id_search_result: wrong id found %u %u", id, le32_to_cpu(map->m_begin[pos]));
if (res == 1)
{
if (pos > map->m_used_slots_count)
- die("check_id_search_result: get bad position (%u), used %u",
+ die("check_id_search_result: get bad position (%u), used %u",
pos, map->m_used_slots_count);
- if (pos >= 0 && pos <= map->m_used_slots_count && *(map->m_begin + pos - 1) >= id)
+ if (pos >= 0 && pos <= map->m_used_slots_count && le32_to_cpu(map->m_begin[pos - 1]) >= id)
die("check_id_search_result: previous id (%u) not less than (%u)",
- *(map->m_begin + pos - 1), id);
- if (pos >= 0 && pos < map->m_used_slots_count && *(map->m_begin + pos) < id)
+ le32_to_cpu(map->m_begin[pos - 1]), id);
+ if (pos >= 0 && pos < map->m_used_slots_count && le32_to_cpu(map->m_begin[pos]) < id)
die("check_id_search_result: found id (%u) not much than (%u)",
- *(map->m_begin + pos), id);
+ le32_to_cpu(map->m_begin[pos]), id);
}
}
-
-static int comp_ids (void * p1, void * p2)
-{
- __u32 * id1, * id2;
-
- id1 = p1;
- id2 = p2;
-
- if ( *id1 < *id2 )
- return -1;
- if ( *id1 > *id2 )
- return 1;
- return 0;
-}
-
-
/* */
struct id_map * init_id_map (void)
{
@@ -132,18 +118,18 @@ struct id_map * init_id_map (void)
/* free whole map */
-void free_id_map (struct id_map ** map)
+void free_id_map (struct id_map * map)
{
- freemem ((*map)->m_begin);
- freemem (*map);
- *map = 0;
+ freemem (map->m_begin);
+ freemem (map);
}
/* return 1 if id is marked used, 0 otherwise */
-int is_objectid_really_used (struct id_map * map, __u32 id, int * ppos)
+int is_objectid_really_used (struct id_map * map, __u32 id, __u32 * ppos)
{
int res;
+ __u32 le_id = cpu_to_le32 (id);
*ppos = 0;
@@ -151,13 +137,14 @@ int is_objectid_really_used (struct id_map * map, __u32 id, int * ppos)
return 0;
/* smth exists in the map, find proper place to insert or this id */
- res = ubin_search (&id, map->m_begin, map->m_used_slots_count, sizeof (__u32), ppos, comp_ids);
+ res = reiserfs_bin_search (&le_id, map->m_begin, map->m_used_slots_count,
+ sizeof (__u32), ppos, comp_ids);
#if 1
check_id_search_result (map, res, *ppos, id);
#endif
/* *ppos is position in objectid map of the element which is equal id
or position of an element which is smallest and greater than id */
- if (res == ITEM_NOT_FOUND)
+ if (res == POSITION_NOT_FOUND)
/* id is not found in the map. if returned position is odd -
id is marked used */
return (*ppos % 2);
@@ -166,26 +153,30 @@ int is_objectid_really_used (struct id_map * map, __u32 id, int * ppos)
return !(*ppos % 2);
}
-
-static void check_objectid_map (struct id_map * map)
+static void check_objectid_map (struct id_map * map, int pos)
{
+ /* check only previous id, current and 2 next ones,
+ if not specified to check evth */
+ int count = 3;
int i;
+ int first = pos;
- for (i = 1; i < map->m_used_slots_count; i ++)
- if (map->m_begin [i - 1] >= map->m_begin [i])
- die ("check_objectid_map: map corrupted");
-}
+ if (first == 0) {
+ first = 1;
+ } else if (first == -1) {
+ count = map->m_used_slots_count - 1;
+ first = 1;
+ }
+ if (first + count > map->m_used_slots_count)
+ count = map->m_used_slots_count - first;
-/* returns 1 objectid is marked used already, 0 otherwise */
-int mark_objectid_really_used (struct id_map * map, __u32 id)
-{
- int pos;
+ for (i = first; i < first + count; i ++)
+ if (le32_to_cpu(map->m_begin [i - 1]) >= le32_to_cpu(map->m_begin [i]))
+ die ("check_objectid_map: map corrupted");
+}
-
- /* check whether id is used and get place if used or place to insert if not */
- if (is_objectid_really_used (map, id, &pos) == 1)
- return 1;
+int __mark_objectid_really_used(struct id_map *map, __u32 id, __u32 pos) {
map->objectids_marked ++;
if (pos % 2 == 0){
@@ -200,7 +191,7 @@ int mark_objectid_really_used (struct id_map * map, __u32 id)
/* we can mark id as used w/o expanding of id map */
map->m_begin[pos] = cpu_to_le32 (id);
- check_objectid_map (map);
+ check_objectid_map (map, pos);
return 0;
}
@@ -215,7 +206,7 @@ int mark_objectid_really_used (struct id_map * map, __u32 id)
map->m_begin[pos] = cpu_to_le32 (id);
map->m_begin[pos+1] = cpu_to_le32 (id + 1);
- check_objectid_map (map);
+ check_objectid_map (map, pos);
return 0;
}
@@ -226,19 +217,31 @@ int mark_objectid_really_used (struct id_map * map, __u32 id)
/* if end id of current interval == start id of next interval we
eliminated a sequence of unused objectids */
if (pos + 1 < map->m_used_slots_count &&
- map->m_begin[pos + 1] == map->m_begin[pos]) {
+ map->m_begin[pos + 1] == map->m_begin[pos]) { /* safe, both are le */
memmove (map->m_begin + pos, map->m_begin + pos + 2, (map->m_used_slots_count - pos - 2) * sizeof (__u32));
map->m_used_slots_count -= 2;
try_to_shrink_id_map (map);
}
- check_objectid_map (map);
+ check_objectid_map (map, pos);
return 0;
}
+/* returns 1 objectid is marked used already, 0 otherwise */
+int mark_objectid_really_used (struct id_map * map, __u32 id)
+{
+ __u32 pos;
+
+ /* check whether id is used and get place if used or place to insert if not */
+ if (is_objectid_really_used (map, id, &pos) == 1)
+ return 1;
+
+ return __mark_objectid_really_used(map, id, pos) ;
+}
+
-static __u32 get_free_id (reiserfs_filsys_t fs)
+static __u32 get_free_id (reiserfs_filsys_t * fs)
{
struct id_map * map;
@@ -256,13 +259,14 @@ static __u32 get_free_id (reiserfs_filsys_t fs)
}
-__u32 get_unused_objectid (reiserfs_filsys_t fs)
+__u32 get_unused_objectid (reiserfs_filsys_t * fs)
{
__u32 objectid;
objectid = get_free_id (fs);
if (mark_objectid_really_used (proper_id_map (fs), objectid))
- die ("get_unused_objectid: could not mark %lu used", objectid);
+ die ("get_unused_objectid: could not mark %lu used",
+ ( long unsigned ) objectid);
return objectid;
}
@@ -274,7 +278,7 @@ __u32 get_unused_objectid (reiserfs_filsys_t fs)
#if 0
/* returns 0 if on-disk objectid map matches to the correct one, 1
otherwise */
-int compare_id_maps (reiserfs_filsys_t fs)
+int compare_id_maps (reiserfs_filsys_t * fs)
{
struct id_map * map;
int disk_size;
@@ -293,7 +297,7 @@ int compare_id_maps (reiserfs_filsys_t fs)
/* copy objectid map into buffer containing super block */
-void correct_objectid_map (reiserfs_filsys_t fs)
+void correct_objectid_map (reiserfs_filsys_t * fs)
{
struct id_map * map;
int size, disk_max;
@@ -320,17 +324,15 @@ void correct_objectid_map (reiserfs_filsys_t fs)
#endif
-#if 0
/* print the map of objectids */
-void print_objectid_list ()
+void print_objectid_list (__u32 *map, int count)
{
int i;
- printf ("\n control id map: all %d, used:%d", id_map.m_page_count * MAP_SIZE, id_map.m_used_slots_count);
-
- for (i = 0; i < id_map.m_used_slots_count; i += 2)
- printf ("\n[%u-%u]", id_map.m_begin[i], id_map.m_begin[i + 1] - 1);
+ for (i = 0; i < count ; i += 2)
+ printf ("\n[%u-%u]", le32_to_cpu(map[i]),le32_to_cpu(map[i+1]));
}
+#if 0
/* print on-disk map of objectids */
void print_disk_objectid_list (void)
{
@@ -339,53 +341,120 @@ void print_disk_objectid_list (void)
printf ("\n on-disk id map. used:%lu", SB_OBJECTID_MAP_SIZE(&g_sb));
for (i = 0; i < SB_OBJECTID_MAP_SIZE(&g_sb); i += 2)
- printf ("\n[%u-%u]", objectid_map[i], objectid_map[i + 1] - 1);
+ printf ("\n[%u-%u]", objectid_map[i], objectid_map[i + 1] - 1);
}
#endif
-void flush_objectid_map (struct id_map * map, reiserfs_filsys_t fs)
+void flush_objectid_map (struct id_map * map, reiserfs_filsys_t * fs)
{
int size, max;
int sb_size;
__u32 * sb_objectid_map;
- sb_size = (is_reiser2fs_magic_string (fs->s_rs) ? SB_SIZE : SB_SIZE_V1);
- sb_objectid_map = (__u32 *)((char *)(fs->s_rs) + sb_size);
+ sb_size = reiserfs_super_block_size (fs->fs_ondisk_sb);
+ sb_objectid_map = (__u32 *)((char *)(fs->fs_ondisk_sb) + sb_size);
- check_objectid_map (map);
-
- max = ((fs->s_blocksize - sb_size) >> 3 << 1);
- set_objectid_map_max_size (fs->s_rs, max);
+ max = ((fs->fs_blocksize - sb_size) >> 3 << 1);
+ set_sb_oid_maxsize (fs->fs_ondisk_sb, max);
if (map->m_used_slots_count > max)
size = max;
else
size = map->m_used_slots_count;
+ check_objectid_map (map, -1);
+
memcpy (sb_objectid_map, map->m_begin, size * sizeof (__u32));
memset (sb_objectid_map + size, 0, (max - size) * sizeof (__u32));
- set_objectid_map_size (fs->s_rs, size);
+ set_sb_oid_cursize (fs->fs_ondisk_sb, size);
if (size == max)
- /*((__u32 *)((char *)(fs->s_rs) + sb_size))*/
- sb_objectid_map [max - 1] = map->m_begin [map->m_used_slots_count - 1];
+ sb_objectid_map [max - 1] = map->m_begin [map->m_used_slots_count - 1];
- check_objectid_map (map);
+// check_objectid_map (map);
}
-void fetch_objectid_map (struct id_map * map, reiserfs_filsys_t fs)
+void fetch_objectid_map (struct id_map * map, reiserfs_filsys_t * fs)
{
int sb_size;
__u32 * sb_objectid_map;
- sb_size = (is_reiser2fs_magic_string (fs->s_rs) ? SB_SIZE : SB_SIZE_V1);
- sb_objectid_map = (__u32 *)((char *)(fs->s_rs) + sb_size);
+ sb_size = reiserfs_super_block_size (fs->fs_ondisk_sb);
+ sb_objectid_map = (__u32 *)((char *)(fs->fs_ondisk_sb) + sb_size);
if (map->m_page_count != 1)
die ("fetch_objectid_map: can not fetch long map");
grow_id_map (map);
- memcpy (map->m_begin, sb_objectid_map, rs_objectid_map_size (fs->s_rs) * sizeof (__u32));
- map->m_used_slots_count = rs_objectid_map_size (fs->s_rs);
+ memcpy (map->m_begin, sb_objectid_map, get_sb_oid_cursize (fs->fs_ondisk_sb) * sizeof (__u32));
+ map->m_used_slots_count = get_sb_oid_cursize (fs->fs_ondisk_sb);
+}
+
+#define OBJMAP_START_MAGIC 375331
+#define OBJMAP_END_MAGIC 7700472
+
+void reiserfs_objectid_map_save (FILE * fp, struct id_map * id_map)
+{
+ __u32 v;
+ int i;
+
+ v = OBJMAP_START_MAGIC;
+ fwrite (&v, 4, 1, fp);
+
+ v = id_map->m_used_slots_count;
+ fwrite (&v, 4, 1, fp);
+
+ for (i = 0; i < id_map->m_page_count - 1; i++) {
+ fwrite ((char *)id_map->m_begin + MAP_SIZE * i, 4, 1, fp);
+ }
+
+ for (i = 0; i < id_map->m_used_slots_count * sizeof(__u32) - (id_map->m_page_count - 1) * MAP_SIZE; i++) {
+ fwrite ((char *)id_map->m_begin + MAP_SIZE * (id_map->m_page_count - 1) + i, 4, 1, fp);
+ }
+
+ v = OBJMAP_END_MAGIC;
+ fwrite (&v, 4, 1, fp);
}
+
+struct id_map * reiserfs_objectid_map_load (FILE * fp)
+{
+ __u32 v;
+ int i;
+ struct id_map * id_map;
+
+ fread (&v, 4, 1, fp);
+ if (v != OBJMAP_START_MAGIC) {
+ reiserfs_warning (stderr, "reiserfs_objectid_map_load: no objectid map begin magic found");
+ return 0;
+ }
+
+ /* read bit size of objectid map */
+ fread (&v, 4, 1, fp);
+
+ id_map = init_id_map ();
+
+ id_map->m_used_slots_count = v;
+ id_map->m_page_count = v / MAP_SIZE + 1;
+
+ id_map->m_begin = expandmem (id_map->m_begin, 0, id_map->m_page_count * MAP_SIZE);
+
+ for (i = 0; i < id_map->m_page_count - 1; i++) {
+ fread ((char *)id_map->m_begin + MAP_SIZE * i, 4, 1, fp);
+ }
+
+ for (i = 0; i < id_map->m_used_slots_count * sizeof(__u32) - (id_map->m_page_count - 1) * MAP_SIZE; i++) {
+ fread ((char *)id_map->m_begin + MAP_SIZE * (id_map->m_page_count - 1) + i, 4, 1, fp);
+ }
+
+ fread (&v, 4, 1, fp);
+
+ if (v != OBJMAP_END_MAGIC) {
+ reiserfs_warning (stderr, "reiserfs_objectid_map_load: no objectid map end magic found");
+ return 0;
+ }
+
+ fflush (stderr);
+ return id_map;
+}
+
diff --git a/fsck/ustree.c b/fsck/ustree.c
index 68e7f48..9a41178 100644
--- a/fsck/ustree.c
+++ b/fsck/ustree.c
@@ -1,5 +1,5 @@
/*
- * Copyright 1996-2001 Hans Reiser
+ * Copyright 1996-2002 Hans Reiser
*/
#include "fsck.h"
@@ -20,18 +20,6 @@ int comp_dir_entries (void * key1, void * key2)
}
-void init_tb_struct (struct tree_balance * tb, struct super_block * s, struct path * path, int size)
-{
- memset (tb, '\0', sizeof(struct tree_balance));
- tb->tb_sb = s;
- tb->tb_path = path;
-
- PATH_OFFSET_PBUFFER(path, ILLEGAL_PATH_ELEMENT_OFFSET) = NULL;
- PATH_OFFSET_POSITION(path, ILLEGAL_PATH_ELEMENT_OFFSET) = 0;
- tb->insert_size[0] = size;
-}
-
-
struct tree_balance * cur_tb = 0;
void reiserfsck_paste_into_item (struct path * path, const char * body, int size)
@@ -52,7 +40,7 @@ void reiserfsck_insert_item (struct path * path, struct item_head * ih, const ch
{
struct tree_balance tb;
- init_tb_struct (&tb, fs, path, IH_SIZE + ih_item_len(ih));
+ init_tb_struct (&tb, fs, path, IH_SIZE + get_ih_item_len(ih));
if (fix_nodes (/*tb.transaction_handle,*/ M_INSERT, &tb, ih/*, body*/) != CARRY_ON)
die ("reiserfsck_insert_item: fix_nodes failed");
do_balance (/*tb.transaction_handle,*/ &tb, ih, body, M_INSERT, 0/*zero num*/);
@@ -65,17 +53,17 @@ static void free_unformatted_nodes (struct item_head * ih, struct buffer_head *
int i;
for (i = 0; i < I_UNFM_NUM (ih); i ++, punfm ++)
- if (*punfm) {
+ if (*punfm != 0) {
struct buffer_head * to_be_forgotten;
- to_be_forgotten = find_buffer (fs->s_dev, *punfm, fs->s_blocksize);
+ to_be_forgotten = find_buffer (fs->fs_dev, le32_to_cpu (*punfm), fs->fs_blocksize);
if (to_be_forgotten) {
//atomic_inc(&to_be_forgotten->b_count);
to_be_forgotten->b_count ++;
bforget (to_be_forgotten);
}
- reiserfs_free_block (fs, *punfm);
+ reiserfs_free_block (fs, le32_to_cpu (*punfm));
}
}
@@ -88,7 +76,7 @@ void reiserfsck_delete_item (struct path * path, int temporary)
if (is_indirect_ih (ih) && !temporary)
free_unformatted_nodes (ih, PATH_PLAST_BUFFER (path));
- init_tb_struct (&tb, fs, path, -(IH_SIZE + ih_item_len(ih)));
+ init_tb_struct (&tb, fs, path, -(IH_SIZE + get_ih_item_len(ih)));
if (fix_nodes (/*tb.transaction_handle,*/ M_DELETE, &tb, 0/*ih*/) != CARRY_ON)
die ("reiserfsck_delete_item: fix_nodes failed");
@@ -107,10 +95,10 @@ void reiserfsck_cut_from_item (struct path * path, int cut_size)
if (is_indirect_ih (ih = PATH_PITEM_HEAD (path))) {
__u32 unfm_ptr = B_I_POS_UNFM_POINTER (PATH_PLAST_BUFFER (path), ih, I_UNFM_NUM (ih) - 1);
- if (unfm_ptr) {
+ if (unfm_ptr != 0) {
struct buffer_head * to_be_forgotten;
- to_be_forgotten = find_buffer (fs->s_dev, le32_to_cpu (unfm_ptr), fs->s_blocksize);
+ to_be_forgotten = find_buffer (fs->fs_dev, le32_to_cpu (unfm_ptr), fs->fs_blocksize);
if (to_be_forgotten) {
//atomic_inc(&to_be_forgotten->b_count);
to_be_forgotten->b_count ++;
@@ -130,45 +118,8 @@ void reiserfsck_cut_from_item (struct path * path, int cut_size)
}
-/* uget_lkey is utils clone of stree.c/get_lkey */
-struct key * uget_lkey (struct path * path)
-{
- int pos, offset = path->path_length;
- struct buffer_head * bh;
-
- if (offset < FIRST_PATH_ELEMENT_OFFSET)
- die ("uget_lkey: illegal offset in the path (%d)", offset);
-
-
- /* While not higher in path than first element. */
- while (offset-- > FIRST_PATH_ELEMENT_OFFSET) {
- if (! buffer_uptodate (PATH_OFFSET_PBUFFER (path, offset)) )
- die ("uget_lkey: parent is not uptodate");
-
- /* Parent at the path is not in the tree now. */
- if (! B_IS_IN_TREE (bh = PATH_OFFSET_PBUFFER (path, offset)))
- die ("uget_lkey: buffer on the path is not in tree");
-
- /* Check whether position in the parent is correct. */
- if ((pos = PATH_OFFSET_POSITION (path, offset)) > B_NR_ITEMS (bh))
- die ("uget_lkey: invalid position (%d) in the path", pos);
-
- /* Check whether parent at the path really points to the child. */
- if (B_N_CHILD_NUM (bh, pos) != PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr)
- die ("uget_lkey: invalid block number (%d). Must be %d",
- B_N_CHILD_NUM (bh, pos), PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr);
-
- /* Return delimiting key if position in the parent is not equal to zero. */
- if (pos)
- return B_N_PDELIM_KEY(bh, pos - 1);
- }
-
- /* there is no left delimiting key */
- return 0;
-}
-
-
/* uget_rkey is utils clone of stree.c/get_rkey */
+/*
struct key * uget_rkey (struct path * path)
{
int pos, offset = path->path_length;
@@ -181,316 +132,33 @@ struct key * uget_rkey (struct path * path)
if (! buffer_uptodate (PATH_OFFSET_PBUFFER (path, offset)))
die ("uget_rkey: parent is not uptodate");
- /* Parent at the path is not in the tree now. */
+ // Parent at the path is not in the tree now.
if (! B_IS_IN_TREE (bh = PATH_OFFSET_PBUFFER (path, offset)))
die ("uget_rkey: buffer on the path is not in tree");
- /* Check whether position in the parrent is correct. */
+ // Check whether position in the parrent is correct.
if ((pos = PATH_OFFSET_POSITION (path, offset)) > B_NR_ITEMS (bh))
die ("uget_rkey: invalid position (%d) in the path", pos);
- /* Check whether parent at the path really points to the child. */
- if (B_N_CHILD_NUM (bh, pos) != PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr)
- die ("uget_rkey: invalid block number (%d). Must be %d",
- B_N_CHILD_NUM (bh, pos), PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr);
+ // Check whether parent at the path really points to the child.
+ if (get_dc_child_blocknr (B_N_CHILD (bh, pos)) != PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr)
+ die ("uget_rkey: invalid block number (%d). Must be %ld",
+ get_dc_child_blocknr (B_N_CHILD (bh, pos)), PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr);
- /* Return delimiting key if position in the parent is not the last one. */
+ // Return delimiting key if position in the parent is not the last one.
if (pos != B_NR_ITEMS (bh))
return B_N_PDELIM_KEY(bh, pos);
}
-
- /* there is no right delimiting key */
- return 0;
-}
-
-
-inline int ubin_search (void * key, void * base, int num, int width, __u32 *ppos, comp_function_t comp_func)
-{
- __u32 rbound, lbound, j;
-
- lbound = 0;
-
- if (num == 0){
- *ppos = 0;
- return ITEM_NOT_FOUND;
- }
-
- rbound = num - 1;
-
- for (j = (rbound + lbound) / 2; lbound <= rbound; j = (rbound + lbound) / 2) {
- switch (comp_func ((void *)((char *)base + j * width), key ) ) {
- case -1:/* second is greater */
- lbound = j + 1;
- continue;
-
- case 1: /* first is greater */
- if (j == 0){
- *ppos = lbound;
- return ITEM_NOT_FOUND;
- }
- rbound = j - 1;
- continue;
-
- case 0:
- *ppos = j;
- return ITEM_FOUND;
- }
- }
-
- *ppos = lbound;
- return ITEM_NOT_FOUND;
-}
-
-/* this searches in tree through items */
-int usearch_by_key (struct super_block * s, struct key * key, struct path * path)
-{
- struct buffer_head * bh;
- unsigned long block = SB_ROOT_BLOCK (s);
- struct path_element * curr;
- int retval;
-
- path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
- while (1) {
- curr = PATH_OFFSET_PELEMENT (path, ++ path->path_length);
- bh = curr->pe_buffer = bread (s->s_dev, block, s->s_blocksize);
- if (bh == 0)
- reiserfs_panic ("usearch_by_key: unable to read %lu block on device 0x%x\n",block, s->s_dev);
- retval = ubin_search (key, B_N_PKEY (bh, 0), B_NR_ITEMS (bh),
- is_leaf_node (bh) ? IH_SIZE : KEY_SIZE, &(curr->pe_position), comp_keys);
- if (retval == ITEM_FOUND) {
- /* key found, return if this is leaf level */
- if (is_leaf_node (bh)) {
- path->pos_in_item = 0;
- return ITEM_FOUND;
- }
- curr->pe_position ++;
- } else {
- /* key not found in the node */
- if (is_leaf_node (bh))
- return ITEM_NOT_FOUND;
- }
- block = B_N_CHILD_NUM (bh, curr->pe_position);
- }
- die ("search_by_key: you can not get here");
+ // there is no right delimiting key
return 0;
}
-
-
-/* key is key of directory entry. This searches in tree through items and in
- the found directory item as well */
-int usearch_by_entry_key (struct super_block * s, struct key * key, struct path * path)
-{
- struct buffer_head * bh;
- struct item_head * ih;
- struct key tmpkey;
-
- if (usearch_by_key (s, key, path) == ITEM_FOUND) {
- /* entry found */
- path->pos_in_item = 0;
- return POSITION_FOUND;
- }
-
- bh = PATH_PLAST_BUFFER (path);
-
- if (PATH_LAST_POSITION (path) == 0) {
- /* previous item does not exist, that means we are in leftmost leaf of
- the tree */
- if (uget_lkey (path) != 0)
- die ("search_by_entry_key: invalid position after search_by_key");
-
- if (not_of_one_file (B_N_PKEY (bh, 0), key)) {
- path->pos_in_item = 0;
- return DIRECTORY_NOT_FOUND;
- }
-
- if (!is_direntry_ih (get_ih (path))) {
- fsck_progress ("search_by_entry_key: directory expected to have this key %K\n", key);
- return REGULAR_FILE_FOUND;
- }
-
- /* position for name insertion is found */
- path->pos_in_item = 0;
- return POSITION_NOT_FOUND;
- }
-
- /* take previous item */
- PATH_LAST_POSITION (path) --;
- ih = PATH_PITEM_HEAD (path);
- if (not_of_one_file (&(ih->ih_key), key) || !is_direntry_ih(ih)) {
- /* previous item belongs to another object or is stat data, check next
- item */
-
- PATH_LAST_POSITION (path) ++;
- if (PATH_LAST_POSITION (path) < B_NR_ITEMS (bh))
- {
- /* found item is not last item of the node */
- struct item_head * next_ih = B_N_PITEM_HEAD (bh, PATH_LAST_POSITION (path));
-
- if (not_of_one_file (&(next_ih->ih_key), key))
- {
- path->pos_in_item = 0;
- return DIRECTORY_NOT_FOUND;
- }
- if (!is_direntry_ih(next_ih))
- {
- /* there is an item in the tree, but it is not a directory item */
- reiserfs_warning (stderr, "search_by_entry_key: directory expected to have this key %k\n",
- key);
- return REGULAR_FILE_FOUND;
- }
- } else {
- /* found item is last item of the node */
- struct key * next_key = uget_rkey (path);
-
- if (next_key == 0 || not_of_one_file (next_key, key))
- {
- /* there is not any part of such directory in the tree */
- path->pos_in_item = 0;
- return DIRECTORY_NOT_FOUND;
- }
-
- if (!is_direntry_key (next_key))
- {
- /* there is an item in the tree, but it is not a directory item */
- fsck_progress ("search_by_entry_key: directory expected to have this key %k\n",
- key);
- return REGULAR_FILE_FOUND;
- }
-
- // we got right delimiting key - search for it - the entry will be
- // pasted in position 0
- copy_key (&tmpkey, next_key);
- pathrelse (path);
- if (usearch_by_key (s, &tmpkey, path) != ITEM_FOUND || PATH_LAST_POSITION (path) != 0)
- die ("search_by_entry_key: item not found by corresponding delimiting key");
- }
-
- /* next item is the part of this directory */
- path->pos_in_item = 0;
-
- return POSITION_NOT_FOUND;
- }
-
- /* previous item is part of desired directory */
- if (ubin_search (&(key->u.k_offset_v1.k_offset), B_I_DEH (bh, ih), ih_entry_count (ih),
- DEH_SIZE, &(path->pos_in_item), comp_dir_entries) == ITEM_FOUND)
- return POSITION_FOUND;
-
- return POSITION_NOT_FOUND;
-}
-
-
-/* key is key of byte in the regular file. This searches in tree
- through items and in the found item as well */
-int usearch_by_position (struct super_block * s, struct key * key, int version, struct path * path)
-{
- struct buffer_head * bh;
- struct item_head * ih;
-
- if (usearch_by_key (s, key, path) == ITEM_FOUND)
- {
- ih = PATH_PITEM_HEAD (path);
-
- if (!is_direct_ih(ih) && !is_indirect_ih(ih))
- return DIRECTORY_FOUND;
- path->pos_in_item = 0;
- return POSITION_FOUND;
- }
-
- bh = PATH_PLAST_BUFFER (path);
- ih = PATH_PITEM_HEAD (path);
-
-
- if ( (PATH_LAST_POSITION(path) < B_NR_ITEMS (bh)) &&
- !not_of_one_file (&ih->ih_key, key) &&
- (get_offset(&ih->ih_key) == get_offset(key)) )
- {
-
- if (!is_direct_ih(ih) && !is_indirect_ih(ih))
- return DIRECTORY_FOUND;
- path->pos_in_item = 0;
-
-
- return POSITION_FOUND;
- }
-
- if (PATH_LAST_POSITION (path) == 0) {
- /* previous item does not exist, that means we are in leftmost leaf of the tree */
- if (!not_of_one_file (B_N_PKEY (bh, 0), key)) {
- if (!is_direct_ih(ih) && !is_indirect_ih (ih))
- return DIRECTORY_FOUND;
- return POSITION_NOT_FOUND;
- }
- return FILE_NOT_FOUND;
- }
-
-
- /* take previous item */
- PATH_LAST_POSITION (path) --;
- ih = PATH_PITEM_HEAD (path);
-
- if (not_of_one_file (&ih->ih_key, key) || is_stat_data_ih(ih)) {
- struct key * next_key;
-
- /* previous item belongs to another object or is a stat data, check next item */
- PATH_LAST_POSITION (path) ++;
- if (PATH_LAST_POSITION (path) < B_NR_ITEMS (PATH_PLAST_BUFFER (path)))
- /* next key is in the same node */
- next_key = B_N_PKEY (PATH_PLAST_BUFFER (path), PATH_LAST_POSITION (path));
- else
- next_key = uget_rkey (path);
- if (next_key == 0 || not_of_one_file (next_key, key)) {
- /* there is no any part of such file in the tree */
- path->pos_in_item = 0;
- return FILE_NOT_FOUND;
- }
-
- if (is_direntry_key (next_key)) {
- fsck_log ("\nusearch_by_position: looking for %k found a directory with the same key\n", next_key);
- return DIRECTORY_FOUND;
- }
- /* next item is the part of this file */
- path->pos_in_item = 0;
- if ( get_offset(next_key) == get_offset(key) ) {
- pathrelse(path);
- if (usearch_by_key (s, next_key, path) != ITEM_FOUND) {
- reiserfs_panic ("usearch_by_position: keys must be equals %k %k",
- next_key, &PATH_PITEM_HEAD (path)->ih_key);
- }
- return POSITION_FOUND;
- }
-
- return POSITION_NOT_FOUND;
- }
-
- if (is_direntry_ih(ih)) {
- return DIRECTORY_FOUND;
- }
- if (is_stat_data_ih(ih)) {
- PATH_LAST_POSITION (path) ++;
- return FILE_NOT_FOUND;
- }
-
- /* previous item is part of desired file */
-
-
- //if (is_key_in_item (bh,ih,key,bh->b_size)) {
- if (I_K_KEY_IN_ITEM (ih, key, bh->b_size)) {
- path->pos_in_item = get_offset (key) - get_offset (&ih->ih_key);
- if (is_indirect_ih (ih) )
- path->pos_in_item /= bh->b_size;
- return POSITION_FOUND;
- }
-
- path->pos_in_item = is_indirect_ih (ih) ? I_UNFM_NUM (ih) : ih_item_len (ih);
- return POSITION_NOT_FOUND;
-}
+*/
static unsigned long first_child (struct buffer_head * bh)
{
- return child_block_number (bh, 0);
+ return get_dc_child_blocknr (B_N_CHILD (bh, 0));
}
#if 0
@@ -500,6 +168,7 @@ static unsigned long last_child (struct buffer_head * bh)
}
#endif
+
static unsigned long get_child (int pos, struct buffer_head * parent)
{
if (pos == -1)
@@ -507,22 +176,15 @@ static unsigned long get_child (int pos, struct buffer_head * parent)
if (pos > B_NR_ITEMS (parent))
die ("get_child: no child found, should not happen: %d of %d", pos, B_NR_ITEMS (parent));
- return child_block_number (parent, pos);
+ return get_dc_child_blocknr (B_N_CHILD (parent, pos));
-/*
- for (i = 0; i < B_NR_ITEMS (parent); i ++)
- {
- if (child_block_number (parent, i) == block)
- return child_block_number (parent, i + 1);
- }
- die ("next_child: no child found: should not happen");
- return 0;
- */
}
static void print (int cur, int total)
{
+ if (fsck_quiet (fs))
+ return;
printf ("/%3d (of %3d)", cur, total);fflush (stdout);
}
@@ -530,160 +192,84 @@ static void print (int cur, int total)
/* erase /XXX(of XXX) */
static void erase (void)
{
+ if (fsck_quiet (fs))
+ return;
printf ("\b\b\b\b\b\b\b\b\b\b\b\b\b");
printf (" ");
printf ("\b\b\b\b\b\b\b\b\b\b\b\b\b");
fflush (stdout);
}
-#if 0
-void pass_through_tree2 (struct super_block * s, do_after_read_t action1,
+void pass_through_tree (reiserfs_filsys_t * fs, do_after_read_t action1,
do_on_full_path_t action2)
{
struct buffer_head * path[MAX_HEIGHT] = {0,};
int total[MAX_HEIGHT] = {0,};
int cur[MAX_HEIGHT] = {0,};
int h = 0;
- unsigned long block = SB_ROOT_BLOCK (s);
- int del_p;
+ unsigned long block = get_sb_root_block (fs->fs_ondisk_sb);
+ int problem;
- if (block >= SB_BLOCK_COUNT (s) || not_data_block (s, block))
- return;
+
+ if (block >= get_sb_block_count (fs->fs_ondisk_sb) || not_data_block (fs, block)) {
+ die ("\nBad root block %lu. (--rebuild-tree did not complete)\n", block);
+ }
while ( 1 ) {
+ problem = 0;
+
if (path[h])
die ("pass_through_tree: empty slot expected");
if (h)
print (cur[h - 1], total[h - 1]);
- path[h] = bread (s->s_dev, block, s->s_blocksize);
- get_child (-1, path[h]);
-
- if (path[h] == 0)
- reiserfs_warning ("pass_through_tree: unable to read %lu block on device 0x%x\n",
- block, s->s_dev);
+ if (fs->fs_badblocks_bm && reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, block)) {
+ fsck_log ("%s: block %lu specified in badblock list found in tree, whole subtree skipped\n",
+ __FUNCTION__, block);
+ fsck_data (fs)->check.bad_nodes++;
+ one_more_corruption (fs, fatal);
- del_p = 0;
- if (path[h] && action1) {
- if (action1 (s, path, h)) {
- ;
-#if 0
- // something wrong with a buffer we just have read
- if (opt_fsck_mode == FSCK_FAST_REBUILD){
- //need to change the way we are going on
- del_p = 1;
- if (h == 0)
- break;
- } else {
- ;
- //reiserfs_panic (s, "Run reiserfsck with --rebuild-tree\n");
- }
-#endif
+ if (h == 0) {
+ brelse (path[h]);
+ path[h] = 0;
+ break;
}
- }
-
- if (!path[h] || is_leaf_node (path[h]))
- {
- if (path[h] && action2) {
- if (action2 (s, path, h)) {
- ;
-#if 0
- if (opt_fsck_mode == FSCK_FAST_REBUILD) {
- //need to change the way we are going on
- del_p = 1;
- if (h == 0)
- break;
- } else {
- ;
- //reiserfs_panic (s, "Run reiserfsck with --rebuild-tree\n");
+ problem = 1;
+ } else {
+ path[h] = bread (fs->fs_dev, block, fs->fs_blocksize);
+ if (path[h] == 0)
+ /* FIXME: handle case when read failed */
+ die ("pass_through_tree: unable to read %lu block on device 0x%x\n",
+ block, fs->fs_dev);
+
+ if (action1)
+ if ((problem = action1 (fs, path, h))) {
+ fsck_log ("whole subtree skipped\n");
+ fsck_data (fs)->check.bad_nodes++;
+
+ if (h == 0) {
+ brelse (path[h]);
+ path[h] = 0;
+ break;
}
-#endif
}
- }
-
- if (path[h])
- brelse (path[h]);
- if (h)
- erase ();
-
- while (h && (!path[h-1] || cur[h-1] == total[h-1] ))
- {
- path[h] = 0;
- h --;
- if (path[h])
- brelse (path[h]);
- if (h)
- erase ();
- }
-
- if (h == 0) {
- path[h] = 0;
- break;
- }
-
- if (path[h])
- cur[h - 1] ++;
- if (del_p){
- total[h-1]--;
- del_p = 0;
- }
- block = get_child (cur[h - 1] - 1, path[h-1]);
- path[h] = 0;
- continue;
- }
- total[h] = B_NR_ITEMS (path[h]) + 1;
- cur[h] = 1;
- block = first_child (path[h]);
- h ++;
- }
-}
-#endif
-
-void pass_through_tree (struct super_block * s, do_after_read_t action1,
- do_on_full_path_t action2)
-{
- struct buffer_head * path[MAX_HEIGHT] = {0,};
- int total[MAX_HEIGHT] = {0,};
- int cur[MAX_HEIGHT] = {0,};
- int h = 0;
- unsigned long block = SB_ROOT_BLOCK (s);
-
-
- if (block >= SB_BLOCK_COUNT (s) || not_data_block (s, block)) {
- fsck_progress ("\nBad root block %lu. (--rebuild-tree did not complete)\n", block);
- return;
- }
-
-
- while ( 1 ) {
- if (path[h])
- die ("pass_through_tree: empty slot expected");
- if (h)
- print (cur[h - 1], total[h - 1]);
-
- path[h] = bread (s->s_dev, block, s->s_blocksize);
- if (path[h] == 0)
- /* FIXME: handle case when read failed */
- die ("pass_through_tree: unable to read %lu block on device 0x%x\n",
- block, s->s_dev);
-
- if (action1)
- action1 (s, path, h);
+ }
- if (is_leaf_node (path[h])) {
- if (action2)
- action2 (s, path, h);
+ if (problem || is_leaf_node (path[h])) {
+ if (!problem && action2)
+ action2 (fs, path, h);
brelse (path[h]);
if (h)
erase ();
- while (h && (cur[h-1] == total[h-1])) {
- path[h] = 0;
- h --;
- brelse (path[h]);
- if (h)
- erase ();
+ while (h && (cur[h-1] == total[h-1] || problem)) {
+ problem = 0;
+ path[h] = 0;
+ h --;
+ brelse (path[h]);
+ if (h)
+ erase ();
}
if (h == 0) {
@@ -692,7 +278,7 @@ void pass_through_tree (struct super_block * s, do_after_read_t action1,
}
block = get_child (cur[h - 1], path[h-1]);
- cur[h - 1] ++;
+ cur[h - 1] ++;
path[h] = 0;
continue;
}
diff --git a/include/Makefile.am b/include/Makefile.am
index 0de55ab..96c1615 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -1 +1 @@
-noinst_HEADERS = io.h misc.h reiserfs_fs.h reiserfs_lib.h
+noinst_HEADERS = io.h misc.h reiserfs_fs.h reiserfs_lib.h swab.h
diff --git a/include/Makefile.in b/include/Makefile.in
index 813e729..dfd02cb 100644
--- a/include/Makefile.in
+++ b/include/Makefile.in
@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -62,13 +62,15 @@ MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
+sbindir = @sbindir@
-noinst_HEADERS = io.h misc.h reiserfs_fs.h reiserfs_lib.h
+noinst_HEADERS = io.h misc.h reiserfs_fs.h reiserfs_lib.h swab.h
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES =
HEADERS = $(noinst_HEADERS)
-DIST_COMMON = Makefile.am Makefile.in
+DIST_COMMON = ./stamp-h.in Makefile.am Makefile.in config.h.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
@@ -85,6 +87,34 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+config.h: stamp-h
+ @if test ! -f $@; then \
+ rm -f stamp-h; \
+ $(MAKE) stamp-h; \
+ else :; fi
+stamp-h: $(srcdir)/config.h.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES= CONFIG_HEADERS=include/config.h \
+ $(SHELL) ./config.status
+ @echo timestamp > stamp-h 2> /dev/null
+$(srcdir)/config.h.in: $(srcdir)/stamp-h.in
+ @if test ! -f $@; then \
+ rm -f $(srcdir)/stamp-h.in; \
+ $(MAKE) $(srcdir)/stamp-h.in; \
+ else :; fi
+$(srcdir)/stamp-h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOHEADER)
+ @echo timestamp > $(srcdir)/stamp-h.in 2> /dev/null
+
+mostlyclean-hdr:
+
+clean-hdr:
+
+distclean-hdr:
+ -rm -f config.h
+
+maintainer-clean-hdr:
+
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP)
@@ -95,15 +125,15 @@ ID: $(HEADERS) $(SOURCES) $(LISP)
here=`pwd` && cd $(srcdir) \
&& mkid -f$$here/ID $$unique $(LISP)
-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS)'; \
unique=`for i in $$list; do echo $$i; done | \
awk ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
- test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
- || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+ test -z "$(ETAGS_ARGS)config.h.in$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags config.h.in $$unique $(LISP) -o $$here/TAGS)
mostlyclean-tags:
@@ -122,7 +152,7 @@ distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
- cp -pr $$/$$file $(distdir)/$$file; \
+ cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
@@ -137,6 +167,9 @@ check-am: all-am
check: check-am
installcheck-am:
installcheck: installcheck-am
+all-recursive-am: config.h
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
install-exec-am:
install-exec: install-exec-am
@@ -148,7 +181,7 @@ install-am: all-am
install: install-am
uninstall-am:
uninstall: uninstall-am
-all-am: Makefile $(HEADERS)
+all-am: Makefile $(HEADERS) config.h
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
@@ -164,28 +197,29 @@ distclean-generic:
-rm -f config.cache config.log stamp-h stamp-h[0-9]*
maintainer-clean-generic:
-mostlyclean-am: mostlyclean-tags mostlyclean-generic
+mostlyclean-am: mostlyclean-hdr mostlyclean-tags mostlyclean-generic
mostlyclean: mostlyclean-am
-clean-am: clean-tags clean-generic mostlyclean-am
+clean-am: clean-hdr clean-tags clean-generic mostlyclean-am
clean: clean-am
-distclean-am: distclean-tags distclean-generic clean-am
+distclean-am: distclean-hdr distclean-tags distclean-generic clean-am
distclean: distclean-am
-maintainer-clean-am: maintainer-clean-tags maintainer-clean-generic \
- distclean-am
+maintainer-clean-am: maintainer-clean-hdr maintainer-clean-tags \
+ maintainer-clean-generic distclean-am
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
maintainer-clean: maintainer-clean-am
-.PHONY: tags mostlyclean-tags distclean-tags clean-tags \
-maintainer-clean-tags distdir info-am info dvi-am dvi check check-am \
-installcheck-am installcheck install-exec-am install-exec \
+.PHONY: mostlyclean-hdr distclean-hdr clean-hdr maintainer-clean-hdr \
+tags mostlyclean-tags distclean-tags clean-tags maintainer-clean-tags \
+distdir info-am info dvi-am dvi check check-am installcheck-am \
+installcheck all-recursive-am install-exec-am install-exec \
install-data-am install-data install-am install uninstall-am uninstall \
all-redirect all-am all installdirs mostlyclean-generic \
distclean-generic clean-generic maintainer-clean-generic clean \
diff --git a/include/config.h.in b/include/config.h.in
new file mode 100644
index 0000000..ef58491
--- /dev/null
+++ b/include/config.h.in
@@ -0,0 +1,90 @@
+/* include/config.h.in. Generated automatically from configure.in by autoheader. */
+/*
+ * Copyright 1996, 1997 Hans Reiser, see reiserfs/README for licensing and copyright details
+ */
+
+/* Define if you don't have `vprintf' but do have `_doprnt.' */
+#undef HAVE_DOPRNT
+
+/* Define if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define if you have the `strftime' function. */
+#undef HAVE_STRFTIME
+
+/* Define if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define if you have the `strstr' function. */
+#undef HAVE_STRSTR
+
+/* Define if you have the `strtol' function. */
+#undef HAVE_STRTOL
+
+/* Define if `st_rdev' is member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_RDEV
+
+/* Define if your `struct stat' has `st_rdev'. Deprecated, use
+ `HAVE_STRUCT_STAT_ST_RDEV' instead. */
+#undef HAVE_ST_RDEV
+
+/* Define if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define if you have the `vprintf' function. */
+#undef HAVE_VPRINTF
+
+/* gets set when configure --enable-io-failure-emulation */
+#undef IO_FAILURE_EMULATION
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define as `__inline' if that's what the C compiler calls it, or to nothing
+ if it is not supported. */
+#undef inline
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+#undef size_t
diff --git a/include/io.h b/include/io.h
index 3ffbbfe..1576fcb 100644
--- a/include/io.h
+++ b/include/io.h
@@ -1,29 +1,42 @@
+/*
+ * Copyright 1996-2002 Hans Reiser
+ */
+
+
struct buffer_head {
- unsigned long b_blocknr;
- unsigned short b_dev;
- unsigned long b_size;
- char * b_data;
- unsigned long b_state;
- unsigned int b_count;
- unsigned int b_list ;
- void (*b_end_io)(struct buffer_head *bh, int uptodate);
-
- struct buffer_head * b_next;
- struct buffer_head * b_prev;
- struct buffer_head * b_hash_next;
- struct buffer_head * b_hash_prev;
+ unsigned long b_blocknr;
+ unsigned short b_dev;
+ unsigned long b_size;
+ char * b_data;
+ unsigned long b_state;
+ unsigned int b_count;
+ unsigned int b_list ;
+ void (*b_start_io) (unsigned long);
+ void (*b_end_io)(struct buffer_head *bh, int uptodate);
+
+ struct buffer_head * b_next;
+ struct buffer_head * b_prev;
+ struct buffer_head * b_hash_next;
+ struct buffer_head * b_hash_prev;
};
#define BH_Uptodate 0
#define BH_Dirty 1
#define BH_Lock 2
+#define BH_Do_not_flush 3
#define buffer_uptodate(bh) test_bit(BH_Uptodate, &(bh)->b_state)
#define buffer_dirty(bh) test_bit(BH_Dirty, &(bh)->b_state)
#define buffer_locked(bh) test_bit(BH_Lock, &(bh)->b_state)
#define buffer_clean(bh) !test_bit(BH_Dirty, &(bh)->b_state)
+#define buffer_do_not_flush(bh) test_bit(BH_Do_not_flush, &(bh)->b_state)
#define mark_buffer_dirty(bh) set_bit(BH_Dirty, &(bh)->b_state)
+#define mark_buffer_uptodate(bh,i) set_bit(BH_Uptodate, &(bh)->b_state)
+#define mark_buffer_clean(bh) clear_bit(BH_Dirty, &(bh)->b_state)
+#define mark_buffer_do_not_flush(bh) set_bit(BH_Do_not_flush, &(bh)->b_state)
+#define clear_buffer_do_not_flush(bh) clear_bit(BH_Do_not_flush, &(bh)->b_state)
+
/*
printf ("%s:%s:%u %p %p %p\n",
__FILE__, __FUNCTION__, __LINE__,
@@ -32,26 +45,29 @@ __FILE__, __FUNCTION__, __LINE__,
__builtin_return_address (2));
*/
-#define mark_buffer_uptodate(bh,i) set_bit(BH_Uptodate, &(bh)->b_state)
-#define mark_buffer_clean(bh) clear_bit(BH_Dirty, &(bh)->b_state)
void __wait_on_buffer (struct buffer_head * bh);
-struct buffer_head * getblk (int dev, int block, int size);
-struct buffer_head * reiserfs_getblk (int dev, int block, int size, int *repeat);
+struct buffer_head * getblk (int dev, unsigned long block, int size);
+struct buffer_head * reiserfs_getblk (int dev, unsigned long block, int size, int *repeat);
-struct buffer_head * find_buffer (int dev, int block, int size);
-struct buffer_head * get_hash_table(dev_t dev, int block, int size);
+struct buffer_head * find_buffer (int dev, unsigned long block, int size);
+struct buffer_head * get_hash_table(dev_t dev, unsigned long block, int size);
struct buffer_head * bread (int dev, unsigned long block, size_t size);
-struct buffer_head * reiserfs_bread (int dev, int block, int size, int *repeat);
+struct buffer_head * reiserfs_bread (int dev, unsigned long block, int size, int *repeat);
int valid_offset (int fd, loff_t offset);
int bwrite (struct buffer_head * bh);
void brelse (struct buffer_head * bh);
void bforget (struct buffer_head * bh);
void check_and_free_buffer_mem (void);
+void init_rollback_file (char * rollback_file, int *bloksize, FILE * log);
+int open_rollback_file (char * rollback_file, FILE * log);
+void close_rollback_file ();
+void do_fsck_rollback (int fd_device, int fd_journal_device, FILE * log);
-void flush_buffers (void);
+void flush_buffers (dev_t);
void free_buffers (void);
+void invalidate_buffers (dev_t dev);
-loff_t reiserfs_llseek (unsigned int fd, loff_t offset, unsigned int origin);
+int user_confirmed (FILE * fp, char * q, char * yes);
diff --git a/include/misc.h b/include/misc.h
index 91df4db..97308a6 100644
--- a/include/misc.h
+++ b/include/misc.h
@@ -1,42 +1,136 @@
/*
- * Copyright 1996-2000 Hans Reiser
+ * Copyright 1996-2002 Hans Reiser
*/
/* nothing abount reiserfs here */
+#include <endian.h>
+#include "swab.h"
-void die (char * fmt, ...);
+#define POSITION_FOUND 8
+#define POSITION_NOT_FOUND 9
+
+void die (char * fmt, ...) __attribute__ ((format (printf, 1, 2)));
void * getmem (int size);
void freemem (void * p);
void checkmem (char * p, int size);
void * expandmem (void * p, int size, int by);
+int get_mem_size (char * p);
int is_mounted (char * device_name);
int is_mounted_read_only (char * device_name);
void check_and_free_mem (void);
char * kdevname (int dev);
-int set_bit (int nr, void * addr);
-int clear_bit (int nr, void * addr);
-int test_bit(int nr, const void * addr);
-int find_first_zero_bit (const void *vaddr, unsigned size);
-int find_next_zero_bit (const void *vaddr, unsigned size, unsigned offset);
-
-void print_how_far (unsigned long * passed, unsigned long total, int inc, int quiet);
+void print_how_far (FILE * fp, unsigned long * passed, unsigned long total, int inc, int quiet);
void print_how_fast (unsigned long total,
- unsigned long passed, int cursor_pos);
-int user_confirmed (char * q, char * yes);
+ unsigned long passed, int cursor_pos, int reset_time);
+__u32 get_random (void);
+int uuid_is_null(unsigned char * uuid);
+int generate_random_uuid (unsigned char * uuid);
+int uuid_is_correct (unsigned char * uuid);
+int set_uuid (const unsigned char * text, unsigned char * UUID);
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+int le_set_bit (int nr, void * addr);
+int le_clear_bit (int nr, void * addr);
+int le_test_bit(int nr, const void * addr);
+int le_find_first_zero_bit (const void *vaddr, unsigned size);
+int le_find_next_zero_bit (const void *vaddr, unsigned size, unsigned offset);
+# define cpu_to_le16(val) (val)
+# define le16_to_cpu(val) (val)
+# define cpu_to_le32(val) (val)
+# define le32_to_cpu(val) (val)
+# define cpu_to_le64(val) (val)
+# define le64_to_cpu(val) (val)
+# define set_bit(nr, addr) le_set_bit(nr, addr)
+# define clear_bit(nr, addr) le_clear_bit(nr, addr)
+# define test_bit(nr, addr) le_test_bit(nr, addr)
+# define find_first_zero_bit(vaddr, size) le_find_first_zero_bit(vaddr, size)
+# define find_next_zero_bit(vaddr, size, off) \
+ le_find_next_zero_bit(vaddr, size, off)
+#elif __BYTE_ORDER == __BIG_ENDIAN
+
+int be_set_bit (int nr, void * addr);
+int be_clear_bit (int nr, void * addr);
+int be_test_bit(int nr, const void * addr);
+int be_find_first_zero_bit (const void *vaddr, unsigned size);
+int be_find_next_zero_bit (const void *vaddr, unsigned size, unsigned offset);
+# define cpu_to_le16(val) swab16(val)
+# define le16_to_cpu(val) swab16(val)
+# define cpu_to_le32(val) swab32(val)
+# define le32_to_cpu(val) swab32(val)
+# define cpu_to_le64(val) swab64(val)
+# define le64_to_cpu(val) swab64(val)
+# define set_bit(nr, addr) be_set_bit(nr, addr)
+# define clear_bit(nr, addr) be_clear_bit(nr, addr)
+# define test_bit(nr, addr) be_test_bit(nr, addr)
+# define find_first_zero_bit(vaddr, size) be_find_first_zero_bit(vaddr, size)
+# define find_next_zero_bit(vaddr, size, off) \
+ be_find_next_zero_bit(vaddr, size, off)
+#else
+# error "nuxi/pdp-endian archs are not supported"
+#endif
+
+
+
+unsigned long count_blocks (char * filename, int blocksize);
+
+mode_t get_st_mode (char * file_name);
+dev_t get_st_rdev (char * file_name);
+off64_t get_st_size (char * file_name);
+blkcnt64_t get_st_blocks (char * file_name);
+
+
+/* these are to access bitfield in endian safe manner */
+__u16 mask16 (int from, int count);
+__u32 mask32 (int from, int count);
+__u64 mask64 (int from, int count);
+
+
+int reiserfs_bin_search (void * key, void * base, __u32 num, int width,
+ __u32 *ppos, comparison_fn_t comp_func);
+
+struct block_handler {
+ __u32 blocknr;
+ dev_t device;
+};
+
+int blocklist__is_block_saved (struct block_handler ** base, __u32 * count, __u32 blocknr, dev_t device, __u32 * position);
+void blocklist__insert_in_position (void ** base, __u32 * count, void * block_h, int elem_size, __u32 * position);
+int blockdev_list_compare (const void * block1, const void * block2);
+
+
+#define set_bit_field_XX(XX,vp,val,from,count) \
+{\
+ __u##XX * p, tmp;\
+\
+ /* make sure that given value can be put in 'count' bits */\
+ if (val > (1 << count))\
+ die ("set_bit_field: val %d is too big for %d bits", val, count);\
+\
+ p = (__u##XX *)vp;\
+ tmp = le##XX##_to_cpu (*p);\
+\
+ /* clear 'count' bits starting from 'from'-th one */\
+ tmp &= ~mask##XX (from, count);\
+\
+ /* put given value in proper bits */\
+ tmp |= (val << from);\
+\
+ *p = cpu_to_le##XX (tmp);\
+}
-/*
-int test_and_set_bit (int nr, void * addr);
-int test_and_clear_bit (int nr, void * addr);
-*/
-inline __u32 cpu_to_le32 (__u32 val);
-inline __u32 le32_to_cpu (__u32 val);
-inline __u16 cpu_to_le16 (__u16 val);
-inline __u16 le16_to_cpu (__u16 val);
-inline __u64 cpu_to_le64 (__u64 val);
-inline __u64 le64_to_cpu (__u64 val);
-
-unsigned long count_blocks (char * filename, int blocksize, int fd);
+#define get_bit_field_XX(XX,vp,from,count) \
+\
+ __u##XX * p, tmp;\
+\
+ p = (__u##XX *)vp;\
+ tmp = le##XX##_to_cpu (*p);\
+\
+ /* clear all bits but 'count' bits starting from 'from'-th one */\
+ tmp &= mask##XX (from, count);\
+\
+ /* get value written in specified bits */\
+ tmp >>= from;\
+ return tmp;
diff --git a/include/reiserfs_fs.h b/include/reiserfs_fs.h
index 101a151..eaa01d8 100644
--- a/include/reiserfs_fs.h
+++ b/include/reiserfs_fs.h
@@ -1,51 +1,50 @@
/*
- * Copyright 1996-2001 by Hans Reiser, licensing governed by reiserfs/README
+ * Copyright 1996-2002 by Hans Reiser, licensing governed by reiserfs/README
*/
/*
- * include/linux/reiser_fs.h
- *
* Reiser File System constants and structures
- *
*/
-/* in reading the #defines, it may help to understand that they employ
- the following abbreviations:
-
-B = Buffer
-I = Item header
-H = Height within the tree (should be changed to LEV)
-N = Number of the item in the node
-STAT = stat data
-DEH = Directory Entry Header
-EC = Entry Count
-E = Entry number
-UL = Unsigned Long
-BLKH = BLocK Header
-UNFM = UNForMatted node
-DC = Disk Child
-P = Path
-
-These #defines are named by concatenating these abbreviations, where
-first comes the arguments, and last comes the return value, of the
-macro.
+/* in reading the #defines, it may help to understand that they employ the
+ following abbreviations:
+
+ B = Buffer
+ I = Item header
+ H = Height within the tree (should be changed to LEV)
+ N = Number of the item in the node
+ STAT = stat data
+ DEH = Directory Entry Header
+ EC = Entry Count
+ E = Entry number
+ UL = Unsigned Long
+ BLKH = BLocK Header
+ UNFM = UNForMatted node
+ DC = Disk Child
+ P = Path
+
+ These #defines are named by concatenating these abbreviations, where first
+ comes the arguments, and last comes the return value, of the macro.
*/
-#include <limits.h>
+#ifndef NO_EXTERN_INLINE
+# define extern_inline extern inline
+#else
+# define extern_inline
+#endif
-/* NEW_GET_NEW_BUFFER will try to allocate new blocks better */
-/*#define NEW_GET_NEW_BUFFER*/
-#define OLD_GET_NEW_BUFFER
+#define get_leXX(xx,p,field) (le##xx##_to_cpu ((p)->field))
+#define set_leXX(xx,p,field,val) do { (p)->field = cpu_to_le##xx(val); } while (0)
-/* n must be power of 2 */
-#define _ROUND_UP(x,n) (((x)+(n)-1u) & ~((n)-1u))
+#define get_le16(p,field) get_leXX (16, p, field)
+#define set_le16(p,field,val) set_leXX (16, p, field, val)
-// to be ok for alpha and others we have to align structures to 8 byte
-// boundary.
-// FIXME: do not change 4 by anything else: there is code which relies on that
-#define ROUND_UP(x) _ROUND_UP(x,8LL)
+#define get_le32(p,field) get_leXX (32, p, field)
+#define set_le32(p,field,val) set_leXX (32, p, field, val)
+#define get_le64(p,field) get_leXX (64, p, field)
+#define set_le64(p,field,val) set_leXX (64, p, field, val)
@@ -61,11 +60,6 @@ macro.
#define DEFAULT_HASH R5_HASH
-// can be used only to complete indirect to direct convertion and for
-// nothing else
-#define RESERVED_SPACE 20
-
-
/* super block of prejournalled version */
struct reiserfs_super_block_v0
{
@@ -83,119 +77,200 @@ struct reiserfs_super_block_v0
};
-/* this is the super from 3.5.X, where X >= 10 */
+struct journal_params {
+ __u32 jp_journal_1st_block; /* where does journal start from on its
+ device */
+ __u32 jp_journal_dev; /* journal device st_rdev */
+ __u32 jp_journal_size; /* size of the journal on FS creation. used to
+ make sure they don't overflow it */
+ __u32 jp_journal_trans_max; /* max number of blocks in a transaction. */
+ __u32 jp_journal_magic; /* random value made on fs creation (this was
+ sb_journal_block_count) */
+ __u32 jp_journal_max_batch; /* max number of blocks to batch into a trans */
+ __u32 jp_journal_max_commit_age; /* in seconds, how old can an async commit be */
+ __u32 jp_journal_max_trans_age; /* in seconds, how old can a transaction be */
+};
+
+
+#define get_jp_journal_1st_block(jp) get_le32 (jp, jp_journal_1st_block)
+#define set_jp_journal_1st_block(jp,val) set_le32 (jp, jp_journal_1st_block, val)
+
+#define get_jp_journal_dev(jp) get_le32 (jp, jp_journal_dev)
+#define set_jp_journal_dev(jp,val) set_le32 (jp, jp_journal_dev, val)
+
+#define get_jp_journal_size(jp) get_le32 (jp, jp_journal_size)
+#define set_jp_journal_size(jp,val) set_le32 (jp, jp_journal_size, val)
+
+#define get_jp_journal_max_trans_len(jp) get_le32 (jp, jp_journal_trans_max)
+#define set_jp_journal_max_trans_len(jp,val) set_le32 (jp, jp_journal_trans_max, val)
+
+#define get_jp_journal_magic(jp) get_le32 (jp, jp_journal_magic)
+#define set_jp_journal_magic(jp,val) set_le32 (jp, jp_journal_magic, val)
+
+#define NEED_TUNE 0xffffffff
+
+#define get_jp_journal_max_batch(jp) get_le32 (jp, jp_journal_max_batch)
+#define set_jp_journal_max_batch(jp,val) set_le32 (jp, jp_journal_max_batch, val)
+
+#define get_jp_journal_max_commit_age(jp) get_le32 (jp, jp_journal_max_commit_age)
+#define set_jp_journal_max_commit_age(jp,val) set_le32 (jp, jp_journal_max_commit_age, val)
+
+#define get_jp_journal_max_trans_age(jp) get_le32 (jp, jp_journal_max_commit_age)
+#define set_jp_journal_max_trans_age(jp,val) set_le32 (jp, jp_journal_max_commit_age, val)
+
+
+/* this is the super from 3.5.X */
struct reiserfs_super_block_v1
{
- __u32 s_block_count; /* blocks count */
- __u32 s_free_blocks; /* free blocks count */
- __u32 s_root_block; /* root block number */
- __u32 s_journal_block; /* journal block number */
- __u32 s_journal_dev; /* journal device number */
- __u32 s_orig_journal_size; /* size of the journal on FS creation. used to make sure they don't overflow it */
- __u32 s_journal_trans_max ; /* max number of blocks in a transaction. */
- __u32 s_journal_block_count ; /* total size of the journal. can change over time */
- __u32 s_journal_max_batch ; /* max number of blocks to batch into a trans */
- __u32 s_journal_max_commit_age ; /* in seconds, how old can an async commit be */
- __u32 s_journal_max_trans_age ; /* in seconds, how old can a transaction be */
- __u16 s_blocksize; /* block size */
- __u16 s_oid_maxsize; /* max size of object id array, see get_objectid() commentary */
- __u16 s_oid_cursize; /* current size of object id array */
- __u16 s_state; /* valid or error */
- char s_magic[10]; /* reiserfs magic string indicates that file system is reiserfs */
- __u16 s_fsck_state; /* when fsck managed to build the tree - it puts */
- __u32 s_hash_function_code; /* indicate, what hash fuction is being use to sort names in a directory*/
- __u16 s_tree_height; /* height of disk tree */
- __u16 s_bmap_nr; /* amount of bitmap blocks needed to address each block of file system */
- __u16 s_version;
+ __u32 sb_block_count; /* 0 number of block on data device */
+ __u32 sb_free_blocks; /* 4 free blocks count */
+ __u32 sb_root_block; /* 8 root of the tree */
+
+ struct journal_params sb_journal; /* 12 */
+
+ __u16 sb_blocksize; /* 44 */
+ __u16 sb_oid_maxsize; /* 46 max size of object id array, see
+ get_objectid() commentary */
+ __u16 sb_oid_cursize; /* 48 current size of object id array */
+ __u16 sb_umount_state; /* 50 this is set to 1 when filesystem was
+ umounted, to 2 - when not */
+
+ char s_magic[10]; /* 52 reiserfs magic string indicates that
+ file system is reiserfs: "ReIsErFs" or
+ "ReIsEr2Fs" or "ReIsEr3Fs" */
+ __u16 sb_fs_state; /* 62 it is set to used by fsck to mark which phase of
+ rebuilding is done (used for fsck debugging) */
+ __u32 sb_hash_function_code;/* 64 code of fuction which was/is/will be
+ used to sort names in a directory. See
+ codes in above */
+ __u16 sb_tree_height; /* 68 height of filesytem tree. Tree
+ consisting of only one root block has 2
+ here */
+ __u16 sb_bmap_nr; /* 70 amount of bitmap blocks needed to
+ address each block of file system */
+ __u16 sb_version; /* 72 this field is only reliable on
+ filesystem with non-standard journal */
+ __u16 sb_reserved_for_journal; /* 74 size in blocks of journal area on
+ main device, we need to keep after
+ non-standard journal relocation */
};
#define SB_SIZE_V1 (sizeof(struct reiserfs_super_block_v1)) /* 76 bytes */
+#define sb_jp(sb) (&((sb)->s_v1.sb_journal))
-/* Structure of super block on disk, a version of which in RAM is often
- accessed as s->u.reiserfs_sb.s_rs the version in RAM is part of a larger
- structure containing fields never written to disk. */
-struct reiserfs_super_block
-{
- struct reiserfs_super_block_v1 s_v1;
- char s_unused[128] ; /* zero filled by mkreiserfs */
-};
+/* values for sb_version field of struct reiserfs_super_block. sb_version is
+ only reliable on filesystem with non-standard journal */
+#define REISERFS_FORMAT_3_5 0
+#define REISERFS_FORMAT_3_6 2
+#define REISERFS_FORMAT_UNKNOWN -1
+
-#define SB_SIZE (sizeof(struct reiserfs_super_block)) /* 204 bytes */
+/* values for sb_mount_state field */
+#define REISERFS_CLEANLY_UMOUNTED 1 /* this was REISERFS_VALID_FS */
+#define REISERFS_NOT_CLEANLY_UMOUNTED 2 /* this was REISERFS_ERROR. It
+ means that filesystem was not
+ cleanly unmounted */
+/* Structure of super block on disk */
+struct reiserfs_super_block
+{
+/* 0 */ struct reiserfs_super_block_v1 s_v1;
+/* 76 */ __u32 sb_inode_generation;
+/* 80 */ __u32 s_flags; /* Right now used only by inode-attributes, if enabled */
+/* 84 */ unsigned char s_uuid[16]; /* filesystem unique identifier */
+/*100 */ unsigned char s_label[16]; /* filesystem volume label */
+/*116 */ char s_unused[88] ; /* zero filled by mkreiserfs and reiserfs_convert_objectid_map_v1()
+ * so any additions must be updated there as well. */
+/*204*/
+} __attribute__ ((__packed__));;
-typedef __u32 (*hashf_t) (const char *, int);
+typedef enum {
+ reiserfs_attrs_cleared = 0x00000001,
+} reiserfs_super_block_flags;
+#define SB_SIZE (sizeof(struct reiserfs_super_block)) /* 204 bytes */
+/* set/get fields of super block with these defines */
+#define get_sb_block_count(sb) get_le32 (sb, s_v1.sb_block_count)
+#define set_sb_block_count(sb,val) set_le32 (sb, s_v1.sb_block_count, val)
+#define get_sb_free_blocks(sb) get_le32 (sb, s_v1.sb_free_blocks)
+#define set_sb_free_blocks(sb,val) set_le32 (sb, s_v1.sb_free_blocks, val)
-#define SB_BUFFER_WITH_SB(s) ((s)->s_sbh)
-#define SB_AP_BITMAP(s) ((s)->s_ap_bitmap)
+#define get_sb_root_block(sb) get_le32 (sb,s_v1.sb_root_block)
+#define set_sb_root_block(sb,val) set_le32 (sb, s_v1.sb_root_block, val)
-#define SB_DISK_SUPER_BLOCK(s) (&((s)->s_rs->s_v1))
-#define SB_JOURNAL_BLOCK(s) le32_to_cpu ((SB_DISK_SUPER_BLOCK(s)->s_journal_block))
-#define SB_JOURNAL_SIZE(s) le32_to_cpu ((SB_DISK_SUPER_BLOCK(s)->s_orig_journal_size))
-#define SB_BLOCK_COUNT(s) le32_to_cpu ((SB_DISK_SUPER_BLOCK(s)->s_block_count))
-#define SB_FREE_BLOCKS(s) le32_to_cpu ((SB_DISK_SUPER_BLOCK(s)->s_free_blocks))
-#define SB_REISERFS_MAGIC(s) (SB_DISK_SUPER_BLOCK(s)->s_magic)
-#define SB_ROOT_BLOCK(s) le32_to_cpu ((SB_DISK_SUPER_BLOCK(s)->s_root_block))
-#define SB_TREE_HEIGHT(s) le16_to_cpu ((SB_DISK_SUPER_BLOCK(s)->s_tree_height))
-#define SB_REISERFS_STATE(s) le16_to_cpu ((SB_DISK_SUPER_BLOCK(s)->s_state))
-#define SB_VERSION(s) le16_to_cpu ((SB_DISK_SUPER_BLOCK(s)->s_version))
-#define SB_BMAP_NR(s) le16_to_cpu ((SB_DISK_SUPER_BLOCK(s)->s_bmap_nr))
-#define SB_OBJECTID_MAP_SIZE(s) le16_to_cpu ((SB_DISK_SUPER_BLOCK(s)->s_oid_cursize))
-#define SB_OBJECTID_MAP_MAXSIZE(s) le16_to_cpu ((SB_DISK_SUPER_BLOCK(s)->s_oid_maxsize))
+#if 0
+#define get_sb_mount_id(sb) get_le32 (sb,s_v1.sb_mountid)
+#define set_sb_mount_id(sb,val) set_le32 (sb, s_v1.sb_mountid, val)
-#define rs_blocksize(rs) le16_to_cpu ((rs)->s_v1.s_blocksize)
-#define set_blocksize(rs,n) ((rs)->s_v1.s_blocksize = cpu_to_le16 (n))
+#define get_sb_journal_magic(sb) get_le32 (sb, s_v1.sb_journal_magic)
+#define set_sb_journal_magic(sb,val) set_le32 (sb, s_v1.sb_journal_magic, val)
+#endif
-#define rs_block_count(rs) le32_to_cpu ((rs)->s_v1.s_block_count)
-#define set_block_count(rs,n) ((rs)->s_v1.s_block_count = cpu_to_le32 (n))
+#define get_sb_block_size(sb) get_le16 (sb, s_v1.sb_blocksize)
+#define set_sb_block_size(sb,val) set_le16 (sb, s_v1.sb_blocksize, val)
-#define rs_journal_dev(rs) le32_to_cpu ((rs)->s_v1.s_journal_dev)
-#define set_journal_dev(rs,n) ((rs)->s_v1.s_journal_dev = cpu_to_le32 (n))
+#define get_sb_oid_maxsize(sb) get_le16 (sb, s_v1.sb_oid_maxsize)
+#define set_sb_oid_maxsize(sb,val) set_le16 (sb, s_v1.sb_oid_maxsize, val)
-#define rs_journal_start(rs) le32_to_cpu ((rs)->s_v1.s_journal_block)
-#define set_journal_start(rs,n) ((rs)->s_v1.s_journal_block = cpu_to_le32 (n))
+#define get_sb_oid_cursize(sb) get_le16 (sb, s_v1.sb_oid_cursize)
+#define set_sb_oid_cursize(sb,val) set_le16 (sb, s_v1.sb_oid_cursize, val)
-#define rs_journal_size(rs) le32_to_cpu((rs)->s_v1.s_orig_journal_size)
-#define set_journal_size(rs,n) ((rs)->s_v1.s_orig_journal_size = cpu_to_le32(n))
+#define get_sb_umount_state(sb) get_le16 (sb, s_v1.sb_umount_state)
+#define set_sb_umount_state(sb,val) set_le16 (sb, s_v1.sb_umount_state, val)
-#define rs_root_block(rs) le32_to_cpu ((rs)->s_v1.s_root_block)
-#define set_root_block(rs,n) ((rs)->s_v1.s_root_block = cpu_to_le32 (n))
+#define get_sb_fs_state(sb) get_le16 (sb, s_v1.sb_fs_state)
+#define set_sb_fs_state(sb,flag) set_le16 (sb, s_v1.sb_fs_state, flag)
-#define rs_tree_height(rs) le16_to_cpu ((rs)->s_v1.s_tree_height)
-#define set_tree_height(rs,n) ((rs)->s_v1.s_tree_height = cpu_to_le16 (n))
+#define get_sb_hash_code(sb) get_le32 (sb, s_v1.sb_hash_function_code)
+#define set_sb_hash_code(sb,val) set_le32 (sb, s_v1.sb_hash_function_code, val)
-#define rs_free_blocks(rs) le32_to_cpu ((rs)->s_v1.s_free_blocks)
-#define set_free_blocks(rs,n) ((rs)->s_v1.s_free_blocks = cpu_to_le32 (n))
+#define get_sb_tree_height(sb) get_le16 (sb, s_v1.sb_tree_height)
+#define set_sb_tree_height(sb,val) set_le16 (sb, s_v1.sb_tree_height, val)
-#define rs_bmap_nr(rs) le16_to_cpu ((rs)->s_v1.s_bmap_nr)
-#define set_bmap_nr(rs,n) ((rs)->s_v1.s_bmap_nr = cpu_to_le16 (n))
+#define get_sb_bmap_nr(sb) get_le16 (sb, s_v1.sb_bmap_nr)
+#define set_sb_bmap_nr(sb,val) set_le16 (sb, s_v1.sb_bmap_nr, val)
-#define rs_state(rs) le16_to_cpu ((rs)->s_v1.s_state)
-#define set_state(rs,n) ((rs)->s_v1.s_state = cpu_to_le16 (n))
+#define get_sb_version(sb) get_le16 (sb, s_v1.sb_version)
+#define set_sb_version(sb,val) set_le16 (sb, s_v1.sb_version, val)
-#define rs_objectid_map_size(rs) (le16_to_cpu ((rs)->s_v1.s_oid_cursize))
-#define set_objectid_map_size(rs,n) ((rs)->s_v1.s_oid_cursize = cpu_to_le16 (n))
+#define get_sb_reserved_for_journal(sb) get_le16 (sb, s_v1.sb_reserved_for_journal)
+#define set_sb_reserved_for_journal(sb,val) set_le16 (sb, s_v1.sb_reserved_for_journal, val)
-#define rs_objectid_map_max_size(rs) (le16_to_cpu ((rs)->s_v1.s_oid_maxsize))
-#define set_objectid_map_max_size(rs,n) ((rs)->s_v1.s_oid_maxsize = cpu_to_le16 (n))
+#define get_sb_v2_inode_generation(sb) get_le32 (sb, sb_inode_generation)
+#define set_sb_v2_inode_generation(sb,val) set_le32 (sb, sb_inode_generation, val)
-#define rs_hash(rs) (le32_to_cpu ((rs)->s_v1.s_hash_function_code))
-#define set_hash(rs,n) ((rs)->s_v1.s_hash_function_code = cpu_to_le32 (n))
+//#define get_sb_v2_flag(sb, flag) test_bit ((flag), &((struct reiserfs_super_block *)sb)->s_flags)
+//#define set_sb_v2_flag(sb, flag) set_bit ((flag), &((struct reiserfs_super_block *)sb)->s_flags)
+#define get_sb_v2_flag(sb, flag) (get_le32 (sb, s_flags) & flag)
+#define set_sb_v2_flag(sb, flag) set_le32 (sb, s_flags, get_le32 (sb, s_flags) | flag)
+#define clear_sb_v2_flag(sb, flag) set_le32 (sb, s_flags, get_le32 (sb, s_flags) & ~(flag))
-#define rs_version(rs) (le16_to_cpu ((rs)->s_v1.s_version))
-#define set_version(rs,n) ((rs)->s_v1.s_version = cpu_to_le16 (n))
+/*
+#define journal_is_relocated(sb) get_jp_journal_dev(sb_jp (sb))
+*/
-#define TREE_IS_BUILT 0xfaaf
-#define fsck_state(rs) le16_to_cpu (((rs)->s_v1.s_fsck_state))
-#define set_fsck_state(rs,n) ((rs)->s_v1.s_fsck_state = cpu_to_le16 (n))
+/* these are possible values for sb_fs_state */
+#define REISERFS_CONSISTENT 0 /* this is set by mkreiserfs and by reiserfsck */
+#define REISERFS_CORRUPTED 0x1 /* this will be set by kernel code when it
+ encounters suspicious metadata */
+#define PASS_0_DONE 0xfaa1 /* set by fsck when pass-by-pass (-d),
+ REISERFS_CORRUPTED flag included */
+#define PASS_1_DONE 0xfaa3 /* set by fsck when pass-by-pass (-d),
+ REISERFS_CORRUPTED flag included */
+#define TREE_IS_BUILT 0xfaa5 /* set by fsck when pass-by-pass (-d),
+ REISERFS_CORRUPTED flag included */
+#define SEMANTIC_DONE 0xfaa7 /* set by fsck when pass-by-pass (-d),
+ REISERFS_CORRUPTED flag included */
+#define LOST_FOUND_DONE 0xfaa9 /* set by fsck when pass-by-pass (-d),
+ REISERFS_CORRUPTED flag included */
+//#define FIX_FIXABLE_IS_ALLOWED 0xfaa7
-#define sb_size(fs) (fs->s_version == REISERFS_VERSION_2) ? SB_SIZE : SB_SIZE_V1
/* struct stat_data* access macros */
/* v1 */
@@ -225,8 +300,8 @@ typedef __u32 (*hashf_t) (const char *, int);
/* v2 */
#define sd_v2_mode(sd) (le16_to_cpu((sd)->sd_mode))
#define set_sd_v2_mode(sd,n) ((sd)->sd_mode = cpu_to_le16((n)))
-#define sd_v2_reserved(sd) (le16_to_cpu((sd)->sd_reserved))
-#define set_sd_v2_reserved(sd,n) ((sd)->sd_reserved = cpu_to_le16((n)))
+#define sd_v2_sd_attrs(sd) (le16_to_cpu((sd)->sd_attrs))
+#define set_sd_v2_sd_attrs(sd,n) ((sd)->sd_attrs = cpu_to_le16((n)))
#define sd_v2_nlink(sd) (le32_to_cpu((sd)->sd_nlink))
#define set_sd_v2_nlink(sd,n) ((sd)->sd_nlink = cpu_to_le32((n)))
#define sd_v2_size(sd) (le64_to_cpu((sd)->sd_size))
@@ -254,6 +329,8 @@ typedef __u32 (*hashf_t) (const char *, int);
break. -Hans */
#define REISERFS_DISK_OFFSET_IN_BYTES (64 * 1024)
+/*#define MD_RAID_SUPERBLOCKS_IN_BYTES (128 * 1024)*/
+
/* the spot for the super in versions 3.5 - 3.5.11 (inclusive) */
#define REISERFS_OLD_DISK_OFFSET_IN_BYTES (8 * 1024)
@@ -263,70 +340,131 @@ typedef __u32 (*hashf_t) (const char *, int);
/* f_type of struct statfs will be set at this value by statfs(2) */
#define REISERFS_SUPER_MAGIC 0x52654973
-/* various reiserfs signatures. We have 2 so far. ReIsErFs for the system
- which is not able to deal with long files and ReIsEr2Fs for another. Those
- signature should be looked for at the 64-th and at the 8-th 1k block of the
- device */
-#define REISERFS_SUPER_MAGIC_STRING "ReIsErFs"
-#define REISER2FS_SUPER_MAGIC_STRING "ReIsEr2Fs"
-
-
-
-/* values for s_version field of struct reiserfs_super_block */
-#define REISERFS_VERSION_1 0 /* old (short) super block, all keys in old
- format */
-#define REISERFS_VERSION_2 2 /* new super block, keys may be in new format */
-
-/*
- * values for s_state field
- */
-#define REISERFS_VALID_FS 1
-#define REISERFS_ERROR_FS 2
-
-
+/* various reiserfs signatures. We have 3 so far. ReIsErFs for 3.5 format with
+ standard journal, ReIsEr2Fs for 3.6 (or converted 3.5) and ReIsEr3Fs for
+ filesystem with non-standard journal (formats are distinguished by
+ sb_version in that case). Those signatures should be looked for at the
+ 64-th and at the 8-th 1k block of the device */
+#define REISERFS_3_5_SUPER_MAGIC_STRING "ReIsErFs"
+#define REISERFS_3_6_SUPER_MAGIC_STRING "ReIsEr2Fs"
+#define REISERFS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs" /* JR stands for Journal
+ Relocation */
+
+#define get_reiserfs_ondisk_offset(block_of_super_block, block_size) \
+ (block_of_super_block * block_size)
+
+#define is_new_sb_location(block_of_super_block, block_size) \
+ ((get_reiserfs_ondisk_offset(block_of_super_block, block_size) == REISERFS_DISK_OFFSET_IN_BYTES) \
+ ? 1 : 0)
+
+/*only 4k blocks for old location*/
+#define is_old_sb_location(block_of_super_block, block_size) \
+ ((get_reiserfs_ondisk_offset(block_of_super_block, 4096) == REISERFS_OLD_DISK_OFFSET_IN_BYTES) \
+ ? 1 : 0)
/***************************************************************************/
/* JOURNAL */
/***************************************************************************/
-#define JOURNAL_DESC_MAGIC "ReIsErLB" /* ick. magic string to find desc blocks in the journal */
-#define JOURNAL_TRANS_MAX 1024 /* biggest possible single transaction, don't change for now (8/3/99) */
+#define JOURNAL_DESC_MAGIC "ReIsErLB" /* ick. magic string to find desc
+ blocks in the journal */
/* journal.c see journal.c for all the comments here */
-#define JOURNAL_TRANS_HALF 1018 /* must be correct to keep the desc and commit structs at 4k */
+//#define JOURNAL_TRANS_HALF 1018 /* must be correct to keep the desc and commit structs at 4k */
/* first block written in a commit. BUG, not 64bit safe */
struct reiserfs_journal_desc {
- __u32 j_trans_id ; /* id of commit */
- __u32 j_len ; /* length of commit. len +1 is the commit block */
- __u32 j_mount_id ; /* mount id of this trans*/
- __u32 j_realblock[JOURNAL_TRANS_HALF] ; /* real locations for each block */
- char j_magic[12] ;
-} ;
+ __u32 j2_trans_id ; /* id of commit */
+ __u32 j2_len ; /* length of commit. len +1 is the commit block */
+ __u32 j2_mount_id ; /* mount id of this trans*/
+ __u32 j2_realblock[1] ; /* real locations for each block */
+};
+
+#define get_jd_magic(bh) (bh->b_data + bh->b_size - 12)
+
+
+
+#define journal_trans_half(blocksize) \
+((blocksize - sizeof (struct reiserfs_journal_desc) + sizeof (__u32) - 12) / sizeof (__u32))
+
+#define jdesc_header(bh) ((struct reiserfs_journal_desc *)bh->b_data)
+
+#define get_desc_trans_id(bh) get_le32 (jdesc_header (bh), j2_trans_id)
+#define set_desc_trans_id(bh,val) set_le32 (jdesc_header (bh), j2_trans_id, val)
+
+#define get_desc_trans_len(bh) get_le32 (jdesc_header (bh), j2_len)
+#define set_desc_trans_len(bh,val) set_le32 (jdesc_header (bh), j2_len, val)
+
+#define get_desc_mount_id(bh) get_le32 (jdesc_header (bh), j2_mount_id)
+#define set_desc_mount_id(bh,val) set_le32 (jdesc_header (bh), j2_mount_id, val)
+
/* last block written in a commit BUG, not 64bit safe */
struct reiserfs_journal_commit {
- __u32 j_trans_id ; /* must match j_trans_id from the desc block */
- __u32 j_len ; /* ditto */
- __u32 j_realblock[JOURNAL_TRANS_HALF] ; /* real locations for each block */
- char j_digest[16] ; /* md5 sum of all the blocks involved, including desc and commit. not used, kill it */
+ __u32 j3_trans_id ; /* must match j_trans_id from the desc block */
+ __u32 j3_len ; /* ditto */
+ __u32 j3_realblock[1] ; /* real locations for each block */
} ;
-/* this header block gets written whenever a transaction is considered fully flushed, and is more recent than the
-** last fully flushed transaction. fully flushed means all the log blocks and all the real blocks are on disk,
-** and this transaction does not need to be replayed.
-*/
-struct reiserfs_journal_header {
- __u32 j_last_flush_trans_id ; /* id of last fully flushed transaction */
- __u32 j_first_unflushed_offset ; /* offset in the log of where to start replay after a crash */
- __u32 j_mount_id ;
-} ;
+#define jcommit_header(bh) ((struct reiserfs_journal_commit *)bh->b_data)
+
+#define get_commit_trans_id(bh) get_le32 (jcommit_header(bh), j3_trans_id)
+#define set_commit_trans_id(bh,val) set_le32 (jcommit_header(bh), j3_trans_id, val)
+
+#define get_commit_trans_len(bh) get_le32 (jcommit_header(bh), j3_len)
+#define set_comm_trans_len(bh,val) set_le32 (jcommit_header(bh), j3_len, val)
+
+/* this header block gets written whenever a transaction is considered fully
+** flushed, and is more recent than the last fully flushed transaction. fully
+** flushed means all the log blocks and all the real blocks are on disk, and
+** this transaction does not need to be replayed. */
+struct reiserfs_journal_header {
+ __u32 jh_last_flush_trans_id ; /* id of last fully flushed transaction */
+ __u32 jh_first_unflushed_offset ; /* offset in the log of where to start replay after a crash */
+ __u32 jh_mount_id ;
+
+ struct journal_params jh_journal;
+};
+
+
+/* set/get fields of journal header with these defines */
+#define get_jh_mount_id(jh) get_le32 (jh, jh_mount_id)
+#define set_jh_mount_id(jh,val) set_le32 (jh, jh_mount_id, val)
+
+#define get_jh_last_flushed(jh) get_le32 (jh, jh_last_flush_trans_id)
+#define set_jh_last_flushed(jh,val) set_le32 (jh, jh_last_flush_trans_id, val)
+
+#define get_jh_replay_start_offset(jh) get_le32 (jh, jh_first_unflushed_offset)
+#define set_jh_replay_start_offset(jh,val) set_le32 (jh, jh_first_unflushed_offset, val)
-#define JOURNAL_BLOCK_COUNT 8192 /* number of blocks in the journal */
+/* journal default settings */
+
+#define JOURNAL_MIN_SIZE 512
+#define JOURNAL_TRANS_MAX 1024 /* biggest possible single transaction, don't
+ change for now (8/3/99) */
+#define JOURNAL_TRANS_MIN 256 /* need to check whether it works */
+#define JOURNAL_DEFAULT_RATIO 8 /* default journal size / max trans length */
+#define JOURNAL_MIN_RATIO 2
+#define JOURNAL_MAX_BATCH 900 /* max blocks to batch into one transaction,
+ don't make this any bigger than 900 */
+#define JOURNAL_MAX_COMMIT_AGE 30
+#define JOURNAL_MAX_TRANS_AGE 30
+
+/* journal max size is a maximum number of blocks pointed by first bitmap -
+ REISERFS_DISK_OFFSET - superblock - first bitmap - journal herader */
+#define journal_max_size(block_of_super_block,blocksize) \
+ blocksize * 8 - (block_of_super_block + 1 + 1 + 1)
+
+#define journal_default_size(block_of_super_block,blocksize) \
+ ((8192 > journal_max_size (block_of_super_block,blocksize)) ? \
+ journal_max_size (block_of_super_block,blocksize) : 8192)
+
+//#define JOURNAL_DEFAULT_SIZE 8192 number of blocks in the journal
+//#define JOURNAL_DEFAULT_SIZE_FOR_BS_1024 8125 number of blocks in the journal for block size 1KB
#define bh_desc(bh) ((struct reiserfs_journal_desc *)((bh)->b_data))
#define bh_commit(bh) ((struct reiserfs_journal_commit *)((bh)->b_data))
@@ -342,28 +480,60 @@ struct offset_v1 {
} __attribute__ ((__packed__));
struct offset_v2 {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
__u64 k_offset:60;
__u64 k_type: 4; // TYPE_STAT_DATA | TYPE_INDIRECT | TYPE_DIRECT | TYPE_DIRENTRY
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ __u64 k_type: 4; // TYPE_STAT_DATA | TYPE_INDIRECT | TYPE_DIRECT | TYPE_DIRENTRY
+ __u64 k_offset:60;
+#else
+# error "nuxi/pdp-endian archs are not supported"
+#endif
} __attribute__ ((__packed__));
/* Key of the object drop determines its location in the S+tree, and is
composed of 4 components */
struct key {
- __u32 k_dir_id; /* packing locality: by default parent directory object
+ __u32 k2_dir_id; /* packing locality: by default parent directory object
id */
- __u32 k_objectid; /* object identifier */
+ __u32 k2_objectid; /* object identifier */
union {
- struct offset_v1 k_offset_v1;
- struct offset_v2 k_offset_v2;
- } u;
+ struct offset_v1 k2_offset_v1;
+ struct offset_v2 k2_offset_v2;
+ } __attribute__ ((__packed__)) u;
} __attribute__ ((__packed__));
+
+/* set/get fields of keys on disk with these defines */
+#define get_key_dirid(k) get_le32 (k, k2_dir_id)
+#define set_key_dirid(k,val) set_le32 (k, k2_dir_id, val)
+
+#define get_key_objectid(k) get_le32 (k, k2_objectid)
+#define set_key_objectid(k,val) set_le32 (k, k2_objectid, val)
+
+#define get_key_offset_v1(k) get_le32 (k, u.k2_offset_v1.k_offset)
+#define set_key_offset_v1(k,val) set_le32 (k, u.k2_offset_v1.k_offset, val)
+
+#define get_key_uniqueness(k) get_le32 (k, u.k2_offset_v1.k_uniqueness)
+#define set_key_uniqueness(k,val) set_le32 (k, u.k2_offset_v1.k_uniqueness, val)
+
+
+/*
+#define get_key_offset_v2(k) get_le64 (k, u.k2_offset_v2.k_offset)
+#define set_key_offset_v2(k,val) set_le64 (k, u.k2_offset_v2.k_offset, val)
+*/
+/* ??? */
+/*
+#define get_key_type(k) get_le16 (k, u.k2_offset_v2.k_type)
+#define set_key_type(k,val) set_le16 (k, u.k2_offset_v2.k_type, val)
+*/
+/*
#define key_dir_id(key) (le32_to_cpu((key)->k_dir_id))
#define set_key_dir_id(key,n) ((key)->k_dir_id = cpu_to_le32((n)))
#define key_objectid(key) (le32_to_cpu((key)->k_objectid))
#define set_key_objectid(key,n) ((key)->k_objectid = cpu_to_le32((n)))
-
+*/
#define KEY_SIZE (sizeof(struct key))
#define SHORT_KEY_SIZE 8
@@ -388,16 +558,12 @@ struct key {
#define KEY_FORMAT_1 0
#define KEY_FORMAT_2 1
+#define KEY_FORMAT_UNDEFINED 15
-
-
-
-
-
- /* Our function for comparing keys can compare keys of different
- lengths. It takes as a parameter the length of the keys it is to
- compare. These defines are used in determining what is to be
- passed to it as that parameter. */
+ /* Our function for comparing keys can compare keys of different lengths. It
+ takes as a parameter the length of the keys it is to compare. These
+ defines are used in determining what is to be passed to it as that
+ parameter. */
#define REISERFS_FULL_KEY_LEN 4
#define REISERFS_SHORT_KEY_LEN 2
@@ -409,56 +575,66 @@ struct key {
struct item_head
{
- struct key ih_key; /* Everything in the tree is found by searching for it based on its key.*/
+ struct key ih_key; /* Everything in the tree is found by searching for it
+ based on its key.*/
union {
- __u16 ih_free_space1; /* The free space in the last unformatted node of
- an indirect item if this is an indirect item.
- This equals 0xFFFF iff this is a direct item
- or stat data item. Note that the key, not this
- field, is used to determine the item type, and
- thus which field this union contains. */
- __u16 ih_entry_count; /* Iff this is a directory item, this field
- equals the number of directory entries in the
- directory item. */
- } u;
- __u16 ih_item_len; /* total size of the item body */
- __u16 ih_item_location; /* an offset to the item body within the
+ __u16 ih2_free_space; /* The free space in the last unformatted node
+ of an indirect item if this is an indirect
+ item. This equals 0xFFFF iff this is a direct
+ item or stat data item. Note that the key, not
+ this field, is used to determine the item
+ type, and thus which field this union
+ contains. */
+ __u16 ih2_entry_count; /* Iff this is a directory item, this field
+ equals the number of directory entries in
+ the directory item. */
+ } __attribute__ ((__packed__)) u;
+ __u16 ih2_item_len; /* total size of the item body */
+ __u16 ih2_item_location; /* an offset to the item body within the
block */
+
+ __u16 ih_format; /* key format is stored in bits 0-11 of this item
+ flags are stored in bits 12-15 */
+#if 0
struct {
__u16 key_format : 12; /* KEY_FORMAT_1 or KEY_FORMAT_2. This is not
- necessary, but we have space, let use it */
- __u16 fsck_need : 4; /* fsck set here its flag (reachable/unreachable) */
- } ih_format;
+ necessary, but we have space, let use it */
+ __u16 flags : 4; /* fsck set here its flag (reachable/unreachable) */
+ } __attribute__ ((__packed__)) ih2_format;
+#endif
} __attribute__ ((__packed__));
/* size of item header */
#define IH_SIZE (sizeof(struct item_head))
+/* set/get fields of item head on disk with these defines */
+#define get_ih_entry_count(ih) get_le16 (ih, u.ih2_entry_count)
+#define set_ih_entry_count(ih,val) set_le16 (ih, u.ih2_entry_count, val)
-#define ih_item_len(ih) (le16_to_cpu((ih)->ih_item_len))
-#define set_ih_item_len(ih,x) ((ih)->ih_item_len = cpu_to_le16 (x))
+#define get_ih_free_space(ih) get_le16 (ih, u.ih2_free_space)
+#define set_ih_free_space(ih,val) set_le16 (ih, u.ih2_free_space, 0)
-#define ih_location(ih) (le16_to_cpu ((ih)->ih_item_location))
-#define set_ih_location(ih,x) ((ih)->ih_item_location = cpu_to_le16 (x))
+#define get_ih_item_len(ih) get_le16 (ih, ih2_item_len)
+#define set_ih_item_len(ih,val) set_le16 (ih, ih2_item_len, val)
-#define ih_key_format(ih) (le16_to_cpu ((ih)->ih_format.key_format))
-#define set_key_format(ih,x) ((ih)->ih_format.key_format = cpu_to_le16 (x))
+#define get_ih_location(ih) get_le16 (ih, ih2_item_location)
+#define set_ih_location(ih,val) set_le16 (ih, ih2_item_location, val)
+__u16 get_ih_flags (const struct item_head * ih);
+__u16 get_ih_key_format (const struct item_head * ih);
+void set_ih_flags (struct item_head * ih, __u16 val);
+void set_ih_key_format (struct item_head * ih, __u16 val);
-// FIXME: ih_free_space does not appear to be very important, but we
-// have to make sure that earlier version have no trouble when
-// ih_free_space is 0
-#define ih_free_space(ih) 0 // le16_to_cpu (ih->u.ih_free_space)
-#define set_free_space(ih,val) ((ih)->u.ih_free_space1 = 0)//val)
-//#define get_ih_free_space(ih) 0 //(ih_key_format (ih) == KEY_FORMAT ? 0 : ih_free_space (ih))
-//#define set_ih_free_space(ih,val) // (ih_free_space (ih) = (ih_version (ih) == ITEM_VERSION_2 ? 0 : val))
+/*
+#define get_ih_key_format(ih) get_le16 (ih, ih2_format.key_format)
+#define set_ih_key_format(ih,val) set_le16 (ih, ih2_format.key_format, val)
-#define ih_entry_count(ih) (le16_to_cpu ((ih)->u.ih_entry_count))
-//#define set_ih_free_space(ih,x) ((ih)->u.ih_free_space = cpu_to_le16(x))
-#define set_entry_count(ih,x) ((ih)->u.ih_entry_count = cpu_to_le16(x))
+#define get_ih_flags(ih) get_le16 (ih, ih2_format.flags)
+#define set_ih_flags(ih,val) set_le16 (ih, ih2_format.flags, val)
+*/
#define I_K_KEY_IN_ITEM(p_s_ih, p_s_key, n_blocksize) \
( ! not_of_one_file(p_s_ih, p_s_key) && \
@@ -466,17 +642,41 @@ struct item_head
#define IH_Bad 0
#define IH_Unreachable 1
+#define IH_WAS_TAIL 2
/* Bad item flag is set temporary by recover_leaf */
-#define mark_ih_bad(ih) ((ih)->ih_format.fsck_need |= IH_Bad)
-#define ih_bad(ih) test_bit (IH_Bad, &((ih)->ih_format.fsck_need))
-#define unmark_item_bad(ih) clear_bit (IH_Bad, &((ih)->ih_format.fsck_need))
+/*
+extern_inline __u16 mark_ih_bad( struct item_head *ih )
+{
+ set_ih_flags(ih, get_ih_flags(ih) | IH_Bad );
+ return get_ih_flags(ih);
+}
+
+extern_inline __u16 ih_bad( struct item_head *ih )
+{
+ __u16 tmp = get_ih_flags(ih);
+ return test_bit(IH_Bad, &tmp );
+}
+
+extern_inline __u16 unmark_item_bad( struct item_head *ih )
+{
+ __u16 tmp = get_ih_flags(ih);
+ clear_bit( IH_Bad, &tmp );
+ set_ih_flags( ih, tmp );
+ return tmp;
+}
+*/
/* Unreachable bit is set on tree rebuilding and is cleared in semantic pass */
-#define mark_ih_ok(ih) ((ih)->ih_format.fsck_need = 0)
-#define ih_reachable(ih) (!(ih)->ih_format.fsck_need & IH_Unreachable)
-#define mark_ih_unreachable(ih) ((ih)->ih_format.fsck_need |= IH_Unreachable)
+#define clean_ih_flags(ih) set_ih_flags (ih, 0)
+
+#define ih_reachable(ih) (!(get_ih_flags (ih) & (1 << IH_Unreachable)))
+#define mark_ih_reachable(ih) set_ih_flags (ih, get_ih_flags (ih) & ~(1 << IH_Unreachable))
+#define mark_ih_unreachable(ih) set_ih_flags (ih, get_ih_flags (ih) | (1 << IH_Unreachable))
+#define ih_was_tail(ih) (get_ih_flags (ih) & (1 << IH_WAS_TAIL))
+#define mark_ih_was_tail(ih) set_ih_flags (ih, get_ih_flags (ih) | (1 << IH_WAS_TAIL))
+#define mark_ih_become_tail(ih) set_ih_flags (ih, get_ih_flags (ih) & ~(1 << IH_WAS_TAIL))
/* maximal length of item */
@@ -487,7 +687,6 @@ struct item_head
/* object identifier for root dir */
#define REISERFS_ROOT_OBJECTID 2
#define REISERFS_ROOT_PARENT_OBJECTID 1
-/*extern struct key root_key;*/
/*
@@ -502,48 +701,50 @@ struct item_head
/* Header of a disk block. More precisely, header of a formatted leaf
or internal node, and not the header of an unformatted node. */
struct block_head {
- __u16 blk_level; /* Level of a block in the tree. */
- __u16 blk_nr_item; /* Number of keys/items in a block. */
- __u16 blk_free_space; /* Block free space in bytes. */
- __u16 blk_reserved;
- struct key not_used; /* Right delimiting key for this block
- (supported for leaf level nodes only) */
+ __u16 blk2_level; /* Level of a block in the tree. */
+ __u16 blk2_nr_item; /* Number of keys/items in a block. */
+ __u16 blk2_free_space; /* Block free space in bytes. */
+ __u16 blk_reserved;
+ __u32 reserved [4];
};
#define BLKH_SIZE (sizeof(struct block_head))
+/* set/get fields of block head on disk with these defines */
+#define get_blkh_level(blkh) get_le16 (blkh, blk2_level)
+#define set_blkh_level(blkh,val) set_le16 (blkh, blk2_level, val)
+
+#define get_blkh_nr_items(blkh) get_le16 (blkh, blk2_nr_item)
+#define set_blkh_nr_items(blkh,val) set_le16 (blkh, blk2_nr_item, val)
+
+#define get_blkh_free_space(blkh) get_le16 (blkh, blk2_free_space)
+#define set_blkh_free_space(blkh,val) set_le16 (blkh, blk2_free_space, val)
+
+
+
+
+
/*
* values for blk_type field
*/
#define FREE_LEVEL 0 /* Node of this level is out of the tree. */
-
#define DISK_LEAF_NODE_LEVEL 1 /* Leaf node level. */
-#define is_leaf_block_head(buf) (le16_to_cpu (((struct block_head *)(buf))->blk_level) == DISK_LEAF_NODE_LEVEL)
+#define is_leaf_block_head(buf) (get_blkh_level ((struct block_head *)(buf)) == DISK_LEAF_NODE_LEVEL)
#define is_internal_block_head(buf) \
-((le16_to_cpu (((struct block_head *)(buf))->blk_level) > DISK_LEAF_NODE_LEVEL) &&\
- (le16_to_cpu (((struct block_head *)(buf))->blk_level) <= MAX_HEIGHT))
+((get_blkh_level (((struct block_head *)(buf))) > DISK_LEAF_NODE_LEVEL) &&\
+ (get_blkh_level (((struct block_head *)(buf))) <= MAX_HEIGHT))
/* Given the buffer head of a formatted node, resolve to the block head of that node. */
#define B_BLK_HEAD(p_s_bh) ((struct block_head *)((p_s_bh)->b_data))
-/* Number of items that are in buffer. */
-#define node_item_number(bh) (le16_to_cpu ( B_BLK_HEAD(bh)->blk_nr_item ))
-#define node_pointer_number(bh) (node_item_number(bh) + 1)
-#define node_level(bh) (le16_to_cpu ( B_BLK_HEAD(bh)->blk_level ))
-#define node_free_space(bh) (le16_to_cpu ( B_BLK_HEAD(bh)->blk_free_space ))
-
-#define set_node_item_number(bh,n) (B_BLK_HEAD(bh)->blk_nr_item = cpu_to_le16 (n))
-#define set_node_free_space(bh,n) (B_BLK_HEAD(bh)->blk_free_space = cpu_to_le16 (n))
-#define set_node_level(bh,n) (B_BLK_HEAD(bh)->blk_level = cpu_to_le16 (n))
-#define set_leaf_node_level(bh) set_node_level (bh, DISK_LEAF_NODE_LEVEL)
-#define B_NR_ITEMS(bh) node_item_number(bh)
-#define B_LEVEL(bh) node_level(bh)
-#define B_FREE_SPACE(bh) node_free_space(bh)
+#define B_NR_ITEMS(bh) get_blkh_nr_items (B_BLK_HEAD(bh))
+#define B_LEVEL(bh) get_blkh_level (B_BLK_HEAD(bh))
+#define B_FREE_SPACE(bh) get_blkh_free_space (B_BLK_HEAD(bh))
#define is_leaf_node(bh) is_leaf_block_head ((bh)->b_data)
@@ -583,7 +784,7 @@ struct stat_data_v1 {
union {
__u32 sd_rdev;
__u32 sd_blocks; /* number of blocks file uses */
- } u;
+ } __attribute__ ((__packed__)) u;
__u32 sd_first_direct_byte; /* first byte of file which is stored
in a direct item: except that if it
equals 1 it is a symlink and if it
@@ -610,7 +811,7 @@ struct stat_data_v1 {
address blocks) */
struct stat_data {
__u16 sd_mode; /* file type, permissions */
- __u16 sd_reserved;
+ __u16 sd_attrs;
__u32 sd_nlink; /* 32 bit nlink! */
__u64 sd_size; /* 64 bit size!*/
__u32 sd_uid; /* 32 bit uid! */
@@ -622,13 +823,14 @@ struct stat_data {
__u32 sd_blocks;
union {
__u32 sd_rdev;
+ __u32 sd_generation;
//__u32 sd_first_direct_byte;
/* first byte of file which is stored in a direct item: except that if
it equals 1 it is a symlink and if it equals ~(__u32)0 there is no
direct item. The existence of this field really grates on me. Let's
replace it with a macro based on sd_size and our tail suppression
policy? */
- } u;
+ } __attribute__ ((__packed__)) u;
} __attribute__ ((__packed__));
//
// this is 44 bytes long
@@ -637,7 +839,7 @@ struct stat_data {
// there are two ways: to check length of item or ih_version field
// (for old stat data it is set to 0 (KEY_FORMAT_1))
-#define stat_data_v1(ih) (ih_key_format (ih) == KEY_FORMAT_1)
+#define stat_data_v1(ih) (get_ih_key_format (ih) == KEY_FORMAT_1)
/* this is used to check sd_size of stat data v2: max offset which can
be reached with a key of format 2 is 60 bits */
@@ -664,34 +866,43 @@ struct stat_data {
#define DOT_OFFSET 1
#define DOT_DOT_OFFSET 2
-/* */
-#define FIRST_ITEM_OFFSET 1
-/*
- Q: How to get key of object pointed to by entry from entry?
-
- A: Each directory entry has its header. This header has deh_dir_id
- and deh_objectid fields, those are key of object, entry points to */
+/* Each directory entry has its header. This header has deh_dir_id and
+ deh_objectid fields, those are key of object, entry points to */
/* NOT IMPLEMENTED:
Directory will someday contain stat data of object */
-
-
-
struct reiserfs_de_head
{
- __u32 deh_offset; /* third component of the directory entry key */
- __u32 deh_dir_id; /* objectid of the parent directory of the
- object, that is referenced by directory entry */
- __u32 deh_objectid;/* objectid of the object, that is referenced by
- directory entry */
- __u16 deh_location;/* offset of name in the whole item */
- __u16 deh_state; /* whether 1) entry contains stat data (for
- future), and 2) whether entry is hidden
- (unlinked) */
+ __u32 deh2_offset; /* third component of the directory entry key */
+ __u32 deh2_dir_id; /* objectid of the parent directory of the object,
+ that is referenced by directory entry */
+ __u32 deh2_objectid;/* objectid of the object, that is referenced by
+ directory entry */
+ __u16 deh2_location;/* offset of name in the whole item */
+ __u16 deh2_state; /* whether 1) entry contains stat data (for future),
+ and 2) whether entry is hidden (unlinked) */
} __attribute__ ((__packed__));
+
#define DEH_SIZE sizeof(struct reiserfs_de_head)
+/* set/get fields of dir entry head these defines */
+#define get_deh_offset(deh) get_le32 (deh, deh2_offset)
+#define set_deh_offset(deh,val) set_le32 (deh, deh2_offset, val)
+
+#define get_deh_dirid(deh) get_le32 (deh, deh2_dir_id)
+#define set_deh_dirid(deh,val) set_le32 (deh, deh2_dir_id, val)
+
+#define get_deh_objectid(deh) get_le32 (deh, deh2_objectid)
+#define set_deh_objectid(deh,val) set_le32 (deh, deh2_objectid, val)
+
+#define get_deh_location(deh) get_le16 (deh, deh2_location)
+#define set_deh_location(deh,val) set_le16 (deh, deh2_location, val)
+
+#define get_deh_state(deh) get_le16 (deh, deh2_state)
+#define set_deh_state(deh,val) set_le16 (deh, deh2_state, val)
+
+
#define deh_offset(deh) (le32_to_cpu ((deh)->deh_offset))
#define deh_dir_id(deh) (le32_to_cpu ((deh)->deh_dir_id))
@@ -699,6 +910,7 @@ struct reiserfs_de_head
#define deh_location(deh) (le16_to_cpu ((deh)->deh_location))
#define deh_state(deh) (le16_to_cpu ((deh)->deh_state))
+
/* empty directory contains two entries "." and ".." and their headers */
#define EMPTY_DIR_SIZE \
(DEH_SIZE * 2 + ROUND_UP (strlen (".")) + ROUND_UP (strlen ("..")))
@@ -707,65 +919,59 @@ struct reiserfs_de_head
#define EMPTY_DIR_SIZE_V1 (DEH_SIZE * 2 + 3)
#define DEH_Statdata 0 /* not used now */
-#define DEH_Visible 2
+#define DEH_Visible2 2
#define DEH_Bad_offset 4 /* fsck marks entries to be deleted with this flag */
#define DEH_Bad_location 5
-#define mark_de_with_sd(deh) set_bit (DEH_Statdata, &((deh)->deh_state))
-#define mark_de_without_sd(deh) clear_bit (DEH_Statdata, &((deh)->deh_state))
-#define mark_de_visible(deh) set_bit (DEH_Visible, &((deh)->deh_state))
-#define mark_de_hidden(deh) clear_bit (DEH_Visible, &((deh)->deh_state))
-#define mark_de_lost_found(deh) set_bit (DEH_Lost_Found, &((deh)->deh_state))
-#define unmark_de_lost_found(deh) clear_bit (DEH_Lost_Found, &((deh)->deh_state))
-#define de_with_sd(deh) test_bit (DEH_Statdata, &((deh)->deh_state))
-#define de_visible(deh) test_bit (DEH_Visible, &((deh)->deh_state))
-#define de_hidden(deh) !test_bit (DEH_Visible, &((deh)->deh_state))
+#define test_deh_state_le_bit(deh,bit) (get_deh_state (deh) & (1 << bit))
+
+#define set_deh_state_le_bit(deh,bit) \
+{\
+ __u16 state;\
+ state = get_deh_state (deh);\
+ state |= (1 << bit);\
+ set_deh_state(deh, state);\
+}
+
+#define clear_deh_state_le_bit(deh,bit) \
+{\
+ __u16 state;\
+ state = get_deh_state (deh);\
+ state &= ~(1 << bit);\
+ set_deh_state(deh, state);\
+}
+
+
+#define mark_de_without_sd(deh) clear_deh_state_le_bit (deh, DEH_Statdata)
+#define mark_de_visible(deh) set_deh_state_le_bit (deh, DEH_Visible2)
+#define mark_de_hidden(deh) clear_deh_state_le_bit (deh, DEH_Visible)
+
+#define de_with_sd(deh) test_deh_state_le_bit (deh, DEH_Statdata)
+#define de_visible(deh) test_deh_state_le_bit (deh, DEH_Visible2)
+#define de_hidden(deh) !test_deh_state_le_bit (deh, DEH_Visible2)
/* Bad means "hashed unproperly or/and invalid location" */
-#define de_bad_location(deh) test_bit (DEH_Bad_location, &((deh)->deh_state))
-#define mark_de_bad_location(deh) set_bit (DEH_Bad_location, &((deh)->deh_state))
-#define mark_de_good_location(deh) clear_bit (DEH_Bad_location, &((deh)->deh_state))
+#define de_bad_location(deh) test_deh_state_le_bit (deh, DEH_Bad_location)
+#define mark_de_bad_location(deh) set_deh_state_le_bit (deh, DEH_Bad_location)
+#define mark_de_good_location(deh) clear_deh_state_le_bit (deh, DEH_Bad_location)
-#define de_bad_offset(deh) test_bit (DEH_Bad_offset, &((deh)->deh_state))
-#define mark_de_bad_offset(deh) set_bit (DEH_Bad_offset, &((deh)->deh_state))
+#define de_bad_offset(deh) test_deh_state_le_bit (deh, DEH_Bad_offset)
+#define mark_de_bad_offset(deh) set_deh_state_le_bit (deh, DEH_Bad_offset)
#define de_bad(deh) (de_bad_location(deh) || de_bad_offset(deh))
/* for directories st_blocks is number of 512 byte units which fit into dir
size round up to blocksize */
-#define dir_size2st_blocks(blocksize,size) \
-((((size) + (blocksize) - 1) / (blocksize)) * ((blocksize) / 512))
-
+#define dir_size2st_blocks(size) ((size + 511) / 512)
/* array of the entry headers */
#define B_I_DEH(bh,ih) ((struct reiserfs_de_head *)(B_I_PITEM(bh,ih)))
-#define REISERFS_MAX_NAME_LEN(block_size) (block_size - BLKH_SIZE - IH_SIZE - DEH_SIZE) /* -SD_SIZE when entry will contain stat data */
-
-/* this structure is used for operations on directory entries. It is
- not a disk structure. */
-/* When reiserfs_find_entry or search_by_entry_key find directory
- entry, they return filled reiserfs_dir_entry structure */
-struct reiserfs_dir_entry
-{
- struct buffer_head * de_bh;
- int de_item_num;
- struct item_head * de_ih;
- int de_entry_num;
- struct reiserfs_de_head * de_deh;
- int de_entrylen;
- int de_namelen;
- char * de_name;
- char * de_gen_number_bit_string;
-
- __u32 de_dir_id;
- __u32 de_objectid;
-
- struct key de_entry_key;
-};
+#define REISERFS_MAX_NAME_LEN(block_size) (block_size - BLKH_SIZE - IH_SIZE - DEH_SIZE)
+ /* -SD_SIZE when entry will contain stat data */
/* hash value occupies 24 bits starting from 7 up to 30 */
@@ -789,34 +995,37 @@ struct reiserfs_dir_entry
/* Disk child pointer: The pointer from an internal node of the tree
to a node that is on disk. */
struct disk_child {
- __u32 dc_block_number; /* Disk child's block number. */
- __u16 dc_size; /* Disk child's used space. */
- __u16 dc_reserved;
-};
+ __u32 dc2_block_number; /* Disk child's block number. */
+ __u16 dc2_size; /* Disk child's used space. */
+ __u16 dc2_reserved;
+} __attribute__ ((__packed__));
#define DC_SIZE (sizeof(struct disk_child))
+/* set/get fields of disk_child with these defines */
+#define get_dc_child_blocknr(dc) get_le32 (dc, dc2_block_number)
+#define set_dc_child_blocknr(dc,val) set_le32 (dc, dc2_block_number, val)
+
+#define get_dc_child_size(dc) get_le16 (dc, dc2_size)
+#define set_dc_child_size(dc,val) set_le16 (dc, dc2_size, val)
+
+
/* Get disk child by buffer header and position in the tree node. */
#define B_N_CHILD(p_s_bh,n_pos) ((struct disk_child *)\
((p_s_bh)->b_data + BLKH_SIZE + B_NR_ITEMS(p_s_bh) \
* KEY_SIZE + DC_SIZE * (n_pos)))
-/* Get disk child number by buffer header and position in the tree node. */
-#define B_N_CHILD_NUM(p_s_bh,n_pos) (B_N_CHILD(p_s_bh,n_pos)->dc_block_number)
-#define child_block_number(bh,pos) le32_to_cpu (B_N_CHILD(bh,pos)->dc_block_number)
-#define child_block_size(bh,pos) le16_to_cpu (B_N_CHILD(bh,pos)->dc_size)
-
-#define set_dc_block_number(bh,pos,block) (B_N_CHILD (bh, pos)->dc_block_number = cpu_to_le32 (block))
/* maximal value of field child_size in structure disk_child */
/* child size is the combined size of all items and their headers */
-#define MAX_CHILD_SIZE(bh) ((int)( (bh)->b_size - BLKH_SIZE ))
+#define MAX_CHILD_SIZE(blocksize) ((blocksize) - BLKH_SIZE)
+#define MAX_FREE_SPACE(blocksize) MAX_CHILD_SIZE(blocksize)
/* amount of used space in buffer (not including block head) */
-#define B_CHILD_SIZE(cur) (MAX_CHILD_SIZE(cur)-(B_FREE_SPACE(cur)))
+#define B_CHILD_SIZE(cur) (MAX_CHILD_SIZE(cur->b_size)-(B_FREE_SPACE(cur)))
/* max and min number of keys in internal node */
-#define MAX_NR_KEY(bh) ( (MAX_CHILD_SIZE(bh)-DC_SIZE)/(KEY_SIZE+DC_SIZE) )
+#define MAX_NR_KEY(bh) ( (MAX_CHILD_SIZE(bh->b_size)-DC_SIZE)/(KEY_SIZE+DC_SIZE) )
#define MIN_NR_KEY(bh) (MAX_NR_KEY(bh)/2)
@@ -908,19 +1117,23 @@ struct path var = {ILLEGAL_PATH_ELEMENT_OFFSET, }
/* MISC */
/***************************************************************************/
+/* n must be power of 2 */
+#define _ROUND_UP(x,n) (((x)+(n)-1u) & ~((n)-1u))
+
+// to be ok for alpha and others we have to align structures to 8 byte
+// boundary.
+// FIXME: do not change 4 by anything else: there is code which relies on that
+#define ROUND_UP(x) _ROUND_UP(x,8LL)
+
// search_by_key (and clones) and fix_nodes error code
#define CARRY_ON 0
-#define SCHEDULE_OCCURRED 1
-#define PATH_INCORRECT 2
#define IO_ERROR 3
#define NO_DISK_SPACE 4
#define NO_BALANCING_NEEDED 5
#define ITEM_FOUND 6
#define ITEM_NOT_FOUND 7
-#define POSITION_FOUND 8
-#define POSITION_NOT_FOUND 9
#define GOTO_PREVIOUS_ITEM 10
#define POSITION_FOUND_INVISIBLE 11
#define FILE_NOT_FOUND 12
@@ -931,93 +1144,32 @@ struct path var = {ILLEGAL_PATH_ELEMENT_OFFSET, }
#define DIRECTORY_FOUND 15
-
-typedef unsigned long b_blocknr_t;
-typedef __u32 unp_t;
-
struct unfm_nodeinfo {
- __u32 unfm_nodenum;
- unsigned short unfm_freespace;
+ __u32 unfm_nodenum;
+ __u16 unfm_freespace;
};
-/* when reiserfs_file_write is called with a byte count >= MIN_PACK_ON_CLOSE,
-** it sets the inode to pack on close, and when extending the file, will only
-** use unformatted nodes.
-**
-** This is a big speed up for the journal, which is badly hurt by direct->indirect
-** conversions (they must be logged).
-*/
-#define MIN_PACK_ON_CLOSE 512
-
-
- /* This is an aggressive tail suppression policy, I am hoping it
- improves our benchmarks. The principle behind it is that
- percentage space saving is what matters, not absolute space
- saving. This is non-intuitive, but it helps to understand it if
- you consider that the cost to access 4 blocks is not much more
- than the cost to access 1 block, if you have to do a seek and
- rotate. A tail risks a non-linear disk access that is
- significant as a percentage of total time cost for a 4 block file
- and saves an amount of space that is less significant as a
- percentage of space, or so goes the hypothesis. -Hans */
-#define STORE_TAIL_IN_UNFM(n_file_size,n_tail_size,n_block_size) \
-\
-( ((n_tail_size) > MAX_DIRECT_ITEM_LEN(n_block_size)) || \
- ( (n_file_size) >= (n_block_size) * 4 ) || \
- ( ( (n_file_size) >= (n_block_size) * 3 ) && \
- ( (n_tail_size) >= (MAX_DIRECT_ITEM_LEN(n_block_size))/4) ) || \
- ( ( (n_file_size) >= (n_block_size) * 2 ) && \
- ( (n_tail_size) >= (MAX_DIRECT_ITEM_LEN(n_block_size))/2) ) || \
- ( ( (n_file_size) >= (n_block_size) ) && \
- ( (n_tail_size) >= (MAX_DIRECT_ITEM_LEN(n_block_size) * 3)/4) ) )
-
-
-#define first_direct_byte(inode) ((inode)->u.reiserfs_i.i_first_direct_byte)
-
-#define has_tail(inode) (first_direct_byte(inode) != NO_BYTES_IN_DIRECT_ITEM)
-
-#define tail_offset(inode) (first_direct_byte(inode) - 1)
-
-// mark file as not having tail stored in direct item
-#define file_has_no_tail(inode) (first_direct_byte (inode) = NO_BYTES_IN_DIRECT_ITEM)
-
-#define block_size(inode) ((inode)->i_sb->s_blocksize)
-#define file_size(inode) ((inode)->i_size)
-#define tail_size(inode) (file_size (inode) & (block_size (inode) - 1))
-
-#define tail_has_to_be_packed(inode) (!dont_have_tails ((inode)->i_sb) &&\
-!STORE_TAIL_IN_UNFM(file_size (inode), tail_size(inode), block_size (inode)))
-
/* Size of pointer to the unformatted node. */
#define UNFM_P_SIZE (sizeof(__u32))
-#define INODE_PKEY(inode) ((struct key *)((inode)->u.reiserfs_i.i_key))
-#define inode_key_format(inode) ((inode)->u.reiserfs_i.i_key_format)
-
-//#define MAX_UL_INT ULONG_MAX
-//#define MAX_INT INT_MAX
-//#define MAX_US_INT USHRT_MAX
-#define MAX_KEY1_OFFSET INT_MAX
+#define MAX_KEY1_OFFSET 0xffffffff
#define MAX_KEY2_OFFSET 0xfffffffffffffffLL
-
-
-#define MAX_KEY_UNIQUENESS UINT_MAX
-#define MAX_KEY_OBJECTID UINT_MAX
-
-#define MAX_B_NUM UINT_MAX
-#define MAX_FC_NUM USHRT_MAX
-
-
-/* the purpose is to detect overflow of an unsigned short */
-#define REISERFS_LINK_MAX (USHRT_MAX - 1000)
-
-
-/* The following defines are used in reiserfs_insert_item and reiserfs_append_item */
-#define REISERFS_KERNEL_MEM 0 /* reiserfs kernel memory mode */
-#define REISERFS_USER_MEM 1 /* reiserfs user memory mode */
+/* this is aggressive tail suppression policy taken from the kernel */
+#define STORE_TAIL_IN_UNFM(n_file_size,n_tail_size,n_block_size) \
+(\
+ (!(n_tail_size)) || \
+ (((n_tail_size) > MAX_DIRECT_ITEM_LEN(n_block_size)) || \
+ ( (n_file_size) >= (n_block_size) * 4 ) || \
+ ( ( (n_file_size) >= (n_block_size) * 3 ) && \
+ ( (n_tail_size) >= (MAX_DIRECT_ITEM_LEN(n_block_size))/4) ) || \
+ ( ( (n_file_size) >= (n_block_size) * 2 ) && \
+ ( (n_tail_size) >= (MAX_DIRECT_ITEM_LEN(n_block_size))/2) ) || \
+ ( ( (n_file_size) >= (n_block_size) ) && \
+ ( (n_tail_size) >= (MAX_DIRECT_ITEM_LEN(n_block_size) * 3)/4) ) ) \
+)
/***************************************************************************/
@@ -1049,7 +1201,8 @@ struct virtual_item
{
unsigned short vi_type; /* item type, mergeability */
unsigned short vi_item_len; /* length of item that it will have after balancing */
-
+ __u64 vi_item_offset; /* offset of item that it have before balancing */
+
short vi_entry_count; /* number of entries in directory item
(including the new one if any, or excluding
entry if it must be cut) */
@@ -1058,9 +1211,10 @@ struct virtual_item
struct virtual_node
{
- char * vn_free_ptr; /* this is a pointer to the free space in the buffer */
+ char * vn_free_ptr; /* this is a pointer to the free space in the buffer */
unsigned short vn_nr_item; /* number of items in virtual node */
- short vn_size; /* size of node , that node would have if it has unlimited size and no balancing is performed */
+ short vn_size; /* size of node , that node would have if it has unlimited
+ size and no balancing is performed */
short vn_mode; /* mode of balancing (paste, insert, delete, cut) */
short vn_affected_item_num;
short vn_pos_in_item;
@@ -1092,7 +1246,7 @@ struct virtual_node
struct tree_balance
{
struct reiserfs_transaction_handle *transaction_handle ;
- struct super_block * tb_sb;
+ reiserfs_filsys_t * tb_fs;
struct path * tb_path;
struct buffer_head * L[MAX_HEIGHT]; /* array of left neighbors of nodes in the path */
struct buffer_head * R[MAX_HEIGHT]; /* array of right neighbors of nodes in the path*/
@@ -1237,7 +1391,7 @@ struct buffer_info {
#define not_of_one_file comp_short_keys
/* number of blocks pointed to by the indirect item */
-#define I_UNFM_NUM(p_s_ih) ( (p_s_ih)->ih_item_len / UNFM_P_SIZE )
+#define I_UNFM_NUM(p_s_ih) ( get_ih_item_len(p_s_ih) / UNFM_P_SIZE )
/* the used space within the unformatted node corresponding to pos within the item pointed to by ih */
#define I_POS_UNFM_SIZE(ih,pos,size) (((pos) == I_UNFM_NUM(ih) - 1 ) ? (size) - ih_free_space (ih) : (size))
@@ -1257,20 +1411,20 @@ struct buffer_info {
#define B_N_PKEY(bh,item_num) ( &(B_N_PITEM_HEAD(bh,item_num)->ih_key) )
/* get item body */
-#define B_N_PITEM(bh,item_num) ( (bh)->b_data + B_N_PITEM_HEAD((bh),(item_num))->ih_item_location)
+#define B_N_PITEM(bh,item_num) ( (bh)->b_data + get_ih_location (B_N_PITEM_HEAD((bh),(item_num))))
/* get the stat data by the buffer header and the item order */
#define B_N_STAT_DATA(bh,nr) \
-( (struct stat_data *)((bh)->b_data+B_N_PITEM_HEAD((bh),(nr))->ih_item_location ) )
+( (struct stat_data *)((bh)->b_data+get_ih_location(B_N_PITEM_HEAD((bh),(nr))) ) )
/* following defines use reiserfs buffer header and item header */
/* get item body */
-#define B_I_PITEM(bh,ih) ( (bh)->b_data + ih_location(ih))
+#define B_I_PITEM(bh,ih) ( (bh)->b_data + get_ih_location(ih))
/* get stat-data */
#define B_I_STAT_DATA(bh, ih) ( (struct stat_data * )B_I_PITEM(bh,ih) )
-#define MAX_DIRECT_ITEM_LEN(size) ((size) - BLKH_SIZE - 2*IH_SIZE - SD_SIZE - UNFM_P_SIZE)
+#define MAX_DIRECT_ITEM_LEN(size) ((size) - BLKH_SIZE - 2*IH_SIZE - SD_V1_SIZE - UNFM_P_SIZE)
/* indirect items consist of entries which contain blocknrs, pos
indicates which entry, and B_I_POS_UNFM_POINTER resolves to the
@@ -1285,35 +1439,27 @@ struct buffer_info {
-
-/* objectid.c */
-__u32 reiserfs_get_unused_objectid (struct reiserfs_transaction_handle *th);
-void reiserfs_release_objectid (struct reiserfs_transaction_handle *th, __u32 objectid_to_release);
-int reiserfs_convert_objectid_map_v1(struct super_block *s);
-
-
/* stree.c */
void padd_item (char * item, int total_length, int length);
int B_IS_IN_TREE(struct buffer_head *);
-struct key * get_rkey (struct path * p_s_chk_path, struct super_block * p_s_sb);
+struct key * get_rkey (struct path * p_s_chk_path, reiserfs_filsys_t *);
int bin_search (void * p_v_key, void * p_v_base, int p_n_num, int p_n_width, int * p_n_pos);
-int search_by_key (struct super_block *, struct key *, struct path *, int * , int);
-int search_by_entry_key (struct super_block * sb, struct key * key, struct path * path);
-int search_for_position_by_key (struct super_block * p_s_sb, struct key * p_s_key,
- struct path * p_s_search_path);
-int search_by_objectid (struct super_block *, struct key *, struct path *, int *);
+int search_by_key (reiserfs_filsys_t *, struct key *, struct path *, int);
+int search_by_entry_key (reiserfs_filsys_t *, struct key *, struct path *);
+int search_for_position_by_key (reiserfs_filsys_t *, struct key *, struct path *);
+int search_by_objectid (reiserfs_filsys_t *, struct key *, struct path *, int *);
void decrement_counters_in_path (struct path * p_s_search_path);
void pathrelse (struct path * p_s_search_path);
-int is_left_mergeable (struct super_block * s, struct path * path);
-int is_right_mergeable (struct super_block * s, struct path * path);
+int is_left_mergeable (reiserfs_filsys_t * s, struct path * path);
+int is_right_mergeable (reiserfs_filsys_t * s, struct path * path);
int are_items_mergeable (struct item_head * left, struct item_head * right, int bsize);
/* fix_nodes.c */
-void * reiserfs_kmalloc (size_t size, int flags, struct super_block * s);
-void reiserfs_kfree (/*const*/ void * vp, size_t size, struct super_block * s);
+void * reiserfs_kmalloc (size_t size, int flags, reiserfs_filsys_t * s);
+void reiserfs_kfree (/*const*/ void * vp, size_t size, reiserfs_filsys_t * s);
int fix_nodes (/*struct reiserfs_transaction_handle *th,*/ int n_op_mode, struct tree_balance * p_s_tb,
/*int n_pos_in_item,*/ struct item_head * p_s_ins_ih);
void unfix_nodes (/*struct reiserfs_transaction_handle *th,*/ struct tree_balance *);
@@ -1321,15 +1467,18 @@ void free_buffers_in_tb (struct tree_balance * p_s_tb);
void init_path (struct path *);
/* prints.c */
-#define PRINT_LEAF_ITEMS 1 /* print all items */
-#define PRINT_ITEM_DETAILS 2 /* print contents of directory items and stat
- data items and indirect items */
-#define PRINT_DIRECT_ITEMS 4 /* print contents of direct items */
+/* options */
+#define PRINT_TREE_DETAILS 0x1 /* print all items from internal tree */
+#define PRINT_DETAILS 0x2 /* print all items from bitmap */
+#define PRINT_ITEM_DETAILS 0x4 /* print contents of directory items and stat
+ data items and indirect items */
+#define PRINT_DIRECT_ITEMS 0x8 /* print contents of direct items */
+
void print_tb (int mode, int item_pos, int pos_in_item, struct tree_balance * tb, char * mes);
-void print_bmap (FILE * fp, reiserfs_filsys_t fs, int silent);
-void print_objectid_map (FILE * fp, reiserfs_filsys_t fs);
+void print_bmap (FILE * fp, reiserfs_filsys_t * fs, int silent);
+void print_objectid_map (FILE * fp, reiserfs_filsys_t * fs);
@@ -1338,20 +1487,20 @@ int leaf_move_items (int shift_mode, struct tree_balance * tb,
int mov_num, int mov_bytes, struct buffer_head * Snew);
int leaf_shift_left (struct tree_balance * tb, int shift_num, int shift_bytes);
int leaf_shift_right (struct tree_balance * tb, int shift_num, int shift_bytes);
-void leaf_delete_items (reiserfs_filsys_t, struct buffer_info * cur_bi,
+void leaf_delete_items (reiserfs_filsys_t *, struct buffer_info * cur_bi,
int last_first, int first, int del_num, int del_bytes);
-void leaf_insert_into_buf (reiserfs_filsys_t, struct buffer_info * bi,
+void leaf_insert_into_buf (reiserfs_filsys_t *, struct buffer_info * bi,
int before, struct item_head * inserted_item_ih, const char * inserted_item_body,
int zeros_number);
-void leaf_paste_in_buffer (reiserfs_filsys_t, struct buffer_info * bi, int pasted_item_num,
+void leaf_paste_in_buffer (reiserfs_filsys_t *, struct buffer_info * bi, int pasted_item_num,
int pos_in_item, int paste_size, const char * body, int zeros_number);
-void leaf_cut_from_buffer (reiserfs_filsys_t, struct buffer_info * bi, int cut_item_num,
+void leaf_cut_from_buffer (reiserfs_filsys_t *, struct buffer_info * bi, int cut_item_num,
int pos_in_item, int cut_size);
void leaf_paste_entries (struct buffer_head * bh, int item_num, int before, int new_entry_count,
struct reiserfs_de_head * new_dehs, const char * records,
int paste_size);
-void delete_item (reiserfs_filsys_t fs, struct buffer_head * bh, int item_num);
-void cut_entry (reiserfs_filsys_t fs, struct buffer_head * bh,
+void delete_item (reiserfs_filsys_t *, struct buffer_head * bh, int item_num);
+void cut_entry (reiserfs_filsys_t *, struct buffer_head * bh,
int item_num, int entry_num, int del_count);
@@ -1365,10 +1514,11 @@ void do_balance (struct tree_balance * tb,
void reiserfs_invalidate_buffer (struct tree_balance * tb, struct buffer_head * bh, int);
int get_left_neighbor_position (struct tree_balance * tb, int h);
int get_right_neighbor_position (struct tree_balance * tb, int h);
-void replace_key (reiserfs_filsys_t, struct buffer_head *, int, struct buffer_head *, int);
+void replace_key (reiserfs_filsys_t *, struct buffer_head *, int, struct buffer_head *, int);
void replace_lkey (struct tree_balance *, int, struct item_head *);
void replace_rkey (struct tree_balance *, int, struct item_head *);
void make_empty_node (struct buffer_info *);
+void make_empty_leaf (struct buffer_head *);
struct buffer_head * get_FEB (struct tree_balance *);
@@ -1385,8 +1535,17 @@ __u32 r5_hash (const char *msg, int len);
/* node_format.c */
-int get_journal_old_start_must (struct reiserfs_super_block * rs);
-int get_journal_start_must (int blocksize);
+int get_journal_old_start_must (reiserfs_filsys_t * fs);
+int get_journal_new_start_must (reiserfs_filsys_t * fs);
+int get_journal_start_must (reiserfs_filsys_t * fs);
/*extern hashf_t hashes [];*/
+/*
+ * Local variables:
+ * c-indentation-style: "bsd"
+ * c-basic-offset: 4
+ * tab-width: 8
+ * fill-column: 78
+ * End:
+ */
diff --git a/include/reiserfs_lib.h b/include/reiserfs_lib.h
index b23893e..de13de6 100644
--- a/include/reiserfs_lib.h
+++ b/include/reiserfs_lib.h
@@ -1,11 +1,13 @@
/*
- * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
+ * Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
*/
#ifndef REISERFS_LIB_H
#define REISERFS_LIB_H
-typedef struct super_block * reiserfs_filsys_t;
+
+typedef struct reiserfs_filsys reiserfs_filsys_t;
+
#include "reiserfs_fs.h"
@@ -14,98 +16,187 @@ struct _bitmap {
unsigned long bm_bit_size;
char * bm_map;
unsigned long bm_set_bits;
+ int bm_dirty; /* used for fetched bitmap */
};
-typedef struct _bitmap * reiserfs_bitmap_t;
+typedef struct _bitmap reiserfs_bitmap_t;
+
+typedef __u32 (*hashf_t) (const char *, int);
-struct super_block {
- int s_version; /* on-disk format version */
- reiserfs_bitmap_t bitmap; /* copy of reiserfs on-disk bitmap */
+struct reiserfs_filsys {
+ int fs_blocksize;
+ int fs_format; /* on-disk format version */
+ hashf_t fs_hash_function; /* pointer to function which is used to sort
+ names in directory. It is set by
+ reiserfs_open if it is set in the super
+ block, otherwise it is set by first
+ is_properly_hashed */
- int s_dev; /* descriptor of opened block device file */
- int s_blocksize;
- struct buffer_head ** s_ap_bitmap; /* array of buffers containing bitmap
- blocks */
- struct buffer_head * s_sbh; /* buffer containing super block */
- struct reiserfs_super_block * s_rs; /* pointer to its b_data */
- int s_dirt;
- hashf_t s_hash_function; /* pointer to function which is used to sort
- names in directory. It is set by reiserfs_open
- if it is set in the super block, otherwise it
- is set by first is_properly_hashed */
- char * file_name; /* file name of underlying device */
- int s_flags;
- void * s_vp;
- int (*block_allocator) (reiserfs_filsys_t fs,
+ char * fs_file_name; /* file name of underlying device */
+ int fs_dev; /* descriptor of opened block device file */
+ struct buffer_head * fs_super_bh; /* buffer containing super block */
+ struct reiserfs_super_block * fs_ondisk_sb; /* pointer to its b_data */
+
+
+ reiserfs_bitmap_t * fs_bitmap2; /* ondisk bitmap after
+ reiserfs_open_ondisk_bitmap */
+
+
+ /* opened journal fields */
+ char * fs_j_file_name; /* file name of relocated journal device */
+ int fs_journal_dev; /* descriptor of opened journal device */
+ struct buffer_head * fs_jh_bh; /* buffer containing journal header */
+
+ /* badblocks */
+ reiserfs_bitmap_t * fs_badblocks_bm;
+
+ int fs_dirt;
+ int fs_flags;
+ void * fs_vp;
+ int (*block_allocator) (reiserfs_filsys_t * fs,
unsigned long * free_blocknrs,
unsigned long start, int amount_needed);
- int (*block_deallocator) (reiserfs_filsys_t fs, unsigned long block);
+ int (*block_deallocator) (reiserfs_filsys_t * fs, unsigned long block);
+};
+
+
+struct _transaction {
+ unsigned long mount_id;
+ unsigned long trans_id;
+ unsigned long desc_blocknr;
+ unsigned long trans_len;
+ unsigned long commit_blocknr;
+ unsigned long next_trans_offset;
};
+typedef struct _transaction reiserfs_trans_t;
+
/* reiserfslib.c */
-reiserfs_filsys_t reiserfs_open (char * filename, int flags, int * error, void * vp);
-void reiserfs_read_bitmap_blocks (reiserfs_filsys_t);
-void reiserfs_free_bitmap_blocks (reiserfs_filsys_t);
-int no_reiserfs_found (reiserfs_filsys_t fs);
-void reiserfs_reopen (reiserfs_filsys_t fs, int flags);
-void reiserfs_flush (reiserfs_filsys_t fs);
-void reiserfs_free (reiserfs_filsys_t fs);
-void reiserfs_close (reiserfs_filsys_t fs);
-int reiserfs_new_blocknrs (reiserfs_filsys_t fs,
+void init_tb_struct (struct tree_balance * tb, reiserfs_filsys_t *, struct path * path, int size);
+
+reiserfs_filsys_t * reiserfs_open (char * filename, int flags, int * error, void * vp);
+reiserfs_filsys_t * reiserfs_create (char * filename, int version, unsigned long block_count,
+ int block_size, int default_journal, int new_format);
+void reiserfs_flush (reiserfs_filsys_t *);
+void reiserfs_free (reiserfs_filsys_t *);
+void reiserfs_close (reiserfs_filsys_t *);
+void reiserfs_reopen (reiserfs_filsys_t *, int flags);
+int is_opened_rw (reiserfs_filsys_t * fs);
+
+struct key * get_next_key_2 (struct path * path);
+
+/*
+void reiserfs_read_bitmap_blocks (reiserfs_filsys_t *);
+void reiserfs_free_bitmap_blocks (reiserfs_filsys_t *);
+*/
+int no_reiserfs_found (reiserfs_filsys_t *);
+int is_block_count_correct (unsigned long block_of_super_block, int block_size,
+ unsigned long block_count, unsigned long journal_size);
+//unsigned long min_block_amount (int block_size, unsigned long journal_size);
+unsigned long get_size_of_journal_or_reserved_area (struct reiserfs_super_block * sb);
+
+int reiserfs_new_blocknrs (reiserfs_filsys_t *,
unsigned long * free_blocknrs, unsigned long start,
int amount_needed);
-int reiserfs_free_block (reiserfs_filsys_t fs, unsigned long block);
-int spread_bitmaps (reiserfs_filsys_t fs);
-int filesystem_dirty (reiserfs_filsys_t fs);
-void mark_filesystem_dirty (reiserfs_filsys_t fs);
+int reiserfs_free_block (reiserfs_filsys_t *, unsigned long block);
+int spread_bitmaps (reiserfs_filsys_t *);
+int filesystem_dirty (reiserfs_filsys_t *);
+void mark_filesystem_dirty (reiserfs_filsys_t *);
-void reiserfs_paste_into_item (reiserfs_filsys_t fs, struct path * path,
+void reiserfs_paste_into_item (reiserfs_filsys_t *, struct path * path,
const void * body, int size);
-void reiserfs_insert_item (reiserfs_filsys_t fs, struct path * path,
+void reiserfs_insert_item (reiserfs_filsys_t *, struct path * path,
struct item_head * ih, const void * body);
-int reiserfs_find_entry (reiserfs_filsys_t fs, struct key * dir, char * name,
- int * min_gen_counter);
-int reiserfs_add_entry (reiserfs_filsys_t fs, struct key * dir, char * name,
+int reiserfs_locate_entry (reiserfs_filsys_t *, struct key * dir, char * name,
+ struct path * path);
+int reiserfs_find_entry (reiserfs_filsys_t *, struct key * dir, char * name,
+ int * min_gen_counter, struct key * key);
+int reiserfs_add_entry (reiserfs_filsys_t *, struct key * dir, char * name, int name_len,
struct key * key, int fsck_need);
-int _search_by_entry_key (reiserfs_filsys_t fs, struct key * key,
- struct path * path);
+
+/*int reiserfs_bin_search (void * key, void * base, int num, int width,
+ int *ppos, comparison_fn_t comp_func);*/
+struct key * uget_lkey (struct path * path);
+struct key * uget_rkey (struct path * path);
+int reiserfs_search_by_key_3 (reiserfs_filsys_t *, struct key * key,
+ struct path * path);
+int reiserfs_search_by_key_4 (reiserfs_filsys_t *, struct key * key,
+ struct path * path);
+int reiserfs_search_by_entry_key (reiserfs_filsys_t *, struct key * key,
+ struct path * path);
+int usearch_by_position (reiserfs_filsys_t *, struct key * key, int version, struct path * path);
+struct key * reiserfs_next_key (struct path * path);
void copy_key (void * to, void * from);
void copy_short_key (void * to, void * from);
void copy_item_head(void * p_v_to, void * p_v_from);
-int comp_keys (void * k1, void * k2);
-int comp_short_keys (void * p_s_key1, void * p_s_key2);
+int comp_keys (const void * k1, const void * k2);
+int comp_keys_3 (const void * k1, const void * k2);
+int comp_short_keys (const void * p_s_key1, const void * p_s_key2);
int comp_items (struct item_head * p_s_ih, struct path * p_s_path);
+int create_dir_sd (reiserfs_filsys_t * fs,
+ struct path * path, struct key * key,
+ void (*modify_item)(struct item_head *, void *));
+void make_sure_root_dir_exists (reiserfs_filsys_t * fs,
+ void (*modyfy_item)(struct item_head *, void *),
+ int ih_flags);
+
+int create_badblock_bitmap (reiserfs_filsys_t * fs, char * badblocks_file);
+void add_badblock_list (reiserfs_filsys_t * fs, int no_badblock_in_tree_yet);
+
+
+extern struct key root_dir_key;
+extern struct key parent_root_dir_key;
+extern struct key lost_found_dir_key;
+extern __u16 root_dir_format;
+extern __u16 lost_found_dir_format;
+
/* bitmap.c */
+int reiserfs_open_ondisk_bitmap (reiserfs_filsys_t *);
+int reiserfs_create_ondisk_bitmap (reiserfs_filsys_t *);
+void reiserfs_free_ondisk_bitmap (reiserfs_filsys_t *);
+void reiserfs_close_ondisk_bitmap (reiserfs_filsys_t *);
+int reiserfs_flush_to_ondisk_bitmap (reiserfs_bitmap_t * bm, reiserfs_filsys_t * fs);
+
+reiserfs_bitmap_t * reiserfs_create_bitmap (unsigned int bit_count);
+int reiserfs_expand_bitmap (reiserfs_bitmap_t * bm, unsigned int bit_count);
+void reiserfs_shrink_bitmap (reiserfs_bitmap_t * bm, unsigned int bit_count);
+void reiserfs_delete_bitmap (reiserfs_bitmap_t * bm);
+void reiserfs_bitmap_copy (reiserfs_bitmap_t * to, reiserfs_bitmap_t * from);
+int reiserfs_bitmap_compare (reiserfs_bitmap_t * bm1, reiserfs_bitmap_t * bm2);
+void reiserfs_bitmap_disjunction (reiserfs_bitmap_t * disk, reiserfs_bitmap_t * cont);
+void reiserfs_bitmap_set_bit (reiserfs_bitmap_t * bm, unsigned int bit_number);
+void reiserfs_bitmap_clear_bit (reiserfs_bitmap_t * bm, unsigned int bit_number);
+
+int reiserfs_bitmap_test_bit (reiserfs_bitmap_t * bm, unsigned int bit_number);
+int reiserfs_bitmap_find_zero_bit (reiserfs_bitmap_t * bm, unsigned long * start);
+/*int reiserfs_fetch_ondisk_bitmap (reiserfs_bitmap_t * bm, reiserfs_filsys_t *);*/
+/*int reiserfs_flush_bitmap (reiserfs_bitmap_t * bm, reiserfs_filsys_t *);*/
+void reiserfs_bitmap_zero (reiserfs_bitmap_t * bm);
+void reiserfs_bitmap_fill (reiserfs_bitmap_t * bm);
+int reiserfs_bitmap_ones (reiserfs_bitmap_t * bm);
+int reiserfs_bitmap_zeros (reiserfs_bitmap_t * bm);
-reiserfs_bitmap_t reiserfs_create_bitmap (unsigned int bit_count);
-int reiserfs_expand_bitmap (reiserfs_bitmap_t bm, unsigned int bit_count);
-void reiserfs_delete_bitmap (reiserfs_bitmap_t bm);
-void reiserfs_bitmap_copy (reiserfs_bitmap_t to, reiserfs_bitmap_t from);
-int reiserfs_bitmap_compare (reiserfs_bitmap_t bm1, reiserfs_bitmap_t bm2);
-void reiserfs_bitmap_set_bit (reiserfs_bitmap_t bm, unsigned int bit_number);
-void reiserfs_bitmap_clear_bit (reiserfs_bitmap_t bm, unsigned int bit_number);
+FILE * open_file(char * filename, char * option);
+void close_file(FILE * fp);
+void reiserfs_bitmap_save (FILE * fp, reiserfs_bitmap_t * bm);
-int reiserfs_bitmap_test_bit (reiserfs_bitmap_t bm, unsigned int bit_number);
-int reiserfs_bitmap_find_zero_bit (reiserfs_bitmap_t bm, unsigned long * start);
-int reiserfs_fetch_disk_bitmap (reiserfs_bitmap_t bm, reiserfs_filsys_t fs);
-int reiserfs_flush_bitmap (reiserfs_bitmap_t bm, reiserfs_filsys_t fs);
-void reiserfs_bitmap_zero (reiserfs_bitmap_t bm);
-void reiserfs_bitmap_fill (reiserfs_bitmap_t bm);
-int reiserfs_bitmap_ones (reiserfs_bitmap_t bm);
-int reiserfs_bitmap_zeros (reiserfs_bitmap_t bm);
+/* this probably should be in fsck */
+void reiserfs_begin_stage_info_save(FILE * file, unsigned long stage);
+void reiserfs_end_stage_info_save(FILE * file);
+int is_stage_magic_correct (FILE * fp);
+//void reiserfs_stage_info_save(struct fsck_data *, FILE * file);
-void reiserfs_bitmap_save (char * filename, reiserfs_bitmap_t bm);
-reiserfs_bitmap_t reiserfs_bitmap_load (char * filename);
-void reiserfs_bitmap_invert (reiserfs_bitmap_t bm);
+reiserfs_bitmap_t * reiserfs_bitmap_load (FILE * fp);
+void reiserfs_bitmap_invert (reiserfs_bitmap_t * bm);
-int reiserfs_remove_entry (reiserfs_filsys_t fs, struct key * key);
+int reiserfs_remove_entry (reiserfs_filsys_t *, struct key * key);
@@ -115,21 +206,29 @@ int reiserfs_remove_entry (reiserfs_filsys_t fs, struct key * key);
#define THE_INTERNAL 2
#define THE_SUPER 3
#define THE_JDESC 4
-#define THE_UNKNOWN 5
-
-int is_reiserfs_magic_string (struct reiserfs_super_block * rs);
-int is_reiser2fs_magic_string (struct reiserfs_super_block * rs);
+#define HAS_IH_ARRAY 5
+#define THE_UNKNOWN 6
+
+int correct_direct_item_offset (__u64 offset, int format);
+int is_blocksize_correct (int blocksize);
+int is_reiserfs_3_5_magic_string (struct reiserfs_super_block * rs);
+int is_reiserfs_3_6_magic_string (struct reiserfs_super_block * rs);
+int is_reiserfs_jr_magic_string (struct reiserfs_super_block * rs);
+int does_look_like_super_block (struct reiserfs_super_block * rs, int blocksize);
+int is_any_reiserfs_magic_string (struct reiserfs_super_block * rs);
+int get_reiserfs_format (struct reiserfs_super_block * sb);
+int reiserfs_super_block_size (struct reiserfs_super_block * rs);
+/*int magic_2_version (struct reiserfs_super_block * rs);*/
int is_prejournaled_reiserfs (struct reiserfs_super_block * rs);
-int does_desc_match_commit (struct reiserfs_journal_desc *desc,
- struct reiserfs_journal_commit *commit);
int who_is_this (char * buf, int blocksize);
-int journal_size (struct super_block * s);
-int not_data_block (struct super_block * s, unsigned long block);
-int not_journalable (reiserfs_filsys_t fs, unsigned long block);
-int block_of_bitmap (reiserfs_filsys_t fs, unsigned long block);
-int block_of_journal (reiserfs_filsys_t fs, unsigned long block);
+char * which_block (int code);
+int get_journal_size (reiserfs_filsys_t *);
+int not_data_block (reiserfs_filsys_t *, unsigned long block);
+int not_journalable (reiserfs_filsys_t *, unsigned long block);
+int block_of_bitmap (reiserfs_filsys_t *, unsigned long block);
+int block_of_journal (reiserfs_filsys_t *, unsigned long block);
int is_tree_node (struct buffer_head * bh, int level);
-int is_properly_hashed (reiserfs_filsys_t fs,
+int is_properly_hashed (reiserfs_filsys_t *,
char * name, int namelen, __u32 offset);
int dir_entry_bad_location (struct reiserfs_de_head * deh,
struct item_head * ih, int first);
@@ -140,6 +239,7 @@ void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid,
__u32 par_dirid, __u32 par_objid);
void make_empty_dir_item (char * body, __u32 dirid, __u32 objid,
__u32 par_dirid, __u32 par_objid);
+int reiserfs_is_fs_consistent (reiserfs_filsys_t * fs);
typedef void (*item_action_t) (struct buffer_head * bh, struct item_head * ih);
@@ -159,41 +259,144 @@ void set_offset (int format, struct key * key, loff_t offset);
void set_type_and_offset (int format, struct key * key, loff_t offset, int type);
-typedef int (*check_unfm_func_t) (reiserfs_filsys_t fs, __u32);
-int is_it_bad_item (reiserfs_filsys_t, struct item_head *, char *,
+typedef int (*check_unfm_func_t) (reiserfs_filsys_t *, __u32);
+int is_it_bad_item (reiserfs_filsys_t *, struct item_head *, char *,
check_unfm_func_t, int bad_dir);
+int does_node_have_ih_array (char * buf, int blocksize);
+
-#define hash_func_is_unknown(fs) ((fs)->s_hash_function == 0)
-#define reiserfs_hash(fs) ((fs)->s_hash_function)
+#define hash_func_is_unknown(fs) ((fs)->fs_hash_function == 0)
+#define reiserfs_hash(fs) ((fs)->fs_hash_function)
int known_hashes (void);
char * code2name (int code);
int func2code (hashf_t func);
hashf_t code2func (int code);
+hashf_t name2func (char * hash);
int find_hash_in_use (char * name, int namelen, __u32 hash_value_masked, int code_to_try_first);
int entry_length (struct item_head * ih, struct reiserfs_de_head * deh,
int pos_in_item);
char * name_in_entry (struct reiserfs_de_head * deh, int pos_in_item);
-int name_length (struct item_head * ih,
+int name_in_entry_length (struct item_head * ih,
struct reiserfs_de_head * deh, int pos_in_item);
+int name_length (char * name, int key_format);
+
+/* access to stat data fields */
+void get_set_sd_field (int field, struct item_head * ih, void * sd,
+ void * value, int set);
+#define GET_SD_MODE 0
+#define GET_SD_SIZE 1
+#define GET_SD_NLINK 2
+#define GET_SD_BLOCKS 3
+#define GET_SD_FIRST_DIRECT_BYTE 4
+
+#define get_sd_mode(ih,sd,pmode) get_set_sd_field (GET_SD_MODE, ih, sd, pmode, 0/*get*/)
+#define set_sd_mode(ih,sd,pmode) get_set_sd_field (GET_SD_MODE, ih, sd, pmode, 1/*set*/)
+
+#define get_sd_size(ih,sd,psize) get_set_sd_field (GET_SD_SIZE, ih, sd, psize, 0/*get*/)
+#define set_sd_size(ih,sd,psize) get_set_sd_field (GET_SD_SIZE, ih, sd, psize, 1/*set*/)
+
+#define get_sd_blocks(ih,sd,pblocks) get_set_sd_field (GET_SD_BLOCKS, ih, sd, pblocks, 0/*get*/)
+#define set_sd_blocks(ih,sd,pblocks) get_set_sd_field (GET_SD_BLOCKS, ih, sd, pblocks, 1/*set*/)
+
+//#define get_sd_rdev(ih,sd,pblocks) get_set_sd_field (GET_SD_RDEV, ih, sd, pblocks, 0/*get*/)
+//#define set_sd_rdev(ih,sd,pblocks) get_set_sd_field (GET_SD_RDEV, ih, sd, pblocks, 1/*set*/)
+
+//#define get_sd_generation(ih,sd,pblocks) get_set_sd_field (GET_SD_GENER, ih, sd, pblocks, 0/*get*/)
+//#define set_sd_generation(ih,sd,pblocks) get_set_sd_field (GET_SD_GENER, ih, sd, pblocks, 1/*set*/)
+
+#define get_sd_nlink(ih,sd,pnlink) get_set_sd_field (GET_SD_NLINK, ih, sd, pnlink, 0/*get*/)
+#define set_sd_nlink(ih,sd,pnlink) get_set_sd_field (GET_SD_NLINK, ih, sd, pnlink, 1/*set*/)
+
+#define get_sd_first_direct_byte(ih,sd,pfdb) get_set_sd_field (GET_SD_FIRST_DIRECT_BYTE, ih, sd, pfdb, 0/*get*/)
+#define set_sd_first_direct_byte(ih,sd,pfdb) get_set_sd_field (GET_SD_FIRST_DIRECT_BYTE, ih, sd, pfdb, 1/*set*/)
+
+int is_objectid_used (reiserfs_filsys_t * fs, __u32 objectid);
+void mark_objectid_used (reiserfs_filsys_t * fs, __u32 objectid);
+
+/* journal.c */
+int get_boundary_transactions (reiserfs_filsys_t *, reiserfs_trans_t *,
+ reiserfs_trans_t *);
+int next_transaction (reiserfs_filsys_t *, reiserfs_trans_t *, reiserfs_trans_t);
+
+int replay_one_transaction (reiserfs_filsys_t *, reiserfs_trans_t *);
+
+typedef void (*action_on_trans_t) (reiserfs_filsys_t *, reiserfs_trans_t *);
+void for_each_transaction (reiserfs_filsys_t *, action_on_trans_t);
+
+typedef void (*action_on_block_t) (reiserfs_filsys_t *, reiserfs_trans_t *,
+ int index,
+ unsigned long in_journal,
+ unsigned long in_place);
+void for_each_block (reiserfs_filsys_t * fs, reiserfs_trans_t * trans,
+ action_on_block_t action);
+
+void reiserfs_only_reopen (reiserfs_filsys_t * fs, int flag);
+int reiserfs_open_journal (reiserfs_filsys_t *, char *, int flags);
+int reiserfs_create_journal (reiserfs_filsys_t * fs, char * j_filename,
+ unsigned long offset, unsigned long len,
+ int transaction_max_size);
+int reiserfs_journal_opened (reiserfs_filsys_t *);
+void reiserfs_flush_journal (reiserfs_filsys_t * fs);
+void reiserfs_free_journal (reiserfs_filsys_t * fs);
+void reiserfs_close_journal (reiserfs_filsys_t *);
+void reiserfs_reopen_journal (reiserfs_filsys_t * fs, int flag);
+__u32 advise_journal_max_trans_age (void);
+__u32 advise_journal_max_commit_age (void);
+__u32 advise_journal_max_batch (unsigned long journal_trans_max);
+__u32 advise_journal_max_trans_len (__u32 desired, __u32 journal_size, int blocksize);
+
/* prints.c */
void print_indirect_item (FILE * fp, struct buffer_head * bh, int item_num);
-void print_block (FILE * fp, reiserfs_filsys_t, struct buffer_head * bh, ...);//int print_mode, int first, int last);
+void print_block (FILE * fp, reiserfs_filsys_t *, struct buffer_head * bh, ...);//int print_mode, int first, int last);
+int print_super_block (FILE * fp, reiserfs_filsys_t *, char * file_name, struct buffer_head * bh, int short_print);
+void print_journal (reiserfs_filsys_t *);
+void print_journal_header (reiserfs_filsys_t * fs);
void reiserfs_warning (FILE * fp, const char * fmt, ...);
char ftypelet (mode_t mode);
+void reiserfs_print_item (FILE * fp, struct buffer_head * bh,
+ struct item_head * ih);
+void print_filesystem_state (FILE * fp, reiserfs_filsys_t * fs);
+void print_one_transaction (reiserfs_filsys_t * fs, reiserfs_trans_t * trans);
+void print_journal_params (FILE * fp, struct journal_params * jp);
+char * get_reiserfs_version (__u16 version);
+int can_we_format_it (char * device_name, int force);
#define reiserfs_panic(fmt, list...) \
{\
+ fflush (stdout);\
fprintf (stderr, "%s %d %s\n", __FILE__, __LINE__, __FUNCTION__);\
- reiserfs_warning (stderr, fmt, ## list);\
- exit(4);\
+ reiserfs_warning (stderr, (const char *)fmt, ## list);\
+ reiserfs_warning (stderr, "\n" );\
+ abort ();\
}
+#define reiserfs_exit(val, fmt, list...) \
+{\
+ fflush (stdout);\
+ fprintf (stderr, "%s %d %s\n", __FILE__, __LINE__, __FUNCTION__);\
+ reiserfs_warning (stderr, (const char *)fmt, ## list);\
+ reiserfs_warning (stderr, "\n" );\
+ exit (val);\
+}
+
+#define check_forcing_ask_confirmation(force) \
+ if (force < 1) {\
+ /* avoid formatting it without being forced */\
+ reiserfs_warning (stderr, "Use -f to force over\n");\
+ return 0;\
+ }\
+ if (force < 2) {\
+ if (!user_confirmed (stderr, "Continue (y/n):", "y\n"))\
+ return 0;\
+ }\
+
#endif /* REISERFS_LIB_H */
+
diff --git a/include/stamp-h.in b/include/stamp-h.in
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/include/stamp-h.in
diff --git a/include/swab.h b/include/swab.h
new file mode 100644
index 0000000..40c7c8a
--- /dev/null
+++ b/include/swab.h
@@ -0,0 +1,25 @@
+#ifndef _REISERFS_SWAB_H_
+#define _REISERFS_SWAB_H_
+/* Stolen from linux/include/linux/byteorder/swab.h */
+#define swab16(x) \
+ ((__u16)( \
+ (((__u16)(x) & (__u16)0x00ffU) << 8) | \
+ (((__u16)(x) & (__u16)0xff00U) >> 8) ))
+#define swab32(x) \
+ ((__u32)( \
+ (((__u32)(x) & (__u32)0x000000ffUL) << 24) | \
+ (((__u32)(x) & (__u32)0x0000ff00UL) << 8) | \
+ (((__u32)(x) & (__u32)0x00ff0000UL) >> 8) | \
+ (((__u32)(x) & (__u32)0xff000000UL) >> 24) ))
+#define swab64(x) \
+ ((__u64)( \
+ (__u64)(((__u64)(x) & (__u64)0x00000000000000ffULL) << 56) | \
+ (__u64)(((__u64)(x) & (__u64)0x000000000000ff00ULL) << 40) | \
+ (__u64)(((__u64)(x) & (__u64)0x0000000000ff0000ULL) << 24) | \
+ (__u64)(((__u64)(x) & (__u64)0x00000000ff000000ULL) << 8) | \
+ (__u64)(((__u64)(x) & (__u64)0x000000ff00000000ULL) >> 8) | \
+ (__u64)(((__u64)(x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
+ (__u64)(((__u64)(x) & (__u64)0x00ff000000000000ULL) >> 40) | \
+ (__u64)(((__u64)(x) & (__u64)0xff00000000000000ULL) >> 56) ))
+
+#endif /* _REISERFS_SWAB_H_ */
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 270515e..3858b2d 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -3,21 +3,3 @@ noinst_LIBRARIES = libmisc.a
libmisc_a_SOURCES = io.c misc.c
##reiserfs.c
-INCLUDES = -I$(top_srcdir)/include
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/Makefile.in b/lib/Makefile.in
index 309dda3..3fcac5c 100644
--- a/lib/Makefile.in
+++ b/lib/Makefile.in
@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -62,18 +62,18 @@ MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
+sbindir = @sbindir@
noinst_LIBRARIES = libmisc.a
libmisc_a_SOURCES = io.c misc.c
-
-INCLUDES = -I$(top_srcdir)/include
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../include/config.h
CONFIG_CLEAN_FILES =
LIBRARIES = $(noinst_LIBRARIES)
-DEFS = @DEFS@ -I. -I$(srcdir)
+DEFS = @DEFS@ -I. -I$(srcdir) -I../include
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
@@ -175,15 +175,16 @@ distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
- cp -pr $$/$$file $(distdir)/$$file; \
+ cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
-io.o: io.c ../include/io.h ../include/misc.h
-misc.o: misc.c ../include/io.h
+io.o: io.c ../include/io.h ../include/misc.h ../include/swab.h \
+ ../include/config.h
+misc.o: misc.c ../include/swab.h ../include/io.h ../include/misc.h
info-am:
info: info-am
diff --git a/lib/io.c b/lib/io.c
index fe94334..d24dbe3 100644
--- a/lib/io.c
+++ b/lib/io.c
@@ -7,43 +7,89 @@
#include <unistd.h>
#include <string.h>
#include <errno.h>
+#include <stdlib.h>
#include <asm/types.h>
#include <sys/types.h>
-/*#include <linux/unistd.h>*/
+#include <sys/stat.h>
#include "io.h"
#include "misc.h"
+#include "config.h"
+static int is_bad_block (unsigned long block)
+{
+#ifdef IO_FAILURE_EMULATION
+
+ /* this array similates bad blocks on the device */
+ unsigned long bad_blocks [] =
+ {
+ 8208, 8209, 8210
+/*, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19*/
+ };
+ int i;
+
+ for (i = 0; i < sizeof (bad_blocks) / sizeof (bad_blocks[0]); i ++)
+ if (bad_blocks [i] == block)
+ return 1;
-/* All buffers are in double linked cycled list. Buffers of tree are
- hashed by their block number. If getblk found buffer with wanted
- block number in hash queue it moves buffer to the end of list */
+#endif
+
+ return 0;
+}
+
+
+
+/* All buffers are in double linked cycled list. If getblk found buffer with
+ wanted block number in hash queue it moves buffer to the end of list. */
-#define BLOCK_SIZE 1024
-#define MAX_NR_BUFFERS 16384
static int g_nr_buffers;
+
+static unsigned long buffers_memory;
+
+/* create buffers until we spend this fraction of system memory, this
+** is a hard limit on the amount of buffer ram used
+*/
+#define BUFFER_MEMORY_FRACTION 10
+
+/* number of bytes in local buffer cache before we start forcing syncs
+** of dirty data and reusing unused buffers instead of allocating new
+** ones. If a flush doesn't find reusable buffers, new ones are
+** still allocated up to the BUFFER_MEMORY_FRACTION percentage
+**
+*/
+#define BUFFER_SOFT_LIMIT (500 * 1024)
+static int buffer_soft_limit = BUFFER_SOFT_LIMIT;
+
+
#define NR_HASH_QUEUES 4096
static struct buffer_head * g_a_hash_queues [NR_HASH_QUEUES];
-static struct buffer_head * g_buffer_list_head;
+static struct buffer_head * Buffer_list_head;
+static struct buffer_head * g_free_buffers = NULL ;
static struct buffer_head * g_buffer_heads;
+static int buffer_hits = 0 ;
+static int buffer_misses = 0 ;
+static int buffer_reads = 0 ;
+static int buffer_writes = 0 ;
-static void show_buffers (int dev, int size)
+static void _show_buffers(struct buffer_head **list, int dev, int size)
{
int all = 0;
int dirty = 0;
int in_use = 0; /* count != 0 */
int free = 0;
- struct buffer_head * next = g_buffer_list_head;
+ struct buffer_head * next;
+
+ next = *list;
+ if (!next)
+ return ;
for (;;) {
- if (!next)
- die ("show_buffers: buffer list is corrupted");
if (next->b_dev == dev && next->b_size == size) {
all ++;
if (next->b_count != 0) {
@@ -57,11 +103,19 @@ static void show_buffers (int dev, int size)
}
}
next = next->b_next;
- if (next == g_buffer_list_head)
+ if (next == *list)
break;
}
- printf ("show_buffers (dev %d, size %d): free %d, count != 0 %d, dirty %d, all %d\n", dev, size, free, in_use, dirty, all);
+ printf ("show_buffers (dev %d, size %d): free %d, count != 0 %d, dirty %d, all %d\n",
+ dev, size, free, in_use, dirty, all);
+}
+
+
+static void show_buffers (int dev, int size)
+{
+ _show_buffers(&Buffer_list_head, dev, size) ;
+ _show_buffers(&g_free_buffers, dev, size) ;
}
@@ -101,20 +155,21 @@ static void remove_from_hash_queue (struct buffer_head * bh)
}
-static void put_buffer_list_end (struct buffer_head * bh)
+static void put_buffer_list_end (struct buffer_head **list,
+ struct buffer_head * bh)
{
struct buffer_head * last = 0;
if (bh->b_prev || bh->b_next)
die ("put_buffer_list_end: buffer list corrupted");
- if (g_buffer_list_head == 0) {
+ if (*list == 0) {
bh->b_next = bh;
bh->b_prev = bh;
- g_buffer_list_head = bh;
+ *list = bh;
} else {
- last = g_buffer_list_head->b_prev;
-
+ last = (*list)->b_prev;
+
bh->b_next = last->b_next;
bh->b_prev = last;
last->b_next->b_prev = bh;
@@ -123,41 +178,77 @@ static void put_buffer_list_end (struct buffer_head * bh)
}
-static void remove_from_buffer_list (struct buffer_head * bh)
+static void remove_from_buffer_list (struct buffer_head **list,
+ struct buffer_head * bh)
{
if (bh == bh->b_next) {
- g_buffer_list_head = 0;
+ *list = 0;
} else {
bh->b_prev->b_next = bh->b_next;
bh->b_next->b_prev = bh->b_prev;
- if (bh == g_buffer_list_head)
- g_buffer_list_head = bh->b_next;
+ if (bh == *list)
+ *list = bh->b_next;
}
bh->b_next = bh->b_prev = 0;
}
-static void put_buffer_list_head (struct buffer_head * bh)
+static void put_buffer_list_head (struct buffer_head **list,
+ struct buffer_head * bh)
{
- put_buffer_list_end (bh);
- g_buffer_list_head = bh;
+ put_buffer_list_end (list, bh);
+ *list = bh;
}
+/*
+#include <sys/mman.h>
+
+static size_t estimate_memory_amount (void)
+{
+ size_t len = 1;
+ size_t max = 0;
+ void * addr;
+
+ while (len > 0) {
+ addr = mmap (0, len, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (addr == MAP_FAILED) {
+ if (errno != ENOMEM)
+ die ("mmap failed: %m\n");
+ break;
+ }
+ if (mlock (addr, len) != 0) {
+ if (errno == EPERM)
+ die ("No permission to run mlock");
+ break;
+ }
+
+ munlock (addr, len);
+ munmap (addr, len);
+ max = len;
+ len *= 2;
+ }
+
+ // * If we've looped, we don't want to return 0, we want to return the
+ // * last successful len before we looped. In the event that mmap/mlock
+ // * failed for len = 1, max will still be 0, so we don't get an invalid
+ // * result
+ return max;
+}
+*/
#define GROW_BUFFERS__NEW_BUFERS_PER_CALL 10
-/* creates number of new buffers and insert them into head of buffer list
- */
+
+/* creates number of new buffers and insert them into head of buffer list */
static int grow_buffers (int size)
{
int i;
struct buffer_head * bh, * tmp;
- if (g_nr_buffers + GROW_BUFFERS__NEW_BUFERS_PER_CALL > MAX_NR_BUFFERS)
- return 0;
/* get memory for array of buffer heads */
- bh = (struct buffer_head *)getmem (GROW_BUFFERS__NEW_BUFERS_PER_CALL * sizeof (struct buffer_head) + sizeof (struct buffer_head *));
+ bh = (struct buffer_head *)getmem (GROW_BUFFERS__NEW_BUFERS_PER_CALL *
+ sizeof (struct buffer_head) + sizeof (struct buffer_head *));
if (g_buffer_heads == 0)
g_buffer_heads = bh;
else {
@@ -177,15 +268,15 @@ static int grow_buffers (int size)
die ("grow_buffers: no memory for new buffer data");
tmp->b_dev = 0;
tmp->b_size = size;
- put_buffer_list_head (tmp);
-
- g_nr_buffers ++;
+ put_buffer_list_head (&g_free_buffers, tmp);
}
+ buffers_memory += GROW_BUFFERS__NEW_BUFERS_PER_CALL * size;
+ g_nr_buffers += GROW_BUFFERS__NEW_BUFERS_PER_CALL;
return GROW_BUFFERS__NEW_BUFERS_PER_CALL;
}
-struct buffer_head * find_buffer (int dev, int block, int size)
+struct buffer_head * find_buffer (int dev, unsigned long block, int size)
{
struct buffer_head * next;
@@ -203,98 +294,117 @@ struct buffer_head * find_buffer (int dev, int block, int size)
return next;
}
-void __wait_on_buffer (struct buffer_head * bh)
-{
-}
-
-struct buffer_head * get_hash_table(dev_t dev, int block, int size)
-{
- struct buffer_head * bh;
-
- bh = find_buffer (dev, block, size);
- if (bh) {
- bh->b_count ++;
- }
- return bh;
-}
-
-static struct buffer_head * get_free_buffer (int size)
+static struct buffer_head * get_free_buffer (struct buffer_head **list,
+ int size)
{
- struct buffer_head * next = g_buffer_list_head;
+ struct buffer_head * next;
+ next = *list;
if (!next)
return 0;
+
for (;;) {
if (!next)
die ("get_free_buffer: buffer list is corrupted");
if (next->b_count == 0 && buffer_clean (next) && next->b_size == size) {
remove_from_hash_queue (next);
- remove_from_buffer_list (next);
- put_buffer_list_end (next);
+ remove_from_buffer_list (list, next);
return next;
}
next = next->b_next;
- if (next == g_buffer_list_head)
+ if (next == *list)
break;
}
return 0;
}
-static void sync_buffers (int size, int to_write)
+/* to_write == 0 when all blocks have to be flushed. Otherwise - write only
+ buffers with b_count == 0 */
+static int sync_buffers (struct buffer_head **list, dev_t dev, int to_write)
{
- struct buffer_head * next = g_buffer_list_head;
+ struct buffer_head * next;
int written = 0;
+
+restart:
+ next = *list;
+ if (!next)
+ return 0;
for (;;) {
if (!next)
- die ("flush_buffer: buffer list is corrupted");
+ die ("sync_buffers: buffer list is corrupted");
+
+ if (next->b_dev == dev && buffer_dirty (next) && buffer_uptodate (next)) {
+ if ((to_write == 0 || next->b_count == 0) && !buffer_do_not_flush (next)) {
+ bwrite (next);
+ }
+ }
- if ((!size || next->b_size == size) && buffer_dirty (next) && buffer_uptodate (next)) {
- written ++;
- bwrite (next);
+ /* if this buffer is reusable, put it onto the end of the free list */
+ if (next->b_count == 0 && buffer_clean(next)) {
+ remove_from_hash_queue (next);
+ remove_from_buffer_list (list, next);
+ put_buffer_list_end (&g_free_buffers, next);
+ written++ ;
if (written == to_write)
- return;
+ return written;
+ goto restart;
}
-
+ if (to_write && written >= to_write)
+ return written;
+
next = next->b_next;
- if (next == g_buffer_list_head)
+ if (next == *list)
break;
}
+
+ return written;
}
-void flush_buffers (void)
+
+void flush_buffers (dev_t dev)
{
- sync_buffers (0, 0);
+ if (!dev)
+ die ("flush_buffers: device is not specifed");
+ sync_buffers (&Buffer_list_head, dev, 0/*all*/);
+ buffer_soft_limit = BUFFER_SOFT_LIMIT;
}
-struct buffer_head * getblk (int dev, int block, int size)
+struct buffer_head * getblk (int dev, unsigned long block, int size)
{
struct buffer_head * bh;
bh = find_buffer (dev, block, size);
if (bh) {
- if (0 && !buffer_uptodate (bh))
- die ("getblk: buffer must be uptodate");
- // move the buffer to the end of list
+ /* move the buffer to the end of list */
/*checkmem (bh->b_data, bh->b_size);*/
- remove_from_buffer_list (bh);
- put_buffer_list_end (bh);
+ remove_from_buffer_list (&Buffer_list_head, bh);
+ put_buffer_list_end (&Buffer_list_head, bh);
bh->b_count ++;
+ buffer_hits++ ;
return bh;
}
-
- bh = get_free_buffer (size);
- if (bh == 0) {
- if (grow_buffers (size) == 0) {
- sync_buffers (size, 10);
+ buffer_misses++ ;
+
+ bh = get_free_buffer (&g_free_buffers, size);
+ if (bh == NULL) {
+ if (buffers_memory >= buffer_soft_limit) {
+ if (sync_buffers (&Buffer_list_head, dev, 32) == 0) {
+ grow_buffers(size);
+ buffer_soft_limit = buffers_memory + GROW_BUFFERS__NEW_BUFERS_PER_CALL * size;
+ }
+ } else {
+ if (grow_buffers(size) == 0)
+ sync_buffers (&Buffer_list_head, dev, 32);
}
- bh = get_free_buffer (size);
- if (bh == 0) {
+
+ bh = get_free_buffer (&g_free_buffers, size);
+ if (bh == NULL) {
show_buffers (dev, size);
die ("getblk: no free buffers after grow_buffers and refill (%d)", g_nr_buffers);
}
@@ -309,17 +419,13 @@ struct buffer_head * getblk (int dev, int block, int size)
clear_bit(BH_Dirty, &bh->b_state);
clear_bit(BH_Uptodate, &bh->b_state);
+ put_buffer_list_end (&Buffer_list_head, bh);
insert_into_hash_queue (bh);
/*checkmem (bh->b_data, bh->b_size);*/
return bh;
}
-struct buffer_head * reiserfs_getblk (int dev, int block, int size, int *repeat)
-{
- return getblk (dev, block, size);
-}
-
void brelse (struct buffer_head * bh)
{
@@ -328,7 +434,9 @@ void brelse (struct buffer_head * bh)
if (bh->b_count == 0) {
die ("brelse: can not free a free buffer %lu", bh->b_blocknr);
}
- /*checkmem (bh->b_data, bh->b_size);*/
+
+ /*checkmem (bh->b_data, get_mem_size (bh->b_data));*/
+
bh->b_count --;
}
@@ -336,72 +444,56 @@ void brelse (struct buffer_head * bh)
void bforget (struct buffer_head * bh)
{
if (bh) {
+ bh->b_state = 0;
brelse (bh);
remove_from_hash_queue (bh);
- remove_from_buffer_list (bh);
- put_buffer_list_head (bh);
+ remove_from_buffer_list(&Buffer_list_head, bh);
+ if (bh->b_count == 0)
+ put_buffer_list_head(&g_free_buffers, bh);
+ else
+ put_buffer_list_head(&Buffer_list_head, bh);
}
}
-#if 0
-#if ! ( defined __USE_LARGEFILE64 || defined __USE_FILE_OFFSET64 )
-_syscall5 (int, _llseek, uint, fd, ulong, hi, ulong, lo,
- loff_t *, res, uint, wh);
-#endif
-
-loff_t reiserfs_llseek (unsigned int fd, loff_t offset, unsigned int origin)
-{
-#if defined __USE_FILE_OFFSET64
- return lseek(fd, offset, origin);
-#elif defined __USE_LARGEFILE64
- return lseek64(fd, offset, origin);
-#else
- loff_t retval, result;
- retval = _llseek (fd, ((unsigned long long) offset) >> 32,
- ((unsigned long long) offset) & 0xffffffff,
- &result, origin);
- return (retval != 0 ? (loff_t)-1 : result);
-#endif
-}
-#endif
static int f_read(struct buffer_head * bh)
{
loff_t offset;
ssize_t bytes;
+ buffer_reads++ ;
+
offset = (loff_t)bh->b_size * (loff_t)bh->b_blocknr;
- /*if (reiserfs_llseek (bh->b_dev, offset, SEEK_SET) == (loff_t)-1)*/
if (lseek64 (bh->b_dev, offset, SEEK_SET) == (loff_t)-1)
- return 0;
+ return 0;
bytes = read (bh->b_dev, bh->b_data, bh->b_size);
if (bytes != (ssize_t)bh->b_size)
- return 0;
+ return 0;
return 1;
}
+
struct buffer_head * bread (int dev, unsigned long block, size_t size)
{
struct buffer_head * bh;
- /*
- if ((size == 32768 && (block == 16 || 1026)) ||
- (size == 4096 && (block == 128 || block == 8211))) {
- size = 10;
+ if (is_bad_block (block))
return 0;
- }
- */
bh = getblk (dev, block, size);
+
+ /*checkmem (bh->b_data, get_mem_size(bh->b_data));*/
+
if (buffer_uptodate (bh))
return bh;
- if (f_read(bh) == 0)
- {
- brelse(bh);
- return 0;
+ if (f_read(bh) == 0 || is_bad_block (block)) {
+/* BAD BLOCK LIST SUPPORT
+ die ("%s: Cannot read a block # %lu. Specify list of badblocks\n",*/
+ die ("%s: Cannot read a block # %lu.\n",
+ __FUNCTION__, bh->b_blocknr);
}
mark_buffer_uptodate (bh, 0);
@@ -415,81 +507,394 @@ int valid_offset( int fd, loff_t offset)
loff_t res;
/*res = reiserfs_llseek (fd, offset, 0);*/
- res = lseek64 (fd, offset, 0);
+ res = lseek64 (fd, offset, SEEK_SET);
if (res < 0)
return 0;
+ /* if (read (fd, &ch, 1) < 0) does not wirk on files */
if (read (fd, &ch, 1) < 1)
return 0;
+
return 1;
}
-struct buffer_head * reiserfs_bread (int dev, int block, int size, int *repeat)
-{
- return bread (dev, block, size);
+#define ROLLBACK_FILE_START_MAGIC "_RollBackFileForReiserfsFSCK"
+
+static struct block_handler * rollback_blocks_array;
+static __u32 rollback_blocks_number = 0;
+static FILE * s_rollback_file = 0;
+static FILE * log_file;
+static int do_rollback = 0;
+
+static char * rollback_data;
+static int rollback_blocksize;
+
+void init_rollback_file (char * rollback_file, int *blocksize, FILE * log) {
+ char * string;
+ struct stat64 buf;
+
+ if (rollback_file == NULL)
+ return;
+
+ stat64(rollback_file, &buf);
+
+ s_rollback_file = fopen (rollback_file, "w+");
+ if (s_rollback_file == NULL) {
+ fprintf (stderr, "Cannot create file %s, work w/out a rollback file\n", rollback_file);
+ return;
+ }
+
+ rollback_blocksize = *blocksize;
+
+ string = ROLLBACK_FILE_START_MAGIC;
+ fwrite (string, 28, 1, s_rollback_file);
+ fwrite (&rollback_blocksize, sizeof (rollback_blocksize), 1, s_rollback_file);
+ fwrite (&rollback_blocks_number, sizeof (rollback_blocks_number), 1, s_rollback_file);
+ fflush(s_rollback_file);
+
+ rollback_data = getmem(rollback_blocksize);
+
+// printf("\ncheckmem1");
+// fflush (stdout);
+// checkmem (rollback_data, get_mem_size((char *)rollback_data));
+// printf(" OK");
+
+ log_file = log;
+ if (log_file)
+ fprintf (log_file, "rollback: file (%s) initialize\n", rollback_file);
+
+ do_rollback = 0;
+}
+
+#if 0
+static void erase_rollback_file (char * rollback_file) {
+ close_rollback_file ();
+ unlink (rollback_file);
+}
+#endif
+
+int open_rollback_file (char * rollback_file, FILE * log) {
+ char string [28];
+ struct stat64 buf;
+
+ if (rollback_file == NULL)
+ return -1;
+
+ if (stat64(rollback_file, &buf)) {
+ fprintf (stderr, "Cannot stat rollback file (%s)\n", rollback_file);
+ return -1;
+ }
+
+ s_rollback_file = fopen (rollback_file, "r+");
+ if (s_rollback_file == NULL) {
+ fprintf (stderr, "Cannot open file (%s)\n", rollback_file);
+ return -1;
+ }
+
+ fread (string, 28, 1, s_rollback_file);
+ if (!strcmp (string, ROLLBACK_FILE_START_MAGIC)) {
+ fprintf (stderr, "Specified file (%s) does not look like a rollback file\n", rollback_file);
+ fclose (s_rollback_file);
+ s_rollback_file = 0;
+ return -1;
+ }
+
+ fread (&rollback_blocksize, sizeof (rollback_blocksize), 1, s_rollback_file);
+
+ if (rollback_blocksize <= 0) {
+ fprintf(stderr, "rollback: wrong rollback blocksize, exit\n");
+ return -1;
+ }
+
+ log_file = log;
+ if (log_file)
+ fprintf (log_file, "rollback: file (%s) opened\n", rollback_file);
+
+ do_rollback = 1;
+ return 0;
+}
+
+void close_rollback_file () {
+ if (s_rollback_file == 0)
+ return;
+
+ if (!do_rollback) {
+ if (fseek (s_rollback_file, 28 + sizeof(int), SEEK_SET) == (loff_t)-1)
+ return;
+ fwrite (&rollback_blocks_number, sizeof (rollback_blocksize), 1, s_rollback_file);
+ if (log_file != 0)
+ fprintf (log_file, "rollback: %d blocks backed up\n", rollback_blocks_number);
+ }
+
+ fclose (s_rollback_file);
+
+ freemem (rollback_data);
+ freemem (rollback_blocks_array);
+
+// fprintf (stdout, "rollback: (%u) blocks saved, \n", rollback_blocks_number);
+
+/* for (i = 0; i < rollback_blocks_number; i++)
+ fprintf(stdout, "device (%Lu), block number (%u)\n",
+ rollback_blocks_array [i].device,
+ rollback_blocks_array [i].blocknr);
+ fprintf(stdout, "\n");
+ */
}
+void do_fsck_rollback (int fd_device, int fd_journal_device, FILE * progress) {
+ loff_t offset;
+
+ struct stat64 buf;
+ int descriptor;
+ ssize_t retval;
+ int count_failed = 0;
+ int count_rollbacked = 0;
+
+ dev_t b_dev;
+ dev_t n_dev = 0;
+ dev_t n_journal_dev = 0;
+ unsigned long total, done = 0;
+
+ if (fd_device == 0) {
+ fprintf(stderr, "rollback: unspecified device, exit\n");
+ return;
+ }
+
+ if (fd_journal_device) {
+ if (!fstat64 (fd_journal_device, &buf)) {
+ n_journal_dev = buf.st_rdev;
+ } else {
+ fprintf(stderr, "rollback: specified journal device cannot be stated\n");
+ }
+ }
+
+ if (!fstat64 (fd_device, &buf)) {
+ n_dev = buf.st_rdev;
+ } else {
+ fprintf(stderr, "rollback: specified device cannot be stated, exit\n");
+ return;
+ }
+
+ rollback_data = getmem (rollback_blocksize);
+// printf("\ncheckmem2");
+// fflush (stdout);
+// checkmem (rollback_data, get_mem_size((char *)rollback_data));
+// printf(" OK");
+
+ fread (&rollback_blocks_number, sizeof (rollback_blocks_number), 1, s_rollback_file);
+
+ total = rollback_blocks_number;
+
+ while (1) {
+ print_how_far (progress, &done, rollback_blocks_number, 1, 0/*not quiet*/);
+
+ descriptor = 0;
+ if ((retval = fread (&b_dev, sizeof (b_dev), 1, s_rollback_file)) <= 0) {
+ if (retval)
+ fprintf (stderr, "rollback: fread: %s\n", strerror (errno));
+ break;
+ }
+ if ((retval = fread (&offset, sizeof (offset), 1, s_rollback_file)) <= 0) {
+ if (retval)
+ fprintf (stderr, "rollback: fread: %s\n", strerror (errno));
+ break;
+ }
+
+ if ((retval = fread (rollback_data, rollback_blocksize, 1, s_rollback_file)) <= 0) {
+ if (retval)
+ fprintf (stderr, "rollback: fread: %s\n", strerror (errno));
+ break;
+ }
+
+ if (n_dev == b_dev)
+ descriptor = fd_device;
+ if ((n_journal_dev) && (n_journal_dev == b_dev))
+ descriptor = fd_journal_device;
+
+ if (descriptor == 0) {
+ fprintf(stderr, "rollback: block from unknown device, skip block\n");
+ count_failed ++;
+ continue;
+ }
+
+ if (lseek64 (descriptor, offset, SEEK_SET) == (loff_t)-1) {
+ fprintf(stderr, "device cannot be lseeked, skip block\n");
+ count_failed ++;
+ continue;
+ }
+
+ if (write (descriptor, rollback_data, rollback_blocksize) == -1) {
+ fprintf (stderr, "rollback: write %d bytes returned error (block=%Ld, dev=%Ld): %s\n",
+ rollback_blocksize, (long long)offset/rollback_blocksize, (long long)b_dev, strerror (errno));
+ count_failed ++;
+ } else {
+ count_rollbacked ++;
+ /*if you want to know what gets rollbacked, uncomment it*/
+/* if (log_file != 0 && log_file != stdout)
+ fprintf (log_file, "rollback: block %Lu of device %Lu was restored\n",
+ (loff_t)offset/rollback_blocksize, b_dev);
+*/
+// fprintf (stdout, "rollback: block (%Ld) written\n", (loff_t)offset/rollback_blocksize);
+ }
+ }
+
+ printf ("\n");
+ if (log_file != 0)
+ fprintf (log_file, "rollback: (%u) blocks restored\n", count_rollbacked);
+}
+
+/*
+static void rollback__mark_block_saved (struct block_handler * rb_e) {
+ if (rollback_blocks_array == NULL)
+ rollback_blocks_array = getmem (ROLLBACK__INCREASE_BLOCK_NUMBER * sizeof (*rb_e));
+
+ if (rollback_blocks_number == get_mem_size ((void *)rollback_blocks_array) / sizeof (*rb_e))
+ rollback_blocks_array = expandmem (rollback_blocks_array, get_mem_size((void *)rollback_blocks_array),
+ ROLLBACK__INCREASE_BLOCK_NUMBER * sizeof (*rb_e));
+// checkmem ((char *)rollback_blocks_array, get_mem_size((char *)rollback_blocks_array));
+
+ rollback_blocks_array[rollback_blocks_number] = *rb_e;
+ rollback_blocks_number ++;
+ qsort (rollback_blocks_array, rollback_blocks_number, sizeof (*rb_e), rollback_compare);
+
+// printf("\ncheckmem3");
+// fflush (stdout);
+// checkmem ((char *)rollback_blocks_array, get_mem_size((char *)rollback_blocks_array));
+// printf(" OK");
+}
+*/
+/* for now - just make sure that bad blocks did not get here */
int bwrite (struct buffer_head * bh)
{
loff_t offset;
ssize_t bytes;
size_t size;
+ if (is_bad_block (bh->b_blocknr)) {
+ fprintf (stderr, "bwrite: bad block is going to be written: %lu\n",
+ bh->b_blocknr);
+ exit (4);
+ }
+
if (!buffer_dirty (bh) || !buffer_uptodate (bh))
return 0;
+ buffer_writes++ ;
+ if (bh->b_start_io)
+ /* this is used by undo feature of reiserfsck */
+ bh->b_start_io (bh->b_blocknr);
+
size = bh->b_size;
offset = (loff_t)size * (loff_t)bh->b_blocknr;
if (lseek64 (bh->b_dev, offset, SEEK_SET) == (loff_t)-1){
fprintf (stderr, "bwrite: lseek to position %Ld (block=%lu, dev=%d): %s\n",
- offset, bh->b_blocknr, bh->b_dev, strerror (errno));
+ (long long)offset, bh->b_blocknr, bh->b_dev, strerror (errno));
exit (4); /* File system errors left uncorrected */
}
+ if (s_rollback_file != NULL && bh->b_size == rollback_blocksize) {
+ struct stat64 buf;
+ __u32 position;
+ struct block_handler block_h;
+
+ /*log previous content into log*/
+ if (!fstat64 (bh->b_dev, &buf)) {
+ block_h.blocknr = bh->b_blocknr;
+ block_h.device = buf.st_rdev;
+ if (reiserfs_bin_search (&block_h, rollback_blocks_array, rollback_blocks_number,
+ sizeof (block_h), &position, blockdev_list_compare) != POSITION_FOUND) {
+ /*read initial data from the disk*/
+ if (read (bh->b_dev, rollback_data, bh->b_size) == bh->b_size) {
+ fwrite (&buf.st_rdev, sizeof (buf.st_rdev), 1, s_rollback_file);
+ fwrite (&offset, sizeof (offset), 1, s_rollback_file);
+ fwrite (rollback_data, rollback_blocksize, 1, s_rollback_file);
+ fflush(s_rollback_file);
+ blocklist__insert_in_position ((void **)&rollback_blocks_array, &rollback_blocks_number, &block_h,
+ sizeof(block_h), &position);
+ /*if you want to know what gets saved, uncomment it*/
+/* if (log_file != 0 && log_file != stdout) {
+ fprintf (log_file, "rollback: block %lu of device %Lu was backed up\n",
+ bh->b_blocknr, buf.st_rdev);
+ }
+*/
+
+ } else {
+ fprintf (stderr, "bwrite: read (block=%lu, dev=%d): %s\n", bh->b_blocknr,
+ bh->b_dev, strerror (errno));
+ exit (4);
+ }
+ if (lseek64 (bh->b_dev, offset, SEEK_SET) == (loff_t)-1) {
+ fprintf (stderr, "bwrite: lseek to position %Ld (block=%lu, dev=%d): %s\n",
+ (long long)offset, bh->b_blocknr, bh->b_dev, strerror (errno));
+ exit (4);
+ }
+ }
+ } else {
+ fprintf (stderr, "bwrite: fstat of (%d) returned -1: %s\n", bh->b_dev, strerror (errno));
+ }
+ } else if (s_rollback_file != NULL) {
+ fprintf (stderr, "rollback: block (%lu) has the size different from the fs uses, block skipped\n",
+ bh->b_blocknr);
+ }
+
bytes = write (bh->b_dev, bh->b_data, size);
if (bytes != (ssize_t)size) {
- fprintf (stderr, "bwrite: write %d bytes returned %d (block=%ld, dev=%d): %s\n",
- size, bytes, bh->b_blocknr, bh->b_dev, strerror (errno));
+ fprintf (stderr, "bwrite: write %ld bytes returned %ld (block=%ld, dev=%d): %s\n",
+ (long)size, (long)bytes, bh->b_blocknr, bh->b_dev, strerror (errno));
exit (4);
}
mark_buffer_clean (bh);
+
if (bh->b_end_io) {
bh->b_end_io(bh, 1) ;
}
+
return 0;
}
-void check_and_free_buffer_mem (void)
-{
- int i = 0;
- struct buffer_head * next = g_buffer_list_head;
+static int _check_and_free_buffer_list(struct buffer_head *list) {
+ struct buffer_head *next = list ;
+ int count = 0 ;
+ if (!list)
+ return 0 ;
- //sync_buffers (0, 0);
- for (;;) {
- if (!next)
- die ("check_and_free_buffer_mem: buffer list is corrupted");
+ for(;;) {
if (next->b_count != 0)
- fprintf (stderr, "check_and_free_buffer_mem: not free buffer (%ld, %ld, %d)",
- next->b_blocknr, next->b_size, next->b_count);
+ fprintf (stderr, "check_and_free_buffer_mem: not free buffer (%x, %ld, %ld, %d)\n",
+ next->b_dev, next->b_blocknr, next->b_size, next->b_count);
if (buffer_dirty (next) && buffer_uptodate (next))
- fprintf (stderr, "check_and_free_buffer_mem: dirty buffer %lu found\n",
- next->b_blocknr);
+ fprintf (stderr, "check_and_free_buffer_mem: dirty buffer (%x %lu) found\n",
+ next->b_dev, next->b_blocknr);
freemem (next->b_data);
- i ++;
+ count++;
next = next->b_next;
- if (next == g_buffer_list_head)
- break;
+ if (next == list)
+ break;
}
- if (i != g_nr_buffers)
- die ("check_and_free_buffer_mem: found %d buffers, must be %d", i, g_nr_buffers);
+ return count;
+}
+
+void check_and_free_buffer_mem (void)
+{
+ int count = 0;
+ struct buffer_head * next ;
+
+// printf("check and free buffer mem, hits %d misses %d reads %d writes %d\n", buffer_hits, buffer_misses, buffer_reads, buffer_writes) ;
+ /*sync_buffers (0, 0);*/
+
+ count = _check_and_free_buffer_list(Buffer_list_head);
+ count += _check_and_free_buffer_list(g_free_buffers);
+
+ if (count != g_nr_buffers)
+ die ("check_and_free_buffer_mem: found %d buffers, must be %d", count, g_nr_buffers);
/* free buffer heads */
while ((next = g_buffer_heads)) {
@@ -506,3 +911,47 @@ void free_buffers (void)
{
check_and_free_buffer_mem ();
}
+
+
+static void _invalidate_buffer_list(struct buffer_head *list, dev_t dev)
+{
+ struct buffer_head * next;
+
+ if (!list)
+ return;
+
+ next = list;
+
+ for (;;) {
+ if (next->b_dev == dev) {
+ if (buffer_dirty (next) || next->b_count)
+ fprintf (stderr, "invalidate_buffers: dirty buffer or used buffer (%d %lu) found\n",
+ next->b_count, next->b_blocknr);
+ next->b_state = 0;
+ remove_from_hash_queue (next);
+ }
+ next = next->b_next;
+ if (next == list)
+ break;
+ }
+}
+
+/* forget all buffers of the given device */
+void invalidate_buffers (dev_t dev)
+{
+ _invalidate_buffer_list(Buffer_list_head, dev) ;
+ _invalidate_buffer_list(g_free_buffers, dev) ;
+}
+
+
+int user_confirmed (FILE * fp, char * q, char * yes)
+{
+ char * answer = 0;
+ size_t n = 0;
+
+ fprintf (fp, "%s", q);
+ if (getline (&answer, &n, stdin) != strlen (yes) || strcmp (yes, answer))
+ return 0;
+
+ return 1;
+}
diff --git a/lib/misc.c b/lib/misc.c
index f14fa6a..16becf9 100644
--- a/lib/misc.c
+++ b/lib/misc.c
@@ -1,11 +1,13 @@
/*
- * Copyright 1996, 1997, 1998 Hans Reiser
+ * Copyright 1996-2002 Hans Reiser
*/
-/*#define _GNU_SOURCE*/
-/*#define _FILE_OFFSET_BITS 64*/
+/* for stat64() */
+#define _FILE_OFFSET_BITS 64
+
+/* for getline() proto and _LARGEFILE64_SOURCE */
+#define _GNU_SOURCE
#include <stdio.h>
-#include <unistd.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
@@ -13,114 +15,28 @@
#include <stdlib.h>
#include <mntent.h>
#include <sys/vfs.h>
-#include <time.h>
#include <fcntl.h>
-#include <sys/stat.h>
-
-#include "io.h"
-
-/*
- * These have been stolen somewhere from linux
- */
-int set_bit (int nr, void * addr)
-{
- __u8 * p, mask;
- int retval;
-
- p = (__u8 *)addr;
- p += nr >> 3;
- mask = 1 << (nr & 0x7);
- /*cli();*/
- retval = (mask & *p) != 0;
- *p |= mask;
- /*sti();*/
- return retval;
-}
-
-
-int clear_bit (int nr, void * addr)
-{
- __u8 * p, mask;
- int retval;
-
- p = (__u8 *)addr;
- p += nr >> 3;
- mask = 1 << (nr & 0x7);
- /*cli();*/
- retval = (mask & *p) != 0;
- *p &= ~mask;
- /*sti();*/
- return retval;
-}
-
-int test_bit(int nr, const void * addr)
-{
- __u8 * p, mask;
-
- p = (__u8 *)addr;
- p += nr >> 3;
- mask = 1 << (nr & 0x7);
- return ((mask & *p) != 0);
-}
-
-int find_first_zero_bit (const void *vaddr, unsigned size)
-{
- const __u8 *p = vaddr, *addr = vaddr;
- int res;
-
- if (!size)
- return 0;
-
- size = (size >> 3) + ((size & 0x7) > 0);
- while (*p++ == 255) {
- if (--size == 0)
- return (p - addr) << 3;
- }
-
- --p;
- for (res = 0; res < 8; res++)
- if (!test_bit (res, p))
- break;
- return (p - addr) * 8 + res;
-}
-
+#include <time.h>
+#include <utime.h>
+#include <ctype.h>
-int find_next_zero_bit (const void *vaddr, unsigned size, unsigned offset)
-{
- const __u8 *addr = vaddr;
- const __u8 *p = addr + (offset >> 3);
- int bit = offset & 7, res;
-
- if (offset >= size)
- return size;
-
- if (bit) {
- /* Look for zero in first char */
- for (res = bit; res < 8; res++)
- if (!test_bit (res, p))
- return (p - addr) * 8 + res;
- p++;
- }
- /* No zero yet, search remaining full bytes for a zero */
- res = find_first_zero_bit (p, size - 8 * (p - addr));
- return (p - addr) * 8 + res;
-}
+#include <unistd.h>
+//#include <linux/unistd.h>
+//#include <sys/stat.h>
+#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
+# define BLKGETSIZE64 _IOR(0x12, 114, sizeof(__u64))
+#endif
+
-/*int test_and_set_bit (int nr, void * addr)
-{
- int oldbit = test_bit (nr, addr);
- set_bit (nr, addr);
- return oldbit;
-}
+#include "swab.h"
+#include "io.h"
+#include "misc.h"
-int test_and_clear_bit (int nr, void * addr)
-{
- int oldbit = test_bit (nr, addr);
- clear_bit (nr, addr);
- return oldbit;
-}*/
+/* Debian modifications by Ed Boraas <ed@debian.org> */
+#include <sys/mount.h>
+/* End Debian mods */
void die (char * fmt, ...)
@@ -133,18 +49,17 @@ void die (char * fmt, ...)
va_end (args);
fprintf (stderr, "\n%s\n\n\n", buf);
- exit (-1);
+ abort ();
}
-
#define MEM_BEGIN "_mem_begin_"
#define MEM_END "mem_end"
#define MEM_FREED "__free_"
#define CONTROL_SIZE (strlen (MEM_BEGIN) + 1 + sizeof (int) + strlen (MEM_END) + 1)
-static int get_mem_size (char * p)
+int get_mem_size (char * p)
{
char * begin;
@@ -189,7 +104,7 @@ void * getmem (int size)
p += size;
strcpy (p, MEM_END);
- checkmem (mem, size);
+// checkmem (mem, size);
return mem;
}
@@ -223,7 +138,7 @@ void * expandmem (void * vp, int size, int by)
if(by > 0)
memset (mem + size, 0, by);
strcpy (mem + size + by, MEM_END);
- checkmem (mem, size + by);
+// checkmem (mem, size + by);
return mem;
}
@@ -246,48 +161,81 @@ void freemem (void * vp)
}
-
typedef int (*func_t) (char *);
static int is_readonly_dir (char * dir)
{
- char * name;
- FILE * f;
+/*
+ int fd;
+ char template [1024];
- name = tempnam (dir, 0);
- if (!name) {
- fprintf (stderr, "is_readonly: tempnam failed, think fs is not readonly\n");
+ snprintf (template, 1024, "%s/testXXXXXX", dir);
+ fd = mkstemp (template);
+ if (fd >= 0) {
+ close (fd);
return 0;
}
-
- f = fopen (name, "w");
- if (f) {
- unlink (name);
- free (name);
+*/
+ if (utime (dir, 0) != -1)
+ /* this is not ro mounted fs */
return 0;
- }
- free (name);
return (errno == EROFS) ? 1 : 0;
}
-int user_confirmed (char * q, char * yes)
+
+#ifdef __i386__
+
+#include <unistd.h>
+#include <linux/unistd.h>
+
+#define __NR_bad_stat64 195
+_syscall2(long, bad_stat64, char *, filename, struct stat64 *, statbuf);
+
+#else
+
+#define bad_stat64 stat64
+
+#endif
+
+/* yes, I know how ugly it is */
+#define return_stat_field(field) \
+ struct stat st;\
+ struct stat64 st64;\
+\
+ if (bad_stat64 (file_name, &st64) == 0) {\
+ return st64.st_##field;\
+ } else if (stat (file_name, &st) == 0)\
+ return st.st_##field;\
+\
+ perror ("stat failed");\
+ exit (1);\
+
+
+mode_t get_st_mode (char * file_name)
+{
+ return_stat_field (mode);
+}
+
+
+/* may I look at this undocumented (at least in the info of libc 2.3.1-58)
+ field? */
+dev_t get_st_rdev (char * file_name)
{
- char * answer = 0;
- size_t n = 0;
+ return_stat_field (rdev);
+}
- fprintf (stderr, "%s", q);
- if (getline (&answer, &n, stdin) != strlen (yes) || strcmp (yes, answer))
- return 0;
- return 1;
+off64_t get_st_size (char * file_name)
+{
+ return_stat_field (size);
}
-#include <unistd.h>
-#include <linux/unistd.h>
+blkcnt64_t get_st_blocks (char * file_name)
+{
+ return_stat_field (blocks);
+}
-#define __NR_stat64 195
-_syscall2(long, stat64, char *, filename, struct stat *, statbuf);
static int _is_mounted (char * device_name, func_t f)
@@ -297,27 +245,22 @@ static int _is_mounted (char * device_name, func_t f)
struct mntent *mnt;
struct statfs stfs;
struct stat root_st;
- struct stat device_st;
- /* struct stat64 device_st64;*/
- int used_stat64 = 1;
+ mode_t mode;
if (stat ("/", &root_st) == -1)
die ("is_mounted: could not stat \"/\": %m\n");
- if (stat64 (device_name, &device_st) == -1) {
- used_stat64 = 0;
- if (stat (device_name, &device_st) == -1)
- die ("is_mounted: could not stat file \"%s\": %m",
- device_name);
- }
- if ((used_stat64 && !S_ISBLK (device_st.st_mode)) || !S_ISBLK (device_st.st_mode))
- /* not block device file could not be mounted */
+ mode = get_st_mode (device_name);
+ if (S_ISREG (mode))
+ /* regular file can not be mounted */
return 0;
- if ((used_stat64 && root_st.st_dev == device_st.st_rdev) ||
- root_st.st_dev == device_st.st_rdev) {
- /* device is mounted as root */
+ if (!S_ISBLK (mode))
+ die ("is_mounted: %s is neither regular file nor block device", device_name);
+
+ if (root_st.st_dev == get_st_rdev (device_name)) {
+ /* device is mounted as root. Check whether it is mounted read-only */
return (f ? f ("/") : 1);
}
@@ -327,17 +270,17 @@ static int _is_mounted (char * device_name, func_t f)
/* proc filesystem is not mounted, or /proc/mounts does not
exist */
if (f)
- return (user_confirmed (" (could not figure out) Is filesystem mounted read-only? (Yes)",
+ return (user_confirmed (stderr, " (could not figure out) Is filesystem mounted read-only? (Yes)",
"Yes\n"));
else
- return (user_confirmed (" (could not figure out) Is filesystem mounted? (Yes)",
+ return (user_confirmed (stderr, " (could not figure out) Is filesystem mounted? (Yes)",
"Yes\n"));
}
retval = 0;
while ((mnt = getmntent (fp)) != NULL)
if (strcmp (device_name, mnt->mnt_fsname) == 0) {
- retval = (f ? f (mnt->mnt_dir) : 1);
+ retval = (f ? f (mnt->mnt_dir) : 1/*mounted*/);
break;
}
endmntent (fp);
@@ -364,7 +307,7 @@ char buf2 [100];
void print_how_fast (unsigned long passed, unsigned long total,
int cursor_pos, int reset_time)
{
- static time_t t0, t1;
+ static time_t t0 = 0, t1 = 0, t2 = 0;
int speed;
int indent;
@@ -372,9 +315,14 @@ void print_how_fast (unsigned long passed, unsigned long total,
time (&t0);
time (&t1);
- if (t1 != t0)
+ if (t1 != t0) {
speed = passed / (t1 - t0);
- else
+ if (total - passed) {
+ if (t1 - t2 < 1)
+ return;
+ t2 = t1;
+ }
+ } else
speed = 0;
/* what has to be written */
@@ -414,7 +362,8 @@ static void str_to_be (char * buf, int prosents)
}
-void print_how_far (unsigned long * passed, unsigned long total,
+void print_how_far (FILE * fp,
+ unsigned long * passed, unsigned long total,
int inc, int quiet)
{
int percent;
@@ -424,8 +373,8 @@ void print_how_far (unsigned long * passed, unsigned long total,
(*passed) += inc;
if (*passed > total) {
- fprintf (stderr, "\nprint_how_far: total %lu has been reached already. cur=%lu\n",
- total, *passed);
+/* fprintf (fp, "\nprint_how_far: total %lu has been reached already. cur=%lu\n",
+ total, *passed);*/
return;
}
@@ -434,7 +383,7 @@ void print_how_far (unsigned long * passed, unsigned long total,
str_to_be (progress_to_be, percent);
if (strlen (current_progress) != strlen (progress_to_be)) {
- fprintf (stderr, "%s", progress_to_be + strlen (current_progress));
+ fprintf (fp, "%s", progress_to_be + strlen (current_progress));
}
strcat (current_progress, progress_to_be + strlen (current_progress));
@@ -443,171 +392,471 @@ void print_how_far (unsigned long * passed, unsigned long total,
print_how_fast (*passed/* - inc*/, total, strlen (progress_to_be),
(*passed == inc) ? 1 : 0);
- fflush (stderr);
+ fflush (fp);
}
-#define ENDIANESS_NOT_DEFINED 0
-#define LITTLE_ENDIAN_ARCH 1
-#define BIG_ENDIAN_ARCH 2
-static int endianess = ENDIANESS_NOT_DEFINED;
+/* calculates number of blocks in a file. Returns 0 for "sparse"
+ regular files and files other than regular files and block devices */
+unsigned long count_blocks (char * filename, int blocksize)
+{
+ loff_t high, low;
+ int fd;
+
+ if (!S_ISBLK (get_st_mode (filename)) && !S_ISREG (get_st_mode (filename)))
+ return 0;
+ fd = open (filename, O_RDONLY);
+ if (fd == -1)
+ die ("count_blocks: open failed (%s)", strerror (errno));
-static void find_endianess (void)
-{
- __u32 x = 0x0f0d0b09;
- char * s;
+#ifdef BLKGETSIZE64
+ {
+ __u64 size;
+ unsigned long sz;
+
+ if (ioctl (fd, BLKGETSIZE64, &size) >= 0) {
+ size /= blocksize;
+ sz = size;
+ if ((__u64)sz != size)
+ die ("count_blocks: block device too large");
+ return sz;
+ }
+ }
+#endif
+
+
+#ifdef BLKGETSIZE
+ {
+ unsigned long size;
+
+ if (ioctl (fd, BLKGETSIZE, &size) >= 0) {
+ return size / (blocksize / 512);
+ }
+ }
+#endif
- s = (char *)&x;
+ low = 0;
+ for( high = 1; valid_offset (fd, high); high *= 2 )
+ low = high;
+ while (low < high - 1) {
+ const loff_t mid = ( low + high ) / 2;
- // little-endian is 1234
- if (s[0] == '\11' && s[1] == '\13' && s[2] == '\15' && s[3] == '\17')
- endianess = LITTLE_ENDIAN_ARCH;
+ if (valid_offset (fd, mid))
+ low = mid;
+ else
+ high = mid;
+ }
+ valid_offset (fd, 0);
- // big-endian is 4321
- if (s[0] == '\17' && s[1] == '\15' && s[2] == '\13' && s[3] == '\11')
- die ("big-endian archs are not supported");
+ close (fd);
- // nuxi/pdp-endian is 3412
- if (s[0] == '\15' && s[1] == '\17' && s[2] == '\11' && s[3] == '\13')
- die ("nuxi/pdp-endian archs are not supported");
+ return (low + 1) / (blocksize);
}
-// we used to use such function in the kernel stuff of reiserfs. Lets
-// have them in utils as well
-inline __u32 cpu_to_le32 (__u32 val)
+
+/*
+ * These have been stolen somewhere from linux
+ */
+int le_set_bit (int nr, void * addr)
{
- if (endianess == ENDIANESS_NOT_DEFINED)
- find_endianess ();
+ __u8 * p, mask;
+ int retval;
+
+ p = (__u8 *)addr;
+ p += nr >> 3;
+ mask = 1 << (nr & 0x7);
+ /*cli();*/
+ retval = (mask & *p) != 0;
+ *p |= mask;
+ /*sti();*/
+ return retval;
+}
- if (endianess == LITTLE_ENDIAN_ARCH)
- return val;
- die ("neither big- nor any other endian archs are supported yet ");
+int le_clear_bit (int nr, void * addr)
+{
+ __u8 * p, mask;
+ int retval;
- return ((val>>24) | ((val>>8)&0xFF00) |
- ((val<<8)&0xFF0000) | (val<<24));
+ p = (__u8 *)addr;
+ p += nr >> 3;
+ mask = 1 << (nr & 0x7);
+ /*cli();*/
+ retval = (mask & *p) != 0;
+ *p &= ~mask;
+ /*sti();*/
+ return retval;
}
+int le_test_bit(int nr, const void * addr)
+{
+ __u8 * p, mask;
+
+ p = (__u8 *)addr;
+ p += nr >> 3;
+ mask = 1 << (nr & 0x7);
+ return ((mask & *p) != 0);
+}
-inline __u32 le32_to_cpu (__u32 val)
+int le_find_first_zero_bit (const void *vaddr, unsigned size)
{
- return cpu_to_le32 (val);
+ const __u8 *p = vaddr, *addr = vaddr;
+ int res;
+
+ if (!size)
+ return 0;
+
+ size = (size >> 3) + ((size & 0x7) > 0);
+ while (*p++ == 255) {
+ if (--size == 0)
+ return (p - addr) << 3;
+ }
+
+ --p;
+ for (res = 0; res < 8; res++)
+ if (!test_bit (res, p))
+ break;
+ return (p - addr) * 8 + res;
}
-inline __u16 cpu_to_le16 (__u16 val)
+int le_find_next_zero_bit (const void *vaddr, unsigned size, unsigned offset)
{
- return val;
+ const __u8 *addr = vaddr;
+ const __u8 *p = addr + (offset >> 3);
+ int bit = offset & 7, res;
+
+ if (offset >= size)
+ return size;
+
+ if (bit) {
+ /* Look for zero in first char */
+ for (res = bit; res < 8; res++)
+ if (!test_bit (res, p))
+ return (p - addr) * 8 + res;
+ p++;
+ }
+ /* No zero yet, search remaining full bytes for a zero */
+ res = find_first_zero_bit (p, size - 8 * (p - addr));
+ return (p - addr) * 8 + res;
+}
- if (endianess == ENDIANESS_NOT_DEFINED)
- find_endianess ();
+int be_set_bit (int nr, void * addr)
+{
+ __u8 mask = 1 << (nr & 0x7);
+ __u8 *p = (__u8 *) addr + (nr >> 3);
+ __u8 old = *p;
- if (endianess == LITTLE_ENDIAN_ARCH)
- return val;
- die ("neither big- nor pdp- endian arch are supported yet ");
+ *p |= mask;
- return (val >> 8) | (val << 8);
+ return (old & mask) != 0;
+}
+
+int be_clear_bit (int nr, void * addr)
+{
+ __u8 mask = 1 << (nr & 0x07);
+ __u8 *p = (unsigned char *) addr + (nr >> 3);
+ __u8 old = *p;
+
+ *p = *p & ~mask;
+ return (old & mask) != 0;
+}
+
+int be_test_bit(int nr, const void * addr)
+{
+ const __u8 *ADDR = (__const__ __u8 *) addr;
+
+ return ((ADDR[nr >> 3] >> (nr & 0x7)) & 1) != 0;
+}
+
+int be_find_first_zero_bit (const void *vaddr, unsigned size)
+{
+ return find_next_zero_bit( vaddr, size, 0 );
}
-
-inline __u16 le16_to_cpu (__u16 val)
+static unsigned long ffz(unsigned long word)
{
- /*printf ("%s:%u %p %p %p\n", __FILE__, __LINE__,
- __builtin_return_address (0),
- __builtin_return_address (1),
- __builtin_return_address (2));*/
- return val;
- return cpu_to_le16 (val);
+ unsigned long result = 0;
+
+ while(word & 1) {
+ result++;
+ word >>= 1;
+ }
+ return result;
}
+/* stolen from linux/include/asm-mips/bitops.h:ext2_find_next_zero_bit()
+ * the bitfield is assumed to be little endian, which is the case here,
+ * since we're reading/writing from the disk in LE order */
+int be_find_next_zero_bit (const void *vaddr, unsigned size, unsigned offset)
+{
+ __u32 *p = ((__u32 *) vaddr) + (offset >> 5);
+ __u32 result = offset & ~31UL;
+ __u32 tmp;
+
+ if (offset >= size)
+ return size;
+ size -= result;
+ offset &= 31UL;
+ if (offset) {
+ tmp = *(p++);
+ tmp |= swab32(~0UL >> (32-offset));
+ if (size < 32)
+ goto found_first;
+ if (~tmp)
+ goto found_middle;
+ size -= 32;
+ result += 32;
+ }
+ while (size & ~31UL) {
+ if (~(tmp = *(p++)))
+ goto found_middle;
+ result += 32;
+ size -= 32;
+ }
+ if (!size)
+ return result;
+ tmp = *p;
+
+found_first:
+ return result + ffz(swab32(tmp) | (~0UL << size));
+found_middle:
+ return result + ffz(swab32(tmp));
+}
-inline __u64 cpu_to_le64 (__u64 val)
+/* there are masks for certain bits */
+__u16 mask16 (int from, int count)
{
- if (endianess == ENDIANESS_NOT_DEFINED)
- find_endianess ();
+ __u16 mask;
- if (endianess == LITTLE_ENDIAN_ARCH)
- return val;
- die ("neither big- nor pdp- endian arch are supported yet ");
- return 0;
+ mask = (0xffff >> from);
+ mask <<= from;
+ mask <<= (16 - from - count);
+ mask >>= (16 - from - count);
+ return mask;
}
-inline __u64 le64_to_cpu (__u64 val)
+__u32 mask32 (int from, int count)
{
- return cpu_to_le64 (val);
+ __u32 mask;
+
+
+ mask = (0xffffffff >> from);
+ mask <<= from;
+ mask <<= (32 - from - count);
+ mask >>= (32 - from - count);
+ return mask;
}
-/* Given a file descriptor and an offset, check whether the offset is
- a valid offset for the file - return 0 if it isn't valid or 1 if it
- is */
-loff_t reiserfs_llseek (unsigned int fd, loff_t offset, unsigned int origin);
-#if 0
-static int valid_offset( int fd, loff_t offset )
+__u64 mask64 (int from, int count)
{
- char ch;
- loff_t res;
+ __u64 mask;
- /*res = reiserfs_llseek (fd, offset, 0);*/
- res = lseek64 (fd, offset, 0);
- if (res < 0)
- return 0;
- if (read (fd, &ch, 1) < 1)
- return 0;
+ mask = (0xffffffffffffffffLL >> from);
+ mask <<= from;
+ mask <<= (64 - from - count);
+ mask >>= (64 - from - count);
+ return mask;
+}
- return 1;
+
+__u32 get_random (void)
+{
+ srandom (time (0));
+ return random ();
}
-#endif
-/* calculates number of blocks on device */
-unsigned long count_blocks (char * filename, int blocksize, int fd)
+/* this implements binary search in the array 'base' among 'num' elements each
+ of those is 'width' bytes long. 'comp_func' is used to compare keys */
+int reiserfs_bin_search (void * key, void * base, __u32 num, int width,
+ __u32 * ppos, comparison_fn_t comp_func)
{
- loff_t high, low;
- int opened_here = 0;
+ __u32 rbound, lbound, j;
+ int ret;
- if (fd < 0) {
- fd = open (filename, O_RDONLY);
- opened_here = 1;
+ if (num == 0 || base == NULL) {
+ /* objectid map may be 0 elements long */
+ *ppos = 0;
+ return POSITION_NOT_FOUND;
}
- if (fd < 0)
- die ("count_blocks: open failed (%s)", strerror (errno));
-#ifdef BLKGETSIZE
- {
- long size;
-
- if (ioctl (fd, BLKGETSIZE, &size) >= 0) {
- if (opened_here)
- close (fd);
- return size / (blocksize / 512);
+ lbound = 0;
+ rbound = num - 1;
+
+ for (j = (rbound + lbound) / 2; lbound <= rbound; j = (rbound + lbound) / 2) {
+ ret = comp_func ((void *)((char *)base + j * width), key ) ;
+ if (ret < 0) { /* second is greater */
+ lbound = j + 1;
+ continue;
+
+ } else if (ret > 0) { /* first is greater */
+ if (j == 0)
+ break;
+ rbound = j - 1;
+ continue;
+ } else { /* equal */
+ *ppos = j;
+ return POSITION_FOUND;
}
}
-#endif
- low = 0;
- for( high = 1; valid_offset (fd, high); high *= 2 )
- low = high;
- while (low < high - 1) {
- const loff_t mid = ( low + high ) / 2;
+ *ppos = lbound;
+ return POSITION_NOT_FOUND;
+}
- if (valid_offset (fd, mid))
- low = mid;
- else
- high = mid;
+
+#define BLOCKLIST__INCREASE_BLOCK_NUMBER 10
+
+/*element is block number and device*/
+int blockdev_list_compare (const void * block1, const void * block2) {
+ if (*(__u32 *)block1 < *(__u32 *)block2)
+ return -1;
+ if (*(__u32 *)block1 > *(__u32 *)block2)
+ return 1;
+
+ if (*((__u32 *)block1 + 1) < *((__u32 *)block2 + 1))
+ return -1;
+ if (*((__u32 *)block1 + 1) > *((__u32 *)block2 + 1))
+ return 1;
+
+ return 0;
+}
+
+/* return -1 if smth found, otherwise return position which new item should be inserted into */
+/*
+int blocklist__is_block_saved (struct block_handler ** base, __u32 * count,
+ __u32 blocknr, dev_t device, __u32 * position) {
+ struct block_handler block_h;
+
+ *position = 0;
+
+ if (*base == NULL)
+ return 0;
+
+ block_h.blocknr = blocknr;
+ block_h.device = device;
+
+ if (reiserfs_bin_search (&block_h, *base, *count, sizeof (block_h),
+ position, blocklist_compare) == POSITION_FOUND)
+ return 1;
+
+ return 0;
+}
+*/
+void blocklist__insert_in_position (void ** base, __u32 * count, void * elem,
+ int elem_size, __u32 * position) {
+ if (elem_size == 0)
+ return;
+
+ if (*base == NULL)
+ *base = getmem (BLOCKLIST__INCREASE_BLOCK_NUMBER * elem_size);
+
+ if (*count == get_mem_size ((void *)*base) / elem_size)
+ *base = expandmem (*base, get_mem_size((void *)*base),
+ BLOCKLIST__INCREASE_BLOCK_NUMBER * elem_size);
+
+ if (*position < *count) {
+ memmove (*base + (*position + 1),
+ *base + (*position),
+ (*count - *position) * elem_size);
}
- valid_offset (fd, 0);
- if (opened_here)
+
+ memcpy (*base + (char) *position * elem_size, elem, elem_size);
+ *count+=1;
+}
+
+static int get_random_bytes (void *out, int size) {
+ int fd;
+
+ if ((fd = open("/dev/urandom", O_RDONLY)) == -1)
+ return 1;
+
+ if (read(fd, out, size) <= 0) {
close (fd);
+ return 1;
+ }
+
+ close (fd);
+ return 0;
+}
- return (low + 1) / (blocksize);
+int generate_random_uuid (unsigned char * uuid)
+{
+ if (get_random_bytes(uuid, 16)) {
+ return -1;
+ }
+
+ /* Set the UUID variant to DCE */
+ uuid[8] = (uuid[8] & 0x3F) | 0x80;
+ /* Set UUID version to 4 --- truely random generation */
+ uuid[6] = (uuid[6] & 0x0F) | 0x40;
+
+ return 0;
+}
+
+int uuid_is_correct (unsigned char * uuid)
+{
+ int i;
+
+ for (i = 0; i < 16; i++)
+ if (uuid[i])
+ break;
+
+ if (i == 16)
+ return 0;
+
+ if (!test_bit(7, &uuid[8]) || test_bit(6, &uuid[8]))
+ return 0;
+
+ if (test_bit(7, &uuid[6]) || !test_bit(6, &uuid[6]) ||
+ test_bit(5, &uuid[6]) || test_bit(4, &uuid[6]))
+ return 0;
+
+ return 1;
+}
+
+static int parse_uuid (const unsigned char * in, unsigned char * uuid)
+{
+ int i, j = 0;
+ unsigned char frame[3];
+
+ if (strlen(in) != 36)
+ return -1;
+
+ for (i = 0; i < 36; i++) {
+ if ((i == 8) || (i == 13) || (i == 18) || (i == 23)) {
+ if (in[i] != '-')
+ return 0;
+ } else if (!isxdigit(in[i])) {
+ return -1;
+ }
+ }
+
+ frame[2] = 0;
+ for (i = 0; i < 36; i ++) {
+ if ((i == 8) || (i == 13) || (i == 18) || (i == 23))
+ continue;
+
+ frame[0] = in[i++];
+ frame[1] = in[i];
+ uuid[j++] = strtoul(frame, NULL, 16);
+ }
+ return 0;
}
+int set_uuid (const unsigned char * text, unsigned char * UUID)
+{
+ if (parse_uuid (text, UUID) || !uuid_is_correct(UUID))
+ return -1;
+ return 0;
+}
diff --git a/mkreiserfs/Makefile.am b/mkreiserfs/Makefile.am
index 54198db..cdb92ec 100644
--- a/mkreiserfs/Makefile.am
+++ b/mkreiserfs/Makefile.am
@@ -4,6 +4,5 @@ mkreiserfs_SOURCES = mkreiserfs.c
man_MANS = mkreiserfs.8
EXTRA_DIST = $(man_MANS)
-LDADD = ../lib/libmisc.a ../reiserfscore/libcore.a
+LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a
-INCLUDES = -I../include
diff --git a/mkreiserfs/Makefile.in b/mkreiserfs/Makefile.in
index f73f030..62bb9f0 100644
--- a/mkreiserfs/Makefile.in
+++ b/mkreiserfs/Makefile.in
@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -62,6 +62,7 @@ MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
+sbindir = @sbindir@
sbin_PROGRAMS = mkreiserfs
@@ -69,21 +70,21 @@ mkreiserfs_SOURCES = mkreiserfs.c
man_MANS = mkreiserfs.8
EXTRA_DIST = $(man_MANS)
-LDADD = ../lib/libmisc.a ../reiserfscore/libcore.a
-
-INCLUDES = -I../include
+LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../include/config.h
CONFIG_CLEAN_FILES =
PROGRAMS = $(sbin_PROGRAMS)
-DEFS = @DEFS@ -I. -I$(srcdir)
+DEFS = @DEFS@ -I. -I$(srcdir) -I../include
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
mkreiserfs_OBJECTS = mkreiserfs.o
mkreiserfs_LDADD = $(LDADD)
-mkreiserfs_DEPENDENCIES = ../lib/libmisc.a ../reiserfscore/libcore.a
+mkreiserfs_DEPENDENCIES = $(top_srcdir)/lib/libmisc.a \
+$(top_srcdir)/reiserfscore/libcore.a
mkreiserfs_LDFLAGS =
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -238,7 +239,7 @@ distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
- cp -pr $$/$$file $(distdir)/$$file; \
+ cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
@@ -246,7 +247,8 @@ distdir: $(DISTFILES)
fi; \
done
mkreiserfs.o: mkreiserfs.c ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h ../version.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h ../include/config.h ../version.h
info-am:
info: info-am
diff --git a/mkreiserfs/mkreiserfs.8 b/mkreiserfs/mkreiserfs.8
index 4509f42..5eaec33 100644
--- a/mkreiserfs/mkreiserfs.8
+++ b/mkreiserfs/mkreiserfs.8
@@ -1,62 +1,103 @@
.\" -*- nroff -*-
-.\" Copyright 1996-2001 Hans Reiser.
+.\" Copyright 1996-2002 Hans Reiser.
.\"
-.TH MKREISERFS 8 "March 2001" "Reiserfsprogs-3.x.0j"
+.TH MKREISERFS 8 "January 2002" "Reiserfsprogs-3.6.2"
.SH NAME
-mkreiserfs \- create a Linux Reiserfs file system
+mkreiserfs \- create a Linux ReiserFS file system
.SH SYNOPSIS
.B mkreiserfs
-[
-.B -h
-.I r5
-|
-.I tea
-|
-.I rupasov
-] [
-.B \-v
-.I 1
-|
-.I 2
-] [
-.B -q
-]
-.I device
-[
-.I size-in-blocks
-]
+[ \fB-dfV\fR ]
+[ \fB-b\fR | \fB--block-size \fIN\fR ]
+[ \fB-h\fR | \fB--hash \fIHASH\fR ]
+[ \fB-u\fR | \fB--uuid \fIUUID\fR ]
+[ \fB-l\fR | \fB--label \fILABEL\fR ]
+[ \fB--format \fIFORMAT\fR ]
+[ \fB-j\fR | \fB--journal-device \fIFILE\fR ]
+[ \fB-s\fR | \fB--journal-size \fIN\fR ]
+[ \fB-o\fR | \fB--journal-offset \fIN\fR ]
+[ \fB-t\fR | \fB--transaction-max-size\fR \fIN\fR ] \fI device\fR
+[ \fIfilesystem-size\fR ]
.SH DESCRIPTION
-It creates a Linux Reiserfs file system on a device
+It creates a Linux ReiserFS file system on a device
(usually a disk partition).
.TP
.I device
is the special file corresponding to the device (e.g /dev/hdXX for
IDE disk partition or /dev/sdXX for SCSI disk partition).
.TP
-.I block-count
-is the number of blocks on the device. If omitted, it will be
+.I filesystem-size
+size of filesystem in blocks. If omitted, it will be
determined by
.B mkreiserfs
automatically.
.SH OPTIONS
.TP
-\fB\-h \fIr5\fR |\fI tea\fR |\fI rupasov
-This specifies the name of hash function file names in directories
-will be sorted with. Choose one of the above. 'r5' is default.
+\fB-b\fR | \fB--block-size \fIN\fR
+\fIN\fR is block size in bytes. 4096 only for now.
+.TP
+\fB-h\fR | \fB--hash \fIHASH\fR
+\fIHASH\fR specifies the name of hash function file names in directories
+will be sorted with. Choose one of r5, rupasov, tea. r5 is default
+.TP
+\fB--format \fIFORMAT\fR
+\fIFORMAT\fR specifies a format new filsystem has to be of. Choose one
+of 3.5 and 3.6. If none is specified mkreiserfs will create format 3.6
+if running kernel is 2.4, 3.5 if 2.2 is running, and will refuse
+creation under other kernels.
+.TP
+\fB-u\fR | \fB--uuid \fIUUID\fR
+Set the universally unique identifier (\fB UUID \fR) of the filesystem to
+\fIUUID\fR (see also \fBuuidgen(8)\fR). The format of the UUID is a
+series of hex digits separated by hypthens, like this:
+"c1b9d5a2-f162-11cf-9ece-0020afc76f16". If the option skipped,
+mkreiserfs generates a new one.
+.TP
+\fB-l\fR | \fB--label \fILABEL\fR
+Set the volume label of the filesystem. \fILABEL\fR can be at most 16
+characters long; if it is longer than 16 characters, mkreiserfs will truncate it.
+.TP
+\fB-j\fR | \fB--journal-device \fIFILE\fR
+\fIFILE\fR is name of block device where the file system is to have
+journal on.
+.TP
+\fB-o\fR | \fB--journal-offset \fIN\fR
+\fIN\fR is an offset where journal starts when it is to be on a
+separate device. Default is 0. Makes no effect when journal is to be
+on a host device
+.TP
+\fB-s\fR | \fB--journal-size \fIN
+\fIN\fR is size of journal in blocks. When journal is to be on a
+separate device - its size defaults to number of blocks that device
+has. When journal is to be on a host device - its size defaults 8193
+and maximal possible value is 32749 (for blocksize 4k). Minimun is 513
+for both cases.
+.TP
+\fB-t\fR | \fB--transaction-max-size \fIN
+\fIN\fR is the maximum transaction size parameter for the journal. The
+default, and max possible, value is 1024 blocks. It should be less
+than half the size of the journal. If specifed incorrectly, it will be
+adjusted.
+.TP
+\fB-f\fR
+This forces mkreiserfs to continue even if device is either whole
+disk, or looks mounted or is not a block device. Specified more than
+once allows to avoid asking for confirmation.
.TP
-\fB\-v \fI1\fR |\fI 2
-This specifies format new filsystem has to be of.
+\fB-d\fR
+This makes mkreiserfs to print debugging information during mkreiserfs.
.TP
-\fB\-q\fR
-This makes the progress bar much less verbose. Useful when
-logged in via a slow link (e.g. serial console).
+\fB-V\fR
+This prints version and exits.
+
.SH AUTHOR
This version of
.B mkreiserfs
-has been written by Hans Reiser <reiser@idiom.com>.
+has been written by Edward Shishkin <edward@namesys.com>.
.SH BUGS
No other blocksizes but 4k are available.
-Please, report about other bugs to Hans Reiser <reiser@idiom.com>.
+Please, report about other bugs to
+the ReiserFS mail-list <reiserfs-list@namesys.com>
.SH SEE ALSO
.BR reiserfsck (8),
-.BR debugreiserfs (8)
+.BR debugreiserfs (8),
+.BR reiserfstune (8)
diff --git a/mkreiserfs/mkreiserfs.c b/mkreiserfs/mkreiserfs.c
index a907d19..1f7c4a1 100644
--- a/mkreiserfs/mkreiserfs.c
+++ b/mkreiserfs/mkreiserfs.c
@@ -1,8 +1,8 @@
/*
- * Copyright 1996, 1997, 1998, 1999 Hans Reiser
+ * Copyright 1996-2002 Hans Reiser, licensing governed by ../README
*/
-/* mkreiserfs is very simple. It supports only 4 and 8K blocks. It skips
+/* mkreiserfs is very simple. It supports only 4k blocks. It skips
first 64k of device, and then writes the super
block, the needed amount of bitmap blocks (this amount is calculated
based on file system size), and root block. Bitmap policy is
@@ -12,8 +12,10 @@
resizing faster. */
//
-// FIXME: not 'not-i386' safe
+// FIXME: not 'not-i386' safe. ? Ed
//
+#define _GNU_SOURCE
+
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -29,476 +31,722 @@
#include <linux/major.h>
#include <sys/stat.h>
#include <linux/kdev_t.h>
+#include <sys/utsname.h>
+#include <getopt.h>
+#include <stdarg.h>
#include "io.h"
#include "misc.h"
#include "reiserfs_lib.h"
+#include "../include/config.h"
#include "../version.h"
-#define print_usage_and_exit() die ("Usage: %s [ -f ] [ -h tea | rupasov | r5 ]"\
- " [ -v 1 | 2] [ -q ] device [block-count]\n\n", argv[0])
-
-
-#define DEFAULT_BLOCKSIZE 4096
+char *program_name;
+static void message( const char * fmt, ... )
+ __attribute__ ((format (printf, 1, 2)));
+ static void message( const char * fmt, ... )
+{
+ char *buf;
+ va_list args;
+
+ buf = NULL;
+ va_start( args, fmt );
+ vasprintf( &buf, fmt, args );
+ va_end( args );
+
+ if( buf ) {
+ fprintf( stderr, "%s: %s\n", program_name, buf );
+ free( buf );
+ }
+}
+static void print_usage_and_exit(void)
+{
+ fprintf(stderr, "Usage: %s [options] "
+ " device [block-count]\n"
+ "\n"
+ "Options:\n\n"
+ " -b | --block-size N size of file-system block, in bytes\n"
+ " -j | --journal-device FILE path to separate device to hold journal\n"
+ " -s | --journal-size N size of the journal in blocks\n"
+ " -o | --journal-offset N offset of the journal from the start of\n"
+ " the separate device, in blocks\n"
+ " -t | --transaction-max-size N maximal size of transaction, in blocks\n"
+ " -h | --hash rupasov|tea|r5 hash function to use by default\n"
+ " -u | --uuid UUID store UUID in the superblock\n"
+ " -l | --label LABEL store LABEL in the superblock\n"
+ " --format 3.5|3.6 old 3.5 format or newer 3.6\n"
+ " -f | --force specified once, make mkreiserfs the whole\n"
+ " disk, not block device or mounted partition;\n"
+ " specified twice, do not ask for confirmation\n"
+ " -d | --debug print debugging information during mkreiser\n"
+ " -V print version and exit\n",
+ program_name);
+ exit (1);
+}
-struct buffer_head * g_sb_bh;
-struct buffer_head * g_bitmap_bh;
-struct buffer_head * g_rb_bh;
-struct buffer_head * g_journal_bh ;
+// " -B badblocks-file list of all bad blocks on the fs\n"
+int Create_default_journal = 1;
+int Block_size = 4096;
+int DEBUG_MODE = 0;
-int g_block_size = DEFAULT_BLOCKSIZE;
-unsigned long int g_block_number;
-int g_hash = DEFAULT_HASH;
-int g_3_6_format = 1; /* new format is default */
+/* size of journal + 1 block for journal header */
+unsigned long Journal_size = 0;
+int Max_trans_size = 0; //JOURNAL_TRANS_MAX;
+int Hash = DEFAULT_HASH;
+int Offset = 0;
+char * Format;
+unsigned char UUID[16];
+unsigned char * LABEL = NULL;
+char * badblocks_file;
-int quiet = 0;
-/* reiserfs needs at least: enough blocks for journal, 64 k at the beginning,
- one block for super block, bitmap block and root block */
-static unsigned long min_block_amount (int block_size, unsigned long journal_size)
+/* form super block (old one) */
+static void make_super_block (reiserfs_filsys_t * fs)
{
- unsigned long blocks;
-
- blocks = REISERFS_DISK_OFFSET_IN_BYTES / block_size +
- 1 + 1 + 1 + journal_size;
- if (blocks > block_size * 8)
- die ("mkreiserfs: journal size specified incorrectly");
+ set_sb_umount_state (fs->fs_ondisk_sb, REISERFS_CLEANLY_UMOUNTED);
+ set_sb_tree_height (fs->fs_ondisk_sb, 2);
+ set_sb_hash_code (fs->fs_ondisk_sb, Hash);
+ if (fs->fs_format == REISERFS_FORMAT_3_6) {
+ if (!uuid_is_correct (UUID) && generate_random_uuid (UUID))
+ reiserfs_warning (stdout, "failed to genetate UUID\n");
+
+ memcpy (fs->fs_ondisk_sb->s_uuid, UUID, 16);
+ if (LABEL != NULL) {
+ if (strlen (LABEL) > 16)
+ reiserfs_warning (stderr, "\nSpecified LABEL is longer then 16 characters, will be truncated\n\n");
+ strncpy (fs->fs_ondisk_sb->s_label, LABEL, 16);
+ }
+ set_sb_v2_flag (fs->fs_ondisk_sb, reiserfs_attrs_cleared);
+ }
- return blocks;
+ if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb) ||
+ strcmp (fs->fs_file_name, fs->fs_j_file_name))
+ /* either standard journal (and we leave all new fields to be 0) or
+ journal is created on separate device so there is no space on data
+ device which can be used as a journal */
+ set_sb_reserved_for_journal (fs->fs_ondisk_sb, 0);
+ else
+ set_sb_reserved_for_journal (fs->fs_ondisk_sb,
+ get_jp_journal_size (sb_jp (fs->fs_ondisk_sb)) + 1);
}
-/* form super block (old one) */
-static void make_super_block (int dev)
+/* wipe out first 64 k of a device and both possible reiserfs super block */
+static void invalidate_other_formats (int dev)
{
- struct reiserfs_super_block * rs;
- int sb_size = g_3_6_format ? SB_SIZE : SB_SIZE_V1;
- __u32 * oids;
-
-
- if (SB_SIZE > g_block_size)
- die ("mkreiserfs: blocksize (%d) too small", g_block_size);
-
- /* get buffer for super block */
- g_sb_bh = getblk (dev, REISERFS_DISK_OFFSET_IN_BYTES / g_block_size, g_block_size);
-
- rs = (struct reiserfs_super_block *)g_sb_bh->b_data;
- set_blocksize (rs, g_block_size);
- set_block_count (rs, g_block_number);
- set_state (rs, REISERFS_VALID_FS);
- set_tree_height (rs, 2);
-
- set_bmap_nr (rs, (g_block_number + (g_block_size * 8 - 1)) / (g_block_size * 8));
- set_version (rs, g_3_6_format ? REISERFS_VERSION_2 : REISERFS_VERSION_1);
-
- set_hash (rs, g_hash);
-
- // journal things
- rs->s_v1.s_journal_dev = cpu_to_le32 (0) ;
- rs->s_v1.s_orig_journal_size = cpu_to_le32 (JOURNAL_BLOCK_COUNT) ;
- rs->s_v1.s_journal_trans_max = cpu_to_le32 (0) ;
- rs->s_v1.s_journal_block_count = cpu_to_le32 (0) ;
- rs->s_v1.s_journal_max_batch = cpu_to_le32 (0) ;
- rs->s_v1.s_journal_max_commit_age = cpu_to_le32 (0) ;
- rs->s_v1.s_journal_max_trans_age = cpu_to_le32 (0) ;
-
- // the differences between sb V1 and sb V2 are: magic string
- memcpy (rs->s_v1.s_magic, g_3_6_format ? REISER2FS_SUPER_MAGIC_STRING : REISERFS_SUPER_MAGIC_STRING,
- strlen (g_3_6_format ? REISER2FS_SUPER_MAGIC_STRING : REISERFS_SUPER_MAGIC_STRING));
- // start of objectid map
- oids = (__u32 *)((char *)rs + sb_size);
+ struct buffer_head * bh;
- // max size of objectid map
- rs->s_v1.s_oid_maxsize = cpu_to_le16 ((g_block_size - sb_size) / sizeof(__u32) / 2 * 2);
+ bh = bread (dev, 0, 64 * 1024);
+ if (!bh)
+ die ("Unable to read first blocks of the device");
+#if defined(__sparc__) || defined(__sparc_v9__)
+ memset (bh->b_data + 1024, 0, bh->b_size - 1024);
+#else
+ memset (bh->b_data, 0, bh->b_size);
+#endif
+ mark_buffer_uptodate (bh, 1);
+ mark_buffer_dirty (bh);
+ bwrite (bh);
+ brelse (bh);
+}
- oids[0] = cpu_to_le32 (1);
- oids[1] = cpu_to_le32 (REISERFS_ROOT_OBJECTID + 1);
- set_objectid_map_size (rs, 2);
- mark_buffer_dirty (g_sb_bh);
- mark_buffer_uptodate (g_sb_bh, 1);
- return;
+void zero_journal (reiserfs_filsys_t * fs)
+{
+ int i;
+ struct buffer_head * bh;
+ unsigned long done;
+ unsigned long start, len;
+
+
+ fprintf (stderr, "Initializing journal - ");
+
+ start = get_jp_journal_1st_block (sb_jp (fs->fs_ondisk_sb));
+ len = get_jp_journal_size (sb_jp (fs->fs_ondisk_sb));
+
+ done = 0;
+ for (i = 0; i < len; i ++) {
+ print_how_far (stderr, &done, len, 1, 1/*be quiet*/);
+ bh = getblk (fs->fs_journal_dev, start + i, fs->fs_blocksize);
+ if (!bh)
+ die ("zero_journal: getblk failed");
+ memset (bh->b_data, 0, bh->b_size);
+ mark_buffer_dirty (bh);
+ mark_buffer_uptodate (bh, 1);
+ bwrite (bh);
+ brelse (bh);
+ }
+ fprintf (stderr, "\n");
+ fflush (stderr);
}
-void zero_journal_blocks(int dev, int start, int len) {
- int i ;
- struct buffer_head *bh ;
- unsigned long done = 0;
+/* this only sets few first bits in bitmap block. Fills not initialized fields
+ of super block (root block and bitmap block numbers) */
+static void make_bitmap (reiserfs_filsys_t * fs)
+{
+ struct reiserfs_super_block * sb = fs->fs_ondisk_sb;
+ int i;
+ unsigned long block;
+ int marked;
+
- printf ("Initializing journal - "); fflush (stdout);
+ marked = 0;
+
+ /* mark skipped area and super block */
+ for (i = 0; i <= fs->fs_super_bh->b_blocknr; i ++) {
+ reiserfs_bitmap_set_bit (fs->fs_bitmap2, i);
+ marked ++;
+ }
- for (i = 0 ; i < len ; i++) {
- print_how_far (&done, len, 1, quiet);
- bh = getblk (dev, start + i, g_block_size) ;
- memset(bh->b_data, 0, g_block_size) ;
- mark_buffer_dirty(bh) ;
- mark_buffer_uptodate(bh,0) ;
- bwrite (bh);
- brelse(bh) ;
+ if (fs->fs_badblocks_bm) {
+ for (i = 0; i < get_sb_block_count (sb); i ++) {
+ if (reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, i)) {
+ reiserfs_bitmap_set_bit (fs->fs_bitmap2, i);
+ marked ++;
+ }
+ }
}
- printf ("\n"); fflush (stdout);
-}
+ /* mark bitmaps as used */
+ block = fs->fs_super_bh->b_blocknr + 1;
-/* this only sets few first bits in bitmap block. Fills not initialized fields
- of super block (root block and bitmap block numbers) */
-static void make_bitmap (void)
-{
- struct reiserfs_super_block * rs = (struct reiserfs_super_block *)g_sb_bh->b_data;
- int i, j;
-
- /* get buffer for bitmap block */
- g_bitmap_bh = getblk (g_sb_bh->b_dev, g_sb_bh->b_blocknr + 1, g_sb_bh->b_size);
-
- /* mark, that first 8K of device is busy */
- for (i = 0; i < REISERFS_DISK_OFFSET_IN_BYTES / g_block_size; i ++)
- set_bit (i, g_bitmap_bh->b_data);
-
- /* mark that super block is busy */
- set_bit (i++, g_bitmap_bh->b_data);
+ for (i = 0; i < get_sb_bmap_nr (sb); i ++) {
+ reiserfs_bitmap_set_bit (fs->fs_bitmap2, block);
+ marked ++;
+ if (spread_bitmaps (fs))
+ block = (block / (fs->fs_blocksize * 8) + 1) * (fs->fs_blocksize * 8);
+ else
+ block ++;
+ }
- /* mark first bitmap block as busy */
- set_bit (i ++, g_bitmap_bh->b_data);
-
- /* sb->s_journal_block = g_block_number - JOURNAL_BLOCK_COUNT ; */ /* journal goes at end of disk */
- set_journal_start (rs, i);
+ if (!get_size_of_journal_or_reserved_area (fs->fs_ondisk_sb))
+ /* root block follows directly super block and first bitmap */
+ block = fs->fs_super_bh->b_blocknr + 1 + 1;
+ else {
+ /* makr journal blocks as used */
+ for (i = 0; i <= get_jp_journal_size (sb_jp (sb)); i ++) {
+ reiserfs_bitmap_set_bit (fs->fs_bitmap2,
+ i + get_jp_journal_1st_block (sb_jp (sb)));
+ marked ++;
+ }
+ block = get_jp_journal_1st_block (sb_jp (sb)) + i;
+ }
- /* mark journal blocks as busy BUG! we need to check to make sure journal
- will fit in the first bitmap block */
- for (j = 0 ; j < (JOURNAL_BLOCK_COUNT + 1); j++) /* the descriptor block goes after the journal */
- set_bit (i ++, g_bitmap_bh->b_data);
+ /*get correct block - not journal nor bitmap*/
+ while (block_of_journal (fs, block) || block_of_bitmap (fs, block)) {
+ block++;
+ }
- /* and tree root is busy */
- set_bit (i, g_bitmap_bh->b_data);
+ while ((block < get_sb_block_count (sb)) && reiserfs_bitmap_test_bit (fs->fs_bitmap2, block)) {
+ block++;
+ }
- set_root_block (rs, i);
- set_free_blocks (rs, rs_block_count (rs) - i - 1);
+ if (block >= get_sb_block_count (sb))
+ die ("mkreiserfs: too many bad blocks");
- /* count bitmap blocks not resides in first s_blocksize blocks - ?? */
- set_free_blocks (rs, rs_free_blocks (rs) - (rs_bmap_nr (rs) - 1));
+ reiserfs_bitmap_set_bit (fs->fs_bitmap2, block);
+ marked ++;
- mark_buffer_dirty (g_bitmap_bh);
- mark_buffer_uptodate (g_bitmap_bh, 0);
+ set_sb_root_block (sb, block);
+ set_sb_free_blocks (sb, get_sb_block_count (sb) - marked);
+}
- mark_buffer_dirty (g_sb_bh);
- return;
+
+static void set_root_dir_nlink (struct item_head * ih, void * sd)
+{
+ __u32 nlink;
+
+ nlink = 3;
+ set_sd_nlink (ih, sd, &nlink);
}
/* form the root block of the tree (the block head, the item head, the
root directory) */
-static void make_root_block (void)
+static void make_root_block (reiserfs_filsys_t * fs)
{
- struct reiserfs_super_block * rs = (struct reiserfs_super_block *)g_sb_bh->b_data;
- char * rb;
- struct item_head * ih;
+ struct reiserfs_super_block * sb;
+ struct buffer_head * bh;
+
+ sb = fs->fs_ondisk_sb;
/* get memory for root block */
- g_rb_bh = getblk (g_sb_bh->b_dev, rs_root_block (rs), rs_blocksize (rs));
- rb = g_rb_bh->b_data;
+ bh = getblk (fs->fs_dev, get_sb_root_block (sb), get_sb_block_size (sb));
+ if (!bh)
+ die ("make_root_block: getblk failed");
- /* block head */
- set_leaf_node_level (g_rb_bh);
- set_node_item_number (g_rb_bh, 0);
- set_node_free_space (g_rb_bh, rs_blocksize (rs) - BLKH_SIZE);
+ mark_buffer_uptodate (bh, 1);
+
+ make_empty_leaf (bh);
+ make_sure_root_dir_exists (fs, set_root_dir_nlink, 0);
+ brelse (bh);
+
+
+ /**/
+ mark_objectid_used (fs, REISERFS_ROOT_PARENT_OBJECTID);
+ mark_objectid_used (fs, REISERFS_ROOT_OBJECTID);
- /* first item is stat data item of root directory */
- ih = (struct item_head *)(g_rb_bh->b_data + BLKH_SIZE);
+}
- make_dir_stat_data (g_block_size, g_3_6_format ? KEY_FORMAT_2 : KEY_FORMAT_1,
- REISERFS_ROOT_PARENT_OBJECTID, REISERFS_ROOT_OBJECTID,
- ih, g_rb_bh->b_data + g_block_size - (g_3_6_format ? SD_SIZE : SD_V1_SIZE));
- set_ih_location (ih, g_block_size - ih_item_len (ih));
- // adjust block head
- set_node_item_number (g_rb_bh, node_item_number (g_rb_bh) + 1);
- set_node_free_space (g_rb_bh, node_free_space (g_rb_bh) - (IH_SIZE + ih_item_len (ih)));
-
- /* second item is root directory item, containing "." and ".." */
- ih ++;
- ih->ih_key.k_dir_id = cpu_to_le32 (REISERFS_ROOT_PARENT_OBJECTID);
- ih->ih_key.k_objectid = cpu_to_le32 (REISERFS_ROOT_OBJECTID);
- ih->ih_key.u.k_offset_v1.k_offset = cpu_to_le32 (DOT_OFFSET);
- ih->ih_key.u.k_offset_v1.k_uniqueness = cpu_to_le32 (DIRENTRY_UNIQUENESS);
- ih->ih_item_len = cpu_to_le16 (g_3_6_format ? EMPTY_DIR_SIZE : EMPTY_DIR_SIZE_V1);
- ih->ih_item_location = cpu_to_le16 (ih_location (ih-1) - ih_item_len (ih));
- ih->u.ih_entry_count = cpu_to_le16 (2);
- set_key_format (ih, KEY_FORMAT_1);
-
- if (g_3_6_format)
- make_empty_dir_item (g_rb_bh->b_data + ih_location (ih),
- REISERFS_ROOT_PARENT_OBJECTID, REISERFS_ROOT_OBJECTID,
- 0, REISERFS_ROOT_PARENT_OBJECTID);
- else
- make_empty_dir_item_v1 (g_rb_bh->b_data + ih_location (ih),
- REISERFS_ROOT_PARENT_OBJECTID, REISERFS_ROOT_OBJECTID,
- 0, REISERFS_ROOT_PARENT_OBJECTID);
+static void report (reiserfs_filsys_t * fs, char * j_filename)
+{
+// print_block (stdout, fs, fs->fs_super_bh);
+ struct reiserfs_super_block * sb = (struct reiserfs_super_block *)(fs->fs_super_bh->b_data);
+ struct stat st;
+ dev_t rdev;
- // adjust block head
- set_node_item_number (g_rb_bh, node_item_number (g_rb_bh) + 1);
- set_node_free_space (g_rb_bh, node_free_space (g_rb_bh) - (IH_SIZE + ih_item_len (ih)));
+ if (!is_any_reiserfs_magic_string (sb))
+ return;
+ if (fstat (fs->fs_super_bh->b_dev, &st) == -1) {
+ /*reiserfs_warning (stderr, "fstat failed: %m\n");*/
+ rdev = 0;
+ } else
+ rdev = st.st_rdev;
- print_block (stdout, 0, g_rb_bh, 3, -1, -1);
+ if (DEBUG_MODE) {
+ reiserfs_warning (stdout, "Block %lu (0x%x) contains super block. ",
+ fs->fs_super_bh->b_blocknr, rdev);
+ }
+ switch (get_reiserfs_format (sb)) {
+ case REISERFS_FORMAT_3_5:
+ reiserfs_warning (stdout, " Format 3.5 with ");
+ break;
+ case REISERFS_FORMAT_3_6:
+ reiserfs_warning (stdout, "Format 3.6 with ");
+ break;
+ }
+ if (is_reiserfs_jr_magic_string (sb))
+ reiserfs_warning (stdout, "non-");
+ reiserfs_warning (stdout, "standard journal\n");
+ reiserfs_warning (stdout, "Count of blocks on the device: %u\n", get_sb_block_count (sb));
+ reiserfs_warning (stdout, "Number of blocks consumed by mkreiserfs formatting process: %u\n",
+ get_sb_block_count (sb) - get_sb_free_blocks (sb));
+ if (DEBUG_MODE)
+ reiserfs_warning (stdout, "Free blocks: %u\n", get_sb_free_blocks (sb));
+ reiserfs_warning (stdout, "Blocksize: %d\n", get_sb_block_size (sb));
+ reiserfs_warning (stdout, "Hash function used to sort names: %s\n",
+ code2name (get_sb_hash_code (sb)));
+ if (DEBUG_MODE) {
+ reiserfs_warning (stdout, "Number of bitmaps: %u\n", get_sb_bmap_nr (sb));
+ reiserfs_warning (stdout, "Root block: %u\n", get_sb_root_block (sb));
+ reiserfs_warning (stdout, "Tree height: %d\n", get_sb_tree_height (sb));
+ reiserfs_warning (stdout, "Objectid map size %d, max %d\n", get_sb_oid_cursize (sb),
+ get_sb_oid_maxsize (sb));
+ reiserfs_warning (stdout, "Journal parameters:\n");
+ print_journal_params (stdout, sb_jp (sb));
+ } else {
+ if (j_filename && strcmp (j_filename, fs->fs_file_name))
+ reiserfs_warning (stdout, "Journal Device [0x%x]\n", get_jp_journal_dev (sb_jp (sb)));
+ reiserfs_warning (stdout, "Journal Size %u blocks (first block %u)\n",
+ get_jp_journal_size (sb_jp (sb)) + 1,
+ get_jp_journal_1st_block (sb_jp (sb)));
+ reiserfs_warning (stdout, "Journal Max transaction length %u\n",
+ get_jp_journal_max_trans_len (sb_jp (sb)));
+ }
+
+ if (j_filename && strcmp (j_filename, fs->fs_file_name)) {
+ reiserfs_warning (stdout, "Space on this device reserved by journal: %u\n",
+ get_sb_reserved_for_journal (sb));
+ }
- mark_buffer_dirty (g_rb_bh);
- mark_buffer_uptodate (g_rb_bh, 0);
+ if (DEBUG_MODE) {
+ reiserfs_warning (stdout, "Filesystem state 0x%x\n", get_sb_fs_state (sb));
+ reiserfs_warning (stdout, "sb_version %u\n", get_sb_version (sb));
+ }
+
+ if (get_reiserfs_format (sb) == REISERFS_FORMAT_3_6) {
+ reiserfs_warning (stdout, "inode generation number: %u\n", get_sb_v2_inode_generation (sb));
+ reiserfs_warning (stdout, "UUID: %U\n", sb->s_uuid);
+ if (strcmp (sb->s_label, ""))
+ reiserfs_warning (stdout, "LABEL: %s\n", sb->s_label);
+ }
+
return;
}
-/*
- * write the super block, the bitmap blocks and the root of the tree
- */
-static void write_super_and_root_blocks (void)
-{
- struct reiserfs_super_block * rs = (struct reiserfs_super_block *)g_sb_bh->b_data;
- int i;
- zero_journal_blocks(g_sb_bh->b_dev, rs_journal_start (rs), JOURNAL_BLOCK_COUNT + 1) ;
- /* super block */
- bwrite (g_sb_bh);
+static void set_hash_function (char * str)
+{
+ if (!strcmp (str, "tea"))
+ Hash = TEA_HASH;
+ else if (!strcmp (str, "rupasov"))
+ Hash = YURA_HASH;
+ else if (!strcmp (str, "r5"))
+ Hash = R5_HASH;
+ else
+ message("wrong hash type specified. Using default");
+}
- /* bitmap blocks */
- for (i = 0; i < rs_bmap_nr (rs); i ++) {
- if (i != 0) {
- g_bitmap_bh->b_blocknr = i * rs_blocksize (rs) * 8;
- memset (g_bitmap_bh->b_data, 0, g_bitmap_bh->b_size);
- set_bit (0, g_bitmap_bh->b_data);
- }
- if (i == rs_bmap_nr (rs) - 1) {
- int j;
- /* fill unused part of last bitmap block with 1s */
- if (rs_block_count (rs) % (rs_blocksize (rs) * 8))
- for (j = rs_block_count (rs) % (rs_blocksize (rs) * 8); j < rs_blocksize (rs) * 8; j ++) {
- set_bit (j, g_bitmap_bh->b_data);
- }
- }
- /* write bitmap */
- mark_buffer_dirty (g_bitmap_bh);
- bwrite (g_bitmap_bh);
+static void set_reiserfs_version (char * str)
+{
+ if (!strcmp (str, "3.5"))
+ Format = "3.5";
+ else {
+ Format = "3.6";
+ if (strcmp (str, "3.6"))
+ message("wrong reiserfs version specified. Using default 3.6 format");
}
+}
- /* root block */
- bwrite (g_rb_bh);
- brelse (g_rb_bh);
- brelse (g_bitmap_bh);
- brelse (g_sb_bh);
+static int str2int (char * str)
+{
+ int val;
+ char * tmp;
+
+ val = (int) strtol (str, &tmp, 0);
+ if (*tmp)
+ die ("%s: strtol is unable to make an integer of %s\n", program_name, str);
+ return val;
}
-static void report (char * devname)
+static void set_block_size (char * str, int *b_size)
{
- struct reiserfs_super_block * rs = (struct reiserfs_super_block *)g_sb_bh->b_data;
- unsigned int i;
-
- printf ("Creating reiserfs of %s format\n", g_3_6_format ? "3.6" : "3.5");
- printf ("Block size %d bytes\n", rs_blocksize (rs));
- printf ("Block count %d\n", rs_block_count (rs));
- printf ("Used blocks %d\n", rs_block_count (rs) - rs_free_blocks (rs));
- printf ("Free blocks count %d\n", rs_free_blocks (rs));
- printf ("First %ld blocks skipped\n", g_sb_bh->b_blocknr);
- printf ("Super block is in %ld\n", g_sb_bh->b_blocknr);
- printf ("Bitmap blocks (%d) are : \n\t%ld", rs_bmap_nr (rs), g_bitmap_bh->b_blocknr);
- for (i = 1; i < rs_bmap_nr (rs); i ++) {
- printf (", %d", i * rs_blocksize (rs) * 8);
- }
- printf ("\nJournal size %d (blocks %d-%d of file %s)\n",
- JOURNAL_BLOCK_COUNT, rs_journal_start (rs),
- rs_journal_start (rs) + JOURNAL_BLOCK_COUNT, devname);
- printf ("Root block %u\n", rs_root_block (rs));
- printf ("Hash function \"%s\"\n", g_hash == TEA_HASH ? "tea" :
- ((g_hash == YURA_HASH) ? "rupasov" : "r5"));
- fflush (stdout);
+ *b_size = str2int (str);
+
+ if (!is_blocksize_correct (*b_size))
+ die ("%s: wrong blocksize %s specified, only divisible by 1024 are supported currently",
+ program_name, str);
}
-/* wipe out first 2 k of a device and both possible reiserfs super block */
-static void invalidate_other_formats (int dev)
+static void set_transaction_max_size (char * str)
{
- struct buffer_head * bh;
-
- bh = getblk (dev, 0, 2048);
- mark_buffer_uptodate (bh, 1);
- mark_buffer_dirty (bh);
- bwrite (bh);
- brelse (bh);
+ Max_trans_size = str2int( str );
+}
- bh = getblk(dev, REISERFS_OLD_DISK_OFFSET_IN_BYTES / 1024, 1024) ;
- mark_buffer_uptodate (bh, 1);
- mark_buffer_dirty (bh);
- bwrite (bh);
- brelse (bh);
- bh = getblk(dev, REISERFS_DISK_OFFSET_IN_BYTES / 1024, 1024) ;
- mark_buffer_uptodate (bh, 1);
- mark_buffer_dirty (bh);
- bwrite (bh);
- brelse (bh);
+/* reiserfs_create_journal will check this */
+static void set_journal_device_size (char * str)
+{
+ Journal_size = str2int (str);
+/*
+ if (Journal_size < JOURNAL_MIN_SIZE)
+ die ("%s: wrong journal size specified: %lu. Should be at least %u",
+ program_name,
+ Journal_size + 1, JOURNAL_MIN_SIZE + 1);
+*/
}
-static void set_hash_function (char * str)
+/* reiserfs_create_journal will check this */
+static void set_offset_in_journal_device (char * str)
{
- if (!strcmp (str, "tea"))
- g_hash = TEA_HASH;
- else if (!strcmp (str, "rupasov"))
- g_hash = YURA_HASH;
- else if (!strcmp (str, "r5"))
- g_hash = R5_HASH;
- else
- printf ("mkreiserfs: wrong hash type specified. Using default\n");
+ Offset = str2int( str );
}
-static void set_reiserfs_version (char * str)
+static int is_journal_default (char * name, char * jname, int blocksize)
{
- if (!strcmp (str, "1"))
- g_3_6_format = 0;
- else if (!strcmp (str, "2"))
- g_3_6_format = 1;
- else
- printf ("mkreiserfs: wrong reiserfs version specified. Using default 3.5 format\n");
+ if (jname && strcmp (name, jname))
+ return 0;
+ if (Journal_size &&
+ Journal_size != journal_default_size (REISERFS_DISK_OFFSET_IN_BYTES / blocksize, blocksize) + 1)
+ /* journal size is set and it is not default size */
+ return 0;
+ if (Max_trans_size != JOURNAL_TRANS_MAX)
+ return 0;
+ return 1;
}
-
-int main (int argc, char **argv)
+
+
+/* if running kernel is 2.2 - mkreiserfs creates 3.5 format, if 2.4 - 3.6,
+ otherwise - mkreiserfs fails */
+static int select_format (void)
{
- char *tmp;
- int dev;
- int force = 0;
- struct stat st;
- char * device_name;
- char c;
+ struct utsname sysinfo;
- print_banner ("mkreiserfs");
- if (argc < 2)
- print_usage_and_exit ();
+ if (Format) {
+ if (!strcmp (Format, "3.5"))
+ return REISERFS_FORMAT_3_5;
+
+ if (strcmp (Format, "3.6")) {
+ message ("Unknown fromat %s specified\n", Format);
+ exit (1);
+ }
+ return REISERFS_FORMAT_3_6;
+ }
+
+ message ("Guessing about desired format.. ");
+
+ if (uname (&sysinfo) == -1) {
+ message ("could not get system info: %m");
+ exit (1);
+ }
+
+ message ("Kernel %s is running.", sysinfo.release);
+ if (!strncmp (sysinfo.release, "2.5", 3))
+ return REISERFS_FORMAT_3_6;
+
+ if (!strncmp (sysinfo.release, "2.4", 3))
+ return REISERFS_FORMAT_3_6;
+
+ if (strncmp (sysinfo.release, "2.2", 3)) {
+ message( "You should run either 2.4 or 2.2 to be able "
+ "to create reiserfs filesystem or specify desired format with -v");
+ exit (1);
+ }
+ message ("Creating filesystem of format 3.5");
+ return REISERFS_FORMAT_3_5;
+}
- while ( ( c = getopt( argc, argv, "fh:v:q" ) ) != EOF )
- switch( c )
- {
- case 'f' : /* force if file is not a block device or fs is
- mounted. Confirm still required */
- force = 1;
- break;
- case 'h':
- set_hash_function (optarg);
- break;
+int main (int argc, char **argv)
+{
+ reiserfs_filsys_t * fs;
+ int force;
+ char * device_name;
+ char * jdevice_name;
+ unsigned long fs_size;
+ int c;
+ static int flag;
- case 'v':
- set_reiserfs_version (optarg);
- break;
- case 'q':
- quiet = 1;
- break;
+ program_name = strrchr( argv[ 0 ], '/' );
+ program_name = program_name ? ++ program_name : argv[ 0 ];
+
+ print_banner (program_name);
- default :
- print_usage_and_exit ();
- }
- device_name = argv [optind];
-
+ if (argc < 2)
+ print_usage_and_exit ();
+
+ force = 0;
+ fs_size = 0;
+ device_name = 0;
+ jdevice_name = 0;
+
+
+ while (1) {
+ static struct option options[] = {
+ {"block-size", required_argument, 0, 'b'},
+ {"journal-device", required_argument, 0, 'j'},
+ {"journal-size", required_argument, 0, 's'},
+ {"transaction-max-size", required_argument, 0, 't'},
+ {"journal-offset", required_argument, 0, 'o'},
+ {"hash", required_argument, 0, 'h'},
+ {"uuid", required_argument, 0, 'u'},
+ {"label", required_argument, 0, 'l'},
+ {"format", required_argument, &flag, 1},
+ {0, 0, 0, 0}
+ };
+ int option_index;
+
+ c = getopt_long (argc, argv, "b:j:s:t:o:h:u:l:Vfd",
+ options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 0:
+ if (flag) {
+ Format = optarg;
+ flag = 0;
+ }
+ break;
+ case 'b': /* --block-size */
+ set_block_size (optarg, &Block_size);
+ break;
+
+ case 'j': /* --journal-device */
+ Create_default_journal = 0;
+ jdevice_name = optarg;
+ break;
+
+ case 's': /* --journal-size */
+ Create_default_journal = 0;
+ set_journal_device_size (optarg);
+ break;
+
+ case 't': /* --transaction-max-size */
+ Create_default_journal = 0;
+ set_transaction_max_size (optarg);
+ break;
+
+ case 'o': /* --offset */
+ Create_default_journal = 0;
+ set_offset_in_journal_device (optarg);
+ break;
+
+ case 'B': /* --badblock-list */
+ asprintf (&badblocks_file, "%s", optarg);
+ break;
+
+ case 'h': /* --hash */
+ set_hash_function (optarg);
+ break;
+
+ case 'v': /* --format */
+ set_reiserfs_version (optarg);
+ break;
+
+ case 'V':
+ exit (1);
+
+ case 'f':
+ force ++;
+ break;
+
+ case 'd':
+ DEBUG_MODE = 1;
+ break;
+
+ case 'u':
+ if (set_uuid (optarg, UUID)) {
+ reiserfs_warning(stdout, "wrong UUID specified\n");
+ return 1;
+ }
+
+ break;
+
+ case 'l':
+ LABEL = optarg;
+ break;
+
+ default:
+ print_usage_and_exit();
+ }
+ }
- /* get block number for file system */
+
+ /* device to be formatted */
+ device_name = argv [optind];
+
if (optind == argc - 2) {
- g_block_number = strtol (argv[optind + 1], &tmp, 0);
- if (*tmp == 0) { /* The string is integer */
- if (g_block_number > count_blocks (device_name, g_block_size, -1))
- die ("mkreiserfs: specified block number (%d) is too high", g_block_number);
- } else {
- die ("mkreiserfs: bad block count : %s\n", argv[optind + 1]);
- }
- } else
- if (optind == argc - 1) {
- /* number of blocks is not specified */
- g_block_number = count_blocks (device_name, g_block_size, -1);
- tmp = "";
- } else
- print_usage_and_exit ();
-
-
- /*g_block_number = g_block_number / 8 * 8;*/
-
- if (g_block_number < min_block_amount (g_block_size, JOURNAL_BLOCK_COUNT + 1))
- die ("mkreiserfs: can not create filesystem on that small device (%lu blocks).\n"
- "It should have at least %lu blocks",
- g_block_number, min_block_amount (g_block_size, JOURNAL_BLOCK_COUNT + 1));
-
- if (is_mounted (device_name)) {
- printf ("mkreiserfs: '%s' contains a mounted file system\n", device_name);
- if (!force)
- exit (1);
- if (!user_confirmed ("Forced to continue, but please confirm (y/n)", "y"))
- exit (1);
+ /* number of blocks for filesystem is specified */
+ fs_size = str2int (argv[optind + 1]);
+ } else if (optind == argc - 1) {
+ /* number of blocks is not specified */
+ fs_size = count_blocks (device_name, Block_size);
+ } else {
+ print_usage_and_exit ();
}
- dev = open (device_name, O_RDWR);
- if (dev == -1)
- die ("mkreiserfs: can not open '%s': %s", device_name, strerror (errno));
-
- if (fstat (dev, &st) < 0)
- die ("mkreiserfs: unable to stat %s", device_name);
+ if (is_journal_default (device_name, jdevice_name, Block_size))
+ Create_default_journal = 1;
+
+ if (!Max_trans_size) {
+ /* max transaction size has not been specified,
+ for blocksize >= 4096 - max transaction size is 1024. For block size < 4096
+ - trans max size is decreased proportionally */
+ Max_trans_size = JOURNAL_TRANS_MAX;
+ if (Block_size < 4096)
+ Max_trans_size = JOURNAL_TRANS_MAX / (4096 / Block_size);
+ }
+
+ if (!can_we_format_it (device_name, force))
+ return 1;
+
+ if (jdevice_name)
+ if (!can_we_format_it (jdevice_name, force))
+ return 1;
+
+ fs = reiserfs_create (device_name, select_format (), fs_size, Block_size, Create_default_journal, 1);
+ if (!fs) {
+ return 1;
+ }
+
+ if (!reiserfs_create_journal (fs, jdevice_name, Offset, Journal_size, Max_trans_size)) {
+ return 1;
+ }
- if (!S_ISBLK (st.st_mode)) {
- printf ("mkreiserfs: %s is not a block special device.\n", device_name);
- if (!force) {
- exit (1);
- }
- if (!user_confirmed ("Forced to continue, but please confirm (y/n)", "y"))
- exit (1);
- } else {
- // from e2progs-1.18/misc/mke2fs.c
- if ((MAJOR (st.st_rdev) == HD_MAJOR && MINOR (st.st_rdev)%64 == 0) ||
- (SCSI_BLK_MAJOR (MAJOR(st.st_rdev)) && MINOR (st.st_rdev) % 16 == 0)) {
- printf ("mkreiserfs: %s is entire device, not just one partition! Continue? (y/n) ",
- device_name);
- if (!user_confirmed ("Continue (y/n)", "y"))
- exit (1);
- }
+ if (!reiserfs_create_ondisk_bitmap (fs)) {
+ return 1;
}
/* these fill buffers (super block, first bitmap, root block) with
reiserfs structures */
- make_super_block (dev);
- make_bitmap ();
- make_root_block ();
+ if (uuid_is_correct (UUID) && fs->fs_format != REISERFS_FORMAT_3_6) {
+ reiserfs_warning(stdout, "UUID can be specified only with 3.6 format\n");
+ return 1;
+ }
+
+ if (badblocks_file)
+ create_badblock_bitmap (fs, badblocks_file);
+
+
+ make_super_block (fs);
+ make_bitmap (fs);
+ make_root_block (fs);
+ add_badblock_list (fs, 1);
- report (device_name);
+ report (fs, jdevice_name);
- printf ("ATTENTION: YOU SHOULD REBOOT AFTER FDISK!\n\t ALL DATA WILL BE LOST ON '%s'! ", device_name);
- if (!user_confirmed ("(y/n)", "y\n"))
- die ("mkreiserfs: Disk was not formatted");
+ if (!force) {
+ fprintf (stderr, "ATTENTION: YOU SHOULD REBOOT AFTER FDISK!\n"
+ "\tALL DATA WILL BE LOST ON '%s'", device_name);
+ if (jdevice_name && strcmp (jdevice_name, device_name))
+ fprintf (stderr, " AND ON JOURNAL DEVICE '%s'", jdevice_name);
- invalidate_other_formats (dev);
- write_super_and_root_blocks ();
+ if (!user_confirmed (stderr, "!\nContinue (y/n):", "y\n"))
+ return 1;
+ }
- check_and_free_buffer_mem ();
- printf ("Syncing.."); fflush (stdout);
+ invalidate_other_formats (fs->fs_dev);
+
+
+ zero_journal (fs);
+
+ reiserfs_close (fs);
- close(dev) ;
+ printf ("Syncing.."); fflush (stdout);
sync ();
+ printf ("ok\n");
- printf ("\n\nReiserFS core development sponsored by SuSE Labs (suse.com)\n\n"
- "Journaling sponsored by MP3.com.\n\n"
- //"Item handlers sponsored by Ecila.com\n\n
- "To learn about the programmers and ReiserFS, please go to\n"
- "http://www.devlinux.com/namesys\n\nHave fun.\n\n");
- fflush (stdout);
+ if (DEBUG_MODE)
+ return 0;
+ printf ("\nThe Defense Advanced Research Projects Agency (DARPA) is the primary sponsor of"
+ "\nReiser4. DARPA does not endorse this project; it merely sponsors it."
+ "\n"
+ "\nContinuing core development of version 3 is mostly paid for by Hans Reiser from"
+ "\nmoney made selling licenses in addition to the GPL to companies who don't want"
+ "\nit known that they use ReiserFS as a foundation for their proprietary product."
+ "\nAnd my lawyer asked 'People pay you money for this?'. Yup. Hee Hee. Life is"
+ "\ngood. If you buy ReiserFS, you can focus on your value add rather than"
+ "\nreinventing an entire FS. You should buy some free software too...."
+ "\n"
+ "\nSuSE pays for continuing work on journaling for version 3, and paid for much of"
+ "\nthe previous version 3 work. Reiserfs integration in their distro is"
+ "\nconsistently solid."
+ "\n"
+ "\nMP3.com paid for initial journaling development."
+ "\n"
+ "\nBigstorage.com contributes to our general fund every month, and has done so for"
+ "\nquite a long time."
+ "\n"
+ "\nThanks to all of those sponsors, including the secret ones. Without you, Hans"
+ "\nwould still have that day job, and the merry band of hackers would be missing"
+ "\nquite a few...."
+ "\n"
+ "\nHave fun.\n");
return 0;
}
+
+
+
+/*
+ * Use BSD fomatting.
+ * Local variables:
+ * c-indentation-style: "bsd"
+ * mode-name: "BSDC"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff --git a/reiserfscore/Makefile.am b/reiserfscore/Makefile.am
index 3dc78bc..f1b9be3 100644
--- a/reiserfscore/Makefile.am
+++ b/reiserfscore/Makefile.am
@@ -1,5 +1,5 @@
noinst_LIBRARIES = libcore.a
-libcore_a_SOURCES = do_balan.c fix_node.c hashes.c ibalance.c lbalance.c prints.c stree.c node_formats.c reiserfslib.c bitmap.c includes.h
+libcore_a_SOURCES = do_balan.c fix_node.c hashes.c ibalance.c lbalance.c prints.c \
+stree.c node_formats.c reiserfslib.c bitmap.c journal.c includes.h
-INCLUDES = -I../include
diff --git a/reiserfscore/Makefile.in b/reiserfscore/Makefile.in
index 967298f..2306ebc 100644
--- a/reiserfscore/Makefile.in
+++ b/reiserfscore/Makefile.in
@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -62,24 +62,26 @@ MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
+sbindir = @sbindir@
noinst_LIBRARIES = libcore.a
-libcore_a_SOURCES = do_balan.c fix_node.c hashes.c ibalance.c lbalance.c prints.c stree.c node_formats.c reiserfslib.c bitmap.c includes.h
+libcore_a_SOURCES = do_balan.c fix_node.c hashes.c ibalance.c lbalance.c prints.c stree.c node_formats.c reiserfslib.c bitmap.c journal.c includes.h
-INCLUDES = -I../include
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../include/config.h
CONFIG_CLEAN_FILES =
LIBRARIES = $(noinst_LIBRARIES)
-DEFS = @DEFS@ -I. -I$(srcdir)
+DEFS = @DEFS@ -I. -I$(srcdir) -I../include
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
libcore_a_LIBADD =
libcore_a_OBJECTS = do_balan.o fix_node.o hashes.o ibalance.o \
-lbalance.o prints.o stree.o node_formats.o reiserfslib.o bitmap.o
+lbalance.o prints.o stree.o node_formats.o reiserfslib.o bitmap.o \
+journal.o
AR = ar
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -176,7 +178,7 @@ distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
- cp -pr $$/$$file $(distdir)/$$file; \
+ cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
@@ -184,26 +186,36 @@ distdir: $(DISTFILES)
fi; \
done
bitmap.o: bitmap.c includes.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
do_balan.o: do_balan.c includes.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
fix_node.o: fix_node.c includes.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
hashes.o: hashes.c
ibalance.o: ibalance.c includes.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
+journal.o: journal.c includes.h ../include/io.h ../include/misc.h \
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
lbalance.o: lbalance.c includes.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
node_formats.o: node_formats.c includes.h ../include/io.h \
- ../include/misc.h ../include/reiserfs_lib.h \
+ ../include/misc.h ../include/swab.h ../include/reiserfs_lib.h \
../include/reiserfs_fs.h
prints.o: prints.c includes.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
reiserfslib.o: reiserfslib.c includes.h ../include/io.h \
- ../include/misc.h ../include/reiserfs_lib.h \
+ ../include/misc.h ../include/swab.h ../include/reiserfs_lib.h \
../include/reiserfs_fs.h
stree.o: stree.c includes.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h
info-am:
info: info-am
diff --git a/reiserfscore/bitmap.c b/reiserfscore/bitmap.c
index 4318c08..b3b09da 100644
--- a/reiserfscore/bitmap.c
+++ b/reiserfscore/bitmap.c
@@ -1,25 +1,25 @@
/*
- * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
+ * Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
*/
/*
* 2000/10/26 - Initial version.
*/
-#include <assert.h>
#include "includes.h"
+#include <assert.h>
/* create clean bitmap */
-reiserfs_bitmap_t reiserfs_create_bitmap (unsigned int bit_count)
+reiserfs_bitmap_t * reiserfs_create_bitmap (unsigned int bit_count)
{
- reiserfs_bitmap_t bm;
+ reiserfs_bitmap_t * bm;
bm = getmem (sizeof (*bm));
if (!bm)
return 0;
bm->bm_bit_size = bit_count;
- bm->bm_byte_size = (bit_count + 7) / 8;
+ bm->bm_byte_size = ((unsigned long long)bit_count + 7) / 8;
bm->bm_set_bits = 0;
bm->bm_map = getmem (bm->bm_byte_size);
if (!bm->bm_map) {
@@ -32,7 +32,7 @@ reiserfs_bitmap_t reiserfs_create_bitmap (unsigned int bit_count)
/* Expand existing bitmap. Return non-zero if can't. FIXME: it is
assumed that bit_count is new number of blocks to be addressed */
-int reiserfs_expand_bitmap (reiserfs_bitmap_t bm, unsigned int bit_count)
+int reiserfs_expand_bitmap (reiserfs_bitmap_t * bm, unsigned int bit_count)
{
unsigned int byte_count = ((bit_count + 7) / 8);
char * new_map;
@@ -50,8 +50,16 @@ int reiserfs_expand_bitmap (reiserfs_bitmap_t bm, unsigned int bit_count)
return 0;
}
+void reiserfs_shrink_bitmap (reiserfs_bitmap_t * bm, unsigned int bit_count)
+{
+ assert (bm->bm_bit_size >= bit_count);
+
+ bm->bm_byte_size = (bit_count + 7) / 8;
+ bm->bm_bit_size = bit_count;
+}
+
/* bitmap destructor */
-void reiserfs_delete_bitmap (reiserfs_bitmap_t bm)
+void reiserfs_delete_bitmap (reiserfs_bitmap_t * bm)
{
freemem(bm->bm_map);
bm->bm_map = NULL; /* to not reuse bitmap handle */
@@ -61,19 +69,19 @@ void reiserfs_delete_bitmap (reiserfs_bitmap_t bm)
}
-void reiserfs_bitmap_copy (reiserfs_bitmap_t to, reiserfs_bitmap_t from)
+void reiserfs_bitmap_copy (reiserfs_bitmap_t * to, reiserfs_bitmap_t * from)
{
assert (to->bm_byte_size == from->bm_byte_size);
memcpy (to->bm_map, from->bm_map, from->bm_byte_size);
to->bm_bit_size = from->bm_bit_size;
to->bm_set_bits = from->bm_set_bits;
+ to->bm_dirty = 1;
}
-
-int reiserfs_bitmap_compare (reiserfs_bitmap_t bm1, reiserfs_bitmap_t bm2)
+int reiserfs_bitmap_compare (reiserfs_bitmap_t * bm1, reiserfs_bitmap_t * bm2)
{
int bytes, bits;
- int i, diff;
+ long unsigned i, diff;
assert (bm1->bm_byte_size == bm2->bm_byte_size &&
bm1->bm_bit_size == bm2->bm_bit_size);
@@ -82,50 +90,70 @@ int reiserfs_bitmap_compare (reiserfs_bitmap_t bm1, reiserfs_bitmap_t bm2)
/* compare full bytes */
bytes = bm1->bm_bit_size / 8;
+ bits = bytes * 8;
if (memcmp (bm1->bm_map, bm2->bm_map, bytes)) {
- for (i = 0; i < bytes; i ++)
- if (bm1->bm_map [i] != bm2->bm_map[i]) {
- printf ("byte %d: bm1: %x bm2 %x\n", i, bm1->bm_map[i], bm2->bm_map[i]);
+ for (i = 0; i < bits; i ++)
+ if (reiserfs_bitmap_test_bit(bm1, i) != reiserfs_bitmap_test_bit(bm2, i))
diff ++;
- }
}
-
+
/* compare last byte of bitmap which can be used partially */
bits = bm1->bm_bit_size % 8;
- if (bits) {
- int mask;
+ for (i = bm1->bm_bit_size / 8 * 8; i < bm1->bm_bit_size / 8 * 8 + bits; i ++)
+ if (reiserfs_bitmap_test_bit(bm1, i) != reiserfs_bitmap_test_bit(bm2, i))
+ diff ++;
+
+/* int mask;
mask = 255 >> (8 - bits);
if ((bm1->bm_map [bytes] & mask) != (bm2->bm_map [bytes] & mask)) {
- printf ("last byte %d: bm1: %x bm2 %x\n", bytes, bm1->bm_map[bytes], bm2->bm_map[bytes]);
diff ++;
}
- }
+ }*/
return diff;
}
-void reiserfs_bitmap_set_bit (reiserfs_bitmap_t bm, unsigned int bit_number)
+void reiserfs_bitmap_disjunction (reiserfs_bitmap_t * to, reiserfs_bitmap_t * from)
+{
+ int i;
+
+ assert (to->bm_byte_size == from->bm_byte_size &&
+ to->bm_bit_size == from->bm_bit_size);
+
+ for (i = 0; i < to->bm_bit_size; i++) {
+ if (test_bit(i, from->bm_map) && !test_bit(i, to->bm_map)) {
+ set_bit(i, to->bm_map);
+ to->bm_set_bits ++;
+ to->bm_dirty = 1;
+ }
+ }
+}
+
+
+void reiserfs_bitmap_set_bit (reiserfs_bitmap_t * bm, unsigned int bit_number)
{
assert(bit_number < bm->bm_bit_size);
if (test_bit (bit_number, bm->bm_map))
return;
set_bit(bit_number, bm->bm_map);
bm->bm_set_bits ++;
+ bm->bm_dirty = 1;
}
-void reiserfs_bitmap_clear_bit (reiserfs_bitmap_t bm, unsigned int bit_number)
+void reiserfs_bitmap_clear_bit (reiserfs_bitmap_t * bm, unsigned int bit_number)
{
assert(bit_number < bm->bm_bit_size);
if (!test_bit (bit_number, bm->bm_map))
return;
clear_bit (bit_number, bm->bm_map);
bm->bm_set_bits --;
+ bm->bm_dirty = 1;
}
-int reiserfs_bitmap_test_bit (reiserfs_bitmap_t bm, unsigned int bit_number)
+int reiserfs_bitmap_test_bit (reiserfs_bitmap_t * bm, unsigned int bit_number)
{
if (bit_number >= bm->bm_bit_size)
printf ("bit %u, bitsize %lu\n", bit_number, bm->bm_bit_size);
@@ -134,19 +162,19 @@ int reiserfs_bitmap_test_bit (reiserfs_bitmap_t bm, unsigned int bit_number)
}
-int reiserfs_bitmap_zeros (reiserfs_bitmap_t bm)
+int reiserfs_bitmap_zeros (reiserfs_bitmap_t * bm)
{
return bm->bm_bit_size - bm->bm_set_bits;
}
-int reiserfs_bitmap_ones (reiserfs_bitmap_t bm)
+int reiserfs_bitmap_ones (reiserfs_bitmap_t * bm)
{
return bm->bm_set_bits;
}
-int reiserfs_bitmap_find_zero_bit (reiserfs_bitmap_t bm, unsigned long * start)
+int reiserfs_bitmap_find_zero_bit (reiserfs_bitmap_t * bm, unsigned long * start)
{
unsigned int bit_nr = *start;
assert(*start < bm->bm_bit_size);
@@ -162,31 +190,57 @@ int reiserfs_bitmap_find_zero_bit (reiserfs_bitmap_t bm, unsigned long * start)
}
-/* copy reiserfs filesystem bitmap into memory bitmap */
-int reiserfs_fetch_disk_bitmap (reiserfs_bitmap_t bm, reiserfs_filsys_t fs)
+/* read every bitmap block and copy their content into bitmap 'bm' */
+static int reiserfs_fetch_ondisk_bitmap (reiserfs_bitmap_t * bm, reiserfs_filsys_t * fs)
{
+ unsigned long to_copy;
+ int copied;
int i;
- int bytes;
char * p;
- int unused_bits;
+ int last_byte_unused_bits;
+ unsigned long block;
+ struct buffer_head * bh;
+
- reiserfs_warning (stderr, "Fetching on-disk bitmap..");
- assert (bm->bm_bit_size == SB_BLOCK_COUNT (fs));
+ to_copy = (get_sb_block_count (fs->fs_ondisk_sb) + 7) / 8;
- bytes = fs->s_blocksize;
+ /*reiserfs_warning (stderr, "Fetching on-disk bitmap..");*/
+ assert (bm->bm_byte_size == to_copy);
+
+ copied = fs->fs_blocksize;
p = bm->bm_map;
- for (i = 0; i < SB_BMAP_NR (fs); i ++) {
- if ((i == (SB_BMAP_NR (fs) - 1)) && bm->bm_byte_size % fs->s_blocksize)
- bytes = bm->bm_byte_size % fs->s_blocksize;
+ block = fs->fs_super_bh->b_blocknr + 1;
+
+ while (to_copy) {
+ bh = bread (fs->fs_dev, block, fs->fs_blocksize);
+ if (!bh) {
+ reiserfs_warning (stderr, "reiserfs_fetch_ondisk_bitmap: "
+ "bread failed reading bitmap (%lu)\n", block);
+ bh = getblk (fs->fs_dev, block, fs->fs_blocksize);
+ if (!bh)
+ reiserfs_panic ("reiserfs_fetch_ondisk_bitmap: getblk failed");
+ memset (bh->b_data, 0xff, bh->b_size);
+ mark_buffer_uptodate (bh, 1);
+ }
- memcpy (p, SB_AP_BITMAP (fs)[i]->b_data, bytes);
- p += bytes;
+ if (to_copy < fs->fs_blocksize)
+ copied = to_copy;
+ memcpy (p, bh->b_data, copied);
+ brelse (bh);
+ p += copied;
+ to_copy -= copied;
+
+ /* next bitmap block */
+ if (spread_bitmaps (fs))
+ block = (block / (fs->fs_blocksize * 8) + 1) * (fs->fs_blocksize * 8);
+ else
+ block ++;
}
/* on disk bitmap has bits out of SB_BLOCK_COUNT set to 1, where as
reiserfs_bitmap_t has those bits set to 0 */
- unused_bits = bm->bm_byte_size * 8 - bm->bm_bit_size;
- for (i = 0; i < unused_bits; i ++)
+ last_byte_unused_bits = bm->bm_byte_size * 8 - bm->bm_bit_size;
+ for (i = 0; i < last_byte_unused_bits; i ++)
clear_bit (bm->bm_bit_size + i, bm->bm_map);
bm->bm_set_bits = 0;
@@ -194,59 +248,97 @@ int reiserfs_fetch_disk_bitmap (reiserfs_bitmap_t bm, reiserfs_filsys_t fs)
for (i = 0; i < bm->bm_bit_size; i ++)
if (reiserfs_bitmap_test_bit (bm, i))
bm->bm_set_bits ++;
-
- /* unused part of last bitmap block is filled with 0s */
- if (bm->bm_bit_size % (fs->s_blocksize * 8))
- for (i = SB_BLOCK_COUNT (fs) % (fs->s_blocksize * 8); i < fs->s_blocksize * 8; i ++)
- if (!test_bit (i, SB_AP_BITMAP (fs)[SB_BMAP_NR (fs) - 1]->b_data)) {
- reiserfs_warning (stderr, "fetch_bitmap: on-disk bitmap is not padded properly\n");
- break;
- }
- reiserfs_warning (stderr, "done\n");
+ bm->bm_dirty = 0;
return 0;
}
-/* copy bitmap to buffers which hold on-disk bitmap */
-int reiserfs_flush_bitmap (reiserfs_bitmap_t bm, reiserfs_filsys_t fs)
+/* copy bitmap 'bm' to buffers which hold on-disk bitmap if bitmap was ever
+ changed and return 1. Otherwise - return 0 */
+int reiserfs_flush_to_ondisk_bitmap (reiserfs_bitmap_t * bm, reiserfs_filsys_t * fs)
{
+ unsigned long to_copy;
+ int copied;
int i;
- int bytes;
char * p;
+ int last_byte_unused_bits;
+ unsigned long block;
+ struct buffer_head * bh;
- bytes = fs->s_blocksize;
- p = bm->bm_map;
- for (i = 0; i < SB_BMAP_NR (fs); i ++) {
- if ((i == (SB_BMAP_NR (fs) - 1)) && (bm->bm_byte_size % fs->s_blocksize))
- bytes = bm->bm_byte_size % fs->s_blocksize;
- memcpy (SB_AP_BITMAP (fs)[i]->b_data, p, bytes);
- mark_buffer_dirty (SB_AP_BITMAP (fs)[i]);
-
- p += bytes;
+ /* make sure that the device is big enough */
+ bh = bread (fs->fs_dev, bm->bm_bit_size - 1, fs->fs_blocksize);
+ if (!bh) {
+ reiserfs_warning (stderr, "reiserfs_flush_to_ondisk_bitmap: bread failed for block %lu\n",
+ bm->bm_bit_size - 1);
+/*
+ bh = getblk (fs->fs_dev, bm->bm_bit_size - 1, fs->fs_blocksize);
+ if (!bh)
+ reiserfs_panic ("reiserfs_flush_to_ondisk_bitmap: getblk failed");
+ mark_buffer_uptodate (bh, 1);
+ mark_buffer_dirty (bh);
+ bwrite (bh);*/
}
+ brelse (bh);
- /* unused part of last bitmap block is filled with 0s */
- if (bm->bm_bit_size % (fs->s_blocksize * 8))
- for (i = bm->bm_bit_size % (fs->s_blocksize * 8); i < fs->s_blocksize * 8; i ++)
- set_bit (i, SB_AP_BITMAP (fs)[SB_BMAP_NR (fs) - 1]->b_data);
+ if (!bm->bm_dirty)
+ return 0;
- return 0;
+ to_copy = bm->bm_byte_size;
+
+ copied = fs->fs_blocksize;
+ p = bm->bm_map;
+ block = fs->fs_super_bh->b_blocknr + 1;
+
+ while (to_copy) {
+ /* we bread to make sure that filesystem contains enough blocks */
+ bh = getblk (fs->fs_dev, block, fs->fs_blocksize);
+ if (!bh)
+ reiserfs_panic ("reiserfs_flush_to_ondisk_bitmap: "
+ "getblk failed for (%lu)\n", block);
+ memset (bh->b_data, 0xff, bh->b_size);
+ mark_buffer_uptodate (bh, 1);
+
+ if (to_copy < fs->fs_blocksize)
+ copied = to_copy;
+ memcpy (bh->b_data, p, copied);
+ if (copied == to_copy) {
+ /* set unused bits of last byte of a bitmap to 1 */
+ last_byte_unused_bits = bm->bm_byte_size * 8 - bm->bm_bit_size;
+ for (i = 0; i < last_byte_unused_bits; i ++)
+ set_bit ((bm->bm_bit_size % (fs->fs_blocksize * 8)) + i, bh->b_data);
+ }
+ mark_buffer_dirty (bh);
+ brelse (bh);
+ p += copied;
+ to_copy -= copied;
+
+ /* next bitmap block */
+ if (spread_bitmaps (fs))
+ block = (block / (fs->fs_blocksize * 8) + 1) * (fs->fs_blocksize * 8);
+ else
+ block ++;
+ }
+
+
+ return 1;
}
-void reiserfs_bitmap_zero (reiserfs_bitmap_t bm)
+void reiserfs_bitmap_zero (reiserfs_bitmap_t * bm)
{
memset (bm->bm_map, 0, bm->bm_byte_size);
bm->bm_set_bits = 0;
+ bm->bm_dirty = 1;
}
-void reiserfs_bitmap_fill (reiserfs_bitmap_t bm)
+void reiserfs_bitmap_fill (reiserfs_bitmap_t * bm)
{
memset (bm->bm_map, 0xff, bm->bm_byte_size);
bm->bm_set_bits = bm->bm_bit_size;
+ bm->bm_dirty = 1;
}
@@ -260,23 +352,47 @@ void reiserfs_bitmap_fill (reiserfs_bitmap_t bm)
#define BITMAP_START_MAGIC 374031
#define BITMAP_END_MAGIC 7786472
-void reiserfs_bitmap_save (char * filename, reiserfs_bitmap_t bm)
+
+FILE * open_file (char * filename, char * option)
+{
+ FILE * fp = fopen (filename, option);
+ if (!fp) {
+ reiserfs_warning (stderr, "open_file: could not open file %s\n", filename);
+ return 0;
+ }
+ reiserfs_warning (stderr, "Temp file opened by fsck: \"%s\" .. \n", filename);
+ return fp;
+}
+
+
+void close_file (FILE * fp)
{
- FILE * fp;
+ fclose (fp);
+ /*reiserfs_warning (stderr, "done\n"); fflush (stderr);*/
+}
+
+
+void reiserfs_bitmap_save (FILE * fp, reiserfs_bitmap_t * bm)
+{
+// FILE * fp;
__u32 v;
int zeros;
int count;
int i;
int extents;
-
- fp = fopen (filename, "w+");
+ long position;
+
+ /* fp = fopen (filename, "w+");
if (!fp) {
reiserfs_warning (stderr, "reiserfs_bitmap_save: could not save bitmap in %s: %m",
filename);
return;
- }
+ }*/
+
- reiserfs_warning (stderr, "Saving bitmap in \"%s\" .. ", filename); fflush (stderr);
+// reiserfs_warning (stderr, "Saving bitmap in \"%s\" .. ", filename); fflush (stderr);
+
+
v = BITMAP_START_MAGIC;
fwrite (&v, 4, 1, fp);
@@ -286,10 +402,11 @@ void reiserfs_bitmap_save (char * filename, reiserfs_bitmap_t bm)
/*printf ("SAVE: bit_size - %d\n", v);*/
+ position = ftell(fp);
if (fseek (fp, 4, SEEK_CUR)) {
reiserfs_warning (stderr, "reiserfs_bitmap_save: fseek failed: %m\n");
- fclose (fp);
+// fclose (fp);
return;
}
@@ -338,42 +455,106 @@ void reiserfs_bitmap_save (char * filename, reiserfs_bitmap_t bm)
v = BITMAP_END_MAGIC;
fwrite (&v, 4, 1, fp);
- if (fseek (fp, 8, SEEK_SET)) {
+ if (fseek (fp, position, SEEK_SET)) {
reiserfs_warning (stderr, "reiserfs_bitmap_save: fseek failed: %m");
- fclose (fp);
return;
}
fwrite (&extents, 4, 1, fp);
- /*printf ("SAVE: extents %d\n", extents);*/
-
- fclose (fp);
- reiserfs_warning (stderr, "done\n"); fflush (stderr);
+ if (fseek (fp, 0, SEEK_END)) {
+ reiserfs_warning (stderr, "reiserfs_bitmap_save: fseek failed: %m");
+ return;
+ }
+}
+
+
+/* format of fsck dump file:
+ after pass0
+ magic number (32 bits)
+ passed stage number
+ bitmap of leaves
+ bitmap of good_unfm
+ bitmap of bad_unfm
+ magic number (32 bits) */
+
+#define FSCK_DUMP_START_MAGIC 374033
+#define FSCK_DUMP_END_MAGIC 7786470
+
+
+void reiserfs_begin_stage_info_save(FILE * file, unsigned long stage)
+{
+ __u32 v = FSCK_DUMP_START_MAGIC;
+ fwrite (&v, 4, 1, file);
+ fwrite (&stage, 4, 1, file);
+}
+
+
+void reiserfs_end_stage_info_save(FILE * file)
+{
+ __u32 v = FSCK_DUMP_END_MAGIC;
+ fwrite (&v, 4, 1, file);
+}
+
+
+/*return last passed stage*/
+int is_stage_magic_correct (FILE * fp)
+{
+ __u32 v;
+
+ if (fseek (fp, -4, SEEK_END)) {
+ reiserfs_warning (stderr, "is_stage_magic_correct: fseek failed: %m\n");
+ return -1;
+ }
+
+ fread (&v, 4, 1, fp);
+ if (v != FSCK_DUMP_END_MAGIC) {
+ reiserfs_warning (stderr, "is_stage_magic_correct: no magic found\n");
+ return -1;
+ }
+
+ if (fseek (fp, 0, SEEK_SET)) {
+ reiserfs_warning (stderr, "is_stage_magic_correct: fseek failed: %m\n");
+ return -1;
+ }
+
+ fread (&v, 4, 1, fp);
+ if (v != FSCK_DUMP_START_MAGIC) {
+ reiserfs_warning (stderr, "is_stage_magic_correct: no magic found\n");
+ return -1;
+ }
+
+ fread (&v, 4, 1, fp);
+ if (v != PASS_0_DONE && v != PASS_1_DONE && v != TREE_IS_BUILT && v != SEMANTIC_DONE && v != LOST_FOUND_DONE) {
+ reiserfs_warning (stderr, "is_stage_magic_correct: wrong pass found");
+ return -1;
+ }
+
+ return (__u16)v;
}
-reiserfs_bitmap_t reiserfs_bitmap_load (char * filename)
+reiserfs_bitmap_t * reiserfs_bitmap_load (FILE * fp)
{
- FILE * fp;
+// FILE * fp;
__u32 v;
int count;
int i, j;
int extents;
int bit;
- reiserfs_bitmap_t bm;
+ reiserfs_bitmap_t * bm;
- fp = fopen (filename, "r");
+/* fp = fopen (filename, "r");
if (!fp) {
- reiserfs_warning (stderr, "reiserfs_bitmap_load: fseek failed: %m\n");
+ reiserfs_warning (stderr, "reiserfs_bitmap_load: fopen failed: %m\n");
return 0;
- }
+ }*/
fread (&v, 4, 1, fp);
if (v != BITMAP_START_MAGIC) {
reiserfs_warning (stderr, "reiserfs_bitmap_load: "
"no bitmap start magic found");
- fclose (fp);
+// fclose (fp);
return 0;
}
@@ -383,12 +564,10 @@ reiserfs_bitmap_t reiserfs_bitmap_load (char * filename)
bm = reiserfs_create_bitmap (v);
if (!bm) {
reiserfs_warning (stderr, "reiserfs_bitmap_load: creation failed");
- fclose (fp);
+// fclose (fp);
return 0;
}
- reiserfs_warning (stderr, "Loading bitmap from %s .. ", filename); fflush (stderr);
-
/*printf ("LOAD: bit_size - %d\n", v);*/
fread (&extents, 4, 1, fp);
@@ -414,24 +593,24 @@ reiserfs_bitmap_t reiserfs_bitmap_load (char * filename)
/*printf ("LOAD: Endmagic %d\n", v);*/
- fclose (fp);
+// fclose (fp);
if (v != BITMAP_END_MAGIC) {
reiserfs_warning (stderr, "reiserfs_bitmap_load: "
"no bitmap end magic found");
return 0;
}
- reiserfs_warning (stderr, "%d bits set - done\n", reiserfs_bitmap_ones (bm));
+ /* reiserfs_warning (stderr, "%d bits set - done\n", reiserfs_bitmap_ones (bm));*/
fflush (stderr);
return bm;
}
-void reiserfs_bitmap_invert (reiserfs_bitmap_t bm)
+void reiserfs_bitmap_invert (reiserfs_bitmap_t * bm)
{
int i;
- reiserfs_warning (stderr, "Bitmap inverting..");fflush (stderr);
+ /*reiserfs_warning (stderr, "Bitmap inverting..");fflush (stderr);*/
for (i = 0; i < bm->bm_bit_size; i ++) {
if (reiserfs_bitmap_test_bit (bm, i))
reiserfs_bitmap_clear_bit (bm, i);
@@ -439,10 +618,67 @@ void reiserfs_bitmap_invert (reiserfs_bitmap_t bm)
reiserfs_bitmap_set_bit (bm, i);
}
- reiserfs_warning (stderr, "done\n");
+ /*reiserfs_warning (stderr, "done\n");*/
}
+void reiserfs_free_ondisk_bitmap (reiserfs_filsys_t * fs)
+{
+ if (fs->fs_bitmap2) {
+ reiserfs_delete_bitmap (fs->fs_bitmap2);
+ fs->fs_bitmap2 = 0;
+ }
+}
+
+
+/* read bitmap blocks */
+int reiserfs_open_ondisk_bitmap (reiserfs_filsys_t * fs)
+{
+ struct buffer_head * bh;
+
+ if (fs->fs_bitmap2)
+ reiserfs_panic ("%s: bitmap is initiaized already", __FUNCTION__);
+ fs->fs_bitmap2 = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb));
+ if (!fs->fs_bitmap2)
+ return 0;
+
+ if ( (get_sb_block_count (fs->fs_ondisk_sb) + fs->fs_blocksize * 8 - 1) / (fs->fs_blocksize * 8) !=
+ get_sb_bmap_nr (fs->fs_ondisk_sb)) {
+ reiserfs_warning (stderr, "%s: wrong either bitmaps number,\n", __FUNCTION__);
+ reiserfs_warning (stderr, "count of blocks or blocksize, run with --rebuild-sb to fix it\n");
+ return 0;
+ }
+ bh = bread (fs->fs_dev, fs->fs_bitmap2->bm_bit_size - 1, fs->fs_blocksize);
+ if (!bh) {
+ reiserfs_warning (stderr, "%s: bread failed for block %lu\n", __FUNCTION__, fs->fs_bitmap2->bm_bit_size - 1);
+ reiserfs_warning (stderr, "\tYour partition is not big enough. Enlarge your partition or\n");
+ reiserfs_warning (stderr, "\trun reiserfsck with --rebuild-sb to fix super block.\n");
+ return 0;
+ }
+ brelse (bh);
+
+ reiserfs_fetch_ondisk_bitmap (fs->fs_bitmap2, fs);
+ return 1;
+}
+int reiserfs_create_ondisk_bitmap (reiserfs_filsys_t * fs)
+{
+ if (fs->fs_bitmap2)
+ reiserfs_panic ("create: bitmap is initiaized already");
+ fs->fs_bitmap2 = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb));
+ if (!fs->fs_bitmap2)
+ return 0;
+
+ return 1;
+}
+
+
+void reiserfs_close_ondisk_bitmap (reiserfs_filsys_t * fs)
+{
+ if (!fs->fs_bitmap2)
+ return;
+ reiserfs_flush_to_ondisk_bitmap (fs->fs_bitmap2, fs);
+ reiserfs_free_ondisk_bitmap (fs);
+}
diff --git a/reiserfscore/do_balan.c b/reiserfscore/do_balan.c
index f81ff78..f771869 100644
--- a/reiserfscore/do_balan.c
+++ b/reiserfscore/do_balan.c
@@ -18,20 +18,7 @@
#include "includes.h"
-
-#ifdef CONFIG_REISERFS_CHECK
-
-struct tree_balance * cur_tb = NULL; /* detects whether more than one copy of tb exists as a means
- of checking whether schedule is interrupting do_balance */
-struct tree_balance init_tb; /* Sometimes used to store a snapshot of tb during debugging. */
-int init_item_pos, init_pos_in_item, init_mode; /* Sometimes used to store a snapshot of tb during debugging. */
-
-
-#endif /* CONFIG_REISERFS_CHECK */
-
-
-
-/* summary:
+/* summary:
if deleting something ( tb->insert_size[0] < 0 )
return(balance_leaf_when_delete()); (flag d handled here)
else
@@ -74,18 +61,6 @@ static int balance_leaf_when_delete (/*struct reiserfs_transaction_handle *th,*/
int n;
struct item_head * ih;
-#ifdef CONFIG_REISERFS_CHECK
- if ( tb->FR[0] && B_BLK_HEAD(tb->FR[0])->blk_level <= DISK_LEAF_NODE_LEVEL )
- reiserfs_panic (tb->tb_sb,
- "balance_leaf_when_delete: 11999:level == %u\n", B_BLK_HEAD(tb->FR[0])->blk_level);
- if ( tb->blknum[0] > 1 )
- reiserfs_panic (tb->tb_sb,
- "PAP-12005: balance_leaf_when_delete: tb->blknum == %d, can not be > 1", tb->blknum[0]);
-
- if ( ! tb->blknum[0] && ! PATH_H_PPARENT(tb->tb_path, 0))
- reiserfs_panic (tb->tb_sb, "PAP-12010: balance_leaf_when_delete: tree can not be empty");
-#endif
-
ih = B_N_PITEM_HEAD (tbS0, item_pos);
/* Delete or truncate the item */
@@ -96,22 +71,16 @@ static int balance_leaf_when_delete (/*struct reiserfs_transaction_handle *th,*/
bi.bi_bh = tbS0;
bi.bi_parent = PATH_H_PPARENT (tb->tb_path, 0);
bi.bi_position = PATH_H_POSITION (tb->tb_path, 1);
- leaf_delete_items (tb->tb_sb, &bi, 0, item_pos, 1, -1);
-
-#ifdef CONFIG_REISERFS_CHECK
- if (! item_pos && !tb->CFL[0])
- reiserfs_panic (tb->tb_sb, "PAP-12020: balance_leaf_when_delete: "
- "tb->CFL[0]==0 when item_pos == 0");
-#endif
+ leaf_delete_items (tb->tb_fs, &bi, 0, item_pos, 1, -1);
if ( ! item_pos ) {
// we have removed first item in the node - update left delimiting key
if ( B_NR_ITEMS(tbS0) ) {
- replace_key(tb->tb_sb, tb->CFL[0],tb->lkey[0],tbS0,0);
+ replace_key(tb->tb_fs, tb->CFL[0],tb->lkey[0],tbS0,0);
}
else {
if ( ! PATH_H_POSITION (tb->tb_path, 1) )
- replace_key(tb->tb_sb, tb->CFL[0],tb->lkey[0],PATH_H_PPARENT(tb->tb_path, 0),0);
+ replace_key(tb->tb_fs, tb->CFL[0],tb->lkey[0],PATH_H_PPARENT(tb->tb_path, 0),0);
}
}
@@ -127,23 +96,13 @@ static int balance_leaf_when_delete (/*struct reiserfs_transaction_handle *th,*/
/* when we cut a directory tb->insert_size[0] means number
of entries to be cut (always 1) */
tb->insert_size[0] = -1;
- leaf_cut_from_buffer (tb->tb_sb, &bi, item_pos, pos_in_item, -tb->insert_size[0]);
-
-#ifdef CONFIG_REISERFS_CHECK
- if (! item_pos && ! pos_in_item && ! tb->CFL[0])
- reiserfs_panic (tb->tb_sb, "PAP-12030: balance_leaf_when_delete: can not change delimiting key. CFL[0]=%p", tb->CFL[0]);
-#endif /* CONFIG_REISERFS_CHECK */
+ leaf_cut_from_buffer (tb->tb_fs, &bi, item_pos, pos_in_item, -tb->insert_size[0]);
if ( ! item_pos && ! pos_in_item ) {
- replace_key(tb->tb_sb, tb->CFL[0],tb->lkey[0],tbS0,0);
+ replace_key(tb->tb_fs, tb->CFL[0],tb->lkey[0],tbS0,0);
}
} else {
- leaf_cut_from_buffer (tb->tb_sb, &bi, item_pos, pos_in_item, -tb->insert_size[0]);
-
-#ifdef CONFIG_REISERFS_CHECK
- if (! ih->ih_item_len)
- reiserfs_panic (tb->tb_sb, "PAP-12035: balance_leaf_when_delete: cut must leave non-zero dynamic length of item");
-#endif /* CONFIG_REISERFS_CHECK */
+ leaf_cut_from_buffer (tb->tb_fs, &bi, item_pos, pos_in_item, -tb->insert_size[0]);
}
break;
}
@@ -166,7 +125,7 @@ static int balance_leaf_when_delete (/*struct reiserfs_transaction_handle *th,*/
{
/* all contents of all the 3 buffers will be in L[0] */
if ( PATH_H_POSITION (tb->tb_path, 1) == 0 && 1 < B_NR_ITEMS(tb->FR[0]) )
- replace_key(tb->tb_sb, tb->CFL[0],tb->lkey[0],tb->FR[0],1);
+ replace_key(tb->tb_fs, tb->CFL[0],tb->lkey[0],tb->FR[0],1);
leaf_move_items (LEAF_FROM_S_TO_L, tb, n, -1, 0);
@@ -182,7 +141,7 @@ static int balance_leaf_when_delete (/*struct reiserfs_transaction_handle *th,*/
leaf_move_items(LEAF_FROM_L_TO_R, tb, B_NR_ITEMS(tb->L[0]), -1, 0);
/* right_delimiting_key is correct in R[0] */
- replace_key(tb->tb_sb, tb->CFR[0],tb->rkey[0],tb->R[0],0);
+ replace_key(tb->tb_fs, tb->CFR[0],tb->rkey[0],tb->R[0],0);
reiserfs_invalidate_buffer (tb, tbS0, 1/*do_free_block*/);
reiserfs_invalidate_buffer (tb, tb->L[0], 1/*do_free_block*/);
@@ -190,11 +149,6 @@ static int balance_leaf_when_delete (/*struct reiserfs_transaction_handle *th,*/
return -1;
}
-#ifdef CONFIG_REISERFS_CHECK
- if ( tb->rnum[0] != 0 )
- reiserfs_panic (tb->tb_sb, "PAP-12045: balance_leaf_when_delete: rnum must be 0 (%d)", tb->rnum[0]);
-#endif /* CONFIG_REISERFS_CHECK */
-
/* all contents of L[0] and S[0] will be in L[0] */
leaf_shift_left(tb, n, -1);
@@ -204,19 +158,6 @@ static int balance_leaf_when_delete (/*struct reiserfs_transaction_handle *th,*/
}
/* a part of contents of S[0] will be in L[0] and the rest part of S[0] will be in R[0] */
-#ifdef CONFIG_REISERFS_CHECK
- if (( tb->lnum[0] + tb->rnum[0] < n ) || ( tb->lnum[0] + tb->rnum[0] > n+1 ))
- reiserfs_panic (tb->tb_sb, "PAP-12050: balance_leaf_when_delete: rnum(%d) and lnum(%d) and item number in S[0] are not consistent",
- tb->rnum[0], tb->lnum[0], n);
-
- if (( tb->lnum[0] + tb->rnum[0] == n ) && (tb->lbytes != -1 || tb->rbytes != -1))
- reiserfs_panic (tb->tb_sb, "PAP-12055: balance_leaf_when_delete: bad rbytes (%d)/lbytes (%d) parameters when items are not split",
- tb->rbytes, tb->lbytes);
- if (( tb->lnum[0] + tb->rnum[0] == n + 1 ) && (tb->lbytes < 1 || tb->rbytes != -1))
- reiserfs_panic (tb->tb_sb, "PAP-12060: balance_leaf_when_delete: bad rbytes (%d)/lbytes (%d) parameters when items are split",
- tb->rbytes, tb->lbytes);
-#endif
-
leaf_shift_left (tb, tb->lnum[0], tb->lbytes);
leaf_shift_right(tb, tb->rnum[0], tb->rbytes);
@@ -231,16 +172,9 @@ static int balance_leaf_when_delete (/*struct reiserfs_transaction_handle *th,*/
reiserfs_invalidate_buffer (tb, tbS0, 1/*do_free_block*/);
return 0;
}
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( tb->rnum[0] )
- reiserfs_panic (tb->tb_sb, "PAP-12065: balance_leaf_when_delete: bad rnum parameter must be 0 (%d)", tb->rnum[0]);
-#endif
-
return 0;
}
-
static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
struct tree_balance * tb, /* see reiserfs_fs.h */
struct item_head * ih, /* item header of inserted item */
@@ -299,49 +233,28 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
/* part of new item falls into L[0] */
int new_item_len;
-#ifdef CONFIG_REISERFS_CHECK
- if (!I_IS_DIRECT_ITEM (ih))
- reiserfs_panic (tb->tb_sb, "PAP-12075: balance_leaf: "
- "this item (%h) can not be split on insertion", ih);
-#endif
ret_val = leaf_shift_left (/*th,*/ tb, tb->lnum[0]-1, -1);
-
/* Calculate item length to insert to S[0] */
- new_item_len = ih->ih_item_len - tb->lbytes;
+ new_item_len = get_ih_item_len (ih) - tb->lbytes;
/* Calculate and check item length to insert to L[0] */
- ih->ih_item_len -= new_item_len;
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( (int)(ih->ih_item_len) <= 0 )
- reiserfs_panic(tb->tb_sb, "PAP-12080: balance_leaf: "
- "there is nothing to insert into L[0]: ih_item_len=%d",
- (int)ih->ih_item_len);
-#endif
-
+ set_ih_item_len (ih, get_ih_item_len (ih) - new_item_len);
/* Insert new item into L[0] */
bi.bi_bh = tb->L[0];
bi.bi_parent = tb->FL[0];
bi.bi_position = get_left_neighbor_position (tb, 0);
- leaf_insert_into_buf (tb->tb_sb, &bi, n + item_pos - ret_val, ih, body,
- zeros_number > ih->ih_item_len ? ih->ih_item_len : zeros_number);
+ leaf_insert_into_buf (tb->tb_fs, &bi, n + item_pos - ret_val, ih, body,
+ zeros_number > get_ih_item_len (ih) ? get_ih_item_len (ih) : zeros_number);
/* Calculate key component, item length and body to insert into S[0] */
//ih->ih_key.k_offset += tb->lbytes;
set_offset (key_format (&ih->ih_key), &ih->ih_key, get_offset (&ih->ih_key) + tb->lbytes);
- ih->ih_item_len = new_item_len;
+ set_ih_item_len (ih, new_item_len);
if ( tb->lbytes > zeros_number ) {
body += (tb->lbytes - zeros_number);
zeros_number = 0;
}
else
zeros_number -= tb->lbytes;
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( (int)(ih->ih_item_len) <= 0 )
- reiserfs_panic(tb->tb_sb, "PAP-12085: balance_leaf: "
- "there is nothing to insert into S[0]: ih_item_len=%d",
- (int)ih->ih_item_len);
-#endif
} else {
/* new item in whole falls into L[0] */
/* Shift lnum[0]-1 items to L[0] */
@@ -351,7 +264,7 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
bi.bi_bh = tb->L[0];
bi.bi_parent = tb->FL[0];
bi.bi_position = get_left_neighbor_position (tb, 0);
- leaf_insert_into_buf (tb->tb_sb, &bi, n + item_pos - ret_val, ih, body, zeros_number);
+ leaf_insert_into_buf (tb->tb_fs, &bi, n + item_pos - ret_val, ih, body, zeros_number);
tb->insert_size[0] = 0;
zeros_number = 0;
@@ -363,12 +276,6 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
if ( item_pos == tb->lnum[0] - 1 && tb->lbytes != -1 ) {
/* we must shift the part of the appended item */
if ( I_IS_DIRECTORY_ITEM (B_N_PITEM_HEAD (tbS0, item_pos))) {
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( zeros_number )
- reiserfs_panic(tb->tb_sb, "PAP-12090: balance_leaf: illegal parameter in case of a directory");
-#endif
-
/* directory item */
if ( tb->lbytes > pos_in_item ) {
/* new directory entry falls into L[0] */
@@ -379,14 +286,14 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
ret_val = leaf_shift_left(tb, tb->lnum[0], tb->lbytes - 1);
if ( ret_val && ! item_pos ) {
pasted = B_N_PITEM_HEAD(tb->L[0],B_NR_ITEMS(tb->L[0])-1);
- l_pos_in_item += ih_entry_count(pasted) - (tb->lbytes-1);
+ l_pos_in_item += get_ih_entry_count(pasted) - (tb->lbytes-1);
}
/* Append given directory entry to directory item */
bi.bi_bh = tb->L[0];
bi.bi_parent = tb->FL[0];
bi.bi_position = get_left_neighbor_position (tb, 0);
- leaf_paste_in_buffer (tb->tb_sb, &bi, n + item_pos - ret_val, l_pos_in_item,
+ leaf_paste_in_buffer (tb->tb_fs, &bi, n + item_pos - ret_val, l_pos_in_item,
tb->insert_size[0], body, zeros_number);
/* previous string prepared space for pasting new entry, following string pastes this entry */
@@ -409,18 +316,6 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
}
else {
/* regular object */
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( tb->lbytes <= 0 )
- reiserfs_panic(tb->tb_sb, "PAP-12095: balance_leaf: "
- "there is nothing to shift to L[0]. lbytes=%d",
- tb->lbytes);
- if ( pos_in_item != B_N_PITEM_HEAD(tbS0, item_pos)->ih_item_len )
- reiserfs_panic(tb->tb_sb, "PAP-12100: balance_leaf: "
- "incorrect position to paste: item_len=%d, pos_in_item=%d",
- B_N_PITEM_HEAD(tbS0,item_pos)->ih_item_len, pos_in_item);
-#endif
-
if ( tb->lbytes >= pos_in_item ) {
/* appended item will be in L[0] in whole */
int l_n;
@@ -432,34 +327,19 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
/* Calculate new insert_size[0] */
tb->insert_size[0] -= l_n;
-#ifdef CONFIG_REISERFS_CHECK
- if ( tb->insert_size[0] <= 0 )
- reiserfs_panic(tb->tb_sb, "PAP-12105: balance_leaf: "
- "there is nothing to paste into L[0]. insert_size=%d",
- tb->insert_size[0]);
-#endif
-
- ret_val = leaf_shift_left(tb, tb->lnum[0],
- B_N_PITEM_HEAD(tbS0,item_pos)->ih_item_len);
+ ret_val = leaf_shift_left(tb, tb->lnum[0],
+ get_ih_item_len (B_N_PITEM_HEAD(tbS0,item_pos)));
/* Append to body of item in L[0] */
bi.bi_bh = tb->L[0];
bi.bi_parent = tb->FL[0];
bi.bi_position = get_left_neighbor_position (tb, 0);
- leaf_paste_in_buffer(tb->tb_sb,
+ leaf_paste_in_buffer(tb->tb_fs,
&bi,n + item_pos - ret_val,
- B_N_PITEM_HEAD(tb->L[0],n+item_pos-ret_val)->ih_item_len,
- l_n,body, zeros_number > l_n ? l_n : zeros_number
- );
-
-#ifdef CONFIG_REISERFS_CHECK
- if (l_n && I_IS_INDIRECT_ITEM(B_N_PITEM_HEAD(tb->L[0],
- n + item_pos - ret_val)))
- reiserfs_panic(tb->tb_sb, "PAP-12110: balance_leaf: "
- "pasting more than 1 unformatted node pointer into indirect item");
-#endif
+ get_ih_item_len (B_N_PITEM_HEAD(tb->L[0],n+item_pos-ret_val)),
+ l_n,body, zeros_number > l_n ? l_n : zeros_number);
/* 0-th item in S0 can be only of DIRECT type when l_n != 0*/
- //B_N_PKEY (tbS0, 0)->k_offset += l_n;
+ //B_N_PKEY (tbS0, 0)->k_offset += l_n;z
key = B_N_PKEY (tbS0, 0);
set_offset (key_format (key), key, get_offset (key) + l_n);
@@ -475,16 +355,6 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
else
zeros_number -= l_n;
pos_in_item = 0;
-
-#ifdef CONFIG_REISERFS_CHECK
- if (not_of_one_file (B_N_PKEY(tbS0,0),
- B_N_PKEY(tb->L[0],B_NR_ITEMS(tb->L[0])-1)) ||
- !is_left_mergeable (B_N_PITEM_HEAD (tbS0, 0), tbS0->b_size) ||
- !is_left_mergeable((struct item_head *)B_N_PDELIM_KEY(tb->CFL[0],tb->lkey[0]), tbS0->b_size))
- reiserfs_panic (tb->tb_sb, "PAP-12120: balance_leaf: "
- "item must be merge-able with left neighboring item");
-#endif
-
}
else {
/* only part of the appended item will be in L[0] */
@@ -492,12 +362,6 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
/* Calculate position in item for append in S[0] */
pos_in_item -= tb->lbytes;
-#ifdef CONFIG_REISERFS_CHECK
- if ( pos_in_item <= 0 )
- reiserfs_panic(tb->tb_sb, "PAP-12125: balance_leaf: "
- "no place for paste. pos_in_item=%d", pos_in_item);
-#endif
-
/* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */
leaf_shift_left(tb,tb->lnum[0],tb->lbytes);
}
@@ -505,20 +369,15 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
} else {
/* appended item will be in L[0] in whole */
struct item_head * pasted;
-
-#ifndef FU//REISERFS_FSCK
- // this works
- if ( ! item_pos && is_left_mergeable (tb->tb_sb, tb->tb_path) == 1 )
-#else
- if ( ! item_pos && is_left_mergeable (B_N_PITEM_HEAD (tbS0, 0), tbS0->b_size) )
-#endif
+
+ if ( ! item_pos && is_left_mergeable (tb->tb_fs, tb->tb_path) == 1 )
{ /* if we paste into first item of S[0] and it is left mergable */
/* then increment pos_in_item by the size of the last item in L[0] */
pasted = B_N_PITEM_HEAD(tb->L[0],n-1);
if ( I_IS_DIRECTORY_ITEM(pasted) )
- pos_in_item += ih_entry_count (pasted);
+ pos_in_item += get_ih_entry_count (pasted);
else
- pos_in_item += pasted->ih_item_len;
+ pos_in_item += get_ih_item_len (pasted);
}
/* Shift lnum[0] - 1 items in whole. Shift lbytes - 1 byte from item number lnum[0] */
@@ -527,7 +386,7 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
bi.bi_bh = tb->L[0];
bi.bi_parent = tb->FL[0];
bi.bi_position = get_left_neighbor_position (tb, 0);
- leaf_paste_in_buffer (tb->tb_sb, &bi, n + item_pos - ret_val, pos_in_item, tb->insert_size[0],
+ leaf_paste_in_buffer (tb->tb_fs, &bi, n + item_pos - ret_val, pos_in_item, tb->insert_size[0],
body, zeros_number);
/* if appended item is directory, paste entry */
@@ -538,7 +397,7 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
/* if appended item is indirect item, put unformatted node into un list */
if (I_IS_INDIRECT_ITEM (pasted))
- set_free_space (pasted, ((struct unfm_nodeinfo*)body)->unfm_freespace);
+ set_ih_free_space (pasted, ((struct unfm_nodeinfo*)body)->unfm_freespace);
//pasted->u.ih_free_space = ((struct unfm_nodeinfo*)body)->unfm_freespace;
tb->insert_size[0] = 0;
@@ -571,23 +430,17 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
int old_key_comp, old_len, r_zeros_number;
const char * r_body;
-#ifdef CONFIG_REISERFS_CHECK
- if ( !I_IS_DIRECT_ITEM(ih) )
- reiserfs_panic(tb->tb_sb, "PAP-12135: balance_leaf: "
- "this item (%h) can not be split", ih);
-#endif
-
leaf_shift_right(tb, tb->rnum[0] - 1, -1);
/* Remember key component and item length */
old_key_comp = get_offset (&ih->ih_key);
- old_len = ih->ih_item_len;
+ old_len = get_ih_item_len (ih);
/* Calculate key component and item length to insert into R[0] */
//ih->ih_key.k_offset += (old_len - tb->rbytes);
set_offset (key_format (&ih->ih_key), &ih->ih_key, old_key_comp + old_len - tb->rbytes);
- ih->ih_item_len = tb->rbytes;
+ set_ih_item_len (ih, tb->rbytes);
/* Insert part of the item into R[0] */
bi.bi_bh = tb->R[0];
bi.bi_parent = tb->FR[0];
@@ -602,16 +455,16 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
zeros_number -= r_zeros_number;
}
- leaf_insert_into_buf (tb->tb_sb, &bi, 0, ih, r_body, r_zeros_number);
+ leaf_insert_into_buf (tb->tb_fs, &bi, 0, ih, r_body, r_zeros_number);
/* Replace right delimiting key by first key in R[0] */
- replace_key(tb->tb_sb, tb->CFR[0],tb->rkey[0],tb->R[0],0);
+ replace_key(tb->tb_fs, tb->CFR[0],tb->rkey[0],tb->R[0],0);
/* Calculate key component and item length to insert into S[0] */
//ih->ih_key.k_offset = old_key_comp;
set_offset (key_format (&ih->ih_key), &ih->ih_key, old_key_comp);
- ih->ih_item_len = old_len - tb->rbytes;
+ set_ih_item_len (ih, old_len - tb->rbytes);
tb->insert_size[0] -= tb->rbytes;
@@ -625,11 +478,11 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
bi.bi_bh = tb->R[0];
bi.bi_parent = tb->FR[0];
bi.bi_position = get_right_neighbor_position (tb, 0);
- leaf_insert_into_buf (tb->tb_sb, &bi, item_pos - n + tb->rnum[0] - 1, ih, body, zeros_number);
+ leaf_insert_into_buf (tb->tb_fs, &bi, item_pos - n + tb->rnum[0] - 1, ih, body, zeros_number);
/* If we insert new item in the begin of R[0] change the right delimiting key */
if ( item_pos - n + tb->rnum[0] - 1 == 0 ) {
- replace_key (tb->tb_sb, tb->CFR[0],tb->rkey[0],tb->R[0],0);
+ replace_key (tb->tb_fs, tb->CFR[0],tb->rkey[0],tb->R[0],0);
}
zeros_number = tb->insert_size[0] = 0;
}
@@ -648,24 +501,11 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
/* we append to directory item */
int entry_count;
-#ifdef CONFIG_REISERFS_CHECK
- if ( zeros_number )
- reiserfs_panic(tb->tb_sb, "PAP-12145: balance_leaf: "
- "illegal parameter in case of a directory");
-#endif
-
- entry_count = ih_entry_count (B_N_PITEM_HEAD(tbS0, item_pos));
+ entry_count = get_ih_entry_count (B_N_PITEM_HEAD(tbS0, item_pos));
if ( entry_count - tb->rbytes < pos_in_item ) {
/* new directory entry falls into R[0] */
int paste_entry_position;
-#ifdef CONFIG_REISERFS_CHECK
- if ( tb->rbytes - 1 >= entry_count || ! tb->insert_size[0] )
- reiserfs_panic(tb->tb_sb, "PAP-12150: balance_leaf: "
- "no enough of entries to shift to R[0]: rbytes=%d, entry_count=%d",
- tb->rbytes, entry_count);
-#endif
-
/* Shift rnum[0]-1 items in whole. Shift rbytes-1 directory entries from directory item number rnum[0] */
leaf_shift_right (tb, tb->rnum[0], tb->rbytes - 1);
@@ -675,7 +515,7 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
bi.bi_bh = tb->R[0];
bi.bi_parent = tb->FR[0];
bi.bi_position = get_right_neighbor_position (tb, 0);
- leaf_paste_in_buffer (tb->tb_sb, &bi, 0, paste_entry_position,
+ leaf_paste_in_buffer (tb->tb_fs, &bi, 0, paste_entry_position,
tb->insert_size[0],body,zeros_number);
/* paste entry */
leaf_paste_entries (
@@ -685,7 +525,7 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
if ( paste_entry_position == 0 ) {
/* change delimiting keys */
- replace_key(tb->tb_sb, tb->CFR[0],tb->rkey[0],tb->R[0],0);
+ replace_key(tb->tb_fs, tb->CFR[0],tb->rkey[0],tb->R[0],0);
}
tb->insert_size[0] = 0;
@@ -706,12 +546,6 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
if ( (n_shift = tb->rbytes - tb->insert_size[0]) < 0 )
n_shift = 0;
-#ifdef CONFIG_REISERFS_CHECK
- if (pos_in_item != B_N_PITEM_HEAD (tbS0, item_pos)->ih_item_len)
- reiserfs_panic(tb->tb_sb,"PAP-12155: balance_leaf: invalid position %d to paste item %h",
- pos_in_item, B_N_PITEM_HEAD(tbS0,item_pos));
-#endif
-
leaf_shift_right (tb, tb->rnum[0], n_shift);
/* Calculate number of bytes which must remain in body after appending to R[0] */
@@ -742,16 +576,10 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
zeros_number -= r_zeros_number;
}
- leaf_paste_in_buffer(tb->tb_sb, &bi, 0, n_shift, tb->insert_size[0] - n_rem, r_body, r_zeros_number);
+ leaf_paste_in_buffer(tb->tb_fs, &bi, 0, n_shift, tb->insert_size[0] - n_rem, r_body, r_zeros_number);
if (I_IS_INDIRECT_ITEM(B_N_PITEM_HEAD(tb->R[0],0))) {
-
-#ifdef CONFIG_REISERFS_CHECK
- if (n_rem)
- reiserfs_panic(tb->tb_sb, "PAP-12160: balance_leaf: paste more than one unformatted node pointer");
-#endif
-
- set_free_space (B_N_PITEM_HEAD(tb->R[0],0), ((struct unfm_nodeinfo*)body)->unfm_freespace);
+ set_ih_free_space (B_N_PITEM_HEAD(tb->R[0],0), ((struct unfm_nodeinfo*)body)->unfm_freespace);
//B_N_PITEM_HEAD(tb->R[0],0)->u.ih_free_space = ((struct unfm_nodeinfo*)body)->unfm_freespace;
}
@@ -772,7 +600,7 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
bi.bi_bh = tb->R[0];
bi.bi_parent = tb->FR[0];
bi.bi_position = get_right_neighbor_position (tb, 0);
- leaf_paste_in_buffer(tb->tb_sb, &bi,item_pos - n + tb->rnum[0], pos_in_item,
+ leaf_paste_in_buffer(tb->tb_fs, &bi,item_pos - n + tb->rnum[0], pos_in_item,
tb->insert_size[0],body, zeros_number);
}
@@ -782,21 +610,14 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
leaf_paste_entries (bi.bi_bh, item_pos - n + tb->rnum[0], pos_in_item, 1,
(struct reiserfs_de_head *)body, body + DEH_SIZE, tb->insert_size[0]);
if ( ! pos_in_item ) {
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( item_pos - n + tb->rnum[0] )
- reiserfs_panic (tb->tb_sb, "PAP-12165: balance_leaf: "
- "directory item must be first item of node when pasting is in 0th position");
-#endif
-
/* update delimiting keys */
- replace_key (tb->tb_sb, tb->CFR[0],tb->rkey[0],tb->R[0],0);
+ replace_key (tb->tb_fs, tb->CFR[0],tb->rkey[0],tb->R[0],0);
}
}
if (I_IS_INDIRECT_ITEM (pasted))
//pasted->u.ih_free_space = ((struct unfm_nodeinfo*)body)->unfm_freespace;
- set_free_space (pasted, ((struct unfm_nodeinfo*)body)->unfm_freespace);
+ set_ih_free_space (pasted, ((struct unfm_nodeinfo*)body)->unfm_freespace);
zeros_number = tb->insert_size[0] = 0;
}
}
@@ -813,34 +634,20 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
} /* tb->rnum[0] > 0 */
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( tb->blknum[0] > 3 )
- reiserfs_panic (tb->tb_sb, "PAP-12180: balance_leaf: "
- "blknum can not be %d. It must be <= 3", tb->blknum[0]);
-
- if ( tb->blknum[0] < 0 )
- reiserfs_panic (tb->tb_sb, "PAP-12185: balance_leaf: "
- "blknum can not be %d. It must be >= 0", tb->blknum[0]);
-
- if ( tb->blknum[0] == 0 && (! tb->lnum[0] || ! tb->rnum[0]) )
- reiserfs_panic(tb->tb_sb, "PAP-12190: balance_leaf: lnum and rnum must not be zero");
-#endif
-
/* if while adding to a node we discover that it is possible to split
it in two, and merge the left part into the left neighbor and the
right part into the right neighbor, eliminating the node */
if ( tb->blknum[0] == 0 ) { /* node S[0] is empty now */
-
-#ifdef CONFIG_REISERFS_CHECK
- if (!tb->CFL[0] || !tb->CFR[0] || !tb->R[0] || !tb->R[0] ||
- COMP_KEYS (B_N_PDELIM_KEY (tb->CFR[0], tb->rkey[0]),
- B_N_PKEY (tb->R[0], 0)))
- reiserfs_panic (tb->tb_sb, "vs-12195: balance_leaf: "
- "right delim key (%k) is not set properly (%k)",
- B_N_PDELIM_KEY (tb->CFR[0], tb->rkey[0]), B_N_PKEY (tb->R[0], 0));
-#endif
-
+ /* if insertion was done before 0-th position in R[0], right
+ delimiting key of the tb->L[0]'s and left delimiting key are
+ not set correctly */
+ if (tb->CFL[0]) {
+ if (!tb->CFR[0])
+ reiserfs_panic (tb->tb_fs, "vs-12195: balance_leaf: CFR not initialized");
+ copy_key (B_N_PDELIM_KEY (tb->CFL[0], tb->lkey[0]), B_N_PDELIM_KEY (tb->CFR[0], tb->rkey[0]));
+ mark_buffer_dirty (tb->CFL[0]);
+ }
+
reiserfs_invalidate_buffer(tb,tbS0, 1);
return 0;
}
@@ -855,18 +662,11 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
sbytes[0] = tb->s1bytes;
sbytes[1] = tb->s2bytes;
for( i = tb->blknum[0] - 2; i >= 0; i-- ) {
-
-#ifdef CONFIG_REISERFS_CHECK
- if (!snum[i])
- reiserfs_panic(tb->tb_sb,"PAP-12200: balance_leaf: snum[%d] == %d. Must be > 0", i, snum[i]);
-#endif /* CONFIG_REISERFS_CHECK */
-
/* here we shift from S to S_new nodes */
-
S_new[i] = get_FEB(tb);
- /* set block level */
- set_leaf_node_level (S_new[i]);
+ /* set block_head's level to leaf level */
+ set_blkh_level (B_BLK_HEAD (S_new[i]), DISK_LEAF_NODE_LEVEL);
n = B_NR_ITEMS(tbS0);
@@ -880,29 +680,18 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
int old_key_comp, old_len, r_zeros_number;
const char * r_body;
-#ifdef CONFIG_REISERFS_CHECK
- if ( !I_IS_DIRECT_ITEM(ih) )
- /* The items which can be inserted are: Stat_data
- item, direct item, indirect item and directory item
- which consist of only two entries "." and "..".
- These items must not be broken except for a direct
- one. */
- reiserfs_panic(tb->tb_sb, "PAP-12205: balance_leaf: "
- "this item %h can not be broken when inserting", ih);
-#endif
-
/* Move snum[i]-1 items from S[0] to S_new[i] */
leaf_move_items (LEAF_FROM_S_TO_SNEW, tb, snum[i] - 1, -1, S_new[i]);
/* Remember key component and item length */
old_key_comp = get_offset (&ih->ih_key);
- old_len = ih->ih_item_len;
+ old_len = get_ih_item_len (ih);
/* Calculate key component and item length to insert into S_new[i] */
//ih->ih_key.k_offset += (old_len - sbytes[i]);
set_offset (key_format (&ih->ih_key), &ih->ih_key, old_key_comp + old_len - sbytes[i]);
- ih->ih_item_len = sbytes[i];
+ set_ih_item_len (ih, sbytes[i]);
/* Insert part of the item into S_new[i] before 0-th item */
bi.bi_bh = S_new[i];
@@ -919,12 +708,12 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
zeros_number -= r_zeros_number;
}
- leaf_insert_into_buf (tb->tb_sb, &bi, 0, ih, r_body, r_zeros_number);
+ leaf_insert_into_buf (tb->tb_fs, &bi, 0, ih, r_body, r_zeros_number);
/* Calculate key component and item length to insert into S[i] */
//ih->ih_key.k_offset = old_key_comp;
set_offset (key_format (&ih->ih_key), &ih->ih_key, old_key_comp);
- ih->ih_item_len = old_len - sbytes[i];
+ set_ih_item_len (ih, old_len - sbytes[i]);
tb->insert_size[0] -= sbytes[i];
}
else /* whole new item falls into S_new[i] */
@@ -936,7 +725,7 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
bi.bi_bh = S_new[i];
bi.bi_parent = 0;
bi.bi_position = 0;
- leaf_insert_into_buf (tb->tb_sb, &bi, item_pos - n + snum[i] - 1, ih, body, zeros_number);
+ leaf_insert_into_buf (tb->tb_fs, &bi, item_pos - n + snum[i] - 1, ih, body, zeros_number);
zeros_number = tb->insert_size[0] = 0;
}
}
@@ -955,30 +744,16 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
{ /* we must shift part of the appended item */
struct item_head * aux_ih;
-#ifdef CONFIG_REISERFS_CHECK
- if ( ih )
- reiserfs_panic (tb->tb_sb, "PAP-12210: balance_leaf: ih must be 0");
-#endif /* CONFIG_REISERFS_CHECK */
-
if ( I_IS_DIRECTORY_ITEM (aux_ih = B_N_PITEM_HEAD(tbS0,item_pos))) {
/* we append to directory item */
int entry_count;
- entry_count = ih_entry_count(aux_ih);
+ entry_count = get_ih_entry_count(aux_ih);
if ( entry_count - sbytes[i] < pos_in_item && pos_in_item <= entry_count ) {
/* new directory entry falls into S_new[i] */
-#ifdef CONFIG_REISERFS_CHECK
- if ( ! tb->insert_size[0] )
- reiserfs_panic (tb->tb_sb, "PAP-12215: balance_leaif: insert_size is already 0");
- if ( sbytes[i] - 1 >= entry_count )
- reiserfs_panic (tb->tb_sb, "PAP-12220: balance_leaf: "
- "there are no so much entries (%d), only %d",
- sbytes[i] - 1, entry_count);
-#endif
-
/* Shift snum[i]-1 items in whole. Shift sbytes[i] directory entries from directory item number snum[i] */
leaf_move_items (LEAF_FROM_S_TO_SNEW, tb, snum[i], sbytes[i]-1, S_new[i]);
@@ -986,7 +761,7 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
bi.bi_bh = S_new[i];
bi.bi_parent = 0;
bi.bi_position = 0;
- leaf_paste_in_buffer (tb->tb_sb, &bi, 0, pos_in_item - entry_count + sbytes[i] - 1,
+ leaf_paste_in_buffer (tb->tb_fs, &bi, 0, pos_in_item - entry_count + sbytes[i] - 1,
tb->insert_size[0], body,zeros_number);
/* paste new directory entry */
leaf_paste_entries (
@@ -1006,12 +781,6 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
const char * r_body;
struct item_head * tmp;
-#ifdef CONFIG_REISERFS_CHECK
- if ( pos_in_item != B_N_PITEM_HEAD(tbS0,item_pos)->ih_item_len ||
- tb->insert_size[0] <= 0 )
- reiserfs_panic (tb->tb_sb, "PAP-12225: balance_leaf: item too short or insert_size <= 0");
-#endif
-
/* Calculate number of bytes which must be shifted from appended item */
n_shift = sbytes[i] - tb->insert_size[0];
if ( n_shift < 0 )
@@ -1037,14 +806,14 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
zeros_number -= r_zeros_number;
}
- leaf_paste_in_buffer(tb->tb_sb, &bi, 0, n_shift, tb->insert_size[0]-n_rem, r_body,r_zeros_number);
+ leaf_paste_in_buffer(tb->tb_fs, &bi, 0, n_shift, tb->insert_size[0]-n_rem, r_body,r_zeros_number);
tmp = B_N_PITEM_HEAD (S_new[i], 0);
if (I_IS_INDIRECT_ITEM(tmp)) {
if (n_rem)
reiserfs_panic ("PAP-12230: balance_leaf: "
"invalid action with indirect item");
//tmp->u.ih_free_space = ((struct unfm_nodeinfo*)body)->unfm_freespace;
- set_free_space (tmp, ((struct unfm_nodeinfo*)body)->unfm_freespace);
+ set_ih_free_space (tmp, ((struct unfm_nodeinfo*)body)->unfm_freespace);
}
//B_N_PKEY(S_new[i],0)->k_offset += n_rem;
@@ -1060,29 +829,13 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
{
int ret_val;
struct item_head * pasted;
-
-#ifdef CONFIG_REISERFS_CHECK
- struct item_head * ih = B_N_PITEM_HEAD(tbS0,item_pos);
-
- if ( ! I_IS_DIRECTORY_ITEM(ih) && (pos_in_item != ih->ih_item_len ||
- tb->insert_size[0] <= 0) )
- reiserfs_panic (tb->tb_sb, "PAP-12235: balance_leaf: pos_in_item must be equal to ih_item_len");
-#endif /* CONFIG_REISERFS_CHECK */
-
+
ret_val = leaf_move_items (LEAF_FROM_S_TO_SNEW, tb, snum[i], sbytes[i], S_new[i]);
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( ret_val )
- reiserfs_panic (tb->tb_sb, "PAP-12240: balance_leaf: "
- "unexpected value returned by leaf_move_items (%d)",
- ret_val);
-#endif /* CONFIG_REISERFS_CHECK */
-
/* paste into item */
bi.bi_bh = S_new[i];
bi.bi_parent = 0;
bi.bi_position = 0;
- leaf_paste_in_buffer(tb->tb_sb, &bi, item_pos - n + snum[i], pos_in_item, tb->insert_size[0], body, zeros_number);
+ leaf_paste_in_buffer(tb->tb_fs, &bi, item_pos - n + snum[i], pos_in_item, tb->insert_size[0], body, zeros_number);
pasted = B_N_PITEM_HEAD(S_new[i], item_pos - n + snum[i]);
if (I_IS_DIRECTORY_ITEM (pasted)) {
@@ -1093,7 +846,7 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
/* if we paste to indirect item update ih_free_space */
if (I_IS_INDIRECT_ITEM (pasted))
//pasted->u.ih_free_space = ((struct unfm_nodeinfo*)body)->unfm_freespace;
- set_free_space (pasted, ((struct unfm_nodeinfo*)body)->unfm_freespace);
+ set_ih_free_space (pasted, ((struct unfm_nodeinfo*)body)->unfm_freespace);
zeros_number = tb->insert_size[0] = 0;
}
} else {
@@ -1109,18 +862,6 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
memcpy (insert_key + i,B_N_PKEY(S_new[i],0),KEY_SIZE);
insert_ptr[i] = S_new[i];
-
-#ifdef CONFIG_REISERFS_CHECK
- if (S_new[i]->b_count != 1) {
- if (buffer_journaled(S_new[i]) || buffer_journal_dirty(S_new[i])) {
- ;
- } else {
- reiserfs_panic (tb->tb_sb, "PAP-12247: balance_leaf: S_new[%d]->b_count=%u blocknr = %lu\n", i, S_new[i]->b_count,
- S_new[i]->b_blocknr);
- }
- }
-#endif
-
}
/* if the affected item was not wholly shifted then we perform all
@@ -1134,12 +875,12 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
bi.bi_bh = tbS0;
bi.bi_parent = PATH_H_PPARENT (tb->tb_path, 0);
bi.bi_position = PATH_H_POSITION (tb->tb_path, 1);
- leaf_insert_into_buf (tb->tb_sb, &bi, item_pos, ih, body, zeros_number);
+ leaf_insert_into_buf (tb->tb_fs, &bi, item_pos, ih, body, zeros_number);
/* If we insert the first key change the delimiting key */
if( item_pos == 0 ) {
if (tb->CFL[0]) /* can be 0 in reiserfsck */
- replace_key (tb->tb_sb, tb->CFL[0], tb->lkey[0],tbS0,0);
+ replace_key (tb->tb_fs, tb->CFL[0], tb->lkey[0],tbS0,0);
}
break;
@@ -1149,107 +890,59 @@ static int balance_leaf(/*struct reiserfs_transaction_handle *th, */
pasted = B_N_PITEM_HEAD (tbS0, item_pos);
/* when directory, may be new entry already pasted */
if (I_IS_DIRECTORY_ITEM (pasted)) {
- if ( pos_in_item >= 0 && pos_in_item <= ih_entry_count (pasted) ) {
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( ! tb->insert_size[0] )
- reiserfs_panic (tb->tb_sb, "PAP-12260: balance_leaf: insert_size is 0 already");
-#endif /* CONFIG_REISERFS_CHECK */
-
+ if ( pos_in_item >= 0 && pos_in_item <= get_ih_entry_count (pasted) ) {
/* prepare space */
bi.bi_bh = tbS0;
bi.bi_parent = PATH_H_PPARENT (tb->tb_path, 0);
bi.bi_position = PATH_H_POSITION (tb->tb_path, 1);
- leaf_paste_in_buffer(tb->tb_sb, &bi, item_pos, pos_in_item, tb->insert_size[0], body, zeros_number);
+ leaf_paste_in_buffer(tb->tb_fs, &bi, item_pos, pos_in_item, tb->insert_size[0], body, zeros_number);
/* paste entry */
leaf_paste_entries (bi.bi_bh, item_pos, pos_in_item, 1, (struct reiserfs_de_head *)body,
body + DEH_SIZE, tb->insert_size[0]);
if ( ! item_pos && ! pos_in_item ) {
-
-#ifdef CONFIG_REISERFS_CHECK
- if (!tb->CFL[0])
- reiserfs_panic (tb->tb_sb, "PAP-12270: balance_leaf: "
- "is not able to update left dkey");
-#endif /* CONFIG_REISERFS_CHECK */
-
if (tb->CFL[0]) // can be 0 in reiserfsck
- replace_key(tb->tb_sb, tb->CFL[0], tb->lkey[0],tbS0,0);
+ replace_key(tb->tb_fs, tb->CFL[0], tb->lkey[0],tbS0,0);
}
tb->insert_size[0] = 0;
}
} else { /* regular object */
- if ( pos_in_item == pasted->ih_item_len ) {
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( tb->insert_size[0] <= 0 )
- reiserfs_panic (tb->tb_sb,
- "PAP-12275: balance_leaf: insert size must not be %d", tb->insert_size[0]);
-#endif /* CONFIG_REISERFS_CHECK */
-
+ if ( pos_in_item == get_ih_item_len (pasted) ) {
bi.bi_bh = tbS0;
bi.bi_parent = PATH_H_PPARENT (tb->tb_path, 0);
bi.bi_position = PATH_H_POSITION (tb->tb_path, 1);
- leaf_paste_in_buffer (tb->tb_sb, &bi, item_pos, pos_in_item, tb->insert_size[0], body, zeros_number);
+ leaf_paste_in_buffer (tb->tb_fs, &bi, item_pos, pos_in_item, tb->insert_size[0], body, zeros_number);
if (I_IS_INDIRECT_ITEM (pasted)) {
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( tb->insert_size[0] != UNFM_P_SIZE )
- reiserfs_panic (tb->tb_sb,
- "PAP-12280: balance_leaf: insert_size for indirect item must be %d, not %d",
- UNFM_P_SIZE, tb->insert_size[0]);
-#endif /* CONFIG_REISERFS_CHECK */
-
//pasted->u.ih_free_space = ((struct unfm_nodeinfo*)body)->unfm_freespace;
- set_free_space (pasted, ((struct unfm_nodeinfo*)body)->unfm_freespace);
+ set_ih_free_space (pasted, ((struct unfm_nodeinfo*)body)->unfm_freespace);
}
tb->insert_size[0] = 0;
}
-
-#ifdef CONFIG_REISERFS_CHECK
- else {
- if ( tb->insert_size[0] ) {
- print_tb (init_mode, init_item_pos, init_pos_in_item, &init_tb, "12285");
- reiserfs_panic (tb->tb_sb, "PAP-12285: balance_leaf: "
- "insert_size must be 0 (%d), pos_in_item %d. (%h)",
- tb->insert_size[0], pos_in_item, pasted);
- }
- }
-#endif /* CONFIG_REISERFS_CHECK */
-
}
} /* case M_PASTE: */
}
}
-#ifdef CONFIG_REISERFS_CHECK
- if ( flag == M_PASTE && tb->insert_size[0] ) {
- print_tb (M_PASTE, item_pos, pos_in_item, tb, "balance");
- reiserfs_panic (tb->tb_sb, "PAP-12290: balance_leaf: insert_size is still not 0 (%d)", tb->insert_size[0]);
- }
-#endif /* CONFIG_REISERFS_CHECK */
-
return 0;
} /* Leaf level of the tree is balanced (end of balance_leaf) */
+void make_empty_leaf (struct buffer_head * bh)
+{
+ set_blkh_nr_items (B_BLK_HEAD (bh), 0);
+ set_blkh_free_space (B_BLK_HEAD (bh), MAX_FREE_SPACE (bh->b_size));
+ set_blkh_level (B_BLK_HEAD (bh), DISK_LEAF_NODE_LEVEL);
+}
+
/* Make empty node */
void make_empty_node (struct buffer_info * bi)
{
- struct block_head * blkh;
-
-#ifdef CONFIG_REISERFS_CHECK
- if (bi->bi_bh == NULL)
- reiserfs_panic (0, "PAP-12295: make_empty_node: pointer to the buffer is NULL");
-#endif
-
- (blkh = B_BLK_HEAD(bi->bi_bh))->blk_nr_item = 0;
- blkh->blk_free_space = MAX_CHILD_SIZE(bi->bi_bh);
+ make_empty_leaf (bi->bi_bh);
if (bi->bi_parent)
- B_N_CHILD (bi->bi_parent, bi->bi_position)->dc_size = 0;
+ set_dc_child_size (B_N_CHILD (bi->bi_parent, bi->bi_position), 0);
}
@@ -1281,27 +974,10 @@ struct buffer_head * get_FEB (struct tree_balance * tb)
/* Replace n_dest'th key in buffer dest by n_src'th key of buffer src.*/
-void replace_key (reiserfs_filsys_t fs,
+void replace_key (reiserfs_filsys_t * fs,
struct buffer_head * dest, int n_dest,
struct buffer_head * src, int n_src)
{
-
-#ifdef CONFIG_REISERFS_CHECK
- if (dest == NULL || src == NULL)
- reiserfs_panic (0, "vs-12305: replace_key: sourse or destination buffer is 0 (src=%p, dest=%p)", src, dest);
-
- if ( ! B_IS_KEYS_LEVEL (dest) )
- reiserfs_panic (0, "vs-12310: replace_key: invalid level (%d) for destination buffer. Must be > %d",
- B_BLK_HEAD(dest)->blk_level, DISK_LEAF_NODE_LEVEL);
-
- if (n_dest < 0 || n_src < 0)
- reiserfs_panic (0, "vs-12315: replace_key: src(%d) or dest(%d) key number less than 0", n_src, n_dest);
-
- if (n_dest >= B_NR_ITEMS(dest) || n_src >= B_NR_ITEMS(src))
- reiserfs_panic (0, "vs-12320: replace_key: src(%d(%d)) or dest(%d(%d)) key number is too big",
- n_src, B_NR_ITEMS(src), n_dest, B_NR_ITEMS(dest));
-#endif /* CONFIG_REISERFS_CHECK */
-
if (dest) {
if (is_leaf_node (src))
/* source buffer contains leaf node */
@@ -1316,14 +992,9 @@ void replace_key (reiserfs_filsys_t fs,
void reiserfs_invalidate_buffer (struct tree_balance * tb, struct buffer_head * bh, int do_free_block)
{
-
- B_BLK_HEAD (bh)->blk_level = FREE_LEVEL;
+ set_blkh_level (B_BLK_HEAD (bh), FREE_LEVEL);
clear_bit(BH_Dirty, &bh->b_state);
-#ifdef CONFIG_REISERFS_CHECK
- B_NR_ITEMS (bh) = 0;
-#endif
-
if (do_free_block) {
struct buffer_head * to_be_forgotten;
@@ -1333,7 +1004,7 @@ void reiserfs_invalidate_buffer (struct tree_balance * tb, struct buffer_head *
bforget (to_be_forgotten);
}
- reiserfs_free_block (tb->tb_sb, bh->b_blocknr);
+ reiserfs_free_block (tb->tb_fs, bh->b_blocknr);
}
}
@@ -1345,12 +1016,6 @@ int get_left_neighbor_position (
{
int Sh_position = PATH_H_POSITION (tb->tb_path, h + 1);
-#ifdef CONFIG_REISERFS_CHECK
- if (PATH_H_PPARENT (tb->tb_path, h) == 0 || tb->FL[h] == 0)
- reiserfs_panic (tb->tb_sb, "vs-12325: get_left_neighbor_position: FL[%d](%p) or F[%d](%p) does not exist",
- h, tb->FL[h], h, PATH_H_PPARENT (tb->tb_path, h));
-#endif
-
if (Sh_position == 0)
return B_NR_ITEMS (tb->FL[h]);
else
@@ -1362,223 +1027,12 @@ int get_right_neighbor_position (struct tree_balance * tb, int h)
{
int Sh_position = PATH_H_POSITION (tb->tb_path, h + 1);
-#ifdef CONFIG_REISERFS_CHECK
- if (PATH_H_PPARENT (tb->tb_path, h) == 0 || tb->FR[h] == 0)
- reiserfs_panic (tb->tb_sb, "vs-12330: get_right_neighbor_position: F[%d](%p) or FR[%d](%p) does not exist",
- h, PATH_H_PPARENT (tb->tb_path, h), h, tb->FR[h]);
-#endif
-
if (Sh_position == B_NR_ITEMS (PATH_H_PPARENT (tb->tb_path, h)))
return 0;
else
return Sh_position + 1;
}
-
-#ifdef CONFIG_REISERFS_CHECK
-
-int is_reusable (struct super_block * s, unsigned long block, int bit_value);
-static void check_internal_node (struct super_block * s, struct buffer_head * bh, char * mes)
-{
- struct disk_child * dc;
- int i;
-
- if (!bh)
- reiserfs_panic (s, "PAP-12336: check_internal_node: bh == 0");
-
- if (!bh || !B_IS_IN_TREE (bh))
- return;
-
- if (!buffer_dirty (bh) && !buffer_journaled(bh) ) {
- print_tb (init_mode, init_item_pos, init_pos_in_item, &init_tb, mes);
- reiserfs_panic (s, "PAP-12337: check_internal_node: buffer (%b) must be dirty", bh);
- }
-
- dc = B_N_CHILD (bh, 0);
-
- for (i = 0; i <= B_NR_ITEMS (bh); i ++, dc ++) {
- if (!is_reusable (s, dc->dc_block_number, 1) ) {
- print_tb (init_mode, init_item_pos, init_pos_in_item, &init_tb, mes);
- reiserfs_panic (s, "PAP-12338: check_internal_node: invalid child pointer %y in %b", dc, bh);
- }
- if (dc->dc_size <= BLKH_SIZE) {
- print_tb (init_mode, init_item_pos, init_pos_in_item, &init_tb, mes);
- reiserfs_panic (s, "PAP-12338: check_internal_node: empty node in the tree? %y", dc);
- }
- }
-}
-
-
-static int locked_or_not_in_tree (struct buffer_head * bh, char * which)
-{
- if ( buffer_locked (bh) || !B_IS_IN_TREE (bh) ) {
- reiserfs_warning ("vs-12339: locked_or_not_in_tree: %s (%b)\n", which, bh);
- return 1;
- }
- return 0;
-}
-
-
-static int check_before_balancing (struct tree_balance * tb, int mode)
-{
- int retval = 0;
- int pos_in_item = tb->tb_path->pos_in_item;
-
- if (mode == M_PASTE) {
- // make sure paste can be performed with given parameters
- struct item_head * ih;
-
- ih = get_ih (tb->tb_path);
- if (I_IS_INDIRECT_ITEM (ih)) {
- // we can paste only to the end for now
- if (pos_in_item != I_UNFM_NUM (ih))
- reiserfs_panic (tb->tb_sb, "vs-12333: check_before_balancing: "
- "pos_in_item %d set improperly to paste indirect item %h",
- pos_in_item, ih);
- }
- if (I_IS_DIRECT_ITEM (ih)) {
- // we can paste only to the end for now
- if (pos_in_item != ih_item_len (ih))
- reiserfs_panic (tb->tb_sb, "vs-12334: check_before_balancing: "
- "pos_in_item %d set improperly to paste direct item %h",
- pos_in_item, ih);
- }
- }
-
- if ( cur_tb ) {
- reiserfs_panic (tb->tb_sb, "vs-12335: check_before_balancing: "
- "suspect that schedule occurred based on cur_tb not being null at this point in code. "
- "do_balance cannot properly handle schedule occuring while it runs.");
- }
-
- /* double check that buffers that we will modify are unlocked. (fix_nodes
- should already have prepped all of these for us). */
- if ( tb->lnum[0] ) {
- retval |= locked_or_not_in_tree (tb->L[0], "L[0]");
- retval |= locked_or_not_in_tree (tb->FL[0], "FL[0]");
- retval |= locked_or_not_in_tree (tb->CFL[0], "CFL[0]");
- check_leaf (tb->L[0]);
- }
- if ( tb->rnum[0] ) {
- retval |= locked_or_not_in_tree (tb->R[0], "R[0]");
- retval |= locked_or_not_in_tree (tb->FR[0], "FR[0]");
- retval |= locked_or_not_in_tree (tb->CFR[0], "CFR[0]");
- check_leaf (tb->R[0]);
- }
- retval |= locked_or_not_in_tree (PATH_PLAST_BUFFER (tb->tb_path), "S[0]");
- check_leaf (PATH_PLAST_BUFFER (tb->tb_path));
- return retval;
-}
-
-
-static void check_after_balance_leaf (struct tree_balance * tb)
-{
- if (tb->lnum[0]) {
- if (B_BLK_HEAD (tb->L[0])->blk_free_space !=
- MAX_CHILD_SIZE (tb->L[0]) - B_N_CHILD (tb->FL[0], get_left_neighbor_position (tb, 0))->dc_size) {
- print_tb (init_mode, init_item_pos, init_pos_in_item, &init_tb, "12221");
- reiserfs_panic (tb->tb_sb, "PAP-12355: check_after_balance_leaf: shift to left was incorrect");
- }
- }
- if (tb->rnum[0]) {
- if (B_BLK_HEAD (tb->R[0])->blk_free_space !=
- MAX_CHILD_SIZE (tb->R[0]) - B_N_CHILD (tb->FR[0], get_right_neighbor_position (tb, 0))->dc_size) {
- print_tb (init_mode, init_item_pos, init_pos_in_item, &init_tb, "12222");
- reiserfs_panic (tb->tb_sb, "PAP-12360: check_after_balance_leaf: shift to right was incorrect");
- }
- }
- if (PATH_H_PBUFFER(tb->tb_path,1) &&
- B_BLK_HEAD (PATH_H_PBUFFER(tb->tb_path,0))->blk_free_space !=
- MAX_CHILD_SIZE (PATH_H_PBUFFER(tb->tb_path,0)) -
- B_N_CHILD (PATH_H_PBUFFER(tb->tb_path,1),
- PATH_H_POSITION (tb->tb_path, 1))->dc_size) {
- print_tb (init_mode, init_item_pos, init_pos_in_item, &init_tb, "12223");
- reiserfs_panic (tb->tb_sb, "PAP-12365: check_after_balance_leaf: S is incorrect");
- }
-}
-
-
-static void compare_pair (struct buffer_head * bh1, struct buffer_head * bh2)
-{
- int cur_free, node_size;
-
- if (!bh1 || !bh2)
- return;
-
- cur_free = node_free_space (bh1);
- node_size = bh1->b_size - BLKH_SIZE - ((is_left_mergeable (B_N_PITEM_HEAD (bh2, 0), bh1->b_size)) ? IH_SIZE : 0);
- if (cur_free >= node_size) {
- print_tb (init_mode, init_item_pos, init_pos_in_item, &init_tb, "12366");
- reiserfs_panic (0, "vs-12366: check_leaf_level: balance condition denied bh1 %z, bh2 %z",
- bh1, bh2);
- }
-}
-
-
-static void check_leaf_level (struct tree_balance * tb)
-{
- struct buffer_head * S0 = get_bh (tb->tb_path);
- struct buffer_head * bhs[5] = {0, };
- int i;
-
- // check item types, internal structures of items, etc
- check_leaf (tb->L[0]);
- check_leaf (tb->R[0]);
- check_leaf (S0);
-
- if (tb->blknum[0] > 2) {
- reiserfs_warning ("More than one new node on the leaf level\n");
- return;
- }
-
- // check balance condition for any neighboring buffers
- i = 0;
- if (tb->L[0] && B_IS_IN_TREE (tb->L[0]))
- bhs[i ++] = tb->L[0];
- if (B_IS_IN_TREE (S0))
- bhs[i ++] = S0;
- if (tb->blknum[0] == 2) {
- if (!B_IS_ITEMS_LEVEL(tb->used[0])) {
- reiserfs_warning ("can not find new node\n");
- return;
- }
- bhs[i ++] = tb->used[0];
- }
- if (tb->R[0] && B_IS_IN_TREE (tb->R[0])) {
- bhs[i ++] = tb->R[0];
- }
-
- for (i = 0; i < 4; i ++) {
- compare_pair (bhs[i], bhs[i + 1]);
- }
-
-}
-
-
-static void check_after_balancing (struct tree_balance * tb)
-{
- int h;
-
- check_leaf_level (tb);
-
- /* check all internal nodes */
- for (h = 1; tb->insert_size[h]; h ++) {
- check_internal_node (tb->tb_sb, PATH_H_PBUFFER (tb->tb_path, h), "BAD BUFFER ON PATH");
- if (tb->lnum[h])
- check_internal_node (tb->tb_sb, tb->L[h], "BAD L");
- if (tb->rnum[h])
- check_internal_node (tb->tb_sb, tb->R[h], "BAD R");
- }
-
-}
-
-#endif
-
-
-
-
-
-
/* Now we have all of the buffers that must be used in balancing of the tree.
We rely on the assumption that schedule() will not occur while do_balance
works. ( Only interrupt handlers are acceptable.) We balance the tree
@@ -1635,35 +1089,12 @@ void do_balance (struct tree_balance * tb, /* tree_balance structure */
struct buffer_head *insert_ptr[2]; /* inserted node-ptrs for the next
level */
-
-#ifdef CONFIG_REISERFS_CHECK
- memcpy(&init_tb, tb, sizeof(struct tree_balance));
- init_item_pos = PATH_LAST_POSITION (tb->tb_path);
- init_pos_in_item = tb->tb_path->pos_in_item;//pos_in_item;
- init_mode = flag;
-
- /* do not delete, just comment it out */
- /*print_tb(flag, PATH_LAST_POSITION(tb->tb_path), pos_in_item, tb, "check");*/
-
- if (check_before_balancing (tb/*, pos_in_item*/, flag))
- reiserfs_panic (tb->tb_sb, "PAP-12340: do_balance: "
- "balancing can not be performed");
-
- cur_tb = tb;
-#endif /* CONFIG_REISERFS_CHECK */
-
/* if we have no real work to do */
if ( ! tb->insert_size[0] ) {
-#ifdef CONFIG_REISERFS_CHECK
- cur_tb = NULL;
- if (flag != M_CUT)
- reiserfs_panic (tb->tb_sb, "PAP-12350: do_balance: insert_size == 0, mode == %c", flag);
-#endif
unfix_nodes(/*th,*/ tb);
return;
}
-#ifndef FU //REISERFS_FSCK
if (flag == M_INTERNAL) {
insert_ptr[0] = (struct buffer_head *)body;
/* we must prepare insert_key */
@@ -1681,33 +1112,17 @@ void do_balance (struct tree_balance * tb, /* tree_balance structure */
/* and insert_ptr instead of balance_leaf */
child_pos = PATH_H_B_ITEM_ORDER (tb->tb_path, 0)/*item_pos*/;
} else
-#endif
-
/* balance leaf returns 0 except if combining L R and S into one node.
see balance_internal() for explanation of this line of code.*/
child_pos = PATH_H_B_ITEM_ORDER (tb->tb_path, 0) +
balance_leaf (/*th,*/ tb/*, pos_in_item*/, ih, body, flag, zeros_num, insert_key, insert_ptr);
-#ifdef CONFIG_REISERFS_CHECK
- check_after_balance_leaf (tb);
-#endif
-
/* Balance internal level of the tree. */
for ( h = 1; h < MAX_HEIGHT && tb->insert_size[h]; h++ )
child_pos = balance_internal (/*th,*/ tb, h, child_pos, insert_key, insert_ptr);
-#ifdef CONFIG_REISERFS_CHECK
- cur_tb = NULL;
- check_after_balancing (tb);
-#endif
-
/* Release all (except for S[0]) non NULL buffers fixed by fix_nodes() */
unfix_nodes(/*th,*/ tb);
-
-#ifdef CONFIG_REISERFS_CHECK
- tb->tb_sb->u.reiserfs_sb.s_do_balance ++;
-#endif
-
}
diff --git a/reiserfscore/fix_node.c b/reiserfscore/fix_node.c
index 6b18240..4968faa 100644
--- a/reiserfscore/fix_node.c
+++ b/reiserfscore/fix_node.c
@@ -38,86 +38,55 @@
#include "includes.h"
-__u64 get_bytes_number (struct item_head * ih, int blocksize)
-{
- switch (get_type (&ih->ih_key)) {
- case TYPE_DIRECT:
- return ih_item_len (ih);
- case TYPE_INDIRECT:
- return I_UNFM_NUM(ih) * blocksize - ih_free_space (ih);
- case TYPE_STAT_DATA:
- return 0;
- }
- reiserfs_warning (stderr, "get_bytes_number: called for wrong type of item %h", ih);
- return 0;
-}
-/* To make any changes in the tree we find a node, that contains item
- to be changed/deleted or position in the node we insert a new item
- to. We call this node S. To do balancing we need to decide what we
- will shift to left/right neighbor, or to a new node, where new item
- will be etc. To make this analysis simpler we build virtual
- node. Virtual node is an array of items, that will replace items of
- node S. (For instance if we are going to delete an item, virtual
- node does not contain it). Virtual node keeps information about
- item sizes and types, mergeability of first and last items, sizes
- of all entries in directory item. We use this array of items when
- calculating what we can shift to neighbors and how many nodes we
- have to have if we do not any shiftings, if we shift to left/right
- neighbor or to both. */
-
-
-/* taking item number in virtual node, returns number of item, that it has in source buffer */
+/* To make any changes in the tree we find a node, that contains item to be
+ changed/deleted or position in the node we insert a new item to. We call
+ this node S. To do balancing we need to decide what we will shift to
+ left/right neighbor, or to a new node, where new item will be etc. To make
+ this analysis simpler we build virtual node. Virtual node is an array of
+ items, that will replace items of node S. (For instance if we are going to
+ delete an item, virtual node does not contain it). Virtual node keeps
+ information about item sizes and types, mergeability of first and last
+ items, sizes of all entries in directory item. We use this array of items
+ when calculating what we can shift to neighbors and how many nodes we have
+ to have if we do not any shiftings, if we shift to left/right neighbor or
+ to both. */
+
+
+/* taking item number in virtual node, returns number of item, that it has in
+ source buffer */
static inline int old_item_num (int new_num, int affected_item_num, int mode)
{
- if (mode == M_PASTE || mode == M_CUT || new_num < affected_item_num)
- return new_num;
-
- if (mode == M_INSERT) {
-
-#ifdef CONFIG_REISERFS_CHECK
- if (new_num == 0)
- reiserfs_panic (0,"vs-8005: old_item_num: for INSERT mode and item number of inserted item");
-#endif
-
- return new_num - 1;
- }
-
-#ifdef CONFIG_REISERFS_CHECK
- if (mode != M_DELETE)
- reiserfs_panic (0, "vs-8010: old_item_num: mode must be M_DELETE (mode = \'%c\'", mode);
-#endif
+ if (mode == M_PASTE || mode == M_CUT || new_num < affected_item_num)
+ return new_num;
+
+ if (mode == M_INSERT)
+ return new_num - 1;
- /* delete mode */
- return new_num + 1;
+ /* delete mode */
+ return new_num + 1;
}
-/*
- * function returns old entry number in directory item in real node
- * using new entry number in virtual item in virtual node */
+/* function returns old entry number in directory item in real node using new
+ entry number in virtual item in virtual node */
static inline int old_entry_num (int new_num, int affected_item_num, int new_entry_num, int pos_in_item, int mode)
{
- if ( mode == M_INSERT || mode == M_DELETE)
- return new_entry_num;
-
- if (new_num != affected_item_num) {
- /* cut or paste is applied to another item */
- return new_entry_num;
- }
-
- if (new_entry_num < pos_in_item)
- return new_entry_num;
-
- if (mode == M_CUT)
- return new_entry_num + 1;
-
-#ifdef CONFIG_REISERFS_CHECK
- if (mode != M_PASTE)
- reiserfs_panic (0, "vs-8015: old_entry_num: mode must be M_PASTE (mode = \'%c\'", mode);
-#endif
-
- return new_entry_num - 1;
+ if ( mode == M_INSERT || mode == M_DELETE)
+ return new_entry_num;
+
+ if (new_num != affected_item_num) {
+ /* cut or paste is applied to another item */
+ return new_entry_num;
+ }
+
+ if (new_entry_num < pos_in_item)
+ return new_entry_num;
+
+ if (mode == M_CUT)
+ return new_entry_num + 1;
+
+ return new_entry_num - 1;
}
@@ -128,8 +97,7 @@ static inline int old_entry_num (int new_num, int affected_item_num, int new_ent
static void set_entry_sizes (struct tree_balance * tb,
int old_num, int new_num,
struct buffer_head * bh,
- struct item_head * ih
- )
+ struct item_head * ih)
{
struct virtual_node * vn = tb->tb_vn;
int i;
@@ -138,21 +106,13 @@ static void set_entry_sizes (struct tree_balance * tb,
deh = B_I_DEH (bh, ih);
- /* seek to given virtual item in array of virtual items */
+ /* seek to given virtual item in array of virtual items */
vi = vn->vn_vi + new_num;
/* virtual directory item have this amount of entry after */
- vi->vi_entry_count = ih_entry_count (ih) +
+ vi->vi_entry_count = get_ih_entry_count (ih) +
((old_num == vn->vn_affected_item_num) ? ((vn->vn_mode == M_CUT) ? -1 :
(vn->vn_mode == M_PASTE ? 1 : 0)) : 0);
-
-#ifdef CONFIG_REISERFS_CHECK
- /* check whether we have enough space for array of entry sizes */
- if (tb->vn_buf + tb->vn_buf_size - vn->vn_free_ptr < vi->vi_entry_count * sizeof (__u16))
- reiserfs_panic (tb->tb_sb, "vs-8020: set_entry_sizes: "
- "no enough space for %d entries of virtual item", vi->vi_entry_count);
-#endif
-
vi->vi_entry_sizes = (__u16 *)vn->vn_free_ptr;
vn->vn_free_ptr += vi->vi_entry_count * sizeof (__u16);
@@ -167,25 +127,6 @@ static void set_entry_sizes (struct tree_balance * tb,
/* set size of pasted entry */
if (old_num == vn->vn_affected_item_num && vn->vn_mode == M_PASTE)
vi->vi_entry_sizes[vn->vn_pos_in_item] = tb->insert_size[0];
-
-
-#ifdef CONFIG_REISERFS_CHECK
- /* compare total size of entries with item length */
- {
- int k, l;
-
- l = 0;
- for (k = 0; k < vi->vi_entry_count; k ++)
- l += vi->vi_entry_sizes[k];
-
- if (l + IH_SIZE != vi->vi_item_len +
- ((old_num == vn->vn_affected_item_num && (vn->vn_mode == M_PASTE || vn->vn_mode == M_CUT)) ? tb->insert_size[0] : 0) ) {
- reiserfs_panic (0, "vs-8025: set_entry_sizes: (mode==%c, old_num==%d, aff_num==%d, insert_size==%d), invalid length of directory item",
- vn->vn_mode, old_num, vn->vn_affected_item_num, tb->insert_size[0]);
- }
- }
-#endif
-
}
@@ -203,7 +144,7 @@ static void create_virtual_node (struct tree_balance * tb, int h)
temp_ih = B_N_PITEM_HEAD (PATH_PLAST_BUFFER (tb->tb_path), B_NR_ITEMS (PATH_PLAST_BUFFER (tb->tb_path)) - 1);
/* size of changed node */
- vn->vn_size = MAX_CHILD_SIZE (Sh) - B_BLK_HEAD (Sh)->blk_free_space + tb->insert_size[h];
+ vn->vn_size = MAX_CHILD_SIZE (Sh->b_size) - get_blkh_free_space (B_BLK_HEAD (Sh)) + tb->insert_size[h];
/* for internal nodes array if virtual items is not created */
if (h) {
@@ -224,12 +165,8 @@ static void create_virtual_node (struct tree_balance * tb, int h)
ih = B_N_PITEM_HEAD (Sh, 0);
/* define the mergeability for 0-th item (if it is not being deleted) */
-#ifndef FU //REISERFS_FSCK
- if (is_left_mergeable (tb->tb_sb, tb->tb_path) == 1 && (vn->vn_mode != M_DELETE || vn->vn_affected_item_num))
-#else
- if (is_left_mergeable (ih, Sh->b_size) && (vn->vn_mode != M_DELETE || vn->vn_affected_item_num))
-#endif
- vn->vn_vi[0].vi_type |= VI_TYPE_LEFT_MERGEABLE;
+ if (is_left_mergeable (tb->tb_fs, tb->tb_path) == 1 && (vn->vn_mode != M_DELETE || vn->vn_affected_item_num))
+ vn->vn_vi[0].vi_type |= VI_TYPE_LEFT_MERGEABLE;
/* go through all items those remain in the virtual node (except for the new (inserted) one) */
for (new_num = 0; new_num < vn->vn_nr_item; new_num ++) {
@@ -241,16 +178,10 @@ static void create_virtual_node (struct tree_balance * tb, int h)
/* get item number in source node */
j = old_item_num (new_num, vn->vn_affected_item_num, vn->vn_mode);
- vn->vn_vi[new_num].vi_item_len += ih[j].ih_item_len + IH_SIZE;
+ vn->vn_vi[new_num].vi_item_len += get_ih_item_len (&ih[j]) + IH_SIZE;
if (I_IS_STAT_DATA_ITEM (ih + j)) {
vn->vn_vi[new_num].vi_type |= VI_TYPE_STAT_DATA;
-
-#ifdef CONFIG_REISERFS_CHECK
- if (new_num == vn->vn_affected_item_num && (vn->vn_mode == M_CUT || vn->vn_mode == M_PASTE))
- reiserfs_panic (0, "vs-8035: create_virtual_node: stat data cannot be affected item");
-#endif
-
continue;
}
@@ -264,10 +195,12 @@ static void create_virtual_node (struct tree_balance * tb, int h)
if (I_IS_DIRECTORY_ITEM (ih + j)) {
set_entry_sizes (tb, j, new_num, Sh, ih + j);
vn->vn_vi[new_num].vi_type |= VI_TYPE_DIRECTORY;
- if (ih[j].ih_key.u.k_offset_v1.k_offset == DOT_OFFSET)
+ if (get_key_offset_v1 (&ih[j].ih_key) == DOT_OFFSET)
vn->vn_vi[new_num].vi_type |= VI_TYPE_FIRST_DIRECTORY_ITEM;
}
+ vn->vn_vi[new_num].vi_item_offset = get_offset (&(ih + j)->ih_key);
+
if (new_num != vn->vn_affected_item_num)
/* this is not being changed */
continue;
@@ -279,14 +212,9 @@ static void create_virtual_node (struct tree_balance * tb, int h)
/* virtual inserted item is not defined yet */
if (vn->vn_mode == M_INSERT) {
-
-#ifdef CONFIG_REISERFS_CHECK
- if (vn->vn_ins_ih == 0)
- reiserfs_panic (0, "vs-8040: create_virtual_node: item header of inserted item is not specified");
-#endif
-
vn->vn_vi[vn->vn_affected_item_num].vi_item_len = tb->insert_size[0];
-
+ vn->vn_vi[vn->vn_affected_item_num].vi_item_offset = get_offset (&vn->vn_ins_ih->ih_key);
+
switch (get_type (&vn->vn_ins_ih->ih_key)) {
case TYPE_STAT_DATA:
vn->vn_vi[vn->vn_affected_item_num].vi_type |= VI_TYPE_STAT_DATA;
@@ -310,31 +238,9 @@ static void create_virtual_node (struct tree_balance * tb, int h)
/* set right merge flag we take right delimiting key and check whether it is a mergeable item */
if (tb->CFR[0]) {
ih = (struct item_head *)B_N_PDELIM_KEY (tb->CFR[0], tb->rkey[0]);
-#ifndef FU //REISERFS_FSCK
- if (is_right_mergeable (tb->tb_sb, tb->tb_path) == 1 && (vn->vn_mode != M_DELETE ||
- vn->vn_affected_item_num != B_NR_ITEMS (Sh) - 1))
-#else
- if (is_left_mergeable (ih, Sh->b_size) && (vn->vn_mode != M_DELETE ||
- vn->vn_affected_item_num != B_NR_ITEMS (Sh) - 1))
-#endif
- vn->vn_vi[vn->vn_nr_item-1].vi_type |= VI_TYPE_RIGHT_MERGEABLE;
-
-#ifdef CONFIG_REISERFS_CHECK
- if (is_left_mergeable (ih, Sh->b_size) &&
- !(vn->vn_mode != M_DELETE || vn->vn_affected_item_num != B_NR_ITEMS (Sh) - 1) ) {
- /* we delete last item and it could be merged with right neighbor's first item */
- if (!(B_NR_ITEMS (Sh) == 1 && I_IS_DIRECTORY_ITEM (B_N_PITEM_HEAD (Sh, 0)) &&
- ih_entry_count (B_N_PITEM_HEAD (Sh, 0)) == 1)) {
- /* node contains more than 1 item, or item is not directory item, or this item contains more than 1 entry */
- print_block (Sh, 0, -1, -1);
- reiserfs_panic (tb->tb_sb, "vs-8045: create_virtual_node: rdkey %k, affected item==%d (mode==%c) Must be %c",
- &(ih->ih_key), vn->vn_affected_item_num, vn->vn_mode, M_DELETE);
- } else
- /* we can delete directory item, that has only one directory entry in it */
- ;
- }
-#endif
-
+ if (is_right_mergeable (tb->tb_fs, tb->tb_path) == 1 &&
+ (vn->vn_mode != M_DELETE || vn->vn_affected_item_num != B_NR_ITEMS (Sh) - 1))
+ vn->vn_vi[vn->vn_nr_item-1].vi_type |= VI_TYPE_RIGHT_MERGEABLE;
}
}
@@ -347,11 +253,6 @@ static int check_left (struct tree_balance * tb, int h, int cur_free)
struct virtual_node * vn = tb->tb_vn;
int d_size, ih_size, bytes = -1;
-#ifdef CONFIG_REISERFS_CHECK
- if (cur_free < 0)
- reiserfs_panic (0, "vs-8050: check_left: cur_free (%d) < 0", cur_free);
-#endif
-
/* internal level */
if (h > 0) {
if (!cur_free ) {
@@ -371,27 +272,13 @@ static int check_left (struct tree_balance * tb, int h, int cur_free)
return 0;
}
-#ifdef CONFIG_REISERFS_CHECK
- if (!PATH_H_PPARENT (tb->tb_path, 0))
- reiserfs_panic (0, "vs-8055: check_left: parent does not exist or invalid");
-#endif
-
if ((unsigned int)cur_free >= (vn->vn_size - ((vn->vn_vi[0].vi_type & VI_TYPE_LEFT_MERGEABLE) ? IH_SIZE : 0))) {
/* all contents of S[0] fits into L[0] */
-
-#ifdef CONFIG_REISERFS_CHECK
- if (vn->vn_mode == M_INSERT || vn->vn_mode == M_PASTE) {
- reiserfs_panic (0, "vs-8055: check_left: invalid mode or balance condition failed (cur_free %d)vn->vn_size %d",
- cur_free, vn->vn_size);
- }
-#endif
-
tb->lnum[0] = vn->vn_nr_item;
tb->lbytes = -1;
return -1;
}
-
d_size = 0, ih_size = IH_SIZE;
/* first item may be merge with last item in left neighbor */
@@ -424,10 +311,15 @@ static int check_left (struct tree_balance * tb, int h, int cur_free)
return -1;
}
- if (vn->vn_vi[i].vi_type & VI_TYPE_DIRECT)
- /* body of a direct item can be split at any byte */
- tb->lbytes = bytes = cur_free;
-
+ if (vn->vn_vi[i].vi_type & VI_TYPE_DIRECT) {
+ /* body of a direct item can be split by 8 bytes */
+ int align = 8 - (vn->vn_vi[i].vi_item_offset - 1) % 8;
+// reiserfs_warning(stderr,"\nbalancing: cur_free (%d) ", cur_free);
+ tb->lbytes = bytes = (cur_free >= align) ? (align + ((cur_free - align) / 8 * 8)) : 0;
+// reiserfs_warning(stderr,"offset (0x%Lx), move_left (%d), get offset (0x%Lx)",
+// vn->vn_vi[i].vi_item_offset, bytes, vn->vn_vi[i].vi_item_offset + bytes);
+ }
+
if (vn->vn_vi[i].vi_type & VI_TYPE_INDIRECT)
/* body of a indirect item can be split at unformatted pointer bound */
tb->lbytes = bytes = cur_free - cur_free % UNFM_P_SIZE;
@@ -469,12 +361,6 @@ static int check_left (struct tree_balance * tb, int h, int cur_free)
/* something can flow from the item */
tb->lnum[0] ++;
-
-#ifdef CONFIG_REISERFS_CHECK
- if (bytes == -1)
- reiserfs_panic (tb->tb_sb, "vs-8060: check_left: bytes is not initialized");
-#endif
-
return bytes; /* part of split item in bytes */
}
@@ -489,448 +375,398 @@ static int check_left (struct tree_balance * tb, int h, int cur_free)
neighbor */
static int check_right (struct tree_balance * tb, int h, int cur_free)
{
- int i;
- struct virtual_node * vn = tb->tb_vn;
- int d_size, ih_size, bytes = -1;
+ int i;
+ struct virtual_node * vn = tb->tb_vn;
+ int d_size, ih_size, bytes = -1;
-#ifdef CONFIG_REISERFS_CHECK
- if (cur_free < 0)
- reiserfs_panic (tb->tb_sb, "vs-8070: check_right: cur_free < 0");
-#endif
+ /* internal level */
+ if (h > 0) {
+ if (!cur_free) {
+ tb->rnum[h] = 0;
+ return 0;
+ }
+ tb->rnum[h] = cur_free / (DC_SIZE + KEY_SIZE);
+ return -1;
+ }
+
+ /* leaf level */
- /* internal level */
- if (h > 0) {
- if (!cur_free) {
- tb->rnum[h] = 0;
- return 0;
+ if (!cur_free || !vn->vn_nr_item) {
+ /* no free space */
+ tb->rnum[h] = 0;
+ tb->rbytes = -1;
+ return 0;
}
- tb->rnum[h] = cur_free / (DC_SIZE + KEY_SIZE);
- return -1;
- }
-
- /* leaf level */
-
- if (!cur_free || !vn->vn_nr_item) {
- /* no free space */
- tb->rnum[h] = 0;
- tb->rbytes = -1;
- return 0;
- }
-
-#ifdef CONFIG_REISERFS_CHECK
- if (!PATH_H_PPARENT (tb->tb_path, 0))
- reiserfs_panic (tb->tb_sb, "vs-8075: check_right: parent does not exist or invalid");
-#endif
- if ((unsigned int)cur_free >= (vn->vn_size - ((vn->vn_vi[vn->vn_nr_item-1].vi_type & VI_TYPE_RIGHT_MERGEABLE) ? IH_SIZE : 0)))
+ if ((unsigned int)cur_free >= (vn->vn_size - ((vn->vn_vi[vn->vn_nr_item-1].vi_type & VI_TYPE_RIGHT_MERGEABLE) ? IH_SIZE : 0)))
{
- /* all contents of S[0] fits into R[0] */
-
-#ifdef CONFIG_REISERFS_CHECK
- if (vn->vn_mode == M_INSERT || vn->vn_mode == M_PASTE)
- reiserfs_panic (tb->tb_sb, "vs-8080: check_right: invalid mode or balance condition failed");
-#endif
-
- tb->rnum[h] = vn->vn_nr_item;
- tb->rbytes = -1;
- return -1;
+ /* all contents of S[0] fits into R[0] */
+ tb->rnum[h] = vn->vn_nr_item;
+ tb->rbytes = -1;
+ return -1;
}
-
- d_size = 0, ih_size = IH_SIZE;
-
- /* last item may be merge with first item in right neighbor */
- if (vn->vn_vi[vn->vn_nr_item - 1].vi_type & VI_TYPE_RIGHT_MERGEABLE)
- d_size = -(int)IH_SIZE, ih_size = 0;
-
- tb->rnum[0] = 0;
- for (i = vn->vn_nr_item - 1; i >= 0; i --, d_size = 0, ih_size = IH_SIZE)
- {
- d_size += vn->vn_vi[i].vi_item_len;
- if (cur_free >= d_size)
- {
- /* the item can be shifted entirely */
- cur_free -= d_size;
- tb->rnum[0] ++;
- continue;
+
+ d_size = 0, ih_size = IH_SIZE;
+
+ /* last item may be merge with first item in right neighbor */
+ if (vn->vn_vi[vn->vn_nr_item - 1].vi_type & VI_TYPE_RIGHT_MERGEABLE)
+ d_size = -(int)IH_SIZE, ih_size = 0;
+
+ tb->rnum[0] = 0;
+ for (i = vn->vn_nr_item - 1; i >= 0; i --, d_size = 0, ih_size = IH_SIZE) {
+ d_size += vn->vn_vi[i].vi_item_len;
+ if (cur_free >= d_size) {
+ /* the item can be shifted entirely */
+ cur_free -= d_size;
+ tb->rnum[0] ++;
+ continue;
}
- /* the item cannot be shifted entirely, try to split it */
- if (vn->vn_vi[i].vi_type & VI_TYPE_STAT_DATA || vn->vn_vi[i].vi_type & VI_TYPE_INSERTED_DIRECTORY_ITEM)
- {
- /* virtual item is a stat_data or empty directory body ("." and "..), that is not split able */
- tb->rbytes = -1;
- return -1;
+ /* the item cannot be shifted entirely, try to split it */
+ if (vn->vn_vi[i].vi_type & VI_TYPE_STAT_DATA || vn->vn_vi[i].vi_type & VI_TYPE_INSERTED_DIRECTORY_ITEM) {
+ /* virtual item is a stat_data or empty directory body ("." and
+ "..), that is not split able */
+ tb->rbytes = -1;
+ return -1;
}
-
- /* check whether R[0] can hold ih and at least one byte of the item body */
- if ( cur_free <= ih_size )
- /* cannot shift even a part of the current item */
- {
- tb->rbytes = -1;
- return -1;
+
+ /* check whether R[0] can hold ih and at least one byte of the item
+ body */
+ if ( cur_free <= ih_size ) {
+ /* cannot shift even a part of the current item */
+ tb->rbytes = -1;
+ return -1;
}
-
- /* R[0] can hold the header of the item and at least one byte of its body */
- cur_free -= ih_size; /* cur_free is still > 0 */
-
- /* item is of direct type */
- if (vn->vn_vi[i].vi_type & VI_TYPE_DIRECT)
- /* body of a direct item can be split at any byte */
- tb->rbytes = bytes = cur_free;
- /* item is of indirect type */
- if (vn->vn_vi[i].vi_type & VI_TYPE_INDIRECT)
- /* an unformatted node pointer (having size long) is a solid granule of the item */
- tb->rbytes = bytes = cur_free - cur_free % UNFM_P_SIZE;
-
- /* item is of directory type */
- if (vn->vn_vi[i].vi_type & VI_TYPE_DIRECTORY)
- {
- int j;
- struct virtual_item * vi;
-
- tb->rbytes = 0;
- bytes = 0;
- vi = &vn->vn_vi[i];
+ /* R[0] can hold the header of the item and at least one byte of its
+ body */
+ cur_free -= ih_size; /* cur_free is still > 0 */
+
+ /* item is of direct type */
+ if (vn->vn_vi[i].vi_type & VI_TYPE_DIRECT) {
+ /* body of a direct item can be split by 8 bytes */
+ int align = vn->vn_vi[i].vi_item_len % 8;
+// reiserfs_warning(stderr,"\nbalancing: cur_free (%d) ", cur_free);
+ tb->rbytes = bytes = (cur_free >= align) ? (align + ((cur_free - align) / 8 * 8)) : 0;
+// reiserfs_warning(stderr, "offset (0x%Lx) len (%d), move right (%d), get offset (0x%Lx)",
+// vn->vn_vi[i].vi_item_offset, vn->vn_vi[i].vi_item_len, bytes,
+// vn->vn_vi[i].vi_item_offset + vn->vn_vi[i].vi_item_len - bytes);
+ }
+
+ /* item is of indirect type */
+ if (vn->vn_vi[i].vi_type & VI_TYPE_INDIRECT)
+ /* an unformatted node pointer (having size long) is a solid
+ granule of the item */
+ tb->rbytes = bytes = cur_free - cur_free % UNFM_P_SIZE;
+
+ /* item is of directory type */
+ if (vn->vn_vi[i].vi_type & VI_TYPE_DIRECTORY) {
+ int j;
+ struct virtual_item * vi;
+
+ tb->rbytes = 0;
+ bytes = 0;
+ vi = &vn->vn_vi[i];
- for (j = vi->vi_entry_count - 1; j >= 0; j --)
- {
- if (vi->vi_entry_sizes[j] > cur_free)
- /* j-th entry doesn't fit into L[0] */
- break;
+ for (j = vi->vi_entry_count - 1; j >= 0; j --) {
+ if (vi->vi_entry_sizes[j] > cur_free)
+ /* j-th entry doesn't fit into L[0] */
+ break;
- bytes += vi->vi_entry_sizes[j];
- cur_free -= vi->vi_entry_sizes[j];
- tb->rbytes ++;
- }
-
- /* ".." can not be cut from first directory item */
- if ((vn->vn_vi[i].vi_type & VI_TYPE_FIRST_DIRECTORY_ITEM) && tb->rbytes > vi->vi_entry_count - 2) {
-
-#ifdef CONFIG_REISERFS_CHECK
- if (tb->rbytes > vi->vi_entry_count - 1) {
- reiserfs_panic (tb->tb_sb, "vs-8085: check_right: all entries can be shifted to right neighbor");
+ bytes += vi->vi_entry_sizes[j];
+ cur_free -= vi->vi_entry_sizes[j];
+ tb->rbytes ++;
}
-#endif
-
- tb->rbytes = vi->vi_entry_count - 2;
- }
+
+ /* ".." can not be cut from first directory item */
+ if ((vn->vn_vi[i].vi_type & VI_TYPE_FIRST_DIRECTORY_ITEM) && tb->rbytes > vi->vi_entry_count - 2)
+ tb->rbytes = vi->vi_entry_count - 2;
}
- if ( tb->rbytes <= 0 )
- {
+ if ( tb->rbytes <= 0 ) {
/* nothing can flow from the item */
tb->rbytes = -1;
return -1;
- }
-
-
+ }
+
+
/* something can flow from the item */
tb->rnum[0] ++;
-#ifdef CONFIG_REISERFS_CHECK
- if (bytes == -1)
- reiserfs_panic (tb->tb_sb, "vs-8090: check_right: bytes is not initialized");
-#endif
return bytes; /* part of split item in bytes */
}
-
- reiserfs_panic ("vs-8095: check_right: all items fit in the left neighbor");
- return 0;
+
+ reiserfs_panic ("vs-8095: check_right: all items fit in the left neighbor");
+ return 0;
}
/* sum of entry sizes between from-th and to-th entries including both edges */
static int directory_part_size (struct virtual_item * vi, int from, int to)
{
- int i, retval;
-
- retval = 0;
- for (i = from; i <= to; i ++)
- retval += vi->vi_entry_sizes[i];
-
- return retval;
+ int i, retval;
+
+ retval = 0;
+ for (i = from; i <= to; i ++)
+ retval += vi->vi_entry_sizes[i];
+
+ return retval;
}
/*
* from - number of items, which are shifted to left neighbor entirely
* to - number of item, which are shifted to right neighbor entirely
- * from_bytes - number of bytes of boundary item (or directory entries) which are shifted to left neighbor
- * to_bytes - number of bytes of boundary item (or directory entries) which are shifted to right neighbor */
+ * from_bytes - number of bytes of boundary item (or directory entries) which
+ * are shifted to left neighbor
+ * to_bytes - number of bytes of boundary item (or directory entries) which
+ * are shifted to right neighbor */
+
static int get_num_ver (int mode, struct tree_balance * tb, int h,
int from, int from_bytes,
int to, int to_bytes,
short * snum012, int flow
)
{
- int i;
- int bytes;
- struct virtual_node * vn = tb->tb_vn;
- struct virtual_item * vi;
-
- int total_node_size, max_node_size, current_item_size;
- int needed_nodes;
- int start_item, /* position of item we start filling node from */
- end_item, /* position of item we finish filling node by */
- start_bytes,/* number of first bytes (entries for directory) of start_item-th item
- we do not include into node that is being filled */
- end_bytes; /* number of last bytes (entries for directory) of end_item-th item
- we do node include into node that is being filled */
- int splitted_item_positions[2]; /* these are positions in virtual item of items,
+ int i;
+ int bytes;
+ struct virtual_node * vn = tb->tb_vn;
+ struct virtual_item * vi;
+
+ int total_node_size, max_node_size, current_item_size;
+ int needed_nodes;
+ int start_item, /* position of item we start filling node from */
+ end_item, /* position of item we finish filling node by */
+ start_bytes,/* number of first bytes (entries for directory) of start_item-th item
+ we do not include into node that is being filled */
+ end_bytes; /* number of last bytes (entries for directory) of end_item-th item
+ we do node include into node that is being filled */
+ int splitted_item_positions[2]; /* these are positions in virtual item of items,
that are splitted between S[0] and S1new and S1new and S2new */
+ max_node_size = MAX_CHILD_SIZE (tb->tb_fs->fs_blocksize);
+
+ /* snum012 [0-2] - number of items, that lay to S[0], first new node and
+ second new node */
+ snum012[3] = -1; /* s1bytes */
+ snum012[4] = -1; /* s2bytes */
+
-#ifdef CONFIG_REISERFS_CHECK
- /* We only create additional nodes if we are in insert or paste mode
- or we are in replace mode at the internal level. If h is 0 and
- the mode is M_REPLACE then in fix_nodes we change the mode to
- paste or insert before we get here in the code. */
- if ( tb->insert_size[h] < 0 || (mode != M_INSERT && mode != M_PASTE))
- reiserfs_panic (0, "vs-8100: get_num_ver: insert_size < 0 in overflow");
-#endif
-
- max_node_size = MAX_CHILD_SIZE (PATH_H_PBUFFER (tb->tb_path, h));
-
- /* snum012 [0-2] - number of items, that lay
- to S[0], first new node and second new node */
- snum012[3] = -1; /* s1bytes */
- snum012[4] = -1; /* s2bytes */
-
-
- /* internal level */
- if (h > 0) {
- i = ((to - from) * (KEY_SIZE + DC_SIZE) + DC_SIZE);
- if (i == max_node_size)
- return 1;
- return (i / max_node_size + 1);
- }
-
-
- /* leaf level */
- needed_nodes = 1;
- total_node_size = 0;
-
- start_item = from;
- start_bytes = from_bytes;
- end_item = vn->vn_nr_item - to - 1;
- end_bytes = to_bytes;
-
- /* go through all items begining from the start_item-th item and ending by
- the end_item-th item. If start_bytes != -1 we skip first start_bytes
- item units (entries in case of directory). If end_bytes != -1 we skip
- end_bytes units of the end_item-th item. */
- for (i = start_item; i <= end_item; i ++) {
-
-#ifdef CONFIG_REISERFS_CHECK
- if (needed_nodes > 3)
- reiserfs_panic (0, "vs-8105: get_num_ver: too many nodes are needed");
-#endif
-
- /* get size of current item */
- current_item_size = (vi = &vn->vn_vi[i])->vi_item_len;
-
- /* do not take in calculation head part (from_bytes) of from-th item */
- if (i == start_item && start_bytes != -1) {
- if (vi->vi_type & VI_TYPE_DIRECTORY)
- current_item_size -= directory_part_size (vi, 0, start_bytes - 1);
- else
- current_item_size -= start_bytes;
- }
-
- /* do not take in calculation tail part of (to-1)-th item */
- if (i == end_item && end_bytes != -1) {
- if (vi->vi_type & VI_TYPE_DIRECTORY)
- /* first entry, that is not included */
- current_item_size -= directory_part_size (vi, vi->vi_entry_count - end_bytes, vi->vi_entry_count - 1);
- else
- current_item_size -= end_bytes;
- }
-
- /* if item fits into current node entirely */
- if (total_node_size + current_item_size <= max_node_size) {
- snum012[needed_nodes - 1] ++;
- total_node_size += current_item_size;
- continue;
+ /* internal level */
+ if (h > 0) {
+ i = ((to - from) * (KEY_SIZE + DC_SIZE) + DC_SIZE);
+ if (i == max_node_size)
+ return 1;
+ return (i / max_node_size + 1);
}
+
- if (current_item_size > max_node_size) {
- /* virtual item length is longer, than max size of item in a node. It is impossible for direct item */
-#ifdef CONFIG_REISERFS_CHECK
- if (vi->vi_type & VI_TYPE_DIRECT)
- reiserfs_panic (0, "vs-8110: get_num_ver: direct item length is %d. It can not be longer than %d",
- current_item_size, max_node_size);
-#endif
- /* we will try to split it */
- flow = 1;
- }
+ /* leaf level */
+ needed_nodes = 1;
+ total_node_size = 0;
+
+ start_item = from;
+ start_bytes = from_bytes;
+ end_item = vn->vn_nr_item - to - 1;
+ end_bytes = to_bytes;
+
+ /* go through all items begining from the start_item-th item and ending by
+ the end_item-th item. If start_bytes != -1 we skip first start_bytes
+ item units (entries in case of directory). If end_bytes != -1 we skip
+ end_bytes units of the end_item-th item. */
+ for (i = start_item; i <= end_item; i ++) {
+ /* get size of current item */
+ current_item_size = (vi = &vn->vn_vi[i])->vi_item_len;
+
+ /* do not take in calculation head part (from_bytes) of from-th item */
+ if (i == start_item && start_bytes != -1) {
+ if (vi->vi_type & VI_TYPE_DIRECTORY)
+ current_item_size -= directory_part_size (vi, 0, start_bytes - 1);
+ else
+ current_item_size -= start_bytes;
+ }
+
+ /* do not take in calculation tail part of (to-1)-th item */
+ if (i == end_item && end_bytes != -1) {
+ if (vi->vi_type & VI_TYPE_DIRECTORY)
+ /* first entry, that is not included */
+ current_item_size -= directory_part_size (vi, vi->vi_entry_count - end_bytes, vi->vi_entry_count - 1);
+ else
+ current_item_size -= end_bytes;
+ }
+
+ /* if item fits into current node entirely */
+ if (total_node_size + current_item_size <= max_node_size) {
+ snum012[needed_nodes - 1] ++;
+ total_node_size += current_item_size;
+ continue;
+ }
+
+ if (current_item_size > max_node_size)
+ /* virtual item length is longer, than max size of item in a
+ node. It is impossible for direct item */
+ /* we will try to split it */
+ flow = 1;
+
+
+ if (!flow) {
+ /* as we do not split items, take new node and continue */
+ needed_nodes ++; i --; total_node_size = 0;
+ continue;
+ }
+
+ if (total_node_size + (int)IH_SIZE >= max_node_size) {
+ /* even minimal item does not fit into current node, take new node
+ and continue */
+ needed_nodes ++, i--, total_node_size = 0;
+ continue;
+ }
+ if (vi->vi_type & VI_TYPE_STAT_DATA) {
+ /* stat data can not be split */
+ needed_nodes ++, i--, total_node_size = 0;
+ continue;
+ }
+
+ /*bytes is free space in filled node*/
+ bytes = max_node_size - total_node_size - IH_SIZE;
+
+ if (vi->vi_type & VI_TYPE_DIRECT) {
+ /* body of a direct item can be split by 8 bytes. */
+ int align = 8 - (vn->vn_vi[i].vi_item_offset - 1) % 8;
+// reiserfs_warning(stderr,"\nbalancing: cur_free (%d) ", bytes);
+// reiserfs_warning(stderr,"offset (0x%Lx), move (%d), get offset (0x%Lx)",
+// vn->vn_vi[i].vi_item_offset, (bytes - align) / 8 * 8,
+// vn->vn_vi[i].vi_item_offset + ((bytes - align) / 8 * 8));
+ bytes = (bytes >= align) ? (align + ((bytes - align) / 8 * 8)) : 0;
+ }
- if (!flow) {
- /* as we do not split items, take new node and continue */
- needed_nodes ++; i --; total_node_size = 0;
- continue;
- }
- if (total_node_size + (int)IH_SIZE >= max_node_size) {
- /* even minimal item does not fit into current node, take new node and continue */
- needed_nodes ++, i--, total_node_size = 0;
- continue;
- }
- if (vi->vi_type & VI_TYPE_STAT_DATA) {
+ /* item is of indirect type */
+ if (vi->vi_type & VI_TYPE_INDIRECT)
+ /* an unformatted node pointer (having size long) is a solid
+ granule of the item. bytes of unformatted node pointers fits
+ into free space of filled node */
+ bytes -= (bytes) % UNFM_P_SIZE;
+
+ /* S1bytes or S2bytes. It depends from needed_nodes */
+ snum012[needed_nodes - 1 + 3] = bytes;
+
+ /* item is of directory type */
+ if (vi->vi_type & VI_TYPE_DIRECTORY) {
+ /* calculate, how many entries can be put into current node */
+ int j;
+ int end_entry;
+
+ snum012[needed_nodes - 1 + 3] = 0;
- /* stat data can not be split */
- needed_nodes ++, i--, total_node_size = 0;
- continue;
- }
+ total_node_size += IH_SIZE;
+ if (start_bytes == -1 || i != start_item)
+ start_bytes = 0;
+
+ end_entry = vi->vi_entry_count - ((i == end_item && end_bytes != -1) ? end_bytes : 0);
+ for (j = start_bytes; j < end_entry; j ++) {
+ /* j-th entry doesn't fit into current node */
+ if (total_node_size + vi->vi_entry_sizes[j] > max_node_size)
+ break;
+ snum012[needed_nodes - 1 + 3] ++;
+ bytes += vi->vi_entry_sizes[j];
+ total_node_size += vi->vi_entry_sizes[j];
+ }
+ /* "." can not be cut from first directory item */
+ if (start_bytes == 0 && (vn->vn_vi[i].vi_type & VI_TYPE_FIRST_DIRECTORY_ITEM) &&
+ snum012[needed_nodes - 1 + 3] < 2)
+ snum012[needed_nodes - 1 + 3] = 0;
+ }
+
+ if (snum012[needed_nodes-1+3] <= 0 ) {
+ /* nothing fits into current node, take new node and continue */
+ needed_nodes ++, i--, total_node_size = 0;
+ continue;
+ }
+
+ /* something fits into the current node */
+ if (vi->vi_type & VI_TYPE_DIRECTORY)
+ start_bytes += snum012[needed_nodes - 1 + 3];
+ else
+ start_bytes = bytes;
+
+ snum012[needed_nodes - 1] ++;
+ splitted_item_positions[needed_nodes - 1] = i;
- /* body of a direct item can be split at any byte */
- /* bytes is free space in filled node */
- bytes = max_node_size - total_node_size - IH_SIZE;
-
- /* item is of indirect type */
- if (vi->vi_type & VI_TYPE_INDIRECT)
- /* an unformatted node pointer (having size long) is a solid granule of the item */
- /* bytes of unformatted node pointers fits into free space of filled node */
- bytes -= (bytes) % UNFM_P_SIZE;
-
- /* S1bytes or S2bytes. It depends from needed_nodes */
- snum012[needed_nodes - 1 + 3] = bytes;
-
- /* item is of directory type */
- if (vi->vi_type & VI_TYPE_DIRECTORY) {
- /* calculate, how many entries can be put into current node */
- int j;
- int end_entry;
-
- snum012[needed_nodes - 1 + 3] = 0;
-
- total_node_size += IH_SIZE;
- if (start_bytes == -1 || i != start_item)
- start_bytes = 0;
-
- end_entry = vi->vi_entry_count - ((i == end_item && end_bytes != -1) ? end_bytes : 0);
- for (j = start_bytes; j < end_entry; j ++) {
- /* j-th entry doesn't fit into current node */
- if (total_node_size + vi->vi_entry_sizes[j] > max_node_size)
- break;
- snum012[needed_nodes - 1 + 3] ++;
- bytes += vi->vi_entry_sizes[j];
- total_node_size += vi->vi_entry_sizes[j];
- }
- /* "." can not be cut from first directory item */
- if (start_bytes == 0 && (vn->vn_vi[i].vi_type & VI_TYPE_FIRST_DIRECTORY_ITEM) &&
- snum012[needed_nodes - 1 + 3] < 2)
- snum012[needed_nodes - 1 + 3] = 0;
-
-
-#ifdef CONFIG_REISERFS_CHECK
- if (vi->vi_entry_count &&
- vi->vi_entry_count - ((i == end_item && end_bytes != -1) ? end_bytes : 0)
- - (start_bytes) <= snum012[needed_nodes - 1 + 3])
- reiserfs_panic (0, "vs-8115: get_num_ver: required part of directory fits into current node");
-#endif
+ needed_nodes ++;
+ /* continue from the same item with start_bytes != -1 */
+ start_item = i;
+ i --;
+ total_node_size = 0;
}
- if (snum012[needed_nodes-1+3] <= 0 ) {
- /* nothing fits into current node, take new node and continue */
- needed_nodes ++, i--, total_node_size = 0;
- continue;
+
+ /* snum012[3] and snum012[4] contain how many bytes (entries) of split
+ item can be in S[0] and S1new. s1bytes and s2bytes are how many bytes
+ (entries) can be in S1new and S2new. Recalculate it */
+
+ if (snum012[4] > 0) { /* s2bytes */
+ /* get number of item that is split between S1new and S2new */
+ int split_item_num;
+ int bytes_to_r, bytes_to_l;
+
+ split_item_num = splitted_item_positions[1];
+ bytes_to_l = ((from == split_item_num && from_bytes != -1) ? from_bytes : 0);
+ bytes_to_r = ((end_item == split_item_num && end_bytes != -1) ? end_bytes : 0);
+ if (vn->vn_vi[split_item_num].vi_type & VI_TYPE_DIRECTORY) {
+ int entries_to_S2new;
+
+ /* calculate number of entries fit into S2new */
+ entries_to_S2new = vn->vn_vi[split_item_num].vi_entry_count - snum012[4] - bytes_to_r - bytes_to_l;
+ if (snum012[3] != -1 && snum012[1] == 1) {
+ /* directory split into 3 nodes */
+ int entries_to_S1new;
+
+ entries_to_S2new -= snum012[3];
+ entries_to_S1new = snum012[4];
+ snum012[3] = entries_to_S1new;
+ snum012[4] = entries_to_S2new;
+ return needed_nodes;
+ }
+ snum012[4] = entries_to_S2new;
+ } else {
+ /* item is not of directory type */
+ int bytes_to_S2new;
+
+ bytes_to_S2new = vn->vn_vi[split_item_num].vi_item_len - IH_SIZE - snum012[4] - bytes_to_r - bytes_to_l;
+ snum012[4] = bytes_to_S2new;
+ }
}
-
- /* something fits into the current node */
- if (vi->vi_type & VI_TYPE_DIRECTORY)
- start_bytes += snum012[needed_nodes - 1 + 3];
- else
- start_bytes = bytes;
-
- snum012[needed_nodes - 1] ++;
- splitted_item_positions[needed_nodes - 1] = i;
-
- needed_nodes ++;
- /* continue from the same item with start_bytes != -1 */
- start_item = i;
- i --;
- total_node_size = 0;
- }
-
-
- /* snum012[3] and snum012[4] contain how many bytes (entries) of
- split item can be in S[0] and S1new. s1bytes and s2bytes are how
- many bytes (entries) can be in S1new and S2new. Recalculate it */
-
- if (snum012[4] > 0) { /* s2bytes */
- /* get number of item that is split between S1new and S2new */
- int split_item_num;
- int bytes_to_r, bytes_to_l;
-
- split_item_num = splitted_item_positions[1];
- bytes_to_l = ((from == split_item_num && from_bytes != -1) ? from_bytes : 0);
- bytes_to_r = ((end_item == split_item_num && end_bytes != -1) ? end_bytes : 0);
- if (vn->vn_vi[split_item_num].vi_type & VI_TYPE_DIRECTORY) {
- int entries_to_S2new;
-
- /* calculate number of entries fit into S2new */
- entries_to_S2new = vn->vn_vi[split_item_num].vi_entry_count - snum012[4] - bytes_to_r - bytes_to_l;
- if (snum012[3] != -1 && snum012[1] == 1) {
- /* directory split into 3 nodes */
- int entries_to_S1new;
-
- entries_to_S2new -= snum012[3];
- entries_to_S1new = snum012[4];
- snum012[3] = entries_to_S1new;
- snum012[4] = entries_to_S2new;
- return needed_nodes;
- }
- snum012[4] = entries_to_S2new;
- } else {
- /* item is not of directory type */
- int bytes_to_S2new;
-
- bytes_to_S2new = vn->vn_vi[split_item_num].vi_item_len - IH_SIZE - snum012[4] - bytes_to_r - bytes_to_l;
- snum012[4] = bytes_to_S2new;
+
+ /* now we know S2bytes, calculate S1bytes */
+ if (snum012[3] > 0) { /* s1bytes */
+ /* get number of item that is split between S0 and S1new */
+ int split_item_num;
+ int bytes_to_r, bytes_to_l;
+
+ split_item_num = splitted_item_positions[0];
+ bytes_to_l = ((from == split_item_num && from_bytes != -1) ? from_bytes : 0);
+ bytes_to_r = ((end_item == split_item_num && end_bytes != -1) ? end_bytes : 0);
+ if (vn->vn_vi[split_item_num].vi_type & VI_TYPE_DIRECTORY) {
+ /* entries, who go to S1new node */
+ snum012[3] = vn->vn_vi[split_item_num].vi_entry_count - snum012[3] - bytes_to_r - bytes_to_l;
+ } else
+ /* bytes, who go to S1new node (not including HI_SIZE) */
+ snum012[3] = vn->vn_vi[split_item_num].vi_item_len - IH_SIZE - snum012[3] - bytes_to_r - bytes_to_l;
}
- }
-
- /* now we know S2bytes, calculate S1bytes */
- if (snum012[3] > 0) { /* s1bytes */
- /* get number of item that is split between S0 and S1new */
- int split_item_num;
- int bytes_to_r, bytes_to_l;
-
- split_item_num = splitted_item_positions[0];
- bytes_to_l = ((from == split_item_num && from_bytes != -1) ? from_bytes : 0);
- bytes_to_r = ((end_item == split_item_num && end_bytes != -1) ? end_bytes : 0);
- if (vn->vn_vi[split_item_num].vi_type & VI_TYPE_DIRECTORY) {
- /* entries, who go to S1new node */
- snum012[3] = vn->vn_vi[split_item_num].vi_entry_count - snum012[3] - bytes_to_r - bytes_to_l;
- } else
- /* bytes, who go to S1new node (not including HI_SIZE) */
- snum012[3] = vn->vn_vi[split_item_num].vi_item_len - IH_SIZE - snum012[3] - bytes_to_r - bytes_to_l;
- }
-
- return needed_nodes;
+
+ return needed_nodes;
}
-
-#ifdef CONFIG_REISERFS_CHECK
-extern struct tree_balance * cur_tb;
-#endif
-
-
-/* size of item_num-th item in bytes when regular and in entries when
- item is directory */
+/* size of item_num-th item in bytes when regular and in entries when item is
+ directory */
static int item_length (struct tree_balance * tb, int item_num)
{
- struct virtual_node * vn = tb->tb_vn;
-
-#ifdef CONFIG_REISERFS_CHECK
- if (item_num >= vn->vn_nr_item)
- reiserfs_panic (tb->tb_sb, "vs-8120: item_length: invalid index of item: index = %d (item number = %d)", item_num, vn->vn_nr_item);
-#endif
+ struct virtual_node * vn = tb->tb_vn;
- if (vn->vn_vi[item_num].vi_type & VI_TYPE_DIRECTORY)
- return vn->vn_vi[item_num].vi_entry_count;
+ if (vn->vn_vi[item_num].vi_type & VI_TYPE_DIRECTORY)
+ return vn->vn_vi[item_num].vi_entry_count;
- return vn->vn_vi[item_num].vi_item_len - IH_SIZE;
+ return vn->vn_vi[item_num].vi_item_len - IH_SIZE;
}
@@ -955,22 +791,22 @@ static void set_parameters (struct tree_balance * tb, int h, int lnum,
int rnum, int blk_num, short * s012, int lb, int rb)
{
- tb->lnum[h] = lnum;
- tb->rnum[h] = rnum;
- tb->blknum[h] = blk_num;
+ tb->lnum[h] = lnum;
+ tb->rnum[h] = rnum;
+ tb->blknum[h] = blk_num;
- if (h == 0)
+ if (h == 0)
{ /* only for leaf level */
- if (s012 != NULL)
+ if (s012 != NULL)
{
- tb->s0num = * s012 ++,
- tb->s1num = * s012 ++,
- tb->s2num = * s012 ++;
- tb->s1bytes = * s012 ++;
- tb->s2bytes = * s012;
+ tb->s0num = * s012 ++,
+ tb->s1num = * s012 ++,
+ tb->s2num = * s012 ++;
+ tb->s1bytes = * s012 ++;
+ tb->s2bytes = * s012;
}
- tb->lbytes = lb;
- tb->rbytes = rb;
+ tb->lbytes = lb;
+ tb->rbytes = rb;
}
}
@@ -981,7 +817,7 @@ static void decrement_key (struct key * p_s_key)
type = get_type (p_s_key);
switch (type) {
case TYPE_STAT_DATA:
- p_s_key->k_objectid --;
+ set_key_objectid (p_s_key, get_key_objectid (p_s_key) - 1);
set_type_and_offset (key_format (p_s_key), p_s_key,
(loff_t)MAX_FILE_SIZE_V2, TYPE_INDIRECT);
return;
@@ -996,55 +832,13 @@ static void decrement_key (struct key * p_s_key)
}
reiserfs_warning (stderr, "vs-8125: decrement_key: item of wrong type found %k",
p_s_key);
-#if 0
-
- unsigned long * p_n_key_field = (unsigned long *)p_s_key + REISERFS_FULL_KEY_LEN - 1;
- int n_counter;
-
-
- for( n_counter = 0; n_counter < REISERFS_FULL_KEY_LEN; n_counter++, p_n_key_field-- )
- if ( *p_n_key_field ) {
- (*p_n_key_field)--;
- break;
- }
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( n_counter == REISERFS_FULL_KEY_LEN )
- reiserfs_panic(NULL, "PAP-8175: decrement_key: zero key");
-#endif
-
-#endif
-
-}
-
-
-#ifdef FU //REISERFS_FSCK
-
-inline int is_left_mergeable (struct item_head * ih, unsigned long bsize)
-{
- if (I_IS_DIRECT_ITEM (ih))
- return ((get_offset (&ih->ih_key) & (bsize - 1)) != 1);
-
- if (I_IS_INDIRECT_ITEM (ih))
- return (get_offset (&ih->ih_key) != 1);
-
- if (I_IS_DIRECTORY_ITEM (ih))
- return ((ih)->ih_key.u.k_offset_v1.k_offset != DOT_OFFSET);
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( ! I_IS_STAT_DATA_ITEM (ih))
- reiserfs_panic (0, "vs-16060: is_left_mergeable: item [%h] must be a stat data", ih);
-#endif
-
- return 0;
}
-#else
int are_items_mergeable (struct item_head * left, struct item_head * right, int bsize)
{
if (comp_keys (&left->ih_key, &right->ih_key) != -1) {
- reiserfs_panic (0, "vs-16070: are_items_mergeable: left %k, right %k", &(left->ih_key), &(right->ih_key));
+ reiserfs_panic ("vs-16070: are_items_mergeable: left %k, right %k", &(left->ih_key), &(right->ih_key));
}
if (not_of_one_file (&left->ih_key, &right->ih_key))
@@ -1062,18 +856,17 @@ int are_items_mergeable (struct item_head * left, struct item_head * right, int
}
/* get left neighbor of the leaf node */
-static struct buffer_head * get_left_neighbor (struct super_block * s, struct path * path)
+static struct buffer_head * get_left_neighbor (reiserfs_filsys_t * s, struct path * path)
{
struct key key;
struct path path_to_left_neighbor;
struct buffer_head * bh;
- int repeat;
copy_key (&key, B_N_PKEY (PATH_PLAST_BUFFER (path), 0));
decrement_key (&key);
init_path (&path_to_left_neighbor);
- search_by_key (s, &key, &path_to_left_neighbor, &repeat, DISK_LEAF_NODE_LEVEL);
+ search_by_key (s, &key, &path_to_left_neighbor, DISK_LEAF_NODE_LEVEL);
if (PATH_LAST_POSITION (&path_to_left_neighbor) == 0) {
pathrelse (&path_to_left_neighbor);
return 0;
@@ -1084,112 +877,109 @@ static struct buffer_head * get_left_neighbor (struct super_block * s, struct pa
return bh;
}
+
extern struct key MIN_KEY;
-static struct buffer_head * get_right_neighbor (struct super_block * s, struct path * path)
+static struct buffer_head * get_right_neighbor (reiserfs_filsys_t * s, struct path * path)
{
- struct key key;
- struct key * rkey;
- int repeat;
- struct path path_to_right_neighbor;
- struct buffer_head * bh;
-
- rkey = get_rkey (path, s);
- if (comp_keys (rkey, &MIN_KEY) == 0)
- reiserfs_panic ("vs-16080: get_right_neighbor: get_rkey returned min key (path has changed)");
- copy_key (&key, rkey);
-
+ struct key key;
+ struct key * rkey;
+ struct path path_to_right_neighbor;
+ struct buffer_head * bh;
+
+ rkey = get_rkey (path, s);
+ if (comp_keys (rkey, &MIN_KEY) == 0)
+ reiserfs_panic ("vs-16080: get_right_neighbor: get_rkey returned min key (path has changed)");
+ copy_key (&key, rkey);
+
- init_path (&path_to_right_neighbor);
- search_by_key (s, &key, &path_to_right_neighbor, &repeat, DISK_LEAF_NODE_LEVEL);
- if (PATH_PLAST_BUFFER (&path_to_right_neighbor) == PATH_PLAST_BUFFER (path)) {
+ init_path (&path_to_right_neighbor);
+ search_by_key (s, &key, &path_to_right_neighbor, DISK_LEAF_NODE_LEVEL);
+ if (PATH_PLAST_BUFFER (&path_to_right_neighbor) == PATH_PLAST_BUFFER (path)) {
+ pathrelse (&path_to_right_neighbor);
+ return 0;
+ }
+ bh = PATH_PLAST_BUFFER (&path_to_right_neighbor);
+ bh->b_count ++;
pathrelse (&path_to_right_neighbor);
- return 0;
- }
- bh = PATH_PLAST_BUFFER (&path_to_right_neighbor);
- bh->b_count ++;
- pathrelse (&path_to_right_neighbor);
- return bh;
+ return bh;
}
-int is_left_mergeable (struct super_block * s, struct path * path)
+int is_left_mergeable (reiserfs_filsys_t * s, struct path * path)
{
- struct item_head * right;
- struct buffer_head * bh;
- int retval;
-
- right = B_N_PITEM_HEAD (PATH_PLAST_BUFFER (path), 0);
-
- bh = get_left_neighbor (s, path);
- if (bh == 0) {
- return 0;
- }
- retval = are_items_mergeable (B_N_PITEM_HEAD (bh, B_NR_ITEMS (bh) - 1), right, bh->b_size);
- brelse (bh);
- return retval;
+ struct item_head * right;
+ struct buffer_head * bh;
+ int retval;
+
+ right = B_N_PITEM_HEAD (PATH_PLAST_BUFFER (path), 0);
+
+ bh = get_left_neighbor (s, path);
+ if (bh == 0) {
+ return 0;
+ }
+ retval = are_items_mergeable (B_N_PITEM_HEAD (bh, B_NR_ITEMS (bh) - 1), right, bh->b_size);
+ brelse (bh);
+ return retval;
}
-int is_right_mergeable (struct super_block * s, struct path * path)
+int is_right_mergeable (reiserfs_filsys_t * s, struct path * path)
{
- struct item_head * left;
- struct buffer_head * bh;
- int retval;
-
- left = B_N_PITEM_HEAD (PATH_PLAST_BUFFER (path), B_NR_ITEMS (PATH_PLAST_BUFFER (path)) - 1);
-
- bh = get_right_neighbor (s, path);
- if (bh == 0) {
- return 0;
- }
- retval = are_items_mergeable (left, B_N_PITEM_HEAD (bh, 0), bh->b_size);
- brelse (bh);
- return retval;
+ struct item_head * left;
+ struct buffer_head * bh;
+ int retval;
+
+ left = B_N_PITEM_HEAD (PATH_PLAST_BUFFER (path), B_NR_ITEMS (PATH_PLAST_BUFFER (path)) - 1);
+
+ bh = get_right_neighbor (s, path);
+ if (bh == 0) {
+ return 0;
+ }
+ retval = are_items_mergeable (left, B_N_PITEM_HEAD (bh, 0), bh->b_size);
+ brelse (bh);
+ return retval;
}
-#endif /* REISERFS_FSCK */
-
-/* check, does node disappear if we shift tb->lnum[0] items to left
- neighbor and tb->rnum[0] to the right one. */
+/* check, does node disappear if we shift tb->lnum[0] items to left neighbor
+ and tb->rnum[0] to the right one. */
static int is_leaf_removable (struct tree_balance * tb)
{
- struct virtual_node * vn = tb->tb_vn;
- int to_left, to_right;
- int size;
- int remain_items;
-
- /* number of items, that will be shifted to left (right) neighbor
- entirely */
- to_left = tb->lnum[0] - ((tb->lbytes != -1) ? 1 : 0);
- to_right = tb->rnum[0] - ((tb->rbytes != -1) ? 1 : 0);
- remain_items = vn->vn_nr_item;
-
- /* how many items remain in S[0] after shiftings to neighbors */
- remain_items -= (to_left + to_right);
-
- if (remain_items < 1) {
- /* all content of node can be shifted to neighbors */
- set_parameters (tb, 0, to_left, vn->vn_nr_item - to_left, 0, NULL, -1, -1);
- return 1;
- }
-
- if (remain_items > 1 || tb->lbytes == -1 || tb->rbytes == -1)
- /* S[0] is not removable */
+ struct virtual_node * vn = tb->tb_vn;
+ int to_left, to_right;
+ int size;
+ int remain_items;
+
+ /* number of items, that will be shifted to left (right) neighbor entirely */
+ to_left = tb->lnum[0] - ((tb->lbytes != -1) ? 1 : 0);
+ to_right = tb->rnum[0] - ((tb->rbytes != -1) ? 1 : 0);
+ remain_items = vn->vn_nr_item;
+
+ /* how many items remain in S[0] after shiftings to neighbors */
+ remain_items -= (to_left + to_right);
+
+ if (remain_items < 1) {
+ /* all content of node can be shifted to neighbors */
+ set_parameters (tb, 0, to_left, vn->vn_nr_item - to_left, 0, NULL, -1, -1);
+ return 1;
+ }
+
+ if (remain_items > 1 || tb->lbytes == -1 || tb->rbytes == -1)
+ /* S[0] is not removable */
+ return 0;
+
+ /* check, whether we can divide 1 remaining item between neighbors */
+
+ /* get size of remaining item (in directory entry count if directory) */
+ size = item_length (tb, to_left);
+
+ if (tb->lbytes + tb->rbytes >= size) {
+ set_parameters (tb, 0, to_left + 1, to_right + 1, 0, NULL, tb->lbytes, -1);
+ return 1;
+ }
+
return 0;
-
- /* check, whether we can divide 1 remaining item between neighbors */
-
- /* get size of remaining item (in directory entry count if directory) */
- size = item_length (tb, to_left);
-
- if (tb->lbytes + tb->rbytes >= size) {
- set_parameters (tb, 0, to_left + 1, to_right + 1, 0, NULL, tb->lbytes, -1);
- return 1;
- }
-
- return 0;
}
@@ -1213,43 +1003,16 @@ static int are_leaves_removable (struct tree_balance * tb, int lfree, int rfree)
/* there was only one item and it will be deleted */
struct item_head * ih;
-#ifdef CONFIG_REISERFS_CHECK
- if (B_NR_ITEMS (S0) != 1)
- reiserfs_panic (0, "vs-8125: are_leaves_removable: item number must be 1: it is %d", B_NR_ITEMS(S0));
-#endif
-
ih = B_N_PITEM_HEAD (S0, 0);
if (tb->CFR[0] && !not_of_one_file (&(ih->ih_key), B_N_PDELIM_KEY (tb->CFR[0], tb->rkey[0])))
if (I_IS_DIRECTORY_ITEM(ih)) {
-#ifdef FU //REISERFS_FSCK
-
- /* Directory must be in correct state here: that is
- somewhere at the left side should exist first
- directory item. But the item being deleted can not
- be that first one because its right neighbor is
- item of the same directory. (But first item always
- gets deleted in last turn). So, neighbors of
- deleted item can be merged, so we can save ih_size */
- ih_size = IH_SIZE;
-
-#ifdef CONFIG_REISERFS_CHECK
- /* we might check that left neighbor exists and is of
- the same directory */
- if (get_offset (&ih->ih_key) == DOT_OFFSET)
- reiserfs_panic (tb->tb_sb, "vs-8130: are_leaves_removable: "
- "first directory item can not be removed until directory is not empty");
-#endif
-
-
-#else /* REISERFS_FSCK */
-
/* we can delete any directory item in fsck (if it is unreachable) */
if (get_offset (&ih->ih_key) != DOT_OFFSET) {
/* must get left neighbor here to make sure, that
left neighbor is of the same directory */
struct buffer_head * left;
- left = get_left_neighbor (tb->tb_sb, tb->tb_path);
+ left = get_left_neighbor (tb->tb_fs, tb->tb_path);
if (left) {
struct item_head * last;
@@ -1262,12 +1025,11 @@ static int are_leaves_removable (struct tree_balance * tb, int lfree, int rfree)
brelse (left);
}
}
-#endif
}
}
- if (MAX_CHILD_SIZE (S0) + vn->vn_size <= rfree + lfree + ih_size) {
+ if (MAX_CHILD_SIZE (S0->b_size) + vn->vn_size <= rfree + lfree + ih_size) {
set_parameters (tb, 0, -1, -1, -1, NULL, -1, -1);
return 1;
}
@@ -1318,30 +1080,6 @@ else \
-1, -1);\
}
-#if 0
-void free_buffers_in_tb (
- struct tree_balance * p_s_tb
- ) {
- int n_counter;
-
- decrement_counters_in_path(p_s_tb->tb_path);
-
- for ( n_counter = 0; n_counter < MAX_HEIGHT; n_counter++ ) {
- decrement_bcount(p_s_tb->L[n_counter]);
- p_s_tb->L[n_counter] = NULL;
- decrement_bcount(p_s_tb->R[n_counter]);
- p_s_tb->R[n_counter] = NULL;
- decrement_bcount(p_s_tb->FL[n_counter]);
- p_s_tb->FL[n_counter] = NULL;
- decrement_bcount(p_s_tb->FR[n_counter]);
- p_s_tb->FR[n_counter] = NULL;
- decrement_bcount(p_s_tb->CFL[n_counter]);
- p_s_tb->CFL[n_counter] = NULL;
- decrement_bcount(p_s_tb->CFR[n_counter]);
- p_s_tb->CFR[n_counter] = NULL;
- }
-}
-#endif
/* Get new buffers for storing new nodes that are created while balancing.
@@ -1359,15 +1097,12 @@ static int get_empty_nodes (struct tree_balance * p_s_tb,
int n_counter,
n_number_of_freeblk,
n_amount_needed,/* number of needed empty blocks */
- n_repeat1,
n_repeat;
- struct super_block * p_s_sb = p_s_tb->tb_sb;
+ reiserfs_filsys_t * fs = p_s_tb->tb_fs;
- //#ifndef FU //REISERFS_FSCK
if (n_h == 0 && p_s_tb->insert_size[n_h] == 0x7fff)
return CARRY_ON;
- //#endif
/* number_of_freeblk is the number of empty blocks which have been
acquired for use by the balancing algorithm minus the number of
@@ -1398,41 +1133,24 @@ static int get_empty_nodes (struct tree_balance * p_s_tb,
else /* If we have enough already then there is nothing to do. */
return CARRY_ON;
- if ( (n_repeat = reiserfs_new_blocknrs (p_s_tb->tb_sb, a_n_blocknrs,
+ if ( (n_repeat = reiserfs_new_blocknrs (p_s_tb->tb_fs, a_n_blocknrs,
PATH_PLAST_BUFFER(p_s_tb->tb_path)->b_blocknr, n_amount_needed)) != CARRY_ON ) {
- return n_repeat; /* Out of disk space or schedule() occured. */
+ return n_repeat; /* Out of disk space. */
}
-
/* for each blocknumber we just got, get a buffer and stick it on FEB */
for ( p_n_blocknr = a_n_blocknrs, n_counter = 0; n_counter < n_amount_needed;
p_n_blocknr++, n_counter++ ) {
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( ! *p_n_blocknr )
- reiserfs_panic(p_s_sb, "PAP-8135: get_empty_nodes: reiserfs_new_blocknrs failed when got new blocks");
-#endif
-
- n_repeat1 = CARRY_ON;
- p_s_new_bh = reiserfs_getblk(p_s_sb->s_dev, *p_n_blocknr, p_s_sb->s_blocksize, &n_repeat1);
- n_repeat |= n_repeat1;
+ p_s_new_bh = getblk (fs->fs_dev, *p_n_blocknr, fs->fs_blocksize);
if (p_s_new_bh->b_count > 1) {
die ("get_empty_nodes: not free empty buffer");
}
-#ifdef CONFIG_REISERFS_CHECK_NOCHECK
- if ((p_s_new_bh->b_count != 1 && !buffer_journaled(p_s_new_bh))
- || (buffer_dirty (p_s_new_bh) && !buffer_journal_dirty(p_s_new_bh))) {
- reiserfs_panic(p_s_sb,"PAP-8140: get_empty_nodes: not free or dirty buffer %b for the new block",
- p_s_new_bh);
- }
-#endif
- //mark_buffer_journal_new(p_s_new_bh) ;
/* Put empty buffers into the array. */
p_s_tb->FEB[p_s_tb->cur_blknum++] = p_s_new_bh;
}
- return n_repeat;
+ return CARRY_ON;
}
@@ -1450,85 +1168,64 @@ static int get_lfree (struct tree_balance * tb, int h)
if (f == l)
order = PATH_H_B_ITEM_ORDER (tb->tb_path, h) - 1;
else {
- order = B_BLK_HEAD(l)->blk_nr_item;
+ order = get_blkh_nr_items (B_BLK_HEAD(l));
f = l;
}
- if (B_N_CHILD(f,order)->dc_size == 0) {
+ if (get_dc_child_size (B_N_CHILD(f,order)) == 0) {
reiserfs_warning (stderr, "get_lfree: block %u block_head %z has bad child pointer %y, order %d\n",
l->b_blocknr, l, B_N_CHILD(f,order), order);
}
- return (MAX_CHILD_SIZE(f) - B_N_CHILD(f,order)->dc_size);
+ return (MAX_CHILD_SIZE(f->b_size) - get_dc_child_size (B_N_CHILD(f,order)));
}
-/* Get free space of the right neighbor,
- * which is stored in the parent node of the right neighbor.
- */
+/* Get free space of the right neighbor, which is stored in the parent node of
+ * the right neighbor. */
static int get_rfree (struct tree_balance * tb, int h)
{
- struct buffer_head * r, * f;
- int order;
+ struct buffer_head * r, * f;
+ int order;
- if ((f = PATH_H_PPARENT (tb->tb_path, h)) == 0 || (r = tb->FR[h]) == 0)
- return 0;
+ if ((f = PATH_H_PPARENT (tb->tb_path, h)) == 0 || (r = tb->FR[h]) == 0)
+ return 0;
- if (f == r)
- order = PATH_H_B_ITEM_ORDER (tb->tb_path, h) + 1;
- else {
- order = 0;
- f = r;
- }
+ if (f == r)
+ order = PATH_H_B_ITEM_ORDER (tb->tb_path, h) + 1;
+ else {
+ order = 0;
+ f = r;
+ }
- return (MAX_CHILD_SIZE(f) - B_N_CHILD(f,order)->dc_size);
+ return (MAX_CHILD_SIZE(f->b_size) - get_dc_child_size (B_N_CHILD(f,order)));
}
/* Check whether left neighbor is in memory. */
-static int is_left_neighbor_in_cache(
- struct tree_balance * p_s_tb,
- int n_h
- ) {
- struct buffer_head * p_s_father;
- struct super_block * p_s_sb = p_s_tb->tb_sb;
- unsigned long n_left_neighbor_blocknr;
- int n_left_neighbor_position;
-
- if ( ! p_s_tb->FL[n_h] ) /* Father of the left neighbor does not exist. */
- return 0;
-
- /* Calculate father of the node to be balanced. */
- p_s_father = PATH_H_PBUFFER(p_s_tb->tb_path, n_h + 1);
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( ! p_s_father || ! B_IS_IN_TREE (p_s_father) || ! B_IS_IN_TREE (p_s_tb->FL[n_h]) ||
- ! buffer_uptodate (p_s_father) || ! buffer_uptodate (p_s_tb->FL[n_h]) ) {
- reiserfs_panic (p_s_sb, "vs-8165: is_left_neighbor_in_cache: F[h] (%b) or FL[h] (%b) is invalid",
- p_s_father, p_s_tb->FL[n_h]);
- }
-#endif
-
-
- /* Get position of the pointer to the left neighbor into the left father. */
- n_left_neighbor_position = ( p_s_father == p_s_tb->FL[n_h] ) ?
- p_s_tb->lkey[n_h] : B_BLK_HEAD(p_s_tb->FL[n_h])->blk_nr_item;
- /* Get left neighbor block number. */
- n_left_neighbor_blocknr = B_N_CHILD_NUM(p_s_tb->FL[n_h], n_left_neighbor_position);
- /* Look for the left neighbor in the cache. */
- if ( (p_s_father = find_buffer(p_s_sb->s_dev, n_left_neighbor_blocknr, p_s_sb->s_blocksize)) ) {
+static int is_left_neighbor_in_cache (struct tree_balance * p_s_tb,
+ int n_h)
+{
+ struct buffer_head * p_s_father;
+ reiserfs_filsys_t * fs = p_s_tb->tb_fs;
+ unsigned long n_left_neighbor_blocknr;
+ int n_left_neighbor_position;
-#ifdef CONFIG_REISERFS_CHECK
- if ( buffer_uptodate (p_s_father) && ! B_IS_IN_TREE(p_s_father) ) {
- reiserfs_panic(p_s_sb, "vs-8170: is_left_neighbor_in_cache: left neighbor (%b %z) is not in the tree",
- p_s_father, p_s_father);
- }
-#endif
+ if ( ! p_s_tb->FL[n_h] ) /* Father of the left neighbor does not exist. */
+ return 0;
- return 1;
- }
+ /* Calculate father of the node to be balanced. */
+ p_s_father = PATH_H_PBUFFER(p_s_tb->tb_path, n_h + 1);
+ /* Get position of the pointer to the left neighbor into the left father. */
+ n_left_neighbor_position = ( p_s_father == p_s_tb->FL[n_h] ) ?
+ p_s_tb->lkey[n_h] : get_blkh_nr_items (B_BLK_HEAD(p_s_tb->FL[n_h]));
+ /* Get left neighbor block number. */
+ n_left_neighbor_blocknr = get_dc_child_blocknr (B_N_CHILD (p_s_tb->FL[n_h], n_left_neighbor_position));
+ /* Look for the left neighbor in the cache. */
+ if ( (p_s_father = find_buffer(fs->fs_dev, n_left_neighbor_blocknr, fs->fs_blocksize)) )
+ return 1;
- return 0;
+ return 0;
}
@@ -1537,10 +1234,9 @@ static int is_left_neighbor_in_cache(
-
void init_path (struct path * path)
{
- path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
+ path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
}
@@ -1552,121 +1248,90 @@ void init_path (struct path * path)
SCHEDULE_OCCURRED - schedule occured while the function worked;
* CARRY_ON - schedule didn't occur while the function worked;
*/
-static int get_far_parent(
- struct tree_balance * p_s_tb,
- int n_h,
- struct buffer_head ** pp_s_father,
- struct buffer_head ** pp_s_com_father,
- char c_lr_par
- ) {
- struct buffer_head * p_s_parent;
- struct path s_path_to_neighbor_father,
- * p_s_path = p_s_tb->tb_path;
- struct key s_lr_father_key;
- int n_counter,
- n_position = INT_MAX,
- n_repeat,
- n_first_last_position = 0,
- n_path_offset = PATH_H_PATH_OFFSET(p_s_path, n_h);
-
- /* Starting from F[n_h] go upwards in the tree, and look for the common
- ancestor of F[n_h], and its neighbor l/r, that should be obtained. */
-
- n_counter = n_path_offset;
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( n_counter < FIRST_PATH_ELEMENT_OFFSET )
- reiserfs_panic(p_s_tb->tb_sb, "PAP-8180: get_far_parent: invalid path length");
-#endif
-
-
- for ( ; n_counter > FIRST_PATH_ELEMENT_OFFSET; n_counter-- ) {
- /* Check whether parent of the current buffer in the path is really parent in the tree. */
- if ( ! B_IS_IN_TREE(p_s_parent = PATH_OFFSET_PBUFFER(p_s_path, n_counter - 1)) )
- return PATH_INCORRECT;
- /* Check whether position in the parent is correct. */
- if ( (n_position = PATH_OFFSET_POSITION(p_s_path, n_counter - 1)) > B_NR_ITEMS(p_s_parent) )
- return PATH_INCORRECT;
- /* Check whether parent at the path really points to the child. */
- if ( B_N_CHILD_NUM(p_s_parent, n_position) !=
- PATH_OFFSET_PBUFFER(p_s_path, n_counter)->b_blocknr )
- return PATH_INCORRECT;
- /* Return delimiting key if position in the parent is not equal to first/last one. */
- if ( c_lr_par == RIGHT_PARENTS )
- n_first_last_position = B_BLK_HEAD(p_s_parent)->blk_nr_item;
- if ( n_position != n_first_last_position ) {
- (*pp_s_com_father = p_s_parent)->b_count++;
- break;
- }
- }
-
- /* Hopefully we are in the root of the tree. */
- if ( n_counter == FIRST_PATH_ELEMENT_OFFSET ) {
- /* Check whether first buffer in the path is the root of the tree. */
- if ( PATH_OFFSET_PBUFFER(p_s_tb->tb_path, FIRST_PATH_ELEMENT_OFFSET)->b_blocknr ==
- SB_ROOT_BLOCK (p_s_tb->tb_sb) ) {
- *pp_s_father = *pp_s_com_father = NULL;
- return CARRY_ON;
+static int get_far_parent (struct tree_balance * p_s_tb,
+ int n_h,
+ struct buffer_head ** pp_s_father,
+ struct buffer_head ** pp_s_com_father,
+ char c_lr_par)
+{
+ struct buffer_head * p_s_parent;
+ struct path s_path_to_neighbor_father,
+ * p_s_path = p_s_tb->tb_path;
+ struct key s_lr_father_key;
+ int n_counter,
+ n_position = -1,
+ n_first_last_position = 0,
+ n_path_offset = PATH_H_PATH_OFFSET(p_s_path, n_h);
+
+ /* Starting from F[n_h] go upwards in the tree, and look for the common
+ ancestor of F[n_h], and its neighbor l/r, that should be obtained. */
+
+ n_counter = n_path_offset;
+
+ for ( ; n_counter > FIRST_PATH_ELEMENT_OFFSET; n_counter-- ) {
+ /* Check whether parent of the current buffer in the path is really parent in the tree. */
+ if ( ! B_IS_IN_TREE(p_s_parent = PATH_OFFSET_PBUFFER(p_s_path, n_counter - 1)) )
+ reiserfs_panic ("get_far_parent: buffer of path is notin the tree");
+
+ /* Check whether position in the parent is correct. */
+ if ( (n_position = PATH_OFFSET_POSITION(p_s_path, n_counter - 1)) > B_NR_ITEMS(p_s_parent) )
+ reiserfs_panic ("get_far_parent: incorrect position in the parent");
+
+ /* Check whether parent at the path really points to the child. */
+ if ( get_dc_child_blocknr (B_N_CHILD (p_s_parent, n_position)) !=
+ PATH_OFFSET_PBUFFER(p_s_path, n_counter)->b_blocknr )
+ reiserfs_panic ("get_far_parent: incorrect disk child in the parent");
+
+ /* Return delimiting key if position in the parent is not equal to first/last one. */
+ if ( c_lr_par == RIGHT_PARENTS )
+ n_first_last_position = get_blkh_nr_items (B_BLK_HEAD(p_s_parent));
+ if ( n_position != n_first_last_position ) {
+ (*pp_s_com_father = p_s_parent)->b_count++;
+ break;
+ }
}
- return PATH_INCORRECT;
- }
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( B_BLK_HEAD(*pp_s_com_father)->blk_level <= DISK_LEAF_NODE_LEVEL ) {
- reiserfs_panic(p_s_tb->tb_sb, "PAP-8185: get_far_parent: (%b %z) level too small", *pp_s_com_father, *pp_s_com_father);
- }
-#endif
-
- /* Check whether the common parent is locked. */
-#if 0
- if ( test_and_wait_on_buffer(*pp_s_com_father) == SCHEDULE_OCCURRED ) {
- decrement_bcount(*pp_s_com_father);
- return SCHEDULE_OCCURRED; /* schedule() occured */
- }
-#endif
-
- /* So, we got common parent of the current node and its left/right neighbor.
- Now we are geting the parent of the left/right neighbor. */
-
- /* Form key to get parent of the left/right neighbor. */
- copy_key(&s_lr_father_key, B_N_PDELIM_KEY(*pp_s_com_father, ( c_lr_par == LEFT_PARENTS ) ?
- (p_s_tb->lkey[n_h - 1] = n_position - 1) : (p_s_tb->rkey[n_h - 1] = n_position)));
-
- if ( c_lr_par == LEFT_PARENTS ) {
- //reiserfs_warning ("decrememnting key %k\n", &s_lr_father_key);
- decrement_key(&s_lr_father_key);
- //reiserfs_warning ("done: %k\n", &s_lr_father_key);
- }
-
- init_path (&s_path_to_neighbor_father);
+
+ /* we are in the root of the tree. */
+ if ( n_counter == FIRST_PATH_ELEMENT_OFFSET ) {
+ struct reiserfs_super_block * sb;
- if (search_by_key(p_s_tb->tb_sb, &s_lr_father_key, &s_path_to_neighbor_father, &n_repeat, n_h + 1) == IO_ERROR)
- return IO_ERROR;
+ sb = p_s_tb->tb_fs->fs_ondisk_sb;
- if ( n_repeat != CARRY_ON ) {
- pathrelse (&s_path_to_neighbor_father);
- //decrement_counters_in_path(&s_path_to_neighbor_father);
- brelse (*pp_s_com_father);
- //decrement_bcount(*pp_s_com_father);
- return n_repeat;
- }
+ /* Check whether first buffer in the path is the root of the tree. */
+ if ( PATH_OFFSET_PBUFFER(p_s_tb->tb_path, FIRST_PATH_ELEMENT_OFFSET)->b_blocknr ==
+ get_sb_root_block (sb) ) {
+ *pp_s_father = *pp_s_com_father = NULL;
+ return CARRY_ON;
+ }
+ reiserfs_panic ("get_far_parent: root not found in the path");
+ }
+
+ if (n_position == -1)
+ reiserfs_panic ("get_far_parent: position is not defined");
- *pp_s_father = PATH_PLAST_BUFFER(&s_path_to_neighbor_father);
+ /* So, we got common parent of the current node and its left/right
+ neighbor. Now we are geting the parent of the left/right neighbor. */
-#ifdef CONFIG_REISERFS_CHECK
- if ( B_BLK_HEAD(*pp_s_father)->blk_level != n_h + 1 ) {
- reiserfs_panic(p_s_tb->tb_sb, "PAP-8190: get_far_parent: (%b %z) level too small", *pp_s_father, *pp_s_father);
- }
-
- if ( s_path_to_neighbor_father.path_length < FIRST_PATH_ELEMENT_OFFSET )
- reiserfs_panic(0, "PAP-8192: get_far_parent: path length is too small");
+ /* Form key to get parent of the left/right neighbor. */
+ copy_key(&s_lr_father_key, B_N_PDELIM_KEY(*pp_s_com_father, ( c_lr_par == LEFT_PARENTS ) ?
+ (p_s_tb->lkey[n_h - 1] = n_position - 1) : (p_s_tb->rkey[n_h - 1] = n_position)));
-#endif
+ if ( c_lr_par == LEFT_PARENTS ) {
+ //reiserfs_warning ("decrememnting key %k\n", &s_lr_father_key);
+ decrement_key(&s_lr_father_key);
+ //reiserfs_warning ("done: %k\n", &s_lr_father_key);
+ }
- s_path_to_neighbor_father.path_length--;
- pathrelse (&s_path_to_neighbor_father);
- //decrement_counters_in_path(&s_path_to_neighbor_father);
- return CARRY_ON;
+ init_path (&s_path_to_neighbor_father);
+
+ if (search_by_key(p_s_tb->tb_fs, &s_lr_father_key, &s_path_to_neighbor_father, n_h + 1) == IO_ERROR)
+ return IO_ERROR;
+
+ *pp_s_father = PATH_PLAST_BUFFER(&s_path_to_neighbor_father);
+ s_path_to_neighbor_father.path_length--;
+ pathrelse (&s_path_to_neighbor_father);
+ //decrement_counters_in_path(&s_path_to_neighbor_father);
+ return CARRY_ON;
}
@@ -1716,13 +1381,6 @@ static int get_parents (struct tree_balance * p_s_tb, int n_h)
if ( (n_ret_value = get_far_parent(p_s_tb, n_h + 1, &p_s_curf,
&p_s_curcf, LEFT_PARENTS)) != CARRY_ON )
return n_ret_value; /*schedule() occured or path is not correct*/
-#ifdef CONFIG_REISERFS_CHECK
- if (p_s_curf == PATH_OFFSET_PBUFFER(p_s_path, n_path_offset - 1)) {
- reiserfs_panic (p_s_tb->tb_sb, "vs-8194: get_parents: "
- "get_far_parent fails");
- }
-#endif
-
}
brelse(p_s_tb->FL[n_h]);
@@ -1731,16 +1389,10 @@ static int get_parents (struct tree_balance * p_s_tb, int n_h)
brelse(p_s_tb->CFL[n_h]);
p_s_tb->CFL[n_h] = p_s_curcf; /* New initialization of CFL[n_h]. */
-#ifdef CONFIG_REISERFS_CHECK
- if ((p_s_curf && !B_IS_IN_TREE (p_s_curf)) || (p_s_curcf && !B_IS_IN_TREE (p_s_curcf))) {
- reiserfs_panic (p_s_tb->tb_sb, "PAP-8195: get_parents: FL (%b) or CFL (%b) is invalid", p_s_curf, p_s_curcf);
- }
-#endif
-
/* Get parent FR[n_h] of R[n_h]. */
/* Current node is the last child of F[n_h]. FR[n_h] != F[n_h]. */
- if ( n_position == B_BLK_HEAD(PATH_H_PBUFFER(p_s_path, n_h + 1))->blk_nr_item ) {
+ if ( n_position == get_blkh_nr_items (B_BLK_HEAD(PATH_H_PBUFFER(p_s_path, n_h + 1))) ) {
/* Calculate current parent of R[n_h], which is the right neighbor of F[n_h].
Calculate current common parent of R[n_h] and current node. Note that CFR[n_h]
not equal FR[n_path_offset] and CFR[n_h] not equal F[n_h]. */
@@ -1759,12 +1411,6 @@ static int get_parents (struct tree_balance * p_s_tb, int n_h)
brelse/*decrement_bcount*/(p_s_tb->CFR[n_h]);
p_s_tb->CFR[n_h] = p_s_curcf; /* New initialization of CFR[n_path_offset]. */
-#ifdef CONFIG_REISERFS_CHECK
- if ((p_s_curf && !B_IS_IN_TREE (p_s_curf)) || (p_s_curcf && !B_IS_IN_TREE (p_s_curcf))) {
- reiserfs_panic (p_s_tb->tb_sb, "PAP-8205: get_parents: FR (%b) or CFR (%b) is invalid", p_s_curf, p_s_curcf);
- }
-#endif
-
return CARRY_ON; /* schedule not occured while get_parents() worked. */
}
@@ -1783,15 +1429,10 @@ static inline int can_node_be_removed (int mode, int lfree, int sfree, int rfree
r_ih = (struct item_head *)B_N_PDELIM_KEY(tb->CFR[h],tb->rkey[h]);
if (
- lfree + rfree + sfree < MAX_CHILD_SIZE(Sh) + levbytes
+ lfree + rfree + sfree < MAX_CHILD_SIZE(Sh->b_size) + levbytes
/* shifting may merge items which might save space */
-#ifndef FU //REISERFS_FSCK
- - (( ! h && is_left_mergeable (tb->tb_sb, tb->tb_path) == 1 ) ? IH_SIZE : 0)
- - (( ! h && r_ih && is_right_mergeable (tb->tb_sb, tb->tb_path) == 1 ) ? IH_SIZE : 0)
-#else
- - (( ! h && is_left_mergeable (ih, Sh->b_size) ) ? IH_SIZE : 0)
- - (( ! h && r_ih && is_left_mergeable (r_ih, Sh->b_size) ) ? IH_SIZE : 0)
-#endif
+ - (( ! h && is_left_mergeable (tb->tb_fs, tb->tb_path) == 1 ) ? IH_SIZE : 0)
+ - (( ! h && r_ih && is_right_mergeable (tb->tb_fs, tb->tb_path) == 1 ) ? IH_SIZE : 0)
+ (( h ) ? KEY_SIZE : 0))
{
/* node can not be removed */
@@ -1824,34 +1465,31 @@ static inline int can_node_be_removed (int mode, int lfree, int sfree, int rfree
/* ip means Inserting or Pasting */
static int ip_check_balance (/*struct reiserfs_transaction_handle *th,*/ struct tree_balance * tb, int h)
{
- struct virtual_node * vn = tb->tb_vn;
- int levbytes, /* Number of bytes that must be inserted into (value
- is negative if bytes are deleted) buffer which
- contains node being balanced. The mnemonic is
- that the attempted change in node space used level
- is levbytes bytes. */
- n_ret_value;
-
- int lfree, sfree, rfree /* free space in L, S and R */;
-
- /* nver is short for number of vertixes, and lnver is the number if
- we shift to the left, rnver is the number if we shift to the
- right, and lrnver is the number if we shift in both directions.
- The goal is to minimize first the number of vertixes, and second,
- the number of vertixes whose contents are changed by shifting,
- and third the number of uncached vertixes whose contents are
- changed by shifting and must be read from disk. */
- int nver, lnver, rnver, lrnver;
-
- /* used at leaf level only, S0 = S[0] is the node being balanced,
- sInum [ I = 0,1,2 ] is the number of items that will
- remain in node SI after balancing. S1 and S2 are new
- nodes that might be created. */
+ struct virtual_node * vn = tb->tb_vn;
+ int levbytes, /* Number of bytes that must be inserted into (value is
+ negative if bytes are deleted) buffer which contains
+ node being balanced. The mnemonic is that the attempted
+ change in node space used level is levbytes bytes. */
+ n_ret_value;
+
+ int lfree, sfree, rfree /* free space in L, S and R */;
+
+ /* nver is short for number of vertixes, and lnver is the number if we
+ shift to the left, rnver is the number if we shift to the right, and
+ lrnver is the number if we shift in both directions. The goal is to
+ minimize first the number of vertixes, and second, the number of
+ vertixes whose contents are changed by shifting, and third the number
+ of uncached vertixes whose contents are changed by shifting and must be
+ read from disk. */
+ int nver, lnver, rnver, lrnver;
+
+ /* used at leaf level only, S0 = S[0] is the node being balanced, sInum [
+ I = 0,1,2 ] is the number of items that will remain in node SI after
+ balancing. S1 and S2 are new nodes that might be created. */
- /* we perform 8 calls to get_num_ver(). For each call we calculate five parameters.
- where 4th parameter is s1bytes and 5th - s2bytes
- */
- short snum012[40] = {0,}; /* s0num, s1num, s2num for 8 cases
+ /* we perform 8 calls to get_num_ver(). For each call we calculate five
+ parameters. where 4th parameter is s1bytes and 5th - s2bytes */
+ short snum012[40] = {0,}; /* s0num, s1num, s2num for 8 cases
0,1 - do not shift and do not shift but bottle
2 - shift only whole item to left
3 - shift to left and bottle as much as possible
@@ -1859,126 +1497,111 @@ static int ip_check_balance (/*struct reiserfs_transaction_handle *th,*/ struct
6,7 - shift to both directions (whole items and as much as possible)
*/
- /* Sh is the node whose balance is currently being checked */
- struct buffer_head * Sh;
-
-#ifndef FU //REISERFS_FSCK
- /* special mode for insert pointer to the most low internal node */
- if (h == 0 && vn->vn_mode == M_INTERNAL) {
- /* blk_num == 2 is to get pointer inserted to the next level */
- set_parameters (tb, h, 0, 0, 2, NULL, -1, -1);
- return 0;
- }
-#endif
-
- Sh = PATH_H_PBUFFER (tb->tb_path, h);
- levbytes = tb->insert_size[h];
+ /* Sh is the node whose balance is currently being checked */
+ struct buffer_head * Sh;
- /* Calculate balance parameters for creating new root. */
- if ( ! Sh ) {
- if ( ! h )
- reiserfs_panic ("vs-8210: ip_check_balance: S[0] can not be 0");
- switch ( n_ret_value = get_empty_nodes (tb, h) ) {
- case CARRY_ON:
- set_parameters (tb, h, 0, 0, 1, NULL, -1, -1);
- return NO_BALANCING_NEEDED; /* no balancing for higher levels needed */
-
- case NO_DISK_SPACE:
- case SCHEDULE_OCCURRED:
- return n_ret_value;
- default:
- reiserfs_panic("vs-8215: ip_check_balance: incorrect return value of get_empty_nodes");
+ /* special mode for insert pointer to the most low internal node */
+ if (h == 0 && vn->vn_mode == M_INTERNAL) {
+ /* blk_num == 2 is to get pointer inserted to the next level */
+ set_parameters (tb, h, 0, 0, 2, NULL, -1, -1);
+ return 0;
}
- }
-
- if ( (n_ret_value = get_parents (tb, h)) != CARRY_ON ) /* get parents of S[h] neighbors. */
- return n_ret_value;
-
- sfree = B_BLK_HEAD(Sh)->blk_free_space;
-
- /* get free space of neighbors */
- rfree = get_rfree (tb, h);
- lfree = get_lfree (tb, h);
-
- if (can_node_be_removed (vn->vn_mode, lfree, sfree, rfree, tb, h) == NO_BALANCING_NEEDED)
- /* and new item fits into node S[h] without any shifting */
- return NO_BALANCING_NEEDED;
-
- create_virtual_node (tb, h);
-
- /*
- determine maximal number of items we can shift to the left neighbor (in tb structure)
- and the maximal number of bytes that can flow to the left neighbor
- from the left most liquid item that cannot be shifted from S[0] entirely (returned value)
- */
- check_left (tb, h, lfree);
-
- /*
- determine maximal number of items we can shift to the right neighbor (in tb structure)
- and the maximal number of bytes that can flow to the right neighbor
- from the right most liquid item that cannot be shifted from S[0] entirely (returned value)
- */
- check_right (tb, h, rfree);
-
-
- /* all contents of internal node S[h] can be moved into its
- neighbors, S[h] will be removed after balancing */
- if (h && (tb->rnum[h] + tb->lnum[h] >= vn->vn_nr_item + 1)) {
- int to_r;
-
- /* Since we are working on internal nodes, and our internal
- nodes have fixed size entries, then we can balance by the
- number of items rather than the space they consume. In this
- routine we set the left node equal to the right node,
- allowing a difference of less than or equal to 1 child
- pointer. */
- to_r = ((MAX_NR_KEY(Sh)<<1)+2-tb->lnum[h]-tb->rnum[h]+vn->vn_nr_item+1)/2 -
- (MAX_NR_KEY(Sh) + 1 - tb->rnum[h]);
- set_parameters (tb, h, vn->vn_nr_item + 1 - to_r, to_r, 0, NULL, -1, -1);
- return CARRY_ON;
- }
-#ifdef CONFIG_REISERFS_CHECK
- /* this checks balance condition, that any two neighboring nodes can not fit in one node */
- if ( h && ( tb->lnum[h] >= vn->vn_nr_item + 1 || tb->rnum[h] >= vn->vn_nr_item + 1) )
- reiserfs_panic (tb->tb_sb, "vs-8220: ip_check_balance: tree is not balanced on internal level");
+ Sh = PATH_H_PBUFFER (tb->tb_path, h);
+ levbytes = tb->insert_size[h];
+
+ /* Calculate balance parameters for creating new root. */
+ if ( ! Sh ) {
+ if ( ! h )
+ reiserfs_panic ("vs-8210: ip_check_balance: S[0] can not be 0");
+ switch ( n_ret_value = get_empty_nodes (tb, h) ) {
+ case CARRY_ON:
+ set_parameters (tb, h, 0, 0, 1, NULL, -1, -1);
+ return NO_BALANCING_NEEDED; /* no balancing for higher levels needed */
+
+ case NO_DISK_SPACE:
+ return n_ret_value;
- if ( ! h && ((tb->lnum[h] >= vn->vn_nr_item && (tb->lbytes == -1)) ||
- (tb->rnum[h] >= vn->vn_nr_item && (tb->rbytes == -1)) ))
- reiserfs_panic(tb->tb_sb, "vs-8225: ip_check_balance: tree is not balanced on leaf level");
-#endif
+ default:
+ reiserfs_panic("vs-8215: ip_check_balance: incorrect return value of get_empty_nodes");
+ }
+ }
+
+ if ( (n_ret_value = get_parents (tb, h)) != CARRY_ON ) /* get parents of S[h] neighbors. */
+ return n_ret_value;
+
+ sfree = get_blkh_free_space (B_BLK_HEAD(Sh));
+
+ /* get free space of neighbors */
+ rfree = get_rfree (tb, h);
+ lfree = get_lfree (tb, h);
+
+ if (can_node_be_removed (vn->vn_mode, lfree, sfree, rfree, tb, h) == NO_BALANCING_NEEDED)
+ /* and new item fits into node S[h] without any shifting */
+ return NO_BALANCING_NEEDED;
+
+ create_virtual_node (tb, h);
+
+ /* determine maximal number of items we can shift to the left neighbor
+ (in tb structure) and the maximal number of bytes that can flow to the
+ left neighbor from the left most liquid item that cannot be shifted
+ from S[0] entirely (returned value) */
+ check_left (tb, h, lfree);
+
+ /* determine maximal number of items we can shift to the right neighbor
+ (in tb structure) and the maximal number of bytes that can flow to the
+ right neighbor from the right most liquid item that cannot be shifted
+ from S[0] entirely (returned value) */
+ check_right (tb, h, rfree);
+
- /* all contents of S[0] can be moved into its neighbors
- S[0] will be removed after balancing. */
- if (!h && is_leaf_removable (tb))
+ /* all contents of internal node S[h] can be moved into its neighbors,
+ S[h] will be removed after balancing */
+ if (h && (tb->rnum[h] + tb->lnum[h] >= vn->vn_nr_item + 1)) {
+ int to_r;
+
+ /* Since we are working on internal nodes, and our internal nodes have
+ fixed size entries, then we can balance by the number of items
+ rather than the space they consume. In this routine we set the left
+ node equal to the right node, allowing a difference of less than or
+ equal to 1 child pointer. */
+ to_r = ((MAX_NR_KEY(Sh)<<1)+2-tb->lnum[h]-tb->rnum[h]+vn->vn_nr_item+1)/2 -
+ (MAX_NR_KEY(Sh) + 1 - tb->rnum[h]);
+ set_parameters (tb, h, vn->vn_nr_item + 1 - to_r, to_r, 0, NULL, -1, -1);
+ return CARRY_ON;
+ }
+
+ /* all contents of S[0] can be moved into its neighbors S[0] will be
+ removed after balancing. */
+ if (!h && is_leaf_removable (tb))
return CARRY_ON;
-
-
- /* why do we perform this check here rather than earlier??
- Answer: we can win 1 node in some cases above. Moreover we
- checked it above, when we checked, that S[0] is not removable
- in principle */
- if (sfree >= levbytes) { /* new item fits into node S[h] without any shifting */
- if ( ! h )
+
+
+ /* why do we perform this check here rather than earlier??
+ Answer: we can win 1 node in some cases above. Moreover we
+ checked it above, when we checked, that S[0] is not removable
+ in principle */
+ if (sfree >= levbytes) { /* new item fits into node S[h] without any shifting */
+ if ( ! h )
tb->s0num = vn->vn_nr_item;
- set_parameters (tb, h, 0, 0, 1, NULL, -1, -1);
- return NO_BALANCING_NEEDED;
- }
-
-
- {
- int lpar, rpar, nset, lset, rset, lrset;
- /*
- * regular overflowing of the node
- */
-
- /* get_num_ver works in 2 modes (FLOW & NO_FLOW)
- lpar, rpar - number of items we can shift to left/right neighbor (including splitting item)
- nset, lset, rset, lrset - shows, whether flowing items give better packing
- */
+ set_parameters (tb, h, 0, 0, 1, NULL, -1, -1);
+ return NO_BALANCING_NEEDED;
+ }
+
+
+ {
+ int lpar, rpar, nset, lset, rset, lrset;
+ /*
+ * regular overflowing of the node
+ */
+
+ /* get_num_ver works in 2 modes (FLOW & NO_FLOW) lpar, rpar - number
+ of items we can shift to left/right neighbor (including splitting
+ item) nset, lset, rset, lrset - shows, whether flowing items give
+ better packing */
#define FLOW 1
#define NO_FLOW 0 /* do not any splitting */
-
+
/* we choose one the following */
#define NOTHING_SHIFT_NO_FLOW 0
#define NOTHING_SHIFT_FLOW 5
@@ -1990,159 +1613,143 @@ static int ip_check_balance (/*struct reiserfs_transaction_handle *th,*/ struct
#define LR_SHIFT_FLOW 35
- lpar = tb->lnum[h];
- rpar = tb->rnum[h];
+ lpar = tb->lnum[h];
+ rpar = tb->rnum[h];
+
+
+ /* calculate number of blocks S[h] must be split into when nothing is
+ shifted to the neighbors, as well as number of items in each part
+ of the split node (s012 numbers), and number of bytes (s1bytes) of
+ the shared drop which flow to S1 if any */
+ nset = NOTHING_SHIFT_NO_FLOW;
+ nver = get_num_ver (vn->vn_mode, tb, h,
+ 0, -1, h?vn->vn_nr_item:0, -1,
+ snum012, NO_FLOW);
+
+ if (!h) {
+ int nver1;
+
+ /* note, that in this case we try to bottle between S[0] and S1
+ (S1 - the first new node) */
+ nver1 = get_num_ver (vn->vn_mode, tb, h,
+ 0, -1, 0, -1,
+ snum012 + NOTHING_SHIFT_FLOW, FLOW);
+ if (nver > nver1)
+ nset = NOTHING_SHIFT_FLOW, nver = nver1;
+ }
+
+
+ /* calculate number of blocks S[h] must be split into when l_shift_num
+ first items and l_shift_bytes of the right most liquid item to be
+ shifted are shifted to the left neighbor, as well as number of
+ items in each part of the splitted node (s012 numbers), and number
+ of bytes (s1bytes) of the shared drop which flow to S1 if any */
+ lset = LEFT_SHIFT_NO_FLOW;
+ lnver = get_num_ver (vn->vn_mode, tb, h,
+ lpar - (( h || tb->lbytes == -1 ) ? 0 : 1), -1, h ? vn->vn_nr_item:0, -1,
+ snum012 + LEFT_SHIFT_NO_FLOW, NO_FLOW);
+ if (!h) {
+ int lnver1;
+
+ lnver1 = get_num_ver (vn->vn_mode, tb, h,
+ lpar - ((tb->lbytes != -1) ? 1 : 0), tb->lbytes, 0, -1,
+ snum012 + LEFT_SHIFT_FLOW, FLOW);
+ if (lnver > lnver1)
+ lset = LEFT_SHIFT_FLOW, lnver = lnver1;
+ }
+
+
+ /* calculate number of blocks S[h] must be split into when r_shift_num
+ first items and r_shift_bytes of the left most liquid item to be
+ shifted are shifted to the right neighbor, as well as number of
+ items in each part of the splitted node (s012 numbers), and number
+ of bytes (s1bytes) of the shared drop which flow to S1 if any */
+ rset = RIGHT_SHIFT_NO_FLOW;
+ rnver = get_num_ver (vn->vn_mode, tb, h,
+ 0, -1, h ? (vn->vn_nr_item-rpar) : (rpar - (( tb->rbytes != -1 ) ? 1 : 0)), -1,
+ snum012 + RIGHT_SHIFT_NO_FLOW, NO_FLOW);
+ if (!h) {
+ int rnver1;
+
+ rnver1 = get_num_ver (vn->vn_mode, tb, h,
+ 0, -1, (rpar - ((tb->rbytes != -1) ? 1 : 0)), tb->rbytes,
+ snum012 + RIGHT_SHIFT_FLOW, FLOW);
+
+ if (rnver > rnver1)
+ rset = RIGHT_SHIFT_FLOW, rnver = rnver1;
+ }
+
+
+ /* calculate number of blocks S[h] must be split into when items are
+ shifted in both directions, as well as number of items in each part
+ of the splitted node (s012 numbers), and number of bytes (s1bytes)
+ of the shared drop which flow to S1 if any */
+ lrset = LR_SHIFT_NO_FLOW;
+ lrnver = get_num_ver (vn->vn_mode, tb, h,
+ lpar - ((h || tb->lbytes == -1) ? 0 : 1), -1, h ? (vn->vn_nr_item-rpar):(rpar - ((tb->rbytes != -1) ? 1 : 0)), -1,
+ snum012 + LR_SHIFT_NO_FLOW, NO_FLOW);
+ if (!h) {
+ int lrnver1;
+
+ lrnver1 = get_num_ver (vn->vn_mode, tb, h,
+ lpar - ((tb->lbytes != -1) ? 1 : 0), tb->lbytes, (rpar - ((tb->rbytes != -1) ? 1 : 0)), tb->rbytes,
+ snum012 + LR_SHIFT_FLOW, FLOW);
+ if (lrnver > lrnver1)
+ lrset = LR_SHIFT_FLOW, lrnver = lrnver1;
+ }
+
+
+
+ /* Our general shifting strategy is:
+ 1) to minimized number of new nodes;
+ 2) to minimized number of neighbors involved in shifting;
+ 3) to minimized number of disk reads; */
+
+ /* we can win TWO or ONE nodes by shifting in both directions */
+ if (lrnver < lnver && lrnver < rnver) {
+ if (lrset == LR_SHIFT_FLOW)
+ set_parameters (tb, h, tb->lnum[h], tb->rnum[h], lrnver, snum012 + lrset,
+ tb->lbytes, tb->rbytes);
+ else
+ set_parameters (tb, h, tb->lnum[h] - ((tb->lbytes == -1) ? 0 : 1),
+ tb->rnum[h] - ((tb->rbytes == -1) ? 0 : 1), lrnver, snum012 + lrset, -1, -1);
+
+ return CARRY_ON;
+ }
+
+ /* if shifting doesn't lead to better packing then don't shift */
+ if (nver == lrnver) {
+ set_parameters (tb, h, 0, 0, nver, snum012 + nset, -1, -1);
+ return CARRY_ON;
+ }
+ /* now we know that for better packing shifting in only one direction
+ either to the left or to the right is required */
- /* calculate number of blocks S[h] must be split into when
- nothing is shifted to the neighbors,
- as well as number of items in each part of the split node (s012 numbers),
- and number of bytes (s1bytes) of the shared drop which flow to S1 if any */
- nset = NOTHING_SHIFT_NO_FLOW;
- nver = get_num_ver (vn->vn_mode, tb, h,
- 0, -1, h?vn->vn_nr_item:0, -1,
- snum012, NO_FLOW);
+ /* if shifting to the left is better than shifting to the right */
+ if (lnver < rnver) {
+ SET_PAR_SHIFT_LEFT;
+ return CARRY_ON;
+ }
- if (!h)
- {
- int nver1;
+ /* if shifting to the right is better than shifting to the left */
+ if (lnver > rnver) {
+ SET_PAR_SHIFT_RIGHT;
+ return CARRY_ON;
+ }
- /* note, that in this case we try to bottle between S[0] and S1 (S1 - the first new node) */
- nver1 = get_num_ver (vn->vn_mode, tb, h,
- 0, -1, 0, -1,
- snum012 + NOTHING_SHIFT_FLOW, FLOW);
- if (nver > nver1)
- nset = NOTHING_SHIFT_FLOW, nver = nver1;
- }
-
-
- /* calculate number of blocks S[h] must be split into when
- l_shift_num first items and l_shift_bytes of the right most
- liquid item to be shifted are shifted to the left neighbor,
- as well as number of items in each part of the splitted node (s012 numbers),
- and number of bytes (s1bytes) of the shared drop which flow to S1 if any
- */
- lset = LEFT_SHIFT_NO_FLOW;
- lnver = get_num_ver (vn->vn_mode, tb, h,
- lpar - (( h || tb->lbytes == -1 ) ? 0 : 1), -1, h ? vn->vn_nr_item:0, -1,
- snum012 + LEFT_SHIFT_NO_FLOW, NO_FLOW);
- if (!h)
- {
- int lnver1;
-
- lnver1 = get_num_ver (vn->vn_mode, tb, h,
- lpar - ((tb->lbytes != -1) ? 1 : 0), tb->lbytes, 0, -1,
- snum012 + LEFT_SHIFT_FLOW, FLOW);
- if (lnver > lnver1)
- lset = LEFT_SHIFT_FLOW, lnver = lnver1;
- }
-
-
- /* calculate number of blocks S[h] must be split into when
- r_shift_num first items and r_shift_bytes of the left most
- liquid item to be shifted are shifted to the right neighbor,
- as well as number of items in each part of the splitted node (s012 numbers),
- and number of bytes (s1bytes) of the shared drop which flow to S1 if any
- */
- rset = RIGHT_SHIFT_NO_FLOW;
- rnver = get_num_ver (vn->vn_mode, tb, h,
- 0, -1, h ? (vn->vn_nr_item-rpar) : (rpar - (( tb->rbytes != -1 ) ? 1 : 0)), -1,
- snum012 + RIGHT_SHIFT_NO_FLOW, NO_FLOW);
- if (!h)
- {
- int rnver1;
-
- rnver1 = get_num_ver (vn->vn_mode, tb, h,
- 0, -1, (rpar - ((tb->rbytes != -1) ? 1 : 0)), tb->rbytes,
- snum012 + RIGHT_SHIFT_FLOW, FLOW);
-
- if (rnver > rnver1)
- rset = RIGHT_SHIFT_FLOW, rnver = rnver1;
- }
-
-
- /* calculate number of blocks S[h] must be split into when
- items are shifted in both directions,
- as well as number of items in each part of the splitted node (s012 numbers),
- and number of bytes (s1bytes) of the shared drop which flow to S1 if any
- */
- lrset = LR_SHIFT_NO_FLOW;
- lrnver = get_num_ver (vn->vn_mode, tb, h,
- lpar - ((h || tb->lbytes == -1) ? 0 : 1), -1, h ? (vn->vn_nr_item-rpar):(rpar - ((tb->rbytes != -1) ? 1 : 0)), -1,
- snum012 + LR_SHIFT_NO_FLOW, NO_FLOW);
- if (!h)
- {
- int lrnver1;
-
- lrnver1 = get_num_ver (vn->vn_mode, tb, h,
- lpar - ((tb->lbytes != -1) ? 1 : 0), tb->lbytes, (rpar - ((tb->rbytes != -1) ? 1 : 0)), tb->rbytes,
- snum012 + LR_SHIFT_FLOW, FLOW);
- if (lrnver > lrnver1)
- lrset = LR_SHIFT_FLOW, lrnver = lrnver1;
- }
-
-
-
- /* Our general shifting strategy is:
- 1) to minimized number of new nodes;
- 2) to minimized number of neighbors involved in shifting;
- 3) to minimized number of disk reads; */
-
- /* we can win TWO or ONE nodes by shifting in both directions */
- if (lrnver < lnver && lrnver < rnver)
- {
-#ifdef CONFIG_REISERFS_CHECK
- if (h && (tb->lnum[h] != 1 || tb->rnum[h] != 1 || lrnver != 1 || rnver != 2 || lnver != 2 || h != 1))
- reiserfs_panic (0, "vs-8230: check_balance: bad h");
-#endif
- if (lrset == LR_SHIFT_FLOW)
- set_parameters (tb, h, tb->lnum[h], tb->rnum[h], lrnver, snum012 + lrset,
- tb->lbytes, tb->rbytes);
- else
- set_parameters (tb, h, tb->lnum[h] - ((tb->lbytes == -1) ? 0 : 1),
- tb->rnum[h] - ((tb->rbytes == -1) ? 0 : 1), lrnver, snum012 + lrset, -1, -1);
-
- return CARRY_ON;
- }
-
- /* if shifting doesn't lead to better packing then don't shift */
- if (nver == lrnver)
- {
- set_parameters (tb, h, 0, 0, nver, snum012 + nset, -1, -1);
- return CARRY_ON;
- }
-
-
- /* now we know that for better packing shifting in only one
- direction either to the left or to the right is required */
-
- /* if shifting to the left is better than shifting to the right */
- if (lnver < rnver)
- {
- SET_PAR_SHIFT_LEFT;
- return CARRY_ON;
- }
-
- /* if shifting to the right is better than shifting to the left */
- if (lnver > rnver)
- {
- SET_PAR_SHIFT_RIGHT;
- return CARRY_ON;
- }
-
-
- /* now shifting in either direction gives the same number
- of nodes and we can make use of the cached neighbors */
- if (is_left_neighbor_in_cache (tb,h))
- {
- SET_PAR_SHIFT_LEFT;
- return CARRY_ON;
- }
-
- /* shift to the right independently on whether the right neighbor in cache or not */
- SET_PAR_SHIFT_RIGHT;
- return CARRY_ON;
- }
+ /* now shifting in either direction gives the same number of nodes and
+ we can make use of the cached neighbors */
+ if (is_left_neighbor_in_cache (tb,h)) {
+ SET_PAR_SHIFT_LEFT;
+ return CARRY_ON;
+ }
+
+ /* shift to the right independently on whether the right neighbor in
+ cache or not */
+ SET_PAR_SHIFT_RIGHT;
+ return CARRY_ON;
+ }
}
@@ -2164,155 +1771,142 @@ static int ip_check_balance (/*struct reiserfs_transaction_handle *th,*/ struct
*/
static int dc_check_balance_internal (struct tree_balance * tb, int h)
{
- struct virtual_node * vn = tb->tb_vn;
+ struct virtual_node * vn = tb->tb_vn;
/* Sh is the node whose balance is currently being checked,
and Fh is its father. */
- struct buffer_head * Sh, * Fh;
- int maxsize,
- n_ret_value;
- int lfree, rfree /* free space in L and R */;
+ struct buffer_head * Sh, * Fh;
+ int maxsize,
+ n_ret_value;
+ int lfree, rfree /* free space in L and R */;
- Sh = PATH_H_PBUFFER (tb->tb_path, h);
- Fh = PATH_H_PPARENT (tb->tb_path, h);
+ Sh = PATH_H_PBUFFER (tb->tb_path, h);
+ Fh = PATH_H_PPARENT (tb->tb_path, h);
- maxsize = MAX_CHILD_SIZE(Sh);
+ maxsize = MAX_CHILD_SIZE(Sh->b_size);
-/* using tb->insert_size[h], which is negative in this case, create_virtual_node calculates: */
-/* new_nr_item = number of items node would have if operation is */
-/* performed without balancing (new_nr_item); */
- create_virtual_node (tb, h);
+ /* using tb->insert_size[h], which is negative in this case,
+ create_virtual_node calculates: new_nr_item = number of items node
+ would have if operation is performed without balancing (new_nr_item); */
+ create_virtual_node (tb, h);
- if ( ! Fh )
- { /* S[h] is the root. */
- if ( vn->vn_nr_item > 0 )
- {
- set_parameters (tb, h, 0, 0, 1, NULL, -1, -1);
- return NO_BALANCING_NEEDED; /* no balancing for higher levels needed */
+ if ( ! Fh ) {
+ /* S[h] is the root. */
+ if ( vn->vn_nr_item > 0 ) {
+ set_parameters (tb, h, 0, 0, 1, NULL, -1, -1);
+ return NO_BALANCING_NEEDED; /* no balancing for higher levels needed */
}
- /* new_nr_item == 0.
- * Current root will be deleted resulting in
- * decrementing the tree height. */
- set_parameters (tb, h, 0, 0, 0, NULL, -1, -1);
- return CARRY_ON;
+ /* new_nr_item == 0.
+ * Current root will be deleted resulting in
+ * decrementing the tree height. */
+ set_parameters (tb, h, 0, 0, 0, NULL, -1, -1);
+ return CARRY_ON;
}
+
+ if ( (n_ret_value = get_parents(tb,h)) != CARRY_ON )
+ return n_ret_value;
+
+ /* get free space of neighbors */
+ rfree = get_rfree (tb, h);
+ lfree = get_lfree (tb, h);
+
+ /* determine maximal number of items we can fit into neighbors */
- if ( (n_ret_value = get_parents(tb,h)) != CARRY_ON )
- return n_ret_value;
-
-
- /* get free space of neighbors */
- rfree = get_rfree (tb, h);
- lfree = get_lfree (tb, h);
+ check_left (tb, h, lfree);
+ check_right (tb, h, rfree);
+
+ if ( vn->vn_nr_item >= MIN_NR_KEY(Sh) ) {
+ /* Balance condition for the internal node is valid. In this case we
+ * balance only if it leads to better packing. */
+ if ( vn->vn_nr_item == MIN_NR_KEY(Sh) ) {
+ /* Here we join S[h] with one of its neighbors, which is
+ * impossible with greater values of new_nr_item. */
+ if ( tb->lnum[h] >= vn->vn_nr_item + 1 ) {
+ /* All contents of S[h] can be moved to L[h]. */
+ int n;
+ int order_L;
- /* determine maximal number of items we can fit into neighbors */
- check_left (tb, h, lfree);
- check_right (tb, h, rfree);
-
-
- if ( vn->vn_nr_item >= MIN_NR_KEY(Sh) )
- { /* Balance condition for the internal node is valid.
- * In this case we balance only if it leads to better packing. */
- if ( vn->vn_nr_item == MIN_NR_KEY(Sh) )
- { /* Here we join S[h] with one of its neighbors,
- * which is impossible with greater values of new_nr_item. */
- if ( tb->lnum[h] >= vn->vn_nr_item + 1 )
- {
- /* All contents of S[h] can be moved to L[h]. */
- int n;
- int order_L;
-
- order_L = ((n=PATH_H_B_ITEM_ORDER(tb->tb_path, h))==0) ? B_NR_ITEMS(tb->FL[h]) : n - 1;
- n = B_N_CHILD(tb->FL[h],order_L)->dc_size / (DC_SIZE + KEY_SIZE);
- set_parameters (tb, h, -n-1, 0, 0, NULL, -1, -1);
- return CARRY_ON;
+ order_L = ((n=PATH_H_B_ITEM_ORDER(tb->tb_path, h))==0) ? B_NR_ITEMS(tb->FL[h]) : n - 1;
+ n = get_dc_child_size (B_N_CHILD(tb->FL[h],order_L)) / (DC_SIZE + KEY_SIZE);
+ set_parameters (tb, h, -n-1, 0, 0, NULL, -1, -1);
+ return CARRY_ON;
}
-
- if ( tb->rnum[h] >= vn->vn_nr_item + 1 )
- {
- /* All contents of S[h] can be moved to R[h]. */
- int n;
- int order_R;
- order_R = ((n=PATH_H_B_ITEM_ORDER(tb->tb_path, h))==B_NR_ITEMS(Fh)) ? 0 : n + 1;
- n = B_N_CHILD(tb->FR[h],order_R)->dc_size / (DC_SIZE + KEY_SIZE);
- set_parameters (tb, h, 0, -n-1, 0, NULL, -1, -1);
- return CARRY_ON;
+ if ( tb->rnum[h] >= vn->vn_nr_item + 1 ) {
+ /* All contents of S[h] can be moved to R[h]. */
+ int n;
+ int order_R;
+
+ order_R = ((n=PATH_H_B_ITEM_ORDER(tb->tb_path, h))==B_NR_ITEMS(Fh)) ? 0 : n + 1;
+ n = get_dc_child_size (B_N_CHILD(tb->FR[h],order_R)) / (DC_SIZE + KEY_SIZE);
+ set_parameters (tb, h, 0, -n-1, 0, NULL, -1, -1);
+ return CARRY_ON;
}
}
-
- if (tb->rnum[h] + tb->lnum[h] >= vn->vn_nr_item + 1)
- {
- /* All contents of S[h] can be moved to the neighbors (L[h] & R[h]). */
- int to_r;
-
- to_r = ((MAX_NR_KEY(Sh)<<1)+2-tb->lnum[h]-tb->rnum[h]+vn->vn_nr_item+1)/2 -
- (MAX_NR_KEY(Sh) + 1 - tb->rnum[h]);
- set_parameters (tb, h, vn->vn_nr_item + 1 - to_r, to_r, 0, NULL, -1, -1);
- return CARRY_ON;
+
+ if (tb->rnum[h] + tb->lnum[h] >= vn->vn_nr_item + 1) {
+ /* All contents of S[h] can be moved to the neighbors (L[h] &
+ R[h]). */
+ int to_r;
+
+ to_r = ((MAX_NR_KEY(Sh)<<1)+2-tb->lnum[h]-tb->rnum[h]+vn->vn_nr_item+1)/2 -
+ (MAX_NR_KEY(Sh) + 1 - tb->rnum[h]);
+ set_parameters (tb, h, vn->vn_nr_item + 1 - to_r, to_r, 0, NULL, -1, -1);
+ return CARRY_ON;
}
-
- /* Balancing does not lead to better packing. */
- set_parameters (tb, h, 0, 0, 1, NULL, -1, -1);
- return NO_BALANCING_NEEDED;
+
+ /* Balancing does not lead to better packing. */
+ set_parameters (tb, h, 0, 0, 1, NULL, -1, -1);
+ return NO_BALANCING_NEEDED;
}
-
- /* Current node contain insufficient number of items. Balancing is required. */
- /* Check whether we can merge S[h] with left neighbor. */
- if (tb->lnum[h] >= vn->vn_nr_item + 1)
- if (is_left_neighbor_in_cache (tb,h) || tb->rnum[h] < vn->vn_nr_item + 1 || !tb->FR[h])
- {
- int n;
- int order_L;
-
- order_L = ((n=PATH_H_B_ITEM_ORDER(tb->tb_path, h))==0) ? B_NR_ITEMS(tb->FL[h]) : n - 1;
- n = B_N_CHILD(tb->FL[h],order_L)->dc_size / (DC_SIZE + KEY_SIZE);
- set_parameters (tb, h, -n-1, 0, 0, NULL, -1, -1);
- return CARRY_ON;
- }
-
- /* Check whether we can merge S[h] with right neighbor. */
- if (tb->rnum[h] >= vn->vn_nr_item + 1)
- {
- int n;
- int order_R;
+
+ /* Current node contain insufficient number of items. Balancing is
+ required. Check whether we can merge S[h] with left neighbor. */
+ if (tb->lnum[h] >= vn->vn_nr_item + 1)
+ if (is_left_neighbor_in_cache (tb,h) || tb->rnum[h] < vn->vn_nr_item + 1 || !tb->FR[h]) {
+ int n;
+ int order_L;
- order_R = ((n=PATH_H_B_ITEM_ORDER(tb->tb_path, h))==B_NR_ITEMS(Fh)) ? 0 : (n + 1);
- n = B_N_CHILD(tb->FR[h],order_R)->dc_size / (DC_SIZE + KEY_SIZE);
- set_parameters (tb, h, 0, -n-1, 0, NULL, -1, -1);
- return CARRY_ON;
+ order_L = ((n=PATH_H_B_ITEM_ORDER(tb->tb_path, h))==0) ? B_NR_ITEMS(tb->FL[h]) : n - 1;
+ n = get_dc_child_size (B_N_CHILD(tb->FL[h],order_L)) / (DC_SIZE + KEY_SIZE);
+ set_parameters (tb, h, -n-1, 0, 0, NULL, -1, -1);
+ return CARRY_ON;
+ }
+
+ /* Check whether we can merge S[h] with right neighbor. */
+ if (tb->rnum[h] >= vn->vn_nr_item + 1) {
+ int n;
+ int order_R;
+
+ order_R = ((n=PATH_H_B_ITEM_ORDER(tb->tb_path, h))==B_NR_ITEMS(Fh)) ? 0 : (n + 1);
+ n = get_dc_child_size (B_N_CHILD(tb->FR[h],order_R)) / (DC_SIZE + KEY_SIZE);
+ set_parameters (tb, h, 0, -n-1, 0, NULL, -1, -1);
+ return CARRY_ON;
}
-
- /* All contents of S[h] can be moved to the neighbors (L[h] & R[h]). */
- if (tb->rnum[h] + tb->lnum[h] >= vn->vn_nr_item + 1)
- {
- int to_r;
-
- to_r = ((MAX_NR_KEY(Sh)<<1)+2-tb->lnum[h]-tb->rnum[h]+vn->vn_nr_item+1)/2 -
- (MAX_NR_KEY(Sh) + 1 - tb->rnum[h]);
- set_parameters (tb, h, vn->vn_nr_item + 1 - to_r, to_r, 0, NULL, -1, -1);
- return CARRY_ON;
+
+ /* All contents of S[h] can be moved to the neighbors (L[h] & R[h]). */
+ if (tb->rnum[h] + tb->lnum[h] >= vn->vn_nr_item + 1) {
+ int to_r;
+
+ to_r = ((MAX_NR_KEY(Sh)<<1)+2-tb->lnum[h]-tb->rnum[h]+vn->vn_nr_item+1)/2 -
+ (MAX_NR_KEY(Sh) + 1 - tb->rnum[h]);
+ set_parameters (tb, h, vn->vn_nr_item + 1 - to_r, to_r, 0, NULL, -1, -1);
+ return CARRY_ON;
}
-
- /* For internal nodes try to borrow item from a neighbor */
-#ifdef CONFIG_REISERFS_CHECK
- if (!tb->FL[h] && !tb->FR[h])
- reiserfs_panic (0, "vs-8235: dc_check_balance_internal: trying to borrow for root");
-#endif
-
- /* Borrow one or two items from caching neighbor */
- if (is_left_neighbor_in_cache (tb,h) || !tb->FR[h])
- {
- int from_l;
+
+ /* For internal nodes try to borrow item from a neighbor */
+ /* Borrow one or two items from caching neighbor */
+ if (is_left_neighbor_in_cache (tb,h) || !tb->FR[h]) {
+ int from_l;
- from_l = (MAX_NR_KEY(Sh) + 1 - tb->lnum[h] + vn->vn_nr_item + 1) / 2 - (vn->vn_nr_item + 1);
- set_parameters (tb, h, -from_l, 0, 1, NULL, -1, -1);
- return CARRY_ON;
+ from_l = (MAX_NR_KEY(Sh) + 1 - tb->lnum[h] + vn->vn_nr_item + 1) / 2 - (vn->vn_nr_item + 1);
+ set_parameters (tb, h, -from_l, 0, 1, NULL, -1, -1);
+ return CARRY_ON;
}
-
- set_parameters (tb, h, 0, -((MAX_NR_KEY(Sh)+1-tb->rnum[h]+vn->vn_nr_item+1)/2-(vn->vn_nr_item+1)), 1,
- NULL, -1, -1);
- return CARRY_ON;
+
+ set_parameters (tb, h, 0, -((MAX_NR_KEY(Sh)+1-tb->rnum[h]+vn->vn_nr_item+1)/2-(vn->vn_nr_item+1)), 1,
+ NULL, -1, -1);
+ return CARRY_ON;
}
@@ -2331,90 +1925,79 @@ static int dc_check_balance_internal (struct tree_balance * tb, int h)
*/
static int dc_check_balance_leaf (struct tree_balance * tb, int h)
{
- struct virtual_node * vn = tb->tb_vn;
-
- /* Number of bytes that must be deleted from
- (value is negative if bytes are deleted) buffer which
- contains node being balanced. The mnemonic is that the
- attempted change in node space used level is levbytes bytes. */
- int levbytes;
- /* the maximal item size */
- int maxsize,
- n_ret_value;
- /* S0 is the node whose balance is currently being checked,
- and F0 is its father. */
- struct buffer_head * S0, * F0;
- int lfree, rfree /* free space in L and R */;
-
- S0 = PATH_H_PBUFFER (tb->tb_path, 0);
- F0 = PATH_H_PPARENT (tb->tb_path, 0);
-
- levbytes = tb->insert_size[h];
-
- maxsize = MAX_CHILD_SIZE(S0); /* maximal possible size of an item */
-
- if ( ! F0 )
- { /* S[0] is the root now. */
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( -levbytes >= maxsize - B_BLK_HEAD(S0)->blk_free_space )
- reiserfs_panic (tb->tb_sb, "vs-8240: dc_check_balance_leaf: attempt to create empty buffer tree");
-#endif
+ struct virtual_node * vn = tb->tb_vn;
- set_parameters (tb, h, 0, 0, 1, NULL, -1, -1);
- return NO_BALANCING_NEEDED;
- }
+ /* Number of bytes that must be deleted from (value is negative if bytes
+ are deleted) buffer which contains node being balanced. The mnemonic
+ is that the attempted change in node space used level is levbytes
+ bytes. */
+ int levbytes;
+ /* the maximal item size */
+ int maxsize,
+ n_ret_value;
+ /* S0 is the node whose balance is currently being checked, and F0 is its
+ father. */
+ struct buffer_head * S0, * F0;
+ int lfree, rfree /* free space in L and R */;
+
+ S0 = PATH_H_PBUFFER (tb->tb_path, 0);
+ F0 = PATH_H_PPARENT (tb->tb_path, 0);
- if ( (n_ret_value = get_parents(tb,h)) != CARRY_ON )
- return n_ret_value;
+ levbytes = tb->insert_size[h];
- /* get free space of neighbors */
- rfree = get_rfree (tb, h);
- lfree = get_lfree (tb, h);
+ maxsize = MAX_CHILD_SIZE(S0->b_size); /* maximal possible size of an item */
- create_virtual_node (tb, h);
+ if ( ! F0 ) {
+ /* S[0] is the root now. */
+ set_parameters (tb, h, 0, 0, 1, NULL, -1, -1);
+ return NO_BALANCING_NEEDED;
+ }
+
+ if ( (n_ret_value = get_parents(tb,h)) != CARRY_ON )
+ return n_ret_value;
+
+ /* get free space of neighbors */
+ rfree = get_rfree (tb, h);
+ lfree = get_lfree (tb, h);
- /* if 3 leaves can be merge to one, set parameters and return */
- if (are_leaves_removable (tb, lfree, rfree))
- return CARRY_ON;
+ create_virtual_node (tb, h);
+
+ /* if 3 leaves can be merge to one, set parameters and return */
+ if (are_leaves_removable (tb, lfree, rfree))
+ return CARRY_ON;
- /* determine maximal number of items we can shift to the left/right neighbor
- and the maximal number of bytes that can flow to the left/right neighbor
- from the left/right most liquid item that cannot be shifted from S[0] entirely
- */
- check_left (tb, h, lfree);
- check_right (tb, h, rfree);
-
- /* check whether we can merge S with left neighbor. */
- if (tb->lnum[0] >= vn->vn_nr_item && tb->lbytes == -1)
- if (is_left_neighbor_in_cache (tb,h) ||
- ((tb->rnum[0] - ((tb->rbytes == -1) ? 0 : 1)) < vn->vn_nr_item) || /* S can not be merged with R */
- !tb->FR[h]) {
-
-#ifdef CONFIG_REISERFS_CHECK
- if (!tb->FL[h])
- reiserfs_panic (0, "vs-8245: dc_check_balance_leaf: FL[h] must exist");
-#endif
+ /* determine maximal number of items we can shift to the left/right
+ neighbor and the maximal number of bytes that can flow to the
+ left/right neighbor from the left/right most liquid item that cannot be
+ shifted from S[0] entirely */
+ check_left (tb, h, lfree);
+ check_right (tb, h, rfree);
+
+ /* check whether we can merge S with left neighbor. */
+ if (tb->lnum[0] >= vn->vn_nr_item && tb->lbytes == -1)
+ if (is_left_neighbor_in_cache (tb,h) ||
+ ((tb->rnum[0] - ((tb->rbytes == -1) ? 0 : 1)) < vn->vn_nr_item) || /* S can not be merged with R */
+ !tb->FR[h]) {
+ /* set parameter to merge S[0] with its left neighbor */
+ set_parameters (tb, h, -1, 0, 0, NULL, -1, -1);
+ return CARRY_ON;
+ }
- /* set parameter to merge S[0] with its left neighbor */
- set_parameters (tb, h, -1, 0, 0, NULL, -1, -1);
- return CARRY_ON;
+ /* check whether we can merge S[0] with right neighbor. */
+ if (tb->rnum[0] >= vn->vn_nr_item && tb->rbytes == -1) {
+ set_parameters (tb, h, 0, -1, 0, NULL, -1, -1);
+ return CARRY_ON;
}
-
- /* check whether we can merge S[0] with right neighbor. */
- if (tb->rnum[0] >= vn->vn_nr_item && tb->rbytes == -1) {
- set_parameters (tb, h, 0, -1, 0, NULL, -1, -1);
- return CARRY_ON;
- }
-
- /* All contents of S[0] can be moved to the neighbors (L[0] & R[0]). Set parameters and return */
- if (is_leaf_removable (tb))
- return CARRY_ON;
-
- /* Balancing is not required. */
- tb->s0num = vn->vn_nr_item;
- set_parameters (tb, h, 0, 0, 1, NULL, -1, -1);
- return NO_BALANCING_NEEDED;
+
+ /* All contents of S[0] can be moved to the neighbors (L[0] & R[0]). Set
+ parameters and return */
+ if (is_leaf_removable (tb))
+ return CARRY_ON;
+
+ /* Balancing is not required. */
+ tb->s0num = vn->vn_nr_item;
+ set_parameters (tb, h, 0, 0, 1, NULL, -1, -1);
+ return NO_BALANCING_NEEDED;
}
@@ -2434,16 +2017,10 @@ static int dc_check_balance_leaf (struct tree_balance * tb, int h)
*/
static int dc_check_balance (struct tree_balance * tb, int h)
{
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( ! (PATH_H_PBUFFER (tb->tb_path, h)) )
- reiserfs_panic(tb->tb_sb, "vs-8250: dc_check_balance: S is not initialized");
-#endif
-
- if ( h )
- return dc_check_balance_internal (tb, h);
- else
- return dc_check_balance_leaf (tb, h);
+ if ( h )
+ return dc_check_balance_internal (tb, h);
+ else
+ return dc_check_balance_leaf (tb, h);
}
@@ -2472,18 +2049,13 @@ static int check_balance (int mode, struct tree_balance * tb,
{
struct virtual_node * vn;
- vn = tb->tb_vn = (struct virtual_node *)(tb->vn_buf);// + ROUND_UP(SB_BMAP_NR (tb->tb_sb) * 2 / 8 + 1, 4));
+ vn = tb->tb_vn = (struct virtual_node *)(tb->vn_buf);// + ROUND_UP(SB_BMAP_NR (tb->tb_fs) * 2 / 8 + 1, 4));
vn->vn_free_ptr = (char *)(tb->tb_vn + 1);
vn->vn_mode = mode;
vn->vn_affected_item_num = inum;
vn->vn_pos_in_item = pos_in_item;
vn->vn_ins_ih = ins_ih;
-#ifdef CONFIG_REISERFS_CHECK
- if (mode == M_INSERT && !vn->vn_ins_ih)
- reiserfs_panic (0, "vs-8255: check_balance: ins_ih can not be 0 in insert mode");
-#endif
-
if ( tb->insert_size[h] > 0 )
/* Calculate balance parameters when size of node is increasing. */
return ip_check_balance (tb, h);
@@ -2493,50 +2065,43 @@ static int check_balance (int mode, struct tree_balance * tb,
}
-
/* Check whether parent at the path is the really parent of the current node.*/
-static int get_direct_parent(
- struct tree_balance * p_s_tb,
- int n_h
- ) {
- struct buffer_head * p_s_bh;
- struct path * p_s_path = p_s_tb->tb_path;
- int n_position,
- n_path_offset = PATH_H_PATH_OFFSET(p_s_tb->tb_path, n_h);
-
- /* We are in the root or in the new root. */
- if ( n_path_offset <= FIRST_PATH_ELEMENT_OFFSET ) {
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( n_path_offset < FIRST_PATH_ELEMENT_OFFSET - 1 )
- reiserfs_panic(p_s_tb->tb_sb, "PAP-8260: get_direct_parent: illegal offset in the path");
-#endif
-
- if ( PATH_OFFSET_PBUFFER(p_s_path, FIRST_PATH_ELEMENT_OFFSET)->b_blocknr ==
- SB_ROOT_BLOCK (p_s_tb->tb_sb) ) {
- /* Root is not changed. */
- PATH_OFFSET_PBUFFER(p_s_path, n_path_offset - 1) = NULL;
+static void get_direct_parent (struct tree_balance * p_s_tb, int n_h)
+{
+ struct buffer_head * p_s_bh;
+ struct path * p_s_path = p_s_tb->tb_path;
+ int n_position,
+ n_path_offset = PATH_H_PATH_OFFSET(p_s_tb->tb_path, n_h);
+
+ /* We are in the root or in the new root. */
+ if ( n_path_offset <= FIRST_PATH_ELEMENT_OFFSET ) {
+ struct reiserfs_super_block * sb;
+
+ if ( n_path_offset < FIRST_PATH_ELEMENT_OFFSET - 1 )
+ reiserfs_panic ("PAP-8260: get_direct_parent: illegal offset in the path");
+
+ sb = p_s_tb->tb_fs->fs_ondisk_sb;
+ if ( PATH_OFFSET_PBUFFER(p_s_path, FIRST_PATH_ELEMENT_OFFSET)->b_blocknr ==
+ get_sb_root_block (sb) ) {
+ /* Root is not changed. */
+ PATH_OFFSET_PBUFFER(p_s_path, n_path_offset - 1) = NULL;
PATH_OFFSET_POSITION(p_s_path, n_path_offset - 1) = 0;
- return CARRY_ON;
+ return;
+ }
+ reiserfs_panic ("get_direct_parent: root changed");
}
- return PATH_INCORRECT; /* Root is changed and we must recalculate the path. */
- }
-
- if ( ! B_IS_IN_TREE(p_s_bh = PATH_OFFSET_PBUFFER(p_s_path, n_path_offset - 1)) )
- return PATH_INCORRECT; /* Parent in the path is not in the tree. */
-
- if ( (n_position = PATH_OFFSET_POSITION(p_s_path, n_path_offset - 1)) > B_NR_ITEMS(p_s_bh) )
- return PATH_INCORRECT;
-
- if ( B_N_CHILD_NUM(p_s_bh, n_position) != PATH_OFFSET_PBUFFER(p_s_path, n_path_offset)->b_blocknr )
- /* Parent in the path is not parent of the current node in the tree. */
- return PATH_INCORRECT;
-
-#if 0
- if ( test_and_wait_on_buffer(p_s_bh) == SCHEDULE_OCCURRED ) /* Buffer was locked. */
- return SCHEDULE_OCCURRED;
-#endif
- return CARRY_ON; /* Parent in the path is unlocked and really parent of the current node. */
+
+ if ( ! B_IS_IN_TREE(p_s_bh = PATH_OFFSET_PBUFFER(p_s_path, n_path_offset - 1)) )
+ reiserfs_panic ("get_direct_parent: parent in the path is not in the tree");
+
+ if ( (n_position = PATH_OFFSET_POSITION(p_s_path, n_path_offset - 1)) > B_NR_ITEMS(p_s_bh) )
+ reiserfs_panic ("get_direct_parent: wrong position in the path");
+
+ if ( get_dc_child_blocknr (B_N_CHILD(p_s_bh, n_position)) != PATH_OFFSET_PBUFFER(p_s_path, n_path_offset)->b_blocknr )
+ reiserfs_panic ("get_direct_parent: parent in the path is not parent "
+ "of the current node in the tree");
+
+ return ; /* Parent in the path is unlocked and really parent of the current node. */
}
@@ -2549,89 +2114,41 @@ static int get_direct_parent(
static int get_neighbors(struct tree_balance * p_s_tb, int n_h)
{
int n_child_position,
- n_repeat,
n_path_offset = PATH_H_PATH_OFFSET(p_s_tb->tb_path, n_h + 1);
unsigned long n_son_number;
- struct super_block * p_s_sb = p_s_tb->tb_sb;
+ reiserfs_filsys_t * fs = p_s_tb->tb_fs;
struct buffer_head * p_s_bh;
/*struct virtual_node * vn = p_s_tb->tb_vn;*/
if ( p_s_tb->lnum[n_h] ) {
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( ! p_s_tb->lnum[n_h] && vn->vn_mode == M_CUT &&
- ! (vn->vn_vi[0].vi_type & VI_TYPE_DIRECTORY) )
- reiserfs_panic (p_s_tb->tb_sb, "PAP-8265: get_neighbors: item must be directory item");
-#endif
-
/* We need left neighbor to balance S[n_h]. */
p_s_bh = PATH_OFFSET_PBUFFER(p_s_tb->tb_path, n_path_offset);
-#ifdef CONFIG_REISERFS_CHECK
- if ( p_s_bh == p_s_tb->FL[n_h] && ! PATH_OFFSET_POSITION(p_s_tb->tb_path, n_path_offset) )
- reiserfs_panic (p_s_tb->tb_sb, "PAP-8270: get_neighbors: invalid position in the parent");
-#endif
-
- n_child_position = ( p_s_bh == p_s_tb->FL[n_h] ) ? p_s_tb->lkey[n_h] : B_BLK_HEAD(p_s_tb->FL[n_h])->blk_nr_item;
- n_son_number = B_N_CHILD_NUM(p_s_tb->FL[n_h], n_child_position);
- n_repeat = CARRY_ON;
- p_s_bh = reiserfs_bread(p_s_sb->s_dev, n_son_number, p_s_sb->s_blocksize, &n_repeat);
+ n_child_position = ( p_s_bh == p_s_tb->FL[n_h] ) ? p_s_tb->lkey[n_h] :
+ get_blkh_nr_items (B_BLK_HEAD(p_s_tb->FL[n_h]));
+ n_son_number = get_dc_child_blocknr (B_N_CHILD (p_s_tb->FL[n_h], n_child_position));
+ p_s_bh = bread(fs->fs_dev, n_son_number, fs->fs_blocksize);
if (!p_s_bh)
return IO_ERROR;
- if ( n_repeat != CARRY_ON ) {
- brelse /*decrement_bcount*/(p_s_bh);
- return SCHEDULE_OCCURRED;
- }
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( ! B_IS_IN_TREE(p_s_tb->FL[n_h]) || n_child_position > B_NR_ITEMS(p_s_tb->FL[n_h]) ||
- B_N_CHILD_NUM(p_s_tb->FL[n_h], n_child_position) != p_s_bh->b_blocknr )
- reiserfs_panic (p_s_tb->tb_sb, "PAP-8275: get_neighbors: invalid parent");
- if ( ! B_IS_IN_TREE(p_s_bh) )
- reiserfs_panic (p_s_tb->tb_sb, "PAP-8280: get_neighbors: invalid child");
-
- if (! n_h && node_free_space (p_s_bh) != MAX_CHILD_SIZE (p_s_bh) - B_N_CHILD (p_s_tb->FL[0],n_child_position)->dc_size) {
- reiserfs_panic (p_s_tb->tb_sb, "PAP-8290: get_neighbors: invalid child size of left neighbor");
- }
-#endif
-
- brelse /*decrement_bcount*/(p_s_tb->L[n_h]);
+ brelse (p_s_tb->L[n_h]);
p_s_tb->L[n_h] = p_s_bh;
}
if ( p_s_tb->rnum[n_h] ) { /* We need right neighbor to balance S[n_path_offset]. */
p_s_bh = PATH_OFFSET_PBUFFER(p_s_tb->tb_path, n_path_offset);
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( p_s_bh == p_s_tb->FR[n_h] && PATH_OFFSET_POSITION(p_s_tb->tb_path, n_path_offset) >= B_NR_ITEMS(p_s_bh) )
- reiserfs_panic (p_s_tb->tb_sb, "PAP-8295: get_neighbors: invalid position in the parent");
-#endif
-
n_child_position = ( p_s_bh == p_s_tb->FR[n_h] ) ? p_s_tb->rkey[n_h] + 1 : 0;
- n_son_number = B_N_CHILD_NUM(p_s_tb->FR[n_h], n_child_position);
- n_repeat = CARRY_ON;
- p_s_bh = reiserfs_bread(p_s_sb->s_dev, n_son_number, p_s_sb->s_blocksize, &n_repeat);
+ n_son_number = get_dc_child_blocknr (B_N_CHILD (p_s_tb->FR[n_h], n_child_position));
+ p_s_bh = bread(fs->fs_dev, n_son_number, fs->fs_blocksize);
if (!p_s_bh)
return IO_ERROR;
- if ( n_repeat != CARRY_ON ) {
- brelse/*decrement_bcount*/(p_s_bh);
- return SCHEDULE_OCCURRED;
- }
- brelse/*decrement_bcount*/(p_s_tb->R[n_h]);
- p_s_tb->R[n_h] = p_s_bh;
-
-#ifdef CONFIG_REISERFS_CHECK
- if (! n_h && node_free_space (p_s_bh) != MAX_CHILD_SIZE (p_s_bh) - B_N_CHILD (p_s_tb->FR[0],n_child_position)->dc_size) {
- reiserfs_panic (p_s_tb->tb_sb, "PAP-8300: get_neighbors: invalid child size of right neighbor (%d != %d - %d)",
- node_free_space (p_s_bh), MAX_CHILD_SIZE (p_s_bh), B_N_CHILD (p_s_tb->FR[0],n_child_position)->dc_size);
- }
-#endif
+ brelse (p_s_tb->R[n_h]);
+ p_s_tb->R[n_h] = p_s_bh;
}
return CARRY_ON;
}
-
+#if 0
void * reiserfs_kmalloc (size_t size, int flags, struct super_block * s)
{
void * vp;
@@ -2643,53 +2160,28 @@ void * reiserfs_kmalloc (size_t size, int flags, struct super_block * s)
void reiserfs_kfree (/*const */void * vp, size_t size, struct super_block * s)
{
freemem (vp);
-#if 0
+
kfree (vp);
s->u.reiserfs_sb.s_kmallocs -= size;
if (s->u.reiserfs_sb.s_kmallocs < 0)
reiserfs_warning ("vs-8302: reiserfs_kfree: allocated memory %d\n", s->u.reiserfs_sb.s_kmallocs);
-#endif
-}
-
-
-static int get_virtual_node_size (struct super_block * sb, struct buffer_head * bh)
-{
- //int size = sizeof (struct virtual_item); /* for new item in case of insert */
- //int i, nr_items;
- //struct item_head * ih;
-
- return sb->s_blocksize;
-#if 0
- size = sizeof (struct virtual_node) + sizeof (struct virtual_item);
- ih = B_N_PITEM_HEAD (bh, 0);
- nr_items = B_NR_ITEMS (bh);
- for (i = 0; i < nr_items; i ++, ih ++) {
- /* each item occupies some space in virtual node */
- size += sizeof (struct virtual_item);
- if (I_IS_DIRECTORY_ITEM (ih))
- /* each entry and new one occupeis 2 byte in the virtual node */
- size += (ih_entry_count (ih) + 1) * sizeof (__u16);
- }
-
- /* 1 bit for each bitmap block to note whether bitmap block was
- dirtied in the operation */
- size += (SB_BMAP_NR (sb) * 2 / 8 + 4);
- return size;
-#endif
}
+#endif
static int get_mem_for_virtual_node (struct tree_balance * tb)
{
- int size;
+ tb->vn_buf = getmem (tb->tb_fs->fs_blocksize);
+ return CARRY_ON;
+}
- size = get_virtual_node_size (tb->tb_sb, PATH_PLAST_BUFFER(tb->tb_path));
- tb->vn_buf = getmem (size);
- return CARRY_ON;
+static void free_virtual_node_mem (struct tree_balance * tb)
+{
+ freemem (tb->vn_buf);
}
@@ -2722,84 +2214,23 @@ static int get_mem_for_virtual_node (struct tree_balance * tb)
*/
-int fix_nodes (/*struct reiserfs_transaction_handle *th,*/
- int n_op_mode, struct tree_balance * p_s_tb,
+int fix_nodes (int n_op_mode, struct tree_balance * p_s_tb,
struct item_head * p_s_ins_ih)
{
int n_pos_in_item = p_s_tb->tb_path->pos_in_item;
int n_ret_value,
n_h,
n_item_num = get_item_pos (p_s_tb->tb_path);
- struct buffer_head * p_s_tbS0 = get_bh (p_s_tb->tb_path);
-// struct item_head * ih = get_ih (p_s_tb->tb_path);
-
-
- /* if it possible in indirect_to_direct conversion */
- if (buffer_locked (p_s_tbS0)) {
- return SCHEDULE_OCCURRED;
- }
+ /* struct buffer_head * p_s_tbS0 = get_bh (p_s_tb->tb_path);*/
+ /* struct item_head * ih = get_ih (p_s_tb->tb_path);*/
-#ifdef CONFIG_REISERFS_CHECK
- if ( cur_tb ) {
- print_tb (n_op_mode, n_item_num, n_pos_in_item, cur_tb,"fix_nodes");
- reiserfs_panic(p_s_tb->tb_sb,"PAP-8305: fix_nodes: there is pending do_balance");
- }
-
- if (!buffer_uptodate (p_s_tbS0) || !B_IS_IN_TREE (p_s_tbS0)) {
- reiserfs_panic (p_s_tb->tb_sb, "PAP-8320: fix_nodes: S[0] (%b %z) is not uptodate "
- "at the beginning of fix_nodes or not in tree (mode %c)", p_s_tbS0, p_s_tbS0, n_op_mode);
- }
-
- /* Check parameters. */
- switch (n_op_mode) {
-#ifndef FU //REISERFS_FSCK
- // FIXME: REISERFS_CHECK can not be turned on for utils
- case M_INTERNAL:
- break;
- case M_INSERT:
- if ( n_item_num < 0 || n_item_num > B_NR_ITEMS(p_s_tbS0) )
- reiserfs_panic(p_s_tb->tb_sb,"PAP-8325: fix_nodes: Incorrect item number %d (in S0 - %d) in case of insert",
- n_item_num, B_NR_ITEMS(p_s_tbS0));
-#else
- case M_INSERT:
- if ( n_item_num <= 0 || n_item_num > B_NR_ITEMS(p_s_tbS0) )
- reiserfs_panic(p_s_tb->tb_sb,"PAP-8330: fix_nodes: Incorrect item number %d (in S0 - %d) in case of insert",
- n_item_num, B_NR_ITEMS(p_s_tbS0));
-#endif
- break;
- case M_PASTE:
- if (I_IS_DIRECT_ITEM (get_ih (p_s_tb->tb_path))) {
- // we can paste only to the end for now
- if (n_pos_in_item != ih_item_len (get_ih (p_s_tb->tb_path)))
- reiserfs_panic (th->t_super, "vs-8332: fix_nodes: "
- "pos_in_item %d set improperly to paste direct item %h",
- n_pos_in_item, get_ih (p_s_tb->tb_path));
- }
- // fall through
- case M_DELETE:
- case M_CUT:
- if ( n_item_num < 0 || n_item_num >= B_NR_ITEMS(p_s_tbS0) ) {
- print_block (p_s_tbS0, 0, -1, -1);
- printk("mode = %c insert_size = %d\n", n_op_mode, p_s_tb->insert_size[0]);
- reiserfs_panic(p_s_tb->tb_sb,"PAP-8335: fix_nodes: Incorrect item number(%d)", n_item_num);
- }
- break;
- default:
- reiserfs_panic(p_s_tb->tb_sb,"PAP-8340: fix_nodes: Incorrect mode of operation");
- }
-#endif
-
-
- if (get_mem_for_virtual_node (p_s_tb) == SCHEDULE_OCCURRED) {
- return SCHEDULE_OCCURRED;
- }
+ if (get_mem_for_virtual_node (p_s_tb) != CARRY_ON)
+ reiserfs_panic ("fix_nodes: no memory for virtual node");
/* Starting from the leaf level; for all levels n_h of the tree. */
for ( n_h = 0; n_h < MAX_HEIGHT && p_s_tb->insert_size[n_h]; n_h++ ) {
- if ( (n_ret_value = get_direct_parent(p_s_tb, n_h)) != CARRY_ON ) {
- return n_ret_value;
- }
+ get_direct_parent(p_s_tb, n_h);
if ( (n_ret_value = check_balance (/*th,*/ n_op_mode, p_s_tb, n_h, n_item_num,
n_pos_in_item, p_s_ins_ih)) != CARRY_ON ) {
@@ -2822,34 +2253,22 @@ int fix_nodes (/*struct reiserfs_transaction_handle *th,*/
}
if ( (n_ret_value = get_empty_nodes(/*th,*/ p_s_tb, n_h)) != CARRY_ON ) {
- return n_ret_value; /* No disk space, or schedule occurred and
- analysis may be invalid and needs to be redone. */
+ return n_ret_value; /* No disk space */
}
if ( ! PATH_H_PBUFFER(p_s_tb->tb_path, n_h) ) {
/* We have a positive insert size but no nodes exist on this
level, this means that we are creating a new root. */
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( p_s_tb->blknum[n_h] != 1 )
- reiserfs_panic(p_s_tb->tb_sb,"PAP-8350: fix_nodes: creating new empty root");
-#endif /* CONFIG_REISERFS_CHECK */
-
if ( n_h < MAX_HEIGHT - 1 )
p_s_tb->insert_size[n_h + 1] = 0;
}
else
if ( ! PATH_H_PBUFFER(p_s_tb->tb_path, n_h + 1) ) {
if ( p_s_tb->blknum[n_h] > 1 ) {
- /* The tree needs to be grown, so this node S[n_h]
- which is the root node is split into two nodes, and
- a new node (S[n_h+1]) will be created to become the root node. */
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( n_h == MAX_HEIGHT - 1 )
- reiserfs_panic(p_s_tb->tb_sb, "PAP-8355: fix_nodes: attempt to create too high of a tree");
-#endif /* CONFIG_REISERFS_CHECK */
-
+ /* The tree needs to be grown, so this node S[n_h] which
+ is the root node is split into two nodes, and a new
+ node (S[n_h+1]) will be created to become the root
+ node. */
p_s_tb->insert_size[n_h + 1] = (DC_SIZE + KEY_SIZE) * (p_s_tb->blknum[n_h] - 1) + DC_SIZE;
}
else
@@ -2860,24 +2279,17 @@ int fix_nodes (/*struct reiserfs_transaction_handle *th,*/
p_s_tb->insert_size[n_h + 1] = (DC_SIZE + KEY_SIZE) * (p_s_tb->blknum[n_h] - 1);
}
- return CARRY_ON; /* schedule did not occur */
+ return CARRY_ON; /* go ahead and balsnce */
}
-void unfix_nodes(/* struct reiserfs_transaction_handle *th,*/struct tree_balance * p_s_tb)
+void unfix_nodes (struct tree_balance * p_s_tb)
{
struct path * p_s_path = p_s_tb->tb_path;
int n_counter;
// int i, j;
//struct buffer_head * bh;
-#ifdef CONFIG_REISERFS_CHECK
- if ( ! p_s_tb->vn_buf )
- reiserfs_panic (p_s_tb->tb_sb,
- "PAP-16050: unfix_nodes: pointer to the virtual node is NULL");
-#endif
-
-
/* Release path buffers. */
pathrelse(p_s_path);
@@ -2896,7 +2308,7 @@ void unfix_nodes(/* struct reiserfs_transaction_handle *th,*/struct tree_balance
for ( n_counter = 0; n_counter < MAX_FEB_SIZE; n_counter++ ) {
if ( p_s_tb->FEB[n_counter] ) {
/* release what was not used */
- reiserfs_free_block(p_s_tb->tb_sb, p_s_tb->FEB[n_counter]->b_blocknr);
+ reiserfs_free_block(p_s_tb->tb_fs, p_s_tb->FEB[n_counter]->b_blocknr);
bforget(p_s_tb->FEB[n_counter]);
/* tree balance bitmap of bitmaps has bit set already */
@@ -2905,8 +2317,7 @@ void unfix_nodes(/* struct reiserfs_transaction_handle *th,*/struct tree_balance
brelse (p_s_tb->used[n_counter]);
}
- reiserfs_kfree (p_s_tb->vn_buf, p_s_tb->vn_buf_size, p_s_tb->tb_sb);
-
+ free_virtual_node_mem (p_s_tb);
}
diff --git a/reiserfscore/hashes.c b/reiserfscore/hashes.c
index 32628ce..930e83a 100644
--- a/reiserfscore/hashes.c
+++ b/reiserfscore/hashes.c
@@ -51,7 +51,7 @@ typedef __u32 u32;
} while(0)
-u32 keyed_hash(const char *msg, int len)
+u32 keyed_hash(const signed char *msg, int len)
{
u32 k[] = { 0x9464a485, 0x542e1a94, 0x3e846bff, 0xb75bcfc3};
@@ -61,8 +61,6 @@ u32 keyed_hash(const char *msg, int len)
int i;
- // assert(len >= 0 && len < 256);
-
pad = (u32)len | ((u32)len << 8);
pad |= pad << 16;
@@ -93,7 +91,6 @@ u32 keyed_hash(const char *msg, int len)
if (len >= 12)
{
- //assert(len < 16);
if (len >= 16)
*(int *)0 = 0;
@@ -119,7 +116,6 @@ u32 keyed_hash(const char *msg, int len)
}
else if (len >= 8)
{
- //assert(len < 12);
if (len >= 12)
*(int *)0 = 0;
a = (u32)msg[ 0] |
@@ -140,7 +136,6 @@ u32 keyed_hash(const char *msg, int len)
}
else if (len >= 4)
{
- //assert(len < 8);
if (len >= 8)
*(int *)0 = 0;
a = (u32)msg[ 0] |
@@ -157,7 +152,6 @@ u32 keyed_hash(const char *msg, int len)
}
else
{
- //assert(len < 4);
if (len >= 4)
*(int *)0 = 0;
a = b = c = d = pad;
@@ -170,12 +164,11 @@ u32 keyed_hash(const char *msg, int len)
TEACORE(FULLROUNDS);
-/* return 0;*/
return h0^h1;
}
-u32 yura_hash (const char *msg, int len)
+u32 yura_hash (const signed char *msg, int len)
{
int j, pow;
u32 a, c;
@@ -211,23 +204,23 @@ u32 yura_hash (const char *msg, int len)
}
-u32 r5_hash (const char *msg, int len)
+u32 r5_hash (const signed char *msg, int len)
{
- u32 a=0;
- int i;
-
- for (i = 0; i < len; i ++) {
- a += msg[i] << 4;
- a += msg[i] >> 4;
- a *= 11;
- }
- return a;
+ u32 a=0;
+ int i;
+
+ for (i = 0; i < len; i ++) {
+ a += msg[i] << 4;
+ a += msg[i] >> 4;
+ a *= 11;
+ }
+ return a;
}
+
#if 0
#include <stdio.h>
-//#include <stddef.h>
int main (void)
{
diff --git a/reiserfscore/ibalance.c b/reiserfscore/ibalance.c
index 782f099..7766ab9 100644
--- a/reiserfscore/ibalance.c
+++ b/reiserfscore/ibalance.c
@@ -34,10 +34,6 @@ static void internal_define_dest_src_infos (
struct buffer_head ** cf
)
{
-#ifdef CONFIG_REISERFS_CHECK
- memset (dest_bi, 0, sizeof (struct buffer_info));
- memset (src_bi, 0, sizeof (struct buffer_info));
-#endif
/* define dest, src, dest parent, dest position */
switch (shift_mode) {
case INTERNAL_SHIFT_FROM_S_TO_L: /* used in internal_shift_left */
@@ -111,13 +107,14 @@ static void internal_define_dest_src_infos (
* Insert count items into buffer cur before position to.
* Items and node pointers are specified by inserted and bh respectively.
*/
-static void internal_insert_childs (reiserfs_filsys_t fs,
+static void internal_insert_childs (reiserfs_filsys_t * fs,
struct buffer_info * cur_bi,
int to, int count,
struct item_head * inserted,
struct buffer_head ** bh)
{
struct buffer_head * cur = cur_bi->bi_bh;
+ struct block_head * blkh;
int nr;
struct key * key;
struct disk_child new_dc[2];
@@ -128,15 +125,8 @@ static void internal_insert_childs (reiserfs_filsys_t fs,
if (count <= 0)
return;
- nr = node_item_number (cur);
-
-#ifdef CONFIG_REISERFS_CHECK
- if (count > 2)
- reiserfs_panic (0, "internal_insert_childs", "too many children (%d) are to be inserted", count);
- if (node_free_space (cur) < count * (KEY_SIZE + DC_SIZE))
- reiserfs_panic (0, "internal_insert_childs", "no enough free space (%d), needed %d bytes",
- node_free_space (cur), count * (KEY_SIZE + DC_SIZE));
-#endif /* CONFIG_REISERFS_CHECK */
+ blkh = B_BLK_HEAD (cur);
+ nr = get_blkh_nr_items (blkh);
/* prepare space for count disk_child */
dc = B_N_CHILD (cur,to+1);
@@ -145,9 +135,10 @@ static void internal_insert_childs (reiserfs_filsys_t fs,
/* make disk child array for insertion */
for (i = 0; i < count; i ++) {
- new_dc[i].dc_size = cpu_to_le16 (MAX_CHILD_SIZE(bh[i]) -
- node_free_space (bh[i]));
- new_dc[i].dc_block_number = cpu_to_le32 (bh[i]->b_blocknr);
+ set_dc_child_size (new_dc + i,
+ MAX_CHILD_SIZE(bh[i]->b_size) -
+ get_blkh_free_space (B_BLK_HEAD (bh[i])));
+ set_dc_child_blocknr (new_dc + i, bh[i]->b_blocknr);
}
memcpy (dc, new_dc, DC_SIZE * count);
@@ -163,13 +154,14 @@ static void internal_insert_childs (reiserfs_filsys_t fs,
memcpy (key + 1, inserted + 1, KEY_SIZE);
/* sizes, item number */
- set_node_item_number (cur, nr + count);
- set_node_free_space (cur, node_free_space (cur) -
- count * (DC_SIZE + KEY_SIZE));
+ set_blkh_nr_items (blkh, nr + count);
+ set_blkh_free_space (blkh, get_blkh_free_space (blkh) - count * (DC_SIZE + KEY_SIZE));
+
mark_buffer_dirty (cur);
if (cur_bi->bi_parent) {
- B_N_CHILD (cur_bi->bi_parent,cur_bi->bi_position)->dc_size += count * (DC_SIZE + KEY_SIZE);
+ dc = B_N_CHILD (cur_bi->bi_parent,cur_bi->bi_position);
+ set_dc_child_size (dc, get_dc_child_size (dc) + count * (DC_SIZE + KEY_SIZE));
mark_buffer_dirty (cur_bi->bi_parent);
}
@@ -178,7 +170,7 @@ static void internal_insert_childs (reiserfs_filsys_t fs,
/* Delete del_num items and node pointers from buffer cur starting from *
* the first_i'th item and first_p'th pointers respectively. */
-static void internal_delete_pointers_items (reiserfs_filsys_t fs,
+static void internal_delete_pointers_items (reiserfs_filsys_t * fs,
struct buffer_info * cur_bi,
int first_p, int first_i,
int del_num)
@@ -189,46 +181,17 @@ static void internal_delete_pointers_items (reiserfs_filsys_t fs,
struct key * key;
struct disk_child * dc;
-
-#ifdef CONFIG_REISERFS_CHECK
- if (cur == NULL)
- reiserfs_panic (0, "internal_delete_pointers_items1: buffer is 0");
-
- if (del_num < 0)
- reiserfs_panic (0, "internal_delete_pointers_items2",
- "negative number of items (%d) can not be deleted", del_num);
-
- if (first_p < 0 || first_p + del_num > B_NR_ITEMS (cur) + 1 || first_i < 0)
- reiserfs_panic (0, "internal_delete_pointers_items3",
- "first pointer order (%d) < 0 or "
- "no so many pointers (%d), only (%d) or "
- "first key order %d < 0", first_p,
- first_p + del_num, B_NR_ITEMS (cur) + 1, first_i);
-#endif /* CONFIG_REISERFS_CHECK */
if ( del_num == 0 )
return;
- nr = (blkh = B_BLK_HEAD(cur))->blk_nr_item;
+ blkh = B_BLK_HEAD(cur);
+ nr = get_blkh_nr_items (blkh);
if ( first_p == 0 && del_num == nr + 1 ) {
-#ifdef CONFIG_REISERFS_CHECK
- if ( first_i != 0 )
- reiserfs_panic (0, "internal_delete_pointers_items5",
- "first deleted key must have order 0, not %d", first_i);
-#endif /* CONFIG_REISERFS_CHECK */
make_empty_node (cur_bi);
return;
}
-#ifdef CONFIG_REISERFS_CHECK
- if (first_i + del_num > B_NR_ITEMS (cur)) {
- printk("first_i = %d del_num = %d\n",first_i,del_num);
- reiserfs_panic (0, "internal_delete_pointers_items4: :"
- "no so many keys (%d) in the node (%b)(%z)", first_i + del_num, cur, cur);
- }
-#endif /* CONFIG_REISERFS_CHECK */
-
-
/* deleting */
dc = B_N_CHILD (cur, first_p);
@@ -237,21 +200,23 @@ static void internal_delete_pointers_items (reiserfs_filsys_t fs,
memmove (key, key + del_num, (nr - first_i - del_num) * KEY_SIZE + (nr + 1 - del_num) * DC_SIZE);
- /* sizes, item number */
- blkh->blk_nr_item -= del_num;
- blkh->blk_free_space += del_num * (KEY_SIZE + DC_SIZE);
+ /* sizes, item number */
+ set_blkh_nr_items (blkh, get_blkh_nr_items (blkh) - del_num);
+ set_blkh_free_space (blkh, get_blkh_free_space (blkh) +
+ del_num * (KEY_SIZE + DC_SIZE));
mark_buffer_dirty (cur);
if (cur_bi->bi_parent) {
- B_N_CHILD (cur_bi->bi_parent, cur_bi->bi_position)->dc_size -= del_num * (KEY_SIZE + DC_SIZE);
+ dc = B_N_CHILD (cur_bi->bi_parent, cur_bi->bi_position);
+ set_dc_child_size (dc, get_dc_child_size (dc) - del_num * (KEY_SIZE + DC_SIZE));
mark_buffer_dirty (cur_bi->bi_parent);
}
}
/* delete n node pointers and items starting from given position */
-static void internal_delete_childs (reiserfs_filsys_t fs,
+static void internal_delete_childs (reiserfs_filsys_t * fs,
struct buffer_info * cur_bi,
int from, int n)
{
@@ -270,7 +235,7 @@ static void internal_delete_childs (reiserfs_filsys_t fs,
* last_first == FIRST_TO_LAST means, that we copy first items from src to tail of dest
* last_first == LAST_TO_FIRST means, that we copy last items from src to head of dest
*/
-static void internal_copy_pointers_items (reiserfs_filsys_t fs,
+static void internal_copy_pointers_items (reiserfs_filsys_t * fs,
struct buffer_info * dest_bi,
struct buffer_head * src,
int last_first, int cpy_num)
@@ -286,31 +251,12 @@ static void internal_copy_pointers_items (reiserfs_filsys_t fs,
nr_src = B_NR_ITEMS (src);
-#ifdef CONFIG_REISERFS_CHECK
- if ( dest == NULL || src == NULL )
- reiserfs_panic (0, "internal_copy_pointers_items", "src (%p) or dest (%p) buffer is 0", src, dest);
-
- if (last_first != FIRST_TO_LAST && last_first != LAST_TO_FIRST)
- reiserfs_panic (0, "internal_copy_pointers_items",
- "invalid last_first parameter (%d)", last_first);
-
- if ( nr_src < cpy_num - 1 )
- reiserfs_panic (0, "internal_copy_pointers_items", "no so many items (%d) in src (%d)", cpy_num, nr_src);
-
- if ( cpy_num < 0 )
- reiserfs_panic (0, "internal_copy_pointers_items", "cpy_num less than 0 (%d)", cpy_num);
-
- if (cpy_num - 1 + B_NR_ITEMS(dest) > (int)MAX_NR_KEY(dest))
- reiserfs_panic (0, "internal_copy_pointers_items",
- "cpy_num (%d) + item number in dest (%d) can not be more than MAX_NR_KEY(%d)",
- cpy_num, B_NR_ITEMS(dest), MAX_NR_KEY(dest));
-#endif
-
if ( cpy_num == 0 )
return;
- /* coping */
- nr_dest = (blkh = B_BLK_HEAD(dest))->blk_nr_item;
+ /* coping */
+ blkh = B_BLK_HEAD (dest);
+ nr_dest = get_blkh_nr_items (blkh);
/*dest_order = (last_first == LAST_TO_FIRST) ? 0 : nr_dest;*/
/*src_order = (last_first == LAST_TO_FIRST) ? (nr_src - cpy_num + 1) : 0;*/
@@ -336,13 +282,14 @@ static void internal_copy_pointers_items (reiserfs_filsys_t fs,
memcpy (key, B_N_PDELIM_KEY (src, src_order), KEY_SIZE * (cpy_num - 1));
/* sizes, item number */
- blkh->blk_nr_item += cpy_num - 1;
- blkh->blk_free_space -= KEY_SIZE * (cpy_num - 1) + DC_SIZE * cpy_num;
+ set_blkh_nr_items (blkh, get_blkh_nr_items (blkh) + cpy_num - 1);
+ set_blkh_free_space (blkh, get_blkh_free_space (blkh) -
+ (KEY_SIZE * (cpy_num - 1) + DC_SIZE * cpy_num));
mark_buffer_dirty (dest);
if (dest_bi->bi_parent) {
- B_N_CHILD(dest_bi->bi_parent,dest_bi->bi_position)->dc_size +=
- KEY_SIZE * (cpy_num - 1) + DC_SIZE * cpy_num;
+ dc = B_N_CHILD(dest_bi->bi_parent,dest_bi->bi_position);
+ set_dc_child_size (dc, get_dc_child_size (dc) + KEY_SIZE * (cpy_num - 1) + DC_SIZE * cpy_num);
mark_buffer_dirty (dest_bi->bi_parent);
}
@@ -354,7 +301,7 @@ static void internal_copy_pointers_items (reiserfs_filsys_t fs,
* last_first == FIRST_TO_LAST means, that we copy/delete first items from src.
* last_first == LAST_TO_FIRST means, that we copy/delete last items from src.
*/
-static void internal_move_pointers_items (reiserfs_filsys_t fs,
+static void internal_move_pointers_items (reiserfs_filsys_t * fs,
struct buffer_info * dest_bi,
struct buffer_info * src_bi,
int last_first, int cpy_num, int del_par)
@@ -380,7 +327,7 @@ static void internal_move_pointers_items (reiserfs_filsys_t fs,
}
/* Insert n_src'th key of buffer src before n_dest'th key of buffer dest. */
-static void internal_insert_key (reiserfs_filsys_t fs,
+static void internal_insert_key (reiserfs_filsys_t * fs,
struct buffer_info * dest_bi,
int dest_position_before, /* insert key before key with n_dest number */
struct buffer_head * src,
@@ -391,26 +338,8 @@ static void internal_insert_key (reiserfs_filsys_t fs,
struct block_head * blkh;
struct key * key;
-
-#ifdef CONFIG_REISERFS_CHECK
- if (dest == NULL || src == NULL)
- reiserfs_panic (0, "internal_insert_key", "sourse(%p) or dest(%p) buffer is 0", src, dest);
-
- if (dest_position_before < 0 || src_position < 0)
- reiserfs_panic (0, "internal_insert_key", "source(%d) or dest(%d) key number less than 0",
- src_position, dest_position_before);
-
- if (dest_position_before > B_NR_ITEMS (dest) || src_position >= B_NR_ITEMS(src))
- reiserfs_panic (0, "internal_insert_key",
- "invalid position in dest (%d (key number %d)) or in src (%d (key number %d))",
- dest_position_before, B_NR_ITEMS (dest), src_position, B_NR_ITEMS(src));
-
- if (B_BLK_HEAD(dest)->blk_free_space < KEY_SIZE)
- reiserfs_panic (0, "internal_insert_key",
- "no enough free space (%d) in dest buffer", B_BLK_HEAD(dest)->blk_free_space);
-#endif
-
- nr = (blkh=B_BLK_HEAD(dest))->blk_nr_item;
+ blkh = B_BLK_HEAD(dest);
+ nr = get_blkh_nr_items (blkh);
/* prepare space for inserting key */
key = B_N_PDELIM_KEY (dest, dest_position_before);
@@ -420,13 +349,16 @@ static void internal_insert_key (reiserfs_filsys_t fs,
memcpy (key, B_N_PDELIM_KEY(src, src_position), KEY_SIZE);
/* Change dirt, free space, item number fields. */
- blkh->blk_nr_item ++;
- blkh->blk_free_space -= KEY_SIZE;
+ set_blkh_nr_items (blkh, get_blkh_nr_items (blkh) + 1);
+ set_blkh_free_space (blkh, get_blkh_free_space (blkh) - KEY_SIZE);
mark_buffer_dirty (dest);
if (dest_bi->bi_parent) {
- B_N_CHILD(dest_bi->bi_parent,dest_bi->bi_position)->dc_size += KEY_SIZE;
+ struct disk_child * dc;
+
+ dc = B_N_CHILD(dest_bi->bi_parent,dest_bi->bi_position);
+ set_dc_child_size (dc, get_dc_child_size (dc) + KEY_SIZE);
mark_buffer_dirty (dest_bi->bi_parent);
}
}
@@ -453,16 +385,16 @@ static void internal_shift_left (int mode, /* INTERNAL_FROM_S_TO_L | INTERNAL_FR
if (pointer_amount) {
/* insert delimiting key from common father of dest and src to node dest into position B_NR_ITEM(dest) */
- internal_insert_key (tb->tb_sb, &dest_bi, B_NR_ITEMS(dest_bi.bi_bh), cf, d_key_position);
+ internal_insert_key (tb->tb_fs, &dest_bi, B_NR_ITEMS(dest_bi.bi_bh), cf, d_key_position);
if (B_NR_ITEMS(src_bi.bi_bh) == pointer_amount - 1) {
if (src_bi.bi_position/*src->b_item_order*/ == 0)
- replace_key (tb->tb_sb, cf, d_key_position, src_bi.bi_parent/*src->b_parent*/, 0);
+ replace_key (tb->tb_fs, cf, d_key_position, src_bi.bi_parent/*src->b_parent*/, 0);
} else
- replace_key (tb->tb_sb, cf, d_key_position, src_bi.bi_bh, pointer_amount - 1);
+ replace_key (tb->tb_fs, cf, d_key_position, src_bi.bi_bh, pointer_amount - 1);
}
/* last parameter is del_parameter */
- internal_move_pointers_items (tb->tb_sb, &dest_bi, &src_bi, FIRST_TO_LAST, pointer_amount, 0);
+ internal_move_pointers_items (tb->tb_fs, &dest_bi, &src_bi, FIRST_TO_LAST, pointer_amount, 0);
}
@@ -481,10 +413,10 @@ static void internal_shift1_left (struct tree_balance * tb,
internal_define_dest_src_infos (INTERNAL_SHIFT_FROM_S_TO_L, tb, h, &dest_bi, &src_bi, &d_key_position, &cf);
if ( pointer_amount > 0 ) /* insert lkey[h]-th key from CFL[h] to left neighbor L[h] */
- internal_insert_key (tb->tb_sb, &dest_bi, B_NR_ITEMS(dest_bi.bi_bh), cf, d_key_position);
+ internal_insert_key (tb->tb_fs, &dest_bi, B_NR_ITEMS(dest_bi.bi_bh), cf, d_key_position);
/* last parameter is del_parameter */
- internal_move_pointers_items (tb->tb_sb, &dest_bi, &src_bi, FIRST_TO_LAST, pointer_amount, 1);
+ internal_move_pointers_items (tb->tb_fs, &dest_bi, &src_bi, FIRST_TO_LAST, pointer_amount, 1);
}
@@ -509,22 +441,17 @@ static void internal_shift_right (int mode, /* INTERNAL_FROM_S_TO_R | INTERNAL_F
if (pointer_amount > 0) {
/* insert delimiting key from common father of dest and src to dest node into position 0 */
- internal_insert_key (tb->tb_sb, &dest_bi, 0, cf, d_key_position);
+ internal_insert_key (tb->tb_fs, &dest_bi, 0, cf, d_key_position);
if (nr == pointer_amount - 1) {
-#ifdef CONFIG_REISERFS_CHECK
- if ( src_bi.bi_bh != PATH_H_PBUFFER (tb->tb_path, h)/*tb->S[h]*/ || dest_bi.bi_bh != tb->R[h])
- reiserfs_panic (tb->tb_sb, "internal_shift_right", "src (%p) must be == tb->S[h](%p) when it disappears",
- src_bi.bi_bh, PATH_H_PBUFFER (tb->tb_path, h));
-#endif
/* when S[h] disappers replace left delemiting key as well */
if (tb->CFL[h])
- replace_key(tb->tb_sb, cf, d_key_position, tb->CFL[h], tb->lkey[h]);
+ replace_key(tb->tb_fs, cf, d_key_position, tb->CFL[h], tb->lkey[h]);
} else
- replace_key(tb->tb_sb, cf, d_key_position, src_bi.bi_bh, nr - pointer_amount);
+ replace_key(tb->tb_fs, cf, d_key_position, src_bi.bi_bh, nr - pointer_amount);
}
/* last parameter is del_parameter */
- internal_move_pointers_items (tb->tb_sb, &dest_bi, &src_bi, LAST_TO_FIRST, pointer_amount, 0);
+ internal_move_pointers_items (tb->tb_fs, &dest_bi, &src_bi, LAST_TO_FIRST, pointer_amount, 0);
}
/* Insert delimiting key to R[h].
@@ -542,10 +469,10 @@ static void internal_shift1_right (struct tree_balance * tb,
internal_define_dest_src_infos (INTERNAL_SHIFT_FROM_S_TO_R, tb, h, &dest_bi, &src_bi, &d_key_position, &cf);
if (pointer_amount > 0) /* insert rkey from CFR[h] to right neighbor R[h] */
- internal_insert_key (tb->tb_sb, &dest_bi, 0, cf, d_key_position);
+ internal_insert_key (tb->tb_fs, &dest_bi, 0, cf, d_key_position);
/* last parameter is del_parameter */
- internal_move_pointers_items (tb->tb_sb, &dest_bi, &src_bi, LAST_TO_FIRST, pointer_amount, 1);
+ internal_move_pointers_items (tb->tb_fs, &dest_bi, &src_bi, LAST_TO_FIRST, pointer_amount, 1);
}
@@ -568,13 +495,7 @@ static void balance_internal_when_delete (struct tree_balance * tb,
bi.bi_position = PATH_H_POSITION (tb->tb_path, h + 1);
- internal_delete_childs (tb->tb_sb, &bi, child_pos, -insert_num);
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( tb->blknum[h] > 1 )
- reiserfs_panic (tb->tb_sb, "balance_internal_when_delete", "tb->blknum[%d]=%d when insert_size < 0",
- h, tb->blknum[h]);
-#endif /* CONFIG_REISERFS_CHECK */
+ internal_delete_childs (tb->tb_fs, &bi, child_pos, -insert_num);
n = B_NR_ITEMS(tbSh);
@@ -582,16 +503,8 @@ static void balance_internal_when_delete (struct tree_balance * tb,
if ( tb->blknum[h] == 0 ) {
/* node S[h] (root of the tree) is empty now */
struct buffer_head *new_root;
+ struct reiserfs_super_block * sb;
-#ifdef CONFIG_REISERFS_CHECK
- if (n || B_BLK_HEAD (tbSh)->blk_free_space != MAX_CHILD_SIZE(tbSh) - DC_SIZE)
- reiserfs_panic (tb->tb_sb, "balance_internal_when_delete", "buffer must have only 0 keys (%d)",
- n);
-
- if (bi.bi_parent)
- reiserfs_panic (tb->tb_sb, "balance_internal_when_delete", "root has parent (%p)", bi.bi_parent);
-#endif /* CONFIG_REISERFS_CHECK */
-
/* choose a new root */
if ( ! tb->L[h-1] || ! B_NR_ITEMS(tb->L[h-1]) )
new_root = tb->R[h-1];
@@ -599,11 +512,12 @@ static void balance_internal_when_delete (struct tree_balance * tb,
new_root = tb->L[h-1];
/* update super block's tree height and pointer to a root block */
- tb->tb_sb->s_rs->s_v1.s_root_block = cpu_to_le32 (new_root->b_blocknr);
- tb->tb_sb->s_rs->s_v1.s_tree_height = SB_TREE_HEIGHT (tb->tb_sb) - 1;
+ sb = tb->tb_fs->fs_ondisk_sb;
+ set_sb_root_block (sb, new_root->b_blocknr);
+ set_sb_tree_height (sb, get_sb_tree_height (sb) - 1);
- mark_buffer_dirty (tb->tb_sb->s_sbh);
- tb->tb_sb->s_dirt = 1;
+ mark_buffer_dirty (tb->tb_fs->fs_super_bh);
+ tb->tb_fs->fs_dirt = 1;
/* mark buffer S[h] not uptodate and put it in free list */
reiserfs_invalidate_buffer(tb, tbSh, 1);
@@ -613,13 +527,6 @@ static void balance_internal_when_delete (struct tree_balance * tb,
}
if ( tb->L[h] && tb->lnum[h] == -B_NR_ITEMS(tb->L[h]) - 1 ) { /* join S[h] with L[h] */
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( tb->rnum[h] != 0 )
- reiserfs_panic (tb->tb_sb, "balance_internal_when_delete", "invalid tb->rnum[%d]==%d when joining S[h] with L[h]",
- h, tb->rnum[h]);
-#endif /* CONFIG_REISERFS_CHECK */
-
internal_shift_left (INTERNAL_SHIFT_FROM_S_TO_L, tb, h, n + 1);/*tb->L[h], tb->CFL[h], tb->lkey[h], tb->S[h], n+1);*/
reiserfs_invalidate_buffer(tb, tbSh, 1); /* preserve not needed, internal, 1 mean free block */
@@ -627,46 +534,22 @@ static void balance_internal_when_delete (struct tree_balance * tb,
}
if ( tb->R[h] && tb->rnum[h] == -B_NR_ITEMS(tb->R[h]) - 1 ) { /* join S[h] with R[h] */
-#ifdef CONFIG_REISERFS_CHECK
- if ( tb->lnum[h] != 0 )
- reiserfs_panic (tb->tb_sb, "balance_internal_when_delete", "invalid tb->lnum[%d]==%d when joining S[h] with R[h]",
- h, tb->lnum[h]);
-#endif /* CONFIG_REISERFS_CHECK */
-
internal_shift_right (INTERNAL_SHIFT_FROM_S_TO_R, tb, h, n + 1);
reiserfs_invalidate_buffer (tb, tbSh, 1);
return;
}
if ( tb->lnum[h] < 0 ) { /* borrow from left neighbor L[h] */
-#ifdef CONFIG_REISERFS_CHECK
- if ( tb->rnum[h] != 0 )
- reiserfs_panic (tb->tb_sb, "balance_internal_when_delete", "invalid tb->rnum[%d]==%d when borrow from L[h]",
- h, tb->rnum[h]);
-#endif /* CONFIG_REISERFS_CHECK */
-
internal_shift_right (INTERNAL_SHIFT_FROM_L_TO_S, tb, h, -tb->lnum[h]);
return;
}
if ( tb->rnum[h] < 0 ) { /* borrow from right neighbor R[h] */
-#ifdef CONFIG_REISERFS_CHECK
- if ( tb->lnum[h] != 0 )
- reiserfs_panic (tb->tb_sb, "balance_internal_when_delete", "invalid tb->lnum[%d]==%d when borrow from R[h]",
- h, tb->lnum[h]);
-#endif /* CONFIG_REISERFS_CHECK */
internal_shift_left (INTERNAL_SHIFT_FROM_R_TO_S, tb, h, -tb->rnum[h]);/*tb->S[h], tb->CFR[h], tb->rkey[h], tb->R[h], -tb->rnum[h]);*/
return;
}
if ( tb->lnum[h] > 0 ) { /* split S[h] into two parts and put them into neighbors */
-#ifdef CONFIG_REISERFS_CHECK
- if ( tb->rnum[h] == 0 || tb->lnum[h] + tb->rnum[h] != n + 1 )
- reiserfs_panic (tb->tb_sb, "balance_internal_when_delete",
- "invalid tb->lnum[%d]==%d or tb->rnum[%d]==%d when S[h](item number == %d) is split between them",
- h, tb->lnum[h], h, tb->rnum[h], n);
-#endif /* CONFIG_REISERFS_CHECK */
-
internal_shift_left (INTERNAL_SHIFT_FROM_S_TO_L, tb, h, tb->lnum[h]);/*tb->L[h], tb->CFL[h], tb->lkey[h], tb->S[h], tb->lnum[h]);*/
internal_shift_right (INTERNAL_SHIFT_FROM_S_TO_R, tb, h, tb->rnum[h]);
reiserfs_invalidate_buffer (tb, tbSh, 1);
@@ -682,12 +565,6 @@ static void balance_internal_when_delete (struct tree_balance * tb,
void replace_lkey (struct tree_balance * tb,
int h, struct item_head * key)
{
-#ifdef CONFIG_REISERFS_CHECK
- if (tb->L[h] == NULL || tb->CFL[h] == NULL)
- reiserfs_panic (tb->tb_sb, "replace_lkey: 12255: "
- "L[h](%p) and CFL[h](%p) must exist in replace_lkey", tb->L[h], tb->CFL[h]);
-#endif
-
if (B_NR_ITEMS(PATH_H_PBUFFER(tb->tb_path, h)) == 0)
return;
@@ -701,16 +578,6 @@ void replace_lkey (struct tree_balance * tb,
void replace_rkey (struct tree_balance * tb,
int h, struct item_head * key)
{
-#ifdef CONFIG_REISERFS_CHECK
- if (tb->R[h] == NULL || tb->CFR[h] == NULL)
- reiserfs_panic (tb->tb_sb, "replace_rkey: 12260: "
- "R[h](%p) and CFR[h](%p) must exist in replace_rkey", tb->R[h], tb->CFR[h]);
-
- if (B_NR_ITEMS(tb->R[h]) == 0)
- reiserfs_panic (tb->tb_sb, "replace_rkey: 12265: "
- "R[h] can not be empty if it exists (item number=%d)", B_NR_ITEMS(tb->R[h]));
-#endif
-
memcpy (B_N_PDELIM_KEY(tb->CFR[h],tb->rkey[h]), key, KEY_SIZE);
mark_buffer_dirty (tb->CFR[h]);
@@ -747,11 +614,6 @@ int balance_internal (struct tree_balance * tb, /* tree_balance structure */
struct buffer_head * new_insert_ptr = NULL;
struct item_head * new_insert_key_addr = insert_key;
-#ifdef CONFIG_REISERFS_CHECK
- if ( h < 1 )
- reiserfs_panic (tb->tb_sb, "balance_internal", "h (%d) can not be < 1 on internal level", h);
-#endif /* CONFIG_REISERFS_CHECK */
-
order = ( tbSh ) ? PATH_H_POSITION (tb->tb_path, h + 1)/*tb->S[h]->b_item_order*/ : 0;
/* Using insert_size[h] calculate the number insert_num of items
@@ -759,17 +621,6 @@ int balance_internal (struct tree_balance * tb, /* tree_balance structure */
insert_num = tb->insert_size[h]/((int)(KEY_SIZE + DC_SIZE));
/* Check whether insert_num is proper **/
-#ifdef CONFIG_REISERFS_CHECK
- if ( insert_num < -2 || insert_num > 2 )
- reiserfs_panic (tb->tb_sb, "balance_internal",
- "incorrect number of items inserted to the internal node (%d)", insert_num);
-
- if ( h > 1 && (insert_num > 1 || insert_num < -1) )
- reiserfs_panic (tb->tb_sb, "balance_internal",
- "incorrect number of items (%d) inserted to the internal node on a level (h=%d) higher than last internal level",
- insert_num, h);
-#endif /* CONFIG_REISERFS_CHECK */
-
/* Make balance in case insert_num < 0 */
if ( insert_num < 0 ) {
balance_internal_when_delete (tb, h, child_pos);
@@ -780,7 +631,7 @@ int balance_internal (struct tree_balance * tb, /* tree_balance structure */
if ( tb->lnum[h] > 0 ) {
/* shift lnum[h] items from S[h] to the left neighbor L[h].
check how many of new items fall into L[h] or CFL[h] after shifting */
- n = B_BLK_HEAD(tb->L[h])->blk_nr_item; /* number of items in L[h] */
+ n = get_blkh_nr_items (B_BLK_HEAD(tb->L[h])); /* number of items in L[h] */
if ( tb->lnum[h] <= child_pos ) {
/* new items don't fall into L[h] or CFL[h] */
internal_shift_left (INTERNAL_SHIFT_FROM_S_TO_L, tb, h, tb->lnum[h]);
@@ -793,7 +644,7 @@ int balance_internal (struct tree_balance * tb, /* tree_balance structure */
bi.bi_bh = tb->L[h];
bi.bi_parent = tb->FL[h];
bi.bi_position = get_left_neighbor_position (tb, h);
- internal_insert_childs (tb->tb_sb, &bi,/*tb->L[h], tb->S[h-1]->b_next*/ n + child_pos + 1,
+ internal_insert_childs (tb->tb_fs, &bi,/*tb->L[h], tb->S[h-1]->b_next*/ n + child_pos + 1,
insert_num,insert_key,insert_ptr);
insert_num = 0;
@@ -808,16 +659,16 @@ int balance_internal (struct tree_balance * tb, /* tree_balance structure */
bi.bi_bh = tb->L[h];
bi.bi_parent = tb->FL[h];
bi.bi_position = get_left_neighbor_position (tb, h);
- internal_insert_childs (tb->tb_sb, &bi,/*tb->L[h], tb->S[h-1]->b_next,*/ n + child_pos + 1,k,
+ internal_insert_childs (tb->tb_fs, &bi,/*tb->L[h], tb->S[h-1]->b_next,*/ n + child_pos + 1,k,
insert_key,insert_ptr);
replace_lkey(tb, h, insert_key + k);
/* replace the first node-ptr in S[h] by node-ptr to insert_ptr[k] */
- (dc = B_N_CHILD(tbSh, 0))->dc_size =
- MAX_CHILD_SIZE(insert_ptr[k]) -
- B_BLK_HEAD(insert_ptr[k])->blk_free_space;
- dc->dc_block_number = insert_ptr[k]->b_blocknr;
+ dc = B_N_CHILD(tbSh, 0);
+ set_dc_child_size (dc, MAX_CHILD_SIZE(insert_ptr[k]->b_size) -
+ get_blkh_free_space (B_BLK_HEAD(insert_ptr[k])));
+ set_dc_child_blocknr (dc, insert_ptr[k]->b_blocknr);
mark_buffer_dirty (tbSh);
@@ -832,7 +683,7 @@ int balance_internal (struct tree_balance * tb, /* tree_balance structure */
if ( tb->rnum[h] > 0 ) {
/*shift rnum[h] items from S[h] to the right neighbor R[h]*/
/* check how many of new items fall into R or CFR after shifting */
- n = B_BLK_HEAD (tbSh)->blk_nr_item; /* number of items in S[h] */
+ n = get_blkh_nr_items (B_BLK_HEAD (tbSh)); /* number of items in S[h] */
if ( n - tb->rnum[h] >= child_pos )
/* new items fall into S[h] */
/*internal_shift_right(tb,h,tbSh,tb->CFR[h],tb->rkey[h],tb->R[h],tb->rnum[h]);*/
@@ -847,7 +698,7 @@ int balance_internal (struct tree_balance * tb, /* tree_balance structure */
bi.bi_bh = tb->R[h];
bi.bi_parent = tb->FR[h];
bi.bi_position = get_right_neighbor_position (tb, h);
- internal_insert_childs (tb->tb_sb, &bi, /*tb->R[h],tb->S[h-1]->b_next*/ child_pos - n - insert_num + tb->rnum[h] - 1,
+ internal_insert_childs (tb->tb_fs, &bi, /*tb->R[h],tb->S[h-1]->b_next*/ child_pos - n - insert_num + tb->rnum[h] - 1,
insert_num,insert_key,insert_ptr);
insert_num = 0;
}
@@ -863,15 +714,15 @@ int balance_internal (struct tree_balance * tb, /* tree_balance structure */
bi.bi_bh = tb->R[h];
bi.bi_parent = tb->FR[h];
bi.bi_position = get_right_neighbor_position (tb, h);
- internal_insert_childs (tb->tb_sb, &bi, /*tb->R[h], tb->R[h]->b_child,*/ 0, k, insert_key + 1, insert_ptr + 1);
+ internal_insert_childs (tb->tb_fs, &bi, /*tb->R[h], tb->R[h]->b_child,*/ 0, k, insert_key + 1, insert_ptr + 1);
replace_rkey(tb, h, insert_key + insert_num - k - 1);
/* replace the first node-ptr in R[h] by node-ptr insert_ptr[insert_num-k-1]*/
- (dc = B_N_CHILD(tb->R[h], 0))->dc_size =
- MAX_CHILD_SIZE(insert_ptr[insert_num-k-1]) -
- B_BLK_HEAD(insert_ptr[insert_num-k-1])->blk_free_space;
- dc->dc_block_number = insert_ptr[insert_num-k-1]->b_blocknr;
+ dc = B_N_CHILD(tb->R[h], 0);
+ set_dc_child_size (dc, MAX_CHILD_SIZE(insert_ptr[insert_num-k-1]->b_size) -
+ get_blkh_free_space (B_BLK_HEAD(insert_ptr[insert_num-k-1])));
+ set_dc_child_blocknr (dc, insert_ptr[insert_num-k-1]->b_blocknr);
mark_buffer_dirty (tb->R[h]);
@@ -880,20 +731,8 @@ int balance_internal (struct tree_balance * tb, /* tree_balance structure */
}
/** Fill new node that appears instead of S[h] **/
-#ifdef CONFIG_REISERFS_CHECK
- if ( tb->blknum[h] > 2 )
- reiserfs_panic(0, "balance_internal", "blknum can not be > 2 for internal level");
- if ( tb->blknum[h] < 0 )
- reiserfs_panic(0, "balance_internal", "blknum can not be < 0");
-#endif /* CONFIG_REISERFS_CHECK */
-
if ( ! tb->blknum[h] )
{ /* node S[h] is empty now */
-#ifdef CONFIG_REISERFS_CHECK
- if ( ! tbSh )
- reiserfs_panic(0,"balance_internal", "S[h] is equal NULL");
-#endif /* CONFIG_REISERFS_CHECK */
-
/* Mark buffer as invalid and put it to head of free list. */
reiserfs_invalidate_buffer(tb, tbSh, 1);/* do not preserve, internal node*/
return order;
@@ -903,21 +742,23 @@ int balance_internal (struct tree_balance * tb, /* tree_balance structure */
/* create new root */
struct disk_child * dc;
struct buffer_head * tbSh_1 = PATH_H_PBUFFER (tb->tb_path, h - 1);
-
+ struct reiserfs_super_block * sb;
if ( tb->blknum[h] != 1 )
reiserfs_panic(0, "balance_internal", "One new node required for creating the new root");
/* S[h] = empty buffer from the list FEB. */
tbSh = get_FEB (tb);
- B_BLK_HEAD(tbSh)->blk_level = h + 1;
+ set_blkh_level (B_BLK_HEAD(tbSh), h + 1);
/* Put the unique node-pointer to S[h] that points to S[h-1]. */
- (dc = B_N_CHILD(tbSh, 0))->dc_block_number = tbSh_1->b_blocknr;
- dc->dc_size = MAX_CHILD_SIZE (tbSh_1) - B_BLK_HEAD(tbSh_1)->blk_free_space;
+ dc = B_N_CHILD(tbSh, 0);
+ set_dc_child_size (dc, MAX_CHILD_SIZE (tbSh_1->b_size) - get_blkh_free_space (B_BLK_HEAD(tbSh_1)));
+ set_dc_child_blocknr (dc, tbSh_1->b_blocknr);
tb->insert_size[h] -= DC_SIZE;
- B_BLK_HEAD(tbSh)->blk_free_space -= DC_SIZE;
+ set_blkh_free_space (B_BLK_HEAD(tbSh),
+ get_blkh_free_space (B_BLK_HEAD(tbSh)) - DC_SIZE);
mark_buffer_dirty (tbSh);
@@ -925,11 +766,12 @@ int balance_internal (struct tree_balance * tb, /* tree_balance structure */
PATH_OFFSET_PBUFFER(tb->tb_path, ILLEGAL_PATH_ELEMENT_OFFSET) = tbSh;
/* Change root in structure super block. */
- tb->tb_sb->s_rs->s_v1.s_root_block = cpu_to_le32 (tbSh->b_blocknr);
- tb->tb_sb->s_rs->s_v1.s_tree_height = cpu_to_le16 (SB_TREE_HEIGHT (tb->tb_sb) + 1);
+ sb = tb->tb_fs->fs_ondisk_sb;
+ set_sb_root_block (sb, tbSh->b_blocknr);
+ set_sb_tree_height (sb, get_sb_tree_height (sb) + 1);
- mark_buffer_dirty (tb->tb_sb->s_sbh);
- tb->tb_sb->s_dirt = 1;
+ mark_buffer_dirty (tb->tb_fs->fs_super_bh);
+ tb->tb_fs->fs_dirt = 1;
}
if ( tb->blknum[h] == 2 ) {
@@ -940,8 +782,7 @@ int balance_internal (struct tree_balance * tb, /* tree_balance structure */
/* S_new = free buffer from list FEB */
S_new = get_FEB(tb);
- B_BLK_HEAD(S_new)->blk_level = h + 1;
-
+ set_blkh_level (B_BLK_HEAD(S_new), h + 1);
dest_bi.bi_bh = S_new;
dest_bi.bi_parent = 0;
@@ -950,7 +791,7 @@ int balance_internal (struct tree_balance * tb, /* tree_balance structure */
src_bi.bi_parent = PATH_H_PPARENT (tb->tb_path, h);
src_bi.bi_position = PATH_H_POSITION (tb->tb_path, h + 1);
- n = B_BLK_HEAD(tbSh)->blk_nr_item; /* number of items in S[h] */
+ n = get_blkh_nr_items (B_BLK_HEAD(tbSh)); /* number of items in S[h] */
snum = (insert_num + n + 1)/2;
if ( n - snum >= child_pos ) {
/* new items don't fall into S_new */
@@ -959,7 +800,7 @@ int balance_internal (struct tree_balance * tb, /* tree_balance structure */
memcpy (&new_insert_key,B_N_PDELIM_KEY(tbSh,n - snum),
KEY_SIZE);
/* last parameter is del_par */
- internal_move_pointers_items (tb->tb_sb, &dest_bi, &src_bi, LAST_TO_FIRST, snum, 0);
+ internal_move_pointers_items (tb->tb_fs, &dest_bi, &src_bi, LAST_TO_FIRST, snum, 0);
} else if ( n + insert_num - snum < child_pos ) {
/* all new items fall into S_new */
/* store the delimiting key for the next level */
@@ -967,11 +808,11 @@ int balance_internal (struct tree_balance * tb, /* tree_balance structure */
memcpy(&new_insert_key,B_N_PDELIM_KEY(tbSh,n + insert_num - snum),
KEY_SIZE);
/* last parameter is del_par */
- internal_move_pointers_items (tb->tb_sb, &dest_bi, &src_bi, LAST_TO_FIRST, snum - insert_num, 0);
+ internal_move_pointers_items (tb->tb_fs, &dest_bi, &src_bi, LAST_TO_FIRST, snum - insert_num, 0);
/* internal_move_pointers_items(S_new,tbSh,1,snum - insert_num,0);*/
/* insert insert_num keys and node-pointers into S_new */
- internal_insert_childs (tb->tb_sb, &dest_bi, /*S_new,tb->S[h-1]->b_next,*/child_pos - n - insert_num + snum - 1,
+ internal_insert_childs (tb->tb_fs, &dest_bi, /*S_new,tb->S[h-1]->b_next,*/child_pos - n - insert_num + snum - 1,
insert_num,insert_key,insert_ptr);
insert_num = 0;
@@ -980,22 +821,22 @@ int balance_internal (struct tree_balance * tb, /* tree_balance structure */
/* some items fall into S_new, but some don't fall */
/* last parameter is del_par */
- internal_move_pointers_items (tb->tb_sb, &dest_bi, &src_bi, LAST_TO_FIRST, n - child_pos + 1, 1);
+ internal_move_pointers_items (tb->tb_fs, &dest_bi, &src_bi, LAST_TO_FIRST, n - child_pos + 1, 1);
/* internal_move_pointers_items(S_new,tbSh,1,n - child_pos + 1,1);*/
/* calculate number of new items that fall into S_new */
k = snum - n + child_pos - 1;
- internal_insert_childs (tb->tb_sb, &dest_bi, /*S_new,*/ 0, k, insert_key + 1, insert_ptr+1);
+ internal_insert_childs (tb->tb_fs, &dest_bi, /*S_new,*/ 0, k, insert_key + 1, insert_ptr+1);
/* new_insert_key = insert_key[insert_num - k - 1] */
memcpy(&new_insert_key,insert_key + insert_num - k - 1,
KEY_SIZE);
/* replace first node-ptr in S_new by node-ptr to insert_ptr[insert_num-k-1] */
- (dc = B_N_CHILD(S_new,0))->dc_size =
- MAX_CHILD_SIZE(insert_ptr[insert_num-k-1]) -
- B_BLK_HEAD(insert_ptr[insert_num-k-1])->blk_free_space;
- dc->dc_block_number = insert_ptr[insert_num-k-1]->b_blocknr;
+ dc = B_N_CHILD(S_new,0);
+ set_dc_child_size (dc, MAX_CHILD_SIZE(insert_ptr[insert_num-k-1]->b_size) -
+ get_blkh_free_space (B_BLK_HEAD(insert_ptr[insert_num-k-1])));
+ set_dc_child_blocknr (dc, insert_ptr[insert_num-k-1]->b_blocknr);
mark_buffer_dirty (S_new);
@@ -1003,50 +844,34 @@ int balance_internal (struct tree_balance * tb, /* tree_balance structure */
}
/* new_insert_ptr = node_pointer to S_new */
new_insert_ptr = S_new;
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( buffer_locked(S_new) )
- reiserfs_panic (tb->tb_sb, "balance_internal", "locked buffer S_new[]");
- if (S_new->b_count != 1)
- if (!(buffer_journaled(S_new) && S_new->b_count == 2)) {
- printk ("REISERFS: balance_internal: S_new->b_count != 1 (%u)\n", S_new->b_count);
- }
-#endif /* CONFIG_REISERFS_CHECK */
-
/*
S_new->b_count --;
*/
/*brelse(S_new);*/
}
- n = B_BLK_HEAD(tbSh)->blk_nr_item; /*number of items in S[h] */
+ n = get_blkh_nr_items (B_BLK_HEAD(tbSh)); /*number of items in S[h] */
-#ifndef FU //REISERFS_FSCK
if ( -1 <= child_pos && child_pos <= n && insert_num > 0 ) {
-#else
- if ( 0 <= child_pos && child_pos <= n && insert_num > 0 ) {
-#endif
- bi.bi_bh = tbSh;
- bi.bi_parent = PATH_H_PPARENT (tb->tb_path, h);
- bi.bi_position = PATH_H_POSITION (tb->tb_path, h + 1);
-#ifndef FU //REISERFS_FSCK
- if (child_pos == -1) {
- /* this is a little different from original do_balance:
- here we insert the minimal keys in the tree, that has never happened when file system works */
- if (tb->CFL[h-1] || insert_num != 1 || h != 1)
- die ("balance_internal: invalid child_pos");
-/* insert_child (tb->S[h], tb->S[h-1], child_pos, insert_num, B_N_ITEM_HEAD(tb->S[0],0), insert_ptr);*/
- internal_insert_childs (tb->tb_sb, &bi, child_pos, insert_num, B_N_PITEM_HEAD (PATH_PLAST_BUFFER (tb->tb_path), 0), insert_ptr);
- } else
-#endif
- internal_insert_childs (tb->tb_sb,
- &bi, child_pos,insert_num,insert_key,insert_ptr);
- }
+ bi.bi_bh = tbSh;
+ bi.bi_parent = PATH_H_PPARENT (tb->tb_path, h);
+ bi.bi_position = PATH_H_POSITION (tb->tb_path, h + 1);
+ if (child_pos == -1) {
+ /* this is a little different from original do_balance:
+ here we insert the minimal keys in the tree, that has never happened when file system works */
+ if (tb->CFL[h-1] || insert_num != 1 || h != 1)
+ die ("balance_internal: invalid child_pos");
+ /* insert_child (tb->S[h], tb->S[h-1], child_pos, insert_num, B_N_ITEM_HEAD(tb->S[0],0), insert_ptr);*/
+ internal_insert_childs (tb->tb_fs, &bi, child_pos, insert_num,
+ B_N_PITEM_HEAD (PATH_PLAST_BUFFER (tb->tb_path), 0), insert_ptr);
+ } else
+ internal_insert_childs (tb->tb_fs, &bi, child_pos,insert_num,insert_key,insert_ptr);
+ }
- memcpy (new_insert_key_addr,&new_insert_key,KEY_SIZE);
- insert_ptr[0] = new_insert_ptr;
+ memcpy (new_insert_key_addr,&new_insert_key,KEY_SIZE);
+ insert_ptr[0] = new_insert_ptr;
- return order;
- }
+ return order;
+}
diff --git a/reiserfscore/includes.h b/reiserfscore/includes.h
index b26aec9..2e6aabd 100644
--- a/reiserfscore/includes.h
+++ b/reiserfscore/includes.h
@@ -4,6 +4,7 @@
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include <errno.h>
#include <asm/types.h>
#include <sys/types.h>
diff --git a/reiserfscore/journal.c b/reiserfscore/journal.c
new file mode 100644
index 0000000..4f53e23
--- /dev/null
+++ b/reiserfscore/journal.c
@@ -0,0 +1,711 @@
+/*
+ * Copyright 2002 Hans Reiser
+ */
+
+#include "includes.h"
+
+/* this provides for everybody who wants to deal with journal */
+int replay_one_transaction (reiserfs_filsys_t *, reiserfs_trans_t *);
+void for_each_transaction (reiserfs_filsys_t *, action_on_trans_t);
+void for_each_block (reiserfs_filsys_t *, reiserfs_trans_t *, action_on_block_t);
+int get_boundary_transactions (reiserfs_filsys_t *, reiserfs_trans_t *,
+ reiserfs_trans_t *);
+int next_transaction (reiserfs_filsys_t *, reiserfs_trans_t *, reiserfs_trans_t);
+
+/* compares description block with commit block. returns 0 if they differ, 1
+ if they match */
+static int does_desc_match_commit (struct buffer_head *d_bh,
+ struct buffer_head *c_bh)
+{
+ return (get_commit_trans_id (c_bh) == get_desc_trans_id (d_bh) &&
+ get_commit_trans_len (c_bh) == get_desc_trans_len (d_bh));
+}
+
+
+/* d_bh is descriptor, return number of block where commit block of this
+ transaction is to be */
+unsigned long commit_expected (reiserfs_filsys_t * fs, struct buffer_head * d_bh)
+{
+ unsigned long offset;
+ struct journal_params * sb_jp;
+
+
+ sb_jp = sb_jp (fs->fs_ondisk_sb);
+ //desc = (struct reiserfs_journal_desc *)d_bh->b_data;
+ offset = d_bh->b_blocknr - get_jp_journal_1st_block (sb_jp);
+ return get_jp_journal_1st_block (sb_jp) +
+ ((offset + get_desc_trans_len (d_bh) + 1) % get_jp_journal_size (sb_jp));
+}
+
+
+/* d_bh contains journal descriptor, return number of block where descriptor
+ block of next transaction should be */
+unsigned long next_desc_expected (reiserfs_filsys_t * fs, struct buffer_head * d_bh)
+{
+ unsigned long offset;
+ struct journal_params * sb_jp;
+
+
+ sb_jp = sb_jp (fs->fs_ondisk_sb);
+ //desc = (struct reiserfs_journal_desc *)d_bh->b_data;
+ offset = d_bh->b_blocknr - get_jp_journal_1st_block (sb_jp);
+ return get_jp_journal_1st_block (sb_jp) +
+ ((offset + get_desc_trans_len (d_bh) + 2) % get_jp_journal_size (sb_jp));
+}
+
+
+/**/
+int is_valid_transaction (reiserfs_filsys_t * fs, struct buffer_head * d_bh)
+{
+ struct buffer_head * c_bh;
+
+
+ if (!d_bh || who_is_this (d_bh->b_data, d_bh->b_size) != THE_JDESC)
+ return 0;
+
+ /* read expected commit block and compare with descriptor block */
+ c_bh = bread (fs->fs_journal_dev, commit_expected (fs, d_bh), fs->fs_blocksize);
+ if (!c_bh)
+ return 0;
+
+ if (does_desc_match_commit (d_bh, c_bh)) {
+ brelse (c_bh);
+ return 1;
+ }
+ brelse (c_bh);
+ return 0;
+}
+
+
+/* read the journal and find the oldest and newest transactions, return numbe
+ of transactions fond */
+int get_boundary_transactions (reiserfs_filsys_t * fs,
+ reiserfs_trans_t * oldest,
+ reiserfs_trans_t * newest)
+{
+ struct reiserfs_super_block * sb;
+ unsigned long j_cur;
+ unsigned long j_start;
+ unsigned long j_size;
+ struct buffer_head * d_bh;
+ __u32 newest_trans_id, oldest_trans_id, trans_id;
+ int trans_nr;
+
+
+ sb = fs->fs_ondisk_sb;
+
+ j_start = get_jp_journal_1st_block (sb_jp (sb));
+ j_size = get_jp_journal_size (sb_jp (sb));
+
+ oldest_trans_id = 0xffffffff;
+ newest_trans_id = 0;
+
+ trans_nr = 0;
+ for (j_cur = 0; j_cur < j_size; j_cur ++) {
+ d_bh = bread (fs->fs_journal_dev, j_start + j_cur, fs->fs_blocksize);
+ if (!is_valid_transaction (fs, d_bh)) {
+ brelse (d_bh);
+ continue;
+ }
+
+ trans_nr ++;
+
+ trans_id = get_desc_trans_id (d_bh);
+ if (trans_id < oldest_trans_id) {
+ oldest_trans_id = trans_id;
+
+ oldest->mount_id = get_desc_mount_id (d_bh);
+ oldest->trans_id = get_desc_trans_id (d_bh);
+ oldest->desc_blocknr = d_bh->b_blocknr;
+ oldest->trans_len = get_desc_trans_len (d_bh);
+ oldest->commit_blocknr = commit_expected (fs, d_bh);
+ newest->next_trans_offset = next_desc_expected (fs, d_bh) - j_start;
+ }
+
+ if (trans_id > newest_trans_id) {
+ newest_trans_id = trans_id;
+
+ newest->mount_id = get_desc_mount_id (d_bh);
+ newest->trans_id = get_desc_trans_id (d_bh);
+ newest->desc_blocknr = d_bh->b_blocknr;
+ newest->trans_len = get_desc_trans_len (d_bh);
+ newest->commit_blocknr = commit_expected (fs, d_bh);
+ newest->next_trans_offset = next_desc_expected (fs, d_bh) - j_start;
+ }
+
+ j_cur += get_desc_trans_len (d_bh) + 1;
+ brelse (d_bh);
+ }
+
+ return trans_nr;
+}
+
+#define TRANS_FOUND 1
+#define TRANS_LAST 2
+#define TRANS_NOT_FOUND 0
+
+/* trans is a valid transaction. Look for valid transaction with smallest
+ trans id which is bigger than the id of the current one */
+int next_transaction (reiserfs_filsys_t * fs, reiserfs_trans_t * trans, reiserfs_trans_t break_trans)
+{
+ struct buffer_head * d_bh, * next_d_bh;
+ int found;
+ unsigned long j_start;
+ unsigned long j_offset;
+ unsigned long block;
+
+
+ j_start = get_jp_journal_1st_block (sb_jp (fs->fs_ondisk_sb));
+
+ found = TRANS_NOT_FOUND;
+
+ /* make sure that 'trans' is a valid transaction */
+ d_bh = bread (fs->fs_journal_dev, trans->desc_blocknr, fs->fs_blocksize);
+ if (!is_valid_transaction (fs, d_bh))
+ die ("next_transaction: valid transaction is expected");
+
+ block = next_desc_expected (fs, d_bh);
+ j_offset = block - j_start;
+
+ while (1) {
+ next_d_bh = bread (fs->fs_journal_dev, block, fs->fs_blocksize);
+ if (is_valid_transaction (fs, next_d_bh))
+ break;
+
+ brelse (next_d_bh);
+ j_offset ++;
+ block = j_start + (j_offset % get_jp_journal_size (sb_jp (fs->fs_ondisk_sb)));
+ }
+
+ //next_desc = (struct reiserfs_journal_desc *)next_d_bh->b_data;
+
+ if (break_trans.trans_id >= get_desc_trans_id (next_d_bh)) {
+ /* found transaction is newer */
+ trans->mount_id = get_desc_mount_id (next_d_bh);
+ trans->trans_id = get_desc_trans_id (next_d_bh);
+ trans->desc_blocknr = next_d_bh->b_blocknr;
+ trans->trans_len = get_desc_trans_len (next_d_bh);
+ trans->commit_blocknr = commit_expected (fs, next_d_bh);
+ trans->next_trans_offset = next_desc_expected (fs, next_d_bh) - j_start;
+ found = TRANS_FOUND;
+ if (break_trans.trans_id == get_desc_trans_id (next_d_bh))
+ found = TRANS_LAST;
+ }
+
+ brelse (d_bh);
+ brelse (next_d_bh);
+ return found;
+}
+
+static void read_journal_write_in_place (reiserfs_filsys_t * fs, reiserfs_trans_t * trans, int index,
+ unsigned long in_journal, unsigned long in_place)
+{
+ struct buffer_head * j_bh, * bh;
+
+ j_bh = bread (fs->fs_journal_dev, in_journal, fs->fs_blocksize);
+ if (!j_bh) {
+ fprintf (stderr, "replay_one_transaction: transaction %lu: reading %lu block failed\n",
+ trans->trans_id, in_journal);
+ return;
+ }
+ if (not_journalable (fs, in_place)) {
+ fprintf (stderr, "replay_one_transaction: transaction %lu: block %ld should not be journalled (%lu)\n",
+ trans->trans_id, in_journal, in_place);
+ brelse (j_bh);
+ return;
+ }
+
+ bh = getblk (fs->fs_dev, in_place, fs->fs_blocksize);
+
+ memcpy (bh->b_data, j_bh->b_data, bh->b_size);
+ mark_buffer_dirty (bh);
+ mark_buffer_uptodate (bh, 1);
+ bwrite (bh);
+ brelse (bh);
+ brelse (j_bh);
+
+}
+
+
+/* go through all blocks of transaction and call 'action' each of them */
+void for_each_block (reiserfs_filsys_t * fs, reiserfs_trans_t * trans,
+ action_on_block_t action)
+{
+ struct buffer_head * d_bh, * c_bh;
+ struct reiserfs_journal_desc * desc;
+ struct reiserfs_journal_commit * commit;
+ unsigned long j_start, j_offset, j_size;
+ int i;
+ unsigned long block;
+ int trans_half;
+
+
+ d_bh = bread (fs->fs_journal_dev, trans->desc_blocknr, fs->fs_blocksize);
+ if (!d_bh) {
+ reiserfs_warning (stdout, "reading descriptor block %lu failed\n", trans->desc_blocknr);
+ return;
+ }
+
+ c_bh = bread (fs->fs_journal_dev, trans->commit_blocknr, fs->fs_blocksize);
+ if (!c_bh) {
+ reiserfs_warning (stdout, "reading commit block %lu failed\n", trans->commit_blocknr);
+ brelse (d_bh);
+ return;
+ }
+
+ desc = (struct reiserfs_journal_desc *)(d_bh->b_data);
+ commit = (struct reiserfs_journal_commit *)(c_bh->b_data);
+
+ /* first block of journal and size of journal */
+ j_start = get_jp_journal_1st_block (sb_jp (fs->fs_ondisk_sb));
+ j_size = get_jp_journal_size (sb_jp (fs->fs_ondisk_sb));
+
+ /* offset in the journal where the transaction starts */
+ j_offset = trans->desc_blocknr - j_start + 1;
+
+ trans_half = journal_trans_half (d_bh->b_size);
+ for (i = 0; i < trans->trans_len; i ++, j_offset ++) {
+ if (i < trans_half)
+ block = le32_to_cpu (desc->j2_realblock[i]);
+ else
+ block = le32_to_cpu (commit->j3_realblock[i - trans_half]);
+ action (fs, trans, i, j_start + (j_offset % j_size), block);
+ }
+
+ brelse (d_bh);
+ brelse (c_bh);
+}
+
+
+/* transaction is supposed to be valid */
+int replay_one_transaction (reiserfs_filsys_t * fs,
+ reiserfs_trans_t * trans)
+{
+ for_each_block (fs, trans, read_journal_write_in_place);
+ return 0;
+}
+
+
+void for_each_transaction (reiserfs_filsys_t * fs, action_on_trans_t action)
+{
+ reiserfs_trans_t oldest, newest;
+ int ret = 0;
+
+ if (!get_boundary_transactions (fs, &oldest, &newest))
+ return;
+
+ while (1) {
+ action (fs, &oldest);
+ if ((ret == TRANS_LAST) || ((ret = next_transaction (fs, &oldest, newest)) == TRANS_NOT_FOUND) )
+ break;
+ }
+}
+
+
+/* user is allowed to specify journal size and ratio between journal size and
+ max trans len. Max batch is calculated as 9/10 of max trans len. Max commit
+ and trans ages are not tunable so far */
+static __u32 advise_journal_length (reiserfs_filsys_t * fs, __u32 desired)
+{
+ if (!desired)
+ return journal_default_size (fs->fs_super_bh->b_blocknr, fs->fs_blocksize);
+
+ if (desired < JOURNAL_MIN_SIZE + 1) {
+ reiserfs_warning (stderr, "WARNING: Journal length is too small %u, resetting to minimal possible %u\n",
+ desired, JOURNAL_MIN_SIZE + 1);
+ return JOURNAL_MIN_SIZE;
+ }
+
+ return desired;
+}
+
+
+unsigned long get_size_of_journal_or_reserved_area (struct reiserfs_super_block * sb)
+{
+ if (is_reiserfs_jr_magic_string (sb))
+ return get_sb_reserved_for_journal (sb);
+
+ /* with standard journal */
+ return get_jp_journal_size (sb_jp (sb)) + 1;
+}
+
+
+__u32 advise_journal_max_trans_len (__u32 desired, __u32 journal_size, int blocksize)
+{
+ __u32 saved;
+ __u32 ratio = 1;
+
+ if (blocksize < 4096)
+ ratio = 4096/blocksize;
+
+ saved = desired;
+ if (!desired)
+ desired = JOURNAL_TRANS_MAX/ratio;
+
+ if (journal_size / desired < JOURNAL_MIN_RATIO)
+ desired = journal_size / JOURNAL_MIN_RATIO;
+
+ if (desired > JOURNAL_TRANS_MAX/ratio)
+ desired = JOURNAL_TRANS_MAX/ratio;
+
+ if (desired < JOURNAL_TRANS_MIN/ratio)
+ desired = JOURNAL_TRANS_MIN/ratio;
+
+ if (saved && saved != desired)
+ reiserfs_warning (stderr,
+ "WARNING: wrong transaction "
+ "max size (%u). Changed to %u\n", saved, desired);
+ return desired;
+}
+#if 0
+ __u32 ret_val;
+ ret_val = 0;
+ if (!desired) ret_val = JOURNAL_TRANS_MAX;
+ if (desired<journal_size/8) ret_val = journal_size/8;
+ if (desired>journal_size/2) ret_val = journal_size/2;
+ if (desired>JOURNAL_TRANS_MAX) ret_val = JOURNAL_TRANS_MAX;
+ if (ret_val) {
+ reiserfs_warning (stderr, "WARNING: Journal max trans length is wrong seting: %u, resetting to available possible %u\n",
+ desired, ret_val);
+ } else {
+ ret_val = desired;
+ }
+ return ret_val;
+}
+#endif
+
+__u32 advise_journal_max_batch (unsigned long journal_trans_max)
+{
+ return journal_trans_max*JOURNAL_MAX_BATCH/JOURNAL_TRANS_MAX;
+}
+
+
+__u32 advise_journal_max_commit_age (void)
+{
+ return JOURNAL_MAX_COMMIT_AGE;
+}
+
+
+__u32 advise_journal_max_trans_age (void)
+{
+ return JOURNAL_MAX_TRANS_AGE;
+}
+
+
+/* read journal header and make sure that it matches with the filesystem
+ opened */
+int reiserfs_open_journal (reiserfs_filsys_t * fs, char * j_filename, int flags)
+{
+ struct buffer_head * bh;
+ struct reiserfs_journal_header * j_head;
+ struct reiserfs_super_block * sb;
+
+
+ sb = fs->fs_ondisk_sb;
+
+ if (!j_filename) {
+ if (is_reiserfs_jr_magic_string (sb)) {
+ /* create a special file to access journal */
+ return 0;
+ }
+
+ j_filename = fs->fs_file_name;
+ } else if (!is_reiserfs_jr_magic_string (sb)) {
+ /* make sure that name specified is a correct name */
+ if (strcmp (j_filename, fs->fs_file_name)) {
+ reiserfs_warning (stderr, "Filesystem with standard journal found, "
+ "wrong name of specified journal device %s \n", j_filename);
+ return 0;
+ }
+ }
+
+ fs->fs_journal_dev = open (j_filename, flags | O_LARGEFILE);
+ if (fs->fs_journal_dev == -1)
+ return 0;
+
+ asprintf (&fs->fs_j_file_name, "%s", j_filename);
+
+ /* read journal header */
+ bh = bread (fs->fs_journal_dev, get_jp_journal_1st_block (sb_jp (sb)) +
+ get_jp_journal_size (sb_jp (sb)), fs->fs_blocksize);
+ if (!bh) {
+ reiserfs_warning (stderr, "reiserfs_open_journal: bread failed reading "
+ "journal header\n");
+ return 0;
+ }
+
+ j_head = (struct reiserfs_journal_header *)(bh->b_data);
+
+ if (is_reiserfs_jr_magic_string (sb)) {
+ if (get_jp_journal_1st_block (&j_head->jh_journal) != get_jp_journal_1st_block (sb_jp (sb)) ||
+ get_jp_journal_dev (&j_head->jh_journal) != get_jp_journal_dev (sb_jp (sb)) ||
+ get_jp_journal_size (&j_head->jh_journal) != get_jp_journal_size (sb_jp (sb))) {
+ reiserfs_warning (stderr, "reiserfs_open_journal: no journal found on %s\n", j_filename);
+ brelse (bh);
+ return 0;
+ }
+ }
+
+ fs->fs_jh_bh = bh;
+ return 1;
+}
+
+
+/* initialize super block's journal related fields and journal header fields. If
+ len is 0 - make journal of default size */
+int reiserfs_create_journal (reiserfs_filsys_t * fs, char * j_filename,
+ unsigned long offset,
+ unsigned long len, /* journal size including journal header */
+ int transaction_max_size)
+{
+ struct stat st;
+ struct buffer_head * bh;
+ struct reiserfs_journal_header * jh;
+ struct reiserfs_super_block * sb;
+ unsigned long blocks;
+
+
+ sb = fs->fs_ondisk_sb;
+
+
+ if (!j_filename || !strcmp (j_filename, fs->fs_file_name)) {
+ /* journal is to be on a host device, make sure that there is enough
+ space for it */
+ if (!len)
+ len = journal_default_size (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1;
+
+ if (!is_block_count_correct (
+ fs->fs_super_bh->b_blocknr, fs->fs_blocksize, get_sb_block_count (sb), len - 1)) {
+// if (get_sb_block_count (sb) < min_block_amount (fs->fs_blocksize, len)) {
+ /* host device does not contain enough blocks */
+ reiserfs_warning (stderr, "reiserfs_create_journal: "
+ "can not create filesystem on %d blocks\n",
+ get_sb_block_count (sb));
+ return 0;
+ }
+
+ j_filename = fs->fs_file_name;
+
+ /* journal is not on a separate device starts after super block and first
+ bitmap. offset is ignored */
+ offset = get_journal_start_must (fs);
+ st.st_rdev = 0;
+ } else {
+ /* journal is to be on separate device */
+ blocks = count_blocks (j_filename, fs->fs_blocksize);
+ if (!len) {
+ /* default size of a journal on a separate device is whole device */
+ if (blocks < offset) {
+ reiserfs_warning (stderr,
+ "reiserfs_create_journal: "
+ "offset is %lu, blocks on device %lu\n",
+ offset, blocks);
+ return 0;
+ }
+ len = blocks - offset;
+ }
+
+ if (len > journal_default_size (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1)
+ reiserfs_warning (stderr,
+ "NOTE: journal new size %lu is bigger than default size %lu:\n"
+ "this may slow down journal initializing and mounting. Hope it is ok.\n\n",
+ len, journal_default_size (fs->fs_super_bh->b_blocknr, fs->fs_blocksize) + 1);
+
+ if (blocks < offset + len) {
+ reiserfs_warning (stderr,
+ "reiserfs_create_journal: "
+ "no enough blocks on device %lu, needed %lu\n",
+ blocks, offset + len);
+ return 0;
+ }
+ if (stat (j_filename, &st) == -1) {
+ reiserfs_warning (stderr, "reiserfs_create_journal: "
+ "stat %s failed: %m\n", j_filename);
+ return 0;
+ }
+ if (!S_ISBLK (st.st_mode)) {
+ reiserfs_warning (stderr, "reiserfs_create_journal: "
+ "%s is not a block device (%x)\n", j_filename, st.st_rdev);
+ return 0;
+ }
+ }
+
+ fs->fs_journal_dev = open (j_filename, O_RDWR | O_LARGEFILE);
+ if (fs->fs_journal_dev == -1) {
+ reiserfs_warning (stderr, "reiserfs_create_journal: could not open %s: %m\n",
+ j_filename);
+ return 0;
+ }
+
+ asprintf (&fs->fs_j_file_name, "%s", j_filename);
+
+ len = advise_journal_length (fs, len - 1) + 1;
+
+ /* get journal header */
+ bh = getblk (fs->fs_journal_dev, offset + len - 1, fs->fs_blocksize);
+ if (!bh) {
+ reiserfs_warning (stderr, "reiserfs_create_journal: "
+ "getblk failed\n");
+ return 0;
+ }
+
+ /* fill journal header */
+ jh = (struct reiserfs_journal_header *)bh->b_data;
+ set_jp_journal_1st_block (&jh->jh_journal, offset);
+ set_jp_journal_dev (&jh->jh_journal, st.st_rdev);
+ set_jp_journal_magic (&jh->jh_journal, get_random ());
+
+ set_jp_journal_size (&jh->jh_journal, len - 1);
+ set_jp_journal_max_trans_len (&jh->jh_journal,
+ advise_journal_max_trans_len(transaction_max_size, len - 1, fs->fs_blocksize));
+ set_jp_journal_max_batch (&jh->jh_journal,
+ advise_journal_max_batch (get_jp_journal_max_trans_len (&jh->jh_journal) ));
+ set_jp_journal_max_commit_age (&jh->jh_journal, advise_journal_max_commit_age ());
+ set_jp_journal_max_trans_age (&jh->jh_journal, advise_journal_max_trans_age ());
+
+ mark_buffer_uptodate (bh, 1);
+ mark_buffer_dirty (bh);
+
+ fs->fs_jh_bh = bh;
+
+ /* make a copy of journal header in the super block */
+ memcpy (sb_jp (sb), &jh->jh_journal, sizeof (struct journal_params));
+
+ mark_buffer_dirty (fs->fs_super_bh);
+
+ return 1;
+}
+
+
+/* brelse journal header, flush all dirty buffers, close device, open, read
+ journal header */
+void reiserfs_reopen_journal (reiserfs_filsys_t * fs, int flag)
+{
+ unsigned long jh_block;
+
+
+ if (!reiserfs_journal_opened (fs))
+ return;
+
+ jh_block = fs->fs_jh_bh->b_blocknr;
+ brelse (fs->fs_jh_bh);
+ flush_buffers (fs->fs_journal_dev);
+ invalidate_buffers (fs->fs_journal_dev);
+ if (close (fs->fs_journal_dev))
+ die ("reiserfs_reopen_journal: closed failed: %m");
+
+ fs->fs_journal_dev = open (fs->fs_j_file_name, flag | O_LARGEFILE);
+ if (fs->fs_journal_dev == -1)
+ die ("reiserfs_reopen_journal: could not reopen journal device");
+
+ fs->fs_jh_bh = bread (fs->fs_journal_dev, jh_block, fs->fs_blocksize);
+ if (!fs->fs_jh_bh)
+ die ("reiserfs_reopen_journal: reading journal header failed");
+}
+
+
+int reiserfs_journal_opened (reiserfs_filsys_t * fs)
+{
+ return fs->fs_jh_bh ? 1 : 0;
+}
+
+
+void reiserfs_flush_journal (reiserfs_filsys_t * fs)
+{
+ if (!reiserfs_journal_opened (fs))
+ return;
+ flush_buffers (fs->fs_journal_dev);
+}
+
+
+void reiserfs_free_journal (reiserfs_filsys_t * fs)
+{
+ if (!reiserfs_journal_opened (fs))
+ return;
+ brelse (fs->fs_jh_bh);
+ fs->fs_jh_bh = 0;
+ free (fs->fs_j_file_name);
+ fs->fs_j_file_name = 0;
+}
+
+
+void reiserfs_close_journal (reiserfs_filsys_t * fs)
+{
+ reiserfs_flush_journal (fs);
+ reiserfs_free_journal (fs);
+
+}
+
+/* update journal header */
+static void update_journal_header (struct buffer_head * bh_jh, reiserfs_trans_t trans) {
+ struct reiserfs_journal_header * j_head;
+
+ j_head = (struct reiserfs_journal_header *)(bh_jh->b_data);
+
+ /* update journal header */
+ set_jh_last_flushed (j_head, trans.trans_id);
+ set_jh_mount_id (j_head, trans.mount_id);
+ set_jh_replay_start_offset (j_head, trans.next_trans_offset);
+ mark_buffer_dirty (bh_jh);
+ bwrite (bh_jh);
+}
+
+/* fixme: what should be done when not all transactions can be replayed in proper order? */
+int replay_journal (reiserfs_filsys_t * fs)
+{
+ struct buffer_head * bh;
+ struct reiserfs_journal_header * j_head;
+ reiserfs_trans_t cur, newest, control;
+ int replayed, ret = 0;
+
+ if (!reiserfs_journal_opened (fs))
+ reiserfs_panic ("replay_journal: journal is not opened");
+
+ if (!is_opened_rw (fs))
+ reiserfs_panic ("replay_journal: fs is not opened with write perms");
+
+ reiserfs_warning (stderr, "Replaying journal..\n");
+ bh = fs->fs_jh_bh;
+
+ j_head = (struct reiserfs_journal_header *)(bh->b_data);
+ control.mount_id = get_jh_mount_id (j_head);
+ control.trans_id = get_jh_last_flushed (j_head);
+ control.desc_blocknr = get_jh_replay_start_offset (j_head);
+
+ if (!get_boundary_transactions (fs, &cur, &newest)) {
+ reiserfs_warning (stderr, "No transactions found\n");
+ return 0;
+ }
+
+ if (control.mount_id != newest.mount_id) {
+ reiserfs_warning (stderr, "Journal header's mountid: %lu\n"
+ "latest transaction found is of mountid %lu\n", control.mount_id, newest.mount_id);
+ if (user_confirmed (stderr, "Should those transactions be replayed?(Y/n)[n]", "Y\n")) {
+ control.mount_id = newest.mount_id;
+// control.trans_id = 0;
+ }
+ }
+
+ replayed = 0;
+ while (1) {
+ if (cur.mount_id == control.mount_id && cur.trans_id > control.trans_id) {
+ reiserfs_warning (stderr, "trans replayed: mountid %lu, transid %lu, desc %lu, "
+ "len %lu, commit %lu, next trans offset %lu\n",
+ cur.mount_id, cur.trans_id, cur.desc_blocknr, cur.trans_len,
+ cur.commit_blocknr, cur.next_trans_offset);
+ replay_one_transaction (fs, &cur);
+ update_journal_header (bh, cur);
+ replayed ++;
+ }
+ if ((ret == TRANS_LAST) || ((ret = next_transaction (fs, &cur, newest)) == TRANS_NOT_FOUND) )
+ break;
+ }
+ reiserfs_warning (stderr, "%d transactions replayed\n", replayed);
+
+ mark_buffer_dirty (fs->fs_super_bh);
+ bwrite (fs->fs_super_bh);
+
+ update_journal_header (bh, newest);
+
+ return 0;
+}
diff --git a/reiserfscore/lbalance.c b/reiserfscore/lbalance.c
index c5036fc..2800e78 100644
--- a/reiserfscore/lbalance.c
+++ b/reiserfscore/lbalance.c
@@ -26,7 +26,7 @@ extern int init_mode;
/* copy copy_count entries from source directory item to dest buffer (creating new item if needed) */
-static void leaf_copy_dir_entries (reiserfs_filsys_t fs,
+static void leaf_copy_dir_entries (reiserfs_filsys_t * fs,
struct buffer_info * dest_bi, struct buffer_head * source,
int last_first, int item_num, int from, int copy_count)
{
@@ -42,17 +42,12 @@ static void leaf_copy_dir_entries (reiserfs_filsys_t fs,
ih = B_N_PITEM_HEAD (source, item_num);
-#ifdef CONFIG_REISERFS_CHECK
- if (!I_IS_DIRECTORY_ITEM (ih))
- reiserfs_panic(0, "vs-10000: leaf_copy_dir_entries: item must be directory item");
-#endif
-
/* length of all record to be copied and first byte of the last of them */
deh = B_I_DEH (source, ih);
if (copy_count) {
- copy_records_len = (from ? deh[from - 1].deh_location : ih->ih_item_len) -
- deh[from + copy_count - 1].deh_location;
- records = source->b_data + ih->ih_item_location + deh[from + copy_count - 1].deh_location;
+ copy_records_len = (from ? get_deh_location (&deh[from - 1]) : get_ih_item_len (ih)) -
+ get_deh_location (&deh[from + copy_count - 1]);
+ records = source->b_data + get_ih_location (ih) + get_deh_location (&deh[from + copy_count - 1]);
} else {
copy_records_len = 0;
records = 0;
@@ -63,13 +58,8 @@ static void leaf_copy_dir_entries (reiserfs_filsys_t fs,
/* if there are no items in dest or the first/last item in dest is not item of the same directory */
if ( (item_num_in_dest == - 1) ||
-#ifndef FU //REISERFS_FSCK
(last_first == FIRST_TO_LAST && are_items_mergeable (B_N_PITEM_HEAD (dest, item_num_in_dest), ih, dest->b_size) == 0) ||
(last_first == LAST_TO_FIRST && are_items_mergeable (ih, B_N_PITEM_HEAD (dest, item_num_in_dest), dest->b_size) == 0)) {
-#else
- (last_first == FIRST_TO_LAST && get_offset (&ih->ih_key) == DOT_OFFSET) ||
- (last_first == LAST_TO_FIRST && not_of_one_file (&ih->ih_key, B_N_PKEY (dest, item_num_in_dest)))) {
-#endif
/* create new item in dest */
struct item_head new_ih;
@@ -77,37 +67,34 @@ static void leaf_copy_dir_entries (reiserfs_filsys_t fs,
memcpy (&new_ih.ih_key, &ih->ih_key, KEY_SIZE);
/* calculate item len */
- new_ih.ih_item_len = cpu_to_le16 (DEH_SIZE * copy_count + copy_records_len);
- set_entry_count (&new_ih, 0);
+ set_ih_item_len (&new_ih, DEH_SIZE * copy_count + copy_records_len);
+ set_ih_entry_count (&new_ih, 0);
if (last_first == LAST_TO_FIRST) {
/* form key by the following way */
- if (from < ih_entry_count (ih)) {
- new_ih.ih_key.u.k_offset_v1.k_offset = deh[from].deh_offset;
- new_ih.ih_key.u.k_offset_v1.k_uniqueness = DIRENTRY_UNIQUENESS;
- /*memcpy (&new_ih.ih_key.k_offset, &deh[from].deh_offset, SHORT_KEY_SIZE);*/
+ if (from < get_ih_entry_count (ih)) {
+ set_key_offset_v1 (&new_ih.ih_key, get_deh_offset (&deh[from]));
} else {
/* no entries will be copied to this item in this function */
- new_ih.ih_key.u.k_offset_v1.k_offset = MAX_KEY1_OFFSET;
- /* this item is not yet valid, but we want I_IS_DIRECTORY_ITEM to return 1 for it, so we -1 */
- new_ih.ih_key.u.k_offset_v1.k_uniqueness = DIRENTRY_UNIQUENESS/*TYPE_DIRECTORY_MAX*/;
+ set_key_offset_v1 (&new_ih.ih_key, MAX_KEY1_OFFSET);
}
+ set_key_uniqueness (&new_ih.ih_key, DIRENTRY_UNIQUENESS);
}
- set_key_format (&new_ih, ih_key_format (ih));
- new_ih.ih_format.fsck_need = ih->ih_format.fsck_need;
+ set_ih_key_format (&new_ih, get_ih_key_format (ih));
+ set_ih_flags (&new_ih, get_ih_flags (ih));
/* insert item into dest buffer */
leaf_insert_into_buf (fs, dest_bi, (last_first == LAST_TO_FIRST) ? 0 : B_NR_ITEMS(dest), &new_ih, NULL, 0);
} else {
/* prepare space for entries */
- leaf_paste_in_buffer (fs, dest_bi, (last_first==FIRST_TO_LAST) ? (B_NR_ITEMS(dest) - 1) : 0, USHRT_MAX,
+ leaf_paste_in_buffer (fs, dest_bi, (last_first == FIRST_TO_LAST) ? (B_NR_ITEMS(dest) - 1) : 0, 0xffff /*MAX_US_INT */,
DEH_SIZE * copy_count + copy_records_len, records, 0);
}
item_num_in_dest = (last_first == FIRST_TO_LAST) ? (B_NR_ITEMS(dest)-1) : 0;
leaf_paste_entries (dest_bi->bi_bh, item_num_in_dest,
- (last_first == FIRST_TO_LAST) ? ih_entry_count (B_N_PITEM_HEAD (dest, item_num_in_dest)) : 0,
+ (last_first == FIRST_TO_LAST) ? get_ih_entry_count (B_N_PITEM_HEAD (dest, item_num_in_dest)) : 0,
copy_count, deh + from, records,
DEH_SIZE * copy_count + copy_records_len
);
@@ -118,7 +105,7 @@ static void leaf_copy_dir_entries (reiserfs_filsys_t fs,
part of it or nothing (see the return 0 below) from SOURCE to the end
(if last_first) or beginning (!last_first) of the DEST */
/* returns 1 if anything was copied, else 0 */
-static int leaf_copy_boundary_item (reiserfs_filsys_t fs,
+static int leaf_copy_boundary_item (reiserfs_filsys_t * fs,
struct buffer_info * dest_bi, struct buffer_head * src, int last_first,
int bytes_or_entries)
{
@@ -135,23 +122,14 @@ static int leaf_copy_boundary_item (reiserfs_filsys_t fs,
that we copy, so we return */
ih = B_N_PITEM_HEAD (src, 0);
dih = B_N_PITEM_HEAD (dest, dest_nr_item - 1);
-#ifndef FU //REISERFS_FSCK
if (!dest_nr_item || (are_items_mergeable (dih, ih, src->b_size) == 0))
-#else
- if (!dest_nr_item || (!is_left_mergeable (ih, src->b_size)))
-#endif
- /* there is nothing to merge */
- return 0;
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( ! ih->ih_item_len )
- reiserfs_panic (0, "vs-10010: leaf_copy_boundary_item: item can not have empty dynamic length");
-#endif
+ /* there is nothing to merge */
+ return 0;
if ( I_IS_DIRECTORY_ITEM(ih) ) {
if ( bytes_or_entries == -1 )
/* copy all entries to dest */
- bytes_or_entries = ih_entry_count(ih);
+ bytes_or_entries = get_ih_entry_count(ih);
leaf_copy_dir_entries (fs, dest_bi, src, FIRST_TO_LAST, 0, 0, bytes_or_entries);
return 1;
}
@@ -160,34 +138,17 @@ static int leaf_copy_boundary_item (reiserfs_filsys_t fs,
part defined by 'bytes_or_entries'; if bytes_or_entries == -1 copy whole body; don't create new item header
*/
if ( bytes_or_entries == -1 )
- bytes_or_entries = ih->ih_item_len;
+ bytes_or_entries = get_ih_item_len (ih);
-#ifdef CONFIG_REISERFS_CHECK
- else {
- if (bytes_or_entries == ih->ih_item_len && I_IS_INDIRECT_ITEM(ih))
- if (ih_free_space (ih))
- reiserfs_panic (0, "vs-10020: leaf_copy_boundary_item: "
- "last unformatted node must be filled entirely (free_space=%d)",
- ih_free_space (ih));
- }
-#endif
-
/* merge first item (or its part) of src buffer with the last
item of dest buffer. Both are of the same file */
- leaf_paste_in_buffer (fs, dest_bi,
- dest_nr_item - 1, dih->ih_item_len, bytes_or_entries, B_I_PITEM(src,ih), 0
- );
+ leaf_paste_in_buffer (fs, dest_bi, dest_nr_item - 1, get_ih_item_len (dih),
+ bytes_or_entries, B_I_PITEM(src,ih), 0);
if (I_IS_INDIRECT_ITEM(dih)) {
-#ifdef CONFIG_REISERFS_CHECK
- if (ih_free_space (dih))
- reiserfs_panic (0, "vs-10030: leaf_copy_boundary_item: "
- "merge to left: last unformatted node of non-last indirect item must be filled entirely (free_space=%d)",
- ih_free_space (dih));
-#endif
- if (bytes_or_entries == ih->ih_item_len)
+ if (bytes_or_entries == get_ih_item_len (ih))
//dih->u.ih_free_space = ih->u.ih_free_space;
- set_free_space (dih, ih_free_space (ih));
+ set_ih_free_space (dih, get_ih_free_space (ih));
}
return 1;
@@ -203,19 +164,15 @@ static int leaf_copy_boundary_item (reiserfs_filsys_t fs,
ih = B_N_PITEM_HEAD (src, src_nr_item - 1);
dih = B_N_PITEM_HEAD (dest, 0);
-#ifndef FU //REISERFS_FSCK
if (!dest_nr_item || are_items_mergeable (ih, dih, src->b_size) == 0)
-#else
- if (!dest_nr_item || !is_left_mergeable (dih, src->b_size))
-#endif
- return 0;
+ return 0;
if ( I_IS_DIRECTORY_ITEM(ih)) {
if ( bytes_or_entries == -1 )
/* bytes_or_entries = entries number in last item body of SOURCE */
- bytes_or_entries = ih_entry_count(ih);
+ bytes_or_entries = get_ih_entry_count(ih);
- leaf_copy_dir_entries (fs, dest_bi, src, LAST_TO_FIRST, src_nr_item - 1, ih_entry_count(ih) - bytes_or_entries,
+ leaf_copy_dir_entries (fs, dest_bi, src, LAST_TO_FIRST, src_nr_item - 1, get_ih_entry_count(ih) - bytes_or_entries,
bytes_or_entries);
return 1;
}
@@ -225,22 +182,9 @@ static int leaf_copy_boundary_item (reiserfs_filsys_t fs,
don't create new item header
*/
-#ifdef CONFIG_REISERFS_CHECK
- if (I_IS_INDIRECT_ITEM(ih) && ih_free_space (ih))
- reiserfs_panic (0, "vs-10040: leaf_copy_boundary_item: "
- "merge to right: last unformatted node of non-last indirect item must be filled entirely (free_space=%d)",
- ih_free_space (ih));
-#endif
-
if ( bytes_or_entries == -1 ) {
/* bytes_or_entries = length of last item body of SOURCE */
- bytes_or_entries = ih->ih_item_len;
-
-#ifdef CONFIG_REISERFS_CHECK
- if (get_offset (&dih->ih_key) != get_offset (&ih->ih_key) + get_bytes_number (ih, src->b_size))/*I_DNM_DATA_LEN(ih))*/
- reiserfs_panic (0, "vs-10050: leaf_copy_boundary_item: right item offset (%lu) must not be (%lu),it must be %lu",
- get_offset (&dih->ih_key), get_offset (&ih->ih_key) + get_bytes_number (ih, src->b_size), get_offset (&dih->ih_key));
-#endif
+ bytes_or_entries = get_ih_item_len (ih);
/* change first item key of the DEST */
//dih->ih_key.k_offset = ih->ih_key.k_offset;
@@ -252,34 +196,18 @@ static int leaf_copy_boundary_item (reiserfs_filsys_t fs,
set_type (key_format (&dih->ih_key), &dih->ih_key, get_type (&ih->ih_key));
} else {
/* merge to right only part of item */
-#ifdef CONFIG_REISERFS_CHECK
- if ( ih->ih_item_len <= bytes_or_entries )
- reiserfs_panic (0, "vs-10060: leaf_copy_boundary_item: no so much bytes %lu (needed %lu)",
- ih->ih_item_len, bytes_or_entries);
-#endif
-
/* change first item key of the DEST */
if ( I_IS_DIRECT_ITEM(dih) ) {
-#ifdef CONFIG_REISERFS_CHECK
- if (get_offset (&dih->ih_key) <= (unsigned long)bytes_or_entries)
- reiserfs_panic (0, "vs-10070: leaf_copy_boundary_item: dih->ih_key.k_offset(%d) <= bytes_or_entries(%d)",
- get_offset (&dih->ih_key), bytes_or_entries);
-#endif
//dih->ih_key.k_offset -= bytes_or_entries;
set_offset (key_format (&dih->ih_key), &dih->ih_key, get_offset (&dih->ih_key) - bytes_or_entries);
} else {
-#ifdef CONFIG_REISERFS_CHECK
- if (get_offset (&dih->ih_key) <=(bytes_or_entries/UNFM_P_SIZE)*dest->b_size )
- reiserfs_panic (0, "vs-10080: leaf_copy_boundary_item: dih->ih_key.k_offset(%d) <= bytes_or_entries(%d)",
- get_offset (&dih->ih_key), (bytes_or_entries/UNFM_P_SIZE)*dest->b_size);
-#endif
//dih->ih_key.k_offset -= ((bytes_or_entries/UNFM_P_SIZE)*dest->b_size);
set_offset (key_format (&dih->ih_key), &dih->ih_key,
get_offset (&dih->ih_key) - ((bytes_or_entries/UNFM_P_SIZE)*dest->b_size));
}
}
- leaf_paste_in_buffer (fs, dest_bi, 0, 0, bytes_or_entries, B_I_PITEM(src,ih) + ih->ih_item_len - bytes_or_entries, 0);
+ leaf_paste_in_buffer (fs, dest_bi, 0, 0, bytes_or_entries, B_I_PITEM(src,ih) + get_ih_item_len (ih) - bytes_or_entries, 0);
return 1;
}
@@ -288,7 +216,7 @@ static int leaf_copy_boundary_item (reiserfs_filsys_t fs,
* last_first == FIRST_TO_LAST means, that we copy cpy_num items beginning from first-th item in src to tail of dest
* last_first == LAST_TO_FIRST means, that we copy cpy_num items beginning from first-th item in src to head of dest
*/
-static void leaf_copy_items_entirely (reiserfs_filsys_t fs, struct buffer_info * dest_bi,
+static void leaf_copy_items_entirely (reiserfs_filsys_t * fs, struct buffer_info * dest_bi,
struct buffer_head * src, int last_first,
int first, int cpy_num)
{
@@ -300,33 +228,13 @@ static void leaf_copy_items_entirely (reiserfs_filsys_t fs, struct buffer_info *
struct block_head * blkh;
struct item_head * ih;
-
-#ifdef CONFIG_REISERFS_CHECK
- if (last_first != LAST_TO_FIRST && last_first != FIRST_TO_LAST)
- reiserfs_panic (0, "vs-10090: leaf_copy_items_entirely: bad last_first parameter %d", last_first);
-
- if (B_NR_ITEMS (src) - first < cpy_num)
- reiserfs_panic (0, "vs-10100: leaf_copy_items_entirely: too few items in source %d, required %d from %d",
- B_NR_ITEMS(src), cpy_num, first);
-
- if (cpy_num < 0)
- reiserfs_panic (0, "vs-10110: leaf_copy_items_entirely: can not copy negative amount of items");
-
- if ( ! dest_bi )
- reiserfs_panic (0, "vs-10120: leaf_copy_items_entirely: can not copy negative amount of items");
-#endif
-
dest = dest_bi->bi_bh;
-#ifdef CONFIG_REISERFS_CHECK
- if ( ! dest )
- reiserfs_panic (0, "vs-10130: leaf_copy_items_entirely: can not copy negative amount of items");
-#endif
-
if (cpy_num == 0)
return;
- nr = (blkh = B_BLK_HEAD(dest))->blk_nr_item;
+ blkh = B_BLK_HEAD(dest);
+ nr = get_blkh_nr_items (blkh);
/* we will insert items before 0-th or nr-th item in dest buffer. It depends of last_first parameter */
dest_before = (last_first == LAST_TO_FIRST) ? 0 : nr;
@@ -334,39 +242,26 @@ static void leaf_copy_items_entirely (reiserfs_filsys_t fs, struct buffer_info *
/* location of head of first new item */
ih = B_N_PITEM_HEAD (dest, dest_before);
-#ifdef CONFIG_REISERFS_CHECK
- if (blkh->blk_free_space < cpy_num * IH_SIZE) {
- reiserfs_panic (0, "vs-10140: leaf_copy_items_entirely: not enough free space for headers %d (needed %d)",
- blkh->blk_free_space, cpy_num * IH_SIZE);
- }
-#endif
-
/* prepare space for headers */
memmove (ih + cpy_num, ih, (nr-dest_before) * IH_SIZE);
/* copy item headers */
memcpy (ih, B_N_PITEM_HEAD (src, first), cpy_num * IH_SIZE);
- blkh->blk_free_space -= IH_SIZE * cpy_num;
+ set_blkh_free_space (blkh, get_blkh_free_space (blkh) - IH_SIZE * cpy_num);
/* location of unmovable item */
- j = location = (dest_before == 0) ? dest->b_size : (ih-1)->ih_item_location;
- for (i = dest_before; i < nr + cpy_num; i ++)
- ih[i-dest_before].ih_item_location =
- (location -= ih[i-dest_before].ih_item_len);
+ j = location = (dest_before == 0) ? dest->b_size : get_ih_location (ih-1);
+ for (i = dest_before; i < nr + cpy_num; i ++) {
+ location -= get_ih_item_len (&ih[i-dest_before]);
+ set_ih_location (&ih[i-dest_before], location);
+ }
/* prepare space for items */
- last_loc = ih[nr+cpy_num-1-dest_before].ih_item_location;
- last_inserted_loc = ih[cpy_num-1].ih_item_location;
+ last_loc = get_ih_location (&ih[nr+cpy_num-1-dest_before]);
+ last_inserted_loc = get_ih_location (&ih[cpy_num-1]);
/* check free space */
-#ifdef CONFIG_REISERFS_CHECK
- if (blkh->blk_free_space < j - last_inserted_loc) {
- reiserfs_panic (0, "vs-10150: leaf_copy_items_entirely: not enough free space for items %d (needed %d)",
- blkh->blk_free_space, j - last_inserted_loc);
- }
-#endif
-
memmove (dest->b_data + last_loc,
dest->b_data + last_loc + j - last_inserted_loc,
last_inserted_loc - last_loc);
@@ -376,22 +271,16 @@ static void leaf_copy_items_entirely (reiserfs_filsys_t fs, struct buffer_info *
j - last_inserted_loc);
/* sizes, item number */
- blkh->blk_nr_item += cpy_num;
- blkh->blk_free_space -= j - last_inserted_loc;
+ set_blkh_nr_items (blkh, get_blkh_nr_items (blkh) + cpy_num);
+ set_blkh_free_space (blkh,
+ get_blkh_free_space (blkh) - (j - last_inserted_loc));
mark_buffer_dirty (dest);
if (dest_bi->bi_parent) {
-#ifdef CONFIG_REISERFS_CHECK
- if (B_N_CHILD (dest_bi->bi_parent, dest_bi->bi_position)->dc_block_number != dest->b_blocknr) {
- reiserfs_panic (0, "vs-10160: leaf_copy_items_entirely: "
- "block number in bh does not match to field in disk_child structure %lu and %lu",
- dest->b_blocknr, B_N_CHILD (dest_bi->bi_parent, dest_bi->bi_position)->dc_block_number);
- }
-#endif
- B_N_CHILD (dest_bi->bi_parent, dest_bi->bi_position)->dc_size +=
- j - last_inserted_loc + IH_SIZE * cpy_num;
-
+ struct disk_child * dc;
+ dc = B_N_CHILD (dest_bi->bi_parent, dest_bi->bi_position);
+ set_dc_child_size (dc, get_dc_child_size (dc) + j - last_inserted_loc + IH_SIZE * cpy_num);
mark_buffer_dirty(dest_bi->bi_parent);
}
}
@@ -399,18 +288,13 @@ static void leaf_copy_items_entirely (reiserfs_filsys_t fs, struct buffer_info *
/* This function splits the (liquid) item into two items (useful when
shifting part of an item into another node.) */
-static void leaf_item_bottle (reiserfs_filsys_t fs,
+static void leaf_item_bottle (reiserfs_filsys_t * fs,
struct buffer_info * dest_bi, struct buffer_head * src, int last_first,
int item_num, int cpy_bytes)
{
struct buffer_head * dest = dest_bi->bi_bh;
struct item_head * ih;
-#ifdef CONFIG_REISERFS_CHECK
- if ( cpy_bytes == -1 )
- reiserfs_panic (0, "vs-10170: leaf_item_bottle: bytes == - 1 means: do not split item");
-#endif
-
if ( last_first == FIRST_TO_LAST ) {
/* if ( if item in position item_num in buffer SOURCE is directory item ) */
if (I_IS_DIRECTORY_ITEM(ih = B_N_PITEM_HEAD(src,item_num)))
@@ -423,31 +307,21 @@ static void leaf_item_bottle (reiserfs_filsys_t fs,
n_ih = new item_header;
*/
memcpy (&n_ih, ih, IH_SIZE);
- n_ih.ih_item_len = cpy_bytes;
+ set_ih_item_len (&n_ih, cpy_bytes);
if (I_IS_INDIRECT_ITEM(ih)) {
-#ifdef CONFIG_REISERFS_CHECK
- if (cpy_bytes == ih->ih_item_len && ih_free_space (ih))
- reiserfs_panic (0, "vs-10180: leaf_item_bottle: "
- "when whole indirect item is bottle to left neighbor, it must have free_space==0 (not %lu)",
- ih_free_space (ih));
-#endif
//n_ih.u.ih_free_space = 0;
- set_free_space (&n_ih, 0);;
+ set_ih_free_space (&n_ih, 0);;
}
-#ifdef CONFIG_REISERFS_CHECK
- if (is_left_mergeable (ih, src->b_size))
- reiserfs_panic (0, "vs-10190: leaf_item_bottle: item %h should not be mergeable", ih);
-#endif
//n_ih.ih_version = ih->ih_version;
- set_key_format (&n_ih, ih_key_format (ih));
- n_ih.ih_format.fsck_need = ih->ih_format.fsck_need;
+ set_ih_key_format (&n_ih, get_ih_key_format (ih));
+ set_ih_flags (&n_ih, get_ih_flags (ih));
leaf_insert_into_buf (fs, dest_bi, B_NR_ITEMS(dest), &n_ih, B_N_PITEM (src, item_num), 0);
}
} else {
/* if ( if item in position item_num in buffer SOURCE is directory item ) */
if (I_IS_DIRECTORY_ITEM(ih = B_N_PITEM_HEAD (src, item_num)))
- leaf_copy_dir_entries (fs, dest_bi, src, LAST_TO_FIRST, item_num, ih_entry_count(ih) - cpy_bytes, cpy_bytes);
+ leaf_copy_dir_entries (fs, dest_bi, src, LAST_TO_FIRST, item_num, get_ih_entry_count(ih) - cpy_bytes, cpy_bytes);
else {
struct item_head n_ih;
@@ -459,32 +333,28 @@ static void leaf_item_bottle (reiserfs_filsys_t fs,
if (I_IS_DIRECT_ITEM(ih)) {
//n_ih.ih_key.k_offset = ih->ih_key.k_offset + ih->ih_item_len - cpy_bytes;
- set_offset (key_format (&ih->ih_key), &n_ih.ih_key, get_offset (&ih->ih_key) + ih->ih_item_len - cpy_bytes);
+ set_offset (key_format (&ih->ih_key), &n_ih.ih_key, get_offset (&ih->ih_key) + get_ih_item_len (ih) - cpy_bytes);
//n_ih.ih_key.k_uniqueness = TYPE_DIRECT;
set_type (key_format (&ih->ih_key), &n_ih.ih_key, TYPE_DIRECT);
//n_ih.u.ih_free_space = USHRT_MAX;
- set_free_space (&n_ih, USHRT_MAX);
+ set_ih_free_space (&n_ih, USHRT_MAX);
} else {
/* indirect item */
-#ifdef CONFIG_REISERFS_CHECK
- if (!cpy_bytes && ih_free_space (ih))
- reiserfs_panic (0, "vs-10200: leaf_item_bottle: ih->ih_free_space must be 0 when indirect item will be appended");
-#endif
//n_ih.ih_key.k_offset = ih->ih_key.k_offset + (ih->ih_item_len - cpy_bytes) / UNFM_P_SIZE * dest->b_size;
set_offset (key_format (&ih->ih_key), &n_ih.ih_key,
- get_offset (&ih->ih_key) + (ih->ih_item_len - cpy_bytes) / UNFM_P_SIZE * dest->b_size);
+ get_offset (&ih->ih_key) + (get_ih_item_len (ih) - cpy_bytes) / UNFM_P_SIZE * dest->b_size);
//n_ih.ih_key.k_uniqueness = TYPE_INDIRECT;
set_type (key_format (&ih->ih_key), &n_ih.ih_key, TYPE_INDIRECT);
//n_ih.u.ih_free_space = ih->u.ih_free_space;
- set_free_space (&n_ih, ih_free_space (ih));
+ set_ih_free_space (&n_ih, get_ih_free_space (ih));
}
/* set item length */
- n_ih.ih_item_len = cpu_to_le16 (cpy_bytes);
+ set_ih_item_len (&n_ih, cpy_bytes);
//n_ih.ih_version = ih->ih_version;
- set_key_format (&n_ih, ih_key_format (ih));
- n_ih.ih_format.fsck_need = ih->ih_format.fsck_need;
- leaf_insert_into_buf (fs, dest_bi, 0, &n_ih, B_N_PITEM(src,item_num) + ih->ih_item_len - cpy_bytes, 0);
+ set_ih_key_format (&n_ih, get_ih_key_format (ih));
+ set_ih_flags (&n_ih, get_ih_flags (ih));
+ leaf_insert_into_buf (fs, dest_bi, 0, &n_ih, B_N_PITEM(src,item_num) + get_ih_item_len (ih) - cpy_bytes, 0);
}
}
}
@@ -494,7 +364,7 @@ static void leaf_item_bottle (reiserfs_filsys_t fs,
If cpy_bytes not equal to minus one than copy cpy_num-1 whole items from SOURCE to DEST.
From last item copy cpy_num bytes for regular item and cpy_num directory entries for
directory item. */
-static int leaf_copy_items (reiserfs_filsys_t fs,
+static int leaf_copy_items (reiserfs_filsys_t * fs,
struct buffer_info * dest_bi, struct buffer_head * src,
int last_first, int cpy_num,
int cpy_bytes)
@@ -503,20 +373,6 @@ static int leaf_copy_items (reiserfs_filsys_t fs,
int pos, i, src_nr_item, bytes;
dest = dest_bi->bi_bh;
-#ifdef CONFIG_REISERFS_CHECK
- if (!dest || !src)
- reiserfs_panic (0, "vs-10210: leaf_copy_items: !dest || !src");
-
- if ( last_first != FIRST_TO_LAST && last_first != LAST_TO_FIRST )
- reiserfs_panic (0, "vs-10220: leaf_copy_items: last_first != FIRST_TO_LAST && last_first != LAST_TO_FIRST");
-
- if ( B_NR_ITEMS(src) < cpy_num )
- reiserfs_panic (0, "vs-10230: leaf_copy_items: No enough items: %d, required %d", B_NR_ITEMS(src), cpy_num);
-
- if ( cpy_num < 0 )
- reiserfs_panic (0, "vs-10240: leaf_copy_items: cpy_num < 0 (%d)", cpy_num);
-#endif
-
if ( cpy_num == 0 )
return 0;
@@ -582,11 +438,6 @@ static void leaf_define_dest_src_infos (int shift_mode, struct tree_balance * tb
struct buffer_info * src_bi, int * first_last,
struct buffer_head * Snew)
{
-#ifdef CONFIG_REISERFS_CHECK
- memset (dest_bi, 0, sizeof (struct buffer_info));
- memset (src_bi, 0, sizeof (struct buffer_info));
-#endif
-
/* define dest, src, dest parent, dest position */
switch (shift_mode) {
case LEAF_FROM_S_TO_L: /* it is used in leaf_shift_left */
@@ -642,12 +493,6 @@ static void leaf_define_dest_src_infos (int shift_mode, struct tree_balance * tb
default:
reiserfs_panic (0, "vs-10250: leaf_define_dest_src_infos: shift type is unknown (%d)", shift_mode);
}
-#ifdef CONFIG_REISERFS_CHECK
- if (src_bi->bi_bh == 0 || dest_bi->bi_bh == 0) {
- reiserfs_panic (0, "vs-10260: leaf_define_dest_src_etc: mode==%d, source (%p) or dest (%p) buffer is initialized incorrectly",
- shift_mode, src_bi->bi_bh, dest_bi->bi_bh);
- }
-#endif
}
@@ -664,9 +509,9 @@ int leaf_move_items (int shift_mode, struct tree_balance * tb,
leaf_define_dest_src_infos (shift_mode, tb, &dest_bi, &src_bi, &first_last, Snew);
- ret_value = leaf_copy_items (tb->tb_sb, &dest_bi, src_bi.bi_bh, first_last, mov_num, mov_bytes);
+ ret_value = leaf_copy_items (tb->tb_fs, &dest_bi, src_bi.bi_bh, first_last, mov_num, mov_bytes);
- leaf_delete_items (tb->tb_sb, &src_bi, first_last, (first_last == FIRST_TO_LAST) ? 0 :
+ leaf_delete_items (tb->tb_fs, &src_bi, first_last, (first_last == FIRST_TO_LAST) ? 0 :
(B_NR_ITEMS(src_bi.bi_bh) - mov_num), mov_num, mov_bytes);
@@ -687,32 +532,12 @@ int leaf_shift_left (struct tree_balance * tb, int shift_num, int shift_bytes)
if ( shift_num ) {
if (B_NR_ITEMS (S0) == 0) {
/* everything is moved from S[0] */
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( shift_bytes != -1 )
- reiserfs_panic (tb->tb_sb, "vs-10270: leaf_shift_left: S0 is empty now, but shift_bytes != -1 (%d)", shift_bytes);
-
- if (init_mode == M_PASTE || init_mode == M_INSERT) {
- print_tb (init_mode, init_item_pos, init_pos_in_item, &init_tb, "vs-10275");
- reiserfs_panic (tb->tb_sb, "vs-10275: leaf_shift_left: balance condition corrupted (%c)", init_mode);
- }
-#endif
-
if (PATH_H_POSITION (tb->tb_path, 1) == 0)
- replace_key(tb->tb_sb, tb->CFL[0], tb->lkey[0], PATH_H_PPARENT (tb->tb_path, 0), 0);
-
- } else {
+ replace_key(tb->tb_fs, tb->CFL[0], tb->lkey[0], PATH_H_PPARENT (tb->tb_path, 0), 0);
+ } else {
/* replace lkey in CFL[0] by 0-th key from S[0]; */
- replace_key(tb->tb_sb, tb->CFL[0], tb->lkey[0], S0, 0);
+ replace_key(tb->tb_fs, tb->CFL[0], tb->lkey[0], S0, 0);
-#ifdef CONFIG_REISERFS_CHECK
- if (shift_bytes != -1 && !(I_IS_DIRECTORY_ITEM (B_N_PITEM_HEAD (S0, 0))
- && !ih_entry_count (B_N_PITEM_HEAD (S0, 0)))) {
- if (!is_left_mergeable (B_N_PITEM_HEAD (S0, 0), S0->b_size)) {
- reiserfs_panic (tb->tb_sb, "vs-10280: leaf_shift_left: item must be mergeable");
- }
- }
-#endif
}
}
@@ -738,7 +563,7 @@ int leaf_shift_right (struct tree_balance * tb, int shift_num, int shift_bytes)
/* replace rkey in CFR[0] by the 0-th key from R[0] */
if (shift_num) {
- replace_key(tb->tb_sb, tb->CFR[0], tb->rkey[0], tb->R[0], 0);
+ replace_key(tb->tb_fs, tb->CFR[0], tb->rkey[0], tb->R[0], 0);
}
return ret_value;
@@ -746,7 +571,7 @@ int leaf_shift_right (struct tree_balance * tb, int shift_num, int shift_bytes)
-static void leaf_delete_items_entirely (struct super_block * sb,
+static void leaf_delete_items_entirely (reiserfs_filsys_t * sb,
/*struct reiserfs_transaction_handle *th,*/
struct buffer_info * bi,
int first,
@@ -758,7 +583,7 @@ static void leaf_delete_items_entirely (struct super_block * sb,
If last_first == 1. Starting from position 'first+1' delete del_num-1 items in whole. Delete part of body of
the last item . Part defined by del_bytes. Don't delete last item header.
*/
-void leaf_delete_items (reiserfs_filsys_t fs,
+void leaf_delete_items (reiserfs_filsys_t * fs,
struct buffer_info * cur_bi,
int last_first,
int first, int del_num, int del_bytes)
@@ -766,18 +591,6 @@ void leaf_delete_items (reiserfs_filsys_t fs,
struct buffer_head * bh;
int item_amount = B_NR_ITEMS (bh = cur_bi->bi_bh);
-#ifdef CONFIG_REISERFS_CHECK
- if ( !bh )
- reiserfs_panic (0, "leaf_delete_items: 10155: bh is not defined");
-
- if ( del_num < 0 )
- reiserfs_panic (0, "leaf_delete_items: 10160: del_num can not be < 0. del_num==%d", del_num);
-
- if ( first < 0 || first + del_num > item_amount )
- reiserfs_panic (0, "leaf_delete_items: 10165: invalid number of first item to be deleted (%d) or "
- "no so much items (%d) to delete (only %d)", first, first + del_num, item_amount);
-#endif
-
if ( del_num == 0 )
return;
@@ -807,10 +620,10 @@ void leaf_delete_items (reiserfs_filsys_t fs,
if (I_IS_DIRECTORY_ITEM(ih = B_N_PITEM_HEAD(bh, B_NR_ITEMS(bh)-1))) /* the last item is directory */
/* len = numbers of directory entries in this item */
- len = ih_entry_count(ih);
+ len = get_ih_entry_count(ih);
else
/* len = body len of item */
- len = ih->ih_item_len;
+ len = get_ih_item_len (ih);
/* delete the part of the last item of the bh
do not delete item header
@@ -822,7 +635,7 @@ void leaf_delete_items (reiserfs_filsys_t fs,
/* insert item into the leaf node in position before */
-void leaf_insert_into_buf (struct super_block * s,
+void leaf_insert_into_buf (reiserfs_filsys_t * s,
struct buffer_info * bi,
int before,
struct item_head * inserted_item_ih,
@@ -838,29 +651,20 @@ void leaf_insert_into_buf (struct super_block * s,
int last_loc, unmoved_loc;
char * to;
- nr = (blkh = B_BLK_HEAD (bh))->blk_nr_item;
-
-#ifdef CONFIG_REISERFS_CHECK
- /* check free space */
- if (blkh->blk_free_space < inserted_item_ih->ih_item_len + IH_SIZE)
- reiserfs_panic (0, "leaf_insert_into_buf: 10170: not enough free space: needed %d, available %d",
- inserted_item_ih->ih_item_len + IH_SIZE, blkh->blk_free_space);
- if (zeros_number > inserted_item_ih->ih_item_len)
- reiserfs_panic (0, "vs-10172: leaf_insert_into_buf: zero number == %d, item length == %d", zeros_number, inserted_item_ih->ih_item_len);
-#endif /* CONFIG_REISERFS_CHECK */
-
+ blkh = B_BLK_HEAD (bh);
+ nr = get_blkh_nr_items (blkh);
/* get item new item must be inserted before */
ih = B_N_PITEM_HEAD (bh, before);
/* prepare space for the body of new item */
- last_loc = nr ? ih[nr - before - 1].ih_item_location : bh->b_size;
- unmoved_loc = before ? (ih-1)->ih_item_location : bh->b_size;
+ last_loc = nr ? get_ih_location (&ih[nr - before - 1]) : bh->b_size;
+ unmoved_loc = before ? get_ih_location (ih-1) : bh->b_size;
- memmove (bh->b_data + last_loc - inserted_item_ih->ih_item_len,
+ memmove (bh->b_data + last_loc - get_ih_item_len (inserted_item_ih),
bh->b_data + last_loc, unmoved_loc - last_loc);
- to = bh->b_data + unmoved_loc - inserted_item_ih->ih_item_len;
+ to = bh->b_data + unmoved_loc - get_ih_item_len (inserted_item_ih);
memset (to, 0, zeros_number);
to += zeros_number;
@@ -869,28 +673,33 @@ void leaf_insert_into_buf (struct super_block * s,
//if (mem_mode == REISERFS_USER_MEM)
// copy_from_user (to, inserted_item_body, inserted_item_ih->ih_item_len - zeros_number);
//else {
- memmove (to, inserted_item_body, inserted_item_ih->ih_item_len - zeros_number);
+ memmove (to, inserted_item_body, get_ih_item_len (inserted_item_ih) - zeros_number);
//}
else
- memset(to, '\0', inserted_item_ih->ih_item_len - zeros_number);
+ memset(to, '\0', get_ih_item_len (inserted_item_ih) - zeros_number);
/* insert item header */
memmove (ih + 1, ih, IH_SIZE * (nr - before));
memmove (ih, inserted_item_ih, IH_SIZE);
/* change locations */
- for (i = before; i < nr + 1; i ++)
- ih[i-before].ih_item_location =
- (unmoved_loc -= ih[i-before].ih_item_len);
+ for (i = before; i < nr + 1; i ++) {
+ unmoved_loc -= get_ih_item_len (&ih[i-before]);
+ set_ih_location (&ih[i-before], unmoved_loc);
+ }
/* sizes, free space, item number */
- blkh->blk_nr_item ++;
- blkh->blk_free_space -= (IH_SIZE + inserted_item_ih->ih_item_len);
+ set_blkh_nr_items (blkh, get_blkh_nr_items (blkh) + 1);
+ set_blkh_free_space (blkh, get_blkh_free_space (blkh) -
+ (IH_SIZE + get_ih_item_len (inserted_item_ih)));
mark_buffer_dirty(bh) ;
if (bi->bi_parent) {
- B_N_CHILD (bi->bi_parent, bi->bi_position)->dc_size += (IH_SIZE + inserted_item_ih->ih_item_len);
+ struct disk_child * dc;
+
+ dc = B_N_CHILD (bi->bi_parent, bi->bi_position);
+ set_dc_child_size (dc, get_dc_child_size (dc) + IH_SIZE + get_ih_item_len (inserted_item_ih));
mark_buffer_dirty(bi->bi_parent) ;
}
@@ -902,7 +711,7 @@ void leaf_insert_into_buf (struct super_block * s,
/* paste paste_size bytes to affected_item_num-th item.
When item is a directory, this only prepare space for new entries */
-void leaf_paste_in_buffer (reiserfs_filsys_t fs,
+void leaf_paste_in_buffer (reiserfs_filsys_t * fs,
struct buffer_info * bi,
int affected_item_num,
int pos_in_item,
@@ -918,27 +727,14 @@ void leaf_paste_in_buffer (reiserfs_filsys_t fs,
int last_loc, unmoved_loc;
- nr = (blkh = B_BLK_HEAD(bh))->blk_nr_item;
-
-#ifdef CONFIG_REISERFS_CHECK
- /* check free space */
- if (blkh->blk_free_space < paste_size)
- reiserfs_panic (th->t_super, "vs-10175: leaf_paste_in_buffer: "
- "not enough free space: needed %d, available %d",
- paste_size, blkh->blk_free_space);
- if (zeros_number > paste_size) {
- print_tb (init_mode, init_item_pos, init_pos_in_item, &init_tb, "10177");
- reiserfs_panic (th->t_super, "vs-10177: leaf_paste_in_buffer: "
- "zero number == %d, paste_size == %d", zeros_number, paste_size);
- }
-#endif /* CONFIG_REISERFS_CHECK */
-
+ blkh = B_BLK_HEAD (bh);
+ nr = get_blkh_nr_items (blkh);
/* item to be appended */
ih = B_N_PITEM_HEAD(bh, affected_item_num);
- last_loc = ih[nr - affected_item_num - 1].ih_item_location;
- unmoved_loc = affected_item_num ? (ih-1)->ih_item_location : bh->b_size;
+ last_loc = get_ih_location (&ih[nr - affected_item_num - 1]);
+ unmoved_loc = affected_item_num ? get_ih_location (ih-1) : bh->b_size;
/* prepare space */
memmove (bh->b_data + last_loc - paste_size, bh->b_data + last_loc,
@@ -947,7 +743,7 @@ void leaf_paste_in_buffer (reiserfs_filsys_t fs,
/* change locations */
for (i = affected_item_num; i < nr; i ++)
- ih[i-affected_item_num].ih_item_location -= paste_size;
+ set_ih_location (&ih[i-affected_item_num], get_ih_location (&ih[i-affected_item_num]) - paste_size);
if ( body ) {
if (!I_IS_DIRECTORY_ITEM(ih)) {
@@ -958,11 +754,11 @@ void leaf_paste_in_buffer (reiserfs_filsys_t fs,
{
if (!pos_in_item) {
/* shift data to right */
- memmove (bh->b_data + ih->ih_item_location + paste_size,
- bh->b_data + ih->ih_item_location, ih->ih_item_len);
+ memmove (bh->b_data + get_ih_location (ih) + paste_size,
+ bh->b_data + get_ih_location (ih), get_ih_item_len (ih));
/* paste data in the head of item */
- memset (bh->b_data + ih->ih_item_location, 0, zeros_number);
- memcpy (bh->b_data + ih->ih_item_location + zeros_number, body, paste_size - zeros_number);
+ memset (bh->b_data + get_ih_location (ih), 0, zeros_number);
+ memcpy (bh->b_data + get_ih_location (ih) + zeros_number, body, paste_size - zeros_number);
} else {
memset (bh->b_data + unmoved_loc - paste_size, 0, zeros_number);
memcpy (bh->b_data + unmoved_loc - paste_size + zeros_number, body, paste_size - zeros_number);
@@ -973,15 +769,18 @@ void leaf_paste_in_buffer (reiserfs_filsys_t fs,
else
memset(bh->b_data + unmoved_loc - paste_size,'\0',paste_size);
- ih->ih_item_len += paste_size;
+ set_ih_item_len (ih, get_ih_item_len (ih) + paste_size);
/* change free space */
- blkh->blk_free_space -= paste_size;
+ set_blkh_free_space (blkh, get_blkh_free_space (blkh) - paste_size);
mark_buffer_dirty(bh) ;
if (bi->bi_parent) {
- B_N_CHILD (bi->bi_parent, bi->bi_position)->dc_size += paste_size;
+ struct disk_child * dc;
+
+ dc = B_N_CHILD (bi->bi_parent, bi->bi_position);
+ set_dc_child_size (dc, get_dc_child_size (dc) + paste_size);
mark_buffer_dirty(bi->bi_parent);
}
if (who_is_this (bh->b_data, bh->b_size) != THE_LEAF)
@@ -989,6 +788,7 @@ void leaf_paste_in_buffer (reiserfs_filsys_t fs,
bh->b_blocknr, bh);
}
+
/* cuts DEL_COUNT entries beginning from FROM-th entry. Directory item
does not have free space, so it moves DEHs and remaining records as
necessary. Return value is size of removed part of directory item
@@ -1007,41 +807,44 @@ static int leaf_cut_entries (struct buffer_head * bh,
/* first byte of item */
- item = bh->b_data + ih_location (ih);
+ item = B_I_PITEM (bh, ih);
/* entry head array */
deh = B_I_DEH (bh, ih);
- entry_count = ih_entry_count (ih);
+ entry_count = get_ih_entry_count (ih);
if (del_count == 0) {
int shift;
int last_location;
- last_location = deh_location (deh + entry_count - 1);
+ last_location = get_deh_location (deh + entry_count - 1);
shift = last_location - DEH_SIZE * entry_count;
memmove (deh + entry_count, item + last_location,
- ih_item_len (ih) - last_location);
+ get_ih_item_len (ih) - last_location);
for (i = 0; i < entry_count; i ++)
- deh[i].deh_location = cpu_to_le16 (deh_location (deh + i) - shift);
+ set_deh_location (&deh[i], get_deh_location (&deh[i]) - shift);
+
return shift;
}
/* first byte of remaining entries, those are BEFORE cut entries
(prev_record) and length of all removed records (cut_records_len) */
- prev_record_offset = (from ? deh[from - 1].deh_location : ih->ih_item_len);
- cut_records_len = prev_record_offset/*from_record*/ - deh[from + del_count - 1].deh_location;
+ prev_record_offset = (from ? get_deh_location (&deh[from - 1]) : get_ih_item_len (ih));
+ cut_records_len = prev_record_offset/*from_record*/ - get_deh_location (&deh[from + del_count - 1]);
prev_record = item + prev_record_offset;
/* adjust locations of remaining entries */
- for (i = ih_entry_count (ih) - 1; i > from + del_count - 1; i --)
- deh[i].deh_location -= (DEH_SIZE * del_count);
+ for (i = get_ih_entry_count (ih) - 1; i > from + del_count - 1; i --) {
+ set_deh_location (deh + i, get_deh_location (deh + i) - (DEH_SIZE * del_count));
+ }
- for (i = 0; i < from; i ++)
- deh[i].deh_location -= DEH_SIZE * del_count + cut_records_len;
+ for (i = 0; i < from; i ++) {
+ set_deh_location (deh + i, get_deh_location (deh + i) - (DEH_SIZE * del_count + cut_records_len));
+ }
- set_entry_count (ih, ih_entry_count (ih) - del_count);
+ set_ih_entry_count (ih, get_ih_entry_count (ih) - del_count);
/* shift entry head array and entries those are AFTER removed entries */
memmove ((char *)(deh + from),
@@ -1050,7 +853,7 @@ static int leaf_cut_entries (struct buffer_head * bh,
/* shift records, those are BEFORE removed entries */
memmove (prev_record - cut_records_len - DEH_SIZE * del_count,
- prev_record, item + ih->ih_item_len - prev_record);
+ prev_record, item + get_ih_item_len (ih) - prev_record);
return DEH_SIZE * del_count + cut_records_len;
}
@@ -1064,7 +867,7 @@ static int leaf_cut_entries (struct buffer_head * bh,
pos_in_item - number of first deleted entry
cut_size - count of deleted entries
*/
-void leaf_cut_from_buffer (reiserfs_filsys_t fs,
+void leaf_cut_from_buffer (reiserfs_filsys_t * fs,
struct buffer_info * bi, int cut_item_num,
int pos_in_item, int cut_size)
{
@@ -1075,7 +878,8 @@ void leaf_cut_from_buffer (reiserfs_filsys_t fs,
int last_loc, unmoved_loc;
int i;
- nr = (blkh = B_BLK_HEAD (bh))->blk_nr_item;
+ blkh = B_BLK_HEAD (bh);
+ nr = get_blkh_nr_items (blkh);
/* item head of truncated item */
ih = B_N_PITEM_HEAD (bh, cut_item_num);
@@ -1084,32 +888,17 @@ void leaf_cut_from_buffer (reiserfs_filsys_t fs,
/* first cut entry ()*/
cut_size = leaf_cut_entries (bh, ih, pos_in_item, cut_size);
if (pos_in_item == 0) {
- /* change key */
-#ifdef CONFIG_REISERFS_CHECK
- if (cut_item_num)
- reiserfs_panic (th->t_super, "leaf_cut_from_buffer: 10190: "
- "when 0-th enrty of item is cut, that item must be first in the node, not %d-th", cut_item_num);
-#endif
/* change item key by key of first entry in the item */
- ih->ih_key.u.k_offset_v1.k_offset = B_I_DEH (bh, ih)->deh_offset;
-
+ set_key_offset_v1 (&ih->ih_key, get_deh_offset (B_I_DEH (bh, ih)));
/*memcpy (&ih->ih_key.k_offset, &(B_I_DEH (bh, ih)->deh_offset), SHORT_KEY_SIZE);*/
- }
+ }
} else {
/* item is direct or indirect */
-#ifdef CONFIG_REISERFS_CHECK
- if (I_IS_STAT_DATA_ITEM (ih))
- reiserfs_panic (th->t_super, "leaf_cut_from_buffer: 10195: item is stat data");
-
- if (pos_in_item && pos_in_item + cut_size != ih->ih_item_len )
- reiserfs_panic (th->t_super, "cut_from_buf: 10200: invalid offset (%lu) or trunc_size (%lu) or ih_item_len (%lu)",
- pos_in_item, cut_size, ih->ih_item_len);
-#endif
-
/* shift item body to left if cut is from the head of item */
if (pos_in_item == 0) {
- memmove (bh->b_data + ih->ih_item_location, bh->b_data + ih->ih_item_location + cut_size,
- ih->ih_item_len - cut_size);
+ memmove (bh->b_data + get_ih_location (ih),
+ bh->b_data + get_ih_location (ih) + cut_size,
+ get_ih_item_len (ih) - cut_size);
/* change key of item */
if (I_IS_DIRECT_ITEM(ih)) {
@@ -1119,20 +908,16 @@ void leaf_cut_from_buffer (reiserfs_filsys_t fs,
//ih->ih_key.k_offset += (cut_size / UNFM_P_SIZE) * bh->b_size;
set_offset (key_format (&ih->ih_key), &ih->ih_key,
get_offset (&ih->ih_key) + (cut_size / UNFM_P_SIZE) * bh->b_size);
-#ifdef CONFIG_REISERFS_CHECK
- if ( ih->ih_item_len == cut_size && ih_free_space (ih) )
- reiserfs_panic (th->t_super, "leaf_cut_from_buf: 10205: invalid ih_free_space (%lu)", ih_free_space (ih));
-#endif
- }
}
+ }
}
/* location of the last item */
- last_loc = ih[nr - cut_item_num - 1].ih_item_location;
+ last_loc = get_ih_location (&ih[nr - cut_item_num - 1]);
/* location of the item, which is remaining at the same place */
- unmoved_loc = cut_item_num ? (ih-1)->ih_item_location : bh->b_size;
+ unmoved_loc = cut_item_num ? get_ih_location (ih-1) : bh->b_size;
/* shift */
@@ -1140,26 +925,30 @@ void leaf_cut_from_buffer (reiserfs_filsys_t fs,
unmoved_loc - last_loc - cut_size);
/* change item length */
- ih->ih_item_len -= cut_size;
+ set_ih_item_len (ih, get_ih_item_len (ih) - cut_size);
if (I_IS_INDIRECT_ITEM(ih)) {
if (pos_in_item)
//ih->u.ih_free_space = 0;
- set_free_space (ih, 0);
+ set_ih_free_space (ih, 0);
}
/* change locations */
- for (i = cut_item_num; i < nr; i ++)
- ih[i-cut_item_num].ih_item_location += cut_size;
+ for (i = cut_item_num; i < nr; i ++) {
+ set_ih_location (&ih[i-cut_item_num], get_ih_location (&ih[i-cut_item_num]) + cut_size);
+ }
/* size, free space */
- blkh->blk_free_space += cut_size;
+ set_blkh_free_space (blkh, get_blkh_free_space (blkh) + cut_size);
mark_buffer_dirty(bh);
- if (bi->bi_parent) {
- B_N_CHILD (bi->bi_parent, bi->bi_position)->dc_size -= cut_size;
- mark_buffer_dirty(bi->bi_parent);
+ if (bi->bi_parent) {
+ struct disk_child * dc;
+
+ dc = B_N_CHILD (bi->bi_parent, bi->bi_position);
+ set_dc_child_size (dc, get_dc_child_size (dc) - cut_size);
+ mark_buffer_dirty(bi->bi_parent);
}
if (who_is_this (bh->b_data, bh->b_size) != THE_LEAF)
reiserfs_panic ("leaf_cut_from_buffer: bad leaf %lu: %b",
@@ -1168,7 +957,7 @@ void leaf_cut_from_buffer (reiserfs_filsys_t fs,
/* delete del_num items from buffer starting from the first'th item */
-static void leaf_delete_items_entirely (reiserfs_filsys_t fs,
+static void leaf_delete_items_entirely (reiserfs_filsys_t * fs,
struct buffer_info * bi,
int first, int del_num)
{
@@ -1179,24 +968,11 @@ static void leaf_delete_items_entirely (reiserfs_filsys_t fs,
struct block_head * blkh;
struct item_head * ih;
-
-#ifdef CONFIG_REISERFS_CHECK
- if (bh == NULL)
- reiserfs_panic (0, "leaf_delete_items_entirely: 10210: buffer is 0");
-
- if (del_num < 0)
- reiserfs_panic (0, "leaf_delete_items_entirely: 10215: del_num less than 0 (%d)", del_num);
-#endif /* CONFIG_REISERFS_CHECK */
-
if (del_num == 0)
return;
- nr = (blkh = B_BLK_HEAD(bh))->blk_nr_item;
-
-#ifdef CONFIG_REISERFS_CHECK
- if (first < 0 || first + del_num > nr)
- reiserfs_panic (0, "leaf_delete_items_entirely: 10220: first=%d, number=%d, there is %d items", first, del_num, nr);
-#endif /* CONFIG_REISERFS_CHECK */
+ blkh = B_BLK_HEAD (bh);
+ nr = get_blkh_nr_items (blkh);
if (first == 0 && del_num == nr) {
/* this does not work */
@@ -1209,11 +985,11 @@ static void leaf_delete_items_entirely (reiserfs_filsys_t fs,
ih = B_N_PITEM_HEAD (bh, first);
/* location of unmovable item */
- j = (first == 0) ? bh->b_size : (ih-1)->ih_item_location;
+ j = (first == 0) ? bh->b_size : get_ih_location (ih-1);
/* delete items */
- last_loc = ih[nr-1-first].ih_item_location;
- last_removed_loc = ih[del_num-1].ih_item_location;
+ last_loc = get_ih_location (&ih[nr - 1 - first]);
+ last_removed_loc = get_ih_location (&ih[del_num-1]);
memmove (bh->b_data + last_loc + j - last_removed_loc,
bh->b_data + last_loc, last_removed_loc - last_loc);
@@ -1222,17 +998,21 @@ static void leaf_delete_items_entirely (reiserfs_filsys_t fs,
memmove (ih, ih + del_num, (nr - first - del_num) * IH_SIZE);
/* change item location */
- for (i = first; i < nr - del_num; i ++)
- ih[i-first].ih_item_location += j - last_removed_loc;
+ for (i = first; i < nr - del_num; i ++) {
+ set_ih_location (&ih[i-first], get_ih_location (&ih[i-first]) + j - last_removed_loc);
+ }
/* sizes, item number */
- blkh->blk_nr_item -= del_num;
- blkh->blk_free_space += j - last_removed_loc + IH_SIZE * del_num;
+ set_blkh_nr_items (blkh, get_blkh_nr_items (blkh)/*nr*/ - del_num);
+ set_blkh_free_space (blkh, get_blkh_free_space (blkh) + j - last_removed_loc + IH_SIZE * del_num);
mark_buffer_dirty(bh);
if (bi->bi_parent) {
- B_N_CHILD (bi->bi_parent, bi->bi_position)->dc_size -= j - last_removed_loc + IH_SIZE * del_num;
+ struct disk_child * dc;
+
+ dc = B_N_CHILD (bi->bi_parent, bi->bi_position);
+ set_dc_child_size (dc, get_dc_child_size (dc) - (j - last_removed_loc + IH_SIZE * del_num));
mark_buffer_dirty(bi->bi_parent);
}
if (who_is_this (bh->b_data, bh->b_size) != THE_LEAF)
@@ -1261,40 +1041,29 @@ void leaf_paste_entries (struct buffer_head * bh,
ih = B_N_PITEM_HEAD(bh, item_num);
-#ifdef CONFIG_REISERFS_CHECK
- /* make sure, that item is directory, and there are enough records in it */
- if (!I_IS_DIRECTORY_ITEM (ih))
- reiserfs_panic (0, "leaf_paste_entries: 10225: item is not directory item");
-
- if (ih_entry_count (ih) < before)
- reiserfs_panic (0, "leaf_paste_entries: 10230: there are no entry we paste entries before. entry_count = %d, before = %d",
- ih_entry_count (ih), before);
-#endif
-
-
/* first byte of dest item */
- item = bh->b_data + ih->ih_item_location;
+ item = B_I_PITEM (bh, ih);
/* entry head array */
deh = B_I_DEH (bh, ih);
/* new records will be pasted at this point */
- insert_point = item + (before ? deh[before - 1].deh_location : (ih->ih_item_len - paste_size));
+ insert_point = item + (before ? get_deh_location (&deh[before - 1]) : (get_ih_item_len (ih) - paste_size));
/* adjust locations of records that will be AFTER new records */
- for (i = ih_entry_count (ih) - 1; i >= before; i --)
- deh[i].deh_location += DEH_SIZE * new_entry_count;
+ for (i = get_ih_entry_count (ih) - 1; i >= before; i --)
+ set_deh_location (deh + i, get_deh_location (deh + i) + DEH_SIZE * new_entry_count);
/* adjust locations of records that will be BEFORE new records */
for (i = 0; i < before; i ++)
- deh[i].deh_location += paste_size;
+ set_deh_location (deh + i, get_deh_location (deh + i) + paste_size);
- old_entry_num = ih_entry_count (ih);
+ old_entry_num = get_ih_entry_count (ih);
//I_ENTRY_COUNT(ih) += new_entry_count;
- set_entry_count (ih, old_entry_num + new_entry_count);
+ set_ih_entry_count (ih, old_entry_num + new_entry_count);
/* prepare space for pasted records */
- memmove (insert_point + paste_size, insert_point, item + (ih->ih_item_len - paste_size) - insert_point);
+ memmove (insert_point + paste_size, insert_point, item + (get_ih_item_len (ih) - paste_size) - insert_point);
/* copy new records */
memcpy (insert_point + DEH_SIZE * new_entry_count, records,
@@ -1310,39 +1079,21 @@ void leaf_paste_entries (struct buffer_head * bh,
/* set locations of new records */
for (i = 0; i < new_entry_count; i ++)
- deh[i].deh_location +=
- (- new_dehs[new_entry_count - 1].deh_location + insert_point + DEH_SIZE * new_entry_count - item);
+ set_deh_location (deh + i,
+ get_deh_location (deh + i) + (- get_deh_location (&new_dehs[new_entry_count - 1]) +
+ insert_point + DEH_SIZE * new_entry_count - item));
/* change item key if neccessary (when we paste before 0-th entry */
if (!before)
- ih->ih_key.u.k_offset_v1.k_offset = new_dehs->deh_offset;
-
-
-#ifdef CONFIG_REISERFS_CHECK
- {
- int prev, next;
- /* check record locations */
- deh = B_I_DEH (bh, ih);
- for (i = 0; i < ih_entry_count(ih); i ++) {
- next = (i < ih_entry_count(ih) - 1) ? deh[i + 1].deh_location : 0;
- prev = (i != 0) ? deh[i - 1].deh_location : 0;
-
- if (prev && prev <= deh[i].deh_location)
- reiserfs_warning ("vs-10240: leaf_paste_entries: directory item corrupted (%d %d)\n", prev, deh[i].deh_location);
- if (next && next >= deh[i].deh_location)
- reiserfs_warning ("vs-10250: leaf_paste_entries: directory item corrupted (%d %d)\n", prev, deh[i].deh_location);
- }
- }
-#endif
-
+ set_key_offset_v1 (&ih->ih_key, get_deh_offset (new_dehs));
}
/* wrappers for operations on one separated node */
-void delete_item (reiserfs_filsys_t fs,
+void delete_item (reiserfs_filsys_t * fs,
struct buffer_head * bh, int item_num)
{
struct buffer_info bi;
@@ -1354,7 +1105,7 @@ void delete_item (reiserfs_filsys_t fs,
}
-void cut_entry (reiserfs_filsys_t fs, struct buffer_head * bh,
+void cut_entry (reiserfs_filsys_t * fs, struct buffer_head * bh,
int item_num, int entry_num, int del_count)
{
struct buffer_info bi;
diff --git a/reiserfscore/node_formats.c b/reiserfscore/node_formats.c
index 43ed843..28cc349 100644
--- a/reiserfscore/node_formats.c
+++ b/reiserfscore/node_formats.c
@@ -1,15 +1,22 @@
/*
- * Copyrright 2000 by Hans Reiser, licensing governed by reiserfs/README
+ * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
#include "includes.h"
+int correct_direct_item_offset (__u64 offset, int format) {
+ if (format == KEY_FORMAT_2) {
+ return (offset && ((offset - 1) % 8 == 0));
+ } else {
+ return (offset);
+ }
+ return 0;
+}
-
-/* this only checks that the node looks like a correct leaf. Item
- internals are not checked */
-static int is_correct_leaf (char * buf, int blocksize)
+/* this only checks block header and item head array (ih_location-s
+ and ih_item_len-s). Item internals are not checked */
+static int does_node_look_like_a_leaf (char * buf, int blocksize)
{
struct block_head * blkh;
struct item_head * ih;
@@ -22,14 +29,14 @@ static int is_correct_leaf (char * buf, int blocksize)
if (!is_leaf_block_head (buf))
return 0;
- nr = le16_to_cpu (blkh->blk_nr_item);
- if (nr < 1 || nr > ((blocksize - BLKH_SIZE) / (IH_SIZE + MIN_ITEM_LEN)))
+ nr = get_blkh_nr_items (blkh);
+ if (nr < 0 || nr > ((blocksize - BLKH_SIZE) / (IH_SIZE + MIN_ITEM_LEN)))
/* item number is too big or too small */
return 0;
ih = (struct item_head *)(buf + BLKH_SIZE) + nr - 1;
- used_space = BLKH_SIZE + IH_SIZE * nr + (blocksize - ih_location (ih));
- if (used_space != blocksize - le16_to_cpu (blkh->blk_free_space))
+ used_space = BLKH_SIZE + IH_SIZE * nr + (blocksize - (nr ? get_ih_location (ih) : blocksize));
+ if (used_space != blocksize - get_blkh_free_space (blkh))
/* free space does not match to calculated amount of use space */
return 0;
@@ -40,15 +47,15 @@ static int is_correct_leaf (char * buf, int blocksize)
ih = (struct item_head *)(buf + BLKH_SIZE);
prev_location = blocksize;
for (i = 0; i < nr; i ++, ih ++) {
- /* items of length are allowed - they may exist for short time
+ /* items of zero length are allowed - they may exist for short time
during balancing */
- if (ih_location (ih) > blocksize || ih_location (ih) < IH_SIZE * nr)
+ if (get_ih_location (ih) > blocksize || get_ih_location (ih) < IH_SIZE * nr)
return 0;
- if (/*ih_item_len (ih) < 1 ||*/ ih_item_len (ih) > MAX_ITEM_LEN (blocksize))
+ if (/*ih_item_len (ih) < 1 ||*/ get_ih_item_len (ih) > MAX_ITEM_LEN (blocksize))
return 0;
- if (prev_location - ih_location (ih) != ih_item_len (ih))
+ if (prev_location - get_ih_location (ih) != get_ih_item_len (ih))
return 0;
- prev_location = ih_location (ih);
+ prev_location = get_ih_location (ih);
}
// one may imagine much more checks
@@ -56,6 +63,32 @@ static int is_correct_leaf (char * buf, int blocksize)
}
+/* check ih_item_len and ih_location. Should be useful when block head is
+ corrupted */
+int does_node_have_ih_array (char * buf, int blocksize)
+{
+ struct item_head * ih;
+ int prev_location;
+ int nr;
+
+ /* look at the table of item head */
+ prev_location = blocksize;
+ ih = (struct item_head *)(buf + BLKH_SIZE);
+ nr = 0;
+ while (1) {
+ if (get_ih_location (ih) + get_ih_item_len (ih) != prev_location)
+ break;
+
+ prev_location = get_ih_location (ih);
+ ih ++;
+ nr ++;
+ }
+ if (nr < 2)
+ return 0;
+ return nr;
+}
+
+
/* returns 1 if buf looks like an internal node, 0 otherwise */
static int is_correct_internal (char * buf, int blocksize)
{
@@ -68,13 +101,13 @@ static int is_correct_internal (char * buf, int blocksize)
if (!is_internal_block_head (buf))
return 0;
- nr = le16_to_cpu (blkh->blk_nr_item);
+ nr = get_blkh_nr_items (blkh);
if (nr > (blocksize - BLKH_SIZE - DC_SIZE) / (KEY_SIZE + DC_SIZE))
/* for internal which is not root we might check min number of keys */
return 0;
used_space = BLKH_SIZE + KEY_SIZE * nr + DC_SIZE * (nr + 1);
- if (used_space != blocksize - le16_to_cpu (blkh->blk_free_space))
+ if (used_space != blocksize - get_blkh_free_space (blkh))
return 0;
// one may imagine much more checks
@@ -89,53 +122,124 @@ int is_tree_node (struct buffer_head * bh, int level)
if (B_LEVEL (bh) != level)
return 0;
if (is_leaf_node (bh))
- return is_correct_leaf (bh->b_data, bh->b_size);
+ return does_node_look_like_a_leaf (bh->b_data, bh->b_size);
return is_correct_internal (bh->b_data, bh->b_size);
}
-static int is_desc_block (struct reiserfs_journal_desc * desc)
+static int is_desc_block (char * buf, unsigned long buf_size)
{
- if (!memcmp(desc->j_magic, JOURNAL_DESC_MAGIC, 8) &&
- le32_to_cpu (desc->j_len) > 0)
+ if (!memcmp(buf + buf_size - 12, JOURNAL_DESC_MAGIC, 8) &&
+ //get_jdesc_len (desc) > 0)
+ le32_to_cpu(*((__u32*)(buf + 4))) > 0)
return 1;
return 0;
}
-int is_reiserfs_magic_string (struct reiserfs_super_block * rs)
+int is_reiserfs_3_5_magic_string (struct reiserfs_super_block * rs)
+{
+ return (!strncmp (rs->s_v1.s_magic, REISERFS_3_5_SUPER_MAGIC_STRING,
+ strlen ( REISERFS_3_5_SUPER_MAGIC_STRING)));
+}
+
+
+int is_reiserfs_3_6_magic_string (struct reiserfs_super_block * rs)
+{
+ return (!strncmp (rs->s_v1.s_magic, REISERFS_3_6_SUPER_MAGIC_STRING,
+ strlen ( REISERFS_3_6_SUPER_MAGIC_STRING)));
+}
+
+
+int is_reiserfs_jr_magic_string (struct reiserfs_super_block * rs)
+{
+ return (!strncmp (rs->s_v1.s_magic, REISERFS_JR_SUPER_MAGIC_STRING,
+ strlen ( REISERFS_JR_SUPER_MAGIC_STRING)));
+}
+
+
+int is_any_reiserfs_magic_string (struct reiserfs_super_block * rs)
{
- return (!strncmp (rs->s_v1.s_magic, REISERFS_SUPER_MAGIC_STRING,
- strlen ( REISERFS_SUPER_MAGIC_STRING)));
+ if (is_reiserfs_3_5_magic_string (rs) ||
+ is_reiserfs_3_6_magic_string (rs) ||
+ is_reiserfs_jr_magic_string (rs))
+ return 1;
+ return 0;
}
-int is_reiser2fs_magic_string (struct reiserfs_super_block * rs)
+int get_reiserfs_format (struct reiserfs_super_block * sb)
{
- return (!strncmp (rs->s_v1.s_magic, REISER2FS_SUPER_MAGIC_STRING,
- strlen ( REISER2FS_SUPER_MAGIC_STRING)));
+ /* after conversion to 3.6 format we change magic correctly,
+ but do not change sb_format. When we create non-standard journal
+ field format in sb get adjusted correctly. Thereby, for standard
+ journal we should rely on magic and for non-standard - on format */
+ if (is_reiserfs_3_5_magic_string (sb) ||
+ (is_reiserfs_jr_magic_string (sb) &&
+ get_sb_version (sb) == REISERFS_FORMAT_3_5))
+ return REISERFS_FORMAT_3_5;
+
+ if (is_reiserfs_3_6_magic_string (sb) ||
+ (is_reiserfs_jr_magic_string (sb) &&
+ get_sb_version (sb) == REISERFS_FORMAT_3_6))
+ return REISERFS_FORMAT_3_6;
+
+ return REISERFS_FORMAT_UNKNOWN;
}
+
+int reiserfs_super_block_size (struct reiserfs_super_block * sb)
+{
+ switch (get_reiserfs_format (sb)) {
+ case REISERFS_FORMAT_3_5:
+ return SB_SIZE_V1;
+ case REISERFS_FORMAT_3_6:
+ return SB_SIZE;
+ }
+ reiserfs_panic ("Unknown format found");
+ return 0;
+}
+
+
+
+#if 0
+/* returns code of 0 - here means 3.5 format,
+ 2 - either pure 3.6 or converted 3.5
+ 3 - journal-relocated 3.6*/
+int magic_2_version (struct reiserfs_super_block * rs)
+{
+ int ret;
+
+ ret = 0;
+ if (is_reiser2fs_magic_string (rs))
+ ret = REISERFS_VERSION_2 ;
+ else if (is_reiser2fs_jr_magic_string (rs))
+ ret = REISERFS_VERSION_3;
+ else if (is_reiserfs_magic_string (rs))
+ ret = REISERFS_VERSION_1;
+ else
+ reiserfs_panic ("magic_2_version: unknown magic string found");
+ return ret;
+}
+#endif
+
+
/* this one had signature in different place of the super_block
structure */
int is_prejournaled_reiserfs (struct reiserfs_super_block * rs)
{
return (!strncmp((char*)rs + REISERFS_SUPER_MAGIC_STRING_OFFSET_NJ,
- REISERFS_SUPER_MAGIC_STRING, strlen(REISERFS_SUPER_MAGIC_STRING)));
+ REISERFS_3_5_SUPER_MAGIC_STRING,
+ strlen(REISERFS_3_5_SUPER_MAGIC_STRING)));
}
-
-/* compares description block with commit block. returns 1 if they differ, 0 if they are the same */
-int does_desc_match_commit (struct reiserfs_journal_desc *desc,
- struct reiserfs_journal_commit *commit)
-{
- if (commit->j_trans_id != desc->j_trans_id || commit->j_len != desc->j_len ||
- commit->j_len > JOURNAL_TRANS_MAX || commit->j_len <= 0) {
- return 1 ;
- }
- return 0 ;
+int does_look_like_super_block (struct reiserfs_super_block * sb, int blocksize) {
+ if (is_any_reiserfs_magic_string (sb) && blocksize == get_sb_block_size (sb))
+ return 1;
+
+ return 0;
}
@@ -143,22 +247,26 @@ int does_desc_match_commit (struct reiserfs_journal_desc *desc,
block, journal descriptor), unformatted */
int who_is_this (char * buf, int blocksize)
{
- if (is_correct_leaf (buf, blocksize))
+ /* super block? */
+ if (does_look_like_super_block ((void *)buf, blocksize))
+ return THE_SUPER;
+
+ if (does_node_look_like_a_leaf (buf, blocksize))
/* block head and item head array seem matching (node level, free
space, item number, item locations and length) */
return THE_LEAF;
+ if (does_node_have_ih_array (buf, blocksize)) {
+ /* item header array found */
+ return HAS_IH_ARRAY;
+ }
+
if (is_correct_internal (buf, blocksize))
return THE_INTERNAL;
- /* super block? */
- if (is_reiser2fs_magic_string ((void *)buf) ||
- is_reiserfs_magic_string ((void *)buf) ||
- is_prejournaled_reiserfs ((void *)buf))
- return THE_SUPER;
/* journal descriptor block? */
- if (is_desc_block ((void *)buf))
+ if (is_desc_block (buf, blocksize))
return THE_JDESC;
/* contents of buf does not look like reiserfs metadata. Bitmaps
@@ -167,44 +275,65 @@ int who_is_this (char * buf, int blocksize)
}
-int block_of_journal (reiserfs_filsys_t fs, unsigned long block)
+char * which_block (int code)
{
- if (block >= SB_JOURNAL_BLOCK (fs) &&
- block <= SB_JOURNAL_BLOCK (fs) + JOURNAL_BLOCK_COUNT)
- return 1;
+ static char * leaf = "leaf";
+ static char * broken_leaf = "leaf w/o block head";
+ static char * internal = "internal";
+ static char * other = "unknown";
+
+ switch (code) {
+ case THE_LEAF:
+ return leaf;
+ case HAS_IH_ARRAY:
+ return broken_leaf;
+ case THE_INTERNAL:
+ return internal;
+ }
+ return other;
+}
+
+
+/** */
+int block_of_journal (reiserfs_filsys_t * fs, unsigned long block)
+{
+ if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb)) {
+ /* standard journal */
+ if (block >= get_journal_start_must (fs) &&
+ block <= get_journal_start_must (fs) + get_jp_journal_size (sb_jp (fs->fs_ondisk_sb)))
+ return 1;
+ return 0;
+ }
+
+ if (get_sb_reserved_for_journal (fs->fs_ondisk_sb))
+ /* there is space reserved for the journal on the host device */
+ if (block >= get_journal_start_must (fs) &&
+ block < get_journal_start_must (fs) + get_sb_reserved_for_journal (fs->fs_ondisk_sb))
+ return 1;
return 0;
}
-int block_of_bitmap (reiserfs_filsys_t fs, unsigned long block)
+int block_of_bitmap (reiserfs_filsys_t * fs, unsigned long block)
{
if (spread_bitmaps (fs)) {
- if (!(block % (fs->s_blocksize * 8)))
+ if (!(block % (fs->fs_blocksize * 8)))
/* bitmap block */
return 1;
- return block == 17;
+ return (block == (REISERFS_DISK_OFFSET_IN_BYTES / fs->fs_blocksize + 1)) ;
} else {
/* bitmap in */
- if (block > 2 && block < 3 + SB_BMAP_NR (fs))
+ if (block > 2 && block < 3 + get_sb_bmap_nr (fs->fs_ondisk_sb))
return 1;
return 0;
}
-#if 0
- int i;
- int bmap_nr;
-
- bmap_nr = SB_BMAP_NR (fs);
- for (i = 0; i < bmap_nr; i ++)
- if (block == SB_AP_BITMAP (fs)[i]->b_blocknr)
- return 1;
-#endif
return 0;
}
/* check whether 'block' can be pointed to by an indirect item */
-int not_data_block (reiserfs_filsys_t fs, unsigned long block)
+int not_data_block (reiserfs_filsys_t * fs, unsigned long block)
{
if (block_of_bitmap (fs, block))
/* it is one of bitmap blocks */
@@ -217,7 +346,7 @@ int not_data_block (reiserfs_filsys_t fs, unsigned long block)
/* block of journal area */
return 1;
- if (block <= fs->s_sbh->b_blocknr)
+ if (block <= fs->fs_super_bh->b_blocknr)
/* either super block or a block from skipped area at the
beginning of filesystem */
return 1;
@@ -227,156 +356,184 @@ int not_data_block (reiserfs_filsys_t fs, unsigned long block)
/* check whether 'block' can be logged */
-int not_journalable (reiserfs_filsys_t fs, unsigned long block)
+int not_journalable (reiserfs_filsys_t * fs, unsigned long block)
{
/* we should not update SB with journal copy during fsck */
- if (block < fs->s_sbh->b_blocknr)
+ if (block < fs->fs_super_bh->b_blocknr)
return 1;
if (block_of_journal (fs, block))
return 1;
- if (block >= SB_BLOCK_COUNT (fs))
+ if (block >= get_sb_block_count (fs->fs_ondisk_sb))
return 1;
return 0;
}
-
// in reiserfs version 0 (undistributed bitmap)
// FIXME: what if number of bitmaps is 15?
-int get_journal_old_start_must (struct reiserfs_super_block * rs)
+int get_journal_old_start_must (reiserfs_filsys_t * fs)
{
- return 3 + rs_bmap_nr (rs);
+ return (REISERFS_OLD_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) + 1 + get_sb_bmap_nr (fs->fs_ondisk_sb);
}
-
-// in reiserfs version 1 (distributed bitmap) journal starts at 18-th
-//
-int get_journal_start_must (int blocksize)
+int get_journal_new_start_must (reiserfs_filsys_t * fs)
{
- return (REISERFS_DISK_OFFSET_IN_BYTES / blocksize) + 2;
+ return (REISERFS_DISK_OFFSET_IN_BYTES / fs->fs_blocksize) + 2;
}
-int get_bmap_num (struct super_block * s)
-{
- return ((is_prejournaled_reiserfs (s->s_rs)) ?
- (((struct reiserfs_super_block_v0 *)s->s_rs)->s_bmap_nr) :
- SB_BMAP_NR (s));
-}
+int get_journal_start_must (reiserfs_filsys_t * fs) {
+// if (fs->fs_super_bh->b_size == 4096 && fs->fs_super_bh->b_blocknr == 2)
+ if (is_old_sb_location (fs->fs_super_bh->b_blocknr, fs->fs_blocksize))
+ return get_journal_old_start_must (fs);
-int get_block_count (struct super_block * s)
-{
- return ((is_prejournaled_reiserfs (s->s_rs)) ?
- (((struct reiserfs_super_block_v0 *)s->s_rs)->s_block_count) :
- SB_BLOCK_COUNT (s));
+ return get_journal_new_start_must (fs);
}
-int get_root_block (struct super_block * s)
+__u64 get_bytes_number (struct item_head * ih, int blocksize)
{
- return ((is_prejournaled_reiserfs (s->s_rs)) ?
- (((struct reiserfs_super_block_v0 *)s->s_rs)->s_root_block) :
- SB_ROOT_BLOCK (s));
+ switch (get_type (&ih->ih_key)) {
+ case TYPE_DIRECT:
+ return get_ih_item_len (ih);
+ case TYPE_INDIRECT:
+ return I_UNFM_NUM(ih) * blocksize;// - get_ih_free_space (ih);
+ case TYPE_STAT_DATA:
+ case TYPE_DIRENTRY:
+ return 0;
+ }
+ reiserfs_warning (stderr, "get_bytes_number: called for wrong type of item %h", ih);
+ return 0;
}
+int check_item_f (reiserfs_filsys_t * fs, struct item_head * ih, char * item);
-int journal_size (struct super_block * s)
+#if 0
+/* look at the 16 byte and try to find: does it look like a reiserfs
+ key. Returns 0 if something looks broken in the key, 1 otherwise */
+static int does_key_look_correct (reiserfs_filsys_t * fs, struct key * key)
{
- return JOURNAL_BLOCK_COUNT;
-}
+ int type;
+
+ if (key->k_dir_id == key->k_objectid ||
+ !key->k_dir_id || key->k_objectid < 2)
+ /* k_dir_id and k_objectid must be different, and > 0 */
+ return 0;
+ if (key->u.k_offset_v1.k_offset == 0 &&
+ key->u.k_offset_v1.k_uniqueness == 0)
+ /* looks like a stat data */
+ return 1;
+ if (!key->u.k_offset_v1.k_offset ||
+ !key->u.k_offset_v1.k_uniqueness)
+ /* these should be either both 0 or both !0 */
+ return 0;
-int check_item_f (reiserfs_filsys_t fs, struct item_head * ih, char * item);
+ type = key->u.k_offset_v2.k_type;
+ if (key->u.k_offset_v1.k_uniqueness == 500)
+ /* looks like a key of directory entry */
+ return (type == 0) ? 1 : 0;
-/* make sure that key format written in item_head matches to key format
- defined looking at the key */
-static int is_key_correct (struct item_head * ih)
-{
- if (is_stat_data_ih (ih)) {
- /* stat data key looks identical in both formats */
- if (ih_item_len (ih) == SD_SIZE && ih_key_format (ih) == KEY_FORMAT_2) {
- /*printf ("new stat data\n");*/
+ if (type == 15) {
+ /* looks like old key of */
+ if (key->u.k_offset_v1.k_uniqueness == 0xffffffff) {
+ /* direct item. Check offset */
+ if (key->u.k_offset_v1.k_offset >= fs->s_blocksize * 4 + 1)
+ /* fixme: this could be more accurate */
+ return 0;
return 1;
}
- if (ih_item_len (ih) == SD_V1_SIZE && ih_key_format (ih) == KEY_FORMAT_1) {
- /*printf ("old stat data\n");*/
+
+ if (key->u.k_offset_v1.k_uniqueness == 0xfffffffe) {
+ /* indirect item. Check offset */
+ if (key->u.k_offset_v1.k_offset % fs->s_blocksize != 1)
+ return 0;
return 1;
}
+
return 0;
}
- if (ih_key_format (ih) == key_format (&ih->ih_key))
- return 1;
- return 0;
-}
+ /* there should be a new key of indirect or direct item */
-/* check stat data item length, ih_free_space, mode */
-static int is_bad_sd (reiserfs_filsys_t fs, struct item_head * ih, char * item)
-{
- mode_t mode;
+ if (type == TYPE_DIRECT) {
+ /* check offset */
+ if (key->u.k_offset_v2.k_offset >= fs->s_blocksize * 4 + 1) /* fixme*/
+ /* fixme: this could be more accurate */
+ return 0;
- if (ih_entry_count (ih) != 0xffff)
+ if ((key->u.k_offset_v2.k_offset - 1) % 8 != 0)
+ /* "new" direct items get split on the boundary of 8 byte */
+ return 0;
+
return 1;
+ }
- if (ih_key_format (ih) == KEY_FORMAT_1) {
- struct stat_data_v1 * sd = (struct stat_data_v1 *)item;
-
- if (ih_item_len (ih) != SD_V1_SIZE)
- /* old stat data must be 32 bytes long */
- return 1;
- mode = le16_to_cpu (sd->sd_mode);
- } else if (ih_key_format (ih) == KEY_FORMAT_2) {
- struct stat_data * sd = (struct stat_data *)item;
-
- if (ih_item_len (ih) != SD_SIZE)
- /* new stat data must be 44 bytes long */
- return 1;
- mode = le16_to_cpu (sd->sd_mode);
- } else
- return 1;
-
- if (!S_ISDIR (mode) && !S_ISREG (mode) && !S_ISCHR (mode) &&
- !S_ISBLK (mode) && !S_ISLNK (mode) && !S_ISFIFO (mode) &&
- !S_ISSOCK (mode))
+ if (type == TYPE_INDIRECT) {
+ /* check offset */
+ if ((key->u.k_offset_v2.k_offset % fs->s_blocksize) != 1)
+ return 0;
return 1;
+ }
return 0;
}
+#endif
+/* ih_key, ih_location and ih_item_len seem correct, check other fields */
+static int does_ih_look_correct (struct item_head * ih)
+{
+ int ih_key_format;
+ int key_key_format;
+ /* key format from item_head */
+ ih_key_format = get_ih_key_format (ih);
+ if (ih_key_format != KEY_FORMAT_1 && ih_key_format != KEY_FORMAT_2)
+ return 0;
-/* symlinks created by 3.6.x have direct items with ih_free_space == 0 */
-static int is_bad_direct (reiserfs_filsys_t fs, struct item_head * ih, char * item)
-{
- if (ih_entry_count (ih) != 0xffff && ih_entry_count (ih) != 0)
- return 1;
- return 0;
-}
+ /* key format calculated on key */
+ key_key_format = key_format (&ih->ih_key);
+ if (is_stat_data_ih (ih)) {
+ /* for stat data we can not find key format from a key itself, so look at
+ the item length */
+ if (get_ih_item_len (ih) == SD_SIZE)
+ key_key_format = KEY_FORMAT_2;
+ else if (get_ih_item_len (ih) == SD_V1_SIZE)
+ key_key_format = KEY_FORMAT_1;
+ else
+ return 0;
+ }
+ if (key_key_format != ih_key_format)
+ return 0;
+ /* we do not check ih_format.fsck_need as fsck might change it. So,
+ debugreiserfs -p will have to dump it */
+ return 1;
+}
/* check item length, ih_free_space for pure 3.5 format, unformatted node
pointers */
-static int is_bad_indirect (reiserfs_filsys_t fs, struct item_head * ih, char * item,
+static int is_bad_indirect (reiserfs_filsys_t * fs, struct item_head * ih, char * item,
check_unfm_func_t check_unfm_func)
{
int i;
__u32 * ind = (__u32 *)item;
- if (ih_item_len (ih) % UNFM_P_SIZE)
+ if (get_ih_item_len (ih) % UNFM_P_SIZE)
return 1;
for (i = 0; i < I_UNFM_NUM (ih); i ++) {
if (!ind [i])
continue;
- if (check_unfm_func && check_unfm_func (fs, ind [i]))
+ if (check_unfm_func && check_unfm_func (fs, le32_to_cpu(ind [i])))
return 1;
}
- if (fs->s_version == REISERFS_VERSION_1) {
+ if (fs->fs_format == REISERFS_FORMAT_3_5) {
/* check ih_free_space for 3.5 format only */
- if (ih_free_space (ih) > fs->s_blocksize - 1)
+ if (get_ih_free_space (ih) > fs->fs_blocksize - 1)
return 1;
}
@@ -390,11 +547,12 @@ static const struct {
} hashes[] = {{0, "not set"},
{keyed_hash, "\"tea\""},
{yura_hash, "\"rupasov\""},
- {r5_hash, "\"r5\""}};
+ {r5_hash, "\"r5\""}};
#define HASH_AMOUNT (sizeof (hashes) / sizeof (hashes [0]))
+
int known_hashes (void)
{
return HASH_AMOUNT;
@@ -406,7 +564,7 @@ int known_hashes (void)
/* this also sets hash function */
-int is_properly_hashed (reiserfs_filsys_t fs,
+int is_properly_hashed (reiserfs_filsys_t * fs,
char * name, int namelen, __u32 offset)
{
int i;
@@ -437,9 +595,13 @@ int is_properly_hashed (reiserfs_filsys_t fs,
}
/* set hash function */
- reiserfs_hash(fs) = hashes [i].func;
- }
- }
+ reiserfs_hash(fs) = hashes [i].func;
+ }
+ }
+
+ if (hash_func_is_unknown (fs)) {
+ return 0;
+ }
}
if (good_name (reiserfs_hash(fs), name, namelen, offset))
@@ -468,6 +630,10 @@ int find_hash_in_use (char * name, int namelen, __u32 hash_value_masked, int cod
{
int i;
+
+ if (!namelen || !name[0])
+ return UNSET_HASH;
+
if (code_to_try_first) {
if (hash_value_masked == GET_HASH_VALUE (hashes [code_to_try_first].func (name, namelen)))
return code_to_try_first;
@@ -486,8 +652,8 @@ int find_hash_in_use (char * name, int namelen, __u32 hash_value_masked, int cod
char * code2name (int code)
{
- if (code >= HASH_AMOUNT)
- code = 0;
+ if (code >= HASH_AMOUNT || code < 0)
+ return 0;
return hashes [code].name;
}
@@ -517,15 +683,26 @@ hashf_t code2func (int code)
}
+hashf_t name2func (char * hash)
+{
+ int i;
+
+ for (i = 0; i < HASH_AMOUNT; i ++)
+ if (!strcmp (hash, hashes [i].name))
+ return hashes [i].func;
+ return 0;
+}
+
+
int dir_entry_bad_location (struct reiserfs_de_head * deh, struct item_head * ih, int first)
{
- if (deh_location (deh) < DEH_SIZE * ih_entry_count (ih))
+ if (get_deh_location (deh) < DEH_SIZE * get_ih_entry_count (ih))
return 1;
- if (deh_location (deh) >= ih_item_len (ih))
+ if (get_deh_location (deh) >= get_ih_item_len (ih))
return 1;
- if (!first && deh_location (deh) >= deh_location (deh - 1))
+ if (!first && get_deh_location (deh) >= get_deh_location (deh - 1))
return 1;
return 0;
@@ -534,27 +711,27 @@ int dir_entry_bad_location (struct reiserfs_de_head * deh, struct item_head * ih
/* the only corruption which is not considered fatal - is hash mismatching. If
bad_dir is set - directory item having such names is considered bad */
-static int is_bad_directory (reiserfs_filsys_t fs, struct item_head * ih, char * item,
+static int is_bad_directory (reiserfs_filsys_t * fs, struct item_head * ih, char * item,
int bad_dir)
{
int i;
int namelen;
struct reiserfs_de_head * deh = (struct reiserfs_de_head *)item;
__u32 prev_offset = 0;
- __u16 prev_location = ih_item_len (ih);
+ __u16 prev_location = get_ih_item_len (ih);
- for (i = 0; i < ih_entry_count (ih); i ++, deh ++) {
- if (deh_location (deh) >= prev_location)
+ for (i = 0; i < get_ih_entry_count (ih); i ++, deh ++) {
+ if (get_deh_location (deh) >= prev_location)
return 1;
- prev_location = deh_location (deh);
+ prev_location = get_deh_location (deh);
- namelen = name_length (ih, deh, i);
- if (namelen > REISERFS_MAX_NAME_LEN (fs->s_blocksize)) {
+ namelen = name_in_entry_length (ih, deh, i);
+ if (namelen > REISERFS_MAX_NAME_LEN (fs->fs_blocksize)) {
return 1;
}
- if (deh_offset (deh) <= prev_offset)
+ if (get_deh_offset (deh) <= prev_offset)
return 1;
- prev_offset = deh_offset (deh);
+ prev_offset = get_deh_offset (deh);
/* check hash value */
if (!is_properly_hashed (fs, item + prev_location, namelen, prev_offset)) {
@@ -569,25 +746,27 @@ static int is_bad_directory (reiserfs_filsys_t fs, struct item_head * ih, char *
return 0;
}
+
/* used by debugreisrefs -p only yet */
-#if 1
-int is_it_bad_item (reiserfs_filsys_t fs, struct item_head * ih, char * item,
+int is_it_bad_item (reiserfs_filsys_t * fs, struct item_head * ih, char * item,
check_unfm_func_t check_unfm, int bad_dir)
{
int retval;
- if (!is_key_correct (ih)) {
- reiserfs_warning (stderr, "is_key_correct %H\n", ih);
+/*
+ if (!does_key_look_correct (fs, &ih->ih_key))
return 1;
- }
- if (is_stat_data_ih (ih)) {
- retval = is_bad_sd (fs, ih, item);
- /*
- if (retval)
- reiserfs_warning (stderr, "is_bad_sd %H\n", ih);*/
- return retval;
- }
+ if (!does_ih_look_correct (ih))
+ return 1;
+*/
+ if (!does_ih_look_correct (ih))
+ return 1;
+
+
+ if (is_stat_data_ih (ih) || is_direct_ih (ih))
+ return 0;
+
if (is_direntry_ih (ih)) {
retval = is_bad_directory (fs, ih, item, bad_dir);
/*
@@ -602,17 +781,9 @@ int is_it_bad_item (reiserfs_filsys_t fs, struct item_head * ih, char * item,
reiserfs_warning (stderr, "is_bad_indirect %H\n", ih);*/
return retval;
}
- if (is_direct_ih (ih)) {
- retval = is_bad_direct (fs, ih, item);
- /*
- if (retval)
- reiserfs_warning (stderr, "is_bad_direct %H\n", ih);*/
- return retval;
- }
+
return 1;
}
-#endif
-
/* prepare new or old stat data for the new directory */
@@ -621,39 +792,41 @@ void make_dir_stat_data (int blocksize, int key_format,
struct item_head * ih, void * sd)
{
memset (ih, 0, IH_SIZE);
- ih->ih_key.k_dir_id = cpu_to_le32 (dirid);
- ih->ih_key.k_objectid = cpu_to_le32 (objectid);
- set_offset (key_format, &ih->ih_key, SD_OFFSET);
- set_type (key_format, &ih->ih_key, TYPE_STAT_DATA);
+ set_key_dirid (&ih->ih_key, dirid);
+ set_key_objectid (&ih->ih_key, objectid);
+ set_key_offset_v1 (&ih->ih_key, SD_OFFSET);
+ set_key_uniqueness (&ih->ih_key, 0);
- set_key_format (ih, key_format);
- set_free_space (ih, MAX_US_INT);
+ set_ih_key_format (ih, key_format);
+ set_ih_free_space (ih, MAX_US_INT);
- if (key_format == KEY_FORMAT_2)
- {
+
+ if (key_format == KEY_FORMAT_2) {
struct stat_data *sd_v2 = (struct stat_data *)sd;
set_ih_item_len (ih, SD_SIZE);
- sd_v2->sd_mode = cpu_to_le16 (S_IFDIR + 0755);
- sd_v2->sd_nlink = cpu_to_le32 (2);
- sd_v2->sd_uid = 0;
- sd_v2->sd_gid = 0;
- sd_v2->sd_size = cpu_to_le64 (EMPTY_DIR_SIZE);
- sd_v2->sd_atime = sd_v2->sd_ctime = sd_v2->sd_mtime = cpu_to_le32 (time (NULL));
- sd_v2->u.sd_rdev = 0;
- sd_v2->sd_blocks = cpu_to_le32 (dir_size2st_blocks (blocksize, EMPTY_DIR_SIZE));
+ set_sd_v2_mode (sd_v2, S_IFDIR + 0755);
+ set_sd_v2_nlink (sd_v2, 2);
+ set_sd_v2_uid (sd_v2, 0);
+ set_sd_v2_gid (sd_v2, 0);
+ set_sd_v2_size (sd_v2, EMPTY_DIR_SIZE);
+ set_sd_v2_atime (sd_v2, time(NULL));
+ sd_v2->sd_ctime = sd_v2->sd_mtime = sd_v2->sd_atime; /* all le */
+ set_sd_v2_rdev (sd_v2, 0);
+ set_sd_v2_blocks (sd_v2, dir_size2st_blocks (EMPTY_DIR_SIZE));
}else{
struct stat_data_v1 *sd_v1 = (struct stat_data_v1 *)sd;
set_ih_item_len (ih, SD_V1_SIZE);
- sd_v1->sd_mode = cpu_to_le16 (S_IFDIR + 0755);
- sd_v1->sd_nlink = cpu_to_le16 (2);
- sd_v1->sd_uid = 0;
- sd_v1->sd_gid = 0;
- sd_v1->sd_size = cpu_to_le32 (EMPTY_DIR_SIZE_V1);
- sd_v1->sd_atime = sd_v1->sd_ctime = sd_v1->sd_mtime = cpu_to_le32 (time (NULL));
- sd_v1->u.sd_blocks = cpu_to_le32 (dir_size2st_blocks (blocksize, EMPTY_DIR_SIZE_V1));
- sd_v1->sd_first_direct_byte = cpu_to_le32 (NO_BYTES_IN_DIRECT_ITEM);
+ set_sd_v1_mode(sd_v1, S_IFDIR + 0755);
+ set_sd_v1_nlink(sd_v1, 2);
+ set_sd_v1_uid (sd_v1, 0);
+ set_sd_v1_gid (sd_v1, 0);
+ set_sd_v1_size(sd_v1, EMPTY_DIR_SIZE_V1);
+ set_sd_v1_atime(sd_v1, time(NULL));
+ sd_v1->sd_ctime = sd_v1->sd_mtime = sd_v1->sd_atime; /* all le */
+ set_sd_v1_blocks(sd_v1, dir_size2st_blocks(EMPTY_DIR_SIZE_V1));
+ set_sd_v1_first_direct_byte(sd_v1, NO_BYTES_IN_DIRECT_ITEM);
}
}
@@ -662,36 +835,36 @@ static void _empty_dir_item (int format, char * body, __u32 dirid, __u32 objid,
__u32 par_dirid, __u32 par_objid)
{
struct reiserfs_de_head * deh;
+ __u16 state;
memset (body, 0, (format == KEY_FORMAT_2 ? EMPTY_DIR_SIZE : EMPTY_DIR_SIZE_V1));
deh = (struct reiserfs_de_head *)body;
/* direntry header of "." */
- deh[0].deh_offset = cpu_to_le32 (DOT_OFFSET);
- deh[0].deh_dir_id = cpu_to_le32 (dirid);
- deh[0].deh_objectid = cpu_to_le32 (objid);
- deh[0].deh_state = 0;
- set_bit (DEH_Visible, &(deh[0].deh_state));
-
+ set_deh_offset (deh, DOT_OFFSET);
+ set_deh_dirid (deh, dirid);
+ set_deh_objectid (deh, objid);
+ state = (1 << DEH_Visible2);
+ set_deh_state (deh, state);
+
/* direntry header of ".." */
- deh[1].deh_offset = cpu_to_le32 (DOT_DOT_OFFSET);
+ set_deh_offset (deh + 1, DOT_DOT_OFFSET);
/* key of ".." for the root directory */
- deh[1].deh_dir_id = cpu_to_le32 (par_dirid);
- deh[1].deh_objectid = cpu_to_le32 (par_objid);
- deh[1].deh_state = 0;
- set_bit (DEH_Visible, &(deh[1].deh_state));
+ set_deh_dirid (deh + 1, par_dirid);
+ set_deh_objectid (deh + 1, par_objid);
+ set_deh_state (deh + 1, state);
if (format == KEY_FORMAT_2) {
- deh[0].deh_location = cpu_to_le16 (EMPTY_DIR_SIZE - ROUND_UP (strlen (".")));
- deh[1].deh_location = cpu_to_le16 (deh_location (&deh[0]) - ROUND_UP (strlen ("..")));
+ set_deh_location (deh, EMPTY_DIR_SIZE - ROUND_UP (strlen (".")));
+ set_deh_location (deh + 1, get_deh_location (deh) - ROUND_UP (strlen ("..")));
} else {
- deh[0].deh_location = cpu_to_le16 (EMPTY_DIR_SIZE_V1 - strlen ("."));
- deh[1].deh_location = cpu_to_le16 (deh_location (&deh[0]) - strlen (".."));
+ set_deh_location (deh, EMPTY_DIR_SIZE_V1 - strlen ("."));
+ set_deh_location (deh + 1, get_deh_location (deh) - strlen (".."));
}
/* copy ".." and "." */
- memcpy (body + deh_location (&deh[0]), ".", 1);
- memcpy (body + deh_location (&deh[1]), "..", 2);
+ memcpy (body + get_deh_location (deh), ".", 1);
+ memcpy (body + get_deh_location (deh + 1), "..", 2);
}
@@ -721,7 +894,7 @@ void for_every_item (struct buffer_head * bh, item_head_action_t action,
item_action_t iaction;
ih = B_N_PITEM_HEAD (bh, 0);
- for (i = 0; i < node_item_number (bh); i ++, ih ++) {
+ for (i = 0; i < get_blkh_nr_items (B_BLK_HEAD (bh)); i ++, ih ++) {
if (action)
action (ih);
@@ -731,6 +904,60 @@ void for_every_item (struct buffer_head * bh, item_head_action_t action,
}
}
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+# define get_key_offset_v2(key) (__u64)((key->u.k2_offset_v2.k_offset))
+# define set_key_offset_v2(key,val) (void)(key->u.k2_offset_v2.k_offset = (val))
+# define get_key_type_v2(key) (__u16)((key->u.k2_offset_v2.k_type))
+# define set_key_type_v2(key,val) (void)(key->u.k2_offset_v2.k_type = (val))
+#elif __BYTE_ORDER == __BIG_ENDIAN
+typedef union {
+ struct offset_v2 offset_v2;
+ __u64 linear;
+} __attribute__ ((__packed__)) offset_v2_esafe_overlay;
+
+static inline __u64 get_key_offset_v2 (const struct key *key)
+{
+ offset_v2_esafe_overlay tmp =
+ *(offset_v2_esafe_overlay *) (&(key->u.k2_offset_v2));
+ tmp.linear = le64_to_cpu( tmp.linear );
+ return tmp.offset_v2.k_offset;
+}
+
+static inline __u32 get_key_type_v2 (const struct key *key)
+{
+ offset_v2_esafe_overlay tmp =
+ *(offset_v2_esafe_overlay *) (&(key->u.k2_offset_v2));
+ tmp.linear = le64_to_cpu( tmp.linear );
+ return tmp.offset_v2.k_type;
+}
+
+static inline void set_key_offset_v2 (struct key *key, __u64 offset)
+{
+ offset_v2_esafe_overlay *tmp =
+ (offset_v2_esafe_overlay *)(&(key->u.k2_offset_v2));
+ tmp->linear = le64_to_cpu(tmp->linear);
+ tmp->offset_v2.k_offset = offset;
+ tmp->linear = cpu_to_le64(tmp->linear);
+}
+
+static inline void set_key_type_v2 (struct key *key, __u32 type)
+{
+ offset_v2_esafe_overlay *tmp =
+ (offset_v2_esafe_overlay *)(&(key->u.k2_offset_v2));
+ if (type > 15)
+ reiserfs_panic ("set_key_type_v2: type is too big %d", type);
+
+ tmp->linear = le64_to_cpu(tmp->linear);
+ tmp->offset_v2.k_type = type;
+ tmp->linear = cpu_to_le64(tmp->linear);
+}
+#else
+# error "nuxi/pdp-endian archs are not supported"
+#endif
+
+static inline int is_key_format_1 (int type) {
+ return ( (type == 0 || type == 15) ? 1 : 0);
+}
/* old keys (on i386) have k_offset_v2.k_type == 15 (direct and
indirect) or == 0 (dir items and stat data) */
@@ -740,9 +967,9 @@ int key_format (const struct key * key)
{
int type;
- type = le16_to_cpu (key->u.k_offset_v2.k_type);
+ type = get_key_type_v2 (key);
- if (type == 0 || type == 15)
+ if (is_key_format_1 (type))
return KEY_FORMAT_1;
return KEY_FORMAT_2;
@@ -752,9 +979,9 @@ int key_format (const struct key * key)
loff_t get_offset (const struct key * key)
{
if (key_format (key) == KEY_FORMAT_1)
- return le32_to_cpu (key->u.k_offset_v1.k_offset);
+ return get_key_offset_v1 (key);
- return le64_to_cpu (key->u.k_offset_v2.k_offset);
+ return get_key_offset_v2 (key);
}
@@ -784,9 +1011,12 @@ __u32 type2uniqueness (int type)
int get_type (const struct key * key)
{
- if (key_format (key) == KEY_FORMAT_1)
- return uniqueness2type (le32_to_cpu (key->u.k_offset_v1.k_uniqueness));
- return le16_to_cpu (key->u.k_offset_v2.k_type);
+ int type_v2 = get_key_type_v2 (key);
+
+ if (is_key_format_1 (type_v2))
+ return uniqueness2type (get_key_uniqueness (key));
+
+ return type_v2;
}
@@ -824,9 +1054,9 @@ int type_unknown (struct key * key)
void set_type (int format, struct key * key, int type)
{
if (format == KEY_FORMAT_1)
- key->u.k_offset_v1.k_uniqueness = cpu_to_le32 (type2uniqueness (type));
+ set_key_uniqueness (key, type2uniqueness (type));
else
- key->u.k_offset_v2.k_type = cpu_to_le16 (type);
+ set_key_type_v2 (key, type);
}
@@ -834,9 +1064,9 @@ void set_type (int format, struct key * key, int type)
void set_offset (int format, struct key * key, loff_t offset)
{
if (format == KEY_FORMAT_1)
- key->u.k_offset_v1.k_offset = cpu_to_le32 (offset);
+ set_key_offset_v1 (key, offset);
else
- key->u.k_offset_v2.k_offset = cpu_to_le64 (offset);
+ set_key_offset_v2 (key, offset);
}
@@ -859,18 +1089,17 @@ void set_type_and_offset (int format, struct key * key, loff_t offset, int type)
int entry_length (struct item_head * ih, struct reiserfs_de_head * deh, int pos_in_item)
{
if (pos_in_item)
- return (deh_location (deh - 1) - deh_location (deh));
- return (ih_item_len (ih) - deh_location (deh));
+ return (get_deh_location (deh - 1) - get_deh_location (deh));
+ return (get_ih_item_len (ih) - get_deh_location (deh));
}
char * name_in_entry (struct reiserfs_de_head * deh, int pos_in_item)
{
- return ((char *)(deh - pos_in_item) + deh_location(deh));
+ return ((char *)(deh - pos_in_item) + get_deh_location(deh));
}
-
-int name_length (struct item_head * ih,
+int name_in_entry_length (struct item_head * ih,
struct reiserfs_de_head * deh, int pos_in_item)
{
int len;
@@ -880,8 +1109,247 @@ int name_length (struct item_head * ih,
name = name_in_entry (deh, pos_in_item);
// name might be padded with 0s
- while (!name [len - 1])
+ while (!name [len - 1] && len > 0)
len --;
return len;
}
+
+int name_length (char * name, int key_format)
+{
+ if (key_format == KEY_FORMAT_2)
+ return ROUND_UP (strlen(name));
+ else if (key_format == KEY_FORMAT_1)
+ return strlen(name);
+
+ return -1;
+}
+
+/* key format is stored in 12 bits starting from 0-th of item_head's ih2_format*/
+__u16 get_ih_key_format (const struct item_head * ih)
+{
+ get_bit_field_XX (16, &ih->ih_format, 0, 12);
+}
+
+
+__u16 get_ih_flags (const struct item_head * ih)
+{
+ get_bit_field_XX (16, &ih->ih_format, 12, 4);
+}
+
+
+void set_ih_key_format (struct item_head * ih, __u16 val)
+{
+ set_bit_field_XX (16, &ih->ih_format, val, 0, 12);
+}
+
+
+void set_ih_flags (struct item_head * ih, __u16 val)
+{
+ set_bit_field_XX (16, &ih->ih_format, val, 12, 4);
+}
+
+
+
+/* access to fields of stat data (both v1 and v2) */
+
+void get_set_sd_field (int field, struct item_head * ih, void * sd,
+ void * value, int set)
+{
+ if (get_ih_key_format (ih) == KEY_FORMAT_1) {
+ struct stat_data_v1 * sd_v1 = sd;
+
+ switch (field) {
+ case GET_SD_MODE:
+ if (set)
+ sd_v1->sd_mode = cpu_to_le16 (*(__u16 *)value);
+ else
+ *(__u16 *)value = le16_to_cpu (sd_v1->sd_mode);
+ break;
+
+ case GET_SD_SIZE:
+ /* value must point to 64 bit int */
+ if (set)
+ sd_v1->sd_size = cpu_to_le32 (*(__u64 *)value);
+ else
+ *(__u64 *)value = le32_to_cpu (sd_v1->sd_size);
+ break;
+
+ case GET_SD_BLOCKS:
+ if (set)
+ sd_v1->u.sd_blocks = cpu_to_le32 (*(__u32 *)value);
+ else
+ *(__u32 *)value = le32_to_cpu (sd_v1->u.sd_blocks);
+ break;
+
+ case GET_SD_NLINK:
+ /* value must point to 32 bit int */
+ if (set)
+ sd_v1->sd_nlink = cpu_to_le16 (*(__u32 *)value);
+ else
+ *(__u32 *)value = le16_to_cpu (sd_v1->sd_nlink);
+ break;
+
+ case GET_SD_FIRST_DIRECT_BYTE:
+ if (set)
+ sd_v1->sd_first_direct_byte = cpu_to_le32 (*(__u32 *)value);
+ else
+ *(__u32 *)value = le32_to_cpu (sd_v1->sd_first_direct_byte);
+ break;
+
+ default:
+ reiserfs_panic ("get_set_sd_field: unknown field of old stat data");
+ }
+ } else {
+ struct stat_data * sd_v2 = sd;
+
+ switch (field) {
+ case GET_SD_MODE:
+ if (set)
+ sd_v2->sd_mode = cpu_to_le16 (*(__u16 *)value);
+ else
+ *(__u16 *)value = le16_to_cpu (sd_v2->sd_mode);
+ break;
+
+ case GET_SD_SIZE:
+ if (set)
+ sd_v2->sd_size = cpu_to_le64 (*(__u64 *)value);
+ else
+ *(__u64 *)value = le64_to_cpu (sd_v2->sd_size);
+ break;
+
+ case GET_SD_BLOCKS:
+ if (set)
+ sd_v2->sd_blocks = cpu_to_le32 (*(__u32 *)value);
+ else
+ *(__u32 *)value = le32_to_cpu (sd_v2->sd_blocks);
+ break;
+
+ case GET_SD_NLINK:
+ if (set)
+ sd_v2->sd_nlink = cpu_to_le32 (*(__u32 *)value);
+ else
+ *(__u32 *)value = le32_to_cpu (sd_v2->sd_nlink);
+ break;
+
+ case GET_SD_FIRST_DIRECT_BYTE:
+ default:
+ reiserfs_panic ("get_set_sd_field: unknown field of new stat data");
+ }
+ }
+}
+
+int comp_ids (const void * p1, const void * p2)
+{
+ __u32 id1 = le32_to_cpu(*(__u32 *)p1) ;
+ __u32 id2 = le32_to_cpu(*(__u32 *)p2) ;
+
+ if (id1 < id2)
+ return -1;
+ if (id1 > id2)
+ return 1 ;
+ return 0 ;
+}
+
+/* functions to manipulate with super block's objectid map */
+
+int is_objectid_used (reiserfs_filsys_t * fs, __u32 objectid)
+{
+ __u32 * objectid_map;
+ __u32 count = get_sb_oid_cursize(fs->fs_ondisk_sb);
+ int ret;
+ __u32 pos;
+ __u32 le_id = cpu_to_le32(objectid);
+
+
+ objectid_map = (__u32 *)((char *)fs->fs_ondisk_sb + reiserfs_super_block_size (fs->fs_ondisk_sb));
+
+ ret = reiserfs_bin_search(&le_id, objectid_map, count, sizeof(__u32), &pos, comp_ids);
+
+ /* if the position returned is odd, the oid is in use */
+ if (ret == POSITION_NOT_FOUND)
+ return (pos & 1) ;
+
+ /* if the position returned is even, the oid is in use */
+ return !(pos & 1) ;
+}
+
+
+void mark_objectid_used (reiserfs_filsys_t * fs, __u32 objectid)
+{
+ int i;
+ __u32 * objectid_map;
+ int cursize;
+
+
+ if (is_objectid_used (fs, objectid)) {
+ return;
+ }
+
+ objectid_map = (__u32 *)((char *)fs->fs_ondisk_sb + reiserfs_super_block_size (fs->fs_ondisk_sb));
+ cursize = get_sb_oid_cursize (fs->fs_ondisk_sb);
+
+ for (i = 0; i < cursize; i += 2) {
+ if (objectid >= le32_to_cpu (objectid_map [i]) &&
+ objectid < le32_to_cpu (objectid_map [i + 1]))
+ /* it is used */
+ return;
+
+ if (objectid + 1 == le32_to_cpu (objectid_map[i])) {
+ /* size of objectid map does not change */
+ objectid_map[i] = cpu_to_le32 (objectid);
+ return;
+ }
+
+ if (objectid == le32_to_cpu (objectid_map[i + 1])) {
+ /* size of objectid map is decreased */
+ objectid_map [i + 1] = cpu_to_le32 (le32_to_cpu (objectid_map [i + 1]) + 1);
+
+ if (i + 2 < cursize) {
+ if (objectid_map[i + 1] == objectid_map[i + 2]) {
+ memmove (objectid_map + i + 1, objectid_map + i + 1 + 2,
+ (cursize - (i + 2 + 2 - 1)) * sizeof (__u32));
+ set_sb_oid_cursize (fs->fs_ondisk_sb, cursize - 2);
+ }
+ }
+ return;
+ }
+
+ if (objectid < le32_to_cpu (objectid_map[i])) {
+ /* size of objectid map must be increased */
+ if (cursize == get_sb_oid_maxsize (fs->fs_ondisk_sb)) {
+ /* here all objectids between objectid and objectid_map[i] get
+ used */
+ objectid_map[i] = cpu_to_le32 (objectid);
+ return;
+ } else {
+ memmove (objectid_map + i + 2, objectid_map + i, (cursize - i) * sizeof (__u32));
+ set_sb_oid_cursize (fs->fs_ondisk_sb, cursize + 2);
+ }
+
+ objectid_map[i] = cpu_to_le32 (objectid);
+ objectid_map[i+1] = cpu_to_le32 (objectid + 1);
+ return;
+ }
+
+ }
+
+ /* append to current objectid map, if we have space */
+ if (i < get_sb_oid_maxsize (fs->fs_ondisk_sb)) {
+ objectid_map[i] = cpu_to_le32 (objectid);
+ objectid_map[i + 1] = cpu_to_le32 (objectid + 1);
+ set_sb_oid_cursize (fs->fs_ondisk_sb, cursize + 2);
+ } else if (i == get_sb_oid_maxsize (fs->fs_ondisk_sb)) {
+ objectid_map[i - 1] = cpu_to_le32 (objectid + 1);
+ } else
+ die ("mark_objectid_as_used: objectid map corrupted");
+
+ return;
+}
+
+
+int is_blocksize_correct (int blocksize)
+{
+ return ((blocksize % 1024) ? 0 : 1);
+}
+
diff --git a/reiserfscore/prints.c b/reiserfscore/prints.c
index 70acc7b..13a7c91 100644
--- a/reiserfscore/prints.c
+++ b/reiserfscore/prints.c
@@ -37,7 +37,7 @@ static int _arginfo2 (const struct printf_info *info, size_t n,
return len;\
-/* %z */
+/* %b */
static int print_block_head (FILE * stream,
const struct printf_info *info,
const void *const *args)
@@ -48,7 +48,7 @@ static int print_block_head (FILE * stream,
bh = *((const struct buffer_head **)(args[0]));
len = asprintf (&buffer, "level=%d, nr_items=%d, free_space=%d rdkey",
- B_LEVEL (bh), B_NR_ITEMS (bh), node_free_space (bh));
+ B_LEVEL (bh), B_NR_ITEMS (bh), B_FREE_SPACE (bh));
FPRINTF;
}
@@ -63,7 +63,8 @@ static int print_short_key (FILE * stream,
int len;
key = *((const struct key **)(args[0]));
- len = asprintf (&buffer, "%u %u", key->k_dir_id, key->k_objectid);
+ len = asprintf (&buffer, "%u %u", get_key_dirid (key),
+ get_key_objectid (key));
FPRINTF;
}
@@ -78,8 +79,9 @@ static int print_key (FILE * stream,
int len;
key = *((const struct key **)(args[0]));
- len = asprintf (&buffer, "%u %u 0x%Lx %s",
- key->k_dir_id, key->k_objectid, get_offset (key), key_of_what (key));
+ len = asprintf (&buffer, "%u %u 0x%Lx %s (%d)",
+ get_key_dirid (key), get_key_objectid (key),
+ (unsigned long long)get_offset (key), key_of_what (key), get_type (key));
FPRINTF;
}
@@ -94,14 +96,14 @@ static int print_item_head (FILE * stream,
int len;
ih = *((const struct item_head **)(args[0]));
- len = asprintf (&buffer, "%u %u 0x%Lx %s, "
- "len %u, entry count %u, fsck need %u, format %s",
- ih->ih_key.k_dir_id, ih->ih_key.k_objectid,
- get_offset (&ih->ih_key), key_of_what (&ih->ih_key),
- ih->ih_item_len, ih_entry_count (ih),
- ih->ih_format.fsck_need,
- ih_key_format (ih) == KEY_FORMAT_2 ? "new" :
- ((ih_key_format (ih) == KEY_FORMAT_1) ? "old" : "BAD"));
+ len = asprintf (&buffer, "%u %u 0x%Lx %s (%d), "
+ "len %u, location %u entry count %u, fsck need %u, format %s",
+ get_key_dirid (&ih->ih_key), get_key_objectid (&ih->ih_key),
+ (unsigned long long)get_offset (&ih->ih_key), key_of_what (&ih->ih_key),
+ get_type (&ih->ih_key), get_ih_item_len (ih), get_ih_location (ih),
+ get_ih_entry_count (ih), get_ih_flags (ih),
+ get_ih_key_format (ih) == KEY_FORMAT_2 ? "new" :
+ ((get_ih_key_format (ih) == KEY_FORMAT_1) ? "old" : "BAD"));
FPRINTF;
}
@@ -115,8 +117,8 @@ static int print_disk_child (FILE * stream,
int len;
dc = *((const struct disk_child **)(args[0]));
- len = asprintf (&buffer, "[dc_number=%u, dc_size=%u]", le32_to_cpu (dc->dc_block_number),
- le16_to_cpu (dc->dc_size));
+ len = asprintf (&buffer, "[dc_number=%u, dc_size=%u]", get_dc_child_blocknr (dc),
+ get_dc_child_size (dc));
FPRINTF;
}
@@ -156,7 +158,7 @@ static int print_sd_mode (FILE * stream,
const void *const *args)
{
int len = 0;
- mode_t mode;
+ __u16 mode;
mode = *(mode_t *)args[0];
len = fprintf (stream, "%c", ftypelet (mode));
@@ -166,7 +168,23 @@ static int print_sd_mode (FILE * stream,
return len;
}
-
+/* %U */
+static int print_sd_uuid (FILE * stream,
+ const struct printf_info *info,
+ const void *const *args)
+{
+ int i;
+ const unsigned char * uuid;
+ int len = 0;
+
+ uuid = *((const unsigned char **)(args[0]));
+ for (i = 0; i < 16; i++) {
+ if (i == 4 || i == 6 || i == 8 || i == 10)
+ len += fprintf (stream, "-");
+ len += fprintf(stream, "%02x", uuid[i]);
+ }
+ return len;
+}
void reiserfs_warning (FILE * fp, const char * fmt, ...)
{
@@ -182,6 +200,7 @@ void reiserfs_warning (FILE * fp, const char * fmt, ...)
register_printf_function ('b', print_block_head, _arginfo);
register_printf_function ('y', print_disk_child, _arginfo);
register_printf_function ('M', print_sd_mode, _arginfo);
+ register_printf_function ('U', print_sd_uuid, _arginfo);
}
va_start (args, fmt);
@@ -249,35 +268,8 @@ void print_path (struct tree_balance * tb, struct path * path)
}
-#if 0
-void print_de (struct reiserfs_dir_entry * de)
-{
- reiserfs_warning ("entry key: [%k], object_key: [%u %u], b_blocknr=%lu, item_num=%d, pos_in_item=%d\n",
- &de->de_entry_key, de->de_dir_id, de->de_objectid,
- de->de_bh->b_blocknr, de->de_item_num, de->de_entry_num);
-}
-
-static char * item_type (struct item_head * ih)
-{
- static char * types[] = {
- "SD", "DIR", "DRCT", "IND", "???"
- };
-
- if (I_IS_STAT_DATA_ITEM(ih))
- return types[0];
- if (I_IS_DIRECTORY_ITEM(ih))
- return types[1];
- if (I_IS_DIRECT_ITEM(ih))
- return types[2];
- if (I_IS_INDIRECT_ITEM(ih))
- return types[3];
- return types[4];
-}
-
-#endif
-
-void print_directory_item (FILE * fp, reiserfs_filsys_t fs,
+void print_directory_item (FILE * fp, reiserfs_filsys_t * fs,
struct buffer_head * bh, struct item_head * ih)
{
int i;
@@ -292,10 +284,10 @@ void print_directory_item (FILE * fp, reiserfs_filsys_t fs,
//printk ("\n%2%-25s%-30s%-15s%-15s%-15s\n", " Name", "length", "Object key", "Hash", "Gen number", "Status");
reiserfs_warning (fp, "%3s: %-25s%s%-22s%-12s%s\n", "###", "Name", "length", " Object key", " Hash", "Gen number");
deh = B_I_DEH (bh, ih);
- for (i = 0; i < ih_entry_count (ih); i ++, deh ++) {
+ for (i = 0; i < get_ih_entry_count (ih); i ++, deh ++) {
if (dir_entry_bad_location (deh, ih, i == 0 ? 1 : 0)) {
reiserfs_warning (fp, "%3d: wrong entry location %u, deh_offset %u\n",
- i, deh_location (deh), deh_offset (deh));
+ i, get_deh_location (deh), get_deh_offset (deh));
continue;
}
if (i && dir_entry_bad_location (deh - 1, ih, ((i - 1) == 0) ? 1 : 0))
@@ -303,15 +295,19 @@ void print_directory_item (FILE * fp, reiserfs_filsys_t fs,
length */
namelen = 25;
else
- namelen = name_length (ih, deh, i);
+ namelen = name_in_entry_length (ih, deh, i);
name = name_in_entry (deh, i);
reiserfs_warning (fp, "%3d: \"%-25.*s\"(%3d)%20K%12d%5d, loc %u, state %x %s\n",
i, namelen, name, namelen,
- (struct key *)&(deh->deh_dir_id),
- GET_HASH_VALUE (deh->deh_offset), GET_GENERATION_NUMBER (deh->deh_offset),
- deh_location (deh), deh->deh_state,
- fs ? (is_properly_hashed (fs, name, namelen, deh_offset (deh)) ? "" : "(BROKEN)") : "??");
+ (struct key *)&(deh->deh2_dir_id),
+ GET_HASH_VALUE (get_deh_offset (deh)),
+ GET_GENERATION_NUMBER (get_deh_offset (deh)),
+ get_deh_location (deh), get_deh_state (deh),
+ code2name (find_hash_in_use (name, namelen,
+ GET_HASH_VALUE (get_deh_offset (deh)),
+ fs ? get_sb_hash_code (fs->fs_ondisk_sb) : UNSET_HASH)));
+ /*fs ? (is_properly_hashed (fs, name, namelen, deh_offset (deh)) ? "" : "(BROKEN)") : "??");*/
}
}
@@ -328,14 +324,14 @@ static void start_new_sequence (__u32 * start, int * len, __u32 new)
static int sequence_finished (__u32 start, int * len, __u32 new)
{
- if (start == INT_MAX)
+ if (le32_to_cpu (start) == INT_MAX)
return 1;
if (start == 0 && new == 0) {
(*len) ++;
return 0;
}
- if (start != 0 && (start + *len) == new) {
+ if (start != 0 && (le32_to_cpu (start) + *len) == le32_to_cpu (new)) {
(*len) ++;
return 0;
}
@@ -348,9 +344,9 @@ static void print_sequence (FILE * fp, __u32 start, int len)
return;
if (len == 1)
- reiserfs_warning (fp, " %d", start);
+ reiserfs_warning (fp, " %d", le32_to_cpu (start));
else
- reiserfs_warning (fp, " %d(%d)", start, len);
+ reiserfs_warning (fp, " %d(%d)", le32_to_cpu (start), len);
}
@@ -364,10 +360,11 @@ void print_indirect_item (FILE * fp, struct buffer_head * bh, int item_num)
ih = B_N_PITEM_HEAD (bh, item_num);
unp = (__u32 *)B_I_PITEM (bh, ih);
- if (ih->ih_item_len % UNFM_P_SIZE)
+ if (get_ih_item_len (ih) % UNFM_P_SIZE)
reiserfs_warning (fp, "print_indirect_item: invalid item len");
- reiserfs_warning (fp, "%d pointers\n[ ", I_UNFM_NUM (ih));
+ reiserfs_warning (fp, "%d pointer%s\n[", I_UNFM_NUM (ih),
+ I_UNFM_NUM (ih) != 1 ? "s" : "" );
for (j = 0; j < I_UNFM_NUM (ih); j ++) {
if (sequence_finished (prev, &num, unp[j])) {
print_sequence (fp, prev, num);
@@ -389,32 +386,61 @@ char * timestamp (time_t t)
static int print_stat_data (FILE * fp, struct buffer_head * bh, struct item_head * ih, int alltimes)
{
- struct stat_data * sd = (struct stat_data *)B_I_PITEM (bh, ih);
- struct stat_data_v1 * sd_v1 = (struct stat_data_v1 *)B_I_PITEM (bh, ih);
int retval;
/* we can not figure out whether it is new stat data or old by key_format
macro. Stat data's key looks identical in both formats */
- if (ih_key_format (ih) == KEY_FORMAT_1) {
- reiserfs_warning (fp, "(OLD SD), mode %M, size %u, nlink %u, uid %d, FDB %d, mtime %s blocks %d",
- sd_v1->sd_mode, sd_v1->sd_size, sd_v1->sd_nlink, sd_v1->sd_uid,
- sd_v1->sd_first_direct_byte, timestamp (sd_v1->sd_mtime), sd_v1->u.sd_blocks);
- retval = (S_ISLNK (sd_v1->sd_mode)) ? 1 : 0;
+ if (get_ih_key_format (ih) == KEY_FORMAT_1) {
+ struct stat_data_v1 * sd_v1 = (struct stat_data_v1 *)B_I_PITEM (bh, ih);
+ reiserfs_warning (fp, "(OLD SD), mode %M, size %u, nlink %u, uid %u, FDB %u, mtime %s blocks %u",
+ sd_v1_mode(sd_v1), sd_v1_size(sd_v1), sd_v1_nlink(sd_v1),
+ sd_v1_uid(sd_v1), sd_v1_first_direct_byte(sd_v1), timestamp
+ (sd_v1_mtime(sd_v1)), sd_v1_blocks(sd_v1));
+ retval = (S_ISLNK (sd_v1_mode(sd_v1))) ? 1 : 0;
+ if (alltimes)
+ reiserfs_warning (fp, "%s %s\n", timestamp (sd_v1_ctime(sd_v1)),
+ timestamp (sd_v1_atime(sd_v1)));
} else {
- reiserfs_warning (fp, "(NEW SD), mode %M, size %Lu, nlink %u, mtime %s blocks %d",
- sd->sd_mode, sd->sd_size, sd->sd_nlink,
- timestamp (sd->sd_mtime), sd->sd_blocks);
- retval = (S_ISLNK (sd->sd_mode)) ? 1 : 0;
+ struct stat_data * sd = (struct stat_data *)B_I_PITEM (bh, ih);
+ reiserfs_warning (fp, "(NEW SD), mode %M, size %Lu, nlink %u, mtime %s blocks %u, uid %u",
+ sd_v2_mode(sd), sd_v2_size(sd), sd_v2_nlink(sd),
+ timestamp (sd_v2_mtime(sd)), sd_v2_blocks(sd), sd_v2_uid(sd));
+ retval = (S_ISLNK (sd_v2_mode(sd))) ? 1 : 0;
+ if (alltimes)
+ reiserfs_warning (fp, "%s %s\n", timestamp (sd_v2_ctime(sd)),
+ timestamp (sd_v2_atime(sd)));
}
- if (alltimes)
- reiserfs_warning (fp, "%s %s\n", timestamp (sd->sd_ctime), timestamp (sd->sd_atime));
reiserfs_warning (fp, "\n");
return retval;
}
+/* used by debugreiserfs/scan.c */
+void reiserfs_print_item (FILE * fp, struct buffer_head * bh,
+ struct item_head * ih)
+{
+ reiserfs_warning (stdout, "block %lu, item %d: %H\n",
+ bh->b_blocknr, ih - B_N_PITEM_HEAD (bh, 0), ih);
+ if (is_stat_data_ih (ih)) {
+ print_stat_data (fp, bh, ih, 0/*all times*/);
+ return;
+ }
+ if (is_indirect_ih (ih)) {
+ print_indirect_item (fp, bh, ih - B_N_PITEM_HEAD (bh, 0));
+ return;
+ }
+ if (is_direct_ih (ih)) {
+ reiserfs_warning (fp, "direct item: block %lu, start %d, %d bytes\n",
+ bh->b_blocknr, get_ih_location (ih), get_ih_item_len (ih));
+ return;
+ }
+
+ print_directory_item (fp, 0, bh, ih);
+}
+
+
/* this prints internal nodes (4 keys/items in line) (dc_number,
dc_size)[k_dirid, k_objectid, k_offset, k_uniqueness](dc_number,
dc_size)...*/
@@ -453,36 +479,41 @@ static int print_internal (FILE * fp, struct buffer_head * bh, int first, int la
static int is_symlink = 0;
-static int print_leaf (FILE * fp, reiserfs_filsys_t fs, struct buffer_head * bh,
+static int print_leaf (FILE * fp, reiserfs_filsys_t * fs, struct buffer_head * bh,
int print_mode, int first, int last)
{
struct block_head * blkh;
struct item_head * ih;
int i;
int from, to;
+ int nr;
- if (!is_leaf_node (bh))
+ if (!is_tree_node (bh, DISK_LEAF_NODE_LEVEL))
return 1;
+
blkh = B_BLK_HEAD (bh);
ih = B_N_PITEM_HEAD (bh,0);
+ nr = get_blkh_nr_items (blkh);
- reiserfs_warning (fp, "\n===================================================================\n");
- reiserfs_warning (fp, "LEAF NODE (%ld) contains %b\n", bh->b_blocknr, bh);
+ reiserfs_warning (fp,
+ "\n===================================================================\n");
+ reiserfs_warning (fp, "LEAF NODE (%ld) contains %b (real items %d)\n",
+ bh->b_blocknr, bh, nr);
- if (!(print_mode & PRINT_LEAF_ITEMS)) {
+ if (!(print_mode & PRINT_TREE_DETAILS)) {
reiserfs_warning (fp, "FIRST ITEM_KEY: %k, LAST ITEM KEY: %k\n",
- &(ih->ih_key), &((ih + blkh->blk_nr_item - 1)->ih_key));
+ &(ih->ih_key), &((ih + get_blkh_nr_items (blkh) - 1)->ih_key));
return 0;
}
- if (first < 0 || first > blkh->blk_nr_item - 1)
+ if (first < 0 || first > nr - 1)
from = 0;
else
from = first;
- if (last < 0 || last > blkh->blk_nr_item)
- to = blkh->blk_nr_item;
+ if (last < 0 || last > nr)
+ to = nr;
else
to = last;
@@ -493,20 +524,20 @@ static int print_leaf (FILE * fp, reiserfs_filsys_t fs, struct buffer_head * bh,
"| | | |e/cn| | |need| |\n");
for (i = from; i < to; i++) {
reiserfs_warning (fp,
- "-------------------------------------------------------------------------------\n"
+ "-------------------------------------------------------------------------------\n"
"|%3d|%30H|\n", i, ih + i);
- if (I_IS_STAT_DATA_ITEM(ih+i) && print_mode & PRINT_ITEM_DETAILS) {
+ if (I_IS_STAT_DATA_ITEM(ih+i)) {
is_symlink = print_stat_data (fp, bh, ih + i, 0/*all times*/);
continue;
}
- if (I_IS_DIRECTORY_ITEM(ih+i) && print_mode & PRINT_ITEM_DETAILS) {
+ if (I_IS_DIRECTORY_ITEM(ih+i)) {
print_directory_item (fp, fs, bh, ih+i);
continue;
}
- if (I_IS_INDIRECT_ITEM(ih+i) && print_mode & PRINT_ITEM_DETAILS) {
+ if (I_IS_INDIRECT_ITEM(ih+i)) {
print_indirect_item (fp, bh, i);
continue;
}
@@ -515,7 +546,7 @@ static int print_leaf (FILE * fp, reiserfs_filsys_t fs, struct buffer_head * bh,
int j = 0;
if (is_symlink || print_mode & PRINT_DIRECT_ITEMS) {
reiserfs_warning (fp, "\"");
- while (j < ih[i].ih_item_len) {
+ while (j < get_ih_item_len (&ih[i])) {
if (B_I_PITEM(bh,ih+i)[j] == 10)
reiserfs_warning (fp, "\\n");
else
@@ -532,84 +563,121 @@ static int print_leaf (FILE * fp, reiserfs_filsys_t fs, struct buffer_head * bh,
}
+void print_journal_params (FILE * fp, struct journal_params * jp)
+{
+ reiserfs_warning (fp, "\tDevice [0x%x]\n", get_jp_journal_dev (jp));
+ reiserfs_warning (fp, "\tMagic [0x%x]\n", get_jp_journal_magic (jp));
+
+ reiserfs_warning (fp, "\tSize %u blocks (including 1 for journal header) (first block %u)\n",
+ get_jp_journal_size (jp) + 1,
+ get_jp_journal_1st_block (jp));
+ reiserfs_warning (fp, "\tMax transaction length %u blocks\n", get_jp_journal_max_trans_len (jp));
+ reiserfs_warning (fp, "\tMax batch size %u blocks\n", get_jp_journal_max_batch (jp));
+ reiserfs_warning (fp, "\tMax commit age %u\n", get_jp_journal_max_commit_age (jp));
+ /*reiserfs_warning (fp, "\tMax transaction age %u\n", get_jp_journal_max_trans_age (jp));*/
+}
/* return 1 if this is not super block */
-static int print_super_block (FILE * fp, struct buffer_head * bh)
+int print_super_block (FILE * fp, reiserfs_filsys_t * fs, char * file_name,
+ struct buffer_head * bh, int short_print)
{
- struct reiserfs_super_block * rs = (struct reiserfs_super_block *)(bh->b_data);
- int skipped, data_blocks;
-
- if (is_reiser2fs_magic_string (rs))
- reiserfs_warning (fp, "Super block of format 3.6 found on the 0x%x in block %ld\n",
- bh->b_dev, bh->b_blocknr);
- else if (is_reiserfs_magic_string (rs))
- reiserfs_warning (fp, "Super block of format 3.5 found on the 0x%x in block %ld\n",
- bh->b_dev, bh->b_blocknr);
- else if (is_prejournaled_reiserfs (rs)) {
- reiserfs_warning (fp, "Prejournaled reiserfs super block found. Not supported here. Use proper tools instead\n");
- return 1;
- } else
- // no reiserfs signature found in the block
+ struct reiserfs_super_block * sb = (struct reiserfs_super_block *)(bh->b_data);
+ dev_t rdev;
+ int format = 0;
+
+ if (!does_look_like_super_block (sb, fs->fs_blocksize))
return 1;
- reiserfs_warning (fp, "Block count %u\n", rs_block_count (rs));
- reiserfs_warning (fp, "Blocksize %d\n", rs_blocksize (rs));
- reiserfs_warning (fp, "Free blocks %u\n", rs_free_blocks (rs));
- skipped = bh->b_blocknr; // FIXME: this would be confusing if
- // someone stores reiserfs super block in reiserfs ;)
- data_blocks = rs_block_count (rs) - skipped - 1 -
- rs_bmap_nr (rs) - (rs_journal_size (rs) + 1) - rs_free_blocks (rs);
- reiserfs_warning (fp, "Busy blocks (skipped %d, bitmaps - %d, journal blocks - %d\n"
- "1 super blocks, %d data blocks\n",
- skipped, rs_bmap_nr (rs),
- (rs_journal_size (rs) + 1), data_blocks);
- reiserfs_warning (fp, "Root block %u\n", rs_root_block (rs));
- reiserfs_warning (fp, "Journal block (first) %d\n", rs_journal_start (rs));
- reiserfs_warning (fp, "Journal dev %d\n", rs->s_v1.s_journal_dev);
- reiserfs_warning (fp, "Journal orig size %d\n", rs_journal_size (rs));
- reiserfs_warning (fp, "Filesystem state %s\n", (rs->s_v1.s_state == REISERFS_VALID_FS) ? "VALID" : "ERROR");
- if (fsck_state (rs) == TREE_IS_BUILT)
- reiserfs_warning (fp, "fsck pass 2 completion code set\n");
-
-#if 0
- __u32 s_journal_trans_max ; /* max number of blocks in a transaction. */
- __u32 s_journal_block_count ; /* total size of the journal. can change over time */
- __u32 s_journal_max_batch ; /* max number of blocks to batch into a trans */
- __u32 s_journal_max_commit_age ; /* in seconds, how old can an async commit be */
- __u32 s_journal_max_trans_age ; /* in seconds, how old can a transaction be */
-#endif
- reiserfs_warning (fp, "Tree height %d\n", rs_tree_height (rs));
+ rdev = get_st_rdev (file_name);
+
+ reiserfs_warning (fp, "Reiserfs super block in block %lu on 0x%x of ",
+ bh->b_blocknr, rdev);
+ switch (get_reiserfs_format (sb)) {
+ case REISERFS_FORMAT_3_5:
+ reiserfs_warning (fp, "format 3.5 with ");
+ format = 1;
+ break;
+ case REISERFS_FORMAT_3_6:
+ reiserfs_warning (fp, "format 3.6 with ");
+ format = 2;
+ break;
+ default:
+ reiserfs_warning (fp, "unknown format with ");
+ break;
+ }
+ if (is_reiserfs_jr_magic_string (sb))
+ reiserfs_warning (fp, "non-");
+ reiserfs_warning (fp, "standard journal\n");
+ if (short_print) {
+ reiserfs_warning (fp, "Blocks (total/free): %u/%u by %d bytes\n",
+ get_sb_block_count (sb), get_sb_free_blocks (sb), get_sb_block_size (sb));
+ } else {
+ reiserfs_warning (fp, "Count of blocks on the device: %u\n", get_sb_block_count (sb));
+ reiserfs_warning (fp, "Number of bitmaps: %u\n", get_sb_bmap_nr (sb));
+ reiserfs_warning (fp, "Blocksize: %d\n", get_sb_block_size (sb));
+ reiserfs_warning (fp, "Free blocks (count of blocks - used [journal, "
+ "bitmaps, data, reserved] blocks): %u\n", get_sb_free_blocks (sb));
+ reiserfs_warning (fp, "Root block: %u\n", get_sb_root_block (sb));
+ }
+ reiserfs_warning (fp, "Filesystem is %scleanly umounted\n",
+ (get_sb_umount_state (sb) == REISERFS_CLEANLY_UMOUNTED) ? "" : "NOT ");
+
+ if (short_print)
+ return 0;
+ reiserfs_warning (fp, "Tree height: %d\n", get_sb_tree_height (sb));
reiserfs_warning (fp, "Hash function used to sort names: %s\n",
- code2name (rs_hash (rs)));
- reiserfs_warning (fp, "Objectid map size %d, max %d\n", rs_objectid_map_size (rs),
- rs_objectid_map_max_size (rs));
- reiserfs_warning (fp, "Version %d\n", rs_version (rs));
+ code2name (get_sb_hash_code (sb)));
+ reiserfs_warning (fp, "Objectid map size %d, max %d\n", get_sb_oid_cursize (sb),
+ get_sb_oid_maxsize (sb));
+ reiserfs_warning (fp, "Journal parameters:\n");
+ print_journal_params (fp, sb_jp (sb));
+ reiserfs_warning (fp, "Blocks reserved by journal: %u\n",
+ get_sb_reserved_for_journal (sb));
+ reiserfs_warning (fp, "Fs state field: 0x%x\n", get_sb_fs_state (sb));
+ reiserfs_warning (fp, "sb_version: %u\n", get_sb_version (sb));
+ if (format == 2) {
+ reiserfs_warning (fp, "inode generation number: %u\n", get_sb_v2_inode_generation (sb));
+ reiserfs_warning (fp, "UUID: %U\n", sb->s_uuid);
+ reiserfs_warning (fp, "LABEL: %.16s\n", sb->s_label);
+ reiserfs_warning (fp, "Set flags in SB:\n");
+ reiserfs_warning (fp, "\t%s\n", ((get_sb_v2_flag (sb, reiserfs_attrs_cleared)) ? "ATTRIBUTES CLEAN" : ""));
+ }
+
return 0;
}
-static int print_desc_block (FILE * fp, struct buffer_head * bh)
+void print_filesystem_state (FILE * fp, reiserfs_filsys_t * fs)
{
- struct reiserfs_journal_desc * desc;
+ reiserfs_warning (fp, "\nFilesystem state: ");
+ if (reiserfs_is_fs_consistent (fs))
+ reiserfs_warning (fp, "consistent\n\n");
+ else
+ reiserfs_warning (fp, "consistency is not checked after last mounting\n\n");
+}
- desc = (struct reiserfs_journal_desc *)(bh->b_data);
- if (memcmp(desc->j_magic, JOURNAL_DESC_MAGIC, 8))
+
+static int print_desc_block (FILE * fp, struct buffer_head * bh)
+{
+ if (memcmp(get_jd_magic (bh), JOURNAL_DESC_MAGIC, 8))
return 1;
- reiserfs_warning (fp, "Desc block %lu (j_trans_id %ld, j_mount_id %ld, j_len %ld)",
- bh->b_blocknr, desc->j_trans_id, desc->j_mount_id, desc->j_len);
+ reiserfs_warning (fp, "Desc block %lu (j_trans_id %ld, j_mount_id %ld, j_len %ld)\n",
+ bh->b_blocknr, get_desc_trans_id (bh),
+ get_desc_mount_id (bh), get_desc_trans_len (bh));
return 0;
}
-void print_block (FILE * fp, reiserfs_filsys_t fs,
+void print_block (FILE * fp, reiserfs_filsys_t * fs,
struct buffer_head * bh, ...)//int print_mode, int first, int last)
{
va_list args;
int mode, first, last;
-
+ char * file_name;
+
va_start (args, bh);
if ( ! bh ) {
@@ -620,8 +688,9 @@ void print_block (FILE * fp, reiserfs_filsys_t fs,
mode = va_arg (args, int);
first = va_arg (args, int);
last = va_arg (args, int);
+ file_name = (fs) ? fs->fs_file_name : NULL ;
if (print_desc_block (fp, bh))
- if (print_super_block (fp, bh))
+ if (print_super_block (fp, fs, file_name, bh, 0))
if (print_leaf (fp, fs, bh, mode, first, last))
if (print_internal (fp, bh, first, last))
reiserfs_warning (fp, "Block %ld contains unformatted data\n", bh->b_blocknr);
@@ -709,21 +778,24 @@ void print_tb (int mode, int item_pos, int pos_in_item, struct tree_balance * tb
}
-static void print_bmap_block (FILE * fp, int i, struct buffer_head * bmap, int blocks, int silent)
+static void print_bmap_block (FILE * fp, int i, unsigned long block, char * map, int blocks, int silent, int blocksize)
{
int j, k;
- int bits = bmap->b_size * 8;
+ int bits = blocksize * 8;
int zeros = 0, ones = 0;
- reiserfs_warning (fp, "#%d: block %lu: ", i, bmap->b_blocknr);
- if (test_bit (0, bmap->b_data)) {
+ reiserfs_warning (fp, "#%d: block %lu: ", i, block);
+
+ blocks = blocksize * 8;
+
+ if (test_bit (0, map)) {
/* first block addressed by this bitmap block is used */
ones ++;
if (!silent)
reiserfs_warning (fp, "Busy (%d-", i * bits);
for (j = 1; j < blocks; j ++) {
- while (test_bit (j, bmap->b_data)) {
+ while (test_bit (j, map)) {
ones ++;
if (j == blocks - 1) {
if (!silent)
@@ -735,7 +807,7 @@ static void print_bmap_block (FILE * fp, int i, struct buffer_head * bmap, int b
if (!silent)
reiserfs_warning (fp, "%d) Free(%d-", j - 1 + i * bits, j + i * bits);
- while (!test_bit (j, bmap->b_data)) {
+ while (!test_bit (j, map)) {
zeros ++;
if (j == blocks - 1) {
if (!silent)
@@ -757,7 +829,7 @@ static void print_bmap_block (FILE * fp, int i, struct buffer_head * bmap, int b
reiserfs_warning (fp, "Free (%d-", i * bits);
for (j = 1; j < blocks; j ++) {
k = 0;
- while (!test_bit (j, bmap->b_data)) {
+ while (!test_bit (j, map)) {
k ++;
if (j == blocks - 1) {
if (!silent)
@@ -772,7 +844,7 @@ static void print_bmap_block (FILE * fp, int i, struct buffer_head * bmap, int b
reiserfs_warning (fp, "%d) Busy(%d-", j - 1 + i * bits, j + i * bits);
k = 0;
- while (test_bit (j, bmap->b_data)) {
+ while (test_bit (j, map)) {
ones ++;
if (j == blocks - 1) {
if (!silent)
@@ -795,155 +867,137 @@ static void print_bmap_block (FILE * fp, int i, struct buffer_head * bmap, int b
}
-/* if silent == 1, do not print details */
-void print_bmap (FILE * fp, reiserfs_filsys_t s, int silent)
+/* read bitmap of disk and print details */
+void print_bmap (FILE * fp, reiserfs_filsys_t * fs, int silent)
{
- int bmapnr = SB_BMAP_NR (s);
+ struct reiserfs_super_block * sb;
+ int bmap_nr;
int i;
- int blocks = s->s_blocksize * 8; /* adressed by bitmap */
-
- reiserfs_warning (fp, "Bitmap blocks are:\n");
- for (i = 0; i < bmapnr; i ++) {
-
- if (i == bmapnr - 1)
- if (SB_BLOCK_COUNT (s) % (s->s_blocksize * 8))
- blocks = SB_BLOCK_COUNT (s) % (s->s_blocksize * 8);
- print_bmap_block (fp, i, SB_AP_BITMAP(s)[i], blocks, silent);
- }
+ int bits_per_block;
+ int blocks;
+ unsigned long block;
+ struct buffer_head * bh;
- /* check unused part of last bitmap */
- {
- int bad_unused_bitmap = 0;
- int ones;
- ones = s->s_blocksize * 8 - SB_BLOCK_COUNT (s) % (s->s_blocksize * 8);
- if (ones == s->s_blocksize * 8)
- ones = 0;
-
- for (i = s->s_blocksize * 8; --i >= blocks; )
- if (!test_bit (i, SB_AP_BITMAP (s)[bmapnr - 1]->b_data))
- bad_unused_bitmap ++;
+ sb = fs->fs_ondisk_sb;
+ bmap_nr = get_sb_bmap_nr (sb);
+ bits_per_block = fs->fs_blocksize * 8;
+ blocks = bits_per_block;
- if (bad_unused_bitmap) {
- reiserfs_warning (fp, "Unused part of bitmap is wrong: should be %d ones, found %d zeros\n",
- ones, bad_unused_bitmap);
+ reiserfs_warning (fp, "Bitmap blocks are:\n");
+ block = fs->fs_super_bh->b_blocknr + 1;
+ for (i = 0; i < bmap_nr; i ++) {
+ bh = bread (fs->fs_dev, block, fs->fs_blocksize);
+ if (!bh) {
+ reiserfs_warning (stderr, "print_bmap: bread failed for %d: %lu\n", i, block);
+ continue;
}
+ if (i == bmap_nr - 1)
+ if (get_sb_block_count (sb) % bits_per_block)
+ blocks = get_sb_block_count (sb) % bits_per_block;
+ print_bmap_block (fp, i, block, bh->b_data, blocks, silent, fs->fs_blocksize);
+ brelse (bh);
+
+ if (spread_bitmaps (fs))
+ block = (block / (fs->fs_blocksize * 8) + 1) * (fs->fs_blocksize * 8);
+ else
+ block ++;
+
}
-
}
-void print_objectid_map (FILE * fp, reiserfs_filsys_t fs)
+void print_objectid_map (FILE * fp, reiserfs_filsys_t * fs)
{
int i;
- struct reiserfs_super_block * rs;
+ struct reiserfs_super_block * sb;
__u32 * omap;
- rs = fs->s_rs;
- if (fs->s_version == REISERFS_VERSION_2)
- omap = (__u32 *)(rs + 1);
- else if (fs->s_version == REISERFS_VERSION_1)
- omap = (__u32 *)((struct reiserfs_super_block_v1 *)rs + 1);
+
+ sb = fs->fs_ondisk_sb;
+ if (fs->fs_format == REISERFS_FORMAT_3_6)
+ omap = (__u32 *)(sb + 1);
+ else if (fs->fs_format == REISERFS_FORMAT_3_5)
+ omap = (__u32 *)((struct reiserfs_super_block_v1 *)sb + 1);
else {
reiserfs_warning (fp, "print_objectid_map: proper signature is not found\n");
return;
}
- reiserfs_warning (fp, "Map of objectids (super block size %d)\n", (char *)omap - (char *)rs);
+ reiserfs_warning (fp, "Map of objectids (super block size %d)\n",
+ (char *)omap - (char *)sb);
- for (i = 0; i < SB_OBJECTID_MAP_SIZE (fs); i ++) {
+ for (i = 0; i < get_sb_oid_cursize (sb); i ++) {
if (i % 2 == 0)
- reiserfs_warning (fp, "busy(%u-%u) ", omap[i], omap[i+1] - 1);
+ reiserfs_warning (fp, "busy(%u-%u) ", le32_to_cpu (omap[i]),
+ le32_to_cpu (omap[i+1]) - 1);
else
reiserfs_warning (fp, "free(%u-%u) ",
- omap[i], ((i+1) == SB_OBJECTID_MAP_SIZE (fs)) ? -1 : omap[i+1] - 1);
+ le32_to_cpu (omap[i]),
+ ((i+1) == get_sb_oid_cursize (sb)) ? -1 : (le32_to_cpu (omap[i+1]) - 1));
}
- reiserfs_warning (fp, "\nObject id array has size %d (max %d):", SB_OBJECTID_MAP_SIZE (fs),
- SB_OBJECTID_MAP_MAXSIZE (fs));
+ reiserfs_warning (fp, "\nObject id array has size %d (max %d):",
+ get_sb_oid_cursize (sb), get_sb_oid_maxsize (sb));
- for (i = 0; i < SB_OBJECTID_MAP_SIZE (fs); i ++)
- reiserfs_warning (fp, "%s%u ", i % 2 ? "" : "*", omap[i]);
+ for (i = 0; i < get_sb_oid_cursize (sb); i ++)
+ reiserfs_warning (fp, "%s%u ", i % 2 ? "" : "*", le32_to_cpu (omap[i]));
reiserfs_warning (fp, "\n");
}
-#if 0
-/* the below is from fileutils-4.0-66 (shortened) */
-
-/* Look at read, write, and execute bits in BITS and set
- flags in CHARS accordingly. */
-static void
-rwx (short unsigned int bits, char *chars)
+void print_journal_header (reiserfs_filsys_t * fs)
{
- chars[0] = (bits & S_IRUSR) ? 'r' : '-';
- chars[1] = (bits & S_IWUSR) ? 'w' : '-';
- chars[2] = (bits & S_IXUSR) ? 'x' : '-';
-}
+ struct reiserfs_journal_header * j_head;
-/* snip */
-/* Return a character indicating the type of file described by
- file mode BITS:
- 'd' for directories
- 'b' for block special files
- 'c' for character special files
- 'l' for symbolic links
- 's' for sockets
- 'p' for fifos
- '-' for regular files
- '?' for any other file type. */
+ j_head = (struct reiserfs_journal_header *)(fs->fs_jh_bh->b_data);
+ reiserfs_warning (stdout, "Journal header (block #%lu of %s):\n"
+ "\tj_last_flush_trans_id %ld\n"
+ "\tj_first_unflushed_offset %ld\n"
+ "\tj_mount_id %ld\n",
+ fs->fs_jh_bh->b_blocknr, fs->fs_j_file_name,
+ get_jh_last_flushed (j_head),
+ get_jh_replay_start_offset (j_head),
+ get_jh_mount_id (j_head));
+ print_journal_params (stdout, &j_head->jh_journal);
+}
-static char
-ftypelet (long int bits)
+
+static void print_trans_element (reiserfs_filsys_t * fs, reiserfs_trans_t * trans,
+ int index, unsigned long in_journal, unsigned long in_place)
{
-#ifdef S_ISBLK
- if (S_ISBLK (bits))
- return 'b';
-#endif
- if (S_ISCHR (bits))
- return 'c';
- if (S_ISDIR (bits))
- return 'd';
- if (S_ISREG (bits))
- return '-';
-#ifdef S_ISFIFO
- if (S_ISFIFO (bits))
- return 'p';
-#endif
-#ifdef S_ISLNK
- if (S_ISLNK (bits))
- return 'l';
-#endif
-#ifdef S_ISSOCK
- if (S_ISSOCK (bits))
- return 's';
-#endif
+ if (index % 8 == 0)
+ reiserfs_warning (stdout, "#%d\t", index);
- return '?';
+ reiserfs_warning (stdout, "%lu->%lu%s ", in_journal, in_place,
+ block_of_bitmap (fs, in_place) ? "B" : "");
+ if ((index + 1) % 8 == 0 || index == trans->trans_len - 1)
+ reiserfs_warning (stdout, "\n");
}
-/* Like filemodestring, but only the relevant part of the `struct stat'
- is given as an argument. */
-static void
-mode_string (short unsigned int mode, char *str)
+void print_one_transaction (reiserfs_filsys_t * fs, reiserfs_trans_t * trans)
{
- str[0] = ftypelet ((long) mode);
- rwx ((mode & 0700) << 0, &str[1]);
- rwx ((mode & 0070) << 3, &str[4]);
- rwx ((mode & 0007) << 6, &str[7]);
+ reiserfs_warning (stdout, "Mountid %u, transid %u, desc %lu, length %u, commit %lu\n",
+ trans->mount_id, trans->trans_id,
+ trans->desc_blocknr,
+ trans->trans_len, trans->commit_blocknr);
+ for_each_block (fs, trans, print_trans_element);
}
-char * st_mode2string (short unsigned int mode, char * buf)
+/* print all valid transactions and found dec blocks */
+void print_journal (reiserfs_filsys_t * fs)
{
- mode_string (mode, buf);
- buf[10] = 0;
- return buf;
-}
+ if (!reiserfs_journal_opened (fs)) {
+ reiserfs_warning (stderr, "print_journal: journal is not opened\n");
+ return;
+ }
+ print_journal_header (fs);
+ for_each_transaction (fs, print_one_transaction);
+}
-#endif
diff --git a/reiserfscore/reiserfslib.c b/reiserfscore/reiserfslib.c
index b024ac8..1b92c0b 100644
--- a/reiserfscore/reiserfslib.c
+++ b/reiserfscore/reiserfslib.c
@@ -3,98 +3,63 @@
*/
#include "includes.h"
+#include <linux/major.h>
+#include <linux/kdev_t.h>
+struct key root_dir_key = {0, 0, {{0, 0},}};
+struct key parent_root_dir_key = {0, 0, {{0, 0},}};
+struct key lost_found_dir_key = {0, 0, {{0, 0}, }};
-/* fixme: this assumes that journal start and journal size are set
- correctly */
-static void check_first_bitmap (reiserfs_filsys_t fs, char * bitmap)
-{
- int i;
- int bad;
-
- bad = 0;
- for (i = 0; i < rs_journal_start (fs->s_rs) +
- rs_journal_size (fs->s_rs) + 1; i ++) {
- if (!test_bit (i, bitmap)) {
- bad = 1;
- /*reiserfs_warning ("block %d is marked free in the first bitmap, fixed\n", i);*/
- /*set_bit (i, bitmap);*/
- }
- }
- if (bad)
- reiserfs_warning (stderr, "reiserfs_open: first bitmap looks corrupted\n");
-}
-
+__u16 root_dir_format = 0;
+__u16 lost_found_dir_format = 0;
-/* read bitmap blocks */
-void reiserfs_read_bitmap_blocks (reiserfs_filsys_t fs)
+static void make_const_keys (void)
{
- struct reiserfs_super_block * rs = fs->s_rs;
- struct buffer_head * bh = SB_BUFFER_WITH_SB(fs);
- int fd = fs->s_dev;
- unsigned long block;
- int i;
-
- /* read bitmaps, and correct a bit if necessary */
- SB_AP_BITMAP (fs) = getmem (sizeof (void *) * rs_bmap_nr (rs));
- for (i = 0, block = bh->b_blocknr + 1;
- i < rs_bmap_nr (rs); i ++) {
- SB_AP_BITMAP (fs)[i] = bread (fd, block, fs->s_blocksize);
- if (!SB_AP_BITMAP (fs)[i]) {
- reiserfs_warning (stderr, "reiserfs_open: bread failed reading bitmap #%d (%lu)\n", i, block);
- SB_AP_BITMAP (fs)[i] = getblk (fd, block, fs->s_blocksize);
- memset (SB_AP_BITMAP (fs)[i]->b_data, 0xff, fs->s_blocksize);
- set_bit (BH_Uptodate, &SB_AP_BITMAP (fs)[i]->b_state);
- }
-
- /* all bitmaps have to have itself marked used on it */
- if (bh->b_blocknr == 16) {
- if (!test_bit (block % (fs->s_blocksize * 8), SB_AP_BITMAP (fs)[i]->b_data)) {
- reiserfs_warning (stderr, "reiserfs_open: bitmap %d was marked free\n", i);
- /*set_bit (block % (fs->s_blocksize * 8), SB_AP_BITMAP (fs)[i]->b_data);*/
- }
- } else {
- /* bitmap not spread over partition: fixme: does not
- work when number of bitmaps => 32768 */
- if (!test_bit (block, SB_AP_BITMAP (fs)[0]->b_data)) {
- reiserfs_warning (stderr, "reiserfs_open: bitmap %d was marked free\n", i);
- /*set_bit (block, SB_AP_BITMAP (fs)[0]->b_data);*/
- }
- }
+ set_key_dirid (&root_dir_key, REISERFS_ROOT_PARENT_OBJECTID);
+ set_key_objectid (&root_dir_key, REISERFS_ROOT_OBJECTID);
- if (i == 0) {
- /* first bitmap has to have marked used super block
- and journal areas */
- check_first_bitmap (fs, SB_AP_BITMAP (fs)[i]->b_data);
- }
-
- block = (bh->b_blocknr == 16 ? ((i + 1) * fs->s_blocksize * 8) : (block + 1));
- }
+ set_key_dirid (&parent_root_dir_key, 0);
+ set_key_objectid (&parent_root_dir_key, REISERFS_ROOT_PARENT_OBJECTID);
}
-void reiserfs_free_bitmap_blocks (reiserfs_filsys_t fs)
-{
- int i;
-
- /* release bitmaps if they were read */
- if (SB_AP_BITMAP (fs)) {
- for (i = 0; i < SB_BMAP_NR (fs); i ++)
- brelse (SB_AP_BITMAP (fs) [i]);
- freemem (SB_AP_BITMAP (fs));
- }
+/* reiserfs needs at least: enough blocks for journal, 64 k at the beginning,
+ one block for super block, bitmap block and root block. Note that first
+ bitmap block must point to all of them */
+int is_block_count_correct (unsigned long block_of_super_block, int block_size,
+ unsigned long block_count, unsigned long journal_size)
+{
+ unsigned long blocks;
+
+ /* RESERVED, MD RAID SBs, super block, bitmap, root, journal size w/ journal header */
+ blocks = block_of_super_block + 1 + 1 + 1 + journal_size;
+
+ /* we have a limit: skipped area, super block, journal and root block
+ all have to be addressed by one first bitmap */
+ if (blocks > block_size * 8)
+ return 0;
+
+ if (blocks > block_count)
+ return 0;
+
+ return 1;
}
-/* read super block and bitmaps. fixme: only 4k blocks, pre-journaled format
- is refused */
-reiserfs_filsys_t reiserfs_open (char * filename, int flags, int *error, void * vp)
+/* read super block. fixme: only 4k blocks, pre-journaled format
+ is refused. Journal and bitmap are to be opened separately */
+reiserfs_filsys_t * reiserfs_open (char * filename, int flags, int *error, void * vp)
{
- reiserfs_filsys_t fs;
+ reiserfs_filsys_t * fs;
struct buffer_head * bh;
- struct reiserfs_super_block * rs;
+ struct reiserfs_super_block * sb;
int fd, i;
-
+
+
+ /* convert root dir key and parent root dir key to little endian format */
+ make_const_keys ();
+
+
fd = open (filename, flags | O_LARGEFILE);
if (fd == -1) {
if (error)
@@ -103,20 +68,22 @@ reiserfs_filsys_t reiserfs_open (char * filename, int flags, int *error, void *
}
fs = getmem (sizeof (*fs));
- fs->s_dev = fd;
- fs->s_vp = vp;
- asprintf (&fs->file_name, "%s", filename);
-
+ fs->fs_dev = fd;
+ fs->fs_vp = vp;
+ asprintf (&fs->fs_file_name, "%s", filename);
+
/* reiserfs super block is either in 16-th or in 2-nd 4k block of the
device */
- for (i = 16; i > 0; i -= 14) {
+ for (i = 2; i < 17; i += 14) {
bh = bread (fd, i, 4096);
if (!bh) {
reiserfs_warning (stderr, "reiserfs_open: bread failed reading block %d\n", i);
} else {
- rs = (struct reiserfs_super_block *)bh->b_data;
+ sb = (struct reiserfs_super_block *)bh->b_data;
- if (is_reiser2fs_magic_string (rs) || is_reiserfs_magic_string (rs))
+ if (is_any_reiserfs_magic_string (sb))
+ /* fixme: we could make some check to make sure that super
+ block looks correctly */
goto found;
/* reiserfs signature is not found at the i-th 4k block */
@@ -128,98 +95,279 @@ reiserfs_filsys_t reiserfs_open (char * filename, int flags, int *error, void *
"found on %s\n", filename);
if (error)
*error = 0;
+ freemem (fs);
+ close (fd);
+ fs = NULL;
return fs;
found:
+
+ fs->fs_blocksize = get_sb_block_size (sb);
- /* fixme: we could make some check to make sure that super block looks
- correctly */
- fs->s_version = is_reiser2fs_magic_string (rs) ? REISERFS_VERSION_2 :
- REISERFS_VERSION_1;
- fs->s_blocksize = rs_blocksize (rs);
- fs->s_hash_function = code2func (rs_hash (rs));
- SB_BUFFER_WITH_SB (fs) = bh;
- fs->s_rs = rs;
- fs->s_flags = flags; /* O_RDONLY or O_RDWR */
- fs->s_vp = vp;
+ /* check block size on the filesystem */
+ if (fs->fs_blocksize != 4096) {
+ i = bh->b_blocknr * 4096 / fs->fs_blocksize;
+ brelse (bh);
+ bh = bread (fd, i, fs->fs_blocksize);
+ if (!bh) {
+ reiserfs_warning (stderr, "reiserfs_open: bread failed reading block %d, size %d\n",
+ i, fs->fs_blocksize);
+ freemem (fs);
+ return 0;
+ }
+ sb = (struct reiserfs_super_block *)bh->b_data;
+ if (!does_look_like_super_block (sb, fs->fs_blocksize)) {
+ reiserfs_warning (stderr, "reiserfs_open: no reiserfs in %d, size %d\n",
+ i, fs->fs_blocksize);
+ freemem (fs);
+ return 0;
+ }
+ }
+
+ fs->fs_hash_function = code2func (get_sb_hash_code (sb));
+ fs->fs_super_bh = bh;
+ fs->fs_ondisk_sb = sb;
+ fs->fs_flags = flags; /* O_RDONLY or O_RDWR */
+
+ fs->fs_format = get_reiserfs_format (sb);
+
+ /*reiserfs_read_bitmap_blocks(fs);*/
+ if (flags & O_RDWR)
+ fs->fs_dirt = 1;
+ else
+ fs->fs_dirt = 0;
-
- reiserfs_read_bitmap_blocks(fs);
-
return fs;
+}
+
+
+/* creates buffer for super block and fills it up with fields which are
+ constant for given size and version of a filesystem */
+reiserfs_filsys_t * reiserfs_create (char * filename,
+ int version,
+ unsigned long block_count, int block_size, int default_journal, int new_format)
+{
+ reiserfs_filsys_t * fs;
+
+
+ /* convert root dir key and parent root dir key to little endian format */
+ make_const_keys ();
+
+
+ if (count_blocks (filename, block_size) < block_count) {
+ reiserfs_warning (stderr, "reiserfs_create: no enough blocks on device\n");
+ return 0;
+ }
+
+ if (!is_block_count_correct (REISERFS_DISK_OFFSET_IN_BYTES / block_size, block_size, block_count, 0)) {
+// if (block_count < min_block_amount (block_size, 0)) {
+ reiserfs_warning (stderr, "reiserfs_create: "
+ "can not create that small (%d blocks) filesystem\n",
+ block_count);
+ return 0;
+ }
+ fs = getmem (sizeof (*fs));
+ if (!fs) {
+ reiserfs_warning (stderr, "reiserfs_create: getmem failed\n");
+ return 0;
+ }
+
+ fs->fs_dev = open (filename, O_RDWR | O_LARGEFILE);
+ if (fs->fs_dev == -1) {
+ reiserfs_warning (stderr, "reiserfs_create: could not open %s: %m\n",
+ filename);
+ freemem (fs);
+ return 0;
+ }
+
+ fs->fs_blocksize = block_size;
+ asprintf (&fs->fs_file_name, "%s", filename);
+ fs->fs_format = version;
+
+ if (new_format)
+ fs->fs_super_bh = getblk (fs->fs_dev, REISERFS_DISK_OFFSET_IN_BYTES / block_size, block_size);
+ else
+ fs->fs_super_bh = getblk (fs->fs_dev, REISERFS_OLD_DISK_OFFSET_IN_BYTES / block_size, block_size);
+
+ if (!fs->fs_super_bh) {
+ reiserfs_warning (stderr, "reiserfs_create: getblk failed\n");
+ return 0;
+ }
+
+ mark_buffer_uptodate (fs->fs_super_bh, 1);
+
+ fs->fs_ondisk_sb = (struct reiserfs_super_block *)fs->fs_super_bh->b_data;
+ memset (fs->fs_ondisk_sb, 0, block_size);
+
+ /* fill super block fields which are constant for given version and block count */
+ set_sb_block_count (fs->fs_ondisk_sb, block_count);
+ /* sb_free_blocks */
+ /* sb_root_block */
+ /* sb_journal_1st_block */
+ /* sb_journal_dev */
+ /* sb_orig_journal_size */
+ /* sb_joural_magic */
+ /* sb_journal magic_F */
+ /* sb_mount_id */
+ /* sb_not_used0 */
+ /* sb_generation_number */
+ set_sb_block_size (fs->fs_ondisk_sb, block_size);
+ switch (version) {
+ case REISERFS_FORMAT_3_5:
+ set_sb_oid_maxsize (fs->fs_ondisk_sb, (block_size - SB_SIZE_V1) / sizeof(__u32) / 2 * 2);
+ /* sb_oid_cursize */
+ /* sb_state */
+ memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_3_5_SUPER_MAGIC_STRING,
+ strlen (REISERFS_3_5_SUPER_MAGIC_STRING));
+ break;
+
+ case REISERFS_FORMAT_3_6:
+ set_sb_oid_maxsize (fs->fs_ondisk_sb, (block_size - SB_SIZE) / sizeof(__u32) / 2 * 2);
+ /* sb_oid_cursize */
+ /* sb_state */
+ memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_3_6_SUPER_MAGIC_STRING,
+ strlen (REISERFS_3_6_SUPER_MAGIC_STRING));
+ break;
+ }
+ if (!default_journal)
+ memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_JR_SUPER_MAGIC_STRING,
+ strlen (REISERFS_JR_SUPER_MAGIC_STRING));
+
+ /* sb_fsck_state */
+ /* sb_hash_function_code */
+ /* sb_tree_height */
+ set_sb_bmap_nr (fs->fs_ondisk_sb,
+ (block_count + (block_size * 8 - 1)) / (block_size * 8));
+ set_sb_version (fs->fs_ondisk_sb, version);
+ /* sb_not_used1 */
+
+ mark_buffer_dirty (fs->fs_super_bh);
+ fs->fs_dirt = 1;
+
+ return fs;
}
-int no_reiserfs_found (reiserfs_filsys_t fs)
+int no_reiserfs_found (reiserfs_filsys_t * fs)
{
- return (fs->s_blocksize == 0) ? 1 : 0;
+ return (fs == NULL || fs->fs_blocksize == 0) ? 1 : 0;
}
-int new_format (reiserfs_filsys_t fs)
+int new_format (reiserfs_filsys_t * fs)
{
- return fs->s_sbh->b_blocknr != 2;
+ return fs->fs_super_bh->b_blocknr != 2;
}
-int spread_bitmaps (reiserfs_filsys_t fs)
+int spread_bitmaps (reiserfs_filsys_t * fs)
{
- return fs->s_sbh->b_blocknr != 2;
+ return fs->fs_super_bh->b_blocknr != 2;
}
-void reiserfs_reopen (reiserfs_filsys_t fs, int flag)
+/* 0 means: do not guarantee that fs is consistent */
+int reiserfs_is_fs_consistent (reiserfs_filsys_t * fs)
{
- close (fs->s_dev);
- fs->s_dev = open (fs->file_name, flag | O_LARGEFILE);
- if (fs->s_dev == -1)
- die ("reiserfs_reopen: could not reopen device: %m");
+ if (get_sb_umount_state (fs->fs_ondisk_sb) == REISERFS_CLEANLY_UMOUNTED &&
+ get_sb_fs_state (fs->fs_ondisk_sb) == REISERFS_CONSISTENT)
+ return 1;
+ return 0;
}
-int filesystem_dirty (reiserfs_filsys_t fs)
+void reiserfs_reopen (reiserfs_filsys_t * fs, int flag)
{
- return fs->s_dirt;
+ reiserfs_only_reopen (fs, flag);
+ reiserfs_reopen_journal (fs, flag);
+
}
-void mark_filesystem_dirty (reiserfs_filsys_t fs)
+/* flush bitmap, brelse super block, flush all dirty buffers, close and open
+ again the device, read super block */
+void reiserfs_only_reopen (reiserfs_filsys_t * fs, int flag)
{
- fs->s_dirt = 1;
+ unsigned long super_block;
+
+
+ /* reiserfs_flush_to_ondisk_bitmap (fs->fs_bitmap2, fs);*/
+ super_block = fs->fs_super_bh->b_blocknr;
+ brelse (fs->fs_super_bh);
+ flush_buffers (fs->fs_dev);
+
+ invalidate_buffers (fs->fs_dev);
+ if (close (fs->fs_dev))
+ die ("reiserfs_reopen: closed failed: %m");
+
+ fs->fs_dev = open (fs->fs_file_name, flag | O_LARGEFILE);
+ if (fs->fs_dev == -1)
+ die ("reiserfs_reopen: could not reopen device: %m");
+
+ fs->fs_super_bh = bread (fs->fs_dev, super_block, fs->fs_blocksize);
+ if (!fs->fs_super_bh)
+ die ("reiserfs_reopen: reading super block failed");
+ fs->fs_ondisk_sb = (struct reiserfs_super_block *)fs->fs_super_bh->b_data;
+ fs->fs_flags = flag; /* O_RDONLY or O_RDWR */
+
+ if (flag & O_RDWR)
+ fs->fs_dirt = 1;
+ else
+ fs->fs_dirt = 0;
+}
+
+
+int is_opened_rw (reiserfs_filsys_t * fs)
+{
+ if ((fs->fs_flags) & O_RDWR)
+ return 1;
+ return 0;
}
/* flush all changes made on a filesystem */
-void reiserfs_flush (reiserfs_filsys_t fs)
+void reiserfs_flush (reiserfs_filsys_t * fs)
{
- flush_buffers ();
+ if (fs->fs_dirt) {
+ reiserfs_flush_journal (fs);
+ flush_buffers (fs->fs_dev);
+ }
+ fs->fs_dirt = 0;
}
/* free all memory involved into manipulating with filesystem */
-void reiserfs_free (reiserfs_filsys_t fs)
+void reiserfs_free (reiserfs_filsys_t * fs)
{
- reiserfs_free_bitmap_blocks(fs);
-
+ reiserfs_free_journal (fs);
+ reiserfs_free_ondisk_bitmap (fs);
+
/* release super block and memory used by filesystem handler */
- brelse (SB_BUFFER_WITH_SB (fs));
-
+ brelse (fs->fs_super_bh);
+ fs->fs_super_bh = 0;
+
free_buffers ();
- free (fs->file_name);
+ free (fs->fs_file_name);
+ fs->fs_file_name = 0;
freemem (fs);
}
-void reiserfs_close (reiserfs_filsys_t fs)
+/* this closes everything: journal. bitmap and the fs itself */
+void reiserfs_close (reiserfs_filsys_t * fs)
{
+ reiserfs_close_journal (fs);
+ reiserfs_close_ondisk_bitmap (fs);
+
reiserfs_flush (fs);
reiserfs_free (fs);
+ fsync(fs->fs_dev);
}
-int reiserfs_new_blocknrs (reiserfs_filsys_t fs,
+int reiserfs_new_blocknrs (reiserfs_filsys_t * fs,
unsigned long * free_blocknrs, unsigned long start, int amount_needed)
{
if (fs->block_allocator)
@@ -229,105 +377,49 @@ int reiserfs_new_blocknrs (reiserfs_filsys_t fs,
}
-int reiserfs_free_block (reiserfs_filsys_t fs, unsigned long block)
+int reiserfs_free_block (reiserfs_filsys_t * fs, unsigned long block)
{
if (fs->block_deallocator)
return fs->block_deallocator (fs, block);
- die ("block allocator is not defined\n");
+ die ("block deallocator is not defined\n");
return 0;
}
+/*
+inline int reiserfs_bin_search (void * key, void * base, int num, int width,
+ int *ppos, comparison_fn_t comp_func) {
+ __u32 position = *ppos;
+ int retval;
-typedef int (comp_function_t) (void * key1, void * key2);
-
-inline int _bin_search (void * key, void * base, int num, int width, __u32 *ppos, comp_function_t comp_func)
-{
- int rbound, lbound, j;
-
- if (num == 0) {
- /* objectid map may be 0 elements long */
- *ppos = 0;
- return ITEM_NOT_FOUND;
- }
-
- lbound = 0;
- rbound = num - 1;
-
- for (j = (rbound + lbound) / 2; lbound <= rbound; j = (rbound + lbound) / 2) {
- switch (comp_func ((void *)((char *)base + j * width), key ) ) {
- case -1:/* second is greater */
- lbound = j + 1;
- continue;
-
- case 1: /* first is greater */
- if (j == 0) {
- *ppos = lbound;
- return ITEM_NOT_FOUND;
- }
- rbound = j - 1;
- continue;
-
- case 0:
- *ppos = j;
- return ITEM_FOUND;
- }
- }
-
- *ppos = lbound;
- return ITEM_NOT_FOUND;
-}
-
-#if 0
-static inline int _bin_search (void * key, void * base, int num, int width, __u32 *ppos)
-{
- __u32 rbound, lbound, j;
-
- lbound = 0;
- rbound = num - 1;
- for (j = (rbound + lbound) / 2; lbound <= rbound; j = (rbound + lbound) / 2) {
- switch (comp_keys ((void *)((char *)base + j * width), key)) {
- case -1:/* second is greater */
- lbound = j + 1;
- continue;
-
- case 1: /* first is greater */
- if (j == 0) {
- *ppos = lbound;
- return ITEM_NOT_FOUND;
- }
- rbound = j - 1;
- continue;
-
- case 0:
- *ppos = j;
- return ITEM_FOUND;
- }
- }
-
- *ppos = lbound;
- return ITEM_NOT_FOUND;
+ retval = reiserfs_bin_search (key, base, num, width, &position, comp_func);
+ *ppos = position;
+ return retval;
}
-#endif
+*/
-static int _search_by_key (reiserfs_filsys_t fs, struct key * key, struct path * path)
+static int reiserfs_search_by_key_x (reiserfs_filsys_t * fs, struct key * key,
+ struct path * path, int key_length)
{
- struct buffer_head * bh;
- unsigned long block = SB_ROOT_BLOCK (fs);
+ struct buffer_head * bh;
+ unsigned long block;
struct path_element * curr;
int retval;
+
+ block = get_sb_root_block (fs->fs_ondisk_sb);
path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
while (1) {
curr = PATH_OFFSET_PELEMENT (path, ++ path->path_length);
- bh = curr->pe_buffer = bread (fs->s_dev, block, fs->s_blocksize);
+ bh = curr->pe_buffer = bread (fs->fs_dev, block, fs->fs_blocksize);
if (bh == 0) {
path->path_length --;
pathrelse (path);
return ITEM_NOT_FOUND;
}
- retval = _bin_search (key, B_N_PKEY (bh, 0), B_NR_ITEMS (bh),
- is_leaf_node (bh) ? IH_SIZE : KEY_SIZE, &(curr->pe_position), comp_keys);
- if (retval == ITEM_FOUND) {
+ retval = reiserfs_bin_search (key, B_N_PKEY (bh, 0), B_NR_ITEMS (bh),
+ is_leaf_node (bh) ? IH_SIZE : KEY_SIZE,
+ &(curr->pe_position), key_length == 4 ? comp_keys : comp_keys_3);
+ if (retval == POSITION_FOUND) {
/* key found, return if this is leaf level */
if (is_leaf_node (bh)) {
path->pos_in_item = 0;
@@ -339,17 +431,116 @@ static int _search_by_key (reiserfs_filsys_t fs, struct key * key, struct path *
if (is_leaf_node (bh))
return ITEM_NOT_FOUND;
}
- block = B_N_CHILD_NUM (bh, curr->pe_position);
+ block = get_dc_child_blocknr (B_N_CHILD (bh, curr->pe_position));
}
printf ("search_by_key: you can not get here\n");
return ITEM_NOT_FOUND;
}
-static int comp_dir_entries (void * p1, void * p2)
+int reiserfs_search_by_key_3 (reiserfs_filsys_t * fs, struct key * key,
+ struct path * path)
+{
+ return reiserfs_search_by_key_x (fs, key, path, 3);
+}
+
+
+int reiserfs_search_by_key_4 (reiserfs_filsys_t * fs, struct key * key,
+ struct path * path)
+{
+ return reiserfs_search_by_key_x (fs, key, path, 4);
+}
+
+
+/* key is key of byte in the regular file. This searches in tree
+ through items and in the found item as well */
+int usearch_by_position (reiserfs_filsys_t * s, struct key * key,
+ int version, struct path * path)
+{
+ struct buffer_head * bh;
+ struct item_head * ih;
+ struct key * next_key;
+
+ if (reiserfs_search_by_key_3 (s, key, path) == ITEM_FOUND) {
+ ih = get_ih (path);
+
+ if (!is_direct_ih (ih) && !is_indirect_ih (ih))
+ return DIRECTORY_FOUND;
+
+ path->pos_in_item = 0;
+ return POSITION_FOUND;
+ }
+
+ bh = get_bh (path);
+ ih = get_ih (path);
+
+
+ if (PATH_LAST_POSITION (path) == 0) {
+ /* previous item does not exist, that means we are in leftmost leaf of
+ * the tree */
+ if (!not_of_one_file (&ih->ih_key, key)) {
+ if (!is_direct_ih (ih) && !is_indirect_ih (ih))
+ return DIRECTORY_FOUND;
+ return POSITION_NOT_FOUND;
+ }
+ return FILE_NOT_FOUND;
+ }
+
+ /* take previous item */
+ PATH_LAST_POSITION (path) --;
+ ih --;
+
+ if (not_of_one_file (&ih->ih_key, key) || is_stat_data_ih(ih)) {
+ /* previous item belongs to another object or is a stat data, check
+ * next item */
+ PATH_LAST_POSITION (path) ++;
+ if (PATH_LAST_POSITION (path) < B_NR_ITEMS (bh))
+ /* next key is in the same node */
+ next_key = B_N_PKEY (bh, PATH_LAST_POSITION (path));
+ else
+ next_key = uget_rkey (path);
+ if (next_key == 0 || not_of_one_file (next_key, key)) {
+ /* there is no any part of such file in the tree */
+ path->pos_in_item = 0;
+ return FILE_NOT_FOUND;
+ }
+
+ if (is_direntry_key (next_key)) {
+ reiserfs_warning (stderr, "usearch_by_position: looking for %k found a directory with the same key\n",
+ next_key);
+ return DIRECTORY_FOUND;
+ }
+
+ /* next item is the part of this file */
+ path->pos_in_item = 0;
+ return POSITION_NOT_FOUND;
+ }
+
+ if (is_direntry_ih (ih)) {
+ return DIRECTORY_FOUND;
+ }
+
+ if (is_stat_data_ih(ih)) {
+ PATH_LAST_POSITION (path) ++;
+ return FILE_NOT_FOUND;
+ }
+
+ /* previous item is part of desired file */
+ if (I_K_KEY_IN_ITEM (ih, key, bh->b_size)) {
+ path->pos_in_item = get_offset (key) - get_offset (&ih->ih_key);
+ if (is_indirect_ih (ih) )
+ path->pos_in_item /= bh->b_size;
+ return POSITION_FOUND;
+ }
+
+ path->pos_in_item = is_indirect_ih (ih) ? I_UNFM_NUM (ih) : get_ih_item_len (ih);
+ return POSITION_NOT_FOUND;
+}
+
+static int comp_dir_entries (const void * p1, const void * p2)
{
__u32 deh_offset;
- __u32 * off1, * off2;
+ const __u32 * off1, * off2;
off1 = p1;
off2 = p2;
@@ -362,31 +553,66 @@ static int comp_dir_entries (void * p1, void * p2)
return 0;
}
+struct key * uget_lkey (struct path * path)
+{
+ int pos, offset = path->path_length;
+ struct buffer_head * bh;
+
+ if (offset < FIRST_PATH_ELEMENT_OFFSET)
+ die ("uget_lkey: illegal offset in the path (%d)", offset);
+
+
+ /* While not higher in path than first element. */
+ while (offset-- > FIRST_PATH_ELEMENT_OFFSET) {
+ if (! buffer_uptodate (PATH_OFFSET_PBUFFER (path, offset)) )
+ die ("uget_lkey: parent is not uptodate");
+
+ /* Parent at the path is not in the tree now. */
+ if (! B_IS_IN_TREE (bh = PATH_OFFSET_PBUFFER (path, offset)))
+ die ("uget_lkey: buffer on the path is not in tree");
-static struct key * _get_rkey (struct path * path)
+ /* Check whether position in the parent is correct. */
+ if ((pos = PATH_OFFSET_POSITION (path, offset)) > B_NR_ITEMS (bh))
+ die ("uget_lkey: invalid position (%d) in the path", pos);
+
+ /* Check whether parent at the path really points to the child. */
+ if (get_dc_child_blocknr (B_N_CHILD (bh, pos)) != PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr)
+ die ("uget_lkey: invalid block number (%d). Must be %ld",
+ get_dc_child_blocknr (B_N_CHILD (bh, pos)), PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr);
+
+ /* Return delimiting key if position in the parent is not equal to zero. */
+ if (pos)
+ return B_N_PDELIM_KEY(bh, pos - 1);
+ }
+
+ /* there is no left delimiting key */
+ return 0;
+}
+
+struct key * uget_rkey (struct path * path)
{
int pos, offset = path->path_length;
struct buffer_head * bh;
if (offset < FIRST_PATH_ELEMENT_OFFSET)
- die ("_get_rkey: illegal offset in the path (%d)", offset);
+ die ("uget_rkey: illegal offset in the path (%d)", offset);
while (offset-- > FIRST_PATH_ELEMENT_OFFSET) {
if (! buffer_uptodate (PATH_OFFSET_PBUFFER (path, offset)))
- die ("_get_rkey: parent is not uptodate");
+ die ("uget_rkey: parent is not uptodate");
/* Parent at the path is not in the tree now. */
if (! B_IS_IN_TREE (bh = PATH_OFFSET_PBUFFER (path, offset)))
- die ("_get_rkey: buffer on the path is not in tree");
+ die ("uget_rkey: buffer on the path is not in tree");
/* Check whether position in the parrent is correct. */
if ((pos = PATH_OFFSET_POSITION (path, offset)) > B_NR_ITEMS (bh))
- die ("_get_rkey: invalid position (%d) in the path", pos);
+ die ("uget_rkey: invalid position (%d) in the path", pos);
/* Check whether parent at the path really points to the child. */
- if (B_N_CHILD_NUM (bh, pos) != PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr)
- die ("_get_rkey: invalid block number (%d). Must be %d",
- B_N_CHILD_NUM (bh, pos), PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr);
+ if (get_dc_child_blocknr (B_N_CHILD (bh, pos)) != PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr)
+ die ("uget_rkey: invalid block number (%d). Must be %ld",
+ get_dc_child_blocknr (B_N_CHILD (bh, pos)), PATH_OFFSET_PBUFFER (path, offset + 1)->b_blocknr);
/* Return delimiting key if position in the parent is not the last one. */
if (pos != B_NR_ITEMS (bh))
@@ -397,17 +623,33 @@ static struct key * _get_rkey (struct path * path)
return 0;
}
+struct key * get_next_key_2 (struct path * path)
+{
+ if (PATH_LAST_POSITION (path) < B_NR_ITEMS (get_bh (path)) - 1)
+ return B_N_PKEY (get_bh (path), PATH_LAST_POSITION (path) + 1);
+ return uget_rkey (path);
+}
+
+struct key * reiserfs_next_key (struct path * path)
+{
+ if (get_item_pos (path) < B_NR_ITEMS (get_bh (path)) - 1)
+ return B_N_PKEY (get_bh (path), get_item_pos (path) + 1);
+
+ return uget_rkey (path);
+}
+
/* NOTE: this only should be used to look for keys who exists */
-int _search_by_entry_key (reiserfs_filsys_t fs, struct key * key,
- struct path * path)
+int reiserfs_search_by_entry_key (reiserfs_filsys_t * fs, struct key * key,
+ struct path * path)
{
struct buffer_head * bh;
int item_pos;
struct item_head * ih;
struct key tmpkey;
+ __u32 offset;
- if (_search_by_key (fs, key, path) == ITEM_FOUND) {
+ if (reiserfs_search_by_key_4 (fs, key, path) == ITEM_FOUND) {
path->pos_in_item = 0;
return POSITION_FOUND;
}
@@ -422,9 +664,10 @@ int _search_by_entry_key (reiserfs_filsys_t fs, struct key * key,
/* there are no items of that directory */
return DIRECTORY_NOT_FOUND;
- if (!is_direntry_ih (ih))
- reiserfs_panic ("_search_by_entry_key: found item is not of directory type %H",
- ih);
+ if (!is_direntry_ih (ih)) {
+ reiserfs_panic ("reiserfs_search_by_entry_key: found item "
+ "is not of directory type %H", ih);
+ }
/* key we looked for should be here */
path->pos_in_item = 0;
@@ -457,7 +700,7 @@ int _search_by_entry_key (reiserfs_filsys_t fs, struct key * key,
key);
} else {
/* next item is in right neighboring node */
- struct key * next_key = _get_rkey (path);
+ struct key * next_key = uget_rkey (path);
if (next_key == 0 || not_of_one_file (next_key, key)) {
/* there are no items of that directory */
@@ -473,7 +716,7 @@ int _search_by_entry_key (reiserfs_filsys_t fs, struct key * key,
pasted in position 0 */
copy_key (&tmpkey, next_key);
pathrelse (path);
- if (_search_by_key (fs, &tmpkey, path) != ITEM_FOUND || PATH_LAST_POSITION (path) != 0)
+ if (reiserfs_search_by_key_4 (fs, &tmpkey, path) != ITEM_FOUND || PATH_LAST_POSITION (path) != 0)
reiserfs_panic ("_search_by_entry_key: item corresponding to delimiting key %k not found",
&tmpkey);
}
@@ -483,21 +726,21 @@ int _search_by_entry_key (reiserfs_filsys_t fs, struct key * key,
return POSITION_NOT_FOUND;
}
-
/* previous item is part of desired directory */
- if (_bin_search (&(key->u.k_offset_v1.k_offset), B_I_DEH (bh, ih), ih_entry_count (ih),
- DEH_SIZE, &(path->pos_in_item), comp_dir_entries) == ITEM_FOUND)
+ offset = get_key_offset_v1 (key);
+ if (reiserfs_bin_search (&offset, B_I_DEH (bh, ih), get_ih_entry_count (ih),
+ DEH_SIZE, &(path->pos_in_item), comp_dir_entries) == POSITION_FOUND)
return POSITION_FOUND;
return POSITION_NOT_FOUND;
}
-static void _init_tb_struct (struct tree_balance * tb, reiserfs_filsys_t fs,
+void init_tb_struct (struct tree_balance * tb, reiserfs_filsys_t * fs,
struct path * path, int size)
{
memset (tb, '\0', sizeof(struct tree_balance));
- tb->tb_sb = fs;
+ tb->tb_fs = fs;
tb->tb_path = path;
PATH_OFFSET_PBUFFER(path, ILLEGAL_PATH_ELEMENT_OFFSET) = NULL;
@@ -506,21 +749,21 @@ static void _init_tb_struct (struct tree_balance * tb, reiserfs_filsys_t fs,
}
-int reiserfs_remove_entry (reiserfs_filsys_t fs, struct key * key)
+int reiserfs_remove_entry (reiserfs_filsys_t * fs, struct key * key)
{
struct path path;
struct tree_balance tb;
struct item_head * ih;
struct reiserfs_de_head * deh;
- if (_search_by_entry_key (fs, key, &path) != POSITION_FOUND) {
+ if (reiserfs_search_by_entry_key (fs, key, &path) != POSITION_FOUND) {
pathrelse (&path);
return 1;
}
ih = get_ih (&path);
- if (ih_entry_count (ih) == 1) {
- _init_tb_struct (&tb, fs, &path, -(IH_SIZE + ih_item_len (ih)));
+ if (get_ih_entry_count (ih) == 1) {
+ init_tb_struct (&tb, fs, &path, -(IH_SIZE + get_ih_item_len (ih)));
if (fix_nodes (M_DELETE, &tb, 0) != CARRY_ON) {
unfix_nodes (&tb);
return 1;
@@ -530,7 +773,7 @@ int reiserfs_remove_entry (reiserfs_filsys_t fs, struct key * key)
}
deh = B_I_DEH (get_bh (&path), ih) + path.pos_in_item;
- _init_tb_struct (&tb, fs, &path, -(DEH_SIZE + entry_length (ih, deh, path.pos_in_item)));
+ init_tb_struct (&tb, fs, &path, -(DEH_SIZE + entry_length (ih, deh, path.pos_in_item)));
if (fix_nodes (M_CUT, &tb, 0) != CARRY_ON) {
unfix_nodes (&tb);
return 1;
@@ -541,12 +784,12 @@ int reiserfs_remove_entry (reiserfs_filsys_t fs, struct key * key)
-void reiserfs_paste_into_item (reiserfs_filsys_t fs, struct path * path,
+void reiserfs_paste_into_item (reiserfs_filsys_t * fs, struct path * path,
const void * body, int size)
{
struct tree_balance tb;
- _init_tb_struct (&tb, fs, path, size);
+ init_tb_struct (&tb, fs, path, size);
if (fix_nodes (M_PASTE, &tb, 0/*ih*/) != CARRY_ON)
reiserfs_panic ("reiserfs_paste_into_item: fix_nodes failed");
@@ -555,12 +798,12 @@ void reiserfs_paste_into_item (reiserfs_filsys_t fs, struct path * path,
}
-void reiserfs_insert_item (reiserfs_filsys_t fs, struct path * path,
+void reiserfs_insert_item (reiserfs_filsys_t * fs, struct path * path,
struct item_head * ih, const void * body)
{
struct tree_balance tb;
- _init_tb_struct (&tb, fs, path, IH_SIZE + ih_item_len(ih));
+ init_tb_struct (&tb, fs, path, IH_SIZE + get_ih_item_len(ih));
if (fix_nodes (M_INSERT, &tb, ih) != CARRY_ON)
die ("reiserfs_insert_item: fix_nodes failed");
@@ -570,7 +813,7 @@ void reiserfs_insert_item (reiserfs_filsys_t fs, struct path * path,
/*===========================================================================*/
-static __u32 hash_value (reiserfs_filsys_t fs, char * name)
+static __u32 hash_value (reiserfs_filsys_t * fs, char * name)
{
__u32 res;
@@ -588,12 +831,84 @@ static __u32 hash_value (reiserfs_filsys_t fs, char * name)
}
+/* if name is found in a directory - return 1 and set path to the name,
+ otherwise return 0 and pathrelse path */
+int reiserfs_locate_entry (reiserfs_filsys_t * fs, struct key * dir, char * name,
+ struct path * path)
+{
+ struct key entry_key;
+ struct item_head * ih;
+ struct reiserfs_de_head * deh;
+ __u32 hash;
+ int i, retval;
+ struct key * rdkey;
+
+ set_key_dirid (&entry_key, get_key_dirid (dir));
+ set_key_objectid (&entry_key, get_key_objectid (dir));
+ hash = hash_value (fs, name);
+ set_key_offset_v1 (&entry_key, hash);
+ set_key_uniqueness (&entry_key, DIRENTRY_UNIQUENESS);
+
+
+ if (reiserfs_search_by_entry_key (fs, &entry_key, path) == DIRECTORY_NOT_FOUND) {
+ pathrelse (path);
+ return 0;
+ }
+
+ do {
+ ih = get_ih (path);
+ deh = B_I_DEH (get_bh (path), ih) + path->pos_in_item;
+ for (i = path->pos_in_item; i < get_ih_entry_count (ih); i ++, deh ++) {
+ if (GET_HASH_VALUE (get_deh_offset (deh)) != GET_HASH_VALUE (hash)) {
+ /* all entries having the same hash were scanned */
+ pathrelse (path);
+ return 0;
+ }
+
+ /* the name in directory has the same hash as the given name */
+ if ((name_in_entry_length (ih, deh, i) == strlen (name)) &&
+ !memcmp (name_in_entry (deh, i), name, strlen (name))) {
+ path->pos_in_item = i;
+ return 1;
+ }
+ }
-/* returns 0 if name is not found in a directory and objectid of
- pointed object otherwise and returns minimal not used generation
- counter. dies if found object is not a directory. */
-int reiserfs_find_entry (reiserfs_filsys_t fs, struct key * dir, char * name,
- int * min_gen_counter)
+ rdkey = uget_rkey (path);
+ if (!rdkey || not_of_one_file (rdkey, dir)) {
+ pathrelse (path);
+ return 0;
+ }
+
+ if (!is_direntry_key (rdkey))
+ reiserfs_panic ("reiserfs_locate_entry: can not find name in broken directory yet");
+
+ /* next item is the item of the directory we are looking name in */
+ if (GET_HASH_VALUE (get_offset (rdkey)) != hash) {
+ /* but there is no names with given hash */
+ pathrelse (path);
+ return 0;
+ }
+
+ /* first name of that item may be a name we are looking for */
+ entry_key = *rdkey;
+ pathrelse (path);
+ retval = reiserfs_search_by_entry_key (fs, &entry_key, path);
+ if (retval != POSITION_FOUND)
+ reiserfs_panic ("reiserfs_locate_entry: wrong delimiting key in the tree");
+
+ } while (1);
+
+ return 0;
+
+}
+
+
+/* returns 0 if name is not found in a directory and 1 if name is
+ found. Stores key found in the entry in 'key'. Returns minimal not used
+ generation counter in 'min_gen_counter'. dies if found object is not a
+ directory. */
+int reiserfs_find_entry (reiserfs_filsys_t * fs, struct key * dir, char * name,
+ int * min_gen_counter, struct key * key)
{
struct key entry_key;
int retval;
@@ -604,59 +919,69 @@ int reiserfs_find_entry (reiserfs_filsys_t fs, struct key * dir, char * name,
struct key * rdkey;
__u32 hash;
- entry_key.k_dir_id = dir->k_dir_id;
- entry_key.k_objectid = dir->k_objectid;
+
+ set_key_dirid (&entry_key, get_key_dirid (dir));
+ set_key_objectid (&entry_key, get_key_objectid (dir));
hash = hash_value (fs, name);
- set_type_and_offset (KEY_FORMAT_1, &entry_key, hash, TYPE_DIRENTRY);
+ set_key_offset_v1 (&entry_key, hash);
+ set_key_uniqueness (&entry_key, DIRENTRY_UNIQUENESS);
+
*min_gen_counter = 0;
- if (_search_by_entry_key (fs, &entry_key, &path) == DIRECTORY_NOT_FOUND) {
+ if (reiserfs_search_by_entry_key (fs, &entry_key, &path) == DIRECTORY_NOT_FOUND) {
pathrelse (&path);
return 0;
}
-
+
do {
ih = get_ih (&path);
deh = B_I_DEH (get_bh (&path), ih) + path.pos_in_item;
- for (i = path.pos_in_item; i < ih_entry_count (ih); i ++, deh ++) {
- if (GET_HASH_VALUE (deh_offset (deh)) != GET_HASH_VALUE (hash)) {
+ for (i = path.pos_in_item; i < get_ih_entry_count (ih); i ++, deh ++) {
+ if (GET_HASH_VALUE (get_deh_offset (deh)) != GET_HASH_VALUE (hash)) {
/* all entries having the same hash were scanned */
pathrelse (&path);
return 0;
}
-
- if (GET_GENERATION_NUMBER (deh_offset (deh)) == *min_gen_counter)
+
+ if (GET_GENERATION_NUMBER (get_deh_offset (deh)) == *min_gen_counter)
(*min_gen_counter) ++;
-
- if (!memcmp (name_in_entry (deh, i), name, strlen (name))) {
+
+ if ((name_in_entry_length (ih, deh, i) == strlen (name)) &&
+ (!memcmp (name_in_entry (deh, i), name, strlen (name)))) {
+ /* entry found in the directory */
+ if (key) {
+ memset (key, 0, sizeof (struct key));
+ set_key_dirid (key, get_deh_dirid (deh));
+ set_key_objectid (key, get_deh_objectid (deh));
+ }
pathrelse (&path);
- return deh_objectid (deh) ? deh_objectid (deh) : 1;
+ return 1;//get_deh_objectid (deh) ? get_deh_objectid (deh) : 1;
}
}
-
- rdkey = _get_rkey (&path);
+
+ rdkey = uget_rkey (&path);
if (!rdkey || not_of_one_file (rdkey, dir)) {
pathrelse (&path);
return 0;
}
-
+
if (!is_direntry_key (rdkey))
reiserfs_panic ("reiserfs_find_entry: can not find name in broken directory yet");
-
+
/* next item is the item of the directory we are looking name in */
if (GET_HASH_VALUE (get_offset (rdkey)) != hash) {
/* but there is no names with given hash */
pathrelse (&path);
return 0;
}
-
+
/* first name of that item may be a name we are looking for */
entry_key = *rdkey;
pathrelse (&path);
- retval = _search_by_entry_key (fs, &entry_key, &path);
+ retval = reiserfs_search_by_entry_key (fs, &entry_key, &path);
if (retval != POSITION_FOUND)
reiserfs_panic ("reiserfs_find_entry: wrong delimiting key in the tree");
-
+
} while (1);
return 0;
@@ -667,21 +992,23 @@ int reiserfs_find_entry (reiserfs_filsys_t fs, struct key * dir, char * name,
char * make_entry (char * entry, char * name, struct key * key, __u32 offset)
{
struct reiserfs_de_head * deh;
-
+ __u16 state;
+
if (!entry)
entry = getmem (DEH_SIZE + ROUND_UP (strlen (name)));
memset (entry, 0, DEH_SIZE + ROUND_UP (strlen (name)));
deh = (struct reiserfs_de_head *)entry;
- deh->deh_location = 0;
- deh->deh_offset = cpu_to_le32 (offset);
- deh->deh_state = 0;
- mark_de_visible (deh);
-
+
+ set_deh_location (deh, 0);
+ set_deh_offset (deh, offset);
+ state = (1 << DEH_Visible2);
+ set_deh_state (deh, state);
+
/* key of object entry will point to */
- deh->deh_dir_id = cpu_to_le32 (key->k_dir_id);
- deh->deh_objectid = cpu_to_le32 (key->k_objectid);
-
+ set_deh_dirid (deh, get_key_dirid (key));
+ set_deh_objectid (deh, get_key_objectid (key));
+
memcpy ((char *)(deh + 1), name, strlen (name));
return entry;
}
@@ -689,8 +1016,8 @@ char * make_entry (char * entry, char * name, struct key * key, __u32 offset)
/* add new name into a directory. If it exists in a directory - do
nothing */
-int reiserfs_add_entry (reiserfs_filsys_t fs, struct key * dir, char * name,
- struct key * key, int fsck_need)
+int reiserfs_add_entry (reiserfs_filsys_t * fs, struct key * dir, char * name, int name_len,
+ struct key * key, int fsck_need)
{
struct item_head entry_ih = {{0,}, };
char * entry;
@@ -700,40 +1027,49 @@ int reiserfs_add_entry (reiserfs_filsys_t fs, struct key * dir, char * name,
int item_len;
__u32 hash;
- if (reiserfs_find_entry (fs, dir, name, &gen_counter))
+ if (reiserfs_find_entry (fs, dir, name, &gen_counter, 0))
+ /* entry is in the directory already or directory was not found */
return 0;
/* compose entry key to look for its place in the tree */
- entry_ih.ih_key.k_dir_id = cpu_to_le32 (dir->k_dir_id);
- entry_ih.ih_key.k_objectid = cpu_to_le32 (dir->k_objectid);
+ set_key_dirid (&(entry_ih.ih_key), get_key_dirid (dir));
+ set_key_objectid (&(entry_ih.ih_key), get_key_objectid (dir));
hash = hash_value (fs, name) + gen_counter;
if (!strcmp (name, "."))
hash = DOT_OFFSET;
if (!strcmp (name, ".."))
hash = DOT_DOT_OFFSET;
- set_type_and_offset (KEY_FORMAT_1, &(entry_ih.ih_key),
- hash, TYPE_DIRENTRY);
- set_key_format (&entry_ih, KEY_FORMAT_1);
- set_entry_count (&entry_ih, 1);
- if (SB_VERSION (fs) == REISERFS_VERSION_2)
+ set_key_offset_v1 (&(entry_ih.ih_key), hash);
+ set_key_uniqueness (&(entry_ih.ih_key), DIRENTRY_UNIQUENESS);
+
+ set_ih_key_format (&entry_ih, KEY_FORMAT_1);
+ set_ih_entry_count (&entry_ih, 1);
+
+ item_len = DEH_SIZE + name_len;
+/*
+ if (get_reiserfs_format (fs->fs_ondisk_sb) == REISERFS_FORMAT_3_5)
+ item_len = DEH_SIZE + strlen (name);
+ else if (get_reiserfs_format (fs->fs_ondisk_sb) == REISERFS_FORMAT_3_6)
item_len = DEH_SIZE + ROUND_UP (strlen (name));
else
- item_len = DEH_SIZE + strlen (name);
+ reiserfs_panic ("unknown fs format");
+*/
+
set_ih_item_len (&entry_ih, item_len);
/* fsck may need to insert item which was not reached yet */
- entry_ih.ih_format.fsck_need = fsck_need;
+ set_ih_flags (&entry_ih, fsck_need);
entry = make_entry (0, name, key, get_offset (&(entry_ih.ih_key)));
- retval = _search_by_entry_key (fs, &(entry_ih.ih_key), &path);
+ retval = reiserfs_search_by_entry_key (fs, &(entry_ih.ih_key), &path);
switch (retval) {
case POSITION_NOT_FOUND:
reiserfs_paste_into_item (fs, &path, entry, item_len);
break;
case DIRECTORY_NOT_FOUND:
- ((struct reiserfs_de_head *)entry)->deh_location = cpu_to_le16 (DEH_SIZE);
+ set_deh_location ((struct reiserfs_de_head *)entry, DEH_SIZE);
reiserfs_insert_item (fs, &path, &entry_ih, entry);
break;
@@ -764,3 +1100,364 @@ void copy_item_head(void * p_v_to, void * p_v_from)
{
memcpy (p_v_to, p_v_from, IH_SIZE);
}
+
+
+/* inserts new or old stat data of a directory (unreachable, nlinks == 0) */
+int create_dir_sd (reiserfs_filsys_t * fs,
+ struct path * path, struct key * key,
+ void (*modify_item)(struct item_head *, void *))
+{
+ struct item_head ih;
+ struct stat_data sd;
+ int key_format;
+
+ if (fs->fs_format == REISERFS_FORMAT_3_5)
+ key_format = KEY_FORMAT_1;
+ else
+ key_format = KEY_FORMAT_2;
+
+ make_dir_stat_data (fs->fs_blocksize, key_format, get_key_dirid (key),
+ get_key_objectid (key), &ih, &sd);
+
+ if (modify_item)
+ modify_item (&ih, &sd);
+#if 0
+ /* set nlink count to 0 and make the item unreachable */
+ zero_nlink (&ih, &sd, 0);
+ mark_item_unreachable (&ih);
+#endif
+ reiserfs_insert_item (fs, path, &ih, &sd);
+ return key_format;
+}
+
+
+
+void make_sure_root_dir_exists (reiserfs_filsys_t * fs,
+ void (*modify_item)(struct item_head *, void *),
+ int ih_flags)
+{
+ INITIALIZE_PATH (path);
+
+
+ /* is there root's stat data */
+ if (reiserfs_search_by_key_4 (fs, &root_dir_key, &path) == ITEM_NOT_FOUND) {
+ root_dir_format = create_dir_sd (fs, &path, &root_dir_key, modify_item);
+ } else {
+ struct item_head * ih = get_ih (&path);
+
+ if (!is_stat_data_ih (ih))
+ reiserfs_panic ("It must be root's stat data %k\n", &ih->ih_key);
+
+ root_dir_format = (get_ih_item_len (get_ih (&path)) == SD_SIZE) ? KEY_FORMAT_2 : KEY_FORMAT_1;
+ pathrelse (&path);
+ }
+
+ /* add "." and ".." if any of them do not exist. Last two
+ parameters say: 0 - entry is not added on lost_found pass and 1
+ - mark item unreachable */
+
+ reiserfs_add_entry (fs, &root_dir_key, ".", name_length (".", root_dir_format),
+ &root_dir_key, ih_flags);
+ reiserfs_add_entry (fs, &root_dir_key, "..", name_length ("..", root_dir_format),
+ &parent_root_dir_key, ih_flags);
+}
+
+
+/* we only can use a file for filesystem or journal if it is either not
+ mounted block device or regular file and we are forced to use it */
+int can_we_format_it (char * device_name, int force)
+{
+ mode_t mode;
+ dev_t rdev;
+
+
+ if (is_mounted (device_name)) {
+ /* device looks mounted */
+ reiserfs_warning (stderr, "'%s' looks mounted.", device_name);
+ check_forcing_ask_confirmation (force);
+ }
+
+ mode = get_st_mode (device_name);
+ rdev = get_st_rdev (device_name);
+
+ if (!S_ISBLK (mode)) {
+ /* file is not a block device */
+ reiserfs_warning (stderr, "%s is not a block special device", device_name);
+ check_forcing_ask_confirmation (force);
+ } else {
+ /* from e2progs-1.18/misc/mke2fs.c */
+
+
+/*FIXME: it should be probably rewritten for 2.5 later*/
+#ifndef MAJOR
+#define MAJOR(dev) ((dev)>>8)
+#define MINOR(dev) ((dev) & 0xff)
+#endif
+#ifndef SCSI_BLK_MAJOR
+#define SCSI_BLK_MAJOR(M) ((M) == SCSI_DISK_MAJOR || (M) == SCSI_CDROM_MAJOR)
+#endif
+
+#ifndef IDE_DISK_MAJOR
+#ifdef IDE9_MAJOR
+#define IDE_DISK_MAJOR(M) (MAJOR(rdev) == IDE0_MAJOR || MAJOR(rdev) == IDE1_MAJOR || \
+ MAJOR(rdev) == IDE2_MAJOR || MAJOR(rdev) == IDE3_MAJOR || \
+ MAJOR(rdev) == IDE4_MAJOR || MAJOR(rdev) == IDE5_MAJOR || \
+ MAJOR(rdev) == IDE6_MAJOR || MAJOR(rdev) == IDE7_MAJOR || \
+ MAJOR(rdev) == IDE8_MAJOR || MAJOR(rdev) == IDE9_MAJOR)
+#else
+#define IDE_DISK_MAJOR(M) (MAJOR(rdev) == IDE0_MAJOR || MAJOR(rdev) == IDE1_MAJOR || \
+ MAJOR(rdev) == IDE2_MAJOR || MAJOR(rdev) == IDE3_MAJOR || \
+ MAJOR(rdev) == IDE4_MAJOR || MAJOR(rdev) == IDE5_MAJOR)
+#endif
+#endif
+
+ if ((IDE_DISK_MAJOR (MAJOR(rdev)) && MINOR (rdev) % 64 == 0) ||
+ (SCSI_BLK_MAJOR (MAJOR(rdev)) && MINOR (rdev) % 16 == 0)) {
+ /* /dev/hda or similar */
+ reiserfs_warning (stderr, "%s is entire device, not just one partition!",
+ device_name);
+ check_forcing_ask_confirmation (force);
+ }
+ }
+
+ return 1;
+}
+
+
+#if 0
+/*tune*/
+#define check_forcing_ask_confirmation() \
+ if (!Force) {\
+ /* avoid formatting it without being forced */\
+ reiserfs_warning (stderr, "Use -f to force over\n");\
+ return 0;\
+ }\
+ if (Force == 1) {\
+ if (!user_confirmed (stderr, "Continue (y/n):", "y\n"))\
+ return 0;\
+ }\
+
+
+/* we only can use a file for filesystem or journal if it is either not
+ mounted block device or regular file and we are forced to use it */
+static int can_we_format_it (char * device_name)
+{
+ mode_t mode;
+ dev_t rdev;
+
+
+ if (is_mounted (device_name)) {
+ /* device looks mounted */
+ message("'%s' looks mounted.\n", device_name);
+ check_forcing_ask_confirmation ();
+ }
+
+ mode = get_st_mode (device_name);
+ rdev = get_st_rdev (device_name);
+
+ if (!S_ISBLK (mode)) {
+ /* file is not a block device */
+ message("Can not create a journal on not a block device file %s\n", device_name);
+ exit (1);
+ } else {
+ /* from e2progs-1.18/misc/mke2fs.c */
+ if ((MAJOR (rdev) == HD_MAJOR && MINOR (rdev) % 64 == 0) ||
+ (SCSI_BLK_MAJOR (rdev) && MINOR (rdev) % 16 == 0)) {
+ /* /dev/hda or similar */
+ message("%s is entire device, not just one partition!\n",
+ device_name);
+ check_forcing_ask_confirmation ();
+ }
+ }
+
+ return 1;
+}
+
+
+/*mkreiserfs*/
+/* we only can use a file for filesystem or journal if it is either not
+ mounted block device or regular file and we are forced to use it */
+static int can_we_format_it (char * device_name, int force)
+{
+ mode_t mode;
+ dev_t rdev;
+
+ if (is_mounted (device_name)) {
+ /* device looks mounted */
+ message("'%s' looks mounted.", device_name);
+ check_forcing_ask_confirmation ();
+ }
+
+ mode = get_st_mode (device_name);
+ rdev = get_st_rdev (device_name);
+
+ if (!S_ISBLK (mode)) {
+ /* file is not a block device */
+ message("%s is not a block special device", device_name);
+ check_forcing_ask_confirmation ();
+ } else {
+ if (((MAJOR (rdev) == IDE0_MAJOR ||
+ MAJOR (rdev) == IDE1_MAJOR ||
+ MAJOR (rdev) == IDE2_MAJOR ||
+ MAJOR (rdev) == IDE3_MAJOR ||
+ MAJOR (rdev) == IDE4_MAJOR ||
+ MAJOR (rdev) == IDE5_MAJOR ||
+ MAJOR (rdev) == IDE6_MAJOR ||
+ MAJOR (rdev) == IDE7_MAJOR ||
+ MAJOR (rdev) == IDE8_MAJOR ||
+ MAJOR (rdev) == IDE9_MAJOR) &&
+ MINOR (rdev) % 64 == 0) ||
+ (SCSI_BLK_MAJOR (MAJOR (rdev)) &&
+ MINOR (rdev) % 16 == 0)) {
+ /* /dev/hda or similar */
+ message("%s is entire device, not just one partition!",
+ device_name);
+ check_forcing_ask_confirmation ();
+ }
+ }
+
+ return 1;
+}
+
+#endif
+
+
+
+
+int create_badblock_bitmap (reiserfs_filsys_t * fs, char * badblocks_file) {
+ FILE * fd;
+ char buf[128];
+ __u32 blocknr;
+ int count;
+
+ fd = fopen (badblocks_file, "r");
+
+ if (fd == NULL) {
+ fprintf (stderr, "%s: could not open badblock file %s, work without it\n",
+ __FUNCTION__, badblocks_file);
+ return 1;
+ }
+
+ fs->fs_badblocks_bm = reiserfs_create_bitmap (get_sb_block_count (fs->fs_ondisk_sb));
+ reiserfs_bitmap_zero (fs->fs_badblocks_bm);
+
+ while (!feof (fd)) {
+ if (fgets(buf, sizeof(buf), fd) == NULL)
+ break;
+ count = sscanf(buf, "%u", &blocknr);
+
+ if (count <= 0)
+ continue;
+
+ if (blocknr < get_sb_block_count (fs->fs_ondisk_sb) && !not_data_block (fs, blocknr)) {
+ reiserfs_bitmap_set_bit (fs->fs_badblocks_bm, blocknr);
+ } else {
+ fprintf (stderr, "%s: bad block number %u in badblocks file\n", __FUNCTION__, blocknr);
+ }
+ }
+
+ fclose (fd);
+
+ return 0;
+}
+
+void add_badblock_list (reiserfs_filsys_t * fs, int no_badblock_in_tree_yet) {
+ struct tree_balance tb;
+ struct key badblock_key = {-1, -1, {{0, 0}}};
+ struct path badblock_path;
+ struct item_head * tmp_ih;
+ struct item_head badblock_ih;
+// char item[UNFM_P_SIZE];
+ struct unfm_nodeinfo ni;
+
+ __u64 offset;
+ __u32 i, j;
+
+ if (fs->fs_badblocks_bm == NULL)
+ return;
+
+ /* delete all items with badblock_key */
+ while (1) {
+ reiserfs_search_by_key_4 (fs, &badblock_key, &badblock_path);
+
+ if (get_blkh_nr_items ( B_BLK_HEAD (get_bh(&badblock_path))) <= PATH_LAST_POSITION (&badblock_path)) {
+ pathrelse (&badblock_path);
+ break;
+ }
+
+ tmp_ih = get_ih(&badblock_path);
+
+ if (get_key_dirid(&tmp_ih->ih_key) != (__u32)-1 ||
+ get_key_objectid(&tmp_ih->ih_key) != (__u32)-1 || !is_indirect_ih (tmp_ih)) {
+ pathrelse (&badblock_path);
+ break;
+ }
+
+ if (no_badblock_in_tree_yet)
+ reiserfs_panic ("$s: bad block list found in the tree\n", __FUNCTION__);
+
+ memset (get_item (&badblock_path), 0, get_ih_item_len (tmp_ih));
+
+
+ init_tb_struct (&tb, fs, &badblock_path, -(IH_SIZE + get_ih_item_len(PATH_PITEM_HEAD (&badblock_path))));
+
+ if (fix_nodes (M_DELETE, &tb, 0) != CARRY_ON)
+ die ("%s: fix_nodes failed", __FUNCTION__);
+
+ do_balance (/*tb.transaction_handle,*/ &tb, 0, 0, M_DELETE, 0/*zero num*/);
+ }
+
+ set_ih_key_format (&badblock_ih, KEY_FORMAT_2);
+ set_ih_item_len (&badblock_ih, UNFM_P_SIZE);
+ set_ih_free_space (&badblock_ih, 0);
+ set_ih_location (&badblock_ih, 0);
+ set_key_dirid (&badblock_ih.ih_key, -1);
+ set_key_objectid (&badblock_ih.ih_key, -1);
+ set_type (KEY_FORMAT_2, &badblock_ih.ih_key, TYPE_INDIRECT);
+
+ j = 0;
+ ni.unfm_freespace = 0;
+
+ /* insert all badblock pointers */
+ for (i = 0; i < fs->fs_badblocks_bm->bm_bit_size; i++) {
+ int retval;
+
+ if (!reiserfs_bitmap_test_bit (fs->fs_badblocks_bm, i))
+ continue;
+
+ offset = j * fs->fs_blocksize + 1;
+ set_offset (KEY_FORMAT_2, &badblock_ih.ih_key, offset);
+ ni.unfm_nodenum = cpu_to_le32 (i);
+
+ retval = usearch_by_position (fs, &badblock_ih.ih_key, key_format (&badblock_ih.ih_key), &badblock_path);
+
+ switch (retval) {
+ case (FILE_NOT_FOUND):
+ init_tb_struct (&tb, fs, &badblock_path, IH_SIZE + get_ih_item_len(&badblock_ih));
+ if (fix_nodes (/*tb.transaction_handle,*/ M_INSERT, &tb, &badblock_ih/*, body*/) != CARRY_ON)
+ die ("reiserfsck_insert_item: fix_nodes failed");
+ do_balance (/*tb.transaction_handle,*/ &tb, &badblock_ih, (void *)&ni.unfm_nodenum , M_INSERT, 0/*zero num*/);
+
+// reiserfsck_insert_item (&badblock_path, &badblock_ih, item);
+
+ break;
+
+ case (POSITION_NOT_FOUND):
+ /* take unformatted pointer from an indirect item */
+
+ init_tb_struct (&tb, fs, &badblock_path, UNFM_P_SIZE);
+
+ if (fix_nodes (M_PASTE, &tb, 0) != CARRY_ON)
+ die ("reiserfsck_paste_into_item: fix_nodes failed");
+
+ do_balance (&tb, 0, (const char *)&ni, M_PASTE, 0);
+
+// reiserfsck_file_write (&badblock_ih, item, 1 /* was in tree to avoid problems with bitmaps */);
+// reiserfsck_paste_into_item (path, (const char *)&ni, UNFM_P_SIZE);
+
+ break;
+ }
+
+ j++;
+ }
+}
diff --git a/reiserfscore/stree.c b/reiserfscore/stree.c
index aa81791..cde7c7e 100644
--- a/reiserfscore/stree.c
+++ b/reiserfscore/stree.c
@@ -40,15 +40,7 @@
/* Does the buffer contain a disk block which is in the tree. */
inline int B_IS_IN_TREE (struct buffer_head * p_s_bh)
{
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( node_level (p_s_bh) > MAX_HEIGHT ) {
- reiserfs_panic(0, "PAP-1010: B_IS_IN_TREE: block (%b) has too big level (%z)",
- p_s_bh, p_s_bh);
- }
-#endif
-
- return ( node_level (p_s_bh) != FREE_LEVEL );
+ return ( get_blkh_level (B_BLK_HEAD (p_s_bh)) != FREE_LEVEL );
}
@@ -58,18 +50,20 @@ inline int B_IS_IN_TREE (struct buffer_head * p_s_bh)
0 if key1 = key2
1 if key1 > key2
*/
-int comp_short_keys (void * k1, void * k2)
+
+int comp_short_keys (const void * k1, const void * k2)
{
- __u32 * p_s_key1, * p_s_key2;
int n_key_length = REISERFS_SHORT_KEY_LEN;
-
- p_s_key1 = (__u32 *)k1;
- p_s_key2 = (__u32 *)k2;
+ __u32 * p_s_key1 = (__u32 *)k1;
+ __u32 * p_s_key2 = (__u32 *)k2;
+ __u32 u1, u2;
for( ; n_key_length--; ++p_s_key1, ++p_s_key2 ) {
- if ( *p_s_key1 < *p_s_key2 )
+ u1 = le32_to_cpu(*p_s_key1) ;
+ u2 = le32_to_cpu(*p_s_key2) ;
+ if ( u1 < u2 )
return -1;
- if ( *p_s_key1 > *p_s_key2 )
+ if ( u1 > u2 )
return 1;
}
@@ -77,36 +71,53 @@ int comp_short_keys (void * k1, void * k2)
}
+int comp_keys_3 (const void * p1, const void * p2)
+{
+ int retval;
+ const struct key * k1 = p1;
+ const struct key * k2 = p2;
+ loff_t off1, off2;
+
+ retval = comp_short_keys (k1, k2);
+ if (retval)
+ return retval;
+ off1 = get_offset(k1) ;
+ off2 = get_offset(k2) ;
+ if (off1 < off2)
+ return -1;
+
+ if (off1 > off2)
+ return 1;
+
+ return 0;
+}
+
+
/*
Compare keys using all 4 key fields.
Returns: -1 if key1 < key2
0 if key1 = key2
1 if key1 > key2
*/
-int comp_keys (void * p1, void * p2)
+int comp_keys (const void * p1, const void * p2)
{
int retval;
- struct key * k1, * k2;
-
- k1 = p1;
- k2 = p2;
+ const struct key * k1 = p1;
+ const struct key * k2 = p2;
+ __u32 u1, u2;
- retval = comp_short_keys (k1, k2);
+ retval = comp_keys_3 (k1, k2);
if (retval)
return retval;
- if (get_offset (k1) < get_offset (k2))
- return -1;
+ u1 = get_type (k1);
+ u2 = get_type (k2);
- if (get_offset (k1) > get_offset (k2))
- return 1;
-
- /* this part is needed only when tail conversion is in progress */
- if (get_type (k1) < get_type (k2))
- return -1;
+ if (u1 < u2)
+ return -1;
- if (get_type (k1) > get_type (k2))
- return 1;
+ if (u1 > u2)
+ return 1;
return 0;
}
@@ -155,14 +166,6 @@ inline int bin_search (
return ITEM_NOT_FOUND;
}
-#ifdef CONFIG_REISERFS_CHECK
-extern struct tree_balance * cur_tb;
-extern struct tree_balance init_tb;
-extern int init_item_pos, init_pos_in_item, init_mode;
-#endif
-
-
-
/* Minimal possible key. It is never in the tree. */
struct key MIN_KEY = {0, 0, {{0, 0},}};
@@ -176,26 +179,17 @@ struct key MAX_KEY = {0xffffffff, 0xffffffff, {{0xffffffff, 0xffffffff},}};
there is no delimiting key in the tree (buffer is first or last buffer in
tree), and in this case we return a special key, either MIN_KEY or
MAX_KEY. */
-inline struct key * get_lkey (
- struct path * p_s_chk_path,
- struct super_block * p_s_sb
- ) {
- int n_position, n_path_offset = p_s_chk_path->path_length;
+struct key * get_lkey (struct path * p_s_chk_path,
+ reiserfs_filsys_t * fs)
+{
+ struct reiserfs_super_block * sb;
+ int n_position, n_path_offset = p_s_chk_path->path_length;
struct buffer_head * p_s_parent;
-#ifdef CONFIG_REISERFS_CHECK
- if ( n_path_offset < FIRST_PATH_ELEMENT_OFFSET )
- reiserfs_panic(p_s_sb,"PAP-5010: get_lkey: illegal offset in the path");
-#endif
+ sb = fs->fs_ondisk_sb;
/* While not higher in path than first element. */
while ( n_path_offset-- > FIRST_PATH_ELEMENT_OFFSET ) {
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( ! buffer_uptodate(PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset)) )
- reiserfs_panic(p_s_sb, "PAP-5020: get_lkey: parent is not uptodate");
-#endif
-
/* Parent at the path is not in the tree now. */
if ( ! B_IS_IN_TREE(p_s_parent = PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset)) )
return &MAX_KEY;
@@ -203,7 +197,7 @@ inline struct key * get_lkey (
if ( (n_position = PATH_OFFSET_POSITION(p_s_chk_path, n_path_offset)) > B_NR_ITEMS(p_s_parent) )
return &MAX_KEY;
/* Check whether parent at the path really points to the child. */
- if ( B_N_CHILD_NUM(p_s_parent, n_position) !=
+ if ( get_dc_child_blocknr (B_N_CHILD (p_s_parent, n_position)) !=
PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset + 1)->b_blocknr )
return &MAX_KEY;
/* Return delimiting key if position in the parent is not equal to zero. */
@@ -212,33 +206,24 @@ inline struct key * get_lkey (
}
/* Return MIN_KEY if we are in the root of the buffer tree. */
if ( PATH_OFFSET_PBUFFER(p_s_chk_path, FIRST_PATH_ELEMENT_OFFSET)->b_blocknr ==
- SB_ROOT_BLOCK (p_s_sb) )
+ get_sb_root_block (sb) )
return &MIN_KEY;
return &MAX_KEY;
}
/* Get delimiting key of the buffer at the path and its right neighbor. */
-inline struct key * get_rkey (
- struct path * p_s_chk_path,
- struct super_block * p_s_sb
- ) {
+struct key * get_rkey (struct path * p_s_chk_path,
+ reiserfs_filsys_t * fs)
+{
+ struct reiserfs_super_block * sb;
int n_position,
n_path_offset = p_s_chk_path->path_length;
struct buffer_head * p_s_parent;
-#ifdef CONFIG_REISERFS_CHECK
- if ( n_path_offset < FIRST_PATH_ELEMENT_OFFSET )
- reiserfs_panic(p_s_sb,"PAP-5030: get_rkey: illegal offset in the path");
-#endif
+ sb = fs->fs_ondisk_sb;
while ( n_path_offset-- > FIRST_PATH_ELEMENT_OFFSET ) {
-
-#ifdef CONFIG_REISERFS_CHECK
- if ( ! buffer_uptodate(PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset)) )
- reiserfs_panic(p_s_sb, "PAP-5040: get_rkey: parent is not uptodate");
-#endif
-
/* Parent at the path is not in the tree now. */
if ( ! B_IS_IN_TREE(p_s_parent = PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset)) )
return &MIN_KEY;
@@ -246,7 +231,7 @@ inline struct key * get_rkey (
if ( (n_position = PATH_OFFSET_POSITION(p_s_chk_path, n_path_offset)) > B_NR_ITEMS(p_s_parent) )
return &MIN_KEY;
/* Check whether parent at the path really points to the child. */
- if ( B_N_CHILD_NUM(p_s_parent, n_position) !=
+ if ( get_dc_child_blocknr (B_N_CHILD (p_s_parent, n_position)) !=
PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset + 1)->b_blocknr )
return &MIN_KEY;
/* Return delimiting key if position in the parent is not the last one. */
@@ -255,7 +240,7 @@ inline struct key * get_rkey (
}
/* Return MAX_KEY if we are in the root of the buffer tree. */
if ( PATH_OFFSET_PBUFFER(p_s_chk_path, FIRST_PATH_ELEMENT_OFFSET)->b_blocknr ==
- SB_ROOT_BLOCK (p_s_sb) )
+ get_sb_root_block (sb) )
return &MAX_KEY;
return &MIN_KEY;
}
@@ -271,38 +256,22 @@ inline struct key * get_rkey (
static inline int key_in_buffer (
struct path * p_s_chk_path, /* Path which should be checked. */
struct key * p_s_key, /* Key which should be checked. */
- struct super_block * p_s_sb /* Super block pointer. */
+ reiserfs_filsys_t * fs /* Super block pointer. */
) {
-#ifdef CONFIG_REISERFS_CHECK
- if ( ! p_s_key || p_s_chk_path->path_length < FIRST_PATH_ELEMENT_OFFSET ||
- p_s_chk_path->path_length > MAX_HEIGHT )
- reiserfs_panic(p_s_sb, "PAP-5050: key_in_buffer: pointer to the key(%p) is NULL or illegal path length(%d)",
- p_s_key, p_s_chk_path->path_length);
-
- if ( PATH_PLAST_BUFFER(p_s_chk_path)->b_dev == NODEV )
- reiserfs_panic(p_s_sb, "PAP-5060: key_in_buffer: device must not be NODEV");
-#endif
-
- if ( COMP_KEYS(get_lkey(p_s_chk_path, p_s_sb), p_s_key) == 1 )
+ if ( COMP_KEYS(get_lkey(p_s_chk_path, fs), p_s_key) == 1 )
return 0;
- if ( COMP_KEYS(p_s_key, get_rkey(p_s_chk_path, p_s_sb)) != -1 )
+ if ( COMP_KEYS(p_s_key, get_rkey(p_s_chk_path, fs)) != -1 )
return 0;
return 1;
}
-
/* Release all buffers in the path. */
void pathrelse (struct path * p_s_search_path)
{
int n_path_offset = p_s_search_path->path_length;
-#ifdef CONFIG_REISERFS_CHECK
- if ( n_path_offset < ILLEGAL_PATH_ELEMENT_OFFSET )
- reiserfs_panic(NULL, "PAP-5090: pathrelse: illegal path offset");
-#endif
-
- while ( n_path_offset > ILLEGAL_PATH_ELEMENT_OFFSET )
+ while ( n_path_offset > ILLEGAL_PATH_ELEMENT_OFFSET )
brelse(PATH_OFFSET_PBUFFER(p_s_search_path, n_path_offset--));
p_s_search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
@@ -331,119 +300,89 @@ void pathrelse (struct path * p_s_search_path)
key. search_by_key returns a path that must be checked for the
correctness of the top of the path but need not be checked for the
correctness of the bottom of the path */
-int search_by_key(
- struct super_block * p_s_sb, /* Super block. */
- struct key * p_s_key, /* Key to search. */
- struct path * p_s_search_path,/* This structure was allocated and initialized by
- the calling function. It is filled up by this
- function. */
- int * p_n_repeat, /* Whether schedule occured. */
- int n_stop_level /* How far down the tree to search.*/
- ) {
- dev_t n_dev = p_s_sb->s_dev;
- int n_repeat,
- n_block_number = SB_ROOT_BLOCK (p_s_sb),
- expected_level = SB_TREE_HEIGHT (p_s_sb),
- n_block_size = p_s_sb->s_blocksize;
+int search_by_key (reiserfs_filsys_t * fs,
+ struct key * p_s_key, /* Key to search */
+ struct path * p_s_search_path,/* This structure was
+ allocated and
+ initialized by the
+ calling
+ function. It is
+ filled up by this
+ function. */
+ int n_stop_level) /* How far down the tree to search.*/
+{
+ struct reiserfs_super_block * sb;
+ int n_block_number,
+ expected_level,
+ n_block_size = fs->fs_blocksize;
struct buffer_head * p_s_bh;
struct path_element * p_s_last_element;
int n_retval;
- int right_neighbor_of_leaf_node;
-#ifdef CONFIG_REISERFS_CHECK
- int n_repeat_counter = 0;
-#endif
+ sb = fs->fs_ondisk_sb;
+ n_block_number = get_sb_root_block (sb);
+ expected_level = get_sb_tree_height (sb);
+
/* As we add each node to a path we increase its count. This
means that we must be careful to release all nodes in a path
before we either discard the path struct or re-use the path
struct, as we do here. */
pathrelse (p_s_search_path);
- *p_n_repeat = CARRY_ON;
/* With each iteration of this loop we search through the items in
the current node, and calculate the next current node(next path
element) for the next iteration of this loop.. */
while ( 1 ) {
-#ifdef CONFIG_REISERFS_CHECK
- if ( !(++n_repeat_counter % 50000) )
- printk ("PAP-5100: search_by_key(pid %u): there were %d searches from the tree_root lokking for key %p\n",
- current->pid, n_repeat_counter, p_s_key);
-#endif
-
/* prep path to have another element added to it. */
p_s_last_element = PATH_OFFSET_PELEMENT(p_s_search_path, ++p_s_search_path->path_length);
expected_level --;
- n_repeat = CARRY_ON;
/* Read the next tree node, and set the last element in the
path to have a pointer to it. */
if ( ! (p_s_bh = p_s_last_element->pe_buffer =
- reiserfs_bread(n_dev, n_block_number, n_block_size, &n_repeat)) ) {
+ bread (fs->fs_dev, n_block_number, n_block_size)) ) {
p_s_search_path->path_length --;
pathrelse(p_s_search_path);
- *p_n_repeat |= n_repeat;
return IO_ERROR;
}
- *p_n_repeat |= n_repeat;
-
/* It is possible that schedule occured. We must check whether
the key to search is still in the tree rooted from the
current buffer. If not then repeat search from the root. */
- if ( n_repeat != CARRY_ON &&
- (!B_IS_IN_TREE (p_s_bh) || (! key_in_buffer(p_s_search_path, p_s_key, p_s_sb))) ) {
- pathrelse (p_s_search_path);
+ if (!B_IS_IN_TREE (p_s_bh) ||
+ ! key_in_buffer(p_s_search_path, p_s_key, fs))
+ reiserfs_panic ("search_by_key: something wrong with the tree");
- /* Get the root block number so that we can repeat the
- search starting from the root. */
- n_block_number = SB_ROOT_BLOCK (p_s_sb);
- expected_level = SB_TREE_HEIGHT (p_s_sb);
- right_neighbor_of_leaf_node = 0;
-
- /* repeat search from the root */
- continue;
- }
-
-#ifdef CONFIG_REISERFS_CHECK
-
- if ( ! key_in_buffer(p_s_search_path, p_s_key, p_s_sb) )
- reiserfs_panic(p_s_sb, "PAP-5130: search_by_key: key is not in the buffer");
- if ( cur_tb ) {
-/* print_tb (init_mode, init_item_pos, init_pos_in_item, &init_tb, "5140");*/
- reiserfs_panic(p_s_sb, "PAP-5140: search_by_key: schedule occurred in do_balance!");
- }
-
-#endif
-
- // make sure, that the node contents look like a nod of
- // certain level
+ /* make sure, that the node contents look like a node of
+ certain level */
if (!is_tree_node (p_s_bh, expected_level)) {
print_block (stderr, 0, p_s_bh, 3, -1, -1);
- reiserfs_panic ("vs-5150: search_by_key: expeced level %d", expected_level);
- pathrelse (p_s_search_path);
- return IO_ERROR;
+ reiserfs_panic ("search_by_key: expected level %d", expected_level);
}
/* ok, we have acquired next formatted node in the tree */
n_retval = bin_search (p_s_key, B_N_PITEM_HEAD(p_s_bh, 0), B_NR_ITEMS(p_s_bh),
is_leaf_node (p_s_bh) ? IH_SIZE : KEY_SIZE, &(p_s_last_element->pe_position));
- if (node_level (p_s_bh) == n_stop_level)
+ if (get_blkh_level (B_BLK_HEAD (p_s_bh)) == n_stop_level)
return n_retval;
/* we are not in the stop level */
if (n_retval == ITEM_FOUND)
- /* item has been found, so we choose the pointer which is to the right of the found one */
+ /* item has been found, so we choose the pointer which is
+ to the right of the found one */
p_s_last_element->pe_position++;
- /* if item was not found we choose the position which is to the left of the found item. This
- requires no code, bin_search did it already.*/
+ /* if item was not found we choose the position which is to
+ the left of the found item. This requires no code,
+ bin_search did it already.*/
- /* So we have chosen a position in the current node which is an
- internal node. Now we calculate child block number by position in the node. */
- n_block_number = B_N_CHILD_NUM(p_s_bh, p_s_last_element->pe_position);
+ /* So we have chosen a position in the current node which is
+ an internal node. Now we calculate child block number by
+ position in the node. */
+ n_block_number = get_dc_child_blocknr (B_N_CHILD (p_s_bh, p_s_last_element->pe_position));
}
}
@@ -454,14 +393,14 @@ int bin_search_in_dir_item (struct item_head * ih, struct reiserfs_de_head * deh
int rbound, lbound, j;
lbound = 0;
- rbound = ih_entry_count (ih) - 1;
+ rbound = get_ih_entry_count (ih) - 1;
for (j = (rbound + lbound) / 2; lbound <= rbound; j = (rbound + lbound) / 2) {
- if (get_offset (key) < deh_offset (deh + j)) {
+ if (get_offset (key) < get_deh_offset (deh + j)) {
rbound = j - 1;
continue;
}
- if (get_offset (key) > deh_offset (deh + j)) {
+ if (get_offset (key) > get_deh_offset (deh + j)) {
lbound = j + 1;
continue;
}
diff --git a/reiserfsprogs.spec b/reiserfsprogs.spec
index ad24125..8f30758 100644
--- a/reiserfsprogs.spec
+++ b/reiserfsprogs.spec
@@ -1,16 +1,18 @@
+%define reiserfsprogsversion 3.6.2
+
Vendor: Hans Reiser
Distribution: Hans Reiser
Name: reiserfsprogs
Release: 1
-Copyright: 2001 Hans Reiser
+Copyright: 2002 Hans Reiser
Group: Unsorted
Packager: anthon@mnt.org
-Version: 3.x.0j
+Version: %{reiserfsprogsversion}
Summary: utilities belonging to the Reiser filesystem
-Source: reiserfsprogs-%{version}.tar.gz
-BuildRoot: /var/tmp/rpm-reiserfsprogs
+Source: reiserfsprogs-%{reiserfsprogsversion}.tar.gz
+BuildRoot: %{_tmppath}/rpmbuildroot-%{name}
%description
The reiserfsprogs package contains programs for creating (mkreiserfs),
@@ -22,21 +24,25 @@ Authors:
Hans Reiser <reiser@namesys.com>
Vitaly Fertman <vetalf@inbox.ru>
Alexander Zarochentcev <zam@namesys.com>
-Vladimir Saveliev <vs@namesys.botik.ru>
+Vladimir Saveliev <monstr@namesys.com>
%prep
-%setup -q
+# Jeff Johnson states that RPM doesn't delete obviouse crap like / if
+# buildroot is set differently since RPM 3.0.4 (rpm mailing list 2001-04-10)
+ rm -rf $RPM_BUILD_ROOT
+%setup -q -n reiserfsprogs-%{reiserfsprogsversion}
# %patch
%build
MANDIR=$(dirname $(dirname $(man -w fsck | cut -d ' ' -f 1)))
./configure --prefix="" --mandir=$MANDIR
- make all
+ %{__make} all
%install
- mkdir -p $RPM_BUILD_ROOT/sbin
- make DESTDIR=$RPM_BUILD_ROOT install
+ mkdir -p $RPM_BUILD_ROOT/sbin
+ %{__make} DESTDIR=$RPM_BUILD_ROOT install
# do we need this?
- cd $RPM_BUILD_ROOT/sbin
- ln -sf reiserfsck fsck.reiserfs
+ cd $RPM_BUILD_ROOT/sbin
+ %{__ln_s} -f reiserfsck fsck.reiserfs
+ %{__ln_s} -f mkreiserfs mkfs.reiserfs
# __os_install_post is normally executed after %install disable it
%define ___build_post %{nil}
@@ -46,7 +52,7 @@ Vladimir Saveliev <vs@namesys.botik.ru>
# now we have all the files execpt for docs, but their owner is unimportant
cd $RPM_BUILD_ROOT
-rm -f rpm-filelist
+%{__rm} -f rpm-filelist
# we do not have special directories to make
#find . -type d \
# | sed '1,2d;s,^\.,\%attr(-\,root\,root) \%dir ,' >> rpm-filelist
@@ -55,8 +61,24 @@ find . -type f \
find . -type l \
| sed 's,^\.,\%attr(-\,root\,root) ,' >> rpm-filelist
+%post
+CONFIG=/usr/src/linux/.config
+
+if [ -f $CONFIG ] ; then
+ source $CONFIG
+fi
+
+if [ -z $CONFIG_REISERFS_FS ] ; then
+ echo -e "\nIn $CONFIG , you probably have to set:"
+ if [ "$CONFIG_EXPERIMENTAL" != "y" ] ; then
+ echo -e 'CONFIG_EXPERIMENTAL=y'
+ fi
+ echo -e 'CONFIG_REISERFS_FS=y\n or'
+ echo -e 'CONFIG_REISERFS_FS=m'
+ echo -e 'and recompile and reboot your kernel if you cannot use the\nreiserfsprogs utilities'
+fi
+
%clean
-# in case some overrides buildroot with / don't remove the whole tree
- rm -rf /var/tmp/rpm-reiserfsprogs
-%files -f /var/tmp/rpm-reiserfsprogs/rpm-filelist
+ %{__rm} -rf $RPM_BUILD_ROOT
+%files -f %{buildroot}/rpm-filelist
%doc README
diff --git a/resize_reiserfs/Makefile.am b/resize_reiserfs/Makefile.am
index 0af4bea..24c669a 100644
--- a/resize_reiserfs/Makefile.am
+++ b/resize_reiserfs/Makefile.am
@@ -4,6 +4,5 @@ resize_reiserfs_SOURCES = fe.c resize_reiserfs.c do_shrink.c resize.h
man_MANS = resize_reiserfs.8
EXTRA_DIST = $(man_MANS)
-LDADD = ../lib/libmisc.a ../reiserfscore/libcore.a
+LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a
-INCLUDES = -I../include
diff --git a/resize_reiserfs/Makefile.in b/resize_reiserfs/Makefile.in
index d03f545..ab2de68 100644
--- a/resize_reiserfs/Makefile.in
+++ b/resize_reiserfs/Makefile.in
@@ -1,6 +1,6 @@
-# Makefile.in generated automatically by automake 1.4 from Makefile.am
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
-# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc.
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
@@ -62,6 +62,7 @@ MAKEINFO = @MAKEINFO@
PACKAGE = @PACKAGE@
RANLIB = @RANLIB@
VERSION = @VERSION@
+sbindir = @sbindir@
sbin_PROGRAMS = resize_reiserfs
@@ -69,22 +70,21 @@ resize_reiserfs_SOURCES = fe.c resize_reiserfs.c do_shrink.c resize.h
man_MANS = resize_reiserfs.8
EXTRA_DIST = $(man_MANS)
-LDADD = ../lib/libmisc.a ../reiserfscore/libcore.a
-
-INCLUDES = -I../include
+LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../include/config.h
CONFIG_CLEAN_FILES =
PROGRAMS = $(sbin_PROGRAMS)
-DEFS = @DEFS@ -I. -I$(srcdir)
+DEFS = @DEFS@ -I. -I$(srcdir) -I../include
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
resize_reiserfs_OBJECTS = fe.o resize_reiserfs.o do_shrink.o
resize_reiserfs_LDADD = $(LDADD)
-resize_reiserfs_DEPENDENCIES = ../lib/libmisc.a \
-../reiserfscore/libcore.a
+resize_reiserfs_DEPENDENCIES = $(top_srcdir)/lib/libmisc.a \
+$(top_srcdir)/reiserfscore/libcore.a
resize_reiserfs_LDFLAGS =
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -239,7 +239,7 @@ distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
- cp -pr $$/$$file $(distdir)/$$file; \
+ cp -pr $$d/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
@@ -247,12 +247,14 @@ distdir: $(DISTFILES)
fi; \
done
do_shrink.o: do_shrink.c resize.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h ../version.h
-fe.o: fe.c resize.h ../include/io.h ../include/misc.h \
- ../include/reiserfs_lib.h ../include/reiserfs_fs.h ../version.h
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h ../include/config.h ../version.h
+fe.o: fe.c resize.h ../include/io.h ../include/misc.h ../include/swab.h \
+ ../include/reiserfs_lib.h ../include/reiserfs_fs.h \
+ ../include/config.h ../version.h
resize_reiserfs.o: resize_reiserfs.c resize.h ../include/io.h \
- ../include/misc.h ../include/reiserfs_lib.h \
- ../include/reiserfs_fs.h ../version.h
+ ../include/misc.h ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h ../include/config.h ../version.h
info-am:
info: info-am
diff --git a/resize_reiserfs/do_shrink.c b/resize_reiserfs/do_shrink.c
index 62b3026..b4530f2 100644
--- a/resize_reiserfs/do_shrink.c
+++ b/resize_reiserfs/do_shrink.c
@@ -1,8 +1,8 @@
/*
- * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
+ * Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
*/
-#include <time.h>
#include "resize.h"
+#include <time.h>
static unsigned long int_node_cnt = 0, int_moved_cnt = 0;
@@ -15,33 +15,31 @@ static unsigned long unused_block;
static unsigned long blocks_used;
static int block_count_mismatch = 0;
-static reiserfs_bitmap_t bmp;
-static reiserfs_filsys_t fs;
-static struct reiserfs_super_block * rs;
+static reiserfs_bitmap_t * bmp;
+static struct reiserfs_super_block * ondisk_sb;
/* abnornal exit from block reallocation process */
-static void quit_resizer()
+static void quit_resizer(reiserfs_filsys_t * fs)
{
/* save changes to bitmap blocks */
- reiserfs_flush_bitmap (bmp, fs);
reiserfs_close (fs);
/* leave fs in ERROR state */
- die ("resize_reiserfs: fs shrinking was not completed successfully, run reiserfsck.\n");
+ DIE ("fs shrinking was not completed successfully, run reiserfsck.");
}
/* block moving */
-static unsigned long move_generic_block(unsigned long block, unsigned long bnd, int h)
+static unsigned long move_generic_block(reiserfs_filsys_t * fs, unsigned long block, unsigned long bnd, int h)
{
struct buffer_head * bh, * bh2;
/* primitive fsck */
- if (block > rs_block_count(rs)) {
+ if (block > get_sb_block_count(ondisk_sb)) {
fprintf(stderr, "resize_reiserfs: invalid block number (%lu) found.\n", block);
- quit_resizer();
+ quit_resizer(fs);
}
/* progress bar, 3D style :) */
if (opt_verbose)
- print_how_far(&total_node_cnt, blocks_used, 1, 0);
+ print_how_far(stderr, &total_node_cnt, blocks_used, 1, 0);
else
total_node_cnt ++;
@@ -55,16 +53,16 @@ static unsigned long move_generic_block(unsigned long block, unsigned long bnd,
return 0;
/* move wrong block */
- bh = bread(fs->s_dev, block, fs->s_blocksize);
+ bh = bread(fs->fs_dev, block, fs->fs_blocksize);
reiserfs_bitmap_find_zero_bit(bmp, &unused_block);
if (unused_block == 0 || unused_block >= bnd) {
fputs ("resize_reiserfs: can\'t find free block\n", stderr);
- quit_resizer();
+ quit_resizer(fs);
}
/* blocknr changing */
- bh2 = getblk(fs->s_dev, unused_block, fs->s_blocksize);
+ bh2 = getblk(fs->fs_dev, unused_block, fs->fs_blocksize);
memcpy(bh2->b_data, bh->b_data, bh2->b_size);
reiserfs_bitmap_clear_bit(bmp, block);
reiserfs_bitmap_set_bit(bmp, unused_block);
@@ -79,11 +77,11 @@ static unsigned long move_generic_block(unsigned long block, unsigned long bnd,
return unused_block;
}
-static unsigned long move_unformatted_block(unsigned long block, unsigned long bnd, int h)
+static unsigned long move_unformatted_block(reiserfs_filsys_t * fs, unsigned long block, unsigned long bnd, int h)
{
unsigned long b;
unfm_node_cnt++;
- b = move_generic_block(block, bnd, h);
+ b = move_generic_block(fs, block, bnd, h);
if (b)
unfm_moved_cnt++;
return b;
@@ -91,7 +89,7 @@ static unsigned long move_unformatted_block(unsigned long block, unsigned long b
/* recursive function processing all tree nodes */
-static unsigned long move_formatted_block(unsigned long block, unsigned long bnd, int h)
+static unsigned long move_formatted_block(reiserfs_filsys_t * fs, unsigned long block, unsigned long bnd, int h)
{
struct buffer_head * bh;
struct item_head *ih;
@@ -99,7 +97,9 @@ static unsigned long move_formatted_block(unsigned long block, unsigned long bnd
int node_is_internal = 0;
int i, j;
- bh = bread(fs->s_dev, block, fs->s_blocksize);
+ bh = bread(fs->fs_dev, block, fs->fs_blocksize);
+ if (!bh)
+ reiserfs_panic ("move_formatted_block: bread failed");
if (is_leaf_node (bh)) {
@@ -116,7 +116,7 @@ static unsigned long move_formatted_block(unsigned long block, unsigned long bnd
if (indirect [j] == 0) /* hole */
continue;
- unfm_block = move_unformatted_block(le32_to_cpu (indirect [j]), bnd, h + 1);
+ unfm_block = move_unformatted_block(fs, le32_to_cpu (indirect [j]), bnd, h + 1);
if (unfm_block) {
indirect [j] = cpu_to_le32 (unfm_block);
mark_buffer_dirty(bh);
@@ -131,14 +131,14 @@ static unsigned long move_formatted_block(unsigned long block, unsigned long bnd
for (i=0; i <= B_NR_ITEMS(bh); i++) {
unsigned long moved_block;
- moved_block = move_formatted_block(B_N_CHILD_NUM(bh, i), bnd, h+1);
+ moved_block = move_formatted_block(fs, get_dc_child_blocknr (B_N_CHILD (bh, i)), bnd, h+1);
if (moved_block) {
- set_dc_block_number (bh, i, moved_block);
+ set_dc_child_blocknr (B_N_CHILD (bh, i), moved_block);
mark_buffer_dirty(bh);
}
}
} else {
- die ("resize_reiserfs: block (%lu) has invalid format\n", block);
+ DIE ("block (%lu) has invalid format\n", block);
}
if (buffer_dirty(bh)) {
@@ -148,7 +148,7 @@ static unsigned long move_formatted_block(unsigned long block, unsigned long bnd
brelse(bh);
- new_blocknr = move_generic_block(block, bnd, h);
+ new_blocknr = move_generic_block(fs, block, bnd, h);
if (new_blocknr) {
if (node_is_internal)
int_moved_cnt++;
@@ -159,14 +159,13 @@ static unsigned long move_formatted_block(unsigned long block, unsigned long bnd
return new_blocknr;
}
-int shrink_fs(reiserfs_filsys_t reiserfs, unsigned long blocks)
+int shrink_fs(reiserfs_filsys_t * fs, unsigned long blocks)
{
unsigned long n_root_block;
unsigned int bmap_nr_new;
- unsigned long int i;
+
- fs = reiserfs;
- rs = fs->s_rs;
+ ondisk_sb = fs->fs_ondisk_sb;
/* warn about alpha version */
{
@@ -178,37 +177,40 @@ int shrink_fs(reiserfs_filsys_t reiserfs, unsigned long blocks)
"Backup of you data is recommended.\n\n"
"Do you want to continue? [y/N]:"
);
+ fflush(stdout);
c = getchar();
if (c != 'y' && c != 'Y')
exit(1);
}
- bmap_nr_new = (blocks - 1) / (8 * fs->s_blocksize) + 1;
-
+ bmap_nr_new = (blocks - 1) / (8 * fs->fs_blocksize) + 1;
+
/* is shrinking possible ? */
- if (rs_block_count(rs) - blocks > rs_free_blocks(rs) + rs_bmap_nr(rs) - bmap_nr_new) {
+ if (get_sb_block_count(ondisk_sb) - blocks > get_sb_free_blocks(ondisk_sb) + get_sb_bmap_nr(ondisk_sb) - bmap_nr_new) {
fprintf(stderr, "resize_reiserfs: can\'t shrink fs; too many blocks already allocated\n");
return -1;
}
reiserfs_reopen(fs, O_RDWR);
- set_state (fs->s_rs, REISERFS_ERROR_FS);
- mark_buffer_uptodate(SB_BUFFER_WITH_SB(fs), 1);
- mark_buffer_dirty(SB_BUFFER_WITH_SB(fs));
- bwrite(SB_BUFFER_WITH_SB(fs));
+ if (!reiserfs_open_ondisk_bitmap (fs))
+ DIE("cannot open ondisk bitmap");
+ bmp = fs->fs_bitmap2;
+ ondisk_sb = fs->fs_ondisk_sb;
+
+ set_sb_fs_state (fs->fs_ondisk_sb, REISERFS_CORRUPTED);
+ mark_buffer_uptodate(fs->fs_super_bh, 1);
+ mark_buffer_dirty(fs->fs_super_bh);
+ bwrite(fs->fs_super_bh);
/* calculate number of data blocks */
blocks_used =
- SB_BLOCK_COUNT(fs)
- - SB_FREE_BLOCKS(fs)
- - SB_BMAP_NR(fs)
- - SB_JOURNAL_SIZE(fs)
- - REISERFS_DISK_OFFSET_IN_BYTES / fs->s_blocksize
+ get_sb_block_count(fs->fs_ondisk_sb)
+ - get_sb_free_blocks(fs->fs_ondisk_sb)
+ - get_sb_bmap_nr(fs->fs_ondisk_sb)
+ - get_jp_journal_size(sb_jp (fs->fs_ondisk_sb))
+ - REISERFS_DISK_OFFSET_IN_BYTES / fs->fs_blocksize
- 2; /* superblock itself and 1 descriptor after the journal */
- bmp = reiserfs_create_bitmap(rs_block_count(rs));
- reiserfs_fetch_disk_bitmap(bmp, fs);
-
unused_block = 1;
if (opt_verbose) {
@@ -216,9 +218,9 @@ int shrink_fs(reiserfs_filsys_t reiserfs, unsigned long blocks)
fflush(stdout);
}
- n_root_block = move_formatted_block(rs_root_block(rs), blocks, 0);
+ n_root_block = move_formatted_block(fs, get_sb_root_block(ondisk_sb), blocks, 0);
if (n_root_block) {
- set_root_block (rs, n_root_block);
+ set_sb_root_block (ondisk_sb, n_root_block);
}
if (opt_verbose)
@@ -237,33 +239,30 @@ int shrink_fs(reiserfs_filsys_t reiserfs, unsigned long blocks)
" doesn\'t match data block count %lu from super block\n",
(unsigned long)total_node_cnt, blocks_used);
}
-#if 0
- printf("check for used blocks in truncated region\n");
+
+#if 1
{
- unsigned long l;
- for (l = blocks; l < rs_block_count(rs); l++)
- if (is_block_used(bmp, l))
- printf("<%lu>", l);
- printf("\n");
+ unsigned long l;
+
+ /* make sure that none of truncated block are in use */
+ printf("check for used blocks in truncated region\n");
+ for (l = blocks; l < fs->fs_bitmap2->bm_bit_size; l ++) {
+ if ((l % (fs->fs_blocksize * 8)) == 0)
+ continue;
+ if (reiserfs_bitmap_test_bit (fs->fs_bitmap2, l))
+ printf ("<%lu>", l);
+ }
+ printf("\n");
}
-#endif /* 0 */
+#endif
- reiserfs_free_bitmap_blocks(fs);
-
- set_free_blocks (rs, rs_free_blocks(rs) - (rs_block_count(rs) - blocks) + (rs_bmap_nr(rs) - bmap_nr_new));
- set_block_count (rs, blocks);
- set_bmap_nr (rs, bmap_nr_new);
+ reiserfs_shrink_bitmap (fs->fs_bitmap2, blocks);
- reiserfs_read_bitmap_blocks(fs);
-
- for (i = blocks; i < bmap_nr_new * fs->s_blocksize; i++)
- reiserfs_bitmap_set_bit(bmp, i);
-#if 0
- PUT_SB_FREE_BLOCKS(s, SB_FREE_BLOCKS(s) - (SB_BLOCK_COUNT(s) - blocks) + (SB_BMAP_NR(s) - bmap_nr_new));
- PUT_SB_BLOCK_COUNT(s, blocks);
- PUT_SB_BMAP_NR(s, bmap_nr_new);
-#endif
- reiserfs_flush_bitmap(bmp, fs);
+ set_sb_free_blocks (ondisk_sb, get_sb_free_blocks(ondisk_sb)
+ - (get_sb_block_count(ondisk_sb) - blocks)
+ + (get_sb_bmap_nr(ondisk_sb) - bmap_nr_new));
+ set_sb_block_count (ondisk_sb, blocks);
+ set_sb_bmap_nr (ondisk_sb, bmap_nr_new);
return 0;
}
diff --git a/resize_reiserfs/fe.c b/resize_reiserfs/fe.c
index c14c2c5..81ac5af 100644
--- a/resize_reiserfs/fe.c
+++ b/resize_reiserfs/fe.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
+ * Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
*/
#include "resize.h"
diff --git a/resize_reiserfs/resize.h b/resize_reiserfs/resize.h
index 937b500..06da5ce 100644
--- a/resize_reiserfs/resize.h
+++ b/resize_reiserfs/resize.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
+ * Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
*/
#define _GNU_SOURCE
@@ -24,25 +24,28 @@
#include "io.h"
#include "misc.h"
#include "reiserfs_lib.h"
+#include "../include/config.h"
#include "../version.h"
-#define print_usage_and_exit()\
- die ("Usage: %s [-s[+|-]#[G|M|K]] [-fqv] device", argv[0])
-
+#define print_usage_and_exit() {\
+ fprintf (stderr, "Usage: %s [-s[+|-]#[G|M|K]] [-fqv] device\n\n", argv[0]);\
+ exit(16);\
+}
+
+#define DIE(form, args...) die("%s: " form "\n", g_progname , ## args)
/* reiserfs_resize.c */
extern struct buffer_head * g_sb_bh;
+extern char * g_progname;
extern int opt_force;
extern int opt_verbose;
extern int opt_nowrite;
extern int opt_safe;
-int expand_fs(struct super_block * s, unsigned long block_count_new);
-
/* fe.c */
int resize_fs_online(char * devname, unsigned long blocks);
/* do_shrink.c */
-int shrink_fs(struct super_block * s, unsigned long blocks);
+int shrink_fs(reiserfs_filsys_t *, unsigned long blocks);
diff --git a/resize_reiserfs/resize_reiserfs.8 b/resize_reiserfs/resize_reiserfs.8
index 66a3f25..1bcb99c 100644
--- a/resize_reiserfs/resize_reiserfs.8
+++ b/resize_reiserfs/resize_reiserfs.8
@@ -1,14 +1,17 @@
.\" -*- nroff -*-
-.\" Copyright 1996-2001 Hans Reiser.
+.\" Copyright 1996-2002 Hans Reiser.
.\"
-.TH RESIZE_REISERFS 8 "March 2001" "Reiserfsprogs-3.x.0j"
+.TH RESIZE_REISERFS 8 "January 2002" "Reiserfsprogs-3.6.2"
.SH NAME
resize_reiserfs \- Reiserfs filesystem resizer
.SH SYNOPSIS
.BR resize_reiserfs
[
.B \-s
-.IR \fR[\fB+\fR|\fB\- ]\fIsize [\fBK\fR|\fBM\fR|\fBG\fR]
+.IR \fR[\fB+\fR|\fB\- ]\fIsize\fB[\fBK\fR|\fBM\fR|\fBG\fR]
+] [
+.B \-j
+.IR \fR\fIdev
] [
.B \-fqv
]
@@ -68,6 +71,9 @@ you do not make it smaller than the reduced size of the reiserfs filesystem.
.BR \-s\ [+|\-]\fIsize
Set the new size in bytes.
.TP
+.BR \-j\ \fIdev
+Set the journal device name.
+.TP
.BR \-f
Force, do not perform checks.
.TP
@@ -112,5 +118,6 @@ has been written by Alexander Zarochentcev <zam@namesys.com>.
Please, report about the bugs to Alexander Zarochentcev <zam@namesys.com> or
to Hans Reiser <reiser@namesys.com>.
.SH SEE ALSO
-.BR cfsck (8),
+.BR cfdisk (8),
+.BR reiserfsck (8),
.BR debugreiserfs (8)
diff --git a/resize_reiserfs/resize_reiserfs.c b/resize_reiserfs/resize_reiserfs.c
index 3db3d21..09a2e4e 100644
--- a/resize_reiserfs/resize_reiserfs.c
+++ b/resize_reiserfs/resize_reiserfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
+ * Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
*/
/*
@@ -10,29 +10,15 @@
*/
#include "resize.h"
+#include <libgen.h>
int opt_force = 0;
int opt_verbose = 1; /* now "verbose" option is default */
int opt_nowrite = 0;
int opt_safe = 0;
+int opt_skipj = 0;
-#if 0
-/* Given a file descriptor and an offset, check whether the offset is
- a valid offset for the file - return 0 if it isn't valid or 1 if it
- is */
-int valid_offset( int fd, loff_t offset )
-{
- char ch;
-
- if (lseek64 (fd, offset, 0) < 0)
- return 0;
-
- if (read (fd, &ch, 1) < 1)
- return 0;
-
- return 1;
-}
-#endif
+char * g_progname;
/* calculate the new fs size (in blocks) from old fs size and the string
representation of new size */
@@ -76,10 +62,10 @@ static void sb_report(struct reiserfs_super_block * sb1,
"block count %d (%d)\n"
"free blocks %d (%d)\n"
"bitmap block count %d (%d)\n",
- rs_blocksize(sb1),
- rs_block_count(sb1), rs_block_count(sb2),
- rs_free_blocks(sb1), rs_free_blocks(sb2),
- rs_bmap_nr(sb1), rs_bmap_nr(sb2));
+ get_sb_block_size(sb1),
+ get_sb_block_count(sb1), get_sb_block_count(sb2),
+ get_sb_free_blocks(sb1), get_sb_free_blocks(sb2),
+ get_sb_bmap_nr(sb1), get_sb_bmap_nr(sb2));
};
/* conditional bwrite */
@@ -94,63 +80,64 @@ static int bwrite_cond (struct buffer_head * bh)
}
-/* the first one of the mainest functions */
-int expand_fs (reiserfs_filsys_t fs, unsigned long block_count_new) {
- int block_r, block_r_new;
+/* the first one of the most important functions */
+static int expand_fs (reiserfs_filsys_t * fs, unsigned long block_count_new) {
unsigned int bmap_nr_new, bmap_nr_old;
int i;
+ struct reiserfs_super_block * sb;
- reiserfs_bitmap_t bmp;
- struct reiserfs_super_block * rs = fs->s_rs;
reiserfs_reopen(fs, O_RDWR);
- set_state (fs->s_rs, REISERFS_ERROR_FS);
- bwrite_cond(SB_BUFFER_WITH_SB(fs));
-
- bmp = reiserfs_create_bitmap(rs_block_count(rs));
- if (!bmp)
- die ("cannot create bitmap\n");
- reiserfs_fetch_disk_bitmap(bmp, fs);
- reiserfs_free_bitmap_blocks(fs);
- if (reiserfs_expand_bitmap(bmp, block_count_new))
- die ("cannot expand bitmap\n");
-
- /* clean bits in old bitmap tail */
- for (i = rs_block_count(rs);
- i < rs_bmap_nr(rs) * rs_blocksize(rs) * 8 && i < block_count_new;
- i++) {
- reiserfs_bitmap_clear_bit(bmp, i);
- }
-
- /* count used bits in last bitmap block */
- block_r = rs_block_count(rs) - ((rs_bmap_nr(rs) - 1) * rs_blocksize(rs) * 8);
+ if (!reiserfs_open_ondisk_bitmap (fs))
+ DIE("cannot open ondisk bitmap");
- /* count bitmap blocks in new fs */
- bmap_nr_new = (block_count_new - 1) / (rs_blocksize(rs) * 8) + 1;
- block_r_new = block_count_new - (bmap_nr_new - 1) * rs_blocksize(rs) * 8;
+ sb = fs->fs_ondisk_sb;
- bmap_nr_old = rs_bmap_nr(rs);
+ set_sb_fs_state (fs->fs_ondisk_sb, REISERFS_CORRUPTED);
+
+ bwrite_cond(fs->fs_super_bh);
+
+
+ if (reiserfs_expand_bitmap(fs->fs_bitmap2, block_count_new))
+ DIE("cannot expand bitmap\n");
+
+
+ /* count bitmap blocks in new fs */
+ bmap_nr_new = (block_count_new - 1) / (fs->fs_blocksize * 8) + 1;
+ bmap_nr_old = get_sb_bmap_nr(sb);
/* update super block buffer*/
- set_free_blocks (rs, rs_free_blocks(rs) + block_count_new
- - rs_block_count(rs) - (bmap_nr_new - rs_bmap_nr(rs)));
- set_block_count (rs, block_count_new);
- set_bmap_nr (rs, bmap_nr_new);
-
- reiserfs_read_bitmap_blocks(fs);
- for (i = bmap_nr_old; i < bmap_nr_new; i++) /* fix new bitmap blocks */
- reiserfs_bitmap_set_bit(bmp, SB_AP_BITMAP(fs)[i]->b_blocknr);
- reiserfs_flush_bitmap(bmp, fs);
+ set_sb_free_blocks (sb, get_sb_free_blocks(sb) +
+ (block_count_new - get_sb_block_count(sb)) -
+ (bmap_nr_new - bmap_nr_old));
+ set_sb_block_count (sb, block_count_new);
+ set_sb_bmap_nr (sb, bmap_nr_new);
+
+ /* mark new bitmap blocks as used */
+ for (i = bmap_nr_old; i < bmap_nr_new; i++)
+ reiserfs_bitmap_set_bit (fs->fs_bitmap2, i * fs->fs_blocksize * 8);
+
+ /* normally, this is done by reiserfs_bitmap_set_bit, but if we
+ ** haven't actually added any bitmap blocks, the bitmap won't be dirtied.
+ **
+ ** In memory, reiserfsprogs puts zeros for the bits past the end of
+ ** the old filesystem. But, on disk that bitmap is full of ones.
+ ** we explicitly dirty the bitmap here to make sure the zeros get written
+ ** to disk
+ */
+ fs->fs_bitmap2->bm_dirty = 1 ;
return 0;
}
+
int main(int argc, char *argv[]) {
char * bytes_count_str = NULL;
char * devname;
- reiserfs_filsys_t fs;
- struct reiserfs_super_block * rs;
-
+ char * jdevice_name = NULL;
+ reiserfs_filsys_t * fs;
+ struct reiserfs_super_block * sb;
+
int c;
int error;
@@ -158,15 +145,20 @@ int main(int argc, char *argv[]) {
unsigned long block_count_new;
- print_banner ("resize_reiserfs");
+ g_progname = basename(argv[0]);
+ print_banner (g_progname);
- while ((c = getopt(argc, argv, "fvcqs:")) != EOF) {
+ while ((c = getopt(argc, argv, "fvcqks:j:")) != EOF) {
switch (c) {
case 's' :
- if (!optarg)
- die("%s: Missing argument to -s option", argv[0]);
+ if (!optarg)
+ DIE("Missing argument to -s option");
bytes_count_str = optarg;
break;
+ case 'j' :
+ if (!optarg)
+ DIE("Missing argument to -j option");
+ jdevice_name = optarg;
case 'f':
opt_force = 1;
break;
@@ -183,6 +175,9 @@ int main(int argc, char *argv[]) {
case 'q':
opt_verbose = 0;
break;
+ case 'k':
+ opt_skipj = 1;
+ break;
default:
print_usage_and_exit ();
}
@@ -194,56 +189,78 @@ int main(int argc, char *argv[]) {
fs = reiserfs_open(devname, O_RDONLY, &error, 0);
if (!fs)
- die ("%s: can not open '%s': %s", argv[0], devname, strerror(error));
+ DIE ("cannot open '%s': %s", devname, strerror(error));
+ if (!reiserfs_open_journal (fs, jdevice_name, O_RDONLY)) {
+ if (!opt_skipj)
+ DIE ("can not open journal of '%s'", devname);
+ }
+
+ /* forced to continue without journal available/specified */
if (no_reiserfs_found (fs)) {
- die ("resize_reiserfs: no reiserfs found on the device");
+ DIE ("no reiserfs found on the device.");
}
if (!spread_bitmaps (fs)) {
- die ("resize_reiserfs: cannot resize reiserfs in old (not spread bitmap) format.\n");
+ DIE ("cannot resize reiserfs in old (not spread bitmap) format.");
}
- rs = fs->s_rs;
+ sb = fs->fs_ondisk_sb;
if(bytes_count_str) { /* new fs size is specified by user */
- block_count_new = calc_new_fs_size(rs_block_count(rs), fs->s_blocksize, bytes_count_str);
+ block_count_new = calc_new_fs_size(get_sb_block_count(sb), fs->fs_blocksize, bytes_count_str);
} else { /* use whole device */
- block_count_new = count_blocks(devname, fs->s_blocksize, -1);
+ block_count_new = count_blocks(devname, fs->fs_blocksize);
}
if (is_mounted (devname)) {
reiserfs_close(fs);
return resize_fs_online(devname, block_count_new);
- }
-
- if (rs_state(rs) != REISERFS_VALID_FS)
- die ("%s: the file system isn't in valid state\n", argv[0]);
+ }
+
+ if (!reiserfs_is_fs_consistent (fs)) {
+ reiserfs_warning (stderr, "\n\nresize_reiserfs: run reiserfsck --check first\n\n");
+ reiserfs_close (fs);
+ return 1;
+ }
+
+ if (get_sb_umount_state(sb) != REISERFS_CLEANLY_UMOUNTED)
+ /* fixme: shouldn't we check for something like: fsck guarantees: fs is ok */
+ DIE ("the file system isn't in valid state.");
- if(!valid_offset(fs->s_dev, (loff_t) block_count_new * fs->s_blocksize - 1))
- die ("%s: %s too small", argv[0], devname);
+ if (block_count_new >= get_sb_block_count(sb)) {
+ if (block_count_new == get_sb_block_count(sb)) {
+ reiserfs_warning (stderr, "%s already is of the needed size. Nothing to be done\n\n", devname);
+ exit (1);
+ }
+
+ if(!valid_offset(fs->fs_dev, (loff_t) block_count_new * fs->fs_blocksize - 1)) {
+ reiserfs_warning (stderr, "%s is of %lu blocks size only with reiserfs of %d blocks\nsize on it. "\
+ "You are trying to expant reiserfs up to %lu blocks size.\nYou probably forgot to expand your "\
+ "partition size.\n\n", devname, count_blocks (devname, fs->fs_blocksize),
+ get_sb_block_count(sb), block_count_new);
+ exit (1);
+ }
+ }
+
sb_old = 0; /* Needed to keep idiot compiler from issuing false warning */
/* save SB for reporting */
if(opt_verbose) {
sb_old = getmem(SB_SIZE);
- memcpy(sb_old, SB_DISK_SUPER_BLOCK(fs), SB_SIZE);
+ memcpy(sb_old, fs->fs_ondisk_sb, SB_SIZE);
}
- if (block_count_new == SB_BLOCK_COUNT(fs))
- die ("%s: Calculated fs size is the same as the previous one.", argv[0]);
-
- if (block_count_new > SB_BLOCK_COUNT(fs))
- expand_fs(fs, block_count_new);
- else
- shrink_fs(fs, block_count_new);
+ error = (block_count_new > get_sb_block_count(fs->fs_ondisk_sb)) ? expand_fs(fs, block_count_new) : shrink_fs(fs, block_count_new);
+ if (error)
+ return error;
if(opt_verbose) {
- sb_report(rs, sb_old);
+ sb_report(fs->fs_ondisk_sb, sb_old);
freemem(sb_old);
}
- set_state (rs, REISERFS_VALID_FS);
- bwrite_cond(SB_BUFFER_WITH_SB(fs));
+ set_sb_fs_state (fs->fs_ondisk_sb, REISERFS_CONSISTENT);
+ bwrite_cond(fs->fs_super_bh);
if (opt_verbose) {
printf("\nSyncing..");
diff --git a/tune/Makefile.am b/tune/Makefile.am
new file mode 100644
index 0000000..a046409
--- /dev/null
+++ b/tune/Makefile.am
@@ -0,0 +1,9 @@
+sbin_PROGRAMS = reiserfstune
+
+reiserfstune_SOURCES = tune.c tune.h
+
+man_MANS = reiserfstune.8
+EXTRA_DIST = $(man_MANS)
+
+LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a
+
diff --git a/tune/Makefile.in b/tune/Makefile.in
new file mode 100644
index 0000000..6e5eac8
--- /dev/null
+++ b/tune/Makefile.in
@@ -0,0 +1,328 @@
+# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am
+
+# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+DESTDIR =
+
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+
+top_builddir = ..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS)
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+transform = @program_transform_name@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+CC = @CC@
+MAKEINFO = @MAKEINFO@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+sbindir = @sbindir@
+
+sbin_PROGRAMS = reiserfstune
+
+reiserfstune_SOURCES = tune.c tune.h
+
+man_MANS = reiserfstune.8
+EXTRA_DIST = $(man_MANS)
+
+LDADD = $(top_srcdir)/lib/libmisc.a $(top_srcdir)/reiserfscore/libcore.a
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = ../include/config.h
+CONFIG_CLEAN_FILES =
+PROGRAMS = $(sbin_PROGRAMS)
+
+
+DEFS = @DEFS@ -I. -I$(srcdir) -I../include
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+reiserfstune_OBJECTS = tune.o
+reiserfstune_LDADD = $(LDADD)
+reiserfstune_DEPENDENCIES = $(top_srcdir)/lib/libmisc.a \
+$(top_srcdir)/reiserfscore/libcore.a
+reiserfstune_LDFLAGS =
+CFLAGS = @CFLAGS@
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
+man8dir = $(mandir)/man8
+MANS = $(man_MANS)
+
+NROFF = nroff
+DIST_COMMON = Makefile.am Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+TAR = tar
+GZIP_ENV = --best
+SOURCES = $(reiserfstune_SOURCES)
+OBJECTS = $(reiserfstune_OBJECTS)
+
+all: all-redirect
+.SUFFIXES:
+.SUFFIXES: .S .c .o .s
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps tune/Makefile
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+
+mostlyclean-sbinPROGRAMS:
+
+clean-sbinPROGRAMS:
+ -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS)
+
+distclean-sbinPROGRAMS:
+
+maintainer-clean-sbinPROGRAMS:
+
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(sbindir)
+ @list='$(sbin_PROGRAMS)'; for p in $$list; do \
+ if test -f $$p; then \
+ echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \
+ $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ else :; fi; \
+ done
+
+uninstall-sbinPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ list='$(sbin_PROGRAMS)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \
+ done
+
+.c.o:
+ $(COMPILE) -c $<
+
+.s.o:
+ $(COMPILE) -c $<
+
+.S.o:
+ $(COMPILE) -c $<
+
+mostlyclean-compile:
+ -rm -f *.o core *.core
+
+clean-compile:
+
+distclean-compile:
+ -rm -f *.tab.c
+
+maintainer-clean-compile:
+
+reiserfstune: $(reiserfstune_OBJECTS) $(reiserfstune_DEPENDENCIES)
+ @rm -f reiserfstune
+ $(LINK) $(reiserfstune_LDFLAGS) $(reiserfstune_OBJECTS) $(reiserfstune_LDADD) $(LIBS)
+
+install-man8:
+ $(mkinstalldirs) $(DESTDIR)$(man8dir)
+ @list='$(man8_MANS)'; \
+ l2='$(man_MANS)'; for i in $$l2; do \
+ case "$$i" in \
+ *.8*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+ else file=$$i; fi; \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \
+ $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \
+ done
+
+uninstall-man8:
+ @list='$(man8_MANS)'; \
+ l2='$(man_MANS)'; for i in $$l2; do \
+ case "$$i" in \
+ *.8*) list="$$list $$i" ;; \
+ esac; \
+ done; \
+ for i in $$list; do \
+ ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+ inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+ inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+ echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \
+ rm -f $(DESTDIR)$(man8dir)/$$inst; \
+ done
+install-man: $(MANS)
+ @$(NORMAL_INSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) install-man8
+uninstall-man:
+ @$(NORMAL_UNINSTALL)
+ $(MAKE) $(AM_MAKEFLAGS) uninstall-man8
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP)
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ here=`pwd` && cd $(srcdir) \
+ && mkid -f$$here/ID $$unique $(LISP)
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS)'; \
+ unique=`for i in $$list; do echo $$i; done | \
+ awk ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \
+ || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS)
+
+mostlyclean-tags:
+
+clean-tags:
+
+distclean-tags:
+ -rm -f TAGS ID
+
+maintainer-clean-tags:
+
+distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
+
+subdir = tune
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ d=$(srcdir); \
+ if test -d $$d/$$file; then \
+ cp -pr $$d/$$file $(distdir)/$$file; \
+ else \
+ test -f $(distdir)/$$file \
+ || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
+ || cp -p $$d/$$file $(distdir)/$$file || :; \
+ fi; \
+ done
+tune.o: tune.c tune.h ../include/io.h ../include/misc.h \
+ ../include/swab.h ../include/reiserfs_lib.h \
+ ../include/reiserfs_fs.h ../include/config.h ../version.h
+
+info-am:
+info: info-am
+dvi-am:
+dvi: dvi-am
+check-am: all-am
+check: check-am
+installcheck-am:
+installcheck: installcheck-am
+install-exec-am: install-sbinPROGRAMS
+install-exec: install-exec-am
+
+install-data-am: install-man
+install-data: install-data-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+install: install-am
+uninstall-am: uninstall-sbinPROGRAMS uninstall-man
+uninstall: uninstall-am
+all-am: Makefile $(PROGRAMS) $(MANS)
+all-redirect: all-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(mandir)/man8
+
+
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+ -rm -f config.cache config.log stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+mostlyclean-am: mostlyclean-sbinPROGRAMS mostlyclean-compile \
+ mostlyclean-tags mostlyclean-generic
+
+mostlyclean: mostlyclean-am
+
+clean-am: clean-sbinPROGRAMS clean-compile clean-tags clean-generic \
+ mostlyclean-am
+
+clean: clean-am
+
+distclean-am: distclean-sbinPROGRAMS distclean-compile distclean-tags \
+ distclean-generic clean-am
+
+distclean: distclean-am
+
+maintainer-clean-am: maintainer-clean-sbinPROGRAMS \
+ maintainer-clean-compile maintainer-clean-tags \
+ maintainer-clean-generic distclean-am
+ @echo "This command is intended for maintainers to use;"
+ @echo "it deletes files that may require special tools to rebuild."
+
+maintainer-clean: maintainer-clean-am
+
+.PHONY: mostlyclean-sbinPROGRAMS distclean-sbinPROGRAMS \
+clean-sbinPROGRAMS maintainer-clean-sbinPROGRAMS uninstall-sbinPROGRAMS \
+install-sbinPROGRAMS mostlyclean-compile distclean-compile \
+clean-compile maintainer-clean-compile install-man8 uninstall-man8 \
+install-man uninstall-man tags mostlyclean-tags distclean-tags \
+clean-tags maintainer-clean-tags distdir info-am info dvi-am dvi check \
+check-am installcheck-am installcheck install-exec-am install-exec \
+install-data-am install-data install-am install uninstall-am uninstall \
+all-redirect all-am all installdirs mostlyclean-generic \
+distclean-generic clean-generic maintainer-clean-generic clean \
+mostlyclean distclean maintainer-clean
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/tune/reiserfstune.8 b/tune/reiserfstune.8
new file mode 100644
index 0000000..bce332d
--- /dev/null
+++ b/tune/reiserfstune.8
@@ -0,0 +1,147 @@
+.\" -*- nroff -*-
+.\" Copyright 1996-2002 Hans Reiser.
+.\"
+.TH REISERFSTUNE 8 "January 2002" "Reiserfsprogs-3.6.2"
+.SH NAME
+reiserfstune
+.SH SYNOPSIS
+.B reiserfstune
+[ \fB-f\fR ]
+[ \fB-j\fR | \fB--journal-device\fR \fIFILE\fR ]
+[ \fB--no-journal-available\fR ]
+[ \fB--journal-new-device\fR \fIFILE\fR ]
+[ \fB-s\fR | \fB--journal-new-size\fR \fIN\fR ]
+[ \fB-o\fR | \fB--journal-new-offset\fR \fIN\fR ]
+[ \fB-t\fR | \fB--max-transaction-size\fR \fIN\fR ]
+[ \fB-u\fR | \fB--uuid \fIUUID\fR ]
+[ \fB-l\fR | \fB--label \fILABEL\fR ]
+.I device
+.SH DESCRIPTION
+\fBreiserfstune\fR is used for tuning the ReiserFS
+journal. It can change two parameters (journal size and maximum
+transaction size), and it can move the journal's location to a new specified
+block device. (The old ReiserFS's journal may be
+kept unused, or discarded at the user's option.) Note: At the time of
+writing this feature was implemented for a special release of
+ReiserFS, and was not expected to be put into the mainstream kernel
+until approximately Linux 2.5. This means that if you have the stock
+kernel you must apply a special patch. Without this patch the kernel
+will refuse to mount the newly modified file system. We will charge
+$25 to explain this to you if you ask us why it doesn't work.
+.PP
+Perhaps the most interesting application of this code is to put the
+journal on a solid state disk.
+.TP
+\fIdevice
+is the special file corresponding to the newly specified block device (e.g
+/dev/hdXX for IDE disk partition or /dev/sdXX for the SCSI disk partition).
+.SH OPTIONS
+.TP
+\fB-j\fR | \fB--journal-device\fR \fIFILE
+\fIFILE\fR is the file name of the block device the file system has
+the current journal (the one prior to running reiserfstune) on. This option is required when the journal is
+already on a separate device from the main data device (although it
+can be avoided with \fB--no-journal-available\fR). If you don't
+specify journal device by this option, reiserfstune suppose that
+journal is on main device.
+.TP
+\fB--no-journal-available
+allows \fBreiserfstune\fR to continue when the current journal's block
+device is no longer available. This might happen if a disk goes bad
+and you remove it (and run fsck).
+.TP
+\fB--journal-new-device \fIFILE
+\fIFILE\fR is the file name of the block device which will contain the
+new journal for the file system. If you don't specify this,
+reiserfstune supposes that journal device remains the same.
+.TP
+\fB \-s\fR | \fB\--journal-new-size \fIN
+\fIN\fR is the size parameter for the new journal. When journal is to
+be on a separate device - its size defaults to number of blocks that
+device has. When journal is to be on the same device as the filesytem - its size defaults
+to amount of blocks allocated for journal by \fImkreiserfs\fR when it
+created the filesystem. Minimum is 513 for
+both cases.
+.TP
+\fB \-o\fR | \fB\--journal-new-offset \fIN
+\fIN\fR is an offset in blocks where journal will starts from when journal is to
+be on a separate device. Default is 0. Has no effect when journal is
+to be on the same device as the filesystem. Most users have no need
+to use this feature. It can be used when you want the journals from
+multiple filesystems to reside on the same device, and you don't want
+to or cannot partition that device.
+.TP
+\fB \-t\fR | \fB\--maximal-transaction-size \fIN
+\fI\fR is the maximum transaction size parameter for the new
+journal. The default, and max possible, value is 1024 blocks. It
+should be less than half the size of the journal. If specifed
+incorrectly, it will be adjusted.
+.TP
+\fB\-f\fR | \fB--force\fR
+Normally \fBreiserfstune\fR will refuse to change a journal of a
+file system that was created before this journal relocation code. This
+is because if you change the journal, you cannot go back (without special
+option \fB--make-journal-standard\fR) to an old kernel that lacks this feature and be able to use your filesytem. This option forces it to do that. Specified more
+than once it allows to avoid asking for confirmation.
+.TP
+\fB--make-journal-standard\fR
+As it was mentioned above, if your file system has non-standard journal,
+it can not be mounted on the kernel without journal relocation
+code. The thing can be changed, the only condition is that there is reserved
+area on main device of the standard journal size 8193 blocks (it will be so for
+instance if you convert standard journal to non-standard). Just
+specify this option when you relocate journal back, or without relocation
+if you already have it on main device.
+.TP
+\fB-u\fR | \fB--uuid \fIUUID\fR
+Set the universally unique identifier (\fB UUID \fR) of the filesystem to
+\fIUUID\fR (see also \fBuuidgen(8)\fR). The format of the UUID is a
+series of hex digits separated by hypthens, like this:
+"c1b9d5a2-f162-11cf-9ece-0020afc76f16".
+.TP
+\fB-l\fR | \fB--label \fILABEL\fR
+Set the volume label of the filesystem. \fILABEL\fR can be at most 16
+characters long; if it is longer than 16 characters, reiserfstune will truncate it.
+.SH POSSIBLE SCENARIOS OF USING REISERFSTUNE:
+1. You have ReiserFS on /dev/hda1, and you wish to have
+it working with its journal on the device /dev/journal
+.nf
+.IP
+boot kernel patched with special "relocatable journal support" patch
+reiserfstune /dev/hda1 --journal-new-device /dev/journal -f
+mount /dev/hda1 and use.
+You would like to change max transaction size to 512 blocks
+reiserfstune -t 512 /dev/hda1
+You would like to use your file system on another kernel that doesn't
+contain relocatable journal support.
+umount /dev/hda1
+reiserfstune /dev/hda1 -j /dev/journal --journal-new-device /dev/hda1 --make-journal-standard
+mount /dev/hda1 and use.
+.LP
+2. You would like to have ReiserFS on /dev/hda1 and to be able to
+switch between different journals including journal located on the
+device containing the filesystem.
+.nf
+.IP
+boot kernel patched with special "relocatable journal support" patch
+mkreiserfs /dev/hda1
+you got solid state disk (perhaps /dev/sda, they typically look like scsi disks)
+reiserfstune --journal-new-device /dev/sda1 -f /dev/hda1
+Your scsi device dies, it is three in the morning, you have an extra IDE device
+lying around
+reiserfsck --no-journal-available /dev/hda1
+or
+reiserfsck --rebuild-tree --no-journal-available /dev/hda1
+reiserfstune --no-journal-available --journal-new-device /dev/hda1 /dev/hda1
+using /dev/hda1 under patched kernel
+.SH AUTHOR
+This version of \fBreiserfstune\fR has been written by Vladimir
+Demidov <vova@namesys.com> and Edward Shishkin <edward@namesys.com>.
+.SH BUGS
+Please repoort bugs to the ReiserFS mail list <reiserfs-list@namesys.com>
+.SH SEE ALSO
+.BR reiserfsck (8),
+.BR debugreiserfs (8),
+.BR mkreiserfs (8)
+
+
diff --git a/tune/tune.c b/tune/tune.c
new file mode 100644
index 0000000..cc551ef
--- /dev/null
+++ b/tune/tune.c
@@ -0,0 +1,563 @@
+/*
+ * Copyright 2002 Hans Reiser
+ */
+#include "tune.h"
+
+char *program_name;
+
+static void message( const char * fmt, ... )
+ __attribute__ ((format (printf, 1, 2)));
+
+static void message( const char * fmt, ... )
+{
+ char *buf;
+ va_list args;
+
+ buf = NULL;
+ va_start( args, fmt );
+ vasprintf( &buf, fmt, args );
+ va_end( args );
+
+ if( buf ) {
+ fprintf( stderr, "%s: %s\n", program_name, buf );
+ free( buf );
+ }
+}
+
+
+reiserfs_filsys_t * fs;
+
+static void print_usage_and_exit(void)
+{
+ message ("Usage: %s [options] "
+ " device [block-count]\n"
+ "\n"
+ "Options:\n\n"
+ " -j | --journal-device file\n"
+ " --journal-new-device file\n"
+ " -o | --journal-new-offset N\n"
+ " -s | --journal-new-size N\n"
+ " -t | --transaction-max-size N\n"
+ " --no-journal-available\n"
+ " --make-journal-standard\n"
+ /*"\t-p | --keep-old-journal-param (keep parametrs from old journal to new one)\n"*/
+ " -u | --uuid UUID|random\n"
+ " -l | --label LABEL\n"
+ " -f | --force \n", program_name);
+ exit (1);
+}
+
+unsigned long Journal_size = 0;
+int Max_trans_size = JOURNAL_TRANS_MAX;
+int Offset = 0;
+__u16 Options = 0;
+int Force = 0;
+char * LABEL;
+unsigned char UUID[16];
+
+static int should_make_journal_non_standard (int force)
+{
+ message ("ATTENTION! Filesystem with standard journal found. ");
+ check_forcing_ask_confirmation (force);
+ return 1;
+}
+
+static int should_make_journal_standard (reiserfs_filsys_t * fs, char * j_new_dev_name)
+{
+ if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb))
+ return 0;
+
+ if (!user_confirmed (stderr, "ATTENTION! Filesystem with non-standard journal "
+ "found. Continue? (y/n):", "y\n")) {
+ exit(1);
+ }
+ /* make sure journal is on main device, it has default size
+ and the file system has non-standard magic */
+
+ if (j_new_dev_name) {
+ /* new journal was specified - check if it is available */
+ if (strcmp (j_new_dev_name, fs->fs_file_name)) {
+ message ("Can not create standard journal on separated device %s",
+ j_new_dev_name);
+ return 0;
+ }
+ if (Journal_size && (Journal_size != journal_default_size (fs->fs_super_bh->b_blocknr, fs->fs_blocksize))) {
+ message ("Can not create standard journal of the size %lu",
+ Journal_size);
+ return 0;
+ }
+ if (Max_trans_size && (Max_trans_size != JOURNAL_TRANS_MAX)) {
+ message ("Can not create standard journal with the transaction "
+ "max size %u", Max_trans_size);
+ return 0;
+ }
+ }
+ else {
+ /* new journal was not specified - check ondisk journal params */
+ if (get_jp_journal_dev(sb_jp(fs->fs_ondisk_sb))) {
+ message ("Can not create standard journal on separated device [0x%x]",
+ get_jp_journal_dev(sb_jp(fs->fs_ondisk_sb)));
+ return 0;
+ }
+ if(get_jp_journal_size(sb_jp(fs->fs_ondisk_sb))!= journal_default_size (fs->fs_super_bh->b_blocknr, fs->fs_blocksize)){
+ message ("Can not create standard journal of the size %u",
+ get_jp_journal_size(sb_jp(fs->fs_ondisk_sb)));
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int set_standard_journal_params (reiserfs_filsys_t * fs)
+{
+ /* ondisk superblock update */
+
+ if (get_sb_version(fs->fs_ondisk_sb) == 0)
+ memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_3_5_SUPER_MAGIC_STRING,
+ strlen (REISERFS_3_5_SUPER_MAGIC_STRING));
+ else if (get_sb_version(fs->fs_ondisk_sb) == 2)
+ memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_3_6_SUPER_MAGIC_STRING,
+ strlen (REISERFS_3_6_SUPER_MAGIC_STRING));
+ else {
+ message ("Can not set standard reiserfs magic: unknown format found %u,"
+ " try reiserfsck first", get_sb_version(fs->fs_ondisk_sb));
+ return 0;
+ }
+ if (get_jp_journal_max_trans_len(sb_jp(fs->fs_ondisk_sb)) != JOURNAL_TRANS_MAX)
+ set_jp_journal_max_trans_len(sb_jp(fs->fs_ondisk_sb), JOURNAL_TRANS_MAX);
+ if (get_jp_journal_max_batch(sb_jp(fs->fs_ondisk_sb)) != JOURNAL_MAX_BATCH)
+ set_jp_journal_max_batch(sb_jp(fs->fs_ondisk_sb), JOURNAL_MAX_BATCH);
+ if (get_jp_journal_max_commit_age(sb_jp(fs->fs_ondisk_sb)) != JOURNAL_MAX_COMMIT_AGE)
+ set_jp_journal_max_commit_age(sb_jp(fs->fs_ondisk_sb), JOURNAL_MAX_COMMIT_AGE);
+ if (get_jp_journal_max_trans_age(sb_jp(fs->fs_ondisk_sb)) != JOURNAL_MAX_TRANS_AGE)
+ set_jp_journal_max_trans_age(sb_jp(fs->fs_ondisk_sb), JOURNAL_MAX_TRANS_AGE);
+ set_sb_reserved_for_journal (fs->fs_ondisk_sb, 0);
+
+ /* journal_header update */
+
+ ((struct reiserfs_journal_header *)(fs->fs_jh_bh->b_data)) -> jh_journal =
+ *(sb_jp(fs->fs_ondisk_sb));
+ return 1;
+}
+
+void zero_journal (reiserfs_filsys_t * fs)
+{
+ int i;
+ struct buffer_head * bh;
+ unsigned long done;
+ unsigned long start, len;
+
+
+ fprintf (stderr, "Initializing journal - ");
+
+ start = get_jp_journal_1st_block (sb_jp (fs->fs_ondisk_sb));
+ len = get_jp_journal_size (sb_jp (fs->fs_ondisk_sb));
+ done = 0;
+ for (i = 0; i < len; i ++) {
+ print_how_far (stderr, &done, len, 1, 1/*be quiet*/);
+ bh = getblk (fs->fs_journal_dev, start + i, fs->fs_blocksize);
+ if (!bh)
+ die ("zero_journal: getblk failed");
+ memset (bh->b_data, 0, bh->b_size);
+ mark_buffer_dirty (bh);
+ mark_buffer_uptodate (bh, 1);
+ bwrite (bh);
+ brelse (bh);
+ }
+
+ fprintf (stderr, "\n");
+ fflush (stderr);
+}
+
+
+static int str2int (char * str)
+{
+ int val;
+ char * tmp;
+
+ val = (int) strtol (str, &tmp, 0);
+ if (*tmp)
+ die ("%s: strtol is unable to make an integer of %s\n", program_name, str);
+ return val;
+}
+
+
+static void set_transaction_max_size (char * str)
+{
+ Max_trans_size = str2int( str );
+}
+
+
+/* journal must fit into number of blocks pointed by first bitmap */
+static void set_journal_device_size (char * str)
+{
+ Journal_size = str2int (str) ;
+}
+
+
+static void set_offset_in_journal_device (char * str)
+{
+ Offset = str2int( str );
+}
+
+
+int main (int argc, char **argv)
+{
+ reiserfs_filsys_t * fs;
+ char * device_name;
+ char * jdevice_name;
+ char * j_new_device_name;
+ int c;
+ static int flag;
+ struct reiserfs_journal_header * j_head;
+ reiserfs_trans_t old, new;
+ int Is_journal_or_maxtrans_size_specified = 0;
+
+ program_name = strrchr( argv[ 0 ], '/' );
+ program_name = program_name ? ++ program_name : argv[ 0 ];
+
+ print_banner (program_name);
+
+ if (argc < 2)
+ print_usage_and_exit ();
+
+ device_name = 0;
+ jdevice_name = 0;
+ j_new_device_name = 0;
+
+ while (1) {
+ static struct option options[] = {
+ {"journal-device", required_argument, 0, 'j'},
+ {"journal-new-device", required_argument, &flag, OPT_NEW_J},
+ {"journal-new-size", required_argument, 0, 's'},
+ {"transaction-max-size", required_argument, 0, 't'},
+ {"journal-new-offset", required_argument, 0, 'o'},
+ {"no-journal-available", no_argument, &flag, OPT_SKIP_J},
+ /*{"keep-old-journal-param", no_argument, 0, 'p'},*/
+ {"uuid", required_argument, 0, 'u'},
+ {"label", required_argument, 0, 'l'},
+ {"force", no_argument, 0, 'f'},
+ {"really-force", no_argument, &flag, OPT_SUPER_FORCE},
+ {"make-journal-standard", no_argument, &flag, OPT_STANDARD},
+ {0, 0, 0, 0}
+ };
+ int option_index;
+
+ c = getopt_long (argc, argv, "j:s:t:o:fu:l:",
+ options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 0:
+ /* long-only optins */
+ if (flag == OPT_NEW_J) {
+ Options |= OPT_NEW_J;
+ j_new_device_name = optarg;
+ }
+ if (flag == OPT_SKIP_J) {
+ Options |= OPT_SKIP_J;
+ }
+ if (flag == OPT_SUPER_FORCE) {
+ Options |=OPT_SUPER_FORCE;
+ }
+ if (flag == OPT_STANDARD) {
+ Options |=OPT_STANDARD;
+ }
+ break;
+ case 'j': /* --journal-device */
+ jdevice_name = optarg;
+ break;
+
+ case 's': /* --journal-new-size */
+ set_journal_device_size (optarg);
+ Is_journal_or_maxtrans_size_specified = 1;
+ break;
+
+ case 't': /* --transaction-max-size */
+ set_transaction_max_size (optarg);
+ Is_journal_or_maxtrans_size_specified = 1;
+ break;
+
+ case 'o': /* --offset */
+ set_offset_in_journal_device (optarg);
+ break;
+
+ case 'f':
+ /* forces replacing standard journal with non-standard
+ one. Specified more than once - allows to avoid asking for
+ confirmation */
+ Force ++;
+ break;
+ case 'u':
+ /* UUID */
+ if (!strcmp(optarg, "random")) {
+ if (generate_random_uuid (UUID))
+ message ("failed to genetate UUID\n");
+ } else {
+ if (set_uuid (optarg, UUID)) {
+ message ("wrong UUID specified\n");
+ return 1;
+ }
+ }
+
+ break;
+ case 'l':
+ /* LABEL */
+ LABEL = optarg;
+ break;
+#if 0
+ case 'J': /* --journal-new-device */
+ Options |= OPT_NEW_J;
+ j_new_device_name = optarg;
+ break;
+
+ case 'u': /* --no-journal-available */
+ Options |= OPT_SKIPJ;
+ break;
+
+ case 'p': /* --keep-old-journal-param */
+ Options |= OPT_KEEPO;
+ break;
+#endif
+ default:
+ print_usage_and_exit();
+ }
+ }
+
+ if (optind != argc - 1)
+ print_usage_and_exit ();
+
+ /* device to be formatted */
+ device_name = argv [optind];
+
+ if (!jdevice_name && !(Options & OPT_SKIP_J))
+ jdevice_name = device_name;
+
+ if (jdevice_name && (Options & OPT_SKIP_J)) {
+ message ("either specify journal device, "
+ "or choose the option --no-journal-awailable");
+ return 1;
+ }
+ fs = reiserfs_open (device_name, O_RDONLY, 0, NULL);
+ if (no_reiserfs_found(fs)) {
+ message ("Cannot open reiserfs on %s", device_name);
+ return 1;
+ }
+
+ /* now we try to open journal, it makes sence if there is no the flag
+ NEED_TUNE in ondisk superblock */
+ if (get_jp_journal_magic(sb_jp(fs->fs_ondisk_sb)) != NEED_TUNE) {
+ if (!reiserfs_open_journal (fs, jdevice_name, O_RDONLY)) {
+ if (!(Options & OPT_SKIP_J)) {
+ message ("Unable to open old journal.");
+ reiserfs_close (fs);
+ return 1;
+ }
+ else
+ if (!reiserfs_is_fs_consistent (fs)) {
+ message ("Check filesystem consistency first");
+ reiserfs_close (fs);
+ return 1;
+ }
+ /* forced to continue without journal available/specifed */
+ }
+ }
+
+ /* journal was opened or it wasn't opened but the option
+ --no-journal-available has been specified by user */
+
+ /* make sure filesystem is not mounted */
+ if (is_mounted (fs->fs_file_name)) {
+ /* fixme: it can not be mounted, btw */
+ message ("can not rebuild journal of mounted filesystem");
+ reiserfs_close (fs);
+ return 1;
+ }
+
+ /* in spite of journal was opened, the file system can be non-consistent or
+ there are non-replayed transaction in journal,
+ make sure it isn't (if there is no the flag NEED_TUNE in ondisk superblock */
+ if (get_jp_journal_magic(sb_jp(fs->fs_ondisk_sb)) != NEED_TUNE &&
+ reiserfs_journal_opened (fs)) {
+ j_head = (struct reiserfs_journal_header *)(fs->fs_jh_bh->b_data);
+ if (get_boundary_transactions(fs, &old, &new)) {
+ if (new.trans_id != get_jh_last_flushed(j_head)) {
+ if (!(Options & OPT_SUPER_FORCE)) {
+ message ("There are non-replayed transaction in old journal,"
+ " check filesystem consistency first");
+ reiserfs_close (fs);
+ return 1;
+ }
+ }
+ }
+ if (!reiserfs_is_fs_consistent (fs)) {
+ message ("Check filesystem consistency first");
+ reiserfs_close (fs);
+ return 1;
+ }
+ }
+
+ reiserfs_reopen (fs, O_RDWR);
+
+ /* set UUID and LABEL if specified */
+ if (fs->fs_format == REISERFS_FORMAT_3_6) {
+ if (uuid_is_correct (UUID)) {
+ memcpy (fs->fs_ondisk_sb->s_uuid, UUID, 16);
+ mark_buffer_dirty (fs->fs_super_bh);
+ }
+
+ if (LABEL != NULL) {
+ if (strlen (LABEL) > 16)
+ message ("Specified LABEL is longer then 16 characters, will be truncated\n");
+ strncpy (fs->fs_ondisk_sb->s_label, LABEL, 16);
+ mark_buffer_dirty (fs->fs_super_bh);
+ }
+ fs->fs_dirt = 1;
+ } else {
+ if (uuid_is_correct (UUID))
+ reiserfs_panic ("UUID cannot be specified for 3.5 format\n");
+ if (LABEL)
+ reiserfs_panic ("LABEL cannot be specified for 3.5 format\n");
+ }
+
+ if (!j_new_device_name) {
+ /* new journal device hasn't been specify */
+ printf ("Current parameters:\n");
+ print_filesystem_state (stdout, fs);
+ print_block (stdout, fs, fs->fs_super_bh);
+ printf ("Current journal parameters:\n");
+ print_journal_params (stdout, sb_jp (fs->fs_ondisk_sb));
+
+ if ((Options & OPT_STANDARD)
+ && should_make_journal_standard(fs, j_new_device_name)) {
+ if (set_standard_journal_params (fs)) {
+ printf ("\nNew parameters:\n");
+ print_filesystem_state (stdout, fs);
+ print_block (stdout, fs, fs->fs_super_bh);
+ printf ("New journal parameters:\n");
+ print_journal_params (stdout, sb_jp (fs->fs_ondisk_sb));
+ mark_buffer_dirty (fs->fs_super_bh);
+ mark_buffer_uptodate (fs->fs_super_bh, 1);
+ mark_buffer_dirty (fs->fs_jh_bh);
+ mark_buffer_uptodate (fs->fs_jh_bh, 1);
+ reiserfs_close (fs);
+ printf ("Syncing.."); fflush (stdout);
+ sync ();
+ printf ("ok\n");
+ return 0;
+ }
+ }
+ if (Is_journal_or_maxtrans_size_specified)
+ /* new journal device hasn't been specified, but
+ journal size or max transaction size have been, so we suppose
+ that journal device remains the same */
+ j_new_device_name = jdevice_name;
+ else {
+ /* the only parameter has been specified is device_name, so
+ there is nothing to do */
+ reiserfs_close (fs);
+ return 0;
+ }
+ }
+
+ /* new journal device has been specified */
+ /* make sure new journal device is block device file */
+ if (!can_we_format_it (j_new_device_name, Force)) {
+ reiserfs_close (fs);
+ return 1;
+ }
+
+ if (!strcmp (device_name, j_new_device_name)) {
+ unsigned long reserved, journal_size;
+ /* we have to put journal on main device. It is only possible if there
+ is enough space reserved by mkreiserfs */
+
+ if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb))
+ /* standard journal */
+ reserved = get_jp_journal_size(sb_jp(fs->fs_ondisk_sb)) + 1;
+ else
+ /* non-standard journal */
+ reserved = get_sb_reserved_for_journal (fs->fs_ondisk_sb);
+
+ journal_size = (Journal_size ? Journal_size : journal_default_size(fs->fs_super_bh->b_blocknr, fs->fs_blocksize));
+
+/* journal_size = (Journal_size ? Journal_size : // specified
+ (fs->fs_blocksize == 1024 ? (fs->fs_blocksize) * 8 - 3 -
+ REISERFS_DISK_OFFSET_IN_BYTES / fs->fs_blocksize :
+ JOURNAL_DEFAULT_SIZE + 1)); // default
+*/
+ if (journal_size > reserved) {
+ message ("There is no enough space reserved for journal on main "
+ "device (journal_size=%lu, reserved=%lu\n", journal_size,
+ reserved);
+ reiserfs_close (fs);
+ return 1;
+ }
+ }
+
+ message ("Current journal parameters:");
+ print_journal_params (stdout, sb_jp (fs->fs_ondisk_sb));
+
+ if (!is_reiserfs_jr_magic_string (fs->fs_ondisk_sb)) {
+ /* we have standard journal, so check if we can convert it
+ to non-standard one */
+ if (!should_make_journal_non_standard (Force)) {
+ reiserfs_close (fs);
+ return 1;
+ }
+
+ if (is_reiserfs_3_6_magic_string (fs->fs_ondisk_sb))
+ set_sb_version (fs->fs_ondisk_sb, REISERFS_FORMAT_3_6);
+ else if (is_reiserfs_3_5_magic_string (fs->fs_ondisk_sb))
+ set_sb_version (fs->fs_ondisk_sb, REISERFS_FORMAT_3_5);
+ else {
+ message ("Could not convert from unknown version, try reiserfsck first");
+ reiserfs_close (fs);
+ return 1;
+ }
+
+ memcpy (fs->fs_ondisk_sb->s_v1.s_magic, REISERFS_JR_SUPER_MAGIC_STRING,
+ strlen (REISERFS_JR_SUPER_MAGIC_STRING));
+ set_sb_reserved_for_journal (fs->fs_ondisk_sb,
+ get_jp_journal_size (sb_jp(fs->fs_ondisk_sb)) + 1);
+ }
+
+ /* now we are going to close old journal and to create a new one */
+ reiserfs_close_journal (fs);
+
+ if (!reiserfs_create_journal (fs, j_new_device_name, Offset,
+ Journal_size, Max_trans_size)) {
+ message ("Could not create new journal");
+ reiserfs_close (fs);
+ return 1;
+ }
+
+ if (Options & OPT_STANDARD)
+ if (should_make_journal_standard (fs, j_new_device_name))
+ set_standard_journal_params (fs);
+
+ message ("New journal parameters:");
+ print_journal_params (stdout, sb_jp (fs->fs_ondisk_sb));
+
+ print_block (stdout, fs, fs->fs_super_bh);
+
+ if (Force < 2) {
+ message ("ATTENTION: YOU ARE ABOUT TO SETUP THE NEW JOURNAL FOR THE \"%s\"!\n"
+ "AREA OF \"%s\" DEDICATED FOR JOURNAL WILL BE ZEROED!",
+ device_name, j_new_device_name);
+
+ if (!user_confirmed (stderr, "Continue (y/n):", "y\n")) {
+ return 1;
+ }
+ }
+
+ zero_journal (fs);
+ reiserfs_close (fs);
+
+ printf ("Syncing.."); fflush (stdout);
+ sync ();
+ printf ("ok\n");
+
+ return 0;
+}
diff --git a/tune/tune.h b/tune/tune.h
new file mode 100644
index 0000000..529ac4c
--- /dev/null
+++ b/tune/tune.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2002 Hans Reiser, licensing governed by ../README
+ */
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <asm/types.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/vfs.h>
+#include <time.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <linux/kdev_t.h>
+#include <sys/utsname.h>
+#include <getopt.h>
+#include <stdarg.h>
+
+#include "io.h"
+#include "misc.h"
+#include "reiserfs_lib.h"
+#include "../include/config.h"
+#include "../version.h"
+
+/* main.c */
+extern reiserfs_filsys_t * fs;
+
+
+/*
+ * options
+ */
+#define OPT_SUPER_FORCE 0x0010
+#define OPT_OLD_J 0x0100
+#define OPT_NEW_J 0x0200
+#define OPT_SIZEJ 0x0400
+#define OPT_TMAXS 0x0800
+#define OPT_OFSET 0x1000
+#define OPT_SKIP_J 0x2000
+#define OPT_KEEPO 0x4000
+#define OPT_FORCE 0x8000
+#define OPT_STANDARD 0x0020
+
+extern char *program_name;
diff --git a/version.h b/version.h
index 542da44..c62ca84 100644
--- a/version.h
+++ b/version.h
@@ -1,9 +1,7 @@
/*
- * Copyright 2000 Hans Reiser
+ * Copyright 2002 Hans Reiser
*/
-#define REISERFSPROGS_VERSION "3.x.0j"
-
#define print_banner(prog) \
-fprintf (stderr, "\n<-------------%s, 2001------------->\nreiserfsprogs %s\n", \
-prog, REISERFSPROGS_VERSION)
+fprintf (stderr, "\n<-------------%s, 2002------------->\nreiserfsprogs %s\n\n", \
+prog, VERSION)