Initial commit -- seeded with reiserfsprogs 3.x.0j

This commit is contained in:
Jeff Mahoney committed 2012-10-11 11:26:22 -04:00
commit e7102bdb66
77 files changed
+33513

No files matched your search

View File
Whitespace-only changes.
+340
View File
@@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.
+120
View File
@@ -0,0 +1,120 @@
2001-03-31
* reiserfsck
empty lost directories do not get linked into /lost+found
2001-03-28
* reiserfsck
--nolog option is added
2001-03-26
* called 3.x.0j
* reiserfsck
with -o it tries to fix "objectid sharing" problem
* reiserfsprogs.spec (Anthon van der Neut)
rpm can be built as non-root
link from reiserfsck to fsck.reiserfs
rpm -e reiserfsprogs should now work w/o rmdir of /
2001-03-13
* reiserfsck
--quiet option is added
--fix-bogus-files option is added to fix transprently
corrupted modes and to fix sizes which are longer that
real file size
directory item verifying changed
-u has been replaced with -b to pass reiserfsck the list
of block to build tree off
-c is added to have pass 0 to save bitmap fo leaves found
2001-03-10
* called 3.x.0h
* configure.in
RPM_OPT_FLASG is added to CFLAGS (Anthon van der Neut)
* reiserfsck
-u option is added. It should save time when repeating
--rebuild-tree
hash hits statistic is added on pass 0
2001-03-07
* reiserfsck
-V option to print version and exit added
--fix-fixable changed: directory's sd_size and st_blocks
corrections, removing of entries pointing to nowhere
* resize_reiserfs
man page is added
2001-03-05
* resize_reiserfs
Marcel Waldvogel <mwa@arlq.wustl.edu>'s user interface and
error messages improvements
2001-03-01
* mkreiserfs
-q option is added (Larry Auton <lda@winux.com>)
* reiserfsck
--fix-fixable changed: bitmap correction commented
out. Correction of broken slots of indirect items and
corrections of dir entry state added
2001-02-23
* called 3.x.0e
* reiserfsck
not tested on 2.2
is now able to work with regular file (2.4.x is needed for that)
lost+found fixed: it now first links directories then
files. Still not good as it can not pull out deep directory
2001-02-19
* called 3.x.0c
* reiserfsck
--fix-fixable option is added. So far it only repairs bitmaps
and free block count when they mismatch
* library
reiserfs_find/add_entry added
2001-02-05
* mkreiserfs
can make filesystem with 1 data block
3.6 format is now default
2001-01-20
* portability
Zam ran the reiserfsprogs on alpha
* resizer
Zam managed to resize few partitions.
* reiserfsck
pass0 deletes items which are out of order, tries to fix
items with zeroed k_objectid or k_dir_id and to throw
items which are transparently out of order and tries to
fix "." and ".." of directory items. Pass0 corrects also
corruptions in directory items
* man pages:
get included into dist when doing 'make dist'
* mkreisrefs
explains what is mininal size of reiserfs partition which
can be created
2001-01-12
* reiserfsck:
--interactive option is added
* debugreiserfs:
few bugs fixed
2001-01-07
* reiserfs library:
started with reiserfs_open, reiserfs_close, bitmap tools
* reiserfsck:
filesystem mounted read-only can be checked
number of options decreased
journal replay fixed
pass 0 added.
fsck can be stopped after the tree is built. (should safe time when debugging)
a lot of work still left
* debugreiserfs:
metadata packing changed
added a feature to intentionally corrupt filesystem (should be useful for fsck debugging)
* resizer:
not updated yet
* man pages:
updated for all three progs
+182
View File
@@ -0,0 +1,182 @@
Basic Installation
==================
These are generic installation instructions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, a file
`config.cache' that saves the results of its tests to speed up
reconfiguring, and a file `config.log' containing compiler output
(useful mainly for debugging `configure').
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If at some point `config.cache'
contains results you don't want to keep, you may remove or edit it.
The file `configure.in' is used to create `configure' by a program
called `autoconf'. You only need `configure.in' if you want to change
it or regenerate `configure' using a newer version of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system. If you're
using `csh' on an old version of System V, you might need to type
`sh ./configure' instead to prevent `csh' from trying to execute
`configure' itself.
Running `configure' takes awhile. While running, it prints some
messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. You can give `configure'
initial values for variables by setting them in the environment. Using
a Bourne-compatible shell, you can do that on the command line like
this:
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
Or on systems that have the `env' program, you can do it like this:
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you must use a version of `make' that
supports the `VPATH' variable, such as GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
If you have to use a `make' that does not supports the `VPATH'
variable, you have to compile the package for one architecture at a time
in the source code directory. After you have installed the package for
one architecture, use `make distclean' before reconfiguring for another
architecture.
Installation Names
==================
By default, `make install' will install the package's files in
`/usr/local/bin', `/usr/local/man', etc. You can specify an
installation prefix other than `/usr/local' by giving `configure' the
option `--prefix=PATH'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
give `configure' the option `--exec-prefix=PATH', the package will use
PATH as the prefix for installing programs and libraries.
Documentation and other data files will still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=PATH' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' can not figure out
automatically, but needs to determine by the type of host the package
will run on. Usually `configure' can figure that out, but if it prints
a message saying it can not guess the host type, give it the
`--host=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name with three fields:
CPU-COMPANY-SYSTEM
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the host type.
If you are building compiler tools for cross-compiling, you can also
use the `--target=TYPE' option to select the type of system they will
produce code for and the `--build=TYPE' option to select the type of
system on which you are compiling the package.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Operation Controls
==================
`configure' recognizes the following options to control how it
operates.
`--cache-file=FILE'
Use and save the results of the tests in FILE instead of
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
debugging `configure'.
`--help'
Print a summary of the options to `configure', and exit.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--version'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`configure' also accepts some other, not widely useful, options.
+4
View File
@@ -0,0 +1,4 @@
SUBDIRS = include lib reiserfscore mkreiserfs fsck debugreiserfs resize_reiserfs
EXTRA_DIST = version.h reiserfsprogs.spec
+318
View File
@@ -0,0 +1,318 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 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@
SUBDIRS = include lib reiserfscore mkreiserfs fsck debugreiserfs resize_reiserfs
EXTRA_DIST = version.h reiserfsprogs.spec
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \
Makefile.in NEWS aclocal.m4 configure configure.in install-sh missing \
mkinstalldirs
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
all: all-redirect
.SUFFIXES:
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
$(ACLOCAL_M4): configure.in
cd $(srcdir) && $(ACLOCAL)
config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES)
cd $(srcdir) && $(AUTOCONF)
# 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,
# (1) if the variable is set in `config.status', edit `config.status'
# (which will cause the Makefiles to be regenerated when you run `make');
# (2) otherwise, pass the desired values on the `make' command line.
@SET_MAKE@
all-recursive install-data-recursive install-exec-recursive \
installdirs-recursive install-recursive uninstall-recursive \
check-recursive installcheck-recursive info-recursive dvi-recursive:
@set fnord $(MAKEFLAGS); amf=$$2; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
mostlyclean-recursive clean-recursive distclean-recursive \
maintainer-clean-recursive:
@set fnord $(MAKEFLAGS); amf=$$2; \
dot_seen=no; \
rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \
rev="$$subdir $$rev"; \
test "$$subdir" = "." && dot_seen=yes; \
done; \
test "$$dot_seen" = "no" && rev=". $$rev"; \
target=`echo $@ | sed s/-recursive//`; \
for subdir in $$rev; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done && test -z "$$fail"
tags-recursive:
list='$(SUBDIRS)'; for subdir in $$list; do \
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
done
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: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SUBDIRS)'; for subdir in $$list; do \
if test "$$subdir" = .; then :; else \
test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \
fi; \
done; \
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 = $(PACKAGE)-$(VERSION)
top_distdir = $(distdir)
# This target untars the dist file and tries a VPATH configuration. Then
# it guarantees that the distribution is self-contained by making another
# tarfile.
distcheck: dist
-rm -rf $(distdir)
GZIP=$(GZIP_ENV) $(TAR) zxf $(distdir).tar.gz
mkdir $(distdir)/=build
mkdir $(distdir)/=inst
dc_install_base=`cd $(distdir)/=inst && pwd`; \
cd $(distdir)/=build \
&& ../configure --srcdir=.. --prefix=$$dc_install_base \
&& $(MAKE) $(AM_MAKEFLAGS) \
&& $(MAKE) $(AM_MAKEFLAGS) dvi \
&& $(MAKE) $(AM_MAKEFLAGS) check \
&& $(MAKE) $(AM_MAKEFLAGS) install \
&& $(MAKE) $(AM_MAKEFLAGS) installcheck \
&& $(MAKE) $(AM_MAKEFLAGS) dist
-rm -rf $(distdir)
@banner="$(distdir).tar.gz is ready for distribution"; \
dashes=`echo "$$banner" | sed s/./=/g`; \
echo "$$dashes"; \
echo "$$banner"; \
echo "$$dashes"
dist: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
dist-all: distdir
-chmod -R a+r $(distdir)
GZIP=$(GZIP_ENV) $(TAR) chozf $(distdir).tar.gz $(distdir)
-rm -rf $(distdir)
distdir: $(DISTFILES)
-rm -rf $(distdir)
mkdir $(distdir)
-chmod 777 $(distdir)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
for subdir in $(SUBDIRS); do \
if test "$$subdir" = .; then :; else \
test -d $(distdir)/$$subdir \
|| mkdir $(distdir)/$$subdir \
|| exit 1; \
chmod 777 $(distdir)/$$subdir; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(distdir) distdir=../$(distdir)/$$subdir distdir) \
|| exit 1; \
fi; \
done
info-am:
info: info-recursive
dvi-am:
dvi: dvi-recursive
check-am: all-am
check: check-recursive
installcheck-am:
installcheck: installcheck-recursive
install-exec-am:
install-exec: install-exec-recursive
install-data-am:
install-data: install-data-recursive
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-recursive
uninstall-am:
uninstall: uninstall-recursive
all-am: Makefile
all-redirect: all-recursive
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs: installdirs-recursive
installdirs-am:
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-tags mostlyclean-generic
mostlyclean: mostlyclean-recursive
clean-am: clean-tags clean-generic mostlyclean-am
clean: clean-recursive
distclean-am: distclean-tags distclean-generic clean-am
distclean: distclean-recursive
-rm -f config.status
maintainer-clean-am: 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 \
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 \
install-exec install-data-am install-data install-am install \
uninstall-am uninstall all-redirect all-am all installdirs-am \
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:
View File
Whitespace-only changes.
+157
View File
@@ -0,0 +1,157 @@
[LICENSING]
ReiserFS is hereby licensed under the GNU General
Public License version 2.
Source code files that contain the phrase "licensing governed by
reiserfs/README" are "governed files" throughout this file. Governed
files are licensed under the GPL. The portions of them owned by Hans
Reiser, or authorized to be licensed by him, have been in the past,
and likely will be in the future, licensed to other parties under
other licenses. If you add your code to governed files, and don't
want it to be owned by Hans Reiser, put your copyright label on that
code so the poor blight and his customers can keep things straight.
All portions of governed files not labeled otherwise are owned by Hans
Reiser, and by adding your code to it, widely distributing it to
others or sending us a patch, and leaving the sentence in stating that
licensing is governed by the statement in this file, you accept this.
It will be a kindness if you identify whether Hans Reiser is allowed
to license code labeled as owned by you on your behalf other than
under the GPL, because he wants to know if it is okay to do so and put
a check in the mail to you (for non-trivial improvements) when he
makes his next sale. He makes no guarantees as to the amount if any,
though he feels motivated to motivate contributors, and you can surely
discuss this with him before or after contributing. You have the
right to decline to allow him to license your code contribution other
than under the GPL.
Further licensing options are available for commercial and/or other
interests directly from Hans Reiser: hans@reiser.to. If you interpret
the GPL as not allowing those additional licensing options, you read
it wrongly, and Richard Stallman agrees with me, when carefully read
you can see that those restrictions on additional terms do not apply
to the owner of the copyright, and my interpretation of this shall
govern for this license.
Finally, nothing in this license shall be interpreted to allow you to
fail to fairly credit me, or to remove my credits, without my
permission, unless you are an end user not redistributing to others.
If you have doubts about how to properly do that, or about what is
fair, ask. (Last I spoke with him Richard was contemplating how best
to address the fair crediting issue in the next GPL version.)
[END LICENSING]
Reiserfs is a file system based on balanced tree algorithms, which is
described at http://www.namesys.com .
Stop reading here. Go there, then return.
Send bug reports to yura@namesys.botik.ru.
mkreiserfs and other utilities are in reiserfs/utils, or wherever your
Linux provider put them. There is some disagreement about how useful
it is for users to get their fsck and mkreiserfs out of sync with the
version of reiserfs that is in their kernel, with many important
distributors wanting them out of sync.:-) Please try to remember to
recompile and reinstall fsck and mkreiserfs with every update of
reiserfs, this is a common source of confusion. Note that some of the
utilities cannot be compiled without accessing the balancing code
which is in the kernel code, and relocating the utilities may require
you to specify where that code can be found.
Yes, if you update your reiserfs kernel module you do have to
recompile your kernel, most of the time. The errors you get will be
quite cryptic if your forget to do so.
Real users, as opposed to folks who want to hack and then understand
what went wrong, will want REISERFS_CHECK off.
Hideous Commercial Pitch: Spread your development costs across other OS
vendors. Select from the best in the world, not the best in your
building, by buying from third party OS component suppliers. Leverage
the software component development power of the internet. Be the most
aggressive in taking advantage of the commercial possibilities of
decentralized internet development, and add value through your branded
integration that you sell as an operating system. Let your competitors
be the ones to compete against the entire internet by themselves. Be
hip, get with the new economic trend, before your competitors do. Send
email to hans@reiser.to.
To understand the code, after reading the website, start reading the
code by reading reiserfs_fs.h first.
Hans Reiser was the project initiator, primary architect, source of all
funding for the first 5.5 years, and one of the programmers. He owns
the copyright.
Vladimir Saveljev was one of the programmers, and he worked long hours
writing the cleanest code. He always made the effort to be the best he
could be, and to make his code the best that it could be. What resulted
was quite remarkable. I don't think that money can ever motivate someone
to work the way he did, he is one of the most selfless men I know.
Yura helps with benchmarking, coding hashes, and block pre-allocation
code.
Anatoly Pinchuk is a former member of our team who worked closely with
Vladimir throughout the project's development. He wrote a quite
substantial portion of the total code. He realized that there was a
space problem with packing tails of files for files larger than a node
that start on a node aligned boundary (there are reasons to want to node
align files), and he invented and implemented indirect items and
unformatted nodes as the solution.
Konstantin Shvachko, with the help of the Russian version of a VC,
tried to put me in a position where I was forced into giving control
of the project to him. (Fortunately, as the person paying the money
for all salaries from my dayjob I owned all copyrights, and you can't
really force takeovers of sole proprietorships.) This was something
curious, because he never really understood the value of our project,
why we should do what we do, or why innovation was possible in
general, but he was sure that he ought to be controlling it. Every
innovation had to be forced past him while he was with us. He added
two years to the time required to complete reiserfs, and was a net
loss for me. Mikhail Gilula was a brilliant innovator who also left
in a destructive way that erased the value of his contributions, and
that he was shown much generosity just makes it more painful.
Grigory Zaigralin was an extremely effective system administrator for
our group.
Igor Krasheninnikov was wonderful at hardware procurement, repair, and
network installation.
Jeremy Fitzhardinge wrote the teahash.c code, and he gives credit to a
textbook he got the algorithm from in the code. Note that his analysis
of how we could use the hashing code in making 32 bit NFS cookies work
was probably more important than the actual algorithm. Colin Plumb also
contributed to it.
Chris Mason dived right into our code, and in just a few months produced
the journaling code that dramatically increased the value of ReiserFS.
He is just an amazing programmer.
Igor Zagorovsky is writing much of the new item handler and extent code
for our next major release.
Alexander Zarochentcev (sometimes known as zam, or sasha), wrote the
resizer, and is hard at work on implementing allocate on flush. SGI
implemented allocate on flush before us for XFS, and generously took
the time to convince me we should do it also. They are great people,
and a great company.
Yuri Shevchuk and Nikita Danilov are doing squid cache optimization.
Vitaly Fertman is doing fsck.
SuSE, IntegratedLinux.com, Ecila, MP3.com, bigstorage.com, and the
Alpha PC Company made it possible for me to not have a day job
anymore, and to dramatically increase our staffing. Ecila funded
hypertext feature development, MP3.com funded journaling, SuSE funded
core development, IntegratedLinux.com funded squid web cache
appliances, bigstorage.com funded HSM, and the alpha PC company funded
the alpha port. Many of these tasks were helped by sponsors other
than the ones just named. SuSE has helped in much more than just
funding....
Vendored
+104
View File
@@ -0,0 +1,104 @@
dnl aclocal.m4 generated automatically by aclocal 1.4
dnl Copyright (C) 1994, 1995-8, 1999 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.
dnl This program is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
dnl PARTICULAR PURPOSE.
# Do all the work for Automake. This macro actually does too much --
# some checks are only needed if your package does certain things.
# But this isn't really a big deal.
# serial 1
dnl Usage:
dnl AM_INIT_AUTOMAKE(package,version, [no-define])
AC_DEFUN(AM_INIT_AUTOMAKE,
[AC_REQUIRE([AC_PROG_INSTALL])
PACKAGE=[$1]
AC_SUBST(PACKAGE)
VERSION=[$2]
AC_SUBST(VERSION)
dnl test to see if srcdir already configured
if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
ifelse([$3],,
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]))
AC_REQUIRE([AM_SANITY_CHECK])
AC_REQUIRE([AC_ARG_PROGRAM])
dnl FIXME This is truly gross.
missing_dir=`cd $ac_aux_dir && pwd`
AM_MISSING_PROG(ACLOCAL, aclocal, $missing_dir)
AM_MISSING_PROG(AUTOCONF, autoconf, $missing_dir)
AM_MISSING_PROG(AUTOMAKE, automake, $missing_dir)
AM_MISSING_PROG(AUTOHEADER, autoheader, $missing_dir)
AM_MISSING_PROG(MAKEINFO, makeinfo, $missing_dir)
AC_REQUIRE([AC_PROG_MAKE_SET])])
#
# Check to make sure that the build environment is sane.
#
AC_DEFUN(AM_SANITY_CHECK,
[AC_MSG_CHECKING([whether build environment is sane])
# Just in case
sleep 1
echo timestamp > conftestfile
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null`
if test "[$]*" = "X"; then
# -L didn't work.
set X `ls -t $srcdir/configure conftestfile`
fi
if test "[$]*" != "X $srcdir/configure conftestfile" \
&& test "[$]*" != "X conftestfile $srcdir/configure"; then
# If neither matched, then we have a broken ls. This can happen
# 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".
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
alias in your environment])
fi
test "[$]2" = conftestfile
)
then
# Ok.
:
else
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock])
fi
rm -f conftest*
AC_MSG_RESULT(yes)])
dnl AM_MISSING_PROG(NAME, PROGRAM, DIRECTORY)
dnl The program must properly implement --version.
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.
# Redirect stdin to placate older versions of autoconf. Sigh.
if ($2 --version) < /dev/null > /dev/null 2>&1; then
$1=$2
AC_MSG_RESULT(found)
else
$1="$3/missing $2"
AC_MSG_RESULT(missing)
fi
AC_SUBST($1)])
Vendored Executable
+2066
View File
File diff suppressed because it is too large. Load diff
+48
View File
@@ -0,0 +1,48 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(version.h)
AM_INIT_AUTOMAKE(reiserfsprogs, 3.x.0j)
dnl We install in /sbin, the utils are to be available on boot
AC_PREFIX_DEFAULT(/)
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"
fi
dnl Checks for programs.
AC_PROG_RANLIB
dnl AC_PROG_AWK
dnl AC_PROG_INSTALL
dnl AC_PROG_LN_S
dnl Checks for libraries.
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(fcntl.h limits.h malloc.h sys/ioctl.h unistd.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_C_INLINE
AC_TYPE_SIZE_T
AC_STRUCT_ST_RDEV
dnl Checks for library functions.
AC_PROG_GCC_TRADITIONAL
AC_FUNC_MEMCMP
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)
+10
View File
@@ -0,0 +1,10 @@
sbin_PROGRAMS = debugreiserfs unpack
debugreiserfs_SOURCES = debugreiserfs.c pack.c
unpack_SOURCES = unpack.c debugreiserfs.h
man_MANS = debugreiserfs.8
EXTRA_DIST = $(man_MANS)
LDADD = ../lib/libmisc.a ../reiserfscore/libcore.a
INCLUDES = -I../include
+339
View File
@@ -0,0 +1,339 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 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@
sbin_PROGRAMS = debugreiserfs unpack
debugreiserfs_SOURCES = debugreiserfs.c pack.c
unpack_SOURCES = unpack.c debugreiserfs.h
man_MANS = debugreiserfs.8
EXTRA_DIST = $(man_MANS)
LDADD = ../lib/libmisc.a ../reiserfscore/libcore.a
INCLUDES = -I../include
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
PROGRAMS = $(sbin_PROGRAMS)
DEFS = @DEFS@ -I. -I$(srcdir)
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
debugreiserfs_OBJECTS = debugreiserfs.o pack.o
debugreiserfs_LDADD = $(LDADD)
debugreiserfs_DEPENDENCIES = ../lib/libmisc.a ../reiserfscore/libcore.a
debugreiserfs_LDFLAGS =
unpack_OBJECTS = unpack.o
unpack_LDADD = $(LDADD)
unpack_DEPENDENCIES = ../lib/libmisc.a ../reiserfscore/libcore.a
unpack_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 = $(debugreiserfs_SOURCES) $(unpack_SOURCES)
OBJECTS = $(debugreiserfs_OBJECTS) $(unpack_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 debugreiserfs/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:
debugreiserfs: $(debugreiserfs_OBJECTS) $(debugreiserfs_DEPENDENCIES)
@rm -f debugreiserfs
$(LINK) $(debugreiserfs_LDFLAGS) $(debugreiserfs_OBJECTS) $(debugreiserfs_LDADD) $(LIBS)
unpack: $(unpack_OBJECTS) $(unpack_DEPENDENCIES)
@rm -f unpack
$(LINK) $(unpack_LDFLAGS) $(unpack_OBJECTS) $(unpack_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 = debugreiserfs
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
debugreiserfs.o: debugreiserfs.c debugreiserfs.h ../include/io.h \
../include/misc.h ../include/reiserfs_lib.h \
../include/reiserfs_fs.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
unpack.o: unpack.c debugreiserfs.h ../include/io.h ../include/misc.h \
../include/reiserfs_lib.h ../include/reiserfs_fs.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:
+68
View File
@@ -0,0 +1,68 @@
.\" -*- nroff -*-
.\" Copyright 1996-2001 Hans Reiser.
.\"
.TH DEBUGREISERFS 8 "March 2001" "Reiserfsprogs 3.x.0j"
.SH NAME
debugreiserfs
.SH SYNOPSIS
.B debugreiserfs
[
.B -jdcmos
] [
.B -b \fIblocknumber
] [
.B -p \fIfilename.bmp
] [
.B -P \fIfilename.bmp
]
.I device
.SH DESCRIPTION
It helps sometimes to solve problems with reiserfs filesystems. Being
called w/o options it prints super block of reiserfs filesystem found
on the \fIdevice\fR.
.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).
.SH OPTIONS
.TP
\fB-j
print contents of journal
.TP
\fB-d
print formatted nodes of the filesystem
.TP
\fB-c
print contents of direct items
.TP
\fB-m
print contents of bitmap (not very useful)
.TP
\fB-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
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
.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>.
.SH SEE ALSO
.BR reiserfsck (8),
.BR mkreiserfs (8)
File diff suppressed because it is too large. Load diff
+135
View File
@@ -0,0 +1,135 @@
/*
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <malloc.h>
#include <sys/types.h>
#include <asm/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "io.h"
#include "misc.h"
#include "reiserfs_lib.h"
#include "../version.h"
/*
* 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 */
extern int opt_quiet;
extern int mode;
// the leaf is stored in compact form:
// start magic number
// block number __u32
// item number __u16
// struct packed_item
// ..
// end magic number
/* we store hash code in high byte of 16 bits */
#define LEAF_START_MAGIC 0xa5
#define LEAF_END_MAGIC 0x5a
#define FULL_BLOCK_START_MAGIC 0xb6
#define FULL_BLOCK_END_MAGIC 0x6b
#define UNFORMATTED_BITMAP_START_MAGIC 0xc7
#define UNFORMATTED_BITMAP_END_MAGIC 0x7c
#define END_MAGIC 0x8d
#define INTERNAL_START_MAGIC
#define INTERNAL_START_MAGIC
#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 */
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;
};
#define HAS_DIR_ID 1
#define HAS_GEN_COUNTER 2
#define HAS_STATE 4
#define YURA 8
#define TEA 16
#define R5 32
struct packed_dir_entry {
__u8 mask;
__u16 entrylen;
};
#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 fwrite8(pv) {\
if (fwrite (pv, sizeof (__u8), 1, stdout) != 1)\
reiserfs_panic ("fwrite8 failed: %m");\
}
#define fwrite16(pv) {\
if (fwrite (pv, sizeof (__u16), 1, stdout) != 1)\
reiserfs_panic ("fwrite16 failed: %m");\
}
#define fwrite32(pv) {\
if (fwrite (pv, sizeof (__u32), 1, stdout) != 1)\
reiserfs_panic ("fwrite32 failed: %m");\
}
#define fwrite64(pv) {\
if (fwrite (pv, sizeof (__u64), 1, stdout) != 1)\
reiserfs_panic ("fwrite64 failed: %m");\
}
/*
#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;
+765
View File
@@ -0,0 +1,765 @@
/*
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
#include "debugreiserfs.h"
reiserfs_bitmap_t what_to_pack;
reiserfs_bitmap_t what_packed;
int packed_leaves, bad_leaves, full_blocks, internals, descs, full_of_journal;
/* 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 */
static void pack_key (struct packed_item * pi, struct item_head * ih)
{
if (pi->mask & DIR_ID) {
fwrite32 (&ih->ih_key.k_dir_id);
sent += sizeof (__u32);
}
if (pi->mask & OBJECT_ID) {
fwrite32 (&ih->ih_key.k_objectid);
sent += sizeof (__u32);
}
if (pi->mask & OFFSET_BITS_64) {
__u64 offset;
offset = get_offset (&ih->ih_key);
fwrite64 (&offset);
sent += sizeof (__u64);
}
if (pi->mask & OFFSET_BITS_32) {
__u32 offset;
offset = get_offset (&ih->ih_key);
fwrite32 (&offset);
sent += sizeof (__u32);
}
}
static void pack_direct (struct packed_item * pi, struct buffer_head * bh,
struct item_head * ih)
{
pi->mask |= DIRECT_ITEM;
/* 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);
}
/* if there is at least one extent longer than 2 - it is worth packing */
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 */
len ++;
if (len > 2)
return 1;
} else {
/* sequence of blocks or hole broke */
len = 1;
}
}
return 0;
}
/* indirect item can be either packed using "extents" (when it is
worth doing) or be stored as is. Size of item in packed form is not
stored. Unpacking will stop when full item length is reached */
static void pack_indirect (struct packed_item * pi, struct buffer_head * bh,
struct item_head * ih)
{
int i;
__u32 * ind_item;
__u16 len;
pi->mask |= INDIRECT_ITEM;
if (ih_entry_count (ih))
pi->mask |= ENTRY_COUNT;
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);
/* send key components which are to be sent */
pack_key (pi, ih);
if (pi->mask & ENTRY_COUNT) {
__u16 ih_free_space;
ih_free_space = ih_entry_count (ih);
fwrite16 (&ih_free_space);
sent += sizeof (__u16);
}
if (pi->mask & WHOLE_INDIRECT) {
fwrite (ind_item, ih_item_len (ih), 1, stdout);
sent += 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 */
ind_item [i] == ind_item[ i - 1] + 1) { /* subsequent blocks */
len ++;
} else {
fwrite16 (&len);
fwrite32 (&ind_item[i]);
sent += (sizeof (__u32) + sizeof (__u16));
len = 1;
}
}
fwrite16 (&len);
sent += sizeof (__u16);
return;
}
/* directory item is packed:
entry count - 16 bits
for each entry
mask (8 bits) - it shows whether there are any of (deh_dir_id, gen counter, deh_state)
entry length 16 bits
entry itself
deh_objectid - 32 bits
maybe deh_dir_id (32 bits)
maybe gencounter (16)
maybe deh_state (16)
*/
static void pack_direntry (reiserfs_filsys_t fs, struct packed_item * pi,
struct buffer_head * bh,
struct item_head * ih)
{
int i;
struct reiserfs_de_head * deh;
struct packed_dir_entry pe;
__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);
/* send key components which are to be sent */
pack_key (pi, ih);
/* entry count is sent unconditionally */
entry_count = ih_entry_count (ih);
fwrite16 (&entry_count);
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))
/* entry points to name of another directory, store deh_dir_id */
pe.mask |= HAS_DIR_ID;
gen_counter = GET_GENERATION_NUMBER (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)
/* something unusual in deh_state. Store it */
pe.mask |= HAS_STATE;
fwrite8 (&pe.mask);
fwrite16 (&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));
if (pe.mask & HAS_DIR_ID) {
fwrite32 (&deh->deh_dir_id);
sent += sizeof (__u32);
}
if (pe.mask & HAS_GEN_COUNTER) {
fwrite16 (&gen_counter);
sent += sizeof (__u16);
}
if (pe.mask & HAS_STATE) {
fwrite16 (&deh->deh_state);
sent += sizeof (__u16);
}
}
}
static void pack_stat_data (struct packed_item * pi, struct buffer_head * bh,
struct item_head * ih)
{
pi->mask |= STAT_DATA_ITEM;
if (stat_data_v1 (ih)) {
/* for old stat data: we take
mode - 16 bits
nlink - 16 bits
size - 32 bits
blocks/rdev - 32 bits
maybe first_direct byte 32 bits
*/
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;
/* 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);
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) {
fwrite32 (&sd_v1->sd_first_direct_byte);
sent += sizeof (__u32);
}
} else {
/* for new stat data
mode - 16 bits
nlink in either 16 or 32 bits
size in either 32 or 64 bits
blocks - 32 bits
*/
struct stat_data * sd;
__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;
nlink32 = sd->sd_nlink;
} else {
nlink16 = sd->sd_nlink;
}
if (sd->sd_size > 0xffffffff) {
pi->mask |= SIZE_BITS_64;
size64 = sd->sd_size;
} else {
size32 = sd->sd_size;
}
/* 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);
fwrite16 (&sd->sd_mode);
sent += sizeof (__u16);
if (pi->mask & NLINK_BITS_32) {
fwrite32 (&nlink32);
sent += sizeof (__u32);
} else {
fwrite16 (&nlink16);
sent += sizeof (__u16);
}
if (pi->mask & 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)
{
__u16 magic;
__u32 block;
magic = FULL_BLOCK_START_MAGIC;
fwrite16 (&magic);
block = bh->b_blocknr;
fwrite32 (&block);
fwrite (bh->b_data, 4096, 1, stdout);
sent += 4096;
had_to_be_sent += 4096;
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 ++;
}
/* 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)
{
if (block >= SB_BLOCK_COUNT (fs))
return 1;
if (not_data_block (fs, block))
return 1;
return 0;
}
/* we only pack leaves which do not have any corruptions */
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*/))
return 0;
}
return 1;
}
/* 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)
{
int i;
struct item_head * ih;
struct packed_item pi;
__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);
bad_leaves ++;
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);
/* block number */
fwrite32 (&bh->b_blocknr);
/* item number */
v16 = node_item_number (bh);
fwrite16 (&v16);
ih = B_N_PITEM_HEAD (bh, 0);
for (i = 0; i < node_item_number (bh); i ++, ih ++) {
#if 0
v32 = ITEM_START_MAGIC;
fwrite32 (&v32);
#endif
pi.mask = 0;
pi.item_len = ih_item_len (ih);
// format
if (ih_key_format (ih) == KEY_FORMAT_2)
pi.mask |= NEW_FORMAT;
// k_dir_id
if (!i || (i && ih->ih_key.k_dir_id != (ih - 1)->ih_key.k_dir_id)) {
/* if item is first in the leaf or if previous item has different
k_dir_id - store it */
pi.mask |= DIR_ID;
}
// k_object_id
if (!i || (i && ih->ih_key.k_objectid != (ih - 1)->ih_key.k_objectid)) {
/* if item is first in the leaf or if previous item has different
k_objectid - store it */
pi.mask |= 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;
}
if (is_direct_ih (ih)) {
pack_direct (&pi, bh, ih);
} else if (is_indirect_ih (ih))
pack_indirect (&pi, bh, ih);
else if (is_direntry_ih (ih))
pack_direntry (fs, &pi, bh, ih);
else if (is_stat_data_ih (ih))
pack_stat_data (&pi, bh, ih);
else
die ("pack_leaf: unknown item found");
#if 0
v32 = ITEM_END_MAGIC;
fwrite32 (&v32);
#endif
}
v16 = LEAF_END_MAGIC;
fwrite16 (&v16);
packed_leaves ++;
had_to_be_sent += 4096;
return;
}
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)
{
if (!can_pack_internal (fs, bh)) {
pack_full_block (fs, bh);
return;
}
reiserfs_panic ("pack_internal: packing code is not ready");
}
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)
{
int type;
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 */
pack_full_block (fs, bh);
} else
pack_leaf (fs, bh);
reiserfs_bitmap_set_bit (what_packed, bh->b_blocknr);
reiserfs_bitmap_clear_bit (what_to_pack, bh->b_blocknr);
}
/* super block, journal, bitmaps */
static void pack_frozen_data (reiserfs_filsys_t fs)
{
int i;
struct buffer_head * bh;
/* 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));
fflush (stderr);
/* bitmaps */
for (i = 0; i < SB_BMAP_NR (fs); i ++) {
send_block (fs, SB_AP_BITMAP (fs)[i]);
}
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));
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);
brelse (bh);
}
reiserfs_warning (stderr, "ok\n");fflush (stderr);
}
/* pack all "not data blocks" and correct leaf */
void pack_partition (reiserfs_filsys_t fs)
{
int i, j;
struct buffer_head tmp, * bh;
int nr_to_read = BLOCKS_PER_READ;
__u32 magic32;
__u16 blocksize;
__u16 magic16;
unsigned long done = 0, total;
magic32 = REISERFS_SUPER_MAGIC;
fwrite32 (&magic32);
blocksize = fs->s_blocksize;
fwrite16 (&blocksize);
tmp.b_size = 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));
}
/* 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));
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);
}
}
}
}
magic16 = END_MAGIC;
fwrite16 (&magic16);
fprintf (stderr, "Packed\n\tleaves %d\n"
"\tfull blocks %d\n"
"\t\tof journal %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);
if (where_to_save)
reiserfs_bitmap_save (where_to_save, what_packed);
}
void pack_one_block (reiserfs_filsys_t fs, unsigned long block)
{
__u32 magic32;
__u16 magic16;
struct buffer_head * bh;
// reiserfs magic
magic32 = REISERFS_SUPER_MAGIC;
fwrite32 (&magic32);
// blocksize
fwrite16 (&fs->s_blocksize);
bh = bread (fs->s_dev, block, fs->s_blocksize);
if (who_is_this (bh->b_data, bh->b_size) == THE_LEAF)
pack_leaf (fs, bh);
else
pack_full_block (fs, bh);
brelse (bh);
// end magic
magic16 = END_MAGIC;
fwrite16 (&magic16);
fprintf (stderr, "Packed\n\tleaves %d\n\tfull block %d\n\tcorrupted leaves %d\n",
packed_leaves, full_blocks, bad_leaves);
}
#if 0
//
// 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'
//
static int do_unpack (char * file)
{
char * buf;
int fd;
fd = open (file, O_RDONLY);
if (fd == -1) {
perror ("open failed");
return 0;
}
buf = malloc (4096);
if (!buf) {
perror ("malloc failed");
return 0;
}
fread (buf, 4096, 1, stdin);
if (!feof (stdin)) {
printf ("fread returned not eof\n");
return 0;
}
unpack_leaf (buf, fd);
free (buf);
close (fd);
return 0;
}
static int do_pack (char * file, int block)
{
int fd;
struct buffer_head * bh;
char * buf;
int len;
fprintf (stderr, "dumping block %d of the \"%s\"\n", block, file);
fd = open (file, O_RDONLY);
if (fd == -1) {
perror ("open failed");
return 0;
}
bh = bread (fd, block, 4096);
if (!bh) {
fprintf (stderr, "bread failed\n");
return 0;
}
if (who_is_this (bh->b_data, bh->b_size) != THE_LEAF) {
fprintf (stderr, "block %d is not a leaf\n", block);
return 0;
}
len = pack_leaf (bh, buf);
fwrite (buf, len, 1, stdout);
free (buf);
close (fd);
return 0;
}
int main (int argc, char ** argv)
{
if (argc == 3 && !strcmp (argv[1], "unpack"))
return do_unpack (argv[2]);
if (argc == 4 && !strcmp (argv[1], "pack"))
return do_pack (argv[2], atoi (argv[3]));
fprintf (stderr, "Usage: \n\t%s pack filename block\nor\n"
"\t%s unpack filename\n", argv[0], argv[0]);
return 0;
}
#endif
+558
View File
@@ -0,0 +1,558 @@
/*
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
#include "debugreiserfs.h"
#include <sys/resource.h>
#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]);
/* 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;
int unpacked, data_blocks_unpacked;
int verbose = 0;
static void unpack_offset (struct packed_item * pi, struct item_head * ih)
{
if (pi->mask & OFFSET_BITS_64) {
__u64 v64;
if (ih_key_format (ih) != KEY_FORMAT_2)
die ("unpack_offset: key format is not set or wrong");
fread64 (&v64);
set_offset (KEY_FORMAT_2, &ih->ih_key, v64);
return;
}
if (pi->mask & OFFSET_BITS_32) {
__u32 v32;
fread32 (&v32);
set_offset (ih_key_format (ih), &ih->ih_key, v32);
return;
}
// offset is 0
return;
}
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);
}
/* direntry item comes in the following format:
entry count - 16 bits
for each entry
mask - 8 bits
entry length - 16 bits
entry itself
deh_objectid - 32 bits
maybe deh_dir_id (32 bits)
maybe gencounter (16)
maybe deh_state (16)
*/
static void unpack_direntry (struct packed_item * pi, struct buffer_head * bh,
struct item_head * ih, hashf_t hash_func)
{
__u16 entry_count, namelen, gen_counter, entry_len;
__u8 mask;
int i;
struct reiserfs_de_head * deh;
int location;
char * item;
if (!hash_func)
die ("unpack_direntry: hash function is not set");
fread16 (&entry_count);
set_entry_count (ih, entry_count);
item = bh->b_data + ih_location (ih);
deh = (struct reiserfs_de_head *)item;
location = pi->item_len;
for (i = 0; i < entry_count; i ++, deh ++) {
fread8 (&mask);
fread16 (&entry_len);
location -= entry_len;
deh->deh_location = location;
fread (item + location, entry_len, 1, stdin);
/* find name length */
if (*(item + location + entry_len - 1))
namelen = entry_len;
else
namelen = strlen (item + location);
fread32 (&deh->deh_objectid);
if (mask & HAS_DIR_ID)
fread32 (&deh->deh_dir_id);
else
deh->deh_dir_id = ih->ih_key.k_objectid;
if (*(item + location) == '.' && namelen == 1)
/* old or new "." */
deh->deh_offset = DOT_OFFSET;
else if (*(item + location) == '.' && *(item + location + 1) == '.' && namelen == 2)
/* old or new ".." */
deh->deh_offset = DOT_DOT_OFFSET;
else
deh->deh_offset = GET_HASH_VALUE (hash_func (item + location,
namelen));
if (mask & HAS_GEN_COUNTER) {
fread16 (&gen_counter);
deh->deh_offset |= gen_counter;
}
if (mask & HAS_STATE)
fread16 (&deh->deh_state);
else
deh->deh_state = (1 << DEH_Visible);
}
return;
}
/* struct packed_item is already unpacked */
static void unpack_stat_data (struct packed_item * pi, struct buffer_head * bh,
struct item_head * ih)
{
set_entry_count (ih, 0xffff);
if (ih_key_format (ih) == KEY_FORMAT_1) {
/* stat data comes in the following format:
if this is old stat data:
mode - 16 bits
nlink - 16 bits
size - 32 bits
blocks/rdev - 32 bits
maybe first_direct byte 32 bits
*/
struct stat_data_v1 * sd;
sd = (struct stat_data_v1 *)B_I_PITEM (bh, ih);
memset (sd, 0, sizeof (sd));
fread16 (&sd->sd_mode);
fread16 (&sd->sd_nlink);
fread32 (&sd->sd_size);
fread32 (&sd->u.sd_blocks);
if (pi->mask & WITH_SD_FIRST_DIRECT_BYTE) {
fread32 (&sd->sd_first_direct_byte);
} else {
sd->sd_first_direct_byte = 0xffffffff;
}
} else {
/* for new stat data
mode - 16 bits
nlink in either 16 or 32 bits
size in either 32 or 64 bits
blocks - 32 bits
*/
struct stat_data * sd;
sd = (struct stat_data *)B_I_PITEM (bh, ih);
memset (sd, 0, sizeof (sd));
fread16 (&sd->sd_mode);
if (pi->mask & NLINK_BITS_32) {
fread32 (&sd->sd_nlink);
} else {
__u16 nlink16;
fread16 (&nlink16);
sd->sd_nlink = nlink16;
}
if (pi->mask & SIZE_BITS_64) {
fread64 (&sd->sd_size);
} else {
__u32 size32;
fread32 (&size32);
sd->sd_size = size32;
}
fread32 (&sd->sd_blocks);
}
return;
}
/* indirect item comes either in packed form or as is. ih_free_space
can go first */
static void unpack_indirect (struct packed_item * pi, struct buffer_head * bh,
struct item_head * ih)
{
__u32 * ind_item, * end;
int i;
__u16 v16;
v16 = 0;
if (pi->mask & ENTRY_COUNT)
fread16 (&v16);
set_entry_count (ih, v16);
ind_item = (__u32 *)B_I_PITEM (bh, ih);
if (pi->mask & WHOLE_INDIRECT) {
fread (ind_item, pi->item_len, 1, stdin);
return;
}
end = ind_item + I_UNFM_NUM (ih);
while (ind_item < end) {
fread32 (ind_item);
fread16 (&v16);
for (i = 1; i < v16; i ++) {
if (ind_item[0])
ind_item [i] = ind_item[0] + i;
else
ind_item [i] = 0;
}
ind_item += i;
}
return;
}
// FIXME: we have no way to preserve symlinks
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);
return;
}
static void unpack_leaf (int dev, hashf_t hash_func)
{
static int unpacked_leaves = 0;
struct buffer_head * bh;
struct packed_item pi;
struct item_head * ih;
int i;
__u16 v16;
__u32 v32;
/* block number */
fread32 (&v32);
/* item number */
fread16 (&v16);
if (verbose)
fprintf (stderr, "leaf %d\n", v32);
bh = getblk (dev, v32, 4096);
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);
ih = B_N_PITEM_HEAD (bh, 0);
for (i = 0; i < v16; i ++, ih ++) {
#if 0
fread32 (&v32);
if (v32 != ITEM_START_MAGIC)
die ("unpack_leaf: no start item magic found: block %lu, item %i",
bh->b_blocknr, i);
#endif
fread (&pi, sizeof (struct packed_item), 1, stdin);
/* dir_id - if it is there */
if (pi.mask & DIR_ID) {
fread32 (&v32);
ih->ih_key.k_dir_id = 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;
}
/* object_id - if it is there */
if (pi.mask & OBJECT_ID) {
fread32 (&v32);
ih->ih_key.k_objectid = v32;
} else {
if (!i)
die ("unpack_leaf: object_id is not set");
ih->ih_key.k_objectid = (ih - 1)->ih_key.k_objectid;
}
// we need to set item format before offset unpacking
set_key_format (ih, (pi.mask & NEW_FORMAT) ? KEY_FORMAT_2 : KEY_FORMAT_1);
// offset
unpack_offset (&pi, ih);
/* type */
unpack_type (&pi, ih);
/* 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);
// item itself
if (is_direct_ih (ih)) {
unpack_direct (&pi, bh, ih);
} else if (is_indirect_ih (ih)) {
unpack_indirect (&pi, bh, ih);
} else if (is_direntry_ih (ih)) {
unpack_direntry (&pi, bh, ih, 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)));
#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);
#endif
}
fread16 (&v16);
if (v16 != LEAF_END_MAGIC)
die ("unpack_leaf: wrong end signature found - %x, block %lu",
v16, bh->b_blocknr);
mark_buffer_uptodate (bh, 1);
mark_buffer_dirty (bh);
bwrite (bh);
/*
if (!not_data_block (bh->b_blocknr))
data_blocks_unpacked ++;
*/
brelse (bh);
if (what_unpacked)
reiserfs_bitmap_set_bit (what_unpacked, bh->b_blocknr);
unpacked ++;
if (!(++ unpacked_leaves % 10))
fprintf (stderr, "#");
}
static void unpack_full_block (int dev, int blocksize)
{
static int full_blocks_unpacked = 0;
__u32 block;
struct buffer_head * bh;
fread32 (&block);
if (verbose)
fprintf (stderr, "full #%d\n", block);
bh = getblk (dev, block, blocksize);
if (!bh)
die ("unpack_full_block: getblk failed");
fread (bh->b_data, bh->b_size, 1, stdin);
if (who_is_this (bh->b_data, bh->b_size) == THE_SUPER && !what_unpacked) {
unsigned long blocks;
blocks = rs_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);
}
mark_buffer_uptodate (bh, 1);
mark_buffer_dirty (bh);
bwrite (bh);
/*
if (!not_data_block (bh->b_blocknr))
data_blocks_unpacked ++;
*/
brelse (bh);
if (what_unpacked)
reiserfs_bitmap_set_bit (what_unpacked, block);
unpacked ++;
if (!(++ full_blocks_unpacked % 50))
fprintf (stderr, ".");
}
/* just skip bitmaps of unformatted nodes */
static void unpack_unformatted_bitmap (int dev, int blocksize)
{
__u16 bmap_num;
__u32 block_count;
int i;
char * buf;
fread16 (&bmap_num);
fread32 (&block_count);
buf = malloc (blocksize);
if (!buf)
reiserfs_panic ("unpack_unformatted_bitmap: malloc failed: %m");
for (i = 0; i < bmap_num; i ++) {
if (fread (buf, blocksize, 1, stdin) != 1)
reiserfs_panic ("unpack_unformatted_bitmap: "
"could not read bitmap #%d: %m", i);
}
free (buf);
}
// read packed reiserfs partition metadata from stdin
void unpack_partition (int dev)
{
__u32 magic32;
__u16 magic16;
__u16 blocksize;
fread32 (&magic32);
if (magic32 != REISERFS_SUPER_MAGIC)
die ("unpack_partition: reiserfs magic number not found");
fread16 (&blocksize);
if (verbose)
fprintf (stderr, "Blocksize %d\n", blocksize);
while (!feof (stdin)) {
char c[2];
fread (c, 1, 1, stdin);
switch (c[0]) {
case '.':
if (verbose)
fprintf (stderr, "\".\" skipped\n");
continue;
case '1':
fread (c, 1, 1, stdin); /* that was 100%, read in first 0 */
case '2':
case '4':
case '6':
case '8':
fread (c, 1, 1, stdin);
case '0':
fread (c + 1, 1, 1, stdin); /* read % */
if (c[0] != '0' || c[1] != '%')
die ("0%% expected\n");
if (verbose)
fprintf (stderr, "0%% skipped\n");
continue;
}
fread (c + 1, 1, 1, stdin);
magic16 = *(__u16 *)c;
/*fread16 (&magic16);*/
switch (magic16 & 0xff) {
case LEAF_START_MAGIC:
unpack_leaf (dev, code2func (magic16 >> 8));
break;
case FULL_BLOCK_START_MAGIC:
unpack_full_block (dev, blocksize);
break;
case UNFORMATTED_BITMAP_START_MAGIC:
fprintf (stderr, "\nBitmap of unformatted - ignored\n");
unpack_unformatted_bitmap (dev, blocksize);
break;
case END_MAGIC:
break;
default:
die ("unpack_partition: bad magic found - %x", magic16 & 0xff);
}
}
fprintf (stderr, "Unpacked %d (%d) blocks\n", unpacked, what_unpacked ? reiserfs_bitmap_ones (what_unpacked) : 0);
/* fclose (block_list);*/
}
int main (int argc, char ** argv)
{
int fd;
int c;
char * filename = ".bitmap";
struct rlimit lim = {0xffffffff, 0xffffffff};
print_banner ("unpack");
/* with this 2.4.0-test9's file_write does not send SIGXFSZ */
if (setrlimit (RLIMIT_FSIZE, &lim)) {
fprintf (stderr, "sertlimit failed: %m\n");
}
while ((c = getopt (argc, argv, "vb:")) != EOF) {
switch (c) {
case 'v':
verbose = 1;
case 'b':
asprintf (&filename, "%s", optarg);
break;
}
}
if (optind != argc - 1)
/* only one non-option argument is permitted */
print_usage_and_exit();
if (is_mounted (argv[optind]))
reiserfs_panic ("%s seems mounted, umount it first\n", argv[optind]);
fd = open (argv[optind], O_RDWR | O_LARGEFILE);
if (fd == -1) {
perror ("open failed");
return 0;
}
unpack_partition (fd);
if (what_unpacked && filename)
reiserfs_bitmap_save (filename, what_unpacked);
close (fd);
return 0;
}
+11
View File
@@ -0,0 +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
man_MANS = reiserfsck.8
EXTRA_DIST = $(man_MANS)
LDADD = ../lib/libmisc.a ../reiserfscore/libcore.a
INCLUDES = -I../include -I.
+358
View File
@@ -0,0 +1,358 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 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@
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
man_MANS = reiserfsck.8
EXTRA_DIST = $(man_MANS)
LDADD = ../lib/libmisc.a ../reiserfscore/libcore.a
INCLUDES = -I../include -I.
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
PROGRAMS = $(sbin_PROGRAMS)
DEFS = @DEFS@ -I. -I$(srcdir)
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_LDADD = $(LDADD)
reiserfsck_DEPENDENCIES = ../lib/libmisc.a ../reiserfscore/libcore.a
reiserfsck_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 = $(reiserfsck_SOURCES)
OBJECTS = $(reiserfsck_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 fsck/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:
reiserfsck: $(reiserfsck_OBJECTS) $(reiserfsck_DEPENDENCIES)
@rm -f reiserfsck
$(LINK) $(reiserfsck_LDFLAGS) $(reiserfsck_OBJECTS) $(reiserfsck_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 = fsck
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
check.o: check.c fsck.h ../include/io.h ../include/misc.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
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
lost+found.o: lost+found.c fsck.h ../include/io.h ../include/misc.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
pass0.o: pass0.c fsck.h ../include/io.h ../include/misc.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
pass2.o: pass2.c fsck.h ../include/io.h ../include/misc.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
ubitmap.o: ubitmap.c fsck.h ../include/io.h ../include/misc.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
uobjectid.o: uobjectid.c fsck.h ../include/io.h ../include/misc.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
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:
+329
View File
@@ -0,0 +1,329 @@
/*
* Copyright 1996, 1997 Hans Reiser
*/
#include "fsck.h"
/* this goes through buffers checking delimiting keys
*/
struct buffer_head * g_left = 0;
struct buffer_head * g_right = 0;
struct key * g_dkey = 0;
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]))
die ("check_directory_item: entries are not sorted properly");
}
static void check_items (struct buffer_head * bh)
{
int i;
struct item_head * ih;
for (i = 0; i < B_NR_ITEMS (bh); i++)
{
ih = B_N_PITEM_HEAD (bh, i);
if (is_direntry_ih (ih))
check_directory_item (ih, bh);
}
}
static void compare_neighboring_leaves_in_pass1 (void)
{
struct key * left = B_N_PKEY (g_left, B_NR_ITEMS (g_left) - 1);
if (comp_keys (left, B_N_PKEY (g_right, 0)) != -1/*SECOND_GREATER*/)
die ("compare_neighboring_leaves_in_pass1: left key is greater, that the right one");
if (/*comp_keys (B_PRIGHT_DELIM_KEY (g_left), g_dkey) == FIRST_GREATER ||*/
comp_keys (g_dkey, B_N_PKEY (g_right, 0))) {
reiserfs_panic (0, "compare_neighboring_leaves_in_pass1: dkey %k, first key in right %k",
g_dkey, B_N_PKEY (g_right, 0));
}
check_items (g_left);
/*&&&&&&&&&&&&&&&&&&&&&&&&&&
for (i = 0, ih = B_N_PITEM_HEAD (g_left, i); i < B_NR_ITEMS (g_left); i ++, ih ++)
if (is_item_accessed (ih) == YES)
die ("compare_neighboring_leaves_in_pass1: item marked as accessed in g_left");
for (i = 0, ih = B_N_PITEM_HEAD (g_right, i); i < B_NR_ITEMS (g_right); i ++, ih ++)
if (is_item_accessed (ih) == YES)
die ("compare_neighboring_leaves_in_pass1: item marked as accessed in g_right");
&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
}
static void is_there_unaccessed_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 (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_item_reachable (ih)) {
die ("is_there_unaccessed_items: block %lu - unaccessed item found",
bh->b_blocknr);
}
}
}
static void compare_neighboring_leaves_after_all (void)
{
struct item_head * left = B_N_PITEM_HEAD(g_left, B_NR_ITEMS (g_left) - 1);
struct item_head * right = B_N_PITEM_HEAD(g_right, 0);
/* struct key * left = B_N_PKEY (g_left, B_NR_ITEMS (g_left) - 1);
struct key * right = B_N_PKEY (g_right, 0);*/
/*
if (comp_keys (&left->ih_key, B_PRIGHT_DELIM_KEY (g_left)) != SECOND_GREATER)
die ("compare_neighboring_leaves_after_all: invalid right delimiting key");
*/
if (comp_keys (&left->ih_key, B_N_PKEY (g_right, 0)) != -1/*SECOND_GREATER*/)
die ("compare_neighboring_leaves_after_all: left key is greater than the right one");
if (//comp_le_keys (B_PRIGHT_DELIM_KEY (g_left), g_dkey) != KEYS_IDENTICAL ||
comp_keys (g_dkey, B_N_PKEY (g_right, 0))) {
reiserfs_panic (0, "compare_neighboring_leaves_after all: invalid delimiting keys from left to right (%k %k)",
g_dkey, B_N_PKEY (g_right, 0));
}
if (!not_of_one_file (&left->ih_key, &right->ih_key)) {
// items of one file: check offset correctness
if (is_direct_ih (left) || is_indirect_ih (left))
//if (get_offset(&right->ih_key) != get_offset(&left->ih_key) + get_bytes_number (g_left, left /*B_NR_ITEMS (g_left) - 1*/, 0, CHECK_FREE_BYTES))
if (get_offset(&right->ih_key) != get_offset(&left->ih_key) + get_bytes_number (left, g_left->b_size))
die ("compare_neighboring_leaves_after all: hole between items or items are overlapped");
}
is_there_unaccessed_items (g_left);
}
typedef void (check_function_t)(void);
/* only directory item can be fatally bad */
static int is_leaf_bad_xx (struct buffer_head * bh)
{
int i;
struct item_head * ih;
if (!is_leaf_node (bh))
return 0;
for (i = 0, ih = B_N_PITEM_HEAD (bh, 0); i < B_NR_ITEMS (bh); i ++, ih ++)
if (is_bad_item (bh, ih, B_I_PITEM (bh, ih))) {
return 1;
}
return 0;
}
static void reiserfsck_check_tree (int dev, int block, int size, check_function_t comp_func)
{
struct buffer_head * bh;
int what_node;
bh = bread (dev, block, size);
if (bh == 0)
reiserfs_panic("reiserfsck_check_tree: unable to read %lu block on device 0x%x\n",
block, dev);
if (!B_IS_IN_TREE (bh)) {
reiserfs_panic (0, "reiserfsck_check_tree: buffer (%b %z) not in tree", bh, bh);
}
what_node = who_is_this (bh->b_data, bh->b_size);
if (what_node != THE_LEAF && what_node != THE_INTERNAL)
die ("Not formatted node");
if (!is_block_used (bh->b_blocknr))
die ("Not marked as used");
if (is_leaf_node (bh) && is_leaf_bad_xx (bh))
die ("Bad leaf");
if (is_internal_node(bh) && is_internal_bad (bh))
die ("bad internal");
if (is_internal_node (bh)) {
int i;
struct disk_child * dc;
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);
g_dkey = B_N_PDELIM_KEY (bh, i);
}
} else if (is_leaf_node (bh)) {
g_right = bh;
if (g_left != 0 && g_dkey != 0) {
comp_func ();
brelse (g_left);
}
g_left = g_right;
return;
} else {
reiserfs_panic ("reiserfsck_check_tree: block %lu has bad block type (%b)",
bh->b_blocknr, bh);
}
brelse (bh);
}
static void reiserfsck_check_cached_tree (int dev, int block, int size)
{
struct buffer_head * bh;
int what_node;
bh = find_buffer(dev, block, size);
if (bh == 0)
return;
if (!buffer_uptodate (bh)) {
die ("reiserfsck_check_cached_tree: found notuptodate buffer");
}
bh->b_count ++;
if (!B_IS_IN_TREE (bh)) {
die ("reiserfsck_check_cached_tree: buffer (%b %z) not in tree", bh, bh);
}
what_node = who_is_this (bh->b_data, bh->b_size);
if ((what_node != THE_LEAF && what_node != THE_INTERNAL) ||
!is_block_used (bh->b_blocknr) ||
(is_leaf_node (bh) && is_leaf_bad (bh)) ||
(is_internal_node(bh) && is_internal_bad (bh)))
die ("reiserfsck_check_cached_tree: bad node in the tree");
if (is_internal_node (bh)) {
int i;
struct disk_child * dc;
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);
g_dkey = B_N_PDELIM_KEY (bh, i);
}
} else if (is_leaf_node (bh)) {
brelse (bh);
return;
} else {
reiserfs_panic ("reiserfsck_check_cached_tree: block %lu has bad block type (%b)",
bh->b_blocknr, bh);
}
brelse (bh);
}
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);
brelse (g_right);
}
void reiserfsck_check_pass1 ()
{
/* if (opt_check == 1)*/
reiserfsck_tree_check (compare_neighboring_leaves_in_pass1);
}
void check_cached_tree ()
{
reiserfsck_check_cached_tree (fs->s_dev, SB_ROOT_BLOCK (fs), fs->s_blocksize);
}
void reiserfsck_check_after_all ()
{
reiserfsck_tree_check (compare_neighboring_leaves_after_all);
}
#if 0
static int is_bad_sd (struct item_head * ih, char * item)
{
struct stat_data * sd = (struct stat_data *)item;
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);
}
return 0;
}
#endif
#include <sys/ioctl.h>
#include <sys/mount.h>
int blocks_on_device (int dev, int blocksize)
{
int size;
if (ioctl (dev, BLKGETSIZE, &size) >= 0) {
return size / (blocksize / 512);
}
if (ioctl (dev, BLKGETSIZE, &size) >= 0) {
return size / (blocksize / 512);
} else {
struct stat stat_buf;
memset(&stat_buf, '\0', sizeof(struct stat));
if(fstat(dev, &stat_buf) >= 0) {
return stat_buf.st_size / (blocksize / 512);
} else {
die ("can not calculate device size\n");
}
}
return 0;
}
int is_internal_bad (struct buffer_head * bh)
{
struct key * key;
int i;
if (!is_internal_node(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
)
return 1;
}
return 0;
}
+915
View File
@@ -0,0 +1,915 @@
/*
* Copyright 1999 Hans Reiser
*/
#include "fsck.h"
//
//
// check S+ tree of the file system
//
// check_fs_tree stops and recommends to run fsck --rebuild-tree when:
// 1. read fails
// 2. node of wrong level found in the tree
// 3. something in the tree points to wrong block number
// out of filesystem boundary is pointed by tree
// to block marked as free in bitmap
// the same block is pointed from more than one place
// not data blocks (journal area, super block, bitmaps)
// 4. bad formatted node found
// 5. delimiting keys are incorrect
//
/* mark every block we see in the tree in control bitmap, so, when to make
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 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)
{
return !reiserfs_bitmap_test_bit (fsck_disk_bitmap (fs), block);
}
/* 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);
}
/* have we seen this block somewhere in the tree before? */
static int did_we_meet_it (unsigned long block)
{
return reiserfs_bitmap_test_bit (control_bitmap, block);
}
static void init_control_bitmap (reiserfs_filsys_t fs)
{
int i;
control_bitmap = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
if (!control_bitmap)
die ("init_control_bitmap: could not create control bitmap");
/* skipped and super block */
for (i = 0; i <= SB_BUFFER_WITH_SB (fs)->b_blocknr; i ++)
we_met_it (i);
/* bitmaps */
for (i = 0; i < SB_BMAP_NR (fs); i ++)
we_met_it (SB_AP_BITMAP (fs)[i]->b_blocknr);
for (i = 0; i < rs_journal_size (fs->s_rs) + 1; i ++)
we_met_it (i + SB_JOURNAL_BLOCK (fs));
}
#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;
}
/* 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)
{
int diff;
if (tree_scanning_failed) {
fsck_progress ("Could not scan whole tree. "
"--rebuild-tree is required\n");
return;
}
fsck_progress ("Comparing bitmaps..");
/* check free block counter */
if (SB_FREE_BLOCKS (fs) != 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
}
diff = reiserfs_bitmap_compare (fsck_disk_bitmap (fs), 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_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)
{
if (block >= SB_BLOCK_COUNT (s)) {
/*reiserfs_warning ("block out of filesystem boundary found\n");*/
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;
}
return 0;
}
static int got_already (struct super_block * s, unsigned long block)
{
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);
}
return 0;
}
/* 1 if some of fields in the block head of bh look bad */
static int bad_block_head (struct buffer_head * bh)
{
struct block_head * blkh;
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",
bh->b_blocknr, bh);
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);
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)
{
unsigned long objectid;
int pos;
/*
if (opt_fsck_mode == FSCK_FAST_REBUILD)
return 0;
*/
objectid = le32_to_cpu (ih->ih_key.k_objectid);
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);
}
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);
return 0;
}
mark_objectid_really_used (proper_id_map (fs), objectid);
return 0;
}
/* it looks like we can check item length only */
static int bad_direct_item (struct buffer_head * bh, struct item_head * ih)
{
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,
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);
return 1;
}
for (i = 0; i < I_UNFM_NUM (ih); i ++) {
__u32 unfm_ptr;
unfm_ptr = le32_to_cpu (ind [i]);
if (!unfm_ptr)
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);
}
fsck_log ("\n");
continue;
}
if (got_already (fs, unfm_ptr)) {
fsck_log ("bad_indirect_item: 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);
}
fsck_log ("\n");
continue;
}
}
/* 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);
return 0;
}
/* FIXME: this was is_bad_directory from pass0.c */
static int bad_directory_item (struct buffer_head * bh, struct item_head * ih)
{
int i;
char * name;
int namelen;
struct reiserfs_de_head * deh = B_I_DEH (bh, 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 */
__u16 state;
/* make sure item looks like a directory */
if (ih_item_len (ih) / (DEH_SIZE + min_entry_size) < ih_entry_count (ih))
/* entry count can not be that big */
return 1;
if (deh[ih_entry_count (ih) - 1].deh_location != DEH_SIZE * ih_entry_count (ih))
/* last entry should start right after array of dir entry headers */
return 1;
/* check name hashing */
for (i = 0; i < ih_entry_count (ih); i ++, deh ++) {
namelen = name_length (ih, deh, i);
name = name_in_entry (deh, i);
if (!is_properly_hashed (fs, name, namelen, deh_offset (deh))) {
return 1;
}
}
deh = B_I_DEH (bh, ih);
state = 0;
set_bit (DEH_Visible, &state);
/* ok, items looks like a directory */
for (i = 0; i < ih_entry_count (ih); i ++, deh ++) {
if (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);
mark_buffer_dirty (bh);
fsck_log (" - fixed");
}
fsck_log ("\n");
}
}
return 0;
}
static int bad_item (struct super_block * s, struct buffer_head * bh, int i)
{
struct item_head * ih;
ih = B_N_PITEM_HEAD (bh, i);
if (is_stat_data_ih (ih))
return bad_stat_data (bh, ih);
if (is_direct_ih (ih))
return bad_direct_item (bh, ih);
if (is_indirect_ih(ih))
return bad_indirect_item (s, bh, ih);
return bad_directory_item (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)
{
struct item_head * ih;
ih = B_N_PITEM_HEAD (bh, i);
if (comp_keys (&((ih - 1)->ih_key), &ih->ih_key) != -1)
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)
return 1;
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))
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))))
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);
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)
{
int i;
if (bad_block_head (bh))
return 1;
for (i = 0; i < B_NR_ITEMS (bh); i ++) {
if (bad_item (s, 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);
}
}
return 0;
}
/* 1 if bh does not look like internal node */
static int bad_internal (struct super_block * s, struct buffer_head * bh)
{
int 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)
return 1;
if (bad_block_number(s, child_block_number(bh,i))){
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)
{
return SB_TREE_HEIGHT (s) - 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,
int h)
{
struct buffer_head ** pbh = &path[h];
if (B_LEVEL (*pbh) != h_to_level (s, 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));
return 1;
}
if (bad_block_number (s, (*pbh)->b_blocknr)) {
return 1;
}
if (got_already (s, (*pbh)->b_blocknr))
return 1;
if (is_leaf_node (*pbh))
return bad_leaf (s, *pbh);
return bad_internal (s, *pbh);
}
/* internal node bh must point to block */
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)
return i;
}
die ("get_pos: position for block %lu not found", block);
return 0;
}
/* path[h] - leaf node */
static struct key * lkey (struct buffer_head ** path, int h)
{
int pos;
while (h > 0) {
pos = get_pos (path[h - 1], path[h]->b_blocknr);
if (pos)
return B_N_PDELIM_KEY(path[h - 1], pos - 1);
h --;
}
return 0;
}
/* path[h] - leaf node */
static struct key * rkey (struct buffer_head ** path, int h)
{
int pos;
while (h > 0) {
pos = get_pos (path[h - 1], path[h]->b_blocknr);
if (pos != B_NR_ITEMS (path[h - 1]))
return B_N_PDELIM_KEY (path[h - 1], pos);
h --;
}
return 0;
}
/* are all delimiting keys correct */
static int bad_path (struct super_block * s, struct buffer_head ** path, int h1)
{
int h = 0;
struct key * dk;
while (path[h])
h ++;
h--;
// path[h] is leaf
if (h != h1)
die ("bad_path: wrong path");
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
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
return 1;
return 0;
}
/* pass the S+ tree of filesystem */
void check_fs_tree (struct super_block * s)
{
init_control_bitmap (s);
proper_id_map (s) = init_id_map ();
fsck_progress ("Checking S+tree..");
pass_through_tree (s, 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);
free_id_map (&proper_id_map (s));
}
#if 0
void remove_internal_pointer(struct super_block * s, struct buffer_head ** path)
{
int h = 0;
int pos, items;
__u32 block;
while (path[h])
h ++;
h--;
block = path[h]->b_blocknr;
printf("\nremove pointer to (%d) block", block);
brelse(path[h]);
path[h] = 0;
h--;
while (h>=0)
{
if (B_NR_ITEMS(path[h]) <= 1)
{
block = path[h]->b_blocknr;
brelse(path[h]);
path[h] = 0;
mark_block_free(block);
/*unmark_block_formatted(block);*/
used_blocks++;
h --;
continue;
}
pos = get_pos (path[h], block);
if (pos)
{
memmove (B_N_CHILD(path[h],pos), B_N_CHILD(path[h],pos+1),
s->s_blocksize - BLKH_SIZE - B_NR_ITEMS(path[h])*KEY_SIZE - DC_SIZE*(pos+1));
memmove(B_N_PDELIM_KEY(path[h],pos-1), B_N_PDELIM_KEY(path[h],pos),
s->s_blocksize - BLKH_SIZE - (pos)*KEY_SIZE);
}else{
__u32 move_block = path[h]->b_blocknr;
int move_to_pos;
int height = h;
while(--height >= 0)
{
move_to_pos = get_pos (path[height], move_block);
if (move_to_pos == 0){
move_block = path[height]->b_blocknr;
continue;
}
*B_N_PDELIM_KEY(path[height], move_to_pos-1) = *B_N_PDELIM_KEY(path[h], 0);
break;
}
memmove (B_N_CHILD(path[h], 0), B_N_CHILD(path[h], 1),
s->s_blocksize - BLKH_SIZE - B_NR_ITEMS(path[h])*KEY_SIZE - DC_SIZE);
memmove(B_N_PDELIM_KEY(path[h], 0), B_N_PDELIM_KEY(path[h], 1),
s->s_blocksize - BLKH_SIZE - KEY_SIZE);
}
set_node_item_number(path[h], node_item_number(path[h]) - 1);
mark_buffer_dirty(path[h], 1);
break;
}
if (h == -1)
{
SB_DISK_SUPER_BLOCK(s)->s_root_block = ~0;
SB_DISK_SUPER_BLOCK(s)->s_tree_height = ~0;
mark_buffer_dirty(SB_BUFFER_WITH_SB(s), 1);
}
}
void handle_buffer(struct super_block * s, struct buffer_head * bh)
{
int i, j;
struct item_head * ih;
if (is_leaf_node (bh))
{
for (i = 0, ih = B_N_PITEM_HEAD (bh, 0); i < B_NR_ITEMS (bh); i ++, ih ++)
{
if (is_indirect_ih(ih))
for (j = 0; j < I_UNFM_NUM (ih); j ++)
if (B_I_POS_UNFM_POINTER(bh,ih,j)){
/*mark_block_unformatted(le32_to_cpu(B_I_POS_UNFM_POINTER(bh,ih,j)));*/
mark_block_used(le32_to_cpu(B_I_POS_UNFM_POINTER(bh,ih,j)));
used_blocks++;
}
if (is_stat_data_ih (ih)) {
/*add_event (STAT_DATA_ITEMS);*/
if (ih_key_format(ih) == KEY_FORMAT_1)
((struct stat_data_v1 *)B_I_PITEM(bh,ih))->sd_nlink = 0;
else
((struct stat_data *)B_I_PITEM(bh,ih))->sd_nlink = 0;
mark_buffer_dirty(bh, 1);
}
}
}
mark_block_used(bh->b_blocknr);
// we_met_it(s, bh->b_blocknr);
used_blocks++;
}
/* bh must be formatted node. blk_level must be tree_height - h + 1 */
static int handle_node (struct super_block * s, struct buffer_head ** path, int h)
{
if (bad_node(s, path, h)){
remove_internal_pointer(s, path);
return 1;
}
handle_buffer(s, path[h]);
return 0;
}
/* are all delimiting keys correct */
static int handle_path (struct super_block * s, struct buffer_head ** path, int h)
{
if (bad_path(s, path, h)){
remove_internal_pointer(s, path);
return 1;
}
return 0;
}
//return 1 to run rebuild tree from scratch
void check_internal_structure(struct super_block * s)
{
/* control bitmap is used to keep all blocks we should not put into tree again */
/* used bitmap is used to keep all inserted blocks. The same as control bitmap plus unfm blocks */
// init_control_bitmap(s);
printf ("Checking S+tree..");
pass_through_tree (s, handle_node, handle_path);
// compare_bitmaps(s);
printf ("ok\n");
}
#endif
int check_sb (struct super_block * s)
{
int format_sb = 0;
int problem = 0;
struct reiserfs_super_block * rs;
__u32 block_count;
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)))
{
// 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)))
{
// >3.5.9(10) and <=3.5.21
printf("\t>=3.5.9 format SB found\n");
format_sb = 2;
goto good_format;
}
// in 2 block
if (is_reiser2fs_magic_string (rs) &&
SB_JOURNAL_BLOCK(s) == get_journal_old_start_must (rs))
{
// <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))
{
// <3.5.9(10)
printf("\t< 3.5.9(10) format SB found\n");
format_sb = 4;
goto good_format;
}
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);
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));
problem++;
}
block_count = count_blocks ("", s->s_blocksize, s->s_dev);
if (SB_BLOCK_COUNT(s) > block_count){
fsck_log ("check SB: specified block number (%d) is too high\n", SB_BLOCK_COUNT(s));
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));
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));
problem++;
}
if (SB_REISERFS_STATE(s) != REISERFS_VALID_FS){
fsck_log ("check SB: wrong (%d) state\n", SB_REISERFS_STATE(s));
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));
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);
problem++;
}
}
else{
fsck_log ("check SB: wrong SB version (%d)\n", SB_VERSION(s));
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));
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));
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));
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);
problem++;
}
if (!problem) {
fsck_progress ("\t No problem found\n");
} else if (fsck_log_file (fs) != stderr)
fsck_progress ("Look for super block corruptions in the log file\n");
return format_sb;
}
+425
View File
@@ -0,0 +1,425 @@
/*
* Copyright 1996-2001 Hans Reiser
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <asm/types.h>
#include <sys/vfs.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <asm/types.h>
#include <assert.h>
#include "io.h"
#include "misc.h"
#include "reiserfs_lib.h"
/* main.c */
extern reiserfs_filsys_t fs;
extern reiserfs_bitmap_t uninsertable_leaf_bitmap;
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
/* temporary */
#define FSCK_ZERO_FILES 4
#define DO_TEST 5
/*
#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;
/* 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);
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 are_there_allocable_blocks (int amout_needed);
unsigned long alloc_block (void);
void make_allocable (unsigned long block);
void register_uninsertable (unsigned long block);
unsigned long how_many_uninsertables_were_there (void);
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);
#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;
#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 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);
/* pass2.c */
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);
void take_bad_blocks_put_into_tree (void);
void rewrite_object (struct item_head * ih, int do_remap);
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);
void relocate_dir (struct item_head * ih, int change_ih);
__u32 objectid_for_relocation (struct key * key);
/* file.c */
struct si {
struct item_head si_ih;
char * si_dnm_data;
struct si * si_next;
__u32 si_blocknr;
// changed by XB;
struct si * last_known;
};
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);
/* 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);
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 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);
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);
/* pass4.c */
void get_next_key (struct path * path, int i, struct key * key);
int pass_4_check_unaccessed_items (void);
/* check.c */
int is_leaf_bad (struct buffer_head * bh);
int is_internal_bad (struct buffer_head * bh);
int is_bad_item (struct buffer_head * bh, struct item_head *, char *);
/*int check_file_system (void);*/
void reiserfsck_check_pass1 (void);
void reiserfsck_check_after_all (void);
/*char * bad_name (char * name, int namelen);*/
/* to test result of direcotry item recovering on pass 0 */
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);
/* 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 (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,
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);
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);
//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,
unsigned long * pblocknrs,
unsigned long start_from,
int amount_needed);
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_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);
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);
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);
/* segments.c */
struct overwritten_unfm_segment {
int ous_begin;
int ous_end;
struct overwritten_unfm_segment * ous_next;
};
struct overwritten_unfm * look_for_overwritten_unfm (__u32);
struct overwritten_unfm_segment * find_overwritten_unfm (unsigned long unfm, int length, struct overwritten_unfm_segment * segment_to_init);
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);
struct id_map {
__u32 * m_begin; /* pointer to map area */
unsigned long 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 */
unsigned long objectids_marked; /* number of objectids marked used
in a 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 */
unsigned long leaves_corrected;
unsigned long all_contents_removed;
/* pass 1, 2 */
unsigned long read_leaves;
unsigned long uninsertable_leaves;
unsigned long inserted_leaves;
unsigned long shared_objectids;
unsigned long saved_on_pass1;
unsigned long relocated;
unsigned long rewritten;
/* stat of semantic pass */
unsigned long regular_files;
unsigned long broken_files; /* files having stat data and broken body */
unsigned long directories;
unsigned long symlinks;
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 dir_recovered;
unsigned long lost_found_files;
/* 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 */
/* bitmaps */
reiserfs_bitmap_t on_disk_bitmap;
reiserfs_bitmap_t new_bitmap;
reiserfs_bitmap_t allocable_bitmap;
char * bitmap_file_name;
char * new_bitmap_file_name;
unsigned short mode;
unsigned long options;
/* log file name and handle */
char * log_file_name;
FILE * log;
/* hash hits stat */
int hash_amount;
unsigned long * hash_hits;
#define USED_BLOCKS 1
#define EXTERN_BITMAP 2
#define ALL_BLOCKS 3
int scan_area;
int test;
};
#define stats(s) ((struct fsck_data *)((s)->s_vp))
#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
#define fsck_interactive(fs) (stats(fs)->options & OPT_INTERACTIVE)
#define fsck_fix_fixable(fs) (stats(fs)->options & OPT_FIX_FIXABLE)
/* 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_mode(fs) (stats(fs)->mode)
#define fsck_log_file(fs) (stats(fs)->log)
/* ?? */
extern inline int change_version (int version)
{
return (version == 1)?0:1;
}
int fsck_user_confirmed (reiserfs_filsys_t fs, char * q, char * a, int default_answer);
void stage_report (int, reiserfs_filsys_t fs);
/* journal.c */
int reiserfs_replay_journal (struct super_block * s);
#define fsck_log(fmt, list...) \
{\
if (!fsck_silent (fs))\
reiserfs_warning (fsck_log_file (fs), fmt, ## list);\
}
#define fsck_progress(fmt, list...) \
{\
reiserfs_warning (stderr, fmt, ## list);\
fflush (stderr);\
}
+134
View File
@@ -0,0 +1,134 @@
/*
* Copyright 1996-1999 Hans Reiser
*/
#include "fsck.h"
#include <stdarg.h>
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);
}
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;
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);
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\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;
case 1:
fsck_progress ("\t%lu leaves read\n", stat->analyzed);
fsck_progress ("\t\t%lu inserted\n", stat->inserted_leaves);
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;
case 2:
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;
case 3: /* semantic pass */
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->fixed_sizes)
fsck_progress ("\tFiles with fixed size: %ld\n", stat->fixed_sizes);
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;
case 0x3a: /* looking for lost files */
if (stat->lost_found)
fsck_progress ("\tObjects without names %lu\n",
stat->lost_found);
if (stat->empty_lost_dirs)
fsck_progress ("\tEmpty lost dirs removed %lu\n",
stat->empty_lost_dirs);
if (stat->lost_found_dirs)
fsck_progress ("\tDirs linked to /lost+found: %lu\n",
stat->lost_found_dirs);
if (stat->dir_recovered)
fsck_progress ("\t\tDirs without stat data found %lu\n",
stat->dir_recovered);
if (stat->lost_found_files)
fsck_progress ("\tFiles linked to /lost+found %lu\n",
stat->lost_found_files);
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);
break;
case 4: /* removing of unreachable */
if (stat->deleted_items)
fsck_progress ("\tDeleted unreachable items %lu\n",
stat->deleted_items);
break;
}
if (!fsck_user_confirmed (fs, "Continue? (Yes):", "Yes\n", 1)) {
reiserfs_close (fs);
exit (0);
}
}
+219
View File
@@ -0,0 +1,219 @@
/*
* 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;
}
+269
View File
@@ -0,0 +1,269 @@
/*
* Copyright 2000-2001 Hans Reiser
*/
#include "fsck.h"
/* fixme: search_by_key is not needed after any add_entry */
static __u64 _look_for_lost (reiserfs_filsys_t fs, int link_lost_dirs)
{
struct key key, prev_key, * rdkey;
INITIALIZE_PATH (path);
int item_pos;
struct buffer_head * bh;
struct item_head * ih;
unsigned long leaves;
int is_it_dir;
static int lost_files = 0; /* looking for lost dirs we calculate amount of
lost files, so that when we will look for
lost files we will be able to stop when
there are no lost files anymore */
int retval;
__u64 size;
key = root_dir_key;
if (!link_lost_dirs && !lost_files) {
/* we have to look for lost files but we know already that there are
no any */
return 0;
}
fsck_progress ("Looking for lost %s:\n", link_lost_dirs ? "directories" : "files");
leaves = 0;
/* total size of added entries */
size = 0;
while (1) {
retval = usearch_by_key (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)) {
rdkey = uget_rkey (&path);
if (!rdkey) {
pathrelse (&path);
break;
}
key = *rdkey;
pathrelse (&path);
continue;
}
/* we are on the item in the buffer */
}
/* print ~ how many leaves were scanned and how fast it was */
if (!fsck_quiet (fs))
print_how_fast (0, leaves++, 50);
for (ih = get_ih (&path); item_pos < node_item_number (bh); item_pos ++, ih ++) {
if (is_item_reachable (ih))
continue;
/* found item which can not be reached */
if (!is_direntry_ih (ih) && !is_stat_data_ih (ih)) {
continue;
}
if (is_direntry_ih (ih)) {
/* if this directory has no stat data - try to recover it */
struct key sd;
struct path tmp;
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) {
/* 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);
key = sd;
pathrelse (&path);
goto cont;
}
/* stat data marked "not having name" found */
is_it_dir = ((not_a_directory (B_I_PITEM (bh,ih))) ? 0 : 1);
if (is_it_dir) {
struct key tmp_key;
INITIALIZE_PATH (tmp_path);
struct item_head * tmp_ih;
/* 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);
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)) {
/* last directory item is either stat data or empty
directory item - do not link this dir into lost+found */
stats(fs)->empty_lost_dirs ++;
pathrelse (&tmp_path);
continue;
}
pathrelse (&tmp_path);
}
if (link_lost_dirs && !is_it_dir) {
/* we are looking for directories and it is not a dir */
lost_files ++;
continue;
}
stats(fs)->lost_found ++;
{
struct key obj_key = {0, 0, {{0, 0},}};
char * lost_name;
struct item_head tmp_ih;
int pos_in_map;
/* key to continue */
key = ih->ih_key;
key.k_objectid ++;
tmp_ih = *ih;
if (is_objectid_really_used (semantic_id_map (fs), ih->ih_key.k_objectid,
&pos_in_map)) {
/* objectid is used, relocate an object */
stats(fs)->oid_sharing ++;
if (fsck_fix_non_critical (fs)) {
if (is_it_dir) {
relocate_dir (&tmp_ih, 1);
stats(fs)->oid_sharing_dirs_relocated ++;
} else {
relocate_file (&tmp_ih, 1);
stats(fs)->oid_sharing_files_relocated ++;
}
}
} else {
if (!is_it_dir)
mark_objectid_really_used (semantic_id_map (fs), ih->ih_key.k_objectid);
}
asprintf (&lost_name, "%u_%u", le32_to_cpu (tmp_ih.ih_key.k_dir_id),
le32_to_cpu (tmp_ih.ih_key.k_objectid));
/* 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;
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*/);
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);
rebuild_semantic_pass (&obj_key, &lost_found_dir_key, /*dot_dot*/0, /*reloc_ih*/0);
fsck_progress ("ok\n");
stats(fs)->lost_found_dirs ++;
} else {
if (usearch_by_key (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_files --;
}
free (lost_name);
goto cont;
}
} /* for */
prev_key = key;
get_next_key (&path, item_pos - 1, &key);
if (comp_keys (&prev_key, &key) != -1)
reiserfs_panic ("pass_3a: key must grow 2: prev=%k next=%k",
&prev_key, &key);
pathrelse (&path);
cont:
if (!link_lost_dirs && !lost_files) {
break;
}
}
pathrelse (&path);
#if 0
/* check names added we just have added to/lost+found. Those names are
marked DEH_Lost_found flag */
fsck_progress ("Checking lost+found directory.."); fflush (stdout);
check_semantic_tree (&lost_found_dir_key, &root_dir_key, 0, 1/* lost+found*/);
fsck_progress ("ok\n");
#endif
if (!link_lost_dirs && lost_files)
fsck_log ("look_for_lost: %d files seem to left not linked to lost+found\n",
lost_files);
return size;
}
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");
/* when warnings go not to stderr - separate then in the log */
if (fsck_log_file (fs) != stderr)
fsck_log ("####### Pass 3a (lost+found pass) #########\n");
/* look for lost dirs first */
size = _look_for_lost (fs, 1);
/* link files which are still lost */
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)
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);
set_sd_size (ih, sd, &size);
set_sd_blocks (ih, sd, &blocks);
mark_buffer_dirty (get_bh (&path));
pathrelse (&path);
stage_report (0x3a, fs);
}
+709
View File
@@ -0,0 +1,709 @@
/*
* Copyright 1996-2000 Hans Reiser
*/
#include "fsck.h"
#include <getopt.h>
#include "../version.h"
#define print_usage_and_exit() die ("Usage: %s [options] "\
" device\n"\
"\n"\
"Options:\n\n"\
" --check\t\tconsistency checking (default)\n"\
" --rebuild-sb\t\tsuper block checking and rebuilding if needed\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"\
" -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"\
" -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]);
/* fsck is called with one non-optional argument - file name of device
containing reiserfs. This function parses other options, sets flags
based on parsing and returns non-optional argument */
static char * parse_options (struct fsck_data * data, int argc, char * argv [])
{
int c;
static int mode = FSCK_CHECK;
data->scan_area = USED_BLOCKS;
while (1) {
static struct option options[] = {
/* modes */
{"check", no_argument, &mode, FSCK_CHECK},
{"rebuild-sb", no_argument, &mode, FSCK_SB},
{"rebuild-tree", no_argument, &mode, FSCK_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'},
{"quiet", no_argument, 0, 'q'},
{"nolog", no_argument, 0, 'n'},
/* if file exists ad reiserfs can be load of it - only
blocks marked used in that bitmap will be read */
{"scan-marked-in-bitmap", required_argument, 0, 'b'},
/* */
{"create-leaf-bitmap", required_argument, 0, 'c'},
/* all blocks will be read */
{"scan-whole-partition", no_argument, 0, 'S'},
/* special option: will mark free blocks used, zero all
unformatted node pointers and mark them free */
{"zero-files", no_argument, &mode, FSCK_ZERO_FILES},
{0, 0, 0, 0}
};
int option_index;
c = getopt_long (argc, argv, "iql:b:Sc:xoVaprt:n",
options, &option_index);
if (c == -1)
break;
switch (c) {
case 0:
/* long option specifying fsck mode is found */
break;
case 'i': /* --interactive */
data->options |= OPT_INTERACTIVE;
break;
case 'q': /* --quiet */
data->options |= OPT_QUIET;
break;
case 'l': /* --logfile */
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 '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;
break;
case 'S': /* --scan-whole-partition */
data->scan_area = ALL_BLOCKS;
break;
case 'c': /* --create-leaf-bitmap */
asprintf (&data->new_bitmap_file_name, "%s", optarg);
data->options |= OPT_SAVE_EXTERN_BITMAP;
break;
case 'x': /* --fix-fixable */
data->options |= OPT_FIX_FIXABLE;
break;
case 'o': /* --fix-non-critical */
data->options |= OPT_FIX_NON_CRITICAL;
break;
case 'n': /* --nolog */
data->options |= OPT_SILENT;
break;
case 'V':
case 'p': /* these say reiserfsck to do nothing */
case 'r':
case 'a':
mode = DO_NOTHING;
break;
case 't':
mode = DO_TEST;
data->test = atoi (optarg);
break;
default:
print_usage_and_exit();
}
}
if (optind != argc - 1 && mode != DO_NOTHING)
/* only one non-option argument is permitted */
print_usage_and_exit();
data->mode = mode;
if (!data->log)
data->log = stderr;
return argv[optind];
}
reiserfs_filsys_t fs;
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);
/* make file system invalid unless fsck done () */
set_state (fs->s_rs, REISERFS_ERROR_FS);
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);
}
/* 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));
/* objectid map is not touched */
mark_buffer_dirty (fs->s_sbh);
bwrite (fs->s_sbh);
}
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)
{
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;
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;
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");
}
/* 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 ++;
}
/* 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 ++;
}
/* 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 ++;
}
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);
fsck_allocable_bitmap (fs) = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
reiserfs_bitmap_fill (fsck_allocable_bitmap (fs));
}
#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)
{
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");
}
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);
}
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 ();
}
/* called before semantic pass starts */
static void end_rebuilding (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)));
mark_buffer_dirty (SB_BUFFER_WITH_SB (fs));
/* 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);
}
}
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);
proper_id_map (fs) = init_id_map ();
fetch_objectid_map (proper_id_map (fs), fs);
semantic_id_map (fs) = init_id_map ();
return 1;
}
}
return 0;
}
static void start_continuing (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));
}
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));
/* write all dirty blocks */
fsck_progress ("Syncing.."); fflush (stderr);
reiserfs_flush (fs);
sync ();
fsck_progress ("done\n"); fflush (stderr);
reiserfs_delete_bitmap (fsck_new_bitmap (fs));
free_id_map (&proper_id_map(fs));
if (semantic_id_map(fs))
free_id_map (&semantic_id_map(fs));
reiserfs_close (fs);
fsck_progress ("Done\n"); fflush (stderr);
}
static void rebuild_tree (reiserfs_filsys_t fs)
{
if (is_mounted (fs->file_name)) {
fsck_progress ("rebuild_tree: can not rebuild tree of mounted filesystem\n");
return;
}
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 (!skip_rebuilding (fs)) {
fsck_progress ("Rebuilding..\n");
start_rebuild (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);
}
static void zero_files (reiserfs_filsys_t fs)
{
init_bitmaps (fs);
reiserfs_reopen (fs, O_RDWR);
pass_0 (fs);
}
/* check umounted or read-only mounted filesystems only */
static void check_fs (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);
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)) {
fsck_progress ("Device %s is mounted w/ write permissions, can not check it\n",
fs->file_name);
reiserfs_close (fs);
exit (0);
}
fsck_progress ("Filesystem seems mounted read-only. Skipping journal replay..\n");
if (fsck_fix_fixable (fs)) {
fsck_progress ("--fix-fixable ignored\n");
stats(fs)->options &= ~OPT_FIX_FIXABLE;
}
}
fsck_disk_bitmap (fs) = reiserfs_create_bitmap (SB_BLOCK_COUNT (fs));
reiserfs_fetch_disk_bitmap (fsck_disk_bitmap (fs), fs);
if (fsck_fix_fixable (fs))
reiserfs_reopen (fs, O_RDWR);
/*proper_id_map (fs) = init_id_map ();*/
semantic_id_map (fs) = init_id_map ();
check_fs_tree (fs);
semantic_check ();
reiserfs_delete_bitmap (fsck_disk_bitmap (fs));
/*free_id_map (proper_id_map (fs));*/
free_id_map (&semantic_id_map (fs));
reiserfs_close (fs);
}
#include <sys/resource.h>
int main (int argc, char * argv [])
{
char * file_name;
struct fsck_data * data;
struct rlimit rlim = {0xffffffff, 0xffffffff};
print_banner ("reiserfsck");
/* 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");
}
data = getmem (sizeof (struct fsck_data));
file_name = parse_options (data, argc, argv);
if (data->mode == DO_NOTHING) {
freemem (data);
return 0;
}
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);
if (fsck_mode (fs) == FSCK_SB) {
reiserfs_reopen (fs, O_RDWR);
rebuild_sb (fs);
reiserfs_close (fs);
return 0;
}
if (no_reiserfs_found (fs)) {
fsck_progress ("reiserfsck: --rebuild-sb may restore reiserfs super block\n");
reiserfs_close (fs);
return 0;
}
fs->block_allocator = reiserfsck_reiserfs_new_blocknrs;
fs->block_deallocator = reiserfsck_reiserfs_free_block;
if (fsck_mode (fs) == FSCK_CHECK) {
check_fs (fs);
return 0;
}
#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);
printf ("done\n");
if (opt_fsck == 1)
printf ("ReiserFS : checking %s\n",file_name);
else
printf ("Rebuilding..\n");
reset_super_block (fs);
SB_DISK_SUPER_BLOCK(fs)->s_root_block = cpu_to_le32 (root_block);
init_bitmaps (fs);
/* 1,2. building of the tree */
recover_internal_tree(fs);
/* 3. semantic pass */
pass3_semantic ();
/* if --lost+found is set - link unaccessed directories to
lost+found directory */
look_for_lost (fs);
/* 4. look for unaccessed items in the leaves */
pass4_check_unaccessed_items ();
end_fsck ();
}
#endif /* FAST REBUILD READY */
if (fsck_mode (fs) == FSCK_ZERO_FILES)
zero_files (fs);
if (fsck_mode (fs) != FSCK_REBUILD && fsck_mode (fs) != DO_TEST)
return 0;
/* the --rebuild-tree is here */
rebuild_tree (fs);
return 0;
}
+1502
View File
File diff suppressed because it is too large. Load diff
+881
View File
@@ -0,0 +1,881 @@
/*
* Copyright 1996-1999 Hans Reiser
*/
#include "fsck.h"
#include <stdlib.h>
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 * bh;
bh = getblk (dev, blocknr, size);
if (buffer_uptodate (bh))
return bh;
// die ("make_buffer: uptodate buffer found");
memcpy (bh->b_data, data, size);
set_bit (BH_Uptodate, (char *)&bh->b_state);
return bh;
}
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))
return 1;
if ((to_find->k_dir_id != -1) &&
(to_find->k_dir_id != key->k_dir_id))
return 1;
return 0;
}
int is_item_reachable (struct item_head * ih)
{
return ih_reachable (ih) ? 1 : 0;
}
void mark_item_unreachable (struct item_head * ih)
{
mark_ih_unreachable (ih);
if (is_indirect_ih (ih))
set_free_space (ih, 0);
}
void mark_item_reachable (struct item_head * ih, struct buffer_head * bh)
{
mark_ih_ok (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);
if (mark_objectid_really_used (proper_id_map (fs), objectid)) {
stat_shared_objectid_found (fs);
mark_objectid_really_used (shared_id_map (fs), objectid);
}
#endif
zero_nlink (ih, B_I_PITEM (bh, ih));
}
/* this just marks blocks pointed by an indirect item as used in the
new bitmap */
static void indirect_in_tree (struct buffer_head * bh,
struct item_head * ih)
{
int i;
__u32 * unp;
unsigned long unfm_ptr;
unp = (__u32 *)B_I_PITEM (bh, ih);
for (i = 0; i < I_UNFM_NUM (ih); i ++) {
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);
}
}
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);
for_every_item (bh, mark_item_unreachable, actions);
stats(fs)->inserted_leaves ++;
mark_buffer_dirty (bh);
}
static void insert_pointer (struct buffer_head * bh, struct path * path)
{
struct item_head * ih;
char * body;
int zeros_number;
int retval;
struct tree_balance tb;
init_tb_struct (&tb, fs, path, 0x7fff);
/* fix_nodes & do_balance must work for internal nodes only */
ih = 0;
retval = fix_nodes (/*tb.transaction_handle,*/ M_INTERNAL, &tb, ih);
if (retval != CARRY_ON)
die ("insert_pointer: fix_nodes failed with retval == %d", retval);
/* child_pos: we insert after position child_pos: this feature of the insert_child */
/* there is special case: we insert pointer after
(-1)-st key (before 0-th key) in the parent */
if (PATH_LAST_POSITION (path) == 0 && path->pos_in_item == 0)
PATH_H_B_ITEM_ORDER (path, 0) = -1;
else {
if (PATH_H_PPARENT (path, 0) == 0)
PATH_H_B_ITEM_ORDER (path, 0) = 0;
/* PATH_H_B_ITEM_ORDER (path, 0) = PATH_H_PPARENT (path, 0) ? PATH_H_B_ITEM_ORDER (path, 0) : 0;*/
}
ih = 0;
body = (char *)bh;
//memmode = 0;
zeros_number = 0;
do_balance (&tb, ih, body, M_INTERNAL, zeros_number);
leaf_is_in_tree_now (bh);
}
/* return 1 if left and right can be joined. 0 otherwise */
int balance_condition_fails (struct buffer_head * left, struct buffer_head * right)
{
if (B_FREE_SPACE (left) >= B_CHILD_SIZE (right) -
(are_items_mergeable (B_N_PITEM_HEAD (left, B_NR_ITEMS (left) - 1), B_N_PITEM_HEAD (right, 0), left->b_size) ? IH_SIZE : 0))
return 1;
return 0;
}
/* return 1 if new can be joined with last node on the path or with
its right neighbor, 0 otherwise */
int balance_condition_2_fails (struct buffer_head * new, struct path * path)
{
struct buffer_head * bh;
struct key * right_dkey;
int pos, used_space;
bh = PATH_PLAST_BUFFER (path);
if (balance_condition_fails (bh, new))
/* new node can be joined with last buffer on the path */
return 1;
/* new node can not be joined with its left neighbor */
right_dkey = uget_rkey (path);
if (right_dkey == 0)
/* there is no right neighbor */
return 0;
pos = PATH_H_POSITION (path, 1);
if (pos == B_NR_ITEMS (bh = PATH_H_PBUFFER (path, 1))) {
/* we have to read parent of right neighbor. For simplicity we
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)
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;
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;
}
static void get_max_buffer_key (struct buffer_head * bh, struct key * key)
{
struct item_head * ih;
ih = B_N_PITEM_HEAD (bh, B_NR_ITEMS (bh) - 1);
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);
set_offset (KEY_FORMAT_1, key,
le32_to_cpu (B_I_DEH (bh, ih)[ih_entry_count (ih) - 1].deh_offset));
} 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)
{
return (SB_ROOT_BLOCK (fs) == ~0) ? 1 : 0;
}
static 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);
leaf_is_in_tree_now (bh);
}
/* inserts pointer to leaf into tree if possible. If not, marks node as
uninsertable in special bitmap */
static void try_to_insert_pointer_to_leaf (struct buffer_head * new_bh)
{
INITIALIZE_PATH (path);
struct buffer_head * bh; /* last path buffer */
struct key * first_bh_key, last_bh_key; /* first and last keys of new buffer */
struct key last_path_buffer_last_key, * right_dkey;
int ret_value;
if (tree_is_empty () == 1) {
make_single_leaf_tree (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);
if (ret_value == ITEM_FOUND)
goto cannot_insert;
/* get max key in the new node */
get_max_buffer_key (new_bh, &last_bh_key);
bh = PATH_PLAST_BUFFER (&path);
if (comp_keys (B_N_PKEY (bh, 0), &last_bh_key) == 1/* first is greater*/) {
/* new buffer falls before the leftmost leaf */
if (balance_condition_fails (new_bh, bh))
goto cannot_insert;
if (uget_lkey (&path) != 0 || PATH_LAST_POSITION (&path) != 0)
die ("try_to_insert_pointer_to_leaf: bad search result");
path.pos_in_item = 0;
goto insert;
}
/* get max key of buffer, that is in tree */
get_max_buffer_key (bh, &last_path_buffer_last_key);
if (comp_keys (&last_path_buffer_last_key, first_bh_key) != -1/* second is greater */)
/* first key of new buffer falls in the middle of node that is in tree */
goto cannot_insert;
right_dkey = uget_rkey (&path);
if (right_dkey && comp_keys (right_dkey, &last_bh_key) != 1 /* first is greater */)
goto cannot_insert;
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);
out:
pathrelse (&path);
return;
}
/* everything should be correct already in the leaf but contents of indirect
items. So we only
1. zero slots pointing to a leaf
2. zero pointers to blocks which are pointed already
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,
struct buffer_head * bh)
{
int i, j;
struct item_head * ih;
__u32 * ind_item;
unsigned long unfm_ptr;
int dirty = 0;
ih = B_N_PITEM_HEAD (bh, 0);
for (i = 0; i < B_NR_ITEMS (bh); i ++, ih ++) {
if (is_direntry_ih (ih)) {
struct reiserfs_de_head * deh;
char * name;
int name_len;
int hash_code;
deh = B_I_DEH (bh, ih);
for (j = 0; j < ih_entry_count (ih); j ++) {
name = name_in_entry (deh + j, j);
name_len = name_length (ih, deh + j, j);
if ((j == 0 && is_dot (name, name_len)) ||
(j == 1 && is_dot_dot (name, name_len))) {
continue;
}
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)) {
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) {
delete_item (fs, bh, i);
i --;
ih --;
break;
} else {
cut_entry (fs, bh, i, j, 1);
j --;
deh = B_I_DEH (bh, ih);
}
}
}
continue;
}
if (!is_indirect_ih (ih))
continue;
/* correct indirect items */
ind_item = (__u32 *)B_I_PITEM (bh, ih);
for (j = 0; j < I_UNFM_NUM (ih); j ++, ind_item ++) {
unfm_ptr = le32_to_cpu (*ind_item);
if (!unfm_ptr)
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))
/*!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);
/* 1. zero slots pointing to a leaf */
if (is_used_leaf (unfm_ptr)) {
dirty ++;
*ind_item = 0;
stats(fs)->wrong_pointers ++;
continue;
}
/* 2. zero pointers to blocks which are pointed already */
if (is_bad_unformatted (unfm_ptr)) {
/* this unformatted pointed more than once. Did we see it already? */
if (!is_bad_unfm_in_tree_once (unfm_ptr))
/* keep first reference to it and mark about that in
special bitmap */
mark_bad_unfm_in_tree_once (unfm_ptr);
else {
/* Yes, we have seen this pointer already, zero other pointers to it */
dirty ++;
*ind_item = 0;
stats(fs)->wrong_pointers ++;
continue;
}
}
}
}
if (dirty)
mark_buffer_dirty (bh);
}
/*######### has to die ##########*/
/* append item to end of list. Set head if it is 0. For indirect item
set wrong unformatted node pointers to 0 */
void save_item (struct si ** head, struct buffer_head * bh, struct item_head * ih, char * item)
{
struct si * si, * cur;
if (is_bad_item (bh, ih, item/*, fs->s_blocksize, fs->s_dev*/)) {
return;
}
if (is_indirect_ih (ih)) {
fsck_progress ("save_item: %H (should not happen)\n", ih);
}
stats(fs)->saved_on_pass1 ++;
si = getmem (sizeof (*si));
si->si_dnm_data = getmem (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));
// changed by XB
si->last_known = NULL;
if (*head == 0)
*head = si;
else {
cur = *head;
// changed by XB
// while (cur->si_next)
// cur = cur->si_next;
{
int count = 0;
int speedcount = 0;
while (cur->si_next) {
if (cur->last_known!=NULL) {
cur = cur->last_known; // speed up to the end if the chain
speedcount++;
} else {
cur = cur->si_next;
count++;
}
}
if ((*head)!=cur) // no self referencing loop please
(*head)->last_known = cur;
}
cur->si_next = si;
}
return;
}
static void save_items (struct si ** head, 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 ++) {
save_item (head, bh, ih, B_I_PITEM (bh, ih));
}
}
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)
{
while (si) {
insert_item_separately (&(si->si_ih), si->si_dnm_data,
0/*was not in tree*/);
si = remove_saved_item (si);
}
}
/* 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)
{
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");
/* read all leaves found on the pass 0 */
for (i = 0; i < SB_BLOCK_COUNT (fs); i ++) {
if (!is_used_leaf (i))
continue;
print_how_far (&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);
if (!bh) {
/* we were reading one block at time, and failed, so mark
block bad */
fsck_progress ("pass1: reading block %lu failed\n", i);
continue;
}
what_node = who_is_this (bh->b_data, fs->s_blocksize);
if ( what_node != THE_LEAF ) {
fsck_progress ("build_the_tree: nothing but leaves are expected. "
"Block %lu - %s\n", i,
(what_node == THE_INTERNAL) ? "internal" : "??");
brelse (bh);
continue;
}
if (is_block_used (i))
/* block is in new tree already */
die ("build_the_tree: leaf (%lu) is in tree already\n", i);
/* fprintf (block_list, "leaf %d\n", i + j);*/
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);
brelse (bh);
continue;
}
try_to_insert_pointer_to_leaf (bh);
brelse (bh);
}
#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);
brelse (bh);
continue;
}
try_to_insert_pointer_to_leaf (bh);
brelse (bh);
}
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");
/* 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);
}
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 ();
stage_report (2, fs);
fsck_progress ("Tree is built. Checking it - "); fflush (stdout);
reiserfsck_check_pass1 ();
fsck_progress ("done\n"); fflush (stdout);
reiserfs_delete_bitmap (bad_unfm_in_tree_once_bitmap);
}
#if 0
/* pass the S+ tree of filesystem */
void recover_internal_tree (struct super_block * s)
{
check_internal_structure(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
*/
+485
View File
@@ -0,0 +1,485 @@
/*
* Copyright 1996-2001 Hans Reiser
*/
#include "fsck.h"
/* on pass2 we take leaves which could not be inserted into tree
during pass1 and insert each item separately. It is possible that
items of different objects with the same key can be found. We treat
that in the following way: we put it into tree with new key and
link it into /lost+found directory with name made of dir,oid. When
coming item is a directory - we delete object from the tree, put it
back with different key, link it to /lost+found directory and
insert directory as it is */
/* relocation rules: we have an item (it is taken from "non-insertable"
leaf). It has original key yet. We check to see if object with this
key is remapped. Object can be only remapped if it is not a piece
of directory */
/* in list of this structures we store what has been
relocated. */
struct relocated {
unsigned long old_dir_id;
unsigned long old_objectid;
unsigned long new_objectid;
/*mode_t mode;*/
struct relocated * next;
};
/* all relocated files will be linked into lost+found directory at the
beginning of semantic pass */
struct relocated * relocated_list;
/* return objectid the object has to be remapped with */
__u32 objectid_for_relocation (struct key * key)
{
struct relocated * cur;
cur = relocated_list;
while (cur) {
if (cur->old_dir_id == key->k_dir_id &&
cur->old_objectid == key->k_objectid)
/* 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->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);
return cur->new_objectid;
}
/* this item is in tree. All unformatted pointer are correct. Do not
check them */
static void save_item_2 (struct si ** head, struct item_head * ih,
char * item, __u32 blocknr)
{
struct si * si, * cur;
si = getmem (sizeof (*si));
si->si_dnm_data = getmem (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));
if (*head == 0)
*head = si;
else {
cur = *head;
while (cur->si_next)
cur = cur->si_next;
cur->si_next = si;
}
return;
}
struct si * save_and_delete_file_item (struct si * si, struct path * path)
{
struct buffer_head * bh = PATH_PLAST_BUFFER (path);
struct item_head * ih = PATH_PITEM_HEAD (path);
save_item_2 (&si, ih, B_I_PITEM (bh, ih), bh->b_blocknr);
/* delete item temporary - do not free unformatted nodes */
reiserfsck_delete_item (path, 1/*temporary*/);
return si;
}
/* check whether there are any directory items with this key */
static int should_relocate (struct item_head * ih)
{
struct key key;
struct key * rkey;
struct path path;
struct item_head * path_ih;
/* starting with the leftmost item with this key */
key = ih->ih_key;
set_type_and_offset (KEY_FORMAT_1, &key, SD_OFFSET, TYPE_STAT_DATA);
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 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;
}
/* 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))) {
/* item of directory found. so, we have to relocate the file */
pathrelse (&path);
return 1;
}
key = path_ih->ih_key;
set_offset (KEY_FORMAT_1, &key, get_offset (&key) + 1);
pathrelse (&path);
}
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_file (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 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;
}
/* 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))) {
/* item of directory found. Leave it in the tree */
key = path_ih->ih_key;
set_offset (KEY_FORMAT_1, &key, get_offset (&key) + 1);
pathrelse (&path);
continue;
}
si = save_and_delete_file_item (si, &path);
}
if (si || change_ih) {
int moved_items;
struct key old, new;
/* get new objectid for relocation or get objectid with which file
was relocated already */
new_objectid = objectid_for_relocation (&ih->ih_key);
if (change_ih)
ih->ih_key.k_objectid = 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;
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*/);
si = remove_saved_item (si);
moved_items ++;
}
if (moved_items)
fsck_log ("relocate_file: %d items of file %K moved to %K\n",
moved_items, &old, &new);
}
}
/* this works for both new and old stat data */
#define st_mode(sd) le16_to_cpu(((struct stat_data *)(sd))->sd_mode)
#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)
static void overwrite_stat_data (struct item_head * new_ih,
void * new_item, struct path * path)
{
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));
}
} else {
if (st_mtime_v2 (new_item) > st_mtime_v2 (get_item (path))) {
memcpy (get_item (path), new_item, SD_SIZE);
mark_buffer_dirty (get_bh (path));
}
}
return;
}
/* insert sd item if it does not exist, overwrite it otherwise */
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
not a directory */
relocate_file (new_ih, 0/*do not change new_ih*/);
} else {
/* new item is a stat data of something else but directory. If
there are items of directory - we have to relocate the file */
if (should_relocate (new_ih))
relocate_file (new_ih, 1/*change new_ih*/);
}
/* if we will have to insert item into tree - it is ready */
zero_nlink (new_ih, new_item);
mark_item_unreachable (new_ih);
/* we are sure now that if we are inserting stat data of a
directory - there are no items with the same key which are not
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) {
/* this stat data is found */
if (ih_key_format (get_ih(&path)) != 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)..",
&(new_ih->ih_key), st_mode (new_item));
if (stat_data_v1 (new_ih)) {
/* sd to be inserted is of V1, where as sd in the tree
is of V2 */
fsck_log ("found newer in the tree (%M), skip inserting\n",
st_mode (get_item (&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);
reiserfsck_insert_item (&path, new_ih, new_item);
}
} else {
/* both stat data are of the same version */
overwrite_stat_data (new_ih, new_item, &path);
pathrelse (&path);
}
return;
}
/* item not found, insert a new one */
reiserfsck_insert_item (&path, new_ih, new_item);
}
/* this tries to put each item entry to the tree, if there is no items
of the directory, insert item containing 1 entry */
static void put_directory_item_into_tree (struct item_head * comingih, char * item)
{
struct reiserfs_de_head * deh;
int i;
char * buf;
char * name;
int namelen;
/* if there are anything ith 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 ++) {
name = name_in_entry (deh, i);
namelen = name_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 ()");
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*/);
free (buf);
}
/* make a directory */
}
/* relocated files get added into lost+found with slightly different names */
static void link_one (struct relocated * file)
{
char * name;
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;
/* 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 ++;
free (name);
}
void link_relocated_files (void)
{
struct relocated * tmp;
int count;
count = 0;
while (relocated_list) {
link_one (relocated_list);
tmp = relocated_list;
relocated_list = relocated_list->next;
freemem (tmp);
count ++;
}
}
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)
reiserfs_panic ("insert_item_separately: can not insert bad item %H", ih);
if (is_stat_data_ih (ih)) {
put_sd_into_tree (ih, item);
} else if (is_direntry_ih (ih)) {
put_directory_item_into_tree (ih, item);
} else {
if (should_relocate (ih))
relocate_file (ih, 1/*change new_ih*/);
reiserfsck_file_write (ih, item, was_in_tree);
}
}
static void put_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 */
continue;
}
insert_item_separately (ih, B_I_PITEM (bh, ih), 0/*was in tree*/);
}
}
/* 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)
{
struct buffer_head * bh;
unsigned long j;
unsigned long bb_counter = 0;
int what_node;
if (!stats(fs)->uninsertable_leaves)
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: "
"unable to read %lu block on device 0x%x\n",
j, fs->s_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;
}
/*fsck_log ("block %lu is being inserted\n", bh->b_blocknr);*/
put_items (bh);
print_how_far (&bb_counter, stats(fs)->uninsertable_leaves, 1, fsck_quiet (fs));
next:
brelse (bh);
j ++;
}
fsck_progress ("\n");
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);
}
+79
View File
@@ -0,0 +1,79 @@
/*
* Copyright 1996, 1997, 1998 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);
struct key * rkey;
if (i < B_NR_ITEMS (bh) - 1) {
/* 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 */
copy_key (key, rkey);
} else {
/* there is no next item */
memset (key, 0xff, KEY_SIZE);
}
}
int pass_4_check_unaccessed_items (void)
{
struct key key;
struct path path;
int i;
struct buffer_head * bh;
struct item_head * ih;
unsigned long items;
path.path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
key = root_dir_key;
fsck_progress ("Pass 4 - ");
items = 0;
while (usearch_by_key (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);
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;
reiserfsck_delete_item (&path, 0);
goto cont;
}
}
get_next_key (&path, i - 1, &key);
pathrelse (&path);
cont:
}
pathrelse (&path);
fsck_progress ("done\n");
stage_report (4, fs);
return 0;
}
+91
View File
@@ -0,0 +1,91 @@
.\" -*- nroff -*-
.\" Copyright 1996-2001 Hans Reiser.
.\"
.TH REISERFSCK 8 "March 2001" "Reiserfsprogs-3.x.0j"
.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
]
.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
.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).
.SH OPTIONS
.TP
.B --check
This checks filesystem consistency. This is a default action. It may
be used on a filesystem mounted read-only
.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.
.TP
.B --rebuild-sb
.TP
.B --interactive, -i
This makes \fBreiserfsck\fR to stop after each pass completed.
.TP
.B --quiet, -q
have \fBreiserfsck\fR to not reflect its progress
.TP
.B --nolog, -n
have \fBreiserfsck\fR to not log anything
.TP
\fB--logfile \fIfilename\fR, \fB-l \fI filename
have \fBreiserfsck\fR to put info about found corruptions in logfile
rather than on stderr
.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
.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
.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
.TP
.B -r
ignored
.TP
.B -V
Prints version and exits
.SH AUTHOR
This version of \fBreiserfsck\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>.
.SH TODO
Faster recovering, signal handling, i/o error handling, etc.
.SH SEE ALSO
.BR mkreiserfs (8),
.BR debugreiserfs (8)
+202
View File
@@ -0,0 +1,202 @@
/*
* 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);
}
+1346
View File
File diff suppressed because it is too large. Load diff
+189
View File
@@ -0,0 +1,189 @@
/*
* Copyright 1996-1999 Hans Reiser
*/
#include "fsck.h"
/* g_disk_bitmap initially contains copy of disk bitmaps
(cautious version of it);
g_new_bitmap initially has marked only super block, bitmap blocks
and bits after the end of bitmap
in pass 1 we go through g_disk_bitmap.
If block does not look like formatted node, we skip it.
If block contains internal node, put 0 in g_disk_bitmap if block is
not used in new tree yet.
If block contains leaf and is used already (by an indirect item
handled already to this time) save all items. They will be inserted
into tree after pass 1.
If block looking like leaf is not used in the new tree, try to
insert in into tree. If it is not possible, mark block in
g_uninsertable_leaf_bitmap. Blocks marked in this bitmap will be inserted into tree in pass 2. They can not be
This means, that in pass 1 when we have
found block containing the internal nodes we mark it in
g_disk_bitmap as free (reiserfs_free_internal_block). When block
gets into new tree it is marked in g_new_bitmap (mark_block_used)
When collecting resources for do_balance, we mark new blocks with
mark_block_used. After do_balance we unmark unused new blocks in
g_new_bitmap (bitmap.c:/reiserfs_free_block)
Allocating of new blocks: look for 0 bit in g_disk_bitmap
(find_zero_bit_in_bitmap), make sure, that g_new_bitmap contains 0
at the corresponding bit (is_block_used).
*/
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) */
int is_block_used (unsigned long block)
{
return reiserfs_bitmap_test_bit (fsck_new_bitmap (fs), block);
}
void mark_block_used (unsigned long block)
{
if (!block)
return;
if (is_block_used (block))
die ("mark_block_used: (%lu) used already", block);
reiserfs_bitmap_set_bit (fsck_new_bitmap (fs), block);
}
void mark_block_free (unsigned long block)
{
if (!is_block_used (block))
die ("mark_block_used: (%lu) is free", block);
reiserfs_bitmap_clear_bit (fsck_new_bitmap (fs), block);
}
int is_block_uninsertable (unsigned long block)
{
return !reiserfs_bitmap_test_bit (uninsertable_leaf_bitmap, block);
}
/* uninsertable block is marked by bit clearing */
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);
}
int reiserfsck_reiserfs_new_blocknrs (reiserfs_filsys_t fs,
unsigned long * free_blocknrs,
unsigned long start, int amount_needed)
{
int i;
if (!are_there_allocable_blocks (amount_needed))
die ("out of disk space");
for (i = 0; i < amount_needed; i ++) {
free_blocknrs[i] = alloc_block ();
if (!free_blocknrs[i])
die ("reiserfs_new_blocknrs: 0 is allocated");
mark_block_used (free_blocknrs[i]);
}
return CARRY_ON;
}
// FIXME: do you check readability of a block? If f_read fails - you
// free block in bitmap or if you mark bad blocks used to avoid their
// allocation in future you should have bad block counter in a super
// block. Another minor issue: users of _get_new_buffer expect buffer
// to be filled with 0s
struct buffer_head * reiserfsck_get_new_buffer (unsigned long start)
{
unsigned long blocknr = 0;
struct buffer_head * bh = NULL;
reiserfs_new_blocknrs (fs, &blocknr, start, 1);
bh = getblk (fs->s_dev, blocknr, fs->s_blocksize);
return bh;
}
/* free block in new bitmap */
int reiserfsck_reiserfs_free_block (reiserfs_filsys_t fs, unsigned long block)
{
mark_block_free (block);
/* put it back to pool of blocks for allocation */
make_allocable (block);
return 0;
}
+1069
View File
File diff suppressed because it is too large. Load diff
+391
View File
@@ -0,0 +1,391 @@
/*
* Copyright 1996-2001 Hans Reiser
*/
#include "fsck.h"
/* when --check fsck builds a map of objectids of files it finds in the tree
when --rebuild-tree - fsck builds map of objectids it inserts into tree
FIXME: objectid gets into map when stat data item
*/
/* is it marked used in super block's objectid map */
int is_objectid_used (reiserfs_filsys_t s, __u32 objectid)
{
__u32 * objectid_map;
int i = 0;
objectid_map = (__u32 *)((char *)(s->s_rs) + (sb_size(s)));
while (i < SB_OBJECTID_MAP_SIZE (s)) {
if (objectid == objectid_map[i]) {
return 1; /* objectid is used */
}
if (objectid > objectid_map[i] && objectid < objectid_map[i+1]) {
return 1; /* objectid is used */
}
if (objectid < objectid_map[i])
break;
i += 2;
}
/* objectid is free */
return 0;
}
/* 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 ++;
}
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--;
}
}
/* ubin_search_id is used to find id in the map (or proper place to
insert the new id). if smth goes wrong or ubin_search_id stops
working properly check_id_search_result should help to find raised
problems */
static void check_id_search_result(struct id_map * map, int res, __u32 pos,
__u32 id)
{
if (res != ITEM_FOUND && res != ITEM_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)
{
if (pos > map->m_used_slots_count)
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)
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)
die("check_id_search_result: found id (%u) not much than (%u)",
*(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)
{
struct id_map * map;
map = getmem (sizeof (struct id_map));
map->m_begin = NULL;
map->m_used_slots_count = 0;
map->m_page_count = 0;
mark_objectid_really_used (map, 1);
return map;
}
/* free whole map */
void free_id_map (struct id_map ** map)
{
freemem ((*map)->m_begin);
freemem (*map);
*map = 0;
}
/* return 1 if id is marked used, 0 otherwise */
int is_objectid_really_used (struct id_map * map, __u32 id, int * ppos)
{
int res;
*ppos = 0;
if (map->m_begin == NULL)
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);
#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)
/* id is not found in the map. if returned position is odd -
id is marked used */
return (*ppos % 2);
/* if returned position is odd - id is marked free */
return !(*ppos % 2);
}
static void check_objectid_map (struct id_map * map)
{
int i;
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");
}
/* returns 1 objectid is marked used already, 0 otherwise */
int mark_objectid_really_used (struct id_map * map, __u32 id)
{
int 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;
map->objectids_marked ++;
if (pos % 2 == 0){
/* id not found in the map. why? is_id_used() knows */
if (map->m_begin == NULL)
/* map is empty */
grow_id_map (map);
/* id + 1 is used, change id + 1 to id and exit */
if ( id + 1 == le32_to_cpu (map->m_begin[pos]) ) {
/* we can mark id as used w/o expanding of id map */
map->m_begin[pos] = cpu_to_le32 (id);
check_objectid_map (map);
return 0;
}
if (map->m_page_count * MAP_SIZE == map->m_used_slots_count * sizeof(__u32))
/* fixme: do not grow too much */
grow_id_map (map);
if (map->m_used_slots_count - pos > 0)
memmove (map->m_begin + pos + 2, map->m_begin + pos, (map->m_used_slots_count - pos) * sizeof (__u32));
map->m_used_slots_count += 2;
map->m_begin[pos] = cpu_to_le32 (id);
map->m_begin[pos+1] = cpu_to_le32 (id + 1);
check_objectid_map (map);
return 0;
}
/* id found in the map. pos is odd position () */
map->m_begin[pos] = cpu_to_le32 (id + 1);
/* 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]) {
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);
return 0;
}
static __u32 get_free_id (reiserfs_filsys_t fs)
{
struct id_map * map;
map = proper_id_map (fs);
/* If map is not NULL return the second element (first position in
the map). This allocates the first unused objectid. That is to
say, the first entry on the objectid map is the first unused
objectid. */
if (map->m_begin == NULL) {
fprintf (stderr, "get_free_id: hmm, 1 is allocated as objectid\n");
return 1;
}
return (le32_to_cpu (map->m_begin[1]));
}
__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);
return objectid;
}
#define objectid_map(fs) ((char *)((char *)((fs)->s_rs) + sb_size (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)
{
struct id_map * map;
int disk_size;
map = proper_id_map (fs);
disk_size = rs_objectid_map_size (fs->s_rs);
if (disk_size != map->m_used_slots_count ||
memcmp ((char *)((char *)((fs)->s_rs) + sb_size (fs)), map->m_begin, sizeof(__u32) * disk_size)) {
fprintf (stderr, "Objectid maps mismatch\n");
return 1;
}
return 0;
}
/* copy objectid map into buffer containing super block */
void correct_objectid_map (reiserfs_filsys_t fs)
{
struct id_map * map;
int size, disk_max;
map = proper_id_map (fs);
size = map->m_used_slots_count;
disk_max = rs_objectid_map_max_size (fs->s_rs);
if (disk_max < size) {
size = disk_max;
} else {
memset (fu_objectid_map (fs) + size, 0, (disk_max - size) * sizeof (__u32));
}
memcpy (fu_objectid_map (fs), map->m_begin, size * sizeof (__u32));
set_objectid_map_size (fs->s_rs, size);
mark_buffer_dirty (SB_BUFFER_WITH_SB (fs));
/*
if (fs->fu_job->verbose)
fprintf (stderr, "Objectid map corrected\n");
*/
}
#endif
#if 0
/* print the map of objectids */
void print_objectid_list ()
{
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);
}
/* print on-disk map of objectids */
void print_disk_objectid_list (void)
{
int i;
__u32 * objectid_map = (__u32 *)((char *)SB_DISK_SUPER_BLOCK (&g_sb) + (sb_size(&g_sb)));
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);
}
#endif
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);
check_objectid_map (map);
max = ((fs->s_blocksize - sb_size) >> 3 << 1);
set_objectid_map_max_size (fs->s_rs, max);
if (map->m_used_slots_count > max)
size = max;
else
size = map->m_used_slots_count;
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);
if (size == max)
/*((__u32 *)((char *)(fs->s_rs) + sb_size))*/
sb_objectid_map [max - 1] = map->m_begin [map->m_used_slots_count - 1];
check_objectid_map (map);
}
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);
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);
}
+704
View File
@@ -0,0 +1,704 @@
/*
* Copyright 1996-2001 Hans Reiser
*/
#include "fsck.h"
/* key1 and key2 are pointer to deh_offset of the struct reiserfs_de_head */
int comp_dir_entries (void * key1, void * key2)
{
__u32 off1, off2;
off1 = le32_to_cpu (*(__u32 *)key1);
off2 = le32_to_cpu (*(__u32 *)key2);
if (off1 < off2)
return -1;
if (off1 > off2)
return 1;
return 0;
}
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)
{
struct tree_balance tb;
init_tb_struct (&tb, fs, path, size);
if (fix_nodes (/*tb.transaction_handle,*/ M_PASTE, &tb, 0/*ih*/) != CARRY_ON)
//fix_nodes(options, tree_balance, ih_to_option, body_to_option)
die ("reiserfsck_paste_into_item: fix_nodes failed");
do_balance (/*tb.transaction_handle,*/ &tb, 0, body, M_PASTE, 0/*zero num*/);
}
void reiserfsck_insert_item (struct path * path, struct item_head * ih, const char * body)
{
struct tree_balance tb;
init_tb_struct (&tb, fs, path, IH_SIZE + 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*/);
}
static void free_unformatted_nodes (struct item_head * ih, struct buffer_head * bh)
{
__u32 * punfm = (__u32 *)B_I_PITEM (bh, ih);
int i;
for (i = 0; i < I_UNFM_NUM (ih); i ++, punfm ++)
if (*punfm) {
struct buffer_head * to_be_forgotten;
to_be_forgotten = find_buffer (fs->s_dev, *punfm, fs->s_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);
}
}
void reiserfsck_delete_item (struct path * path, int temporary)
{
struct tree_balance tb;
struct item_head * ih = PATH_PITEM_HEAD (path);
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)));
if (fix_nodes (/*tb.transaction_handle,*/ M_DELETE, &tb, 0/*ih*/) != CARRY_ON)
die ("reiserfsck_delete_item: fix_nodes failed");
do_balance (/*tb.transaction_handle,*/ &tb, 0, 0, M_DELETE, 0/*zero num*/);
}
void reiserfsck_cut_from_item (struct path * path, int cut_size)
{
struct tree_balance tb;
struct item_head * ih;
if (cut_size >= 0)
die ("reiserfsck_cut_from_item: cut size == %d", 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) {
struct buffer_head * to_be_forgotten;
to_be_forgotten = find_buffer (fs->s_dev, le32_to_cpu (unfm_ptr), fs->s_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, le32_to_cpu (unfm_ptr));
}
}
init_tb_struct (&tb, fs, path, cut_size);
if (fix_nodes (/*tb.transaction_handle,*/ M_CUT, &tb, 0) != CARRY_ON)
die ("reiserfsck_cut_from_item: fix_nodes failed");
do_balance (/*tb.transaction_handle,*/ &tb, 0, 0, M_CUT, 0/*zero num*/);
}
/* 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;
struct buffer_head * bh;
if (offset < FIRST_PATH_ELEMENT_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 ("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 ("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 ("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);
/* 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");
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);
}
#if 0
static unsigned long last_child (struct buffer_head * bh)
{
return child_block_number (bh, node_item_number (bh));
}
#endif
static unsigned long get_child (int pos, struct buffer_head * parent)
{
if (pos == -1)
return -1;
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);
/*
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)
{
printf ("/%3d (of %3d)", cur, total);fflush (stdout);
}
/* erase /XXX(of XXX) */
static void erase (void)
{
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,
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;
if (block >= SB_BLOCK_COUNT (s) || not_data_block (s, 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);
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);
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 (!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");
}
#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);
brelse (path[h]);
if (h)
erase ();
while (h && (cur[h-1] == total[h-1])) {
path[h] = 0;
h --;
brelse (path[h]);
if (h)
erase ();
}
if (h == 0) {
path[h] = 0;
break;
}
block = get_child (cur[h - 1], path[h-1]);
cur[h - 1] ++;
path[h] = 0;
continue;
}
total[h] = B_NR_ITEMS (path[h]) + 1;
cur[h] = 1;
block = first_child (path[h]);
h ++;
}
}
+1
View File
@@ -0,0 +1 @@
noinst_HEADERS = io.h misc.h reiserfs_fs.h reiserfs_lib.h
+197
View File
@@ -0,0 +1,197 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 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@
noinst_HEADERS = io.h misc.h reiserfs_fs.h reiserfs_lib.h
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
HEADERS = $(noinst_HEADERS)
DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
all: all-redirect
.SUFFIXES:
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps include/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
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 = include
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
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-exec: install-exec-am
install-data-am:
install-data: install-data-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am:
uninstall: uninstall-am
all-am: Makefile $(HEADERS)
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs:
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-tags mostlyclean-generic
mostlyclean: mostlyclean-am
clean-am: clean-tags clean-generic mostlyclean-am
clean: clean-am
distclean-am: distclean-tags distclean-generic clean-am
distclean: distclean-am
maintainer-clean-am: 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 \
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:
+57
View File
@@ -0,0 +1,57 @@
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;
};
#define BH_Uptodate 0
#define BH_Dirty 1
#define BH_Lock 2
#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 mark_buffer_dirty(bh) set_bit(BH_Dirty, &(bh)->b_state)
/*
printf ("%s:%s:%u %p %p %p\n",
__FILE__, __FUNCTION__, __LINE__,
__builtin_return_address (0),
__builtin_return_address (1),
__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 * find_buffer (int dev, int block, int size);
struct buffer_head * get_hash_table(dev_t dev, int 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);
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 flush_buffers (void);
void free_buffers (void);
loff_t reiserfs_llseek (unsigned int fd, loff_t offset, unsigned int origin);
+42
View File
@@ -0,0 +1,42 @@
/*
* Copyright 1996-2000 Hans Reiser
*/
/* nothing abount reiserfs here */
void die (char * fmt, ...);
void * getmem (int size);
void freemem (void * p);
void checkmem (char * p, int size);
void * expandmem (void * p, int size, int by);
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_fast (unsigned long total,
unsigned long passed, int cursor_pos);
int user_confirmed (char * q, char * yes);
/*
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);
File diff suppressed because it is too large. Load diff
+199
View File
@@ -0,0 +1,199 @@
/*
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
#ifndef REISERFS_LIB_H
#define REISERFS_LIB_H
typedef struct super_block * reiserfs_filsys_t;
#include "reiserfs_fs.h"
struct _bitmap {
unsigned long bm_byte_size;
unsigned long bm_bit_size;
char * bm_map;
unsigned long bm_set_bits;
};
typedef struct _bitmap * reiserfs_bitmap_t;
struct super_block {
int s_version; /* on-disk format version */
reiserfs_bitmap_t bitmap; /* copy of reiserfs on-disk bitmap */
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,
unsigned long * free_blocknrs,
unsigned long start, int amount_needed);
int (*block_deallocator) (reiserfs_filsys_t fs, unsigned long block);
};
/* 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,
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);
void reiserfs_paste_into_item (reiserfs_filsys_t fs, struct path * path,
const void * body, int size);
void reiserfs_insert_item (reiserfs_filsys_t fs, 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,
struct key * key, int fsck_need);
int _search_by_entry_key (reiserfs_filsys_t fs, struct key * 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_items (struct item_head * p_s_ih, struct path * p_s_path);
/* bitmap.c */
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);
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);
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);
int reiserfs_remove_entry (reiserfs_filsys_t fs, struct key * key);
/* node_formats.c */
#define THE_LEAF 1
#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);
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);
int is_tree_node (struct buffer_head * bh, int level);
int is_properly_hashed (reiserfs_filsys_t fs,
char * name, int namelen, __u32 offset);
int dir_entry_bad_location (struct reiserfs_de_head * deh,
struct item_head * ih, int first);
void make_dir_stat_data (int blocksize, int key_format,
__u32 dirid, __u32 objectid,
struct item_head * ih, void * sd);
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);
typedef void (*item_action_t) (struct buffer_head * bh, struct item_head * ih);
typedef void (*item_head_action_t) (struct item_head * ih);
void for_every_item (struct buffer_head * bh, item_head_action_t action,
item_action_t * actions);
int key_format (const struct key * key);
loff_t get_offset (const struct key * key);
int uniqueness2type (__u32 uniqueness);
__u32 type2uniqueness (int type);
int get_type (const struct key * key);
char * key_of_what (const struct key * key);
int type_unknown (struct key * key);
void set_type (int format, struct key * key, int type);
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 *,
check_unfm_func_t, int bad_dir);
#define hash_func_is_unknown(fs) ((fs)->s_hash_function == 0)
#define reiserfs_hash(fs) ((fs)->s_hash_function)
int known_hashes (void);
char * code2name (int code);
int func2code (hashf_t func);
hashf_t code2func (int code);
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,
struct reiserfs_de_head * deh, int pos_in_item);
/* 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 reiserfs_warning (FILE * fp, const char * fmt, ...);
char ftypelet (mode_t mode);
#define reiserfs_panic(fmt, list...) \
{\
fprintf (stderr, "%s %d %s\n", __FILE__, __LINE__, __FUNCTION__);\
reiserfs_warning (stderr, fmt, ## list);\
exit(4);\
}
#endif /* REISERFS_LIB_H */
Executable
+251
View File
@@ -0,0 +1,251 @@
#!/bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5 (mit/util/scripts/install.sh).
#
# Copyright 1991 by the Massachusetts Institute of Technology
#
# Permission to use, copy, modify, distribute, and sell this software and its
# documentation for any purpose is hereby granted without fee, provided that
# the above copyright notice appear in all copies and that both that
# copyright notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in advertising or
# publicity pertaining to distribution of the software without specific,
# written prior permission. M.I.T. makes no representations about the
# suitability of this software for any purpose. It is provided "as is"
# without express or implied warranty.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch. It can only install one file at a time, a restriction
# shared with many OS's install programs.
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
mkdirprog="${MKDIRPROG-mkdir}"
transformbasename=""
transform_arg=""
instcmd="$mvprog"
chmodcmd="$chmodprog 0755"
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
dir_arg=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-d) dir_arg=true
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
shift
continue;;
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
# this colon is to work around a 386BSD /bin/sh bug
:
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
else
true
fi
if [ x"$dir_arg" != x ]; then
dst=$src
src=""
if [ -d $dst ]; then
instcmd=:
chmodcmd=""
else
instcmd=mkdir
fi
else
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if [ -f $src -o -d $src ]
then
true
else
echo "install: $src does not exist"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
else
true
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
else
true
fi
fi
## this sed command emulates the dirname command
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
# Make sure that the destination directory exists.
# this part is taken from Noah Friedman's mkinstalldirs script
# Skip lots of stat calls in the usual case.
if [ ! -d "$dstdir" ]; then
defaultIFS='
'
IFS="${IFS-${defaultIFS}}"
oIFS="${IFS}"
# Some sh's can't handle IFS=/ for some reason.
IFS='%'
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
IFS="${oIFS}"
pathcomp=''
while [ $# -ne 0 ] ; do
pathcomp="${pathcomp}${1}"
shift
if [ ! -d "${pathcomp}" ] ;
then
$mkdirprog "${pathcomp}"
else
true
fi
pathcomp="${pathcomp}/"
done
fi
if [ x"$dir_arg" != x ]
then
$doit $instcmd $dst &&
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
else
# If we're going to rename the final executable, determine the name now.
if [ x"$transformarg" = x ]
then
dstfile=`basename $dst`
else
dstfile=`basename $dst $transformbasename |
sed $transformarg`$transformbasename
fi
# don't allow the sed command to completely eliminate the filename
if [ x"$dstfile" = x ]
then
dstfile=`basename $dst`
else
true
fi
# Make a temp file name in the proper directory.
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp &&
trap "rm -f ${dsttmp}" 0 &&
# and set any options; do chmod last to preserve setuid bits
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $instcmd $src $dsttmp" command.
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
# Now rename the file to the real destination.
$doit $rmcmd -f $dstdir/$dstfile &&
$doit $mvcmd $dsttmp $dstdir/$dstfile
fi &&
exit 0
+23
View File
@@ -0,0 +1,23 @@
noinst_LIBRARIES = libmisc.a
libmisc_a_SOURCES = io.c misc.c
##reiserfs.c
INCLUDES = -I$(top_srcdir)/include
+260
View File
@@ -0,0 +1,260 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 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@
noinst_LIBRARIES = libmisc.a
libmisc_a_SOURCES = io.c misc.c
INCLUDES = -I$(top_srcdir)/include
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
LIBRARIES = $(noinst_LIBRARIES)
DEFS = @DEFS@ -I. -I$(srcdir)
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
libmisc_a_LIBADD =
libmisc_a_OBJECTS = io.o misc.o
AR = ar
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
SOURCES = $(libmisc_a_SOURCES)
OBJECTS = $(libmisc_a_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 lib/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
mostlyclean-noinstLIBRARIES:
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
distclean-noinstLIBRARIES:
maintainer-clean-noinstLIBRARIES:
.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:
libmisc.a: $(libmisc_a_OBJECTS) $(libmisc_a_DEPENDENCIES)
-rm -f libmisc.a
$(AR) cru libmisc.a $(libmisc_a_OBJECTS) $(libmisc_a_LIBADD)
$(RANLIB) libmisc.a
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 = lib
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$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
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-exec: install-exec-am
install-data-am:
install-data: install-data-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am:
uninstall: uninstall-am
all-am: Makefile $(LIBRARIES)
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs:
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-noinstLIBRARIES mostlyclean-compile \
mostlyclean-tags mostlyclean-generic
mostlyclean: mostlyclean-am
clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
mostlyclean-am
clean: clean-am
distclean-am: distclean-noinstLIBRARIES distclean-compile \
distclean-tags distclean-generic clean-am
distclean: distclean-am
maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
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-noinstLIBRARIES distclean-noinstLIBRARIES \
clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile 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:
+508
View File
@@ -0,0 +1,508 @@
/*
* Copyright 1996, 1997 Hans Reiser, see reiserfs/README for licensing and copyright details
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <asm/types.h>
#include <sys/types.h>
/*#include <linux/unistd.h>*/
#include "io.h"
#include "misc.h"
/* 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 */
#define BLOCK_SIZE 1024
#define MAX_NR_BUFFERS 16384
static int g_nr_buffers;
#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 * g_buffer_heads;
static void show_buffers (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;
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) {
in_use ++;
}
if (buffer_dirty (next)) {
dirty ++;
}
if (buffer_clean (next) && next->b_count == 0) {
free ++;
}
}
next = next->b_next;
if (next == g_buffer_list_head)
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);
}
static void insert_into_hash_queue (struct buffer_head * bh)
{
int index = bh->b_blocknr % NR_HASH_QUEUES;
if (bh->b_hash_prev || bh->b_hash_next)
die ("insert_into_hash_queue: hash queue corrupted");
if (g_a_hash_queues[index]) {
g_a_hash_queues[index]->b_hash_prev = bh;
bh->b_hash_next = g_a_hash_queues[index];
}
g_a_hash_queues[index] = bh;
}
static void remove_from_hash_queue (struct buffer_head * bh)
{
if (bh->b_hash_next == 0 && bh->b_hash_prev == 0 && bh != g_a_hash_queues[bh->b_blocknr % NR_HASH_QUEUES])
/* (b_dev == 0) ? */
return;
if (bh == g_a_hash_queues[bh->b_blocknr % NR_HASH_QUEUES]) {
if (bh->b_hash_prev != 0)
die ("remove_from_hash_queue: hash queue corrupted");
g_a_hash_queues[bh->b_blocknr % NR_HASH_QUEUES] = bh->b_hash_next;
}
if (bh->b_hash_next)
bh->b_hash_next->b_hash_prev = bh->b_hash_prev;
if (bh->b_hash_prev)
bh->b_hash_prev->b_hash_next = bh->b_hash_next;
bh->b_hash_prev = bh->b_hash_next = 0;
}
static void put_buffer_list_end (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) {
bh->b_next = bh;
bh->b_prev = bh;
g_buffer_list_head = bh;
} else {
last = g_buffer_list_head->b_prev;
bh->b_next = last->b_next;
bh->b_prev = last;
last->b_next->b_prev = bh;
last->b_next = bh;
}
}
static void remove_from_buffer_list (struct buffer_head * bh)
{
if (bh == bh->b_next) {
g_buffer_list_head = 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;
}
bh->b_next = bh->b_prev = 0;
}
static void put_buffer_list_head (struct buffer_head * bh)
{
put_buffer_list_end (bh);
g_buffer_list_head = bh;
}
#define GROW_BUFFERS__NEW_BUFERS_PER_CALL 10
/* 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 *));
if (g_buffer_heads == 0)
g_buffer_heads = bh;
else {
/* link new array to the end of array list */
tmp = g_buffer_heads;
while (*(struct buffer_head **)(tmp + GROW_BUFFERS__NEW_BUFERS_PER_CALL) != 0)
tmp = *(struct buffer_head **)(tmp + GROW_BUFFERS__NEW_BUFERS_PER_CALL);
*(struct buffer_head **)(tmp + GROW_BUFFERS__NEW_BUFERS_PER_CALL) = bh;
}
for (i = 0; i < GROW_BUFFERS__NEW_BUFERS_PER_CALL; i ++) {
tmp = bh + i;
memset (tmp, 0, sizeof (struct buffer_head));
tmp->b_data = getmem (size);
if (tmp->b_data == 0)
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 ++;
}
return GROW_BUFFERS__NEW_BUFERS_PER_CALL;
}
struct buffer_head * find_buffer (int dev, int block, int size)
{
struct buffer_head * next;
next = g_a_hash_queues[block % NR_HASH_QUEUES];
for (;;) {
struct buffer_head *tmp = next;
if (!next)
break;
next = tmp->b_hash_next;
if (tmp->b_blocknr != block || tmp->b_size != size || tmp->b_dev != dev)
continue;
next = tmp;
break;
}
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)
{
struct buffer_head * next = g_buffer_list_head;
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);
return next;
}
next = next->b_next;
if (next == g_buffer_list_head)
break;
}
return 0;
}
static void sync_buffers (int size, int to_write)
{
struct buffer_head * next = g_buffer_list_head;
int written = 0;
for (;;) {
if (!next)
die ("flush_buffer: buffer list is corrupted");
if ((!size || next->b_size == size) && buffer_dirty (next) && buffer_uptodate (next)) {
written ++;
bwrite (next);
if (written == to_write)
return;
}
next = next->b_next;
if (next == g_buffer_list_head)
break;
}
}
void flush_buffers (void)
{
sync_buffers (0, 0);
}
struct buffer_head * getblk (int dev, int 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
/*checkmem (bh->b_data, bh->b_size);*/
remove_from_buffer_list (bh);
put_buffer_list_end (bh);
bh->b_count ++;
return bh;
}
bh = get_free_buffer (size);
if (bh == 0) {
if (grow_buffers (size) == 0) {
sync_buffers (size, 10);
}
bh = get_free_buffer (size);
if (bh == 0) {
show_buffers (dev, size);
die ("getblk: no free buffers after grow_buffers and refill (%d)", g_nr_buffers);
}
}
bh->b_count = 1;
bh->b_dev = dev;
bh->b_size = size;
bh->b_blocknr = block;
bh->b_end_io = NULL ;
memset (bh->b_data, 0, size);
clear_bit(BH_Dirty, &bh->b_state);
clear_bit(BH_Uptodate, &bh->b_state);
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)
{
if (bh == 0)
return;
if (bh->b_count == 0) {
die ("brelse: can not free a free buffer %lu", bh->b_blocknr);
}
/*checkmem (bh->b_data, bh->b_size);*/
bh->b_count --;
}
void bforget (struct buffer_head * bh)
{
if (bh) {
brelse (bh);
remove_from_hash_queue (bh);
remove_from_buffer_list (bh);
put_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;
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;
bytes = read (bh->b_dev, bh->b_data, bh->b_size);
if (bytes != (ssize_t)bh->b_size)
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;
return 0;
}
*/
bh = getblk (dev, block, size);
if (buffer_uptodate (bh))
return bh;
if (f_read(bh) == 0)
{
brelse(bh);
return 0;
}
mark_buffer_uptodate (bh, 0);
return bh;
}
int valid_offset( int fd, loff_t offset)
{
char ch;
loff_t res;
/*res = reiserfs_llseek (fd, offset, 0);*/
res = lseek64 (fd, offset, 0);
if (res < 0)
return 0;
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);
}
int bwrite (struct buffer_head * bh)
{
loff_t offset;
ssize_t bytes;
size_t size;
if (!buffer_dirty (bh) || !buffer_uptodate (bh))
return 0;
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));
exit (4); /* File system errors left uncorrected */
}
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));
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;
//sync_buffers (0, 0);
for (;;) {
if (!next)
die ("check_and_free_buffer_mem: buffer list is corrupted");
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);
if (buffer_dirty (next) && buffer_uptodate (next))
fprintf (stderr, "check_and_free_buffer_mem: dirty buffer %lu found\n",
next->b_blocknr);
freemem (next->b_data);
i ++;
next = next->b_next;
if (next == g_buffer_list_head)
break;
}
if (i != g_nr_buffers)
die ("check_and_free_buffer_mem: found %d buffers, must be %d", i, g_nr_buffers);
/* free buffer heads */
while ((next = g_buffer_heads)) {
g_buffer_heads = *(struct buffer_head **)(next + GROW_BUFFERS__NEW_BUFERS_PER_CALL);
freemem (next);
}
return;
}
/* */
void free_buffers (void)
{
check_and_free_buffer_mem ();
}
+613
View File
@@ -0,0 +1,613 @@
/*
* Copyright 1996, 1997, 1998 Hans Reiser
*/
/*#define _GNU_SOURCE*/
/*#define _FILE_OFFSET_BITS 64*/
#include <stdio.h>
#include <unistd.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <asm/types.h>
#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;
}
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;
}
/*int test_and_set_bit (int nr, void * addr)
{
int oldbit = test_bit (nr, addr);
set_bit (nr, addr);
return oldbit;
}
int test_and_clear_bit (int nr, void * addr)
{
int oldbit = test_bit (nr, addr);
clear_bit (nr, addr);
return oldbit;
}*/
void die (char * fmt, ...)
{
static char buf[1024];
va_list args;
va_start (args, fmt);
vsprintf (buf, fmt, args);
va_end (args);
fprintf (stderr, "\n%s\n\n\n", buf);
exit (-1);
}
#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)
{
char * begin;
begin = p - strlen (MEM_BEGIN) - 1 - sizeof (int);
return *(int *)(begin + strlen (MEM_BEGIN) + 1);
}
void checkmem (char * p, int size)
{
char * begin;
char * end;
begin = p - strlen (MEM_BEGIN) - 1 - sizeof (int);
if (strcmp (begin, MEM_BEGIN))
die ("checkmem: memory corrupted - invalid head sign");
if (*(int *)(begin + strlen (MEM_BEGIN) + 1) != size)
die ("checkmem: memory corrupted - invalid size");
end = begin + size + CONTROL_SIZE - strlen (MEM_END) - 1;
if (strcmp (end, MEM_END))
die ("checkmem: memory corrupted - invalid end sign");
}
void * getmem (int size)
{
char * p;
char * mem;
p = (char *)malloc (CONTROL_SIZE + size);
if (!p)
die ("getmem: no more memory (%d)", size);
strcpy (p, MEM_BEGIN);
p += strlen (MEM_BEGIN) + 1;
*(int *)p = size;
p += sizeof (int);
mem = p;
memset (mem, 0, size);
p += size;
strcpy (p, MEM_END);
checkmem (mem, size);
return mem;
}
void * expandmem (void * vp, int size, int by)
{
int allocated;
char * mem, * p = vp;
int expand_by = by;
if (p) {
checkmem (p, size);
allocated = CONTROL_SIZE + size;
p -= (strlen (MEM_BEGIN) + 1 + sizeof (int));
} else {
allocated = 0;
/* add control bytes to the new allocated area */
expand_by += CONTROL_SIZE;
}
p = realloc (p, allocated + expand_by);
if (!p)
die ("expandmem: no more memory (%d)", size);
if (!vp) {
strcpy (p, MEM_BEGIN);
}
mem = p + strlen (MEM_BEGIN) + 1 + sizeof (int);
*(int *)(p + strlen (MEM_BEGIN) + 1) = size + by;
/* fill new allocated area by 0s */
if(by > 0)
memset (mem + size, 0, by);
strcpy (mem + size + by, MEM_END);
checkmem (mem, size + by);
return mem;
}
void freemem (void * vp)
{
char * p = vp;
int size;
if (!p)
return;
size = get_mem_size (vp);
checkmem (p, size);
p -= (strlen (MEM_BEGIN) + 1 + sizeof (int));
strcpy (p, MEM_FREED);
strcpy (p + size + CONTROL_SIZE - strlen (MEM_END) - 1, MEM_FREED);
free (p);
}
typedef int (*func_t) (char *);
static int is_readonly_dir (char * dir)
{
char * name;
FILE * f;
name = tempnam (dir, 0);
if (!name) {
fprintf (stderr, "is_readonly: tempnam failed, think fs is not readonly\n");
return 0;
}
f = fopen (name, "w");
if (f) {
unlink (name);
free (name);
return 0;
}
free (name);
return (errno == EROFS) ? 1 : 0;
}
int user_confirmed (char * q, char * yes)
{
char * answer = 0;
size_t n = 0;
fprintf (stderr, "%s", q);
if (getline (&answer, &n, stdin) != strlen (yes) || strcmp (yes, answer))
return 0;
return 1;
}
#include <unistd.h>
#include <linux/unistd.h>
#define __NR_stat64 195
_syscall2(long, stat64, char *, filename, struct stat *, statbuf);
static int _is_mounted (char * device_name, func_t f)
{
int retval;
FILE *fp;
struct mntent *mnt;
struct statfs stfs;
struct stat root_st;
struct stat device_st;
/* struct stat64 device_st64;*/
int used_stat64 = 1;
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 */
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 */
return (f ? f ("/") : 1);
}
/* if proc filesystem is mounted */
if (statfs ("/proc", &stfs) == -1 || stfs.f_type != 0x9fa0/*procfs magic*/ ||
(fp = setmntent ("/proc/mounts", "r")) == NULL) {
/* 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)",
"Yes\n"));
else
return (user_confirmed (" (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);
break;
}
endmntent (fp);
return retval;
}
int is_mounted_read_only (char * device_name)
{
return _is_mounted (device_name, is_readonly_dir);
}
int is_mounted (char * device_name)
{
return _is_mounted (device_name, 0);
}
char buf1 [100];
char buf2 [100];
void print_how_fast (unsigned long passed, unsigned long total,
int cursor_pos, int reset_time)
{
static time_t t0, t1;
int speed;
int indent;
if (reset_time)
time (&t0);
time (&t1);
if (t1 != t0)
speed = passed / (t1 - t0);
else
speed = 0;
/* what has to be written */
if (total)
sprintf (buf1, "left %lu, %d /sec", total - passed, speed);
else {
/*(*passed) ++;*/
sprintf (buf1, "done %lu, %d /sec", passed, speed);
}
/* make indent */
indent = 79 - cursor_pos - strlen (buf1);
memset (buf2, ' ', indent);
buf2[indent] = 0;
fprintf (stderr, "%s%s", buf2, buf1);
memset (buf2, '\b', indent + strlen (buf1));
buf2 [indent + strlen (buf1)] = 0;
fprintf (stderr, "%s", buf2);
fflush (stderr);
}
static char * strs[] =
{"0%",".",".",".",".","20%",".",".",".",".","40%",".",".",".",".","60%",".",".",".",".","80%",".",".",".",".","100%"};
static char progress_to_be[1024];
static char current_progress[1024];
static void str_to_be (char * buf, int prosents)
{
int i;
prosents -= prosents % 4;
buf[0] = 0;
for (i = 0; i <= prosents / 4; i ++)
strcat (buf, strs[i]);
}
void print_how_far (unsigned long * passed, unsigned long total,
int inc, int quiet)
{
int percent;
if (*passed == 0)
current_progress[0] = 0;
(*passed) += inc;
if (*passed > total) {
fprintf (stderr, "\nprint_how_far: total %lu has been reached already. cur=%lu\n",
total, *passed);
return;
}
percent = ((*passed) * 100) / 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));
}
strcat (current_progress, progress_to_be + strlen (current_progress));
if (!quiet)
print_how_fast (*passed/* - inc*/, total, strlen (progress_to_be),
(*passed == inc) ? 1 : 0);
fflush (stderr);
}
#define ENDIANESS_NOT_DEFINED 0
#define LITTLE_ENDIAN_ARCH 1
#define BIG_ENDIAN_ARCH 2
static int endianess = ENDIANESS_NOT_DEFINED;
static void find_endianess (void)
{
__u32 x = 0x0f0d0b09;
char * s;
s = (char *)&x;
// little-endian is 1234
if (s[0] == '\11' && s[1] == '\13' && s[2] == '\15' && s[3] == '\17')
endianess = LITTLE_ENDIAN_ARCH;
// big-endian is 4321
if (s[0] == '\17' && s[1] == '\15' && s[2] == '\13' && s[3] == '\11')
die ("big-endian archs are not supported");
// 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");
}
// 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)
{
if (endianess == ENDIANESS_NOT_DEFINED)
find_endianess ();
if (endianess == LITTLE_ENDIAN_ARCH)
return val;
die ("neither big- nor any other endian archs are supported yet ");
return ((val>>24) | ((val>>8)&0xFF00) |
((val<<8)&0xFF0000) | (val<<24));
}
inline __u32 le32_to_cpu (__u32 val)
{
return cpu_to_le32 (val);
}
inline __u16 cpu_to_le16 (__u16 val)
{
return val;
if (endianess == ENDIANESS_NOT_DEFINED)
find_endianess ();
if (endianess == LITTLE_ENDIAN_ARCH)
return val;
die ("neither big- nor pdp- endian arch are supported yet ");
return (val >> 8) | (val << 8);
}
inline __u16 le16_to_cpu (__u16 val)
{
/*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);
}
inline __u64 cpu_to_le64 (__u64 val)
{
if (endianess == ENDIANESS_NOT_DEFINED)
find_endianess ();
if (endianess == LITTLE_ENDIAN_ARCH)
return val;
die ("neither big- nor pdp- endian arch are supported yet ");
return 0;
}
inline __u64 le64_to_cpu (__u64 val)
{
return cpu_to_le64 (val);
}
/* 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 )
{
char ch;
loff_t res;
/*res = reiserfs_llseek (fd, offset, 0);*/
res = lseek64 (fd, offset, 0);
if (res < 0)
return 0;
if (read (fd, &ch, 1) < 1)
return 0;
return 1;
}
#endif
/* calculates number of blocks on device */
unsigned long count_blocks (char * filename, int blocksize, int fd)
{
loff_t high, low;
int opened_here = 0;
if (fd < 0) {
fd = open (filename, O_RDONLY);
opened_here = 1;
}
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);
}
}
#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;
if (valid_offset (fd, mid))
low = mid;
else
high = mid;
}
valid_offset (fd, 0);
if (opened_here)
close (fd);
return (low + 1) / (blocksize);
}
Executable
+190
View File
@@ -0,0 +1,190 @@
#! /bin/sh
# Common stub for a few missing GNU programs while installing.
# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA.
if test $# -eq 0; then
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
fi
case "$1" in
-h|--h|--he|--hel|--help)
echo "\
$0 [OPTION]... PROGRAM [ARGUMENT]...
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
error status if there is no known handling for PROGRAM.
Options:
-h, --help display this help and exit
-v, --version output version information and exit
Supported PROGRAM values:
aclocal touch file \`aclocal.m4'
autoconf touch file \`configure'
autoheader touch file \`config.h.in'
automake touch all \`Makefile.in' files
bison create \`y.tab.[ch]', if possible, from existing .[ch]
flex create \`lex.yy.c', if possible, from existing .c
lex create \`lex.yy.c', if possible, from existing .c
makeinfo touch the output file
yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
;;
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
echo "missing - GNU libit 0.0"
;;
-*)
echo 1>&2 "$0: Unknown \`$1' option"
echo 1>&2 "Try \`$0 --help' for more information"
exit 1
;;
aclocal)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acinclude.m4' or \`configure.in'. You might want
to install the \`Automake' and \`Perl' packages. Grab them from
any GNU archive site."
touch aclocal.m4
;;
autoconf)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`configure.in'. You might want to install the
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
archive site."
touch configure
;;
autoheader)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`acconfig.h' or \`configure.in'. You might want
to install the \`Autoconf' and \`GNU m4' packages. Grab them
from any GNU archive site."
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in`
test -z "$files" && files="config.h"
touch_files=
for f in $files; do
case "$f" in
*:*) touch_files="$touch_files "`echo "$f" |
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
*) touch_files="$touch_files $f.in";;
esac
done
touch $touch_files
;;
automake)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
You might want to install the \`Automake' and \`Perl' packages.
Grab them from any GNU archive site."
find . -type f -name Makefile.am -print |
sed 's/\.am$/.in/' |
while read f; do touch "$f"; done
;;
bison|yacc)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.y' file. You may need the \`Bison' package
in order for those modifications to take effect. You can get
\`Bison' from any GNU archive site."
rm -f y.tab.c y.tab.h
if [ $# -ne 1 ]; then
eval LASTARG="\${$#}"
case "$LASTARG" in
*.y)
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" y.tab.c
fi
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" y.tab.h
fi
;;
esac
fi
if [ ! -f y.tab.h ]; then
echo >y.tab.h
fi
if [ ! -f y.tab.c ]; then
echo 'main() { return 0; }' >y.tab.c
fi
;;
lex|flex)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.l' file. You may need the \`Flex' package
in order for those modifications to take effect. You can get
\`Flex' from any GNU archive site."
rm -f lex.yy.c
if [ $# -ne 1 ]; then
eval LASTARG="\${$#}"
case "$LASTARG" in
*.l)
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
if [ -f "$SRCFILE" ]; then
cp "$SRCFILE" lex.yy.c
fi
;;
esac
fi
if [ ! -f lex.yy.c ]; then
echo 'main() { return 0; }' >lex.yy.c
fi
;;
makeinfo)
echo 1>&2 "\
WARNING: \`$1' is missing on your system. You should only need it if
you modified a \`.texi' or \`.texinfo' file, or any other file
indirectly affecting the aspect of the manual. The spurious
call might also be the consequence of using a buggy \`make' (AIX,
DU, IRIX). You might want to install the \`Texinfo' package or
the \`GNU make' package. Grab either from any GNU archive site."
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
if test -z "$file"; then
file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
fi
touch $file
;;
*)
echo 1>&2 "\
WARNING: \`$1' is needed, and you do not seem to have it handy on your
system. You might have modified some files without having the
proper tools for further handling them. Check the \`README' file,
it often tells you about the needed prerequirements for installing
this package. You may also peek at any GNU archive site, in case
some other package would contain this missing \`$1' program."
exit 1
;;
esac
exit 0
Executable
+40
View File
@@ -0,0 +1,40 @@
#! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
# Created: 1993-05-16
# Public domain
# $Id: mkinstalldirs,v 1.1.1.1 2000/08/03 10:35:16 vs Exp $
errstatus=0
for file
do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d
do
pathcomp="$pathcomp$d"
case "$pathcomp" in
-* ) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp"
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
fi
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# mkinstalldirs ends here
+9
View File
@@ -0,0 +1,9 @@
sbin_PROGRAMS = mkreiserfs
mkreiserfs_SOURCES = mkreiserfs.c
man_MANS = mkreiserfs.8
EXTRA_DIST = $(man_MANS)
LDADD = ../lib/libmisc.a ../reiserfscore/libcore.a
INCLUDES = -I../include
+325
View File
@@ -0,0 +1,325 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 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@
sbin_PROGRAMS = mkreiserfs
mkreiserfs_SOURCES = mkreiserfs.c
man_MANS = mkreiserfs.8
EXTRA_DIST = $(man_MANS)
LDADD = ../lib/libmisc.a ../reiserfscore/libcore.a
INCLUDES = -I../include
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
PROGRAMS = $(sbin_PROGRAMS)
DEFS = @DEFS@ -I. -I$(srcdir)
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
mkreiserfs_OBJECTS = mkreiserfs.o
mkreiserfs_LDADD = $(LDADD)
mkreiserfs_DEPENDENCIES = ../lib/libmisc.a ../reiserfscore/libcore.a
mkreiserfs_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 = $(mkreiserfs_SOURCES)
OBJECTS = $(mkreiserfs_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 mkreiserfs/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:
mkreiserfs: $(mkreiserfs_OBJECTS) $(mkreiserfs_DEPENDENCIES)
@rm -f mkreiserfs
$(LINK) $(mkreiserfs_LDFLAGS) $(mkreiserfs_OBJECTS) $(mkreiserfs_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 = mkreiserfs
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
mkreiserfs.o: mkreiserfs.c ../include/io.h ../include/misc.h \
../include/reiserfs_lib.h ../include/reiserfs_fs.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:
+62
View File
@@ -0,0 +1,62 @@
.\" -*- nroff -*-
.\" Copyright 1996-2001 Hans Reiser.
.\"
.TH MKREISERFS 8 "March 2001" "Reiserfsprogs-3.x.0j"
.SH NAME
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
]
.SH DESCRIPTION
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
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.
.TP
\fB\-v \fI1\fR |\fI 2
This specifies format new filsystem has to be of.
.TP
\fB\-q\fR
This makes the progress bar much less verbose. Useful when
logged in via a slow link (e.g. serial console).
.SH AUTHOR
This version of
.B mkreiserfs
has been written by Hans Reiser <reiser@idiom.com>.
.SH BUGS
No other blocksizes but 4k are available.
Please, report about other bugs to Hans Reiser <reiser@idiom.com>.
.SH SEE ALSO
.BR reiserfsck (8),
.BR debugreiserfs (8)
+504
View File
@@ -0,0 +1,504 @@
/*
* Copyright 1996, 1997, 1998, 1999 Hans Reiser
*/
/* mkreiserfs is very simple. It supports only 4 and 8K 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
primitive: it assumes, that device does not have unreadable blocks,
and it occupies first blocks for super, bitmap and root blocks.
bitmap blocks are interleaved across the disk, mainly to make
resizing faster. */
//
// FIXME: not 'not-i386' safe
//
#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 <linux/major.h>
#include <sys/stat.h>
#include <linux/kdev_t.h>
#include "io.h"
#include "misc.h"
#include "reiserfs_lib.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
struct buffer_head * g_sb_bh;
struct buffer_head * g_bitmap_bh;
struct buffer_head * g_rb_bh;
struct buffer_head * g_journal_bh ;
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 */
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)
{
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");
return blocks;
}
/* form super block (old one) */
static void make_super_block (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);
// max size of objectid map
rs->s_v1.s_oid_maxsize = cpu_to_le16 ((g_block_size - sb_size) / sizeof(__u32) / 2 * 2);
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_blocks(int dev, int start, int len) {
int i ;
struct buffer_head *bh ;
unsigned long done = 0;
printf ("Initializing journal - "); fflush (stdout);
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) ;
}
printf ("\n"); fflush (stdout);
}
/* 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);
/* 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);
/* 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);
/* and tree root is busy */
set_bit (i, g_bitmap_bh->b_data);
set_root_block (rs, i);
set_free_blocks (rs, rs_block_count (rs) - i - 1);
/* count bitmap blocks not resides in first s_blocksize blocks - ?? */
set_free_blocks (rs, rs_free_blocks (rs) - (rs_bmap_nr (rs) - 1));
mark_buffer_dirty (g_bitmap_bh);
mark_buffer_uptodate (g_bitmap_bh, 0);
mark_buffer_dirty (g_sb_bh);
return;
}
/* form the root block of the tree (the block head, the item head, the
root directory) */
static void make_root_block (void)
{
struct reiserfs_super_block * rs = (struct reiserfs_super_block *)g_sb_bh->b_data;
char * rb;
struct item_head * ih;
/* 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;
/* 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);
/* 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);
// 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)));
print_block (stdout, 0, g_rb_bh, 3, -1, -1);
mark_buffer_dirty (g_rb_bh);
mark_buffer_uptodate (g_rb_bh, 0);
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);
/* 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);
}
/* root block */
bwrite (g_rb_bh);
brelse (g_rb_bh);
brelse (g_bitmap_bh);
brelse (g_sb_bh);
}
static void report (char * devname)
{
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);
}
/* wipe out first 2 k of a device and both possible reiserfs super block */
static void invalidate_other_formats (int dev)
{
struct buffer_head * bh;
bh = getblk (dev, 0, 2048);
mark_buffer_uptodate (bh, 1);
mark_buffer_dirty (bh);
bwrite (bh);
brelse (bh);
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);
}
static void set_hash_function (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");
}
static void set_reiserfs_version (char * str)
{
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");
}
int main (int argc, char **argv)
{
char *tmp;
int dev;
int force = 0;
struct stat st;
char * device_name;
char c;
print_banner ("mkreiserfs");
if (argc < 2)
print_usage_and_exit ();
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;
case 'v':
set_reiserfs_version (optarg);
break;
case 'q':
quiet = 1;
break;
default :
print_usage_and_exit ();
}
device_name = argv [optind];
/* get block number for file system */
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);
}
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 (!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);
}
}
/* these fill buffers (super block, first bitmap, root block) with
reiserfs structures */
make_super_block (dev);
make_bitmap ();
make_root_block ();
report (device_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");
invalidate_other_formats (dev);
write_super_and_root_blocks ();
check_and_free_buffer_mem ();
printf ("Syncing.."); fflush (stdout);
close(dev) ;
sync ();
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);
return 0;
}
+5
View File
@@ -0,0 +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
INCLUDES = -I../include
+280
View File
@@ -0,0 +1,280 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 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@
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
INCLUDES = -I../include
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
LIBRARIES = $(noinst_LIBRARIES)
DEFS = @DEFS@ -I. -I$(srcdir)
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
AR = ar
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
DIST_COMMON = Makefile.am Makefile.in
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
SOURCES = $(libcore_a_SOURCES)
OBJECTS = $(libcore_a_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 reiserfscore/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
mostlyclean-noinstLIBRARIES:
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
distclean-noinstLIBRARIES:
maintainer-clean-noinstLIBRARIES:
.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:
libcore.a: $(libcore_a_OBJECTS) $(libcore_a_DEPENDENCIES)
-rm -f libcore.a
$(AR) cru libcore.a $(libcore_a_OBJECTS) $(libcore_a_LIBADD)
$(RANLIB) libcore.a
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 = reiserfscore
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
fi; \
done
bitmap.o: bitmap.c includes.h ../include/io.h ../include/misc.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
fix_node.o: fix_node.c includes.h ../include/io.h ../include/misc.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
lbalance.o: lbalance.c includes.h ../include/io.h ../include/misc.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/reiserfs_fs.h
prints.o: prints.c includes.h ../include/io.h ../include/misc.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/reiserfs_fs.h
stree.o: stree.c includes.h ../include/io.h ../include/misc.h \
../include/reiserfs_lib.h ../include/reiserfs_fs.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-exec: install-exec-am
install-data-am:
install-data: install-data-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
install: install-am
uninstall-am:
uninstall: uninstall-am
all-am: Makefile $(LIBRARIES)
all-redirect: all-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install
installdirs:
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-noinstLIBRARIES mostlyclean-compile \
mostlyclean-tags mostlyclean-generic
mostlyclean: mostlyclean-am
clean-am: clean-noinstLIBRARIES clean-compile clean-tags clean-generic \
mostlyclean-am
clean: clean-am
distclean-am: distclean-noinstLIBRARIES distclean-compile \
distclean-tags distclean-generic clean-am
distclean: distclean-am
maintainer-clean-am: maintainer-clean-noinstLIBRARIES \
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-noinstLIBRARIES distclean-noinstLIBRARIES \
clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \
mostlyclean-compile distclean-compile clean-compile \
maintainer-clean-compile 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:
+448
View File
@@ -0,0 +1,448 @@
/*
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
/*
* 2000/10/26 - Initial version.
*/
#include <assert.h>
#include "includes.h"
/* create clean bitmap */
reiserfs_bitmap_t reiserfs_create_bitmap (unsigned int bit_count)
{
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_set_bits = 0;
bm->bm_map = getmem (bm->bm_byte_size);
if (!bm->bm_map) {
freemem (bm);
return 0;
}
return bm;
}
/* 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)
{
unsigned int byte_count = ((bit_count + 7) / 8);
char * new_map;
new_map = expandmem (bm->bm_map, bm->bm_byte_size,
byte_count - bm->bm_byte_size);
if (!new_map) {
return 1;
}
bm->bm_map = new_map;
bm->bm_byte_size = byte_count;
bm->bm_bit_size = bit_count;
return 0;
}
/* bitmap destructor */
void reiserfs_delete_bitmap (reiserfs_bitmap_t bm)
{
freemem(bm->bm_map);
bm->bm_map = NULL; /* to not reuse bitmap handle */
bm->bm_bit_size = 0;
bm->bm_byte_size = 0;
freemem(bm);
}
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;
}
int reiserfs_bitmap_compare (reiserfs_bitmap_t bm1, reiserfs_bitmap_t bm2)
{
int bytes, bits;
int i, diff;
assert (bm1->bm_byte_size == bm2->bm_byte_size &&
bm1->bm_bit_size == bm2->bm_bit_size);
diff = 0;
/* compare full bytes */
bytes = bm1->bm_bit_size / 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]);
diff ++;
}
}
/* compare last byte of bitmap which can be used partially */
bits = bm1->bm_bit_size % 8;
if (bits) {
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)
{
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 ++;
}
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 --;
}
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);
assert(bit_number < bm->bm_bit_size);
return test_bit(bit_number, bm->bm_map);
}
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)
{
return bm->bm_set_bits;
}
int reiserfs_bitmap_find_zero_bit (reiserfs_bitmap_t bm, unsigned long * start)
{
unsigned int bit_nr = *start;
assert(*start < bm->bm_bit_size);
bit_nr = find_next_zero_bit(bm->bm_map, bm->bm_bit_size, *start);
if (bit_nr >= bm->bm_bit_size) { /* search failed */
return 1;
}
*start = bit_nr;
return 0;
}
/* copy reiserfs filesystem bitmap into memory bitmap */
int reiserfs_fetch_disk_bitmap (reiserfs_bitmap_t bm, reiserfs_filsys_t fs)
{
int i;
int bytes;
char * p;
int unused_bits;
reiserfs_warning (stderr, "Fetching on-disk bitmap..");
assert (bm->bm_bit_size == SB_BLOCK_COUNT (fs));
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 (p, SB_AP_BITMAP (fs)[i]->b_data, bytes);
p += bytes;
}
/* 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 ++)
clear_bit (bm->bm_bit_size + i, bm->bm_map);
bm->bm_set_bits = 0;
/* FIXME: optimize that */
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");
return 0;
}
/* copy bitmap to buffers which hold on-disk bitmap */
int reiserfs_flush_bitmap (reiserfs_bitmap_t bm, reiserfs_filsys_t fs)
{
int i;
int bytes;
char * p;
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;
}
/* 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);
return 0;
}
void reiserfs_bitmap_zero (reiserfs_bitmap_t bm)
{
memset (bm->bm_map, 0, bm->bm_byte_size);
bm->bm_set_bits = 0;
}
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;
}
/* format of bitmap saved in a file:
magic number (32 bits)
bm_bit_size (32 bits)
number of ranges of used and free blocks (32 bits)
number of contiguously used block, .. of free blocks, used, free, etc
magic number (32 bits) */
#define BITMAP_START_MAGIC 374031
#define BITMAP_END_MAGIC 7786472
void reiserfs_bitmap_save (char * filename, reiserfs_bitmap_t bm)
{
FILE * fp;
__u32 v;
int zeros;
int count;
int i;
int extents;
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);
v = BITMAP_START_MAGIC;
fwrite (&v, 4, 1, fp);
v = bm->bm_bit_size;
fwrite (&v, 4, 1, fp);
/*printf ("SAVE: bit_size - %d\n", v);*/
if (fseek (fp, 4, SEEK_CUR)) {
reiserfs_warning (stderr, "reiserfs_bitmap_save: fseek failed: %m\n");
fclose (fp);
return;
}
zeros = 0;
count = 0;
extents = 0;
for (i = 0; i < v; i ++) {
if (reiserfs_bitmap_test_bit (bm, i)) {
if (zeros) {
/* previous bit was not set, write amount of not set
bits, switch to count set bits */
fwrite (&count, 4, 1, fp);
/*printf ("SAVE: Free %d\n", count);*/
extents ++;
count = 1;
zeros = 0;
} else {
/* one more zero bit appeared */
count ++;
}
} else {
/* zero bit found */
if (zeros) {
count ++;
} else {
/* previous bit was set, write amount of set bits,
switch to count not set bits */
fwrite (&count, 4, 1, fp);
/*printf ("SAVE: Used %d\n", count);*/
extents ++;
count = 1;
zeros = 1;
}
}
}
fwrite (&count, 4, 1, fp);
extents ++;
/*
if (zeros)
printf ("SAVE: Free %d\n", count);
else
printf ("SAVE: Used %d\n", count);
*/
v = BITMAP_END_MAGIC;
fwrite (&v, 4, 1, fp);
if (fseek (fp, 8, 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);
}
reiserfs_bitmap_t reiserfs_bitmap_load (char * filename)
{
FILE * fp;
__u32 v;
int count;
int i, j;
int extents;
int bit;
reiserfs_bitmap_t bm;
fp = fopen (filename, "r");
if (!fp) {
reiserfs_warning (stderr, "reiserfs_bitmap_load: fseek 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);
return 0;
}
/* read bit size of bitmap */
fread (&v, 4, 1, fp);
bm = reiserfs_create_bitmap (v);
if (!bm) {
reiserfs_warning (stderr, "reiserfs_bitmap_load: creation failed");
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);
/*printf ("LOAD: extents - %d\n", extents);*/
bit = 0;
for (i = 0; i < extents; i ++) {
fread (&count, 4, 1, fp);
/*
if (i % 2)
printf ("LOAD: Free %d\n", count);
else
printf ("LOAD: Used %d\n", count);
*/
for (j = 0; j < count; j ++, bit ++)
if (i % 2 == 0) {
reiserfs_bitmap_set_bit (bm, bit);
}
}
fread (&v, 4, 1, fp);
/*printf ("LOAD: Endmagic %d\n", v);*/
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));
fflush (stderr);
return bm;
}
void reiserfs_bitmap_invert (reiserfs_bitmap_t bm)
{
int i;
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);
else
reiserfs_bitmap_set_bit (bm, i);
}
reiserfs_warning (stderr, "done\n");
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+253
View File
@@ -0,0 +1,253 @@
/*
* Keyed 32-bit hash function using TEA in a Davis-Meyer function
* H0 = Key
* Hi = E Mi(Hi-1) + Hi-1
*
* (see Applied Cryptography, 2nd edition, p448).
*
* Jeremy Fitzhardinge <jeremy@zip.com.au> 1998
*
* Jeremy has agreed to the contents of reiserfs/README. -Hans
* Yura's function is added (04/07/2000)
*/
//
// keyed_hash
// yura_hash
// r5
//
#include <asm/types.h>
#define DELTA 0x9E3779B9
#define FULLROUNDS 10 /* 32 is overkill, 16 is strong crypto */
#define PARTROUNDS 6 /* 6 gets complete mixing */
#ifndef __KERNEL__
typedef __u32 u32;
#endif
/* a, b, c, d - data; h0, h1 - accumulated hash */
#define TEACORE(rounds) \
do { \
u32 sum = 0; \
int n = rounds; \
u32 b0, b1; \
\
b0 = h0; \
b1 = h1; \
\
do \
{ \
sum += DELTA; \
b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); \
b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); \
} while(--n); \
\
h0 += b0; \
h1 += b1; \
} while(0)
u32 keyed_hash(const char *msg, int len)
{
u32 k[] = { 0x9464a485, 0x542e1a94, 0x3e846bff, 0xb75bcfc3};
u32 h0 = k[0], h1 = k[1];
u32 a, b, c, d;
u32 pad;
int i;
// assert(len >= 0 && len < 256);
pad = (u32)len | ((u32)len << 8);
pad |= pad << 16;
while(len >= 16)
{
a = (u32)msg[ 0] |
(u32)msg[ 1] << 8 |
(u32)msg[ 2] << 16|
(u32)msg[ 3] << 24;
b = (u32)msg[ 4] |
(u32)msg[ 5] << 8 |
(u32)msg[ 6] << 16|
(u32)msg[ 7] << 24;
c = (u32)msg[ 8] |
(u32)msg[ 9] << 8 |
(u32)msg[10] << 16|
(u32)msg[11] << 24;
d = (u32)msg[12] |
(u32)msg[13] << 8 |
(u32)msg[14] << 16|
(u32)msg[15] << 24;
TEACORE(PARTROUNDS);
len -= 16;
msg += 16;
}
if (len >= 12)
{
//assert(len < 16);
if (len >= 16)
*(int *)0 = 0;
a = (u32)msg[ 0] |
(u32)msg[ 1] << 8 |
(u32)msg[ 2] << 16|
(u32)msg[ 3] << 24;
b = (u32)msg[ 4] |
(u32)msg[ 5] << 8 |
(u32)msg[ 6] << 16|
(u32)msg[ 7] << 24;
c = (u32)msg[ 8] |
(u32)msg[ 9] << 8 |
(u32)msg[10] << 16|
(u32)msg[11] << 24;
d = pad;
for(i = 12; i < len; i++)
{
d <<= 8;
d |= msg[i];
}
}
else if (len >= 8)
{
//assert(len < 12);
if (len >= 12)
*(int *)0 = 0;
a = (u32)msg[ 0] |
(u32)msg[ 1] << 8 |
(u32)msg[ 2] << 16|
(u32)msg[ 3] << 24;
b = (u32)msg[ 4] |
(u32)msg[ 5] << 8 |
(u32)msg[ 6] << 16|
(u32)msg[ 7] << 24;
c = d = pad;
for(i = 8; i < len; i++)
{
c <<= 8;
c |= msg[i];
}
}
else if (len >= 4)
{
//assert(len < 8);
if (len >= 8)
*(int *)0 = 0;
a = (u32)msg[ 0] |
(u32)msg[ 1] << 8 |
(u32)msg[ 2] << 16|
(u32)msg[ 3] << 24;
b = c = d = pad;
for(i = 4; i < len; i++)
{
b <<= 8;
b |= msg[i];
}
}
else
{
//assert(len < 4);
if (len >= 4)
*(int *)0 = 0;
a = b = c = d = pad;
for(i = 0; i < len; i++)
{
a <<= 8;
a |= msg[i];
}
}
TEACORE(FULLROUNDS);
/* return 0;*/
return h0^h1;
}
u32 yura_hash (const char *msg, int len)
{
int j, pow;
u32 a, c;
int i;
for (pow=1,i=1; i < len; i++) pow = pow * 10;
if (len == 1)
a = msg[0]-48;
else
a = (msg[0] - 48) * pow;
for (i=1; i < len; i++) {
c = msg[i] - 48;
for (pow=1,j=i; j < len-1; j++) pow = pow * 10;
a = a + c * pow;
}
for (; i < 40; i++) {
c = '0' - 48;
for (pow=1,j=i; j < len-1; j++) pow = pow * 10;
a = a + c * pow;
}
for (; i < 256; i++) {
c = i;
for (pow=1,j=i; j < len-1; j++) pow = pow * 10;
a = a + c * pow;
}
a = a << 7;
return a;
}
u32 r5_hash (const 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;
}
#if 0
#include <stdio.h>
//#include <stddef.h>
int main (void)
{
char * name = 0;
size_t n = 0;
while (1) {
getline (&name, &n, stdin);
if (!strcmp (name, "\n"))
break;
name [strlen (name) - 1] = 0;
printf ("tea %lu\n, r5 %lu\nyura %lu\n",
keyed_hash (name, strlen (name)) & 0x7fffff80,
r5_hash (name, strlen (name)) & 0x7fffff80,
yura_hash (name, strlen (name)) & 0x7fffff80);
free (name);
name = 0;
n = 0;
}
}
#endif
File diff suppressed because it is too large. Load diff
+18
View File
@@ -0,0 +1,18 @@
/*
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <asm/types.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <malloc.h>
#include <sys/vfs.h>
#include <unistd.h>
#include <time.h>
#include "io.h"
#include "misc.h"
#include "reiserfs_lib.h"
File diff suppressed because it is too large. Load diff
+887
View File
@@ -0,0 +1,887 @@
/*
* Copyrright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
#include "includes.h"
/* 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)
{
struct block_head * blkh;
struct item_head * ih;
int used_space;
int prev_location;
int i;
int nr;
blkh = (struct block_head *)buf;
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)))
/* 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))
/* free space does not match to calculated amount of use space */
return 0;
// FIXME: it is_leaf will hit performance too much - we may have
// return 1 here
/* check tables of item heads */
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
during balancing */
if (ih_location (ih) > blocksize || ih_location (ih) < IH_SIZE * nr)
return 0;
if (/*ih_item_len (ih) < 1 ||*/ ih_item_len (ih) > MAX_ITEM_LEN (blocksize))
return 0;
if (prev_location - ih_location (ih) != ih_item_len (ih))
return 0;
prev_location = ih_location (ih);
}
// one may imagine much more checks
return 1;
}
/* returns 1 if buf looks like an internal node, 0 otherwise */
static int is_correct_internal (char * buf, int blocksize)
{
struct block_head * blkh;
int nr;
int used_space;
blkh = (struct block_head *)buf;
if (!is_internal_block_head (buf))
return 0;
nr = le16_to_cpu (blkh->blk_nr_item);
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))
return 0;
// one may imagine much more checks
return 1;
}
// make sure that bh contains formatted node of reiserfs tree of
// 'level'-th level
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 is_correct_internal (bh->b_data, bh->b_size);
}
static int is_desc_block (struct reiserfs_journal_desc * desc)
{
if (!memcmp(desc->j_magic, JOURNAL_DESC_MAGIC, 8) &&
le32_to_cpu (desc->j_len) > 0)
return 1;
return 0;
}
int is_reiserfs_magic_string (struct reiserfs_super_block * rs)
{
return (!strncmp (rs->s_v1.s_magic, REISERFS_SUPER_MAGIC_STRING,
strlen ( REISERFS_SUPER_MAGIC_STRING)));
}
int is_reiser2fs_magic_string (struct reiserfs_super_block * rs)
{
return (!strncmp (rs->s_v1.s_magic, REISER2FS_SUPER_MAGIC_STRING,
strlen ( REISER2FS_SUPER_MAGIC_STRING)));
}
/* 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)));
}
/* 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 ;
}
/* returns code of reiserfs metadata block (leaf, internal, super
block, journal descriptor), unformatted */
int who_is_this (char * buf, int blocksize)
{
if (is_correct_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 (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))
return THE_JDESC;
/* contents of buf does not look like reiserfs metadata. Bitmaps
are possible here */
return THE_UNKNOWN;
}
int block_of_journal (reiserfs_filsys_t fs, unsigned long block)
{
if (block >= SB_JOURNAL_BLOCK (fs) &&
block <= SB_JOURNAL_BLOCK (fs) + JOURNAL_BLOCK_COUNT)
return 1;
return 0;
}
int block_of_bitmap (reiserfs_filsys_t fs, unsigned long block)
{
if (spread_bitmaps (fs)) {
if (!(block % (fs->s_blocksize * 8)))
/* bitmap block */
return 1;
return block == 17;
} else {
/* bitmap in */
if (block > 2 && block < 3 + SB_BMAP_NR (fs))
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)
{
if (block_of_bitmap (fs, block))
/* it is one of bitmap blocks */
return 1;
if (block > 32768)
return 0;
if (block_of_journal (fs, block))
/* block of journal area */
return 1;
if (block <= fs->s_sbh->b_blocknr)
/* either super block or a block from skipped area at the
beginning of filesystem */
return 1;
return 0;
}
/* check whether 'block' can be logged */
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)
return 1;
if (block_of_journal (fs, block))
return 1;
if (block >= SB_BLOCK_COUNT (fs))
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)
{
return 3 + rs_bmap_nr (rs);
}
// in reiserfs version 1 (distributed bitmap) journal starts at 18-th
//
int get_journal_start_must (int blocksize)
{
return (REISERFS_DISK_OFFSET_IN_BYTES / 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_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));
}
int get_root_block (struct super_block * s)
{
return ((is_prejournaled_reiserfs (s->s_rs)) ?
(((struct reiserfs_super_block_v0 *)s->s_rs)->s_root_block) :
SB_ROOT_BLOCK (s));
}
int journal_size (struct super_block * s)
{
return JOURNAL_BLOCK_COUNT;
}
int check_item_f (reiserfs_filsys_t fs, struct item_head * ih, char * item);
/* 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");*/
return 1;
}
if (ih_item_len (ih) == SD_V1_SIZE && ih_key_format (ih) == KEY_FORMAT_1) {
/*printf ("old stat data\n");*/
return 1;
}
return 0;
}
if (ih_key_format (ih) == key_format (&ih->ih_key))
return 1;
return 0;
}
/* 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 (ih_entry_count (ih) != 0xffff)
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))
return 1;
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;
}
/* 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,
check_unfm_func_t check_unfm_func)
{
int i;
__u32 * ind = (__u32 *)item;
if (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]))
return 1;
}
if (fs->s_version == REISERFS_VERSION_1) {
/* check ih_free_space for 3.5 format only */
if (ih_free_space (ih) > fs->s_blocksize - 1)
return 1;
}
return 0;
}
static const struct {
hashf_t func;
char * name;
} hashes[] = {{0, "not set"},
{keyed_hash, "\"tea\""},
{yura_hash, "\"rupasov\""},
{r5_hash, "\"r5\""}};
#define HASH_AMOUNT (sizeof (hashes) / sizeof (hashes [0]))
int known_hashes (void)
{
return HASH_AMOUNT;
}
#define good_name(hashfn,name,namelen,deh_offset) \
(GET_HASH_VALUE ((hashfn) (name, namelen)) == GET_HASH_VALUE (deh_offset))
/* this also sets hash function */
int is_properly_hashed (reiserfs_filsys_t fs,
char * name, int namelen, __u32 offset)
{
int i;
if (namelen == 1 && name[0] == '.') {
if (offset == DOT_OFFSET)
return 1;
return 0;
}
if (namelen == 2 && name[0] == '.' && name[1] == '.') {
if (offset == DOT_DOT_OFFSET)
return 1;
return 0;
}
if (hash_func_is_unknown (fs)) {
/* try to find what hash function the name is sorted with */
for (i = 1; i < HASH_AMOUNT; i ++) {
if (good_name (hashes [i].func, name, namelen, offset)) {
if (!hash_func_is_unknown (fs)) {
/* two or more hash functions give the same value for this
name */
fprintf (stderr, "Detecting hash code: could not detect hash with name \"%.*s\"\n",
namelen, name);
reiserfs_hash (fs) = 0;
return 1;
}
/* set hash function */
reiserfs_hash(fs) = hashes [i].func;
}
}
}
if (good_name (reiserfs_hash(fs), name, namelen, offset))
return 1;
#if 0
fprintf (stderr, "is_properly_hashed: namelen %d, name \"%s\", offset %u, hash %u\n",
namelen, name_from_entry (name, namelen), GET_HASH_VALUE (offset),
GET_HASH_VALUE (reiserfs_hash(fs) (name, namelen)));
/* we could also check whether more than one hash function match on the
name */
for (i = 1; i < sizeof (hashes) / sizeof (hashes [0]); i ++) {
if (i == g_real_hash)
continue;
if (good_name (hashes[i], name, namelen, deh_offset)) {
die ("bad_hash: at least two hashes got screwed up with this name: \"%s\"",
bad_name (name, namelen));
}
}
#endif
return 0;
}
int find_hash_in_use (char * name, int namelen, __u32 hash_value_masked, int code_to_try_first)
{
int i;
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;
}
for (i = 1; i < HASH_AMOUNT; i ++) {
if (i == code_to_try_first)
continue;
if (hash_value_masked == GET_HASH_VALUE (hashes [i].func (name, namelen)))
return i;
}
/* not matching hash found */
return UNSET_HASH;
}
char * code2name (int code)
{
if (code >= HASH_AMOUNT)
code = 0;
return hashes [code].name;
}
int func2code (hashf_t func)
{
int i;
for (i = 0; i < HASH_AMOUNT; i ++)
if (func == hashes [i].func)
return i;
reiserfs_panic ("func2code: no hashes matches this function\n");
return 0;
}
hashf_t code2func (int code)
{
if (code >= HASH_AMOUNT) {
reiserfs_warning (stderr, "code2func: wrong hash code %d.\n"
"Using default %s hash function\n", code,
code2name (DEFAULT_HASH));
code = DEFAULT_HASH;
}
return hashes [code].func;
}
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))
return 1;
if (deh_location (deh) >= ih_item_len (ih))
return 1;
if (!first && deh_location (deh) >= deh_location (deh - 1))
return 1;
return 0;
}
/* 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,
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);
for (i = 0; i < ih_entry_count (ih); i ++, deh ++) {
if (deh_location (deh) >= prev_location)
return 1;
prev_location = deh_location (deh);
namelen = name_length (ih, deh, i);
if (namelen > REISERFS_MAX_NAME_LEN (fs->s_blocksize)) {
return 1;
}
if (deh_offset (deh) <= prev_offset)
return 1;
prev_offset = deh_offset (deh);
/* check hash value */
if (!is_properly_hashed (fs, item + prev_location, namelen, prev_offset)) {
if (bad_dir)
/* make is_bad_leaf to not insert whole leaf. Node will be
marked not-insertable and put into tree item by item in
pass 2 */
return 1;
}
}
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,
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);
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 (is_direntry_ih (ih)) {
retval = is_bad_directory (fs, ih, item, bad_dir);
/*
if (retval)
reiserfs_warning (stderr, "is_bad_directory %H\n", ih);*/
return retval;
}
if (is_indirect_ih (ih)) {
retval = is_bad_indirect (fs, ih, item, check_unfm);
/*
if (retval)
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 */
void make_dir_stat_data (int blocksize, int key_format,
__u32 dirid, __u32 objectid,
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_format (ih, key_format);
set_free_space (ih, MAX_US_INT);
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));
}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);
}
}
static void _empty_dir_item (int format, char * body, __u32 dirid, __u32 objid,
__u32 par_dirid, __u32 par_objid)
{
struct reiserfs_de_head * deh;
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));
/* direntry header of ".." */
deh[1].deh_offset = cpu_to_le32 (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));
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 ("..")));
} 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 (".."));
}
/* copy ".." and "." */
memcpy (body + deh_location (&deh[0]), ".", 1);
memcpy (body + deh_location (&deh[1]), "..", 2);
}
void make_empty_dir_item_v1 (char * body, __u32 dirid, __u32 objid,
__u32 par_dirid, __u32 par_objid)
{
_empty_dir_item (KEY_FORMAT_1, body, dirid, objid, par_dirid, par_objid);
}
void make_empty_dir_item (char * body, __u32 dirid, __u32 objid,
__u32 par_dirid, __u32 par_objid)
{
_empty_dir_item (KEY_FORMAT_2, body, dirid, objid, par_dirid, par_objid);
}
/* for every item call common action and an action corresponding to
item type */
void for_every_item (struct buffer_head * bh, item_head_action_t action,
item_action_t * actions)
{
int i;
struct item_head * ih;
item_action_t iaction;
ih = B_N_PITEM_HEAD (bh, 0);
for (i = 0; i < node_item_number (bh); i ++, ih ++) {
if (action)
action (ih);
iaction = actions[get_type (&ih->ih_key)];
if (iaction)
iaction (bh, ih);
}
}
/* old keys (on i386) have k_offset_v2.k_type == 15 (direct and
indirect) or == 0 (dir items and stat data) */
/* */
int key_format (const struct key * key)
{
int type;
type = le16_to_cpu (key->u.k_offset_v2.k_type);
if (type == 0 || type == 15)
return KEY_FORMAT_1;
return KEY_FORMAT_2;
}
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 le64_to_cpu (key->u.k_offset_v2.k_offset);
}
int uniqueness2type (__u32 uniqueness)
{
switch (uniqueness) {
case V1_SD_UNIQUENESS: return TYPE_STAT_DATA;
case V1_INDIRECT_UNIQUENESS: return TYPE_INDIRECT;
case V1_DIRECT_UNIQUENESS: return TYPE_DIRECT;
case V1_DIRENTRY_UNIQUENESS: return TYPE_DIRENTRY;
}
return TYPE_UNKNOWN;
}
__u32 type2uniqueness (int type)
{
switch (type) {
case TYPE_STAT_DATA: return V1_SD_UNIQUENESS;
case TYPE_INDIRECT: return V1_INDIRECT_UNIQUENESS;
case TYPE_DIRECT: return V1_DIRECT_UNIQUENESS;
case TYPE_DIRENTRY: return V1_DIRENTRY_UNIQUENESS;
}
return V1_UNKNOWN_UNIQUENESS;
}
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);
}
char * key_of_what (const struct key * key)
{
switch (get_type (key)) {
case TYPE_STAT_DATA: return "SD";
case TYPE_INDIRECT: return "IND";
case TYPE_DIRECT: return "DRCT";
case TYPE_DIRENTRY: return "DIR";
default: return "???";
}
}
int type_unknown (struct key * key)
{
int type = get_type (key);
switch (type) {
case TYPE_STAT_DATA:
case TYPE_INDIRECT:
case TYPE_DIRECT:
case TYPE_DIRENTRY:
return 0;
default:
break;
}
return 1;
}
// this sets key format as well as type of item key belongs to
//
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));
else
key->u.k_offset_v2.k_type = cpu_to_le16 (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);
else
key->u.k_offset_v2.k_offset = cpu_to_le64 (offset);
}
void set_type_and_offset (int format, struct key * key, loff_t offset, int type)
{
set_type (format, key, type);
set_offset (format, key, offset);
}
/* length of the directory entry in directory item. This define calculates
length of i-th directory entry using directory entry locations from dir
entry head. When it calculates length of 0-th directory entry, it uses
length of whole item in place of entry location of the non-existent
following entry in the calculation. See picture above.*/
// NOTE: this is not name length. This is length of whole entry
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));
}
char * name_in_entry (struct reiserfs_de_head * deh, int pos_in_item)
{
return ((char *)(deh - pos_in_item) + deh_location(deh));
}
int name_length (struct item_head * ih,
struct reiserfs_de_head * deh, int pos_in_item)
{
int len;
char * name;
len = entry_length (ih, deh, pos_in_item);
name = name_in_entry (deh, pos_in_item);
// name might be padded with 0s
while (!name [len - 1])
len --;
return len;
}
+949
View File
@@ -0,0 +1,949 @@
/*
* Copyright 1996, 1997, 1998 Hans Reiser, see reiserfs/README for licensing and copyright details
*/
#include "includes.h"
#include <stdarg.h>
#include <limits.h>
#include <printf.h>
static int _arginfo (const struct printf_info *info, size_t n,
int *argtypes)
{
if (n > 0)
argtypes[0] = PA_POINTER;
return 1;
}
#if 0
static int _arginfo2 (const struct printf_info *info, size_t n,
int *argtypes)
{
if (n > 0)
argtypes[0] = PA_INT;
return 1;
}
#endif
#define FPRINTF \
if (len == -1) {\
return -1;\
}\
len = fprintf (stream, "%*s",\
info->left ? -info->width : info->width, buffer);\
free (buffer);\
return len;\
/* %z */
static int print_block_head (FILE * stream,
const struct printf_info *info,
const void *const *args)
{
const struct buffer_head * bh;
char * buffer;
int len;
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));
FPRINTF;
}
/* %K */
static int print_short_key (FILE * stream,
const struct printf_info *info,
const void *const *args)
{
const struct key * key;
char * buffer;
int len;
key = *((const struct key **)(args[0]));
len = asprintf (&buffer, "%u %u", key->k_dir_id, key->k_objectid);
FPRINTF;
}
/* %k */
static int print_key (FILE * stream,
const struct printf_info *info,
const void *const *args)
{
const struct key * key;
char * buffer;
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));
FPRINTF;
}
/* %H */
static int print_item_head (FILE * stream,
const struct printf_info *info,
const void *const *args)
{
const struct item_head * ih;
char * buffer;
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"));
FPRINTF;
}
static int print_disk_child (FILE * stream,
const struct printf_info *info,
const void *const *args)
{
const struct disk_child * dc;
char * buffer;
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));
FPRINTF;
}
char ftypelet (mode_t mode)
{
if (S_ISBLK (mode))
return 'b';
if (S_ISCHR (mode))
return 'c';
if (S_ISDIR (mode))
return 'd';
if (S_ISREG (mode))
return '-';
if (S_ISFIFO (mode))
return 'p';
if (S_ISLNK (mode))
return 'l';
if (S_ISSOCK (mode))
return 's';
return '?';
}
static int rwx (FILE * stream, mode_t mode)
{
return fprintf (stream, "%c%c%c",
(mode & S_IRUSR) ? 'r' : '-',
(mode & S_IWUSR) ? 'w' : '-',
(mode & S_IXUSR) ? 'x' : '-');
}
/* %M */
static int print_sd_mode (FILE * stream,
const struct printf_info *info,
const void *const *args)
{
int len = 0;
mode_t mode;
mode = *(mode_t *)args[0];
len = fprintf (stream, "%c", ftypelet (mode));
len += rwx (stream, (mode & 0700) << 0);
len += rwx (stream, (mode & 0070) << 3);
len += rwx (stream, (mode & 0007) << 6);
return len;
}
void reiserfs_warning (FILE * fp, const char * fmt, ...)
{
static int registered = 0;
va_list args;
if (!registered) {
registered = 1;
register_printf_function ('K', print_short_key, _arginfo);
register_printf_function ('k', print_key, _arginfo);
register_printf_function ('H', print_item_head, _arginfo);
register_printf_function ('b', print_block_head, _arginfo);
register_printf_function ('y', print_disk_child, _arginfo);
register_printf_function ('M', print_sd_mode, _arginfo);
}
va_start (args, fmt);
vfprintf (fp, fmt, args);
va_end (args);
}
static char * vi_type (struct virtual_item * vi)
{
static char *types[]={"directory", "direct", "indirect", "stat data"};
if (vi->vi_type & VI_TYPE_STAT_DATA)
return types[3];
if (vi->vi_type & VI_TYPE_INDIRECT)
return types[2];
if (vi->vi_type & VI_TYPE_DIRECT)
return types[1];
if (vi->vi_type & VI_TYPE_DIRECTORY)
return types[0];
reiserfs_panic ("vi_type: 6000: unknown type (0x%x)", vi->vi_type);
return NULL;
}
void print_virtual_node (struct virtual_node * vn)
{
int i, j;
printf ("VIRTUAL NODE CONTAINS %d items, has size %d,%s,%s, ITEM_POS=%d POS_IN_ITEM=%d MODE=\'%c\'\n",
vn->vn_nr_item, vn->vn_size,
(vn->vn_vi[0].vi_type & VI_TYPE_LEFT_MERGEABLE )? "left mergeable" : "",
(vn->vn_vi[vn->vn_nr_item - 1].vi_type & VI_TYPE_RIGHT_MERGEABLE) ? "right mergeable" : "",
vn->vn_affected_item_num, vn->vn_pos_in_item, vn->vn_mode);
for (i = 0; i < vn->vn_nr_item; i ++) {
printf ("%s %d %d", vi_type (&vn->vn_vi[i]), i, vn->vn_vi[i].vi_item_len);
if (vn->vn_vi[i].vi_entry_sizes)
{
printf ("It is directory with %d entries: ", vn->vn_vi[i].vi_entry_count);
for (j = 0; j < vn->vn_vi[i].vi_entry_count; j ++)
printf ("%d ", vn->vn_vi[i].vi_entry_sizes[j]);
}
printf ("\n");
}
}
void print_path (struct tree_balance * tb, struct path * path)
{
int offset = path->path_length;
struct buffer_head * bh;
printf ("Offset Bh (b_blocknr, b_count) Position Nr_item\n");
while ( offset > ILLEGAL_PATH_ELEMENT_OFFSET ) {
bh = PATH_OFFSET_PBUFFER (path, offset);
printf ("%6d %10p (%9lu, %7d) %8d %7d\n", offset,
bh, bh ? bh->b_blocknr : 0, bh ? bh->b_count : 0,
PATH_OFFSET_POSITION (path, offset), bh ? B_NR_ITEMS (bh) : -1);
offset --;
}
}
#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,
struct buffer_head * bh, struct item_head * ih)
{
int i;
int namelen;
struct reiserfs_de_head * deh;
char * name;
/* static char namebuf [80];*/
if (!I_IS_DIRECTORY_ITEM (ih))
return;
//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 ++) {
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));
continue;
}
if (i && dir_entry_bad_location (deh - 1, ih, ((i - 1) == 0) ? 1 : 0))
/* previous entry has bad location so we can not calculate entry
length */
namelen = 25;
else
namelen = name_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)") : "??");
}
}
//
// printing of indirect item
//
static void start_new_sequence (__u32 * start, int * len, __u32 new)
{
*start = new;
*len = 1;
}
static int sequence_finished (__u32 start, int * len, __u32 new)
{
if (start == INT_MAX)
return 1;
if (start == 0 && new == 0) {
(*len) ++;
return 0;
}
if (start != 0 && (start + *len) == new) {
(*len) ++;
return 0;
}
return 1;
}
static void print_sequence (FILE * fp, __u32 start, int len)
{
if (start == INT_MAX)
return;
if (len == 1)
reiserfs_warning (fp, " %d", start);
else
reiserfs_warning (fp, " %d(%d)", start, len);
}
void print_indirect_item (FILE * fp, struct buffer_head * bh, int item_num)
{
struct item_head * ih;
int j;
__u32 * unp, prev = INT_MAX;
int num;
ih = B_N_PITEM_HEAD (bh, item_num);
unp = (__u32 *)B_I_PITEM (bh, ih);
if (ih->ih_item_len % UNFM_P_SIZE)
reiserfs_warning (fp, "print_indirect_item: invalid item len");
reiserfs_warning (fp, "%d pointers\n[ ", I_UNFM_NUM (ih));
for (j = 0; j < I_UNFM_NUM (ih); j ++) {
if (sequence_finished (prev, &num, unp[j])) {
print_sequence (fp, prev, num);
start_new_sequence (&prev, &num, unp[j]);
}
}
print_sequence (fp, prev, num);
reiserfs_warning (fp, "]\n");
}
char timebuf[256];
char * timestamp (time_t t)
{
strftime (timebuf, 256, "%m/%d/%Y %T", localtime (&t));
return timebuf;
}
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;
} 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;
}
if (alltimes)
reiserfs_warning (fp, "%s %s\n", timestamp (sd->sd_ctime), timestamp (sd->sd_atime));
reiserfs_warning (fp, "\n");
return retval;
}
/* 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)...*/
static int print_internal (FILE * fp, struct buffer_head * bh, int first, int last)
{
struct key * key;
struct disk_child * dc;
int i;
int from, to;
if (!is_internal_node (bh))
return 1;
if (first == -1) {
from = 0;
to = B_NR_ITEMS (bh);
} else {
from = first;
to = last < B_NR_ITEMS (bh) ? last : B_NR_ITEMS (bh);
}
reiserfs_warning (fp, "INTERNAL NODE (%ld) contains %b\n", bh->b_blocknr, bh);
dc = B_N_CHILD (bh, from);
reiserfs_warning (fp, "PTR %d: %y ", from, dc);
for (i = from, key = B_N_PDELIM_KEY (bh, from), dc ++; i < to; i ++, key ++, dc ++) {
reiserfs_warning (fp, "KEY %d: %20k PTR %d: %20y ", i, key, i + 1, dc);
if (i && i % 4 == 0)
reiserfs_warning (fp, "\n");
}
reiserfs_warning (fp, "\n");
return 0;
}
static int is_symlink = 0;
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;
if (!is_leaf_node (bh))
return 1;
blkh = B_BLK_HEAD (bh);
ih = B_N_PITEM_HEAD (bh,0);
reiserfs_warning (fp, "\n===================================================================\n");
reiserfs_warning (fp, "LEAF NODE (%ld) contains %b\n", bh->b_blocknr, bh);
if (!(print_mode & PRINT_LEAF_ITEMS)) {
reiserfs_warning (fp, "FIRST ITEM_KEY: %k, LAST ITEM KEY: %k\n",
&(ih->ih_key), &((ih + blkh->blk_nr_item - 1)->ih_key));
return 0;
}
if (first < 0 || first > blkh->blk_nr_item - 1)
from = 0;
else
from = first;
if (last < 0 || last > blkh->blk_nr_item)
to = blkh->blk_nr_item;
else
to = last;
reiserfs_warning (fp,
"-------------------------------------------------------------------------------\n"
"|###|type|ilen|f/sp| loc|fmt|fsck| key |\n"
"| | | |e/cn| | |need| |\n");
for (i = from; i < to; i++) {
reiserfs_warning (fp,
"-------------------------------------------------------------------------------\n"
"|%3d|%30H|\n", i, ih + i);
if (I_IS_STAT_DATA_ITEM(ih+i) && print_mode & PRINT_ITEM_DETAILS) {
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) {
print_directory_item (fp, fs, bh, ih+i);
continue;
}
if (I_IS_INDIRECT_ITEM(ih+i) && print_mode & PRINT_ITEM_DETAILS) {
print_indirect_item (fp, bh, i);
continue;
}
if (I_IS_DIRECT_ITEM(ih+i)) {
int j = 0;
if (is_symlink || print_mode & PRINT_DIRECT_ITEMS) {
reiserfs_warning (fp, "\"");
while (j < ih[i].ih_item_len) {
if (B_I_PITEM(bh,ih+i)[j] == 10)
reiserfs_warning (fp, "\\n");
else
reiserfs_warning (fp, "%c", B_I_PITEM(bh,ih+i)[j]);
j ++;
}
reiserfs_warning (fp, "\"\n");
}
continue;
}
}
reiserfs_warning (fp, "===================================================================\n");
return 0;
}
/* return 1 if this is not super block */
static int print_super_block (FILE * fp, struct buffer_head * bh)
{
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
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));
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));
return 0;
}
static int print_desc_block (FILE * fp, struct buffer_head * bh)
{
struct reiserfs_journal_desc * desc;
desc = (struct reiserfs_journal_desc *)(bh->b_data);
if (memcmp(desc->j_magic, 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);
return 0;
}
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;
va_start (args, bh);
if ( ! bh ) {
reiserfs_warning (stderr, "print_block: buffer is NULL\n");
return;
}
mode = va_arg (args, int);
first = va_arg (args, int);
last = va_arg (args, int);
if (print_desc_block (fp, bh))
if (print_super_block (fp, bh))
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);
}
void print_tb (int mode, int item_pos, int pos_in_item, struct tree_balance * tb, char * mes)
{
int h = 0;
int i;
struct buffer_head * tbSh, * tbFh;
if (!tb)
return;
printf ("\n********************** PRINT_TB for %s *******************\n", mes);
printf ("MODE=%c, ITEM_POS=%d POS_IN_ITEM=%d\n", mode, item_pos, pos_in_item);
printf ("*********************************************************************\n");
printf ("* h * S * L * R * F * FL * FR * CFL * CFR *\n");
/*
01234567890123456789012345678901234567890123456789012345678901234567890123456789
1 2 3 4 5 6 7 8
printk ("*********************************************************************\n");
*/
for (h = 0; h < sizeof(tb->insert_size) / sizeof (tb->insert_size[0]); h ++) {
if (PATH_H_PATH_OFFSET (tb->tb_path, h) <= tb->tb_path->path_length &&
PATH_H_PATH_OFFSET (tb->tb_path, h) > ILLEGAL_PATH_ELEMENT_OFFSET) {
tbSh = PATH_H_PBUFFER (tb->tb_path, h);
tbFh = PATH_H_PPARENT (tb->tb_path, h);
} else {
/* printk ("print_tb: h=%d, PATH_H_PATH_OFFSET=%d, path_length=%d\n",
h, PATH_H_PATH_OFFSET (tb->tb_path, h), tb->tb_path->path_length);*/
tbSh = 0;
tbFh = 0;
}
printf ("* %d * %3ld(%2d) * %3ld(%2d) * %3ld(%2d) * %5ld * %5ld * %5ld * %5ld * %5ld *\n",
h,
(tbSh) ? (tbSh->b_blocknr):(-1),
(tbSh) ? tbSh->b_count : -1,
(tb->L[h]) ? (tb->L[h]->b_blocknr):(-1),
(tb->L[h]) ? tb->L[h]->b_count : -1,
(tb->R[h]) ? (tb->R[h]->b_blocknr):(-1),
(tb->R[h]) ? tb->R[h]->b_count : -1,
(tbFh) ? (tbFh->b_blocknr):(-1),
(tb->FL[h]) ? (tb->FL[h]->b_blocknr):(-1),
(tb->FR[h]) ? (tb->FR[h]->b_blocknr):(-1),
(tb->CFL[h]) ? (tb->CFL[h]->b_blocknr):(-1),
(tb->CFR[h]) ? (tb->CFR[h]->b_blocknr):(-1));
}
printf ("*********************************************************************\n");
/* print balance parameters for leaf level */
h = 0;
printf ("* h * size * ln * lb * rn * rb * blkn * s0 * s1 * s1b * s2 * s2b * curb * lk * rk *\n");
printf ("* %d * %4d * %2d * %2d * %2d * %2d * %4d * %2d * %2d * %3d * %2d * %3d * %4d * %2d * %2d *\n",
h, tb->insert_size[h], tb->lnum[h], tb->lbytes, tb->rnum[h],tb->rbytes, tb->blknum[h],
tb->s0num, tb->s1num,tb->s1bytes, tb->s2num, tb->s2bytes, tb->cur_blknum, tb->lkey[h], tb->rkey[h]);
/* this prints balance parameters for non-leaf levels */
do {
h++;
printf ("* %d * %4d * %2d * * %2d * * %2d *\n",
h, tb->insert_size[h], tb->lnum[h], tb->rnum[h], tb->blknum[h]);
} while (tb->insert_size[h]);
printf ("*********************************************************************\n");
/* print FEB list (list of buffers in form (bh (b_blocknr, b_count), that will be used for new nodes) */
h = 0;
for (i = 0; i < sizeof (tb->FEB) / sizeof (tb->FEB[0]); i ++)
printf ("%s%p (%lu %d)", i == 0 ? "FEB list: " : ", ", tb->FEB[i], tb->FEB[i] ? tb->FEB[i]->b_blocknr : 0,
tb->FEB[i] ? tb->FEB[i]->b_count : 0);
printf ("\n");
printf ("********************** END OF PRINT_TB *******************\n\n");
}
static void print_bmap_block (FILE * fp, int i, struct buffer_head * bmap, int blocks, int silent)
{
int j, k;
int bits = bmap->b_size * 8;
int zeros = 0, ones = 0;
reiserfs_warning (fp, "#%d: block %lu: ", i, bmap->b_blocknr);
if (test_bit (0, bmap->b_data)) {
/* 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)) {
ones ++;
if (j == blocks - 1) {
if (!silent)
reiserfs_warning (fp, "%d)\n", j + i * bits);
goto end;
}
j++;
}
if (!silent)
reiserfs_warning (fp, "%d) Free(%d-", j - 1 + i * bits, j + i * bits);
while (!test_bit (j, bmap->b_data)) {
zeros ++;
if (j == blocks - 1) {
if (!silent)
reiserfs_warning (fp, "%d)\n", j + i * bits);
goto end;
}
j++;
}
if (!silent)
reiserfs_warning (fp, "%d) Busy(%d-", j - 1 + i * bits, j + i * bits);
j --;
end:
}
} else {
/* first block addressed by this bitmap is free */
zeros ++;
if (!silent)
reiserfs_warning (fp, "Free (%d-", i * bits);
for (j = 1; j < blocks; j ++) {
k = 0;
while (!test_bit (j, bmap->b_data)) {
k ++;
if (j == blocks - 1) {
if (!silent)
reiserfs_warning (fp, "%d)\n", j + i * bits);
zeros += k;
goto end2;
}
j++;
}
zeros += k;
if (!silent)
reiserfs_warning (fp, "%d) Busy(%d-", j - 1 + i * bits, j + i * bits);
k = 0;
while (test_bit (j, bmap->b_data)) {
ones ++;
if (j == blocks - 1) {
if (!silent)
reiserfs_warning (fp, "%d)\n", j + i * bits);
ones += k;
goto end2;
}
j++;
}
ones += k;
if (!silent)
reiserfs_warning (fp, "%d) Free(%d-", j - 1 + i * bits, j + i * bits);
j --;
end2:
}
}
reiserfs_warning (fp, "used %d, free %d\n", ones, zeros);
}
/* if silent == 1, do not print details */
void print_bmap (FILE * fp, reiserfs_filsys_t s, int silent)
{
int bmapnr = SB_BMAP_NR (s);
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);
}
/* 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 ++;
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);
}
}
}
void print_objectid_map (FILE * fp, reiserfs_filsys_t fs)
{
int i;
struct reiserfs_super_block * rs;
__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);
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);
for (i = 0; i < SB_OBJECTID_MAP_SIZE (fs); i ++) {
if (i % 2 == 0)
reiserfs_warning (fp, "busy(%u-%u) ", omap[i], 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);
}
reiserfs_warning (fp, "\nObject id array has size %d (max %d):", SB_OBJECTID_MAP_SIZE (fs),
SB_OBJECTID_MAP_MAXSIZE (fs));
for (i = 0; i < SB_OBJECTID_MAP_SIZE (fs); i ++)
reiserfs_warning (fp, "%s%u ", i % 2 ? "" : "*", 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)
{
chars[0] = (bits & S_IRUSR) ? 'r' : '-';
chars[1] = (bits & S_IWUSR) ? 'w' : '-';
chars[2] = (bits & S_IXUSR) ? 'x' : '-';
}
/* 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. */
static char
ftypelet (long int bits)
{
#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
return '?';
}
/* 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)
{
str[0] = ftypelet ((long) mode);
rwx ((mode & 0700) << 0, &str[1]);
rwx ((mode & 0070) << 3, &str[4]);
rwx ((mode & 0007) << 6, &str[7]);
}
char * st_mode2string (short unsigned int mode, char * buf)
{
mode_string (mode, buf);
buf[10] = 0;
return buf;
}
#endif
+766
View File
@@ -0,0 +1,766 @@
/*
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
#include "includes.h"
/* 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");
}
/* read bitmap blocks */
void reiserfs_read_bitmap_blocks (reiserfs_filsys_t fs)
{
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);*/
}
}
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));
}
}
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));
}
}
/* 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)
{
reiserfs_filsys_t fs;
struct buffer_head * bh;
struct reiserfs_super_block * rs;
int fd, i;
fd = open (filename, flags | O_LARGEFILE);
if (fd == -1) {
if (error)
*error = errno;
return 0;
}
fs = getmem (sizeof (*fs));
fs->s_dev = fd;
fs->s_vp = vp;
asprintf (&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) {
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;
if (is_reiser2fs_magic_string (rs) || is_reiserfs_magic_string (rs))
goto found;
/* reiserfs signature is not found at the i-th 4k block */
brelse (bh);
}
}
reiserfs_warning (stderr, "reiserfs_open: neither new nor old reiserfs format "
"found on %s\n", filename);
if (error)
*error = 0;
return fs;
found:
/* 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;
reiserfs_read_bitmap_blocks(fs);
return fs;
}
int no_reiserfs_found (reiserfs_filsys_t fs)
{
return (fs->s_blocksize == 0) ? 1 : 0;
}
int new_format (reiserfs_filsys_t fs)
{
return fs->s_sbh->b_blocknr != 2;
}
int spread_bitmaps (reiserfs_filsys_t fs)
{
return fs->s_sbh->b_blocknr != 2;
}
void reiserfs_reopen (reiserfs_filsys_t fs, int flag)
{
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");
}
int filesystem_dirty (reiserfs_filsys_t fs)
{
return fs->s_dirt;
}
void mark_filesystem_dirty (reiserfs_filsys_t fs)
{
fs->s_dirt = 1;
}
/* flush all changes made on a filesystem */
void reiserfs_flush (reiserfs_filsys_t fs)
{
flush_buffers ();
}
/* free all memory involved into manipulating with filesystem */
void reiserfs_free (reiserfs_filsys_t fs)
{
reiserfs_free_bitmap_blocks(fs);
/* release super block and memory used by filesystem handler */
brelse (SB_BUFFER_WITH_SB (fs));
free_buffers ();
free (fs->file_name);
freemem (fs);
}
void reiserfs_close (reiserfs_filsys_t fs)
{
reiserfs_flush (fs);
reiserfs_free (fs);
}
int reiserfs_new_blocknrs (reiserfs_filsys_t fs,
unsigned long * free_blocknrs, unsigned long start, int amount_needed)
{
if (fs->block_allocator)
return fs->block_allocator (fs, free_blocknrs, start, amount_needed);
die ("block allocator is not defined\n");
return 0;
}
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");
return 0;
}
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;
}
#endif
static int _search_by_key (reiserfs_filsys_t fs, struct key * key, struct path * path)
{
struct buffer_head * bh;
unsigned long block = SB_ROOT_BLOCK (fs);
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 (fs->s_dev, block, fs->s_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) {
/* 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);
}
printf ("search_by_key: you can not get here\n");
return ITEM_NOT_FOUND;
}
static int comp_dir_entries (void * p1, void * p2)
{
__u32 deh_offset;
__u32 * off1, * off2;
off1 = p1;
off2 = p2;
deh_offset = le32_to_cpu (*off1);
if (deh_offset < *off2)
return -1;
if (deh_offset > *off2)
return 1;
return 0;
}
static struct key * _get_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);
while (offset-- > FIRST_PATH_ELEMENT_OFFSET) {
if (! buffer_uptodate (PATH_OFFSET_PBUFFER (path, offset)))
die ("_get_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");
/* 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);
/* 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);
/* 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;
}
/* 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)
{
struct buffer_head * bh;
int item_pos;
struct item_head * ih;
struct key tmpkey;
if (_search_by_key (fs, key, path) == ITEM_FOUND) {
path->pos_in_item = 0;
return POSITION_FOUND;
}
bh = get_bh (path);
item_pos = get_item_pos (path);
ih = get_ih (path);
if (item_pos == 0) {
/* key is less than the smallest key in the tree */
if (not_of_one_file (&(ih->ih_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);
/* key we looked for should be here */
path->pos_in_item = 0;
return POSITION_NOT_FOUND;
}
/* take previous item */
item_pos --;
ih --;
PATH_LAST_POSITION (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 */
item_pos ++;
PATH_LAST_POSITION (path) ++;
if (item_pos < B_NR_ITEMS (bh)) {
/* next item is in the same node */
ih ++;
if (not_of_one_file (&(ih->ih_key), key)) {
/* there are no items of that directory */
path->pos_in_item = 0;
return DIRECTORY_NOT_FOUND;
}
if (!is_direntry_ih (ih))
reiserfs_panic ("_search_by_entry_key: %k is not a directory",
key);
} else {
/* next item is in right neighboring node */
struct key * next_key = _get_rkey (path);
if (next_key == 0 || not_of_one_file (next_key, key)) {
/* there are no items of that directory */
path->pos_in_item = 0;
return DIRECTORY_NOT_FOUND;
}
if (!is_direntry_key (next_key))
reiserfs_panic ("_search_by_entry_key: %k is not a directory",
key);
/* we got right delimiting key - search for it - the entry will be
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)
reiserfs_panic ("_search_by_entry_key: item corresponding to delimiting key %k not found",
&tmpkey);
}
/* 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 (_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)
return POSITION_FOUND;
return POSITION_NOT_FOUND;
}
static 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_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;
}
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) {
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 (fix_nodes (M_DELETE, &tb, 0) != CARRY_ON) {
unfix_nodes (&tb);
return 1;
}
do_balance (&tb, 0, 0, M_DELETE, 0);
return 0;
}
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)));
if (fix_nodes (M_CUT, &tb, 0) != CARRY_ON) {
unfix_nodes (&tb);
return 1;
}
do_balance (&tb, 0, 0, M_CUT, 0);
return 0;
}
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);
if (fix_nodes (M_PASTE, &tb, 0/*ih*/) != CARRY_ON)
reiserfs_panic ("reiserfs_paste_into_item: fix_nodes failed");
do_balance (&tb, 0, body, M_PASTE, 0/*zero num*/);
}
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));
if (fix_nodes (M_INSERT, &tb, ih) != CARRY_ON)
die ("reiserfs_insert_item: fix_nodes failed");
do_balance (&tb, ih, body, M_INSERT, 0/*zero num*/);
}
/*===========================================================================*/
static __u32 hash_value (reiserfs_filsys_t fs, char * name)
{
__u32 res;
if (!strcmp (name, "."))
return DOT_OFFSET;
if (!strcmp (name, ".."))
return DOT_DOT_OFFSET;
res = reiserfs_hash (fs) (name, strlen (name));
res = GET_HASH_VALUE(res);
if (res == 0)
res = 128;
return res;
}
/* 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)
{
struct key entry_key;
int retval;
int i;
INITIALIZE_PATH (path);
struct item_head * ih;
struct reiserfs_de_head * deh;
struct key * rdkey;
__u32 hash;
entry_key.k_dir_id = dir->k_dir_id;
entry_key.k_objectid = dir->k_objectid;
hash = hash_value (fs, name);
set_type_and_offset (KEY_FORMAT_1, &entry_key, hash, TYPE_DIRENTRY);
*min_gen_counter = 0;
if (_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)) {
/* all entries having the same hash were scanned */
pathrelse (&path);
return 0;
}
if (GET_GENERATION_NUMBER (deh_offset (deh)) == *min_gen_counter)
(*min_gen_counter) ++;
if (!memcmp (name_in_entry (deh, i), name, strlen (name))) {
pathrelse (&path);
return deh_objectid (deh) ? deh_objectid (deh) : 1;
}
}
rdkey = _get_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);
if (retval != POSITION_FOUND)
reiserfs_panic ("reiserfs_find_entry: wrong delimiting key in the tree");
} while (1);
return 0;
}
/* compose directory entry: dir entry head and name itself */
char * make_entry (char * entry, char * name, struct key * key, __u32 offset)
{
struct reiserfs_de_head * deh;
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);
/* 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);
memcpy ((char *)(deh + 1), name, strlen (name));
return entry;
}
/* 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)
{
struct item_head entry_ih = {{0,}, };
char * entry;
int retval;
INITIALIZE_PATH(path);
int gen_counter;
int item_len;
__u32 hash;
if (reiserfs_find_entry (fs, dir, name, &gen_counter))
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);
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)
item_len = DEH_SIZE + ROUND_UP (strlen (name));
else
item_len = DEH_SIZE + strlen (name);
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;
entry = make_entry (0, name, key, get_offset (&(entry_ih.ih_key)));
retval = _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);
reiserfs_insert_item (fs, &path, &entry_ih, entry);
break;
default:
reiserfs_panic ("reiserfs_add_entry: looking for %k (inserting name \"%s\") "
"search_by_entry_key returned %d",
&(entry_ih.ih_key), name, retval);
}
freemem (entry);
return item_len;
}
void copy_key (void * to, void * from)
{
memcpy (to, from, KEY_SIZE);
}
void copy_short_key (void * to, void * from)
{
memcpy (to, from, SHORT_KEY_SIZE);
}
void copy_item_head(void * p_v_to, void * p_v_from)
{
memcpy (p_v_to, p_v_from, IH_SIZE);
}
+475
View File
@@ -0,0 +1,475 @@
/*
* Copyright 1996, 1997, 1998 Hans Reiser, see reiserfs/README for licensing and copyright details
*/
/*
* Written by Anatoly P. Pinchuk pap@namesys.botik.ru
* Programm System Institute
* Pereslavl-Zalessky Russia
*/
/*
* This file contains functions dealing with S+tree
*
* comp_keys
* comp_short_keys
* bin_search
* get_lkey
* get_rkey
* key_in_buffer
* decrement_bcount
* decrement_counters_in_path
* pathrelse
* search_by_key
* search_for_position_by_key
* comp_items
* prepare_for_delete_or_cut
* calc_deleted_bytes_number
* init_tb_struct
* reiserfs_delete_item
* indirect_to_direct
* maybe_indirect_to_direct
* reiserfs_cut_from_item
* reiserfs_cut_dir_entry
* reiserfs_paste_into_item
* reiserfs_insert_item
*/
#include "includes.h"
/* 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 );
}
/*
Compare keys using REISERFS_SHORT_KEY_LEN fields.
Returns: -1 if key1 < key2
0 if key1 = key2
1 if key1 > key2
*/
int comp_short_keys (void * k1, 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;
for( ; n_key_length--; ++p_s_key1, ++p_s_key2 ) {
if ( *p_s_key1 < *p_s_key2 )
return -1;
if ( *p_s_key1 > *p_s_key2 )
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 retval;
struct key * k1, * k2;
k1 = p1;
k2 = p2;
retval = comp_short_keys (k1, k2);
if (retval)
return retval;
if (get_offset (k1) < get_offset (k2))
return -1;
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 (get_type (k1) > get_type (k2))
return 1;
return 0;
}
/**************************************************************************
* Binary search toolkit function *
* Search for an item in the array by the item key *
* Returns: 1 if found, 0 if not found; *
* *p_n_pos = number of the searched element if found, else the *
* number of the first element that is larger than p_v_key. *
**************************************************************************/
/* For those not familiar with binary search: n_lbound is the leftmost item that it
could be, n_rbound the rightmost item that it could be. We examine the item
halfway between n_lbound and n_rbound, and that tells us either that we can increase
n_lbound, or decrease n_rbound, or that we have found it, or if n_lbound <= n_rbound that
there are no possible items, and we have not found it. With each examination we
cut the number of possible items it could be by one more than half rounded down,
or we find it. */
inline int bin_search (
void * p_v_key, /* Key to search for. */
void * p_v_base, /* First item in the array. */
int p_n_num, /* Number of items in the array. */
int p_n_width, /* Item size in the array.
searched. Lest the reader be
confused, note that this is crafted
as a general function, and when it
is applied specifically to the array
of item headers in a node, p_n_width
is actually the item header size not
the item size. */
int * p_n_pos /* Number of the searched for element. */
) {
int n_rbound, n_lbound, n_j;
for ( n_j = ((n_rbound = p_n_num - 1) + (n_lbound = 0))/2; n_lbound <= n_rbound; n_j = (n_rbound + n_lbound)/2 )
switch( COMP_KEYS((struct key *)((char * )p_v_base + n_j * p_n_width), p_v_key) ) {
case -1: n_lbound = n_j + 1; continue;
case 1: n_rbound = n_j - 1; continue;
case 0: *p_n_pos = n_j; return ITEM_FOUND; /* Key found in the array. */
}
/* bin_search did not find given key, it returns position of key,
that is minimal and greater than the given one. */
*p_n_pos = n_lbound;
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},}};
/* Maximal possible key. It is never in the tree. */
struct key MAX_KEY = {0xffffffff, 0xffffffff, {{0xffffffff, 0xffffffff},}};
/* Get delimiting key of the buffer by looking for it in the buffers in the
path, starting from the bottom of the path, and going upwards. We must
check the path's validity at each step. If the key is not in the path,
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 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
/* 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;
/* Check whether position in the parent is correct. */
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) !=
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. */
if ( n_position )
return B_N_PDELIM_KEY(p_s_parent, n_position - 1);
}
/* 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) )
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
) {
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
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;
/* Check whether position in the parrent is correct. */
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) !=
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. */
if ( n_position != B_NR_ITEMS(p_s_parent) )
return B_N_PDELIM_KEY(p_s_parent, n_position);
}
/* 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) )
return &MAX_KEY;
return &MIN_KEY;
}
/* Check whether a key is contained in the tree rooted from a buffer at a
path. This works by looking at the left and right delimiting keys for the
buffer in the last path_element in the path. These delimiting keys are
stored at least one level above that buffer in the tree. If the buffer is
the first or last node in the tree order then one of the delimiting keys
may be absent, and in this case get_lkey and get_rkey return a special key
which is MIN_KEY or MAX_KEY. */
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. */
) {
#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 )
return 0;
if ( COMP_KEYS(p_s_key, get_rkey(p_s_chk_path, p_s_sb)) != -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 )
brelse(PATH_OFFSET_PBUFFER(p_s_search_path, n_path_offset--));
p_s_search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
}
/**************************************************************************
* Algorithm SearchByKey *
* look for item in the Disk S+Tree by its key *
* Input: p_s_sb - super block *
* p_s_key - pointer to the key to search *
* Output: true value - 1 - found, 0 - not found *
* p_s_search_path - path from the root to the needed leaf *
**************************************************************************/
/* This function fills up the path from the root to the leaf as it
descends the tree looking for the key. It uses reiserfs_bread to
try to find buffers in the cache given their block number. If it
does not find them in the cache it reads them from disk. For each
node search_by_key finds using reiserfs_bread it then uses
bin_search to look through that node. bin_search will find the
position of the block_number of the next node if it is looking
through an internal node. If it is looking through a leaf node
bin_search will find the position of the item which has key either
equal to given key, or which is the maximal key less than the given
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;
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
/* 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)) ) {
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);
/* 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
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;
}
/* 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)
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 */
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.*/
/* 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);
}
}
int bin_search_in_dir_item (struct item_head * ih, struct reiserfs_de_head * deh,
struct key * key, int * pos_in_item)
{
int rbound, lbound, j;
lbound = 0;
rbound = ih_entry_count (ih) - 1;
for (j = (rbound + lbound) / 2; lbound <= rbound; j = (rbound + lbound) / 2) {
if (get_offset (key) < deh_offset (deh + j)) {
rbound = j - 1;
continue;
}
if (get_offset (key) > deh_offset (deh + j)) {
lbound = j + 1;
continue;
}
/* key found */
*pos_in_item = j;
return POSITION_FOUND;
}
*pos_in_item = lbound;
return POSITION_NOT_FOUND;
}
+62
View File
@@ -0,0 +1,62 @@
Vendor: Hans Reiser
Distribution: Hans Reiser
Name: reiserfsprogs
Release: 1
Copyright: 2001 Hans Reiser
Group: Unsorted
Packager: anthon@mnt.org
Version: 3.x.0j
Summary: utilities belonging to the Reiser filesystem
Source: reiserfsprogs-%{version}.tar.gz
BuildRoot: /var/tmp/rpm-reiserfsprogs
%description
The reiserfsprogs package contains programs for creating (mkreiserfs),
checking and correcting any inconsistencies (reiserfsck) and resizing
(resize_reiserfs) of a reiserfs filesystem.
Authors:
--------
Hans Reiser <reiser@namesys.com>
Vitaly Fertman <vetalf@inbox.ru>
Alexander Zarochentcev <zam@namesys.com>
Vladimir Saveliev <vs@namesys.botik.ru>
%prep
%setup -q
# %patch
%build
MANDIR=$(dirname $(dirname $(man -w fsck | cut -d ' ' -f 1)))
./configure --prefix="" --mandir=$MANDIR
make all
%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
# __os_install_post is normally executed after %install disable it
%define ___build_post %{nil}
# explicitly call it now, so manpages get compressed, exec's stripped etc.
%{?__os_install_post}
%define __os_install_post %{nil}
# now we have all the files execpt for docs, but their owner is unimportant
cd $RPM_BUILD_ROOT
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
find . -type f \
| sed 's,^\.,\%attr(-\,root\,root) ,' | fgrep -v rpm-filelist >> rpm-filelist
find . -type l \
| sed 's,^\.,\%attr(-\,root\,root) ,' >> rpm-filelist
%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
%doc README
+9
View File
@@ -0,0 +1,9 @@
sbin_PROGRAMS = resize_reiserfs
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
+331
View File
@@ -0,0 +1,331 @@
# Makefile.in generated automatically by automake 1.4 from Makefile.am
# Copyright (C) 1994, 1995-8, 1999 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@
sbin_PROGRAMS = resize_reiserfs
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
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_CLEAN_FILES =
PROGRAMS = $(sbin_PROGRAMS)
DEFS = @DEFS@ -I. -I$(srcdir)
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_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 = $(resize_reiserfs_SOURCES)
OBJECTS = $(resize_reiserfs_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 resize_reiserfs/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:
resize_reiserfs: $(resize_reiserfs_OBJECTS) $(resize_reiserfs_DEPENDENCIES)
@rm -f resize_reiserfs
$(LINK) $(resize_reiserfs_LDFLAGS) $(resize_reiserfs_OBJECTS) $(resize_reiserfs_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 = resize_reiserfs
distdir: $(DISTFILES)
@for file in $(DISTFILES); do \
d=$(srcdir); \
if test -d $$d/$$file; then \
cp -pr $$/$$file $(distdir)/$$file; \
else \
test -f $(distdir)/$$file \
|| ln $$d/$$file $(distdir)/$$file 2> /dev/null \
|| cp -p $$d/$$file $(distdir)/$$file || :; \
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
resize_reiserfs.o: resize_reiserfs.c resize.h ../include/io.h \
../include/misc.h ../include/reiserfs_lib.h \
../include/reiserfs_fs.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:
+269
View File
@@ -0,0 +1,269 @@
/*
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
#include <time.h>
#include "resize.h"
static unsigned long int_node_cnt = 0, int_moved_cnt = 0;
static unsigned long leaf_node_cnt = 0, leaf_moved_cnt = 0;
static unsigned long unfm_node_cnt = 0, unfm_moved_cnt = 0;
static unsigned long total_node_cnt = 0;
static unsigned long total_moved_cnt = 0;
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;
/* abnornal exit from block reallocation process */
static void quit_resizer()
{
/* 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");
}
/* block moving */
static unsigned long move_generic_block(unsigned long block, unsigned long bnd, int h)
{
struct buffer_head * bh, * bh2;
/* primitive fsck */
if (block > rs_block_count(rs)) {
fprintf(stderr, "resize_reiserfs: invalid block number (%lu) found.\n", block);
quit_resizer();
}
/* progress bar, 3D style :) */
if (opt_verbose)
print_how_far(&total_node_cnt, blocks_used, 1, 0);
else
total_node_cnt ++;
/* infinite loop check */
if( total_node_cnt > blocks_used && !block_count_mismatch) {
fputs("resize_reiserfs: warning: block count exeeded\n",stderr);
block_count_mismatch = 1;
}
if (block < bnd) /* block will not be moved */
return 0;
/* move wrong block */
bh = bread(fs->s_dev, block, fs->s_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();
}
/* blocknr changing */
bh2 = getblk(fs->s_dev, unused_block, fs->s_blocksize);
memcpy(bh2->b_data, bh->b_data, bh2->b_size);
reiserfs_bitmap_clear_bit(bmp, block);
reiserfs_bitmap_set_bit(bmp, unused_block);
brelse(bh);
mark_buffer_uptodate(bh2,1);
mark_buffer_dirty(bh2);
bwrite(bh2);
brelse(bh2);
total_moved_cnt++;
return unused_block;
}
static unsigned long move_unformatted_block(unsigned long block, unsigned long bnd, int h)
{
unsigned long b;
unfm_node_cnt++;
b = move_generic_block(block, bnd, h);
if (b)
unfm_moved_cnt++;
return b;
}
/* recursive function processing all tree nodes */
static unsigned long move_formatted_block(unsigned long block, unsigned long bnd, int h)
{
struct buffer_head * bh;
struct item_head *ih;
unsigned long new_blocknr = 0;
int node_is_internal = 0;
int i, j;
bh = bread(fs->s_dev, block, fs->s_blocksize);
if (is_leaf_node (bh)) {
leaf_node_cnt++;
for (i=0; i < B_NR_ITEMS(bh); i++) {
ih = B_N_PITEM_HEAD(bh, i);
if (is_indirect_ih(ih)) {
__u32 * indirect;
indirect = (__u32 *)B_I_PITEM (bh, ih);
for (j = 0; j < I_UNFM_NUM(ih); j++) {
unsigned long unfm_block;
if (indirect [j] == 0) /* hole */
continue;
unfm_block = move_unformatted_block(le32_to_cpu (indirect [j]), bnd, h + 1);
if (unfm_block) {
indirect [j] = cpu_to_le32 (unfm_block);
mark_buffer_dirty(bh);
}
}
}
}
} else if (is_internal_node (bh)) { /* internal node */
int_node_cnt++;
node_is_internal = 1;
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);
if (moved_block) {
set_dc_block_number (bh, i, moved_block);
mark_buffer_dirty(bh);
}
}
} else {
die ("resize_reiserfs: block (%lu) has invalid format\n", block);
}
if (buffer_dirty(bh)) {
mark_buffer_uptodate(bh,1);
bwrite(bh);
}
brelse(bh);
new_blocknr = move_generic_block(block, bnd, h);
if (new_blocknr) {
if (node_is_internal)
int_moved_cnt++;
else
leaf_moved_cnt++;
}
return new_blocknr;
}
int shrink_fs(reiserfs_filsys_t reiserfs, unsigned long blocks)
{
unsigned long n_root_block;
unsigned int bmap_nr_new;
unsigned long int i;
fs = reiserfs;
rs = fs->s_rs;
/* warn about alpha version */
{
int c;
printf(
"You are running BETA version of reiserfs shrinker.\n"
"This version is only for testing or VERY CAREFUL use.\n"
"Backup of you data is recommended.\n\n"
"Do you want to continue? [y/N]:"
);
c = getchar();
if (c != 'y' && c != 'Y')
exit(1);
}
bmap_nr_new = (blocks - 1) / (8 * fs->s_blocksize) + 1;
/* is shrinking possible ? */
if (rs_block_count(rs) - blocks > rs_free_blocks(rs) + rs_bmap_nr(rs) - 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));
/* 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
- 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) {
printf("Processing the tree: ");
fflush(stdout);
}
n_root_block = move_formatted_block(rs_root_block(rs), blocks, 0);
if (n_root_block) {
set_root_block (rs, n_root_block);
}
if (opt_verbose)
printf ("\n\nnodes processed (moved):\n"
"int %lu (%lu),\n"
"leaves %lu (%lu),\n"
"unfm %lu (%lu),\n"
"total %lu (%lu).\n\n",
int_node_cnt, int_moved_cnt,
leaf_node_cnt, leaf_moved_cnt,
unfm_node_cnt, unfm_moved_cnt,
(unsigned long)total_node_cnt, total_moved_cnt);
if (block_count_mismatch) {
fprintf(stderr, "resize_reiserfs: data block count %lu"
" 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");
{
unsigned long l;
for (l = blocks; l < rs_block_count(rs); l++)
if (is_block_used(bmp, l))
printf("<%lu>", l);
printf("\n");
}
#endif /* 0 */
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_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);
return 0;
}
+37
View File
@@ -0,0 +1,37 @@
/*
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
#include "resize.h"
/* the front-end for kernel on-line resizer */
int resize_fs_online(char * devname, unsigned long blocks)
{
static char buf[40];
FILE * f;
struct mntent * mnt;
if ((f = setmntent (MOUNTED, "r")) == NULL)
goto fail;
while ((mnt = getmntent (f)) != NULL)
if(strcmp(devname, mnt->mnt_fsname) == 0) {
if (strcmp(mnt->mnt_type,"reiserfs"))
die ("resize_reiserfs: can\'t resize fs other than reiserfs\n");
sprintf(buf,"resize=%lu", blocks);
if (mount(mnt->mnt_fsname, mnt->mnt_dir, mnt->mnt_type,
(unsigned long)(MS_MGC_VAL | MS_REMOUNT), buf))
die ("resize_reiserfs: remount failed: %s\n", strerror(errno));
endmntent(f);
return 0;
}
fail:
die ("resize_reiserfs: can't find mount entry\n");
return 1;
}
+48
View File
@@ -0,0 +1,48 @@
/*
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
#include <asm/types.h>
#include <errno.h>
#include <stdio.h>
#include <mntent.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#if __GLIBC__ >= 2
#include <sys/mount.h>
#else
#include <linux/fs.h>
#endif
#include "io.h"
#include "misc.h"
#include "reiserfs_lib.h"
#include "../version.h"
#define print_usage_and_exit()\
die ("Usage: %s [-s[+|-]#[G|M|K]] [-fqv] device", argv[0])
/* reiserfs_resize.c */
extern struct buffer_head * g_sb_bh;
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);
+116
View File
@@ -0,0 +1,116 @@
.\" -*- nroff -*-
.\" Copyright 1996-2001 Hans Reiser.
.\"
.TH RESIZE_REISERFS 8 "March 2001" "Reiserfsprogs-3.x.0j"
.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]
] [
.B \-fqv
]
.I device
.SH DESCRIPTION
The
.B resize_reiserfs
tool resizes an unmounted reiserfs file system. It enlarges or shrinks an
reiserfs file system located on a
.I device
so that it will have
.I size
bytes or size=old_size +(\-)
.I size
bytes if the + or \- prefix is used.
If the
.B \-s
option is not specified, the filesystem will be resized to fill the
given device.
The
.I size
parameter may have one of the optional modifiers
.BR K ", " M ", " G ,
which means the
.I size
parameter is given in kilo\-, mega\-, gigabytes respectively.
.PP
The
.B resize_reiserfs
program does not manipulate the size of the device. If you wish to
enlarge a filesystem, you must make sure you expand the underlying
device first. This can be done using
.BR cfdisk (8)
for partitions, by deleting the partition and recreating it with a
larger size (assuming there is free space
.I after
the partition in question). Make sure you re\-create it with the
same starting disk cylinder as before! Otherwise, the resize operation
will certainly not work, and you may lose your entire filesystem.
.PP
The
.B resize_reiserfs
program allows to grow a reiserfs on-line if there is a free
space on block
.I device.
.PP
If you wish to shrink an reiserfs partition, first use
.B resize_reiserfs
to shrink the file system. You may then use
.BR cfdisk (8)
to shrink the device. When shrinking the size of the device, make sure
you do not make it smaller than the reduced size of the reiserfs filesystem.
.SH OPTIONS
.TP
.BR \-s\ [+|\-]\fIsize
Set the new size in bytes.
.TP
.BR \-f
Force, do not perform checks.
.TP
.BR \-q
Do not print anything but error messages.
.TP
.BR \-v
Turn on extra progress status messages (default).
.SH RETURN VALUES
0 Resizing successful.
.TP
\-1 In another case.
.SH EXAMPLES
The following example shows how to test
.B resize_reiserfs\fR.
Suppose 2Gb reiserfs filesystem is created on the device /dev/hda8
and is mounted on /mnt.
For shrinking the device we need to unmount it first, then run
.B resize_reiserfs
with a
.I size \fR parameter (in this case -1Gb):
.PP
\ df
.br
\ umount /mnt
.br
\ resize_reiserfs -s -1G /dev/hda8
.br
\ mount /dev/hda8 /mnt
.br
\ df /mnt
.SH WARNING
Note that this is a BETA program and may corrupt filesystems.
.SH AUTHOR
This version of
.B resize_reiserfs
has been written by Alexander Zarochentcev <zam@namesys.com>.
.SH BUGS
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 debugreiserfs (8)
+257
View File
@@ -0,0 +1,257 @@
/*
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
*/
/*
* Written by Alexander Zarochentcev.
*
* FS resize utility
*
*/
#include "resize.h"
int opt_force = 0;
int opt_verbose = 1; /* now "verbose" option is default */
int opt_nowrite = 0;
int opt_safe = 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
/* calculate the new fs size (in blocks) from old fs size and the string
representation of new size */
static unsigned long calc_new_fs_size(unsigned long count, int bs,
char *bytes_str)
{
long long int bytes;
unsigned long blocks;
int c;
bytes = atoll(bytes_str);
c = bytes_str[strlen(bytes_str) - 1];
switch (c) {
case 'G':
case 'g':
bytes *= 1024;
case 'M':
case 'm':
bytes *= 1024;
case 'K':
case 'k':
bytes *= 1024;
}
blocks = bytes / bs;
if (bytes_str[0] == '+' || bytes_str[0] == '-')
return (count + blocks);
return blocks;
}
/* print some fs parameters */
static void sb_report(struct reiserfs_super_block * sb1,
struct reiserfs_super_block * sb2)
{
printf(
"ReiserFS report:\n"
"blocksize %d\n"
"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));
};
/* conditional bwrite */
static int bwrite_cond (struct buffer_head * bh)
{
if(!opt_nowrite) {
mark_buffer_uptodate(bh,1);
mark_buffer_dirty(bh);
bwrite(bh);
}
return 0;
}
/* 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;
unsigned int bmap_nr_new, bmap_nr_old;
int i;
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);
/* 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;
bmap_nr_old = rs_bmap_nr(rs);
/* 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);
return 0;
}
int main(int argc, char *argv[]) {
char * bytes_count_str = NULL;
char * devname;
reiserfs_filsys_t fs;
struct reiserfs_super_block * rs;
int c;
int error;
struct reiserfs_super_block *sb_old;
unsigned long block_count_new;
print_banner ("resize_reiserfs");
while ((c = getopt(argc, argv, "fvcqs:")) != EOF) {
switch (c) {
case 's' :
if (!optarg)
die("%s: Missing argument to -s option", argv[0]);
bytes_count_str = optarg;
break;
case 'f':
opt_force = 1;
break;
case 'v':
opt_verbose++;
break;
case 'n':
/* no nowrite option at this moment */
/* opt_nowrite = 1; */
break;
case 'c':
opt_safe = 1;
break;
case 'q':
opt_verbose = 0;
break;
default:
print_usage_and_exit ();
}
}
if (optind == argc )
print_usage_and_exit();
devname = argv[optind];
fs = reiserfs_open(devname, O_RDONLY, &error, 0);
if (!fs)
die ("%s: can not open '%s': %s", argv[0], devname, strerror(error));
if (no_reiserfs_found (fs)) {
die ("resize_reiserfs: no reiserfs found on the device");
}
if (!spread_bitmaps (fs)) {
die ("resize_reiserfs: cannot resize reiserfs in old (not spread bitmap) format.\n");
}
rs = fs->s_rs;
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);
} else { /* use whole device */
block_count_new = count_blocks(devname, fs->s_blocksize, -1);
}
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(!valid_offset(fs->s_dev, (loff_t) block_count_new * fs->s_blocksize - 1))
die ("%s: %s too small", argv[0], devname);
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);
}
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);
if(opt_verbose) {
sb_report(rs, sb_old);
freemem(sb_old);
}
set_state (rs, REISERFS_VALID_FS);
bwrite_cond(SB_BUFFER_WITH_SB(fs));
if (opt_verbose) {
printf("\nSyncing..");
fflush(stdout);
}
reiserfs_close (fs);
if (opt_verbose)
printf("done\n");
return 0;
}
+9
View File
@@ -0,0 +1,9 @@
/*
* Copyright 2000 Hans Reiser
*/
#define REISERFSPROGS_VERSION "3.x.0j"
#define print_banner(prog) \
fprintf (stderr, "\n<-------------%s, 2001------------->\nreiserfsprogs %s\n", \
prog, REISERFSPROGS_VERSION)