Imported reiserfsprogs-3.6.20
This commit is contained in:
1 parent
0ed773997f
commit
dac518d099
189 files changed
+43353
-29787
No files matched your search
@@ -1,5 +0,0 @@
|
||||
noinst_LIBRARIES = libmisc.a
|
||||
|
||||
libmisc_a_SOURCES = io.c misc.c
|
||||
##reiserfs.c
|
||||
|
||||
-375
@@ -1,375 +0,0 @@
|
||||
# Makefile.in generated by automake 1.7.6 from Makefile.am.
|
||||
# @configure_input@
|
||||
|
||||
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
|
||||
# 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.
|
||||
|
||||
@SET_MAKE@
|
||||
|
||||
srcdir = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
VPATH = @srcdir@
|
||||
pkgdatadir = $(datadir)/@PACKAGE@
|
||||
pkglibdir = $(libdir)/@PACKAGE@
|
||||
pkgincludedir = $(includedir)/@PACKAGE@
|
||||
top_builddir = ..
|
||||
|
||||
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
|
||||
INSTALL = @INSTALL@
|
||||
install_sh_DATA = $(install_sh) -c -m 644
|
||||
install_sh_PROGRAM = $(install_sh) -c
|
||||
install_sh_SCRIPT = $(install_sh) -c
|
||||
INSTALL_HEADER = $(INSTALL_DATA)
|
||||
transform = $(program_transform_name)
|
||||
NORMAL_INSTALL = :
|
||||
PRE_INSTALL = :
|
||||
POST_INSTALL = :
|
||||
NORMAL_UNINSTALL = :
|
||||
PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
host_triplet = @host@
|
||||
ACLOCAL = @ACLOCAL@
|
||||
AMDEP_FALSE = @AMDEP_FALSE@
|
||||
AMDEP_TRUE = @AMDEP_TRUE@
|
||||
AMTAR = @AMTAR@
|
||||
AUTOCONF = @AUTOCONF@
|
||||
AUTOHEADER = @AUTOHEADER@
|
||||
AUTOMAKE = @AUTOMAKE@
|
||||
AWK = @AWK@
|
||||
CC = @CC@
|
||||
CCDEPMODE = @CCDEPMODE@
|
||||
CFLAGS = @CFLAGS@
|
||||
CPP = @CPP@
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
EGREP = @EGREP@
|
||||
EXEEXT = @EXEEXT@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LIBOBJS = @LIBOBJS@
|
||||
LIBS = @LIBS@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAINT = @MAINT@
|
||||
MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
|
||||
MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
OBJEXT = @OBJEXT@
|
||||
PACKAGE = @PACKAGE@
|
||||
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
|
||||
PACKAGE_NAME = @PACKAGE_NAME@
|
||||
PACKAGE_STRING = @PACKAGE_STRING@
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
PACKAGE_VERSION = @PACKAGE_VERSION@
|
||||
PATH_SEPARATOR = @PATH_SEPARATOR@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
UUID_LIBS = @UUID_LIBS@
|
||||
VERSION = @VERSION@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_RANLIB = @ac_ct_RANLIB@
|
||||
ac_ct_STRIP = @ac_ct_STRIP@
|
||||
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
|
||||
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
|
||||
am__include = @am__include@
|
||||
am__leading_dot = @am__leading_dot@
|
||||
am__quote = @am__quote@
|
||||
bindir = @bindir@
|
||||
build = @build@
|
||||
build_alias = @build_alias@
|
||||
build_cpu = @build_cpu@
|
||||
build_os = @build_os@
|
||||
build_vendor = @build_vendor@
|
||||
datadir = @datadir@
|
||||
exec_prefix = @exec_prefix@
|
||||
host = @host@
|
||||
host_alias = @host_alias@
|
||||
host_cpu = @host_cpu@
|
||||
host_os = @host_os@
|
||||
host_vendor = @host_vendor@
|
||||
includedir = @includedir@
|
||||
infodir = @infodir@
|
||||
install_sh = @install_sh@
|
||||
libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localstatedir = @localstatedir@
|
||||
mandir = @mandir@
|
||||
oldincludedir = @oldincludedir@
|
||||
prefix = @prefix@
|
||||
program_transform_name = @program_transform_name@
|
||||
sbindir = @sbindir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
sysconfdir = @sysconfdir@
|
||||
target_alias = @target_alias@
|
||||
noinst_LIBRARIES = libmisc.a
|
||||
|
||||
libmisc_a_SOURCES = io.c misc.c
|
||||
subdir = lib
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
|
||||
CONFIG_HEADER = $(top_builddir)/include/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
LIBRARIES = $(noinst_LIBRARIES)
|
||||
|
||||
libmisc_a_AR = $(AR) cru
|
||||
libmisc_a_LIBADD =
|
||||
am_libmisc_a_OBJECTS = io.$(OBJEXT) misc.$(OBJEXT)
|
||||
libmisc_a_OBJECTS = $(am_libmisc_a_OBJECTS)
|
||||
|
||||
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include
|
||||
depcomp = $(SHELL) $(top_srcdir)/depcomp
|
||||
am__depfiles_maybe = depfiles
|
||||
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/io.Po ./$(DEPDIR)/misc.Po
|
||||
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
|
||||
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
|
||||
CCLD = $(CC)
|
||||
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
|
||||
DIST_SOURCES = $(libmisc_a_SOURCES)
|
||||
DIST_COMMON = Makefile.am Makefile.in
|
||||
SOURCES = $(libmisc_a_SOURCES)
|
||||
|
||||
all: all-am
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o .obj
|
||||
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
|
||||
cd $(top_srcdir) && \
|
||||
$(AUTOMAKE) --gnu lib/Makefile
|
||||
Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
|
||||
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
|
||||
|
||||
AR = ar
|
||||
|
||||
clean-noinstLIBRARIES:
|
||||
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
|
||||
libmisc.a: $(libmisc_a_OBJECTS) $(libmisc_a_DEPENDENCIES)
|
||||
-rm -f libmisc.a
|
||||
$(libmisc_a_AR) libmisc.a $(libmisc_a_OBJECTS) $(libmisc_a_LIBADD)
|
||||
$(RANLIB) libmisc.a
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT) core *.core
|
||||
|
||||
distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/io.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc.Po@am__quote@
|
||||
|
||||
distclean-depend:
|
||||
-rm -rf ./$(DEPDIR)
|
||||
|
||||
.c.o:
|
||||
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
|
||||
@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
|
||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
|
||||
@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
|
||||
@am__fastdepCC_TRUE@ fi
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$<
|
||||
|
||||
.c.obj:
|
||||
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
|
||||
@am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \
|
||||
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
|
||||
@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
|
||||
@am__fastdepCC_TRUE@ fi
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
|
||||
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
|
||||
@am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`
|
||||
uninstall-info-am:
|
||||
|
||||
ETAGS = etags
|
||||
ETAGSFLAGS =
|
||||
|
||||
CTAGS = ctags
|
||||
CTAGSFLAGS =
|
||||
|
||||
tags: TAGS
|
||||
|
||||
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
mkid -fID $$unique
|
||||
|
||||
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|
||||
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
ctags: CTAGS
|
||||
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
|
||||
$(TAGS_FILES) $(LISP)
|
||||
tags=; \
|
||||
here=`pwd`; \
|
||||
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
|
||||
unique=`for i in $$list; do \
|
||||
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
|
||||
done | \
|
||||
$(AWK) ' { files[$$0] = 1; } \
|
||||
END { for (i in files) print i; }'`; \
|
||||
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|
||||
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
|
||||
$$tags $$unique
|
||||
|
||||
GTAGS:
|
||||
here=`$(am__cd) $(top_builddir) && pwd` \
|
||||
&& cd $(top_srcdir) \
|
||||
&& gtags -i $(GTAGS_ARGS) $$here
|
||||
|
||||
distclean-tags:
|
||||
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
|
||||
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
|
||||
|
||||
top_distdir = ..
|
||||
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
|
||||
|
||||
distdir: $(DISTFILES)
|
||||
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
|
||||
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
|
||||
list='$(DISTFILES)'; for file in $$list; do \
|
||||
case $$file in \
|
||||
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
|
||||
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
|
||||
esac; \
|
||||
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
|
||||
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
|
||||
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
|
||||
dir="/$$dir"; \
|
||||
$(mkinstalldirs) "$(distdir)$$dir"; \
|
||||
else \
|
||||
dir=''; \
|
||||
fi; \
|
||||
if test -d $$d/$$file; then \
|
||||
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
|
||||
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
|
||||
fi; \
|
||||
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
|
||||
else \
|
||||
test -f $(distdir)/$$file \
|
||||
|| cp -p $$d/$$file $(distdir)/$$file \
|
||||
|| exit 1; \
|
||||
fi; \
|
||||
done
|
||||
check-am: all-am
|
||||
check: check-am
|
||||
all-am: Makefile $(LIBRARIES)
|
||||
|
||||
installdirs:
|
||||
install: install-am
|
||||
install-exec: install-exec-am
|
||||
install-data: install-data-am
|
||||
uninstall: uninstall-am
|
||||
|
||||
install-am: all-am
|
||||
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
|
||||
|
||||
installcheck: installcheck-am
|
||||
install-strip:
|
||||
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
|
||||
INSTALL_STRIP_FLAG=-s \
|
||||
`test -z '$(STRIP)' || \
|
||||
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
|
||||
mostlyclean-generic:
|
||||
|
||||
clean-generic:
|
||||
|
||||
distclean-generic:
|
||||
-rm -f Makefile $(CONFIG_CLEAN_FILES)
|
||||
|
||||
maintainer-clean-generic:
|
||||
@echo "This command is intended for maintainers to use"
|
||||
@echo "it deletes files that may require special tools to rebuild."
|
||||
clean: clean-am
|
||||
|
||||
clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am
|
||||
|
||||
distclean: distclean-am
|
||||
|
||||
distclean-am: clean-am distclean-compile distclean-depend \
|
||||
distclean-generic distclean-tags
|
||||
|
||||
dvi: dvi-am
|
||||
|
||||
dvi-am:
|
||||
|
||||
info: info-am
|
||||
|
||||
info-am:
|
||||
|
||||
install-data-am:
|
||||
|
||||
install-exec-am:
|
||||
|
||||
install-info: install-info-am
|
||||
|
||||
install-man:
|
||||
|
||||
installcheck-am:
|
||||
|
||||
maintainer-clean: maintainer-clean-am
|
||||
|
||||
maintainer-clean-am: distclean-am maintainer-clean-generic
|
||||
|
||||
mostlyclean: mostlyclean-am
|
||||
|
||||
mostlyclean-am: mostlyclean-compile mostlyclean-generic
|
||||
|
||||
pdf: pdf-am
|
||||
|
||||
pdf-am:
|
||||
|
||||
ps: ps-am
|
||||
|
||||
ps-am:
|
||||
|
||||
uninstall-am: uninstall-info-am
|
||||
|
||||
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
|
||||
clean-noinstLIBRARIES ctags distclean distclean-compile \
|
||||
distclean-depend distclean-generic distclean-tags distdir dvi \
|
||||
dvi-am info info-am install install-am install-data \
|
||||
install-data-am install-exec install-exec-am install-info \
|
||||
install-info-am install-man install-strip installcheck \
|
||||
installcheck-am installdirs maintainer-clean \
|
||||
maintainer-clean-generic mostlyclean mostlyclean-compile \
|
||||
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
|
||||
uninstall-am uninstall-info-am
|
||||
|
||||
# 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:
|
||||
@@ -1,960 +0,0 @@
|
||||
/*
|
||||
* Copyright 1996-2004 by Hans Reiser, licensing governed by
|
||||
* reiserfsprogs/README
|
||||
*/
|
||||
|
||||
#include "io.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
void check_memory_msg (void) {
|
||||
fprintf(stderr,
|
||||
"\nThe problem has occurred looks like a hardware problem (perhaps\n"
|
||||
"memory). Send us the bug report only if the second run dies at\n"
|
||||
"the same place with the same block number.\n");
|
||||
}
|
||||
|
||||
void check_hd_msg (void) {
|
||||
fprintf(stderr,
|
||||
"\nThe problem has occurred looks like a hardware problem. If you have\n"
|
||||
"bad blocks, we advise you to get a new hard drive, because once you\n"
|
||||
"get one bad block that the disk drive internals cannot hide from\n"
|
||||
"your sight,the chances of getting more are generally said to become\n"
|
||||
"much higher (precise statistics are unknown to us), and this disk\n"
|
||||
"drive is probably not expensive enough for you to you to risk your\n"
|
||||
"time and data on it. If you don't want to follow that follow that\n"
|
||||
"advice then if you have just a few bad blocks, try writing to the\n"
|
||||
"bad blocks and see if the drive remaps the bad blocks (that means\n"
|
||||
"it takes a block it has in reserve and allocates it for use for\n"
|
||||
"of that block number). If it cannot remap the block, use badblock\n"
|
||||
"option (-B) with reiserfs utils to handle this block correctly.\n");
|
||||
}
|
||||
|
||||
static int is_bad_block (unsigned long block)
|
||||
{
|
||||
#ifdef IO_FAILURE_EMULATION
|
||||
|
||||
/* this array similates bad blocks on the device */
|
||||
unsigned long bad_blocks [] =
|
||||
{
|
||||
8208, 8209, 8210
|
||||
/*, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19*/
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sizeof (bad_blocks) / sizeof (bad_blocks[0]); i ++)
|
||||
if (bad_blocks [i] == block)
|
||||
return 1;
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* All buffers are in double linked cycled list. If getblk found buffer with
|
||||
wanted block number in hash queue it moves buffer to the end of list. */
|
||||
|
||||
static int g_nr_buffers;
|
||||
|
||||
|
||||
static unsigned long buffers_memory;
|
||||
|
||||
/* create buffers until we spend this fraction of system memory, this
|
||||
** is a hard limit on the amount of buffer ram used
|
||||
*/
|
||||
#define BUFFER_MEMORY_FRACTION 10
|
||||
|
||||
/* number of bytes in local buffer cache before we start forcing syncs
|
||||
** of dirty data and reusing unused buffers instead of allocating new
|
||||
** ones. If a flush doesn't find reusable buffers, new ones are
|
||||
** still allocated up to the BUFFER_MEMORY_FRACTION percentage
|
||||
**
|
||||
*/
|
||||
#define BUFFER_SOFT_LIMIT (500 * 1024)
|
||||
static unsigned long buffer_soft_limit = BUFFER_SOFT_LIMIT;
|
||||
|
||||
|
||||
#define NR_HASH_QUEUES 4096
|
||||
static struct buffer_head * g_a_hash_queues [NR_HASH_QUEUES];
|
||||
static struct buffer_head * Buffer_list_head;
|
||||
static struct buffer_head * g_free_buffers = NULL ;
|
||||
static struct buffer_head * g_buffer_heads;
|
||||
static int buffer_hits = 0 ;
|
||||
static int buffer_misses = 0 ;
|
||||
static int buffer_reads = 0 ;
|
||||
static int buffer_writes = 0 ;
|
||||
|
||||
|
||||
|
||||
static void _show_buffers(struct buffer_head **list, int dev, unsigned long size) {
|
||||
int all = 0;
|
||||
int dirty = 0;
|
||||
int in_use = 0; /* count != 0 */
|
||||
int free = 0;
|
||||
struct buffer_head * next;
|
||||
|
||||
next = *list;
|
||||
if (!next)
|
||||
return ;
|
||||
|
||||
for (;;) {
|
||||
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 == *list)
|
||||
break;
|
||||
}
|
||||
|
||||
printf("show_buffers (dev %d, size %lu): free %d, count != 0 %d, dirty %d, "
|
||||
"all %d\n", dev, size, free, in_use, dirty, all);
|
||||
}
|
||||
|
||||
|
||||
static void show_buffers (int dev, int size)
|
||||
{
|
||||
_show_buffers(&Buffer_list_head, dev, size) ;
|
||||
_show_buffers(&g_free_buffers, dev, size) ;
|
||||
}
|
||||
|
||||
|
||||
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 == -1) ? */
|
||||
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 **list,
|
||||
struct buffer_head * bh)
|
||||
{
|
||||
struct buffer_head * last = 0;
|
||||
|
||||
if (bh->b_prev || bh->b_next)
|
||||
die ("put_buffer_list_end: buffer list corrupted");
|
||||
|
||||
if (*list == 0) {
|
||||
bh->b_next = bh;
|
||||
bh->b_prev = bh;
|
||||
*list = bh;
|
||||
} else {
|
||||
last = (*list)->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 **list,
|
||||
struct buffer_head * bh)
|
||||
{
|
||||
if (bh == bh->b_next) {
|
||||
*list = 0;
|
||||
} else {
|
||||
bh->b_prev->b_next = bh->b_next;
|
||||
bh->b_next->b_prev = bh->b_prev;
|
||||
if (bh == *list)
|
||||
*list = bh->b_next;
|
||||
}
|
||||
|
||||
bh->b_next = bh->b_prev = 0;
|
||||
}
|
||||
|
||||
|
||||
static void put_buffer_list_head (struct buffer_head **list,
|
||||
struct buffer_head * bh)
|
||||
{
|
||||
put_buffer_list_end (list, bh);
|
||||
*list = bh;
|
||||
}
|
||||
|
||||
/*
|
||||
#include <sys/mman.h>
|
||||
|
||||
static size_t estimate_memory_amount (void)
|
||||
{
|
||||
size_t len = 1;
|
||||
size_t max = 0;
|
||||
void * addr;
|
||||
|
||||
while (len > 0) {
|
||||
addr = mmap (0, len, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (addr == MAP_FAILED) {
|
||||
if (errno != ENOMEM)
|
||||
die ("mmap failed: %s\n", strerror(errno));
|
||||
break;
|
||||
}
|
||||
if (mlock (addr, len) != 0) {
|
||||
if (errno == EPERM)
|
||||
die ("No permission to run mlock");
|
||||
break;
|
||||
}
|
||||
|
||||
munlock (addr, len);
|
||||
munmap (addr, len);
|
||||
max = len;
|
||||
len *= 2;
|
||||
}
|
||||
|
||||
// * If we've looped, we don't want to return 0, we want to return the
|
||||
// * last successful len before we looped. In the event that mmap/mlock
|
||||
// * failed for len = 1, max will still be 0, so we don't get an invalid
|
||||
// * result
|
||||
return max;
|
||||
}
|
||||
*/
|
||||
|
||||
#define GROW_BUFFERS__NEW_BUFERS_PER_CALL 10
|
||||
|
||||
/* creates number of new buffers and insert them into head of buffer list */
|
||||
static int grow_buffers (int size)
|
||||
{
|
||||
int i;
|
||||
struct buffer_head * bh, * tmp;
|
||||
|
||||
|
||||
/* 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 = -1;
|
||||
tmp->b_size = size;
|
||||
put_buffer_list_head (&g_free_buffers, tmp);
|
||||
}
|
||||
buffers_memory += GROW_BUFFERS__NEW_BUFERS_PER_CALL * size;
|
||||
g_nr_buffers += GROW_BUFFERS__NEW_BUFERS_PER_CALL;
|
||||
return GROW_BUFFERS__NEW_BUFERS_PER_CALL;
|
||||
}
|
||||
|
||||
|
||||
struct buffer_head *find_buffer(int dev, unsigned long block, unsigned long 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;
|
||||
}
|
||||
|
||||
|
||||
static struct buffer_head * get_free_buffer (struct buffer_head **list,
|
||||
unsigned long size)
|
||||
{
|
||||
struct buffer_head * next;
|
||||
|
||||
next = *list;
|
||||
if (!next)
|
||||
return 0;
|
||||
|
||||
for (;;) {
|
||||
if (!next)
|
||||
die ("get_free_buffer: buffer list is corrupted");
|
||||
if (next->b_count == 0 && buffer_clean (next) && next->b_size == size) {
|
||||
remove_from_hash_queue (next);
|
||||
remove_from_buffer_list (list, next);
|
||||
return next;
|
||||
}
|
||||
next = next->b_next;
|
||||
if (next == *list)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* to_write == 0 when all blocks have to be flushed. Otherwise - write only
|
||||
buffers with b_count == 0 */
|
||||
static int sync_buffers (struct buffer_head **list, int dev, int to_write) {
|
||||
struct buffer_head * next;
|
||||
int written = 0;
|
||||
|
||||
|
||||
restart:
|
||||
next = *list;
|
||||
if (!next)
|
||||
return 0;
|
||||
for (;;) {
|
||||
if (!next)
|
||||
die ("sync_buffers: buffer list is corrupted");
|
||||
|
||||
if (next->b_dev == dev && buffer_dirty (next) && buffer_uptodate (next)) {
|
||||
if ((to_write == 0 || next->b_count == 0) && !buffer_do_not_flush (next)) {
|
||||
bwrite (next);
|
||||
}
|
||||
}
|
||||
|
||||
/* if this buffer is reusable, put it onto the end of the free list */
|
||||
if (next->b_count == 0 && buffer_clean(next)) {
|
||||
remove_from_hash_queue (next);
|
||||
remove_from_buffer_list (list, next);
|
||||
put_buffer_list_end (&g_free_buffers, next);
|
||||
written++ ;
|
||||
if (written == to_write)
|
||||
return written;
|
||||
goto restart;
|
||||
}
|
||||
if (to_write && written >= to_write)
|
||||
return written;
|
||||
|
||||
next = next->b_next;
|
||||
if (next == *list)
|
||||
break;
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
|
||||
void flush_buffers (int dev)
|
||||
{
|
||||
if (dev == -1)
|
||||
die ("flush_buffers: device is not specified");
|
||||
|
||||
sync_buffers (&Buffer_list_head, dev, 0/*all*/);
|
||||
buffer_soft_limit = BUFFER_SOFT_LIMIT;
|
||||
}
|
||||
|
||||
|
||||
struct buffer_head * getblk (int dev, unsigned long block, int size)
|
||||
{
|
||||
struct buffer_head * bh;
|
||||
|
||||
bh = find_buffer (dev, block, size);
|
||||
if (bh) {
|
||||
/* move the buffer to the end of list */
|
||||
|
||||
/*checkmem (bh->b_data, bh->b_size);*/
|
||||
|
||||
remove_from_buffer_list (&Buffer_list_head, bh);
|
||||
put_buffer_list_end (&Buffer_list_head, bh);
|
||||
bh->b_count ++;
|
||||
buffer_hits++ ;
|
||||
return bh;
|
||||
}
|
||||
buffer_misses++ ;
|
||||
|
||||
bh = get_free_buffer (&g_free_buffers, size);
|
||||
if (bh == NULL) {
|
||||
if (buffers_memory >= buffer_soft_limit) {
|
||||
if (sync_buffers (&Buffer_list_head, dev, 32) == 0) {
|
||||
grow_buffers(size);
|
||||
buffer_soft_limit = buffers_memory +
|
||||
GROW_BUFFERS__NEW_BUFERS_PER_CALL * size;
|
||||
}
|
||||
} else {
|
||||
if (grow_buffers(size) == 0)
|
||||
sync_buffers (&Buffer_list_head, dev, 32);
|
||||
}
|
||||
|
||||
bh = get_free_buffer (&g_free_buffers, size);
|
||||
if (bh == NULL) {
|
||||
show_buffers (dev, size);
|
||||
die ("getblk: no free buffers after grow_buffers "
|
||||
"and refill (%d)", g_nr_buffers);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
misc_clear_bit(BH_Dirty, &bh->b_state);
|
||||
misc_clear_bit(BH_Uptodate, &bh->b_state);
|
||||
|
||||
put_buffer_list_end (&Buffer_list_head, bh);
|
||||
insert_into_hash_queue (bh);
|
||||
/*checkmem (bh->b_data, bh->b_size);*/
|
||||
|
||||
return bh;
|
||||
}
|
||||
|
||||
|
||||
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, get_mem_size (bh->b_data));*/
|
||||
|
||||
bh->b_count --;
|
||||
}
|
||||
|
||||
|
||||
void bforget (struct buffer_head * bh)
|
||||
{
|
||||
if (bh) {
|
||||
bh->b_state = 0;
|
||||
brelse (bh);
|
||||
remove_from_hash_queue (bh);
|
||||
remove_from_buffer_list(&Buffer_list_head, bh);
|
||||
put_buffer_list_head(&Buffer_list_head, bh);
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns 0 on success; 1 - end of file; 0 - OK. */
|
||||
static int f_read(struct buffer_head * bh)
|
||||
{
|
||||
unsigned long long offset;
|
||||
ssize_t bytes;
|
||||
|
||||
buffer_reads++ ;
|
||||
|
||||
offset = (unsigned long long)bh->b_size * bh->b_blocknr;
|
||||
if (lseek (bh->b_dev, offset, SEEK_SET) < 0)
|
||||
return -1;
|
||||
|
||||
bytes = read (bh->b_dev, bh->b_data, bh->b_size);
|
||||
|
||||
return bytes < 0 ? -1 : (bytes != (ssize_t)bh->b_size ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
struct buffer_head * bread (int dev, unsigned long block, size_t size)
|
||||
{
|
||||
struct buffer_head * bh;
|
||||
int ret;
|
||||
|
||||
if (is_bad_block (block))
|
||||
return 0;
|
||||
|
||||
bh = getblk (dev, block, size);
|
||||
|
||||
/*checkmem (bh->b_data, get_mem_size(bh->b_data));*/
|
||||
|
||||
if (buffer_uptodate (bh))
|
||||
return bh;
|
||||
|
||||
ret = f_read(bh);
|
||||
|
||||
if (ret > 0) {
|
||||
die ("%s: End of file, cannot read the block (%lu).\n",
|
||||
__FUNCTION__, block);
|
||||
} else if (ret < 0) {
|
||||
/* BAD BLOCK LIST SUPPORT
|
||||
* die ("%s: Cannot read a block # %lu. Specify list of badblocks\n",*/
|
||||
|
||||
if (errno == EIO) {
|
||||
check_hd_msg();
|
||||
die ("%s: Cannot read the block (%lu): (%s).\n",
|
||||
__FUNCTION__, block, strerror(errno));
|
||||
} else {
|
||||
fprintf (stderr, "%s: Cannot read the block (%lu): (%s).\n",
|
||||
__FUNCTION__, block, strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
mark_buffer_uptodate (bh, 0);
|
||||
return bh;
|
||||
}
|
||||
|
||||
#define ROLLBACK_FILE_START_MAGIC "_RollBackFileForReiserfsFSCK"
|
||||
|
||||
static struct block_handler * rollback_blocks_array;
|
||||
static __u32 rollback_blocks_number = 0;
|
||||
static FILE * s_rollback_file = 0;
|
||||
static FILE * log_file;
|
||||
static int do_rollback = 0;
|
||||
|
||||
static char * rollback_data;
|
||||
static int rollback_blocksize;
|
||||
|
||||
void init_rollback_file (char * rollback_file, int *blocksize, FILE * log) {
|
||||
char * string;
|
||||
struct stat buf;
|
||||
|
||||
if (rollback_file == NULL)
|
||||
return;
|
||||
|
||||
stat(rollback_file, &buf);
|
||||
|
||||
s_rollback_file = fopen (rollback_file, "w+");
|
||||
if (s_rollback_file == NULL) {
|
||||
fprintf (stderr, "Cannot create file %s, work without a rollback file\n", rollback_file);
|
||||
return;
|
||||
}
|
||||
|
||||
rollback_blocksize = *blocksize;
|
||||
|
||||
string = ROLLBACK_FILE_START_MAGIC;
|
||||
fwrite (string, 28, 1, s_rollback_file);
|
||||
fwrite (&rollback_blocksize, sizeof (rollback_blocksize), 1, s_rollback_file);
|
||||
fwrite (&rollback_blocks_number, sizeof (rollback_blocks_number), 1, s_rollback_file);
|
||||
fflush(s_rollback_file);
|
||||
|
||||
rollback_data = getmem(rollback_blocksize);
|
||||
|
||||
// printf("\ncheckmem1");
|
||||
// fflush (stdout);
|
||||
// checkmem (rollback_data, get_mem_size((char *)rollback_data));
|
||||
// printf(" OK");
|
||||
|
||||
log_file = log;
|
||||
if (log_file)
|
||||
fprintf (log_file, "rollback: file (%s) initialize\n", rollback_file);
|
||||
|
||||
do_rollback = 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void erase_rollback_file (char * rollback_file) {
|
||||
close_rollback_file ();
|
||||
unlink (rollback_file);
|
||||
}
|
||||
#endif
|
||||
|
||||
int open_rollback_file (char * rollback_file, FILE * log) {
|
||||
char string [28];
|
||||
struct stat buf;
|
||||
|
||||
if (rollback_file == NULL)
|
||||
return -1;
|
||||
|
||||
if (stat(rollback_file, &buf)) {
|
||||
fprintf (stderr, "Cannot stat rollback file (%s)\n", rollback_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
s_rollback_file = fopen (rollback_file, "r+");
|
||||
if (s_rollback_file == NULL) {
|
||||
fprintf (stderr, "Cannot open file (%s)\n", rollback_file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fread (string, 28, 1, s_rollback_file);
|
||||
if (!strcmp (string, ROLLBACK_FILE_START_MAGIC)) {
|
||||
fprintf (stderr, "Specified file (%s) does not look like a rollback file\n", rollback_file);
|
||||
fclose (s_rollback_file);
|
||||
s_rollback_file = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fread (&rollback_blocksize, sizeof (rollback_blocksize), 1, s_rollback_file);
|
||||
|
||||
if (rollback_blocksize <= 0) {
|
||||
fprintf(stderr, "rollback: wrong rollback blocksize, exit\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_file = log;
|
||||
if (log_file)
|
||||
fprintf (log_file, "rollback: file (%s) opened\n", rollback_file);
|
||||
|
||||
do_rollback = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void close_rollback_file () {
|
||||
if (s_rollback_file == 0)
|
||||
return;
|
||||
|
||||
if (!do_rollback) {
|
||||
if (fseek (s_rollback_file, 28 + sizeof(int), SEEK_SET) == (loff_t)-1)
|
||||
return;
|
||||
fwrite (&rollback_blocks_number, sizeof (rollback_blocksize), 1, s_rollback_file);
|
||||
if (log_file != 0)
|
||||
fprintf (log_file, "rollback: %d blocks backed up\n", rollback_blocks_number);
|
||||
}
|
||||
|
||||
fclose (s_rollback_file);
|
||||
|
||||
freemem (rollback_data);
|
||||
freemem (rollback_blocks_array);
|
||||
|
||||
// fprintf (stdout, "rollback: (%u) blocks saved, \n", rollback_blocks_number);
|
||||
|
||||
/* for (i = 0; i < rollback_blocks_number; i++)
|
||||
fprintf(stdout, "device (%Lu), block number (%u)\n",
|
||||
rollback_blocks_array [i].device,
|
||||
rollback_blocks_array [i].blocknr);
|
||||
fprintf(stdout, "\n");
|
||||
*/
|
||||
}
|
||||
|
||||
void do_fsck_rollback (int fd_device, int fd_journal_device, FILE * progress) {
|
||||
long long int offset;
|
||||
|
||||
struct stat buf;
|
||||
int descriptor;
|
||||
ssize_t retval;
|
||||
int count_failed = 0;
|
||||
int count_rollbacked = 0;
|
||||
|
||||
int b_dev;
|
||||
int n_dev = 0;
|
||||
int n_journal_dev = 0;
|
||||
unsigned long total, done = 0;
|
||||
|
||||
if (fd_device == 0) {
|
||||
fprintf(stderr, "rollback: unspecified device, exit\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (fd_journal_device) {
|
||||
if (!fstat (fd_journal_device, &buf)) {
|
||||
n_journal_dev = buf.st_rdev;
|
||||
} else {
|
||||
fprintf(stderr, "rollback: specified journal device cannot be stated\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (!fstat (fd_device, &buf)) {
|
||||
n_dev = buf.st_rdev;
|
||||
} else {
|
||||
fprintf(stderr, "rollback: specified device cannot be stated, exit\n");
|
||||
return;
|
||||
}
|
||||
|
||||
rollback_data = getmem (rollback_blocksize);
|
||||
// printf("\ncheckmem2");
|
||||
// fflush (stdout);
|
||||
// checkmem (rollback_data, get_mem_size((char *)rollback_data));
|
||||
// printf(" OK");
|
||||
|
||||
fread (&rollback_blocks_number, sizeof (rollback_blocks_number), 1, s_rollback_file);
|
||||
|
||||
total = rollback_blocks_number;
|
||||
|
||||
while (1) {
|
||||
print_how_far (progress, &done, rollback_blocks_number, 1, 0/*not quiet*/);
|
||||
|
||||
descriptor = 0;
|
||||
if ((retval = fread (&b_dev, sizeof (b_dev), 1, s_rollback_file)) <= 0) {
|
||||
if (retval)
|
||||
fprintf (stderr, "rollback: fread: %s\n", strerror (errno));
|
||||
break;
|
||||
}
|
||||
if ((retval = fread (&offset, sizeof (offset), 1, s_rollback_file)) <= 0) {
|
||||
if (retval)
|
||||
fprintf (stderr, "rollback: fread: %s\n", strerror (errno));
|
||||
break;
|
||||
}
|
||||
|
||||
if ((retval = fread (rollback_data, rollback_blocksize, 1, s_rollback_file)) <= 0) {
|
||||
if (retval)
|
||||
fprintf (stderr, "rollback: fread: %s\n", strerror (errno));
|
||||
break;
|
||||
}
|
||||
|
||||
if (n_dev == b_dev)
|
||||
descriptor = fd_device;
|
||||
if ((n_journal_dev) && (n_journal_dev == b_dev))
|
||||
descriptor = fd_journal_device;
|
||||
|
||||
if (descriptor == 0) {
|
||||
fprintf(stderr, "rollback: block from unknown device, skip block\n");
|
||||
count_failed ++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lseek (descriptor, offset, SEEK_SET) == (loff_t)-1) {
|
||||
fprintf(stderr, "device cannot be lseeked, skip block\n");
|
||||
count_failed ++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (write (descriptor, rollback_data, rollback_blocksize) == -1) {
|
||||
fprintf (stderr, "rollback: write %d bytes returned error "
|
||||
"(block=%lld, dev=%d): %s\n", rollback_blocksize,
|
||||
offset/rollback_blocksize, b_dev, strerror (errno));
|
||||
count_failed ++;
|
||||
} else {
|
||||
count_rollbacked ++;
|
||||
/*if you want to know what gets rollbacked, uncomment it*/
|
||||
/* if (log_file != 0 && log_file != stdout)
|
||||
fprintf (log_file, "rollback: block %Lu of device %Lu was restored\n",
|
||||
(loff_t)offset/rollback_blocksize, b_dev);
|
||||
*/
|
||||
// fprintf (stdout, "rollback: block (%Ld) written\n", (loff_t)offset/rollback_blocksize);
|
||||
}
|
||||
}
|
||||
|
||||
printf ("\n");
|
||||
if (log_file != 0)
|
||||
fprintf (log_file, "rollback: (%u) blocks restored\n", count_rollbacked);
|
||||
}
|
||||
|
||||
/*
|
||||
static void rollback__mark_block_saved (struct block_handler * rb_e) {
|
||||
if (rollback_blocks_array == NULL)
|
||||
rollback_blocks_array = getmem (ROLLBACK__INCREASE_BLOCK_NUMBER * sizeof (*rb_e));
|
||||
|
||||
if (rollback_blocks_number == get_mem_size ((void *)rollback_blocks_array) / sizeof (*rb_e))
|
||||
rollback_blocks_array = expandmem (rollback_blocks_array, get_mem_size((void *)rollback_blocks_array),
|
||||
ROLLBACK__INCREASE_BLOCK_NUMBER * sizeof (*rb_e));
|
||||
|
||||
// checkmem ((char *)rollback_blocks_array, get_mem_size((char *)rollback_blocks_array));
|
||||
|
||||
rollback_blocks_array[rollback_blocks_number] = *rb_e;
|
||||
rollback_blocks_number ++;
|
||||
qsort (rollback_blocks_array, rollback_blocks_number, sizeof (*rb_e), rollback_compare);
|
||||
|
||||
// printf("\ncheckmem3");
|
||||
// fflush (stdout);
|
||||
// checkmem ((char *)rollback_blocks_array, get_mem_size((char *)rollback_blocks_array));
|
||||
// printf(" OK");
|
||||
}
|
||||
*/
|
||||
/* for now - just make sure that bad blocks did not get here */
|
||||
int bwrite (struct buffer_head * bh)
|
||||
{
|
||||
unsigned long long offset;
|
||||
long long bytes, size;
|
||||
|
||||
if (is_bad_block (bh->b_blocknr)) {
|
||||
fprintf (stderr, "bwrite: bad block is going to be written: %lu\n",
|
||||
bh->b_blocknr);
|
||||
exit(8);
|
||||
}
|
||||
|
||||
if (!buffer_dirty (bh) || !buffer_uptodate (bh))
|
||||
return 0;
|
||||
|
||||
buffer_writes++ ;
|
||||
if (bh->b_start_io)
|
||||
/* this is used by undo feature of reiserfsck */
|
||||
bh->b_start_io (bh->b_blocknr);
|
||||
|
||||
size = bh->b_size;
|
||||
offset = (loff_t)size * (loff_t)bh->b_blocknr;
|
||||
|
||||
if (lseek (bh->b_dev, offset, SEEK_SET) == (loff_t)-1){
|
||||
fprintf (stderr, "bwrite: lseek to position %llu (block=%lu, dev=%d): %s\n",
|
||||
offset, bh->b_blocknr, bh->b_dev, strerror(errno));
|
||||
exit(8); /* File system errors left uncorrected */
|
||||
}
|
||||
|
||||
if (s_rollback_file != NULL && bh->b_size == (unsigned long)rollback_blocksize) {
|
||||
struct stat buf;
|
||||
__u32 position;
|
||||
struct block_handler block_h;
|
||||
|
||||
/*log previous content into the log*/
|
||||
if (!fstat (bh->b_dev, &buf)) {
|
||||
block_h.blocknr = bh->b_blocknr;
|
||||
block_h.device = buf.st_rdev;
|
||||
if (reiserfs_bin_search(&block_h, rollback_blocks_array,
|
||||
rollback_blocks_number, sizeof (block_h),
|
||||
&position, blockdev_list_compare)
|
||||
!= POSITION_FOUND)
|
||||
{
|
||||
/*read initial data from the disk*/
|
||||
if (read(bh->b_dev, rollback_data, bh->b_size) == (long long)bh->b_size) {
|
||||
fwrite(&buf.st_rdev, sizeof (buf.st_rdev), 1, s_rollback_file);
|
||||
fwrite(&offset, sizeof (offset), 1, s_rollback_file);
|
||||
fwrite(rollback_data, rollback_blocksize, 1, s_rollback_file);
|
||||
fflush(s_rollback_file);
|
||||
blocklist__insert_in_position(&block_h, (void *)(&rollback_blocks_array),
|
||||
&rollback_blocks_number, sizeof(block_h), &position);
|
||||
|
||||
/*if you want to know what gets saved, uncomment it*/
|
||||
/* if (log_file != 0 && log_file != stdout) {
|
||||
fprintf (log_file, "rollback: block %lu of device %Lu was "
|
||||
"backed up\n", bh->b_blocknr, buf.st_rdev);
|
||||
}
|
||||
*/
|
||||
|
||||
} else {
|
||||
fprintf (stderr, "bwrite: read (block=%lu, dev=%d): %s\n",
|
||||
bh->b_blocknr, bh->b_dev, strerror (errno));
|
||||
exit(8);
|
||||
}
|
||||
|
||||
if (lseek (bh->b_dev, offset, SEEK_SET) == (loff_t)-1) {
|
||||
fprintf (stderr, "bwrite: lseek to position %llu (block=%lu, "
|
||||
"dev=%d): %s\n", offset, bh->b_blocknr, bh->b_dev,
|
||||
strerror(errno));
|
||||
exit(8);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf (stderr, "bwrite: fstat of (%d) returned -1: %s\n",
|
||||
bh->b_dev, strerror(errno));
|
||||
}
|
||||
} else if (s_rollback_file != NULL) {
|
||||
fprintf (stderr, "rollback: block (%lu) has the size different from "
|
||||
"the fs uses, block skipped\n", bh->b_blocknr);
|
||||
}
|
||||
|
||||
bytes = write(bh->b_dev, bh->b_data, size);
|
||||
if (bytes != size) {
|
||||
fprintf (stderr, "bwrite: write %lld bytes returned %lld (block=%ld, "
|
||||
"dev=%d): %s\n", size, bytes, bh->b_blocknr, bh->b_dev,
|
||||
strerror(errno));
|
||||
exit(8);
|
||||
}
|
||||
|
||||
mark_buffer_clean (bh);
|
||||
|
||||
if (bh->b_end_io) {
|
||||
bh->b_end_io(bh, 1) ;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int _check_and_free_buffer_list(struct buffer_head *list) {
|
||||
struct buffer_head *next = list ;
|
||||
int count = 0 ;
|
||||
if (!list)
|
||||
return 0 ;
|
||||
|
||||
for(;;) {
|
||||
if (next->b_count != 0)
|
||||
fprintf (stderr, "check_and_free_buffer_mem: not free buffer "
|
||||
"(%d, %ld, %ld, %d)\n", next->b_dev, next->b_blocknr,
|
||||
next->b_size, next->b_count);
|
||||
|
||||
if (buffer_dirty (next) && buffer_uptodate (next))
|
||||
fprintf (stderr, "check_and_free_buffer_mem: dirty buffer "
|
||||
"(%d %lu) found\n", next->b_dev, next->b_blocknr);
|
||||
|
||||
freemem (next->b_data);
|
||||
count++;
|
||||
next = next->b_next;
|
||||
if (next == list)
|
||||
break;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static void check_and_free_buffer_mem (void)
|
||||
{
|
||||
int count = 0;
|
||||
struct buffer_head * next ;
|
||||
|
||||
// printf("check and free buffer mem, hits %d misses %d reads %d writes %d\n",
|
||||
// buffer_hits, buffer_misses, buffer_reads, buffer_writes) ;
|
||||
/*sync_buffers (0, 0);*/
|
||||
|
||||
count = _check_and_free_buffer_list(Buffer_list_head);
|
||||
count += _check_and_free_buffer_list(g_free_buffers);
|
||||
|
||||
if (count != g_nr_buffers)
|
||||
die ("check_and_free_buffer_mem: found %d buffers, must be %d",
|
||||
count, g_nr_buffers);
|
||||
|
||||
/* free buffer heads */
|
||||
while ((next = g_buffer_heads)) {
|
||||
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 ();
|
||||
}
|
||||
|
||||
|
||||
static void _invalidate_buffer_list(struct buffer_head *list, int dev)
|
||||
{
|
||||
struct buffer_head * next;
|
||||
|
||||
if (!list)
|
||||
return;
|
||||
|
||||
next = list;
|
||||
|
||||
for (;;) {
|
||||
if (next->b_dev == dev) {
|
||||
if (buffer_dirty (next) || next->b_count)
|
||||
fprintf (stderr, "invalidate_buffers: dirty buffer or used buffer (%d %lu) found\n",
|
||||
next->b_count, next->b_blocknr);
|
||||
next->b_state = 0;
|
||||
remove_from_hash_queue (next);
|
||||
}
|
||||
next = next->b_next;
|
||||
if (next == list)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* forget all buffers of the given device */
|
||||
void invalidate_buffers (int dev)
|
||||
{
|
||||
_invalidate_buffer_list(Buffer_list_head, dev) ;
|
||||
_invalidate_buffer_list(g_free_buffers, dev) ;
|
||||
}
|
||||
-986
@@ -1,986 +0,0 @@
|
||||
/*
|
||||
* Copyright 1996-2004 by Hans Reiser, licensing governed by
|
||||
* reiserfsprogs/README
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "misc.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <mntent.h>
|
||||
#include <sys/vfs.h>
|
||||
#include <time.h>
|
||||
#include <utime.h>
|
||||
#include <ctype.h>
|
||||
#include <linux/hdreg.h>
|
||||
#include <dirent.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <signal.h>
|
||||
|
||||
|
||||
/* Debian modifications by Ed Boraas <ed@debian.org> */
|
||||
#include <sys/mount.h>
|
||||
/* End Debian mods */
|
||||
|
||||
#define STAT_FIELD(Field, Type) \
|
||||
inline Type misc_device_##Field(char *device) { \
|
||||
struct stat st; \
|
||||
\
|
||||
if (stat(device, &st) == 0) \
|
||||
return st.st_##Field; \
|
||||
\
|
||||
fprintf(stderr, "Stat of the device '%s' failed.", device); \
|
||||
exit(8); \
|
||||
}
|
||||
|
||||
STAT_FIELD(mode, mode_t);
|
||||
STAT_FIELD(rdev, dev_t);
|
||||
STAT_FIELD(size, off_t);
|
||||
STAT_FIELD(blocks, blkcnt_t);
|
||||
|
||||
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", buf);
|
||||
abort ();
|
||||
}
|
||||
|
||||
|
||||
#define MEM_BEGIN "_mem_begin_"
|
||||
#define MEM_END "mem_end"
|
||||
#define MEM_FREED "__free_"
|
||||
#define CONTROL_SIZE (strlen (MEM_BEGIN) + 1 + sizeof (int) + strlen (MEM_END) + 1)
|
||||
|
||||
|
||||
unsigned 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 * mem;
|
||||
|
||||
if ((mem = mem_alloc(size)) == NULL)
|
||||
die ("getmem: no more memory (%d)", size);
|
||||
|
||||
memset (mem, 0, size);
|
||||
// checkmem (mem, size);
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
void *mem_alloc(int size) {
|
||||
char * p;
|
||||
char * mem;
|
||||
|
||||
p = (char *)malloc (CONTROL_SIZE + size);
|
||||
if (!p)
|
||||
die ("getmem: no more memory (%d)", size);
|
||||
|
||||
/* Write the MEM_BEGIN magic in the beginning of allocated memory. */
|
||||
strcpy (p, MEM_BEGIN);
|
||||
p += strlen (MEM_BEGIN) + 1;
|
||||
/* Write the size after the magic. */
|
||||
*(int *)p = size;
|
||||
p += sizeof (int);
|
||||
mem = p;
|
||||
p += size;
|
||||
strcpy (p, MEM_END);
|
||||
|
||||
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 *);
|
||||
|
||||
/* Lookup the @file in the @mntfile. @file is mntent.mnt_fsname if @fsname
|
||||
is set; mntent.mnt_dir otherwise. Return the mnt entry from the @mntfile.
|
||||
|
||||
Warning: if the root fs is mounted RO, the content of /etc/mtab may be
|
||||
not correct. */
|
||||
static struct mntent *misc_mntent_lookup(char *mntfile,
|
||||
char *file,
|
||||
int path)
|
||||
{
|
||||
struct mntent *mnt;
|
||||
int name_match = 0;
|
||||
struct stat st;
|
||||
dev_t rdev = 0;
|
||||
dev_t dev = 0;
|
||||
ino_t ino = 0;
|
||||
char *name;
|
||||
FILE *fp;
|
||||
|
||||
assert(mntfile != NULL);
|
||||
assert(file != NULL);
|
||||
|
||||
if (stat(file, &st) == 0) {
|
||||
/* Devices is stated. */
|
||||
if (S_ISBLK(st.st_mode)) {
|
||||
rdev = st.st_rdev;
|
||||
} else {
|
||||
dev = st.st_dev;
|
||||
ino = st.st_ino;
|
||||
}
|
||||
}
|
||||
|
||||
if ((fp = setmntent(mntfile, "r")) == NULL)
|
||||
return INVAL_PTR;
|
||||
|
||||
while ((mnt = getmntent(fp)) != NULL) {
|
||||
/* Check if names match. */
|
||||
name = path ? mnt->mnt_dir : mnt->mnt_fsname;
|
||||
|
||||
if (strcmp(file, name) == 0)
|
||||
name_match = 1;
|
||||
|
||||
if (stat(name, &st))
|
||||
continue;
|
||||
|
||||
/* If names do not match, check if stats match. */
|
||||
if (!name_match) {
|
||||
if (rdev && S_ISBLK(st.st_mode)) {
|
||||
if (rdev != st.st_rdev)
|
||||
continue;
|
||||
} else if (dev && !S_ISBLK(st.st_mode)) {
|
||||
if (dev != st.st_dev ||
|
||||
ino != st.st_ino)
|
||||
continue;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* If not path and not block device do not check anything more. */
|
||||
if (!path && !rdev)
|
||||
break;
|
||||
|
||||
if (path) {
|
||||
/* Either names or stats match. Make sure the st_dev of
|
||||
the path is same as @mnt_fsname device rdev. */
|
||||
if (stat(mnt->mnt_fsname, &st) == 0 &&
|
||||
dev == st.st_rdev)
|
||||
break;
|
||||
} else {
|
||||
/* Either names or stats match. Make sure the st_dev of
|
||||
the mount entry is same as the given device rdev. */
|
||||
if (stat(mnt->mnt_dir, &st) == 0 &&
|
||||
rdev == st.st_dev)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
endmntent (fp);
|
||||
return mnt;
|
||||
}
|
||||
|
||||
static int misc_root_mounted(char *device) {
|
||||
struct stat rootst, devst;
|
||||
|
||||
assert(device != NULL);
|
||||
|
||||
if (stat("/", &rootst) != 0)
|
||||
return -1;
|
||||
|
||||
if (stat(device, &devst) != 0)
|
||||
return -1;
|
||||
|
||||
if (!S_ISBLK(devst.st_mode) ||
|
||||
devst.st_rdev != rootst.st_dev)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int misc_file_ro(char *file) {
|
||||
if (utime(file, 0) == -1) {
|
||||
if (errno == EROFS)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct mntent *misc_mntent(char *device) {
|
||||
int proc = 0, path = 0, root = 0;
|
||||
|
||||
struct mntent *mnt;
|
||||
struct statfs stfs;
|
||||
|
||||
assert(device != NULL);
|
||||
|
||||
/* Check if the root. */
|
||||
if (misc_root_mounted(device) == 1)
|
||||
root = 1;
|
||||
|
||||
#ifdef __linux__
|
||||
/* Check if /proc is procfs. */
|
||||
if (statfs("/proc", &stfs) == 0 && stfs.f_type == 0x9fa0) {
|
||||
proc = 1;
|
||||
|
||||
if (root) {
|
||||
/* Lookup the "/" entry in /proc/mounts. Special
|
||||
case as root entry can present as:
|
||||
rootfs / rootfs rw 0 0
|
||||
Look up the mount point in this case. */
|
||||
mnt = misc_mntent_lookup("/proc/mounts", "/", 1);
|
||||
} else {
|
||||
/* Lookup the @device /proc/mounts */
|
||||
mnt = misc_mntent_lookup("/proc/mounts", device, 0);
|
||||
}
|
||||
|
||||
if (mnt == INVAL_PTR)
|
||||
proc = 0;
|
||||
else if (mnt)
|
||||
return mnt;
|
||||
}
|
||||
#endif /* __linux__ */
|
||||
|
||||
#if defined(MOUNTED) || defined(_PATH_MOUNTED)
|
||||
|
||||
#ifndef MOUNTED
|
||||
#define MOUNTED _PATH_MOUNTED
|
||||
#endif
|
||||
/* Check in MOUNTED (/etc/mtab) if RW. */
|
||||
if (!misc_file_ro(MOUNTED)) {
|
||||
path = 1;
|
||||
|
||||
if (root) {
|
||||
mnt = misc_mntent_lookup(MOUNTED, "/", 1);
|
||||
} else {
|
||||
mnt = misc_mntent_lookup(MOUNTED, device, 0);
|
||||
}
|
||||
|
||||
if (mnt == INVAL_PTR)
|
||||
path = 0;
|
||||
else if (mnt)
|
||||
return mnt;
|
||||
}
|
||||
#endif /* defined(MOUNTED) || defined(_PATH_MOUNTED) */
|
||||
|
||||
/* If has not been checked in neither /proc/mounts nor /etc/mtab (or
|
||||
errors have occured), return INVAL_PTR, NULL otherwise. */
|
||||
return (!proc && !path) ? INVAL_PTR : NULL;
|
||||
}
|
||||
|
||||
int misc_device_mounted(char *device) {
|
||||
struct mntent *mnt;
|
||||
|
||||
/* Check for the "/" first to avoid any possible problem with
|
||||
reflecting the root fs info in mtab files. */
|
||||
if (misc_root_mounted(device) == 1) {
|
||||
return misc_file_ro("/") ? MF_RO : MF_RW;
|
||||
}
|
||||
|
||||
/* Lookup the mount entry. */
|
||||
if ((mnt = misc_mntent(device)) == NULL) {
|
||||
return MF_NOT_MOUNTED;
|
||||
} else if (mnt == INVAL_PTR) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return hasmntopt(mnt, MNTOPT_RO) ? MF_RO : MF_RW;
|
||||
}
|
||||
|
||||
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 = 0, t1 = 0, t2 = 0;
|
||||
int speed;
|
||||
int indent;
|
||||
|
||||
if (reset_time)
|
||||
time (&t0);
|
||||
|
||||
time (&t1);
|
||||
if (t1 != t0) {
|
||||
speed = passed / (t1 - t0);
|
||||
if (total - passed) {
|
||||
if (t1 - t2 < 1)
|
||||
return;
|
||||
t2 = t1;
|
||||
}
|
||||
} 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 (FILE * fp,
|
||||
unsigned long * passed, unsigned long total,
|
||||
unsigned int inc, int quiet)
|
||||
{
|
||||
int percent;
|
||||
|
||||
if (*passed == 0)
|
||||
current_progress[0] = 0;
|
||||
|
||||
(*passed) += inc;
|
||||
if (*passed > total) {
|
||||
/* fprintf (fp, "\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 (fp, "%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 (fp);
|
||||
}
|
||||
|
||||
#if defined(__linux__) && defined(_IOR) && !defined(BLKGETSIZE64)
|
||||
/* Note! Despite this call being called with *64, it must be encoded to
|
||||
* return only sizeof(size_t), since in earlier kernel versions it was
|
||||
* declared _IOR(0x12, 114, sizeof(u64)), making it use sizeof(sizeof(u64)).
|
||||
*
|
||||
* However, the call itself does always return 64bit!
|
||||
*/
|
||||
# define BLKGETSIZE64 _IOR(0x12, 114, size_t)
|
||||
#endif
|
||||
|
||||
/* To not have problem with last sectors on the block device when switching
|
||||
to smaller one. */
|
||||
#define MAX_BS (64 * 1024)
|
||||
|
||||
int valid_offset( int fd, loff_t offset) {
|
||||
char ch;
|
||||
loff_t res;
|
||||
|
||||
/*res = reiserfs_llseek (fd, offset, 0);*/
|
||||
res = lseek (fd, offset, SEEK_SET);
|
||||
if (res < 0)
|
||||
return 0;
|
||||
|
||||
/* if (read (fd, &ch, 1) < 0) does not wirk on files */
|
||||
if (read (fd, &ch, 1) < 1)
|
||||
return 0;
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* calculates number of blocks in a file. Returns 0 for "sparse"
|
||||
regular files and files other than regular files and block devices */
|
||||
unsigned long count_blocks (char * filename, int blocksize)
|
||||
{
|
||||
loff_t high, low;
|
||||
unsigned long sz;
|
||||
__u64 size;
|
||||
int fd;
|
||||
|
||||
if (!S_ISBLK(misc_device_mode(filename)) &&
|
||||
!S_ISREG(misc_device_mode(filename)))
|
||||
return 0;
|
||||
|
||||
fd = open (filename, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "Failed to open '%s': %s.\n", filename, strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef BLKGETSIZE64
|
||||
{
|
||||
if (ioctl (fd, BLKGETSIZE64, &size) >= 0) {
|
||||
size = (size / MAX_BS) * MAX_BS / blocksize;
|
||||
sz = size;
|
||||
if ((__u64)sz != size)
|
||||
die ("count_blocks: block device too large");
|
||||
|
||||
close(fd);
|
||||
return sz;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef BLKGETSIZE
|
||||
{
|
||||
if (ioctl (fd, BLKGETSIZE, &sz) >= 0) {
|
||||
size = sz;
|
||||
|
||||
close(fd);
|
||||
return (size * 512 / MAX_BS) * MAX_BS / blocksize;
|
||||
}
|
||||
}
|
||||
#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);
|
||||
|
||||
close (fd);
|
||||
return (low + 1) * MAX_BS / MAX_BS / blocksize;
|
||||
}
|
||||
|
||||
/* there are masks for certain bits */
|
||||
__u16 mask16 (int from, int count)
|
||||
{
|
||||
__u16 mask;
|
||||
|
||||
|
||||
mask = (0xffff >> from);
|
||||
mask <<= from;
|
||||
mask <<= (16 - from - count);
|
||||
mask >>= (16 - from - count);
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
__u32 mask32 (int from, int count)
|
||||
{
|
||||
__u32 mask;
|
||||
|
||||
|
||||
mask = (0xffffffff >> from);
|
||||
mask <<= from;
|
||||
mask <<= (32 - from - count);
|
||||
mask >>= (32 - from - count);
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
__u64 mask64 (int from, int count)
|
||||
{
|
||||
__u64 mask;
|
||||
|
||||
|
||||
mask = (0xffffffffffffffffLL >> from);
|
||||
mask <<= from;
|
||||
mask <<= (64 - from - count);
|
||||
mask >>= (64 - from - count);
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
||||
__u32 get_random (void)
|
||||
{
|
||||
srandom (time (0));
|
||||
return random ();
|
||||
}
|
||||
|
||||
/* this implements binary search in the array 'base' among 'num' elements each
|
||||
of those is 'width' bytes long. 'comp_func' is used to compare keys */
|
||||
int reiserfs_bin_search (void * key, void * base, __u32 num, int width,
|
||||
__u32 * ppos, comparison_fn_t comp_func)
|
||||
{
|
||||
__u32 rbound, lbound, j;
|
||||
int ret;
|
||||
|
||||
if (num == 0 || base == NULL) {
|
||||
/* objectid map may be 0 elements long */
|
||||
*ppos = 0;
|
||||
return POSITION_NOT_FOUND;
|
||||
}
|
||||
|
||||
lbound = 0;
|
||||
rbound = num - 1;
|
||||
|
||||
for (j = (rbound + lbound) / 2; lbound <= rbound; j = (rbound + lbound) / 2) {
|
||||
ret = comp_func ((void *)((char *)base + j * width), key ) ;
|
||||
if (ret < 0) { /* second is greater */
|
||||
lbound = j + 1;
|
||||
continue;
|
||||
|
||||
} else if (ret > 0) { /* first is greater */
|
||||
if (j == 0)
|
||||
break;
|
||||
rbound = j - 1;
|
||||
continue;
|
||||
} else { /* equal */
|
||||
*ppos = j;
|
||||
return POSITION_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
*ppos = lbound;
|
||||
return POSITION_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
#define BLOCKLIST__ELEMENT_NUMBER 10
|
||||
|
||||
/*element is block number and device*/
|
||||
int blockdev_list_compare (const void * block1, const void * block2) {
|
||||
if (*(__u32 *)block1 < *(__u32 *)block2)
|
||||
return -1;
|
||||
if (*(__u32 *)block1 > *(__u32 *)block2)
|
||||
return 1;
|
||||
|
||||
if (*((__u32 *)block1 + 1) < *((__u32 *)block2 + 1))
|
||||
return -1;
|
||||
if (*((__u32 *)block1 + 1) > *((__u32 *)block2 + 1))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void blocklist__insert_in_position (void *elem, void **base, __u32 *count,
|
||||
int elem_size, __u32 *position)
|
||||
{
|
||||
if (elem_size == 0)
|
||||
return;
|
||||
|
||||
if (*base == NULL)
|
||||
*base = getmem (BLOCKLIST__ELEMENT_NUMBER * elem_size);
|
||||
|
||||
if (*count == get_mem_size((void *)*base) / elem_size)
|
||||
*base = expandmem (*base, get_mem_size((void *)*base),
|
||||
BLOCKLIST__ELEMENT_NUMBER * elem_size);
|
||||
|
||||
if (*position < *count) {
|
||||
memmove (*base + (*position + 1),
|
||||
*base + (*position),
|
||||
(*count - *position) * elem_size);
|
||||
}
|
||||
|
||||
memcpy (*base + (char) *position * elem_size, elem, elem_size);
|
||||
*count+=1;
|
||||
}
|
||||
|
||||
/* 0 - dma is not supported, scsi or regular file */
|
||||
/* 1 - xt drive */
|
||||
/* 2 - ide drive */
|
||||
static void get_dma_support(dma_info_t *dma_info){
|
||||
if (S_ISREG(dma_info->st.st_mode))
|
||||
dma_info->st.st_rdev = dma_info->st.st_dev;
|
||||
|
||||
if (IDE_DISK_MAJOR(major(dma_info->st.st_rdev))) {
|
||||
dma_info->support_type = 2;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef XT_DISK_MAJOR
|
||||
if (major(dma_info->st.st_rdev) == XT_DISK_MAJOR) {
|
||||
dma_info->support_type = 1;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
dma_info->support_type = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return values:
|
||||
* 0 - ok;
|
||||
* 1 - preparation cannot be done
|
||||
* -1 - preparation failed
|
||||
*/
|
||||
|
||||
int prepare_dma_check(dma_info_t *dma_info) {
|
||||
DIR *dir;
|
||||
struct dirent *dirent;
|
||||
struct stat st;
|
||||
dev_t rdev;
|
||||
int rem;
|
||||
char buf[256];
|
||||
|
||||
#ifndef HDIO_GET_DMA
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
if (fstat(dma_info->fd, &dma_info->st))
|
||||
die("stat on device failed\n");
|
||||
|
||||
get_dma_support(dma_info);
|
||||
|
||||
/* dma should be supported */
|
||||
if (dma_info->support_type == 0)
|
||||
return 1;
|
||||
|
||||
if (dma_info->support_type == 2) {
|
||||
rdev = dma_info->st.st_rdev;
|
||||
|
||||
if ((rem = (minor(rdev) % 64)) != 0) {
|
||||
rdev -= rem;
|
||||
if(!(dir = opendir("/dev/"))) {
|
||||
dma_info->support_type = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((dirent = readdir(dir)) != NULL) {
|
||||
if (strncmp(dirent->d_name, ".", 1) == 0 || strncmp(dirent->d_name, "..", 2) == 0)
|
||||
continue;
|
||||
memset(buf, 0, 256);
|
||||
strncat(buf, "/dev/", 5);
|
||||
strncat(buf, dirent->d_name, strlen(dirent->d_name));
|
||||
|
||||
if (stat(buf, &st))
|
||||
break;
|
||||
|
||||
if (S_ISBLK(st.st_mode) && st.st_rdev == rdev)
|
||||
{
|
||||
dma_info->st = st;
|
||||
dma_info->fd = open(buf, O_RDONLY
|
||||
#if defined(O_LARGEFILE)
|
||||
| O_LARGEFILE
|
||||
#endif
|
||||
);
|
||||
closedir(dir);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
dma_info->support_type = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_dma_on (int fd) {
|
||||
#ifdef HDIO_GET_DMA
|
||||
static long parm;
|
||||
if (ioctl(fd, HDIO_GET_DMA, &parm))
|
||||
return -1;
|
||||
else
|
||||
return parm;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static __u64 dma_speed(int fd, int support_type) {
|
||||
static struct hd_driveid id;
|
||||
__u64 speed = 0;
|
||||
|
||||
if (support_type != 2)
|
||||
return 0;
|
||||
|
||||
#ifdef HDIO_OBSOLETE_IDENTITY
|
||||
if (!ioctl(fd, HDIO_GET_IDENTITY, &id) ||
|
||||
!ioctl(fd, HDIO_OBSOLETE_IDENTITY)) {
|
||||
#else
|
||||
if (!ioctl(fd, HDIO_GET_IDENTITY, &id)) {
|
||||
#endif
|
||||
speed |= (__u64)id.dma_1word & ~(__u64)0xff;
|
||||
speed |= ((__u64)id.dma_mword & ~(__u64)0xff) << 16;
|
||||
speed |= ((__u64)id.dma_ultra & ~(__u64)0xff) << 32;
|
||||
} else if (errno == -ENOMSG)
|
||||
return -1;
|
||||
else
|
||||
return -1;
|
||||
|
||||
return speed;
|
||||
}
|
||||
|
||||
int get_dma_info(dma_info_t *dma_info) {
|
||||
if ((dma_info->dma = is_dma_on(dma_info->fd)) == -1)
|
||||
return -1;
|
||||
if ((dma_info->speed = dma_speed(dma_info->fd, dma_info->support_type)) == (__u64)-1)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void clean_after_dma_check(int fd, dma_info_t *dma_info) {
|
||||
signal(SIGALRM, SIG_IGN);
|
||||
if (dma_info->fd && fd != dma_info->fd)
|
||||
close(dma_info->fd);
|
||||
}
|
||||
|
||||
/* Only le bitops operations are used. */
|
||||
|
||||
inline int misc_set_bit (unsigned long long 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;
|
||||
}
|
||||
|
||||
|
||||
inline int misc_clear_bit (unsigned long long 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;
|
||||
}
|
||||
|
||||
inline int misc_test_bit(unsigned long long nr, const void * addr) {
|
||||
__u8 * p, mask;
|
||||
|
||||
p = (__u8 *)addr;
|
||||
p += nr >> 3;
|
||||
mask = 1 << (nr & 0x7);
|
||||
return ((mask & *p) != 0);
|
||||
}
|
||||
|
||||
inline unsigned long long misc_find_first_zero_bit (const void *vaddr,
|
||||
unsigned long long size)
|
||||
{
|
||||
const __u8 *p = vaddr, *addr = vaddr;
|
||||
unsigned long long res;
|
||||
|
||||
if (!size)
|
||||
return 0;
|
||||
|
||||
size = (size >> 3) + ((size & 0x7) > 0);
|
||||
while (*p++ == 255) {
|
||||
if (--size == 0)
|
||||
return (unsigned long long)(p - addr) << 3;
|
||||
}
|
||||
|
||||
--p;
|
||||
for (res = 0; res < 8; res++)
|
||||
if (!misc_test_bit (res, p))
|
||||
break;
|
||||
return res + (p - addr) * 8;
|
||||
}
|
||||
|
||||
|
||||
inline unsigned long long misc_find_next_zero_bit (const void *vaddr,
|
||||
unsigned long long size, unsigned long long offset)
|
||||
{
|
||||
const __u8 *addr = vaddr;
|
||||
const __u8 *p = addr + (offset >> 3);
|
||||
int bit = offset & 7;
|
||||
unsigned long long res;
|
||||
|
||||
if (offset >= size)
|
||||
return size;
|
||||
|
||||
if (bit) {
|
||||
/* Look for zero in first char */
|
||||
for (res = bit; res < 8; res++)
|
||||
if (!misc_test_bit (res, p))
|
||||
return res + (p - addr) * 8;
|
||||
p++;
|
||||
}
|
||||
/* No zero yet, search remaining full bytes for a zero */
|
||||
res = misc_find_first_zero_bit (p, size - 8 * (p - addr));
|
||||
return res + (p - addr) * 8;
|
||||
}
|
||||
|
||||
inline unsigned long long misc_find_first_set_bit (const void *vaddr,
|
||||
unsigned long long size)
|
||||
{
|
||||
const __u8 *p = vaddr, *addr = vaddr;
|
||||
unsigned long long res;
|
||||
|
||||
if (!size)
|
||||
return 0;
|
||||
|
||||
size = (size >> 3) + ((size & 0x7) > 0);
|
||||
while (*p++ == 0) {
|
||||
if (--size == 0)
|
||||
return (unsigned long long)(p - addr) << 3;
|
||||
}
|
||||
|
||||
--p;
|
||||
for (res = 0; res < 8; res++)
|
||||
if (misc_test_bit (res, p))
|
||||
break;
|
||||
|
||||
return res + (p - addr) * 8;
|
||||
}
|
||||
|
||||
inline unsigned long long misc_find_next_set_bit(const void *vaddr,
|
||||
unsigned long long size, unsigned long long offset)
|
||||
{
|
||||
const __u8 *addr = vaddr;
|
||||
const __u8 *p = addr + (offset >> 3);
|
||||
int bit = offset & 7;
|
||||
unsigned long long res;
|
||||
|
||||
if (offset >= size)
|
||||
return size;
|
||||
|
||||
if (bit) {
|
||||
/* Look for zero in first char */
|
||||
for (res = bit; res < 8; res++)
|
||||
if (misc_test_bit (res, p))
|
||||
return res + (p - addr) * 8;
|
||||
p++;
|
||||
}
|
||||
/* No set bit yet, search remaining full bytes for a 1 */
|
||||
res = misc_find_first_set_bit (p, size - 8 * (p - addr));
|
||||
return res + (p - addr) * 8;
|
||||
}
|
||||
|
||||
#include "credits.h"
|
||||
|
||||
/* Reads the "CREDITS" file and prints one paragraph from it. */
|
||||
void misc_print_credit(FILE *out) {
|
||||
char *line;
|
||||
__u32 num1, num2;
|
||||
|
||||
fprintf(out, "A pair of credits:\n");
|
||||
|
||||
srandom (time (0));
|
||||
|
||||
num1 = random() % CREDITS_COUNT;
|
||||
line = credits[num1];
|
||||
fprintf(out, "%s\n", line);
|
||||
|
||||
while ((num1 == (num2 = random() % CREDITS_COUNT))) {}
|
||||
|
||||
line = credits[num2];
|
||||
|
||||
fprintf(out, "%s\n", line);
|
||||
}
|
||||
|
||||
int user_confirmed (FILE * fp, char * q, char * yes) {
|
||||
char * answer = 0;
|
||||
size_t n = 0;
|
||||
|
||||
fprintf (fp, "%s", q);
|
||||
if (getline (&answer, &n, stdin) != (ssize_t)strlen (yes) || strcmp (yes, answer))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
Reference in new issue
Block a user