Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
20c6b26d
Commit
20c6b26d
authored
May 18, 2002
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
http://linux-isdn.bkbits.net/linux-2.5.make
into home.transmeta.com:/home/torvalds/v2.5/linux
parents
9ba364a1
67a670bd
Changes
23
Hide whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
1075 additions
and
1003 deletions
+1075
-1003
Documentation/Changes
Documentation/Changes
+1
-1
Rules.make
Rules.make
+113
-98
drivers/md/md.c
drivers/md/md.c
+45
-47
drivers/md/raid5.c
drivers/md/raid5.c
+442
-370
drivers/md/xor.c
drivers/md/xor.c
+8
-10
fs/intermezzo/ext_attr.c
fs/intermezzo/ext_attr.c
+2
-3
fs/intermezzo/kml.c
fs/intermezzo/kml.c
+18
-22
fs/intermezzo/psdev.c
fs/intermezzo/psdev.c
+109
-141
fs/nfsd/export.c
fs/nfsd/export.c
+10
-8
fs/nfsd/vfs.c
fs/nfsd/vfs.c
+21
-33
fs/read_write.c
fs/read_write.c
+81
-98
fs/reiserfs/inode.c
fs/reiserfs/inode.c
+78
-69
fs/reiserfs/journal.c
fs/reiserfs/journal.c
+2
-2
fs/reiserfs/namei.c
fs/reiserfs/namei.c
+91
-67
include/asm-i386/xor.h
include/asm-i386/xor.h
+3
-1
include/linux/fs.h
include/linux/fs.h
+3
-0
include/linux/raid/md_k.h
include/linux/raid/md_k.h
+3
-2
include/linux/raid/raid5.h
include/linux/raid/raid5.h
+28
-20
include/linux/raid/xor.h
include/linux/raid/xor.h
+1
-1
include/linux/reiserfs_fs.h
include/linux/reiserfs_fs.h
+3
-3
kernel/exit.c
kernel/exit.c
+9
-3
kernel/ksyms.c
kernel/ksyms.c
+2
-0
net/sunrpc/svcsock.c
net/sunrpc/svcsock.c
+2
-4
No files found.
Documentation/Changes
View file @
20c6b26d
...
...
@@ -49,7 +49,7 @@ Card) hardware, for example, you probably needn't concern yourself
with pcmcia-cs.
o Gnu C 2.95.3 # gcc --version
o Gnu make 3.7
7
# make --version
o Gnu make 3.7
8
# make --version
o binutils 2.9.5.0.25 # ld -v
o util-linux 2.10o # fdformat --version
o modutils 2.4.2 # insmod -V
...
...
Rules.make
View file @
20c6b26d
...
...
@@ -49,27 +49,28 @@ SUB_DIRS := $(subdir-y)
MOD_SUB_DIRS
:=
$(
sort
$
(
subdir-m
)
$
(
both-m
))
ALL_SUB_DIRS
:=
$(
sort
$
(
subdir-y
)
$
(
subdir-m
)
$
(
subdir-n
)
$
(
subdir-
))
#
# Common rules
#
%.s
:
%.c
$(CC)
$(CFLAGS)
$(EXTRA_CFLAGS)
-DKBUILD_BASENAME
=
$(
subst
$(comma)
,_,
$(
subst
-,_,
$
(
*
F
)))
$
(
CFLAGS_
$@
)
-S
$<
-o
$@
# export_flags will be set to -DEXPORT_SYMBOL for objects in $(export-objs)
%.i
:
%.c
$(CPP)
$(CFLAGS)
$(EXTRA_CFLAGS)
-DKBUILD_BASENAME
=
$(
subst
$(comma)
,_,
$(
subst
-,_,
$
(
*
F
)))
$
(
CFLAGS_
$@
)
$<
>
$@
c_flags
=
$(CFLAGS)
$(EXTRA_CFLAGS)
$
(
CFLAGS_
$@
)
-DKBUILD_BASENAME
=
$(
subst
$(comma)
,_,
$(
subst
-,_,
$
(
*
F
)))
$(export_flags)
%.o
:
%.c
$(CC)
$(CFLAGS)
$(EXTRA_CFLAGS)
-DKBUILD_BASENAME
=
$(
subst
$(comma)
,_,
$(
subst
-,_,
$
(
*
F
)))
$
(
CFLAGS_
$@
)
-c
-o
$@
$<
@
(
\
echo
'ifeq (
$(
strip
$(
subst
$(comma)
,:,
$(CFLAGS)
$(EXTRA_CFLAGS)
$(CFLAGS_$@
)))
,$
$(
strip
$
$(
subst
$
$(comma)
,:,$
$(CFLAGS)
$
$(EXTRA_CFLAGS)
$$(CFLAGS_$@
)))
)'
;
\
echo
'FILES_FLAGS_UP_TO_DATE += $@'
;
\
echo
'endif'
\
)
>
$(
dir
$@
)
/.
$(
notdir
$@
)
.flags
cmd_cc_s_c
=
$(CC)
$(c_flags)
-S
$<
-o
$@
%.o
:
%.s
$(AS)
$(AFLAGS)
$(EXTRA_CFLAGS)
-o
$@
$<
%.s
:
%.c dummy
$(
call
if_changed,cmd_cc_s_c
)
cmd_cc_i_c
=
$(CPP)
$(c_flags)
$<
>
$@
%.i
:
%.c dummy
$(
call
if_changed,cmd_cc_i_c
)
cmd_cc_o_c
=
$(CC)
$(c_flags)
-c
-o
$@
$<
%.o
:
%.c dummy
$(
call
if_changed,cmd_cc_o_c
)
# Old makefiles define their own rules for compiling .S files,
# but these standard rules are available for any Makefile that
...
...
@@ -77,16 +78,26 @@ ALL_SUB_DIRS := $(sort $(subdir-y) $(subdir-m) $(subdir-n) $(subdir-))
# the Makefiles to these standard rules. -- rmk, mec
ifdef
USE_STANDARD_AS_RULE
%.s
:
%.S
$(CPP)
$(AFLAGS)
$(EXTRA_AFLAGS)
$
(
AFLAGS_
$@
)
$<
>
$@
a_flags
=
$(AFLAGS)
$(EXTRA_AFLAGS)
$
(
AFLAGS_
$@
)
cmd_as_s_S
=
$(CPP)
$(a_flags)
$<
>
$@
%.s
:
%.S dummy
$(
call
if_changed,cmd_as_s_S
)
%.o
:
%.S
$(CC)
$(AFLAGS)
$(EXTRA_AFLAGS)
$
(
AFLAGS_
$@
)
-c
-o
$@
$<
cmd_as_o_S
=
$(CC)
$(a_flags)
-c
-o
$@
$<
%.o
:
%.S dummy
$(
call
if_changed,cmd_as_o_S
)
endif
# FIXME is anybody using this rule? Why does it have EXTRA_CFLAGS?
%.o
:
%.s
$(AS)
$(AFLAGS)
$(EXTRA_CFLAGS)
-o
$@
$<
%.lst
:
%.c
$(CC)
$(
CFLAGS)
$(EXTRA_CFLAGS)
$
(
CFLAGS_
$@
)
-g
-c
-o
$*
.o
$<
$(CC)
$(
c_flags
)
-g
-c
-o
$*
.o
$<
$(TOPDIR)
/scripts/makelst
$*
$(TOPDIR)
$(OBJDUMP)
#
#
...
...
@@ -97,66 +108,61 @@ all_targets: $(O_TARGET) $(L_TARGET)
# Rule to compile a set of .o files into one .o file
#
ifdef
O_TARGET
$(O_TARGET)
:
$(obj-y)
rm
-f
$@
ifneq
"$(strip $(obj-y))" ""
$(LD)
$(EXTRA_LDFLAGS)
-r
-o
$@
$(filter
$(obj-y),
$^)
else
$(AR)
rcs
$@
endif
@
(
\
echo 'ifeq ($(strip $(subst $(comma),
:
,
$(EXTRA_LDFLAGS) $(obj-y)))
,
$$(strip $$(subst $$(comma)
,
:
,
$$(EXTRA_LDFLAGS) $$(obj-y))))' ;
\
echo 'FILES_FLAGS_UP_TO_DATE += $@' ;
\
echo 'endif'
\
) > $(dir $@)/.$(notdir $@).flags
# If the list of objects to link is empty, just create an empty O_TARGET
cmd_link_o_target
=
$(
if
$(
strip
$
(
obj-y
))
,
\
$(LD)
$(EXTRA_LDFLAGS)
-r
-o
$@
$(
filter
$
(
obj-y
)
,
$^
)
,
\
rm
-f
$@
;
$(AR)
rcs
$@
)
$(O_TARGET)
:
$(obj-y) dummy
$(
call
if_changed,cmd_link_o_target
)
endif
# O_TARGET
#
# Rule to compile a set of .o files into one .a file
#
ifdef
L_TARGET
$(L_TARGET)
:
$(obj-y)
rm
-f
$@
$(AR)
$(EXTRA_ARFLAGS)
rcs
$@
$
(
obj-y
)
@
(
\
echo
'ifeq (
$(
strip
$(
subst
$(comma)
,:,
$(EXTRA_ARFLAGS)
$(obj-y
)))
,$
$(
strip
$
$(
subst
$
$(comma)
,:,$
$(EXTRA_ARFLAGS)
$$(obj-y
)))
)'
;
\
echo
'FILES_FLAGS_UP_TO_DATE += $@'
;
\
echo
'endif'
\
)
>
$(
dir
$@
)
/.
$(
notdir
$@
)
.flags
cmd_link_l_target
=
rm
-f
$@
;
$(AR)
$(EXTRA_ARFLAGS)
rcs
$@
$
(
obj-y
)
$(L_TARGET)
:
$(obj-y) dummy
$(
call
if_changed,cmd_link_l_target
)
endif
#
# Rule to link composite objects
#
#
for make >= 3.78 the following is cleaner:
#
multi-used := $(foreach m,$(obj-y) $(obj-m), $(if $($(basename $(m))-objs), $(m)
))
#
export.o is never a composite object, since $(export-objs) has a
#
fixed meaning (== objects which EXPORT_SYMBOL(
))
__obj-y
=
$(
filter-out
export.o,
$
(
obj-y
))
__obj-m
=
$(
filter-out
export.o,
$
(
obj-m
))
multi-used-y
:=
$(
sort
$(
foreach
m,
$
(
__obj-y
)
,
$(
patsubst
%,
$(m)
,
$
(
$(
basename
$(m)
)
-objs
))))
multi-used-m
:=
$(
sort
$(
foreach
m,
$
(
__obj-m
)
,
$(
patsubst
%,
$(m)
,
$
(
$(
basename
$(m)
)
-objs
))))
ld-multi-used-y
:=
$(
filter-out
$
(
list-multi
)
,
$
(
multi-used-y
))
ld-multi-used-m
:=
$(
filter-out
$
(
list-multi
)
,
$
(
multi-used-m
))
ld-multi-objs-y
:=
$(
foreach
m,
$
(
ld-multi-used-y
)
,
$
(
$(
basename
$(m)
)
-objs
))
ld-multi-objs-m
:=
$(
foreach
m,
$
(
ld-multi-used-m
)
,
$
(
$(
basename
$(m)
)
-objs
))
$(ld-multi-used-y)
:
%.o: $(ld-multi-objs-y)
rm
-f
$@
$(LD)
$(EXTRA_LDFLAGS)
-r
-o
$@
$(
filter
$
(
$(
basename
$@
)
-objs
)
,
$^
)
@
(
\
echo
'ifeq (
$(
strip
$(
subst
$(comma)
,:,
$(LD)
$(EXTRA_LDFLAGS)
$(
$(
basename
$@
)
-objs
))
,$
$(
strip
$
$(
subst
$
$(comma)
,:,$
$(LD)
$
$(EXTRA_LDFLAGS)
$$(
$(
basename
$@
)
-objs
))))
)'
;
\
echo
'FILES_FLAGS_UP_TO_DATE += $@'
;
\
echo
'endif'
\
)
>
$(
dir
$@
)
/.
$(
notdir
$@
)
.flags
$(ld-multi-used-m)
:
%.o: $(ld-multi-objs-m)
rm
-f
$@
$(LD)
$(EXTRA_LDFLAGS)
-r
-o
$@
$(
filter
$
(
$(
basename
$@
)
-objs
)
,
$^
)
@
(
\
echo
'ifeq (
$(
strip
$(
subst
$(comma)
,:,
$(LD)
$(EXTRA_LDFLAGS)
$(
$(
basename
$@
)
-objs
))
,$
$(
strip
$
$(
subst
$
$(comma)
,:,$
$(LD)
$
$(EXTRA_LDFLAGS)
$$(
$(
basename
$@
)
-objs
))))
)'
;
\
echo
'FILES_FLAGS_UP_TO_DATE += $@'
;
\
echo
'endif'
\
)
>
$(
dir
$@
)
/.
$(
notdir
$@
)
.flags
# if $(foo-objs) exists, foo.o is a composite object
__multi-used-y
:=
$(
sort
$(
foreach
m,
$
(
__obj-y
)
,
$(
if
$
(
$(
basename
$(m)
)
-objs
)
,
$(m)
)))
__multi-used-m
:=
$(
sort
$(
foreach
m,
$
(
__obj-m
)
,
$(
if
$
(
$(
basename
$(m)
)
-objs
)
,
$(m)
)))
# Backwards compatibility: if a composite object is listed in
# $(list-multi), skip it here, since the Makefile will have an explicit
# link rule for it
multi-used-y
:=
$(
filter-out
$
(
list-multi
)
,
$
(
__multi-used-y
))
multi-used-m
:=
$(
filter-out
$
(
list-multi
)
,
$
(
__multi-used-m
))
# Build list of the parts of our composite objects, our composite
# objects depend on those (obviously)
multi-objs-y
:=
$(
foreach
m,
$
(
multi-used-y
)
,
$
(
$(
basename
$(m)
)
-objs
))
multi-objs-m
:=
$(
foreach
m,
$
(
multi-used-m
)
,
$
(
$(
basename
$(m)
)
-objs
))
cmd_link_multi
=
$(LD)
$(EXTRA_LDFLAGS)
-r
-o
$@
$(
filter
$
(
$(
basename
$@
)
-objs
)
,
$^
)
# We would rather have a list of rules like
# foo.o: $(foo-objs)
# but that's not so easy, so we rather make all composite objects depend
# on the set of all their parts
$(multi-used-y)
:
%.o: $(multi-objs-y) dummy
$(
call
if_changed,cmd_link_multi
)
$(multi-used-m)
:
%.o: $(multi-objs-m) dummy
$(
call
if_changed,cmd_link_multi
)
#
# This make dependencies quickly
...
...
@@ -306,14 +312,10 @@ $(TOPDIR)/include/linux/modversions.h:
endif
# CONFIG_MODVERSIONS
ifneq
"$(strip $(export-objs))" ""
$(export-objs)
:
$(TOPDIR)/include/linux/modversions.h
$(export-objs)
:
%.o: %.c
$(CC)
$(CFLAGS)
$(EXTRA_CFLAGS)
-DKBUILD_BASENAME
=
$(
subst
$(comma)
,_,
$(
subst
-,_,
$
(
*
F
)))
$
(
CFLAGS_
$@
)
-DEXPORT_SYMTAB
-c
$
(
@:.o
=
.c
)
@
(
\
echo
'ifeq (
$(
strip
$(
subst
$(comma)
,:,
$(CFLAGS)
$(EXTRA_CFLAGS)
$(CFLAGS_$@
)
-DEXPORT_SYMTAB
))
,$
$(
strip
$
$(
subst
$
$(comma)
,:,$
$(CFLAGS)
$
$(EXTRA_CFLAGS)
$$(CFLAGS_$@
)
-DEXPORT_SYMTAB
))
)'
;
\
echo
'FILES_FLAGS_UP_TO_DATE += $@'
;
\
echo
'endif'
\
)
>
$(
dir
$@
)
/.
$(
notdir
$@
)
.flags
$(export-objs)
:
export_flags := -DEXPORT_SYMTAB
endif
endif
# CONFIG_MODULES
...
...
@@ -330,35 +332,48 @@ ifneq ($(wildcard $(TOPDIR)/.hdepend),)
include
$(TOPDIR)/.hdepend
endif
# ---------------------------------------------------------------------------
# Check if command line has changed
# Usage:
# normally one uses rules like
#
# Find files whose flags have changed and force recompilation.
# For safety, this works in the converse direction:
# every file is forced, except those whose flags are positively up-to-date.
# %.o: %.c
# <command line>
#
FILES_FLAGS_UP_TO_DATE
:=
# However, these only rebuild the target when the source has changed,
# but not when e.g. the command or the flags on the command line changed.
#
# This extension allows to do the following:
#
# command = <command line>
#
# %.o: %.c dummy
# $(call if_changed,command)
#
# which will make sure to rebuild the target when either its prerequisites
# change or the command line changes
#
# The magic works as follows:
# The addition of dummy to the dependencies causes the rule for rebuilding
# to be always executed. However, the if_changed function will generate
# an empty command when
# o none of the prequesites changed (i.e $? is empty)
# o the command line did not change (we compare the old command line,
# which is saved in .<target>.o, to the current command line using
# the two filter-out commands)
# For use in expunging commas from flags, which mung our checking.
comma
=
,
# read all saved command lines
FILES_FLAGS_EXIST
:=
$(
wildcard
.
*
.flags
)
ifneq
($(
FILES_FLAGS_EXIST
),)
include
$(FILES_FLAGS_EXIST
)
cmd_files
:=
$(
wildcard
.
*
.cmd
)
ifneq
($(
cmd_files
),)
include
$(cmd_files
)
endif
FILES_FLAGS_CHANGED
:=
$(
strip
\
$(
filter-out
$(FILES_FLAGS_UP_TO_DATE)
,
\
$(O_TARGET)
$(L_TARGET)
$
(
active-objs
)
\
))
# A kludge: .S files don't get flag dependencies (yet),
# because that will involve changing a lot of Makefiles. Also
# suppress object files explicitly listed in $(IGNORE_FLAGS_OBJS).
# This allows handling of assembly files that get translated into
# multiple object files (see arch/ia64/lib/idiv.S, for example).
FILES_FLAGS_CHANGED
:=
$(
strip
\
$(
filter-out
$(
patsubst
%.S, %.o,
$(
wildcard
*
.S
)
$(IGNORE_FLAGS_OBJS)
)
,
\
$(FILES_FLAGS_CHANGED)
))
ifneq
($(FILES_FLAGS_CHANGED),)
$(FILES_FLAGS_CHANGED)
:
dummy
endif
# function to only execute the passed command if necessary
if_changed
=
$(
if
$(
strip
$?
\
$(
filter-out
$
(
$(1)
)
,
$
(
cmd_
$@
))
\
$(
filter-out
$
(
cmd_
$@
)
,
$
(
$(1)
)))
,
\
@echo
$
(
$(1)
)
;
$
(
$(1)
)
;
echo
'cmd_$@ := $(
$(1)
)
'
>
.
$@
.cmd
)
drivers/md/md.c
View file @
20c6b26d
...
...
@@ -436,14 +436,15 @@ static int alloc_array_sb(mddev_t * mddev)
static
int
alloc_disk_sb
(
mdk_rdev_t
*
rdev
)
{
if
(
rdev
->
sb
)
if
(
rdev
->
sb
_page
)
MD_BUG
();
rdev
->
sb
=
(
mdp_super_t
*
)
__get_free
_page
(
GFP_KERNEL
);
if
(
!
rdev
->
sb
)
{
rdev
->
sb
_page
=
alloc
_page
(
GFP_KERNEL
);
if
(
!
rdev
->
sb
_page
)
{
printk
(
OUT_OF_MEM
);
return
-
EINVAL
;
}
rdev
->
sb
=
(
mdp_super_t
*
)
page_address
(
rdev
->
sb_page
);
clear_page
(
rdev
->
sb
);
return
0
;
...
...
@@ -451,9 +452,10 @@ static int alloc_disk_sb(mdk_rdev_t * rdev)
static
void
free_disk_sb
(
mdk_rdev_t
*
rdev
)
{
if
(
rdev
->
sb
)
{
free_page
((
unsigned
long
)
rdev
->
sb
);
if
(
rdev
->
sb
_page
)
{
page_cache_release
(
rdev
->
sb_page
);
rdev
->
sb
=
NULL
;
rdev
->
sb_page
=
NULL
;
rdev
->
sb_offset
=
0
;
rdev
->
size
=
0
;
}
else
{
...
...
@@ -462,13 +464,42 @@ static void free_disk_sb(mdk_rdev_t * rdev)
}
}
static
void
bi_complete
(
struct
bio
*
bio
)
{
complete
((
struct
completion
*
)
bio
->
bi_private
);
}
static
int
sync_page_io
(
struct
block_device
*
bdev
,
sector_t
sector
,
int
size
,
struct
page
*
page
,
int
rw
)
{
struct
bio
bio
;
struct
bio_vec
vec
;
struct
completion
event
;
bio_init
(
&
bio
);
bio
.
bi_io_vec
=
&
vec
;
vec
.
bv_page
=
page
;
vec
.
bv_len
=
size
;
vec
.
bv_offset
=
0
;
bio
.
bi_vcnt
=
1
;
bio
.
bi_idx
=
0
;
bio
.
bi_size
=
size
;
bio
.
bi_bdev
=
bdev
;
bio
.
bi_sector
=
sector
;
init_completion
(
&
event
);
bio
.
bi_private
=
&
event
;
bio
.
bi_end_io
=
bi_complete
;
submit_bio
(
rw
,
&
bio
);
run_task_queue
(
&
tq_disk
);
wait_for_completion
(
&
event
);
return
test_bit
(
BIO_UPTODATE
,
&
bio
.
bi_flags
);
}
static
int
read_disk_sb
(
mdk_rdev_t
*
rdev
)
{
struct
address_space
*
mapping
=
rdev
->
bdev
->
bd_inode
->
i_mapping
;
struct
page
*
page
;
char
*
p
;
unsigned
long
sb_offset
;
int
n
=
PAGE_CACHE_SIZE
/
BLOCK_SIZE
;
if
(
!
rdev
->
sb
)
{
MD_BUG
();
...
...
@@ -483,24 +514,14 @@ static int read_disk_sb(mdk_rdev_t * rdev)
*/
sb_offset
=
calc_dev_sboffset
(
rdev
->
dev
,
rdev
->
mddev
,
1
);
rdev
->
sb_offset
=
sb_offset
;
page
=
read_cache_page
(
mapping
,
sb_offset
/
n
,
(
filler_t
*
)
mapping
->
a_ops
->
readpage
,
NULL
);
if
(
IS_ERR
(
page
))
goto
out
;
wait_on_page_locked
(
page
);
if
(
!
PageUptodate
(
page
))
goto
fail
;
if
(
PageError
(
page
))
if
(
!
sync_page_io
(
rdev
->
bdev
,
sb_offset
<<
1
,
MD_SB_BYTES
,
rdev
->
sb_page
,
READ
))
goto
fail
;
p
=
(
char
*
)
page_address
(
page
)
+
BLOCK_SIZE
*
(
sb_offset
%
n
);
memcpy
((
char
*
)
rdev
->
sb
,
p
,
MD_SB_BYTES
);
page_cache_release
(
page
);
printk
(
KERN_INFO
" [events: %08lx]
\n
"
,
(
unsigned
long
)
rdev
->
sb
->
events_lo
);
return
0
;
fail:
page_cache_release
(
page
);
out:
printk
(
NO_SB
,
partition_name
(
rdev
->
dev
));
return
-
EINVAL
;
}
...
...
@@ -893,11 +914,6 @@ static mdk_rdev_t * find_rdev_all(kdev_t dev)
static
int
write_disk_sb
(
mdk_rdev_t
*
rdev
)
{
struct
block_device
*
bdev
=
rdev
->
bdev
;
struct
address_space
*
mapping
=
bdev
->
bd_inode
->
i_mapping
;
struct
page
*
page
;
unsigned
offs
;
int
error
;
kdev_t
dev
=
rdev
->
dev
;
unsigned
long
sb_offset
,
size
;
...
...
@@ -933,29 +949,11 @@ static int write_disk_sb(mdk_rdev_t * rdev)
}
printk
(
KERN_INFO
"(write) %s's sb offset: %ld
\n
"
,
partition_name
(
dev
),
sb_offset
);
fsync_bdev
(
bdev
);
page
=
grab_cache_page
(
mapping
,
sb_offset
/
(
PAGE_CACHE_SIZE
/
BLOCK_SIZE
));
offs
=
sb_offset
%
(
PAGE_CACHE_SIZE
/
BLOCK_SIZE
);
if
(
!
page
)
if
(
!
sync_page_io
(
rdev
->
bdev
,
sb_offset
<<
1
,
MD_SB_BYTES
,
rdev
->
sb_page
,
WRITE
))
goto
fail
;
error
=
mapping
->
a_ops
->
prepare_write
(
NULL
,
page
,
offs
,
offs
+
MD_SB_BYTES
);
if
(
error
)
goto
unlock
;
memcpy
((
char
*
)
page_address
(
page
)
+
offs
,
rdev
->
sb
,
MD_SB_BYTES
);
error
=
mapping
->
a_ops
->
commit_write
(
NULL
,
page
,
offs
,
offs
+
MD_SB_BYTES
);
if
(
error
)
goto
unlock
;
unlock_page
(
page
);
wait_on_page_locked
(
page
);
page_cache_release
(
page
);
fsync_bdev
(
bdev
);
skip:
return
0
;
unlock:
unlock_page
(
page
);
page_cache_release
(
page
);
fail:
printk
(
"md: write_disk_sb failed for device %s
\n
"
,
partition_name
(
dev
));
return
1
;
...
...
drivers/md/raid5.c
View file @
20c6b26d
...
...
@@ -24,19 +24,19 @@
#include <asm/bitops.h>
#include <asm/atomic.h>
static
mdk_personality_t
raid5_personality
;
/*
* Stripe cache
*/
#define NR_STRIPES 256
#define STRIPE_SIZE PAGE_SIZE
#define STRIPE_SECTORS (STRIPE_SIZE>>9)
#define IO_THRESHOLD 1
#define HASH_PAGES 1
#define HASH_PAGES_ORDER 0
#define NR_HASH (HASH_PAGES * PAGE_SIZE / sizeof(struct stripe_head *))
#define HASH_MASK (NR_HASH - 1)
#define stripe_hash(conf, sect) ((conf)->stripe_hashtbl[((sect) /
((conf)->buffer_size >> 9)
) & HASH_MASK])
#define stripe_hash(conf, sect) ((conf)->stripe_hashtbl[((sect) /
STRIPE_SECTORS
) & HASH_MASK])
/*
* The following can be used to debug the driver
...
...
@@ -142,47 +142,36 @@ static struct stripe_head *get_free_stripe(raid5_conf_t *conf)
static
void
shrink_buffers
(
struct
stripe_head
*
sh
,
int
num
)
{
struct
buffer_head
*
bh
;
struct
page
*
p
;
int
i
;
for
(
i
=
0
;
i
<
num
;
i
++
)
{
bh
=
sh
->
bh_cache
[
i
];
if
(
!
bh
)
return
;
sh
->
bh_cache
[
i
]
=
NULL
;
free_page
((
unsigned
long
)
bh
->
b_data
);
kfree
(
bh
);
p
=
sh
->
dev
[
i
].
page
;
if
(
!
p
)
continue
;
sh
->
dev
[
i
].
page
=
NULL
;
page_cache_release
(
p
);
}
}
static
int
grow_buffers
(
struct
stripe_head
*
sh
,
int
num
,
int
b_size
,
int
priority
)
static
int
grow_buffers
(
struct
stripe_head
*
sh
,
int
num
)
{
struct
buffer_head
*
bh
;
int
i
;
for
(
i
=
0
;
i
<
num
;
i
++
)
{
struct
page
*
page
;
bh
=
kmalloc
(
sizeof
(
struct
buffer_head
),
priority
);
if
(
!
bh
)
return
1
;
memset
(
bh
,
0
,
sizeof
(
struct
buffer_head
));
if
((
page
=
alloc_page
(
priority
)))
bh
->
b_data
=
page_address
(
page
);
else
{
kfree
(
bh
);
if
(
!
(
page
=
alloc_page
(
GFP_KERNEL
)))
{
return
1
;
}
atomic_set
(
&
bh
->
b_count
,
0
);
bh
->
b_page
=
page
;
sh
->
bh_cache
[
i
]
=
bh
;
sh
->
dev
[
i
].
page
=
page
;
}
return
0
;
}
static
struct
buffer_head
*
raid5_build_block
(
struct
stripe_head
*
sh
,
int
i
);
static
void
raid5_build_block
(
struct
stripe_head
*
sh
,
int
i
);
static
inline
void
init_stripe
(
struct
stripe_head
*
sh
,
unsigned
long
sector
)
static
inline
void
init_stripe
(
struct
stripe_head
*
sh
,
unsigned
long
sector
,
int
pd_idx
)
{
raid5_conf_t
*
conf
=
sh
->
raid_conf
;
int
disks
=
conf
->
raid_disks
,
i
;
...
...
@@ -198,40 +187,26 @@ static inline void init_stripe(struct stripe_head *sh, unsigned long sector)
remove_hash
(
sh
);
sh
->
sector
=
sector
;
sh
->
size
=
conf
->
buffer_size
;
sh
->
pd_idx
=
pd_idx
;
sh
->
state
=
0
;
for
(
i
=
disks
;
i
--
;
)
{
if
(
sh
->
bh_read
[
i
]
||
sh
->
bh_write
[
i
]
||
sh
->
bh_written
[
i
]
||
buffer_locked
(
sh
->
bh_cache
[
i
]))
{
struct
r5dev
*
dev
=
&
sh
->
dev
[
i
];
if
(
dev
->
toread
||
dev
->
towrite
||
dev
->
written
||
test_bit
(
R5_LOCKED
,
&
dev
->
flags
))
{
printk
(
"sector=%lx i=%d %p %p %p %d
\n
"
,
sh
->
sector
,
i
,
sh
->
bh_read
[
i
]
,
sh
->
bh_write
[
i
],
sh
->
bh_written
[
i
]
,
buffer_locked
(
sh
->
bh_cache
[
i
]
));
sh
->
sector
,
i
,
dev
->
toread
,
dev
->
towrite
,
dev
->
written
,
test_bit
(
R5_LOCKED
,
&
dev
->
flags
));
BUG
();
}
clear_buffer_uptodate
(
sh
->
bh_cache
[
i
])
;
dev
->
flags
=
0
;
raid5_build_block
(
sh
,
i
);
}
insert_hash
(
conf
,
sh
);
}
/* the buffer size has changed, so unhash all stripes
* as active stripes complete, they will go onto inactive list
*/
static
void
shrink_stripe_cache
(
raid5_conf_t
*
conf
)
{
int
i
;
CHECK_DEVLOCK
();
if
(
atomic_read
(
&
conf
->
active_stripes
))
BUG
();
for
(
i
=
0
;
i
<
NR_HASH
;
i
++
)
{
struct
stripe_head
*
sh
;
while
((
sh
=
conf
->
stripe_hashtbl
[
i
]))
remove_hash
(
sh
);
}
}
static
struct
stripe_head
*
__find_stripe
(
raid5_conf_t
*
conf
,
unsigned
long
sector
)
{
struct
stripe_head
*
sh
;
...
...
@@ -245,53 +220,16 @@ static struct stripe_head *__find_stripe(raid5_conf_t *conf, unsigned long secto
return
NULL
;
}
static
struct
stripe_head
*
get_active_stripe
(
raid5_conf_t
*
conf
,
unsigned
long
sector
,
int
size
,
int
noblock
)
static
struct
stripe_head
*
get_active_stripe
(
raid5_conf_t
*
conf
,
unsigned
long
sector
,
int
pd_idx
,
int
noblock
)
{
struct
stripe_head
*
sh
;
PRINTK
(
"get_stripe, sector %lu
\n
"
,
sector
);
md_
spin_lock_irq
(
&
conf
->
device_lock
);
spin_lock_irq
(
&
conf
->
device_lock
);
do
{
if
(
conf
->
buffer_size
==
0
||
(
size
&&
size
!=
conf
->
buffer_size
))
{
/* either the size is being changed (buffer_size==0) or
* we need to change it.
* If size==0, we can proceed as soon as buffer_size gets set.
* If size>0, we can proceed when active_stripes reaches 0, or
* when someone else sets the buffer_size to size.
* If someone sets the buffer size to something else, we will need to
* assert that we want to change it again
*/
int
oldsize
=
conf
->
buffer_size
;
PRINTK
(
"get_stripe %ld/%d buffer_size is %d, %d active
\n
"
,
sector
,
size
,
conf
->
buffer_size
,
atomic_read
(
&
conf
->
active_stripes
));
if
(
size
==
0
)
wait_event_lock_irq
(
conf
->
wait_for_stripe
,
conf
->
buffer_size
,
conf
->
device_lock
);
else
{
while
(
conf
->
buffer_size
!=
size
&&
atomic_read
(
&
conf
->
active_stripes
))
{
conf
->
buffer_size
=
0
;
wait_event_lock_irq
(
conf
->
wait_for_stripe
,
atomic_read
(
&
conf
->
active_stripes
)
==
0
||
conf
->
buffer_size
,
conf
->
device_lock
);
PRINTK
(
"waited and now %ld/%d buffer_size is %d - %d active
\n
"
,
sector
,
size
,
conf
->
buffer_size
,
atomic_read
(
&
conf
->
active_stripes
));
}
if
(
conf
->
buffer_size
!=
size
)
{
printk
(
"raid5: switching cache buffer size, %d --> %d
\n
"
,
oldsize
,
size
);
shrink_stripe_cache
(
conf
);
if
(
size
==
0
)
BUG
();
conf
->
buffer_size
=
size
;
PRINTK
(
"size now %d
\n
"
,
conf
->
buffer_size
);
}
}
}
if
(
size
==
0
)
sector
-=
sector
&
((
conf
->
buffer_size
>>
9
)
-
1
);
sh
=
__find_stripe
(
conf
,
sector
);
if
(
!
sh
)
{
if
(
!
conf
->
inactive_blocked
)
...
...
@@ -307,7 +245,7 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, unsigned long s
conf
->
device_lock
);
conf
->
inactive_blocked
=
0
;
}
else
init_stripe
(
sh
,
sector
);
init_stripe
(
sh
,
sector
,
pd_idx
);
}
else
{
if
(
atomic_read
(
&
sh
->
count
))
{
if
(
!
list_empty
(
&
sh
->
lru
))
...
...
@@ -325,25 +263,35 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, unsigned long s
if
(
sh
)
atomic_inc
(
&
sh
->
count
);
md_
spin_unlock_irq
(
&
conf
->
device_lock
);
spin_unlock_irq
(
&
conf
->
device_lock
);
return
sh
;
}
static
int
grow_stripes
(
raid5_conf_t
*
conf
,
int
num
,
int
priority
)
static
int
grow_stripes
(
raid5_conf_t
*
conf
,
int
num
)
{
struct
stripe_head
*
sh
;
kmem_cache_t
*
sc
;
int
devs
=
conf
->
raid_disks
;
sprintf
(
conf
->
cache_name
,
"md/raid5-%d"
,
conf
->
mddev
->
__minor
);
sc
=
kmem_cache_create
(
conf
->
cache_name
,
sizeof
(
struct
stripe_head
)
+
(
devs
-
1
)
*
sizeof
(
struct
r5dev
),
0
,
0
,
NULL
,
NULL
);
if
(
!
sc
)
return
1
;
conf
->
slab_cache
=
sc
;
while
(
num
--
)
{
sh
=
km
alloc
(
sizeof
(
struct
stripe_head
),
priority
);
sh
=
km
em_cache_alloc
(
sc
,
GFP_KERNEL
);
if
(
!
sh
)
return
1
;
memset
(
sh
,
0
,
sizeof
(
*
sh
));
memset
(
sh
,
0
,
sizeof
(
*
sh
)
+
(
devs
-
1
)
*
sizeof
(
struct
r5dev
)
);
sh
->
raid_conf
=
conf
;
sh
->
lock
=
SPIN_LOCK_UNLOCKED
;
if
(
grow_buffers
(
sh
,
conf
->
raid_disks
,
PAGE_SIZE
,
priority
))
{
if
(
grow_buffers
(
sh
,
conf
->
raid_disks
))
{
shrink_buffers
(
sh
,
conf
->
raid_disks
);
k
free
(
sh
);
k
mem_cache_free
(
sc
,
sh
);
return
1
;
}
/* we just created an active stripe so... */
...
...
@@ -355,11 +303,11 @@ static int grow_stripes(raid5_conf_t *conf, int num, int priority)
return
0
;
}
static
void
shrink_stripes
(
raid5_conf_t
*
conf
,
int
num
)
static
void
shrink_stripes
(
raid5_conf_t
*
conf
)
{
struct
stripe_head
*
sh
;
while
(
num
--
)
{
while
(
1
)
{
spin_lock_irq
(
&
conf
->
device_lock
);
sh
=
get_free_stripe
(
conf
);
spin_unlock_irq
(
&
conf
->
device_lock
);
...
...
@@ -368,21 +316,22 @@ static void shrink_stripes(raid5_conf_t *conf, int num)
if
(
atomic_read
(
&
sh
->
count
))
BUG
();
shrink_buffers
(
sh
,
conf
->
raid_disks
);
k
free
(
sh
);
k
mem_cache_free
(
conf
->
slab_cache
,
sh
);
atomic_dec
(
&
conf
->
active_stripes
);
}
kmem_cache_destroy
(
conf
->
slab_cache
);
conf
->
slab_cache
=
NULL
;
}
static
void
raid5_end_read_request
(
struct
buffer_head
*
bh
,
int
uptodate
)
static
void
raid5_end_read_request
(
struct
bio
*
bi
)
{
struct
stripe_head
*
sh
=
b
h
->
b
_private
;
struct
stripe_head
*
sh
=
b
i
->
bi
_private
;
raid5_conf_t
*
conf
=
sh
->
raid_conf
;
int
disks
=
conf
->
raid_disks
,
i
;
unsigned
long
flags
;
int
uptodate
=
test_bit
(
BIO_UPTODATE
,
&
bi
->
bi_flags
)
;
for
(
i
=
0
;
i
<
disks
;
i
++
)
if
(
b
h
==
sh
->
bh_cache
[
i
]
)
if
(
b
i
==
&
sh
->
dev
[
i
].
req
)
break
;
PRINTK
(
"end_read_request %lu/%d, count: %d, uptodate %d.
\n
"
,
sh
->
sector
,
i
,
atomic_read
(
&
sh
->
count
),
uptodate
);
...
...
@@ -392,7 +341,9 @@ static void raid5_end_read_request (struct buffer_head * bh, int uptodate)
}
if
(
uptodate
)
{
struct
buffer_head
*
buffer
;
#if 0
struct bio *bio;
unsigned long flags;
spin_lock_irqsave(&conf->device_lock, flags);
/* we can return a buffer if we bypassed the cache or
* if the top buffer is not in highmem. If there are
...
...
@@ -409,38 +360,43 @@ static void raid5_end_read_request (struct buffer_head * bh, int uptodate)
} else
buffer = NULL;
spin_unlock_irqrestore(&conf->device_lock, flags);
if
(
sh
->
bh_page
[
i
]
==
NULL
)
if (sh->bh_page[i]==
bh->b_page
)
set_buffer_uptodate(bh);
if (buffer) {
if (buffer->b_page != bh->b_page)
memcpy(buffer->b_data, bh->b_data, bh->b_size);
buffer->b_end_io(buffer, 1);
}
#else
set_bit
(
R5_UPTODATE
,
&
sh
->
dev
[
i
].
flags
);
#endif
}
else
{
md_error
(
conf
->
mddev
,
b
h
->
b
_bdev
);
clear_b
uffer_uptodate
(
bh
);
md_error
(
conf
->
mddev
,
b
i
->
bi
_bdev
);
clear_b
it
(
R5_UPTODATE
,
&
sh
->
dev
[
i
].
flags
);
}
#if 0
/* must restore b_page before unlocking buffer... */
if
(
sh
->
bh_page
[
i
])
{
if (sh->bh_page[i]
!= bh->b_page
) {
bh->b_page = sh->bh_page[i];
bh->b_data = page_address(bh->b_page);
sh
->
bh_page
[
i
]
=
NULL
;
clear_buffer_uptodate(bh);
}
clear_buffer_locked
(
bh
);
#endif
clear_bit
(
R5_LOCKED
,
&
sh
->
dev
[
i
].
flags
);
set_bit
(
STRIPE_HANDLE
,
&
sh
->
state
);
release_stripe
(
sh
);
}
static
void
raid5_end_write_request
(
struct
b
uffer_head
*
bh
,
int
uptodate
)
static
void
raid5_end_write_request
(
struct
b
io
*
bi
)
{
struct
stripe_head
*
sh
=
b
h
->
b
_private
;
struct
stripe_head
*
sh
=
b
i
->
bi
_private
;
raid5_conf_t
*
conf
=
sh
->
raid_conf
;
int
disks
=
conf
->
raid_disks
,
i
;
unsigned
long
flags
;
int
uptodate
=
test_bit
(
BIO_UPTODATE
,
&
bi
->
bi_flags
);
for
(
i
=
0
;
i
<
disks
;
i
++
)
if
(
b
h
==
sh
->
bh_cache
[
i
]
)
if
(
b
i
==
&
sh
->
dev
[
i
].
req
)
break
;
PRINTK
(
"end_write_request %lu/%d, count %d, uptodate: %d.
\n
"
,
sh
->
sector
,
i
,
atomic_read
(
&
sh
->
count
),
uptodate
);
...
...
@@ -449,41 +405,48 @@ static void raid5_end_write_request (struct buffer_head *bh, int uptodate)
return
;
}
md_
spin_lock_irqsave
(
&
conf
->
device_lock
,
flags
);
spin_lock_irqsave
(
&
conf
->
device_lock
,
flags
);
if
(
!
uptodate
)
md_error
(
conf
->
mddev
,
bh
->
b_bdev
);
clear_buffer_locked
(
bh
);
md_error
(
conf
->
mddev
,
bi
->
bi_bdev
);
clear_bit
(
R5_LOCKED
,
&
sh
->
dev
[
i
].
flags
);
set_bit
(
STRIPE_HANDLE
,
&
sh
->
state
);
__release_stripe
(
conf
,
sh
);
md_
spin_unlock_irqrestore
(
&
conf
->
device_lock
,
flags
);
spin_unlock_irqrestore
(
&
conf
->
device_lock
,
flags
);
}
static
struct
buffer_head
*
raid5_build_block
(
struct
stripe_head
*
sh
,
int
i
)
static
unsigned
long
compute_blocknr
(
struct
stripe_head
*
sh
,
int
i
);
static
void
raid5_build_block
(
struct
stripe_head
*
sh
,
int
i
)
{
raid5_conf_t
*
conf
=
sh
->
raid_conf
;
struct
buffer_head
*
bh
=
sh
->
bh_cache
[
i
];
unsigned
long
block
=
sh
->
sector
/
(
sh
->
size
>>
9
);
init_buffer
(
bh
,
raid5_end_read_request
,
sh
);
bh
->
b_dev
=
conf
->
disks
[
i
].
dev
;
/* FIXME - later we will need bdev here */
bh
->
b_blocknr
=
block
;
bh
->
b_state
=
(
1
<<
BH_Req
)
|
(
1
<<
BH_Mapped
);
bh
->
b_size
=
sh
->
size
;
return
bh
;
struct
r5dev
*
dev
=
&
sh
->
dev
[
i
];
bio_init
(
&
dev
->
req
);
dev
->
req
.
bi_io_vec
=
&
dev
->
vec
;
dev
->
req
.
bi_vcnt
++
;
dev
->
vec
.
bv_page
=
dev
->
page
;
dev
->
vec
.
bv_len
=
STRIPE_SIZE
;
dev
->
vec
.
bv_offset
=
0
;
dev
->
req
.
bi_bdev
=
conf
->
disks
[
i
].
bdev
;
dev
->
req
.
bi_sector
=
sh
->
sector
;
dev
->
req
.
bi_private
=
sh
;
dev
->
flags
=
0
;
if
(
i
!=
sh
->
pd_idx
)
dev
->
sector
=
compute_blocknr
(
sh
,
i
);
}
static
int
raid5_
error
(
mddev_t
*
mddev
,
kdev_t
dev
)
static
int
error
(
mddev_t
*
mddev
,
kdev_t
dev
)
{
raid5_conf_t
*
conf
=
(
raid5_conf_t
*
)
mddev
->
private
;
mdp_super_t
*
sb
=
mddev
->
sb
;
struct
disk_info
*
disk
;
int
i
;
PRINTK
(
"raid5
_
error called
\n
"
);
PRINTK
(
"raid5
:
error called
\n
"
);
for
(
i
=
0
,
disk
=
conf
->
disks
;
i
<
conf
->
raid_disks
;
i
++
,
disk
++
)
{
if
(
kdev_same
(
disk
->
dev
,
dev
))
{
...
...
@@ -544,14 +507,14 @@ static int raid5_error (mddev_t *mddev, kdev_t dev)
* Input: a 'big' sector number,
* Output: index of the data and parity disk, and the sector # in them.
*/
static
unsigned
long
raid5_compute_sector
(
unsigned
long
r_sector
,
unsigned
int
raid_disks
,
static
unsigned
long
raid5_compute_sector
(
sector_t
r_sector
,
unsigned
int
raid_disks
,
unsigned
int
data_disks
,
unsigned
int
*
dd_idx
,
unsigned
int
*
pd_idx
,
raid5_conf_t
*
conf
)
{
unsigned
long
stripe
;
sector_t
stripe
;
unsigned
long
chunk_number
;
unsigned
int
chunk_offset
;
unsigned
long
new_sector
;
sector_t
new_sector
;
int
sectors_per_chunk
=
conf
->
chunk_size
>>
9
;
/* First compute the information on this sector */
...
...
@@ -607,17 +570,17 @@ static unsigned long raid5_compute_sector(unsigned long r_sector, unsigned int r
return
new_sector
;
}
#if 0
static
unsigned long
compute_blocknr(struct stripe_head *sh, int i)
static
sector_t
compute_blocknr
(
struct
stripe_head
*
sh
,
int
i
)
{
raid5_conf_t
*
conf
=
sh
->
raid_conf
;
int
raid_disks
=
conf
->
raid_disks
,
data_disks
=
raid_disks
-
1
;
unsigned long
new_sector = sh->sector, check;
sector_t
new_sector
=
sh
->
sector
,
check
;
int
sectors_per_chunk
=
conf
->
chunk_size
>>
9
;
unsigned long
stripe = new_sector / sectors_per_chunk;
sector_t
stripe
=
new_sector
/
sectors_per_chunk
;
int
chunk_offset
=
new_sector
%
sectors_per_chunk
;
int
chunk_number
,
dummy1
,
dummy2
,
dd_idx
=
i
;
unsigned long r_sector, blockn
r;
sector_t
r_secto
r
;
switch
(
conf
->
algorithm
)
{
case
ALGORITHM_LEFT_ASYMMETRIC
:
...
...
@@ -637,22 +600,72 @@ static unsigned long compute_blocknr(struct stripe_head *sh, int i)
chunk_number
=
stripe
*
data_disks
+
i
;
r_sector
=
chunk_number
*
sectors_per_chunk
+
chunk_offset
;
blocknr = r_sector / (sh->size >> 9);
check
=
raid5_compute_sector
(
r_sector
,
raid_disks
,
data_disks
,
&
dummy1
,
&
dummy2
,
conf
);
if
(
check
!=
sh
->
sector
||
dummy1
!=
dd_idx
||
dummy2
!=
sh
->
pd_idx
)
{
printk
(
"compute_blocknr: map not correct
\n
"
);
return
0
;
}
return
blockn
r;
return
r_secto
r
;
}
#endif
#define check_xor() do { \
if (count == MAX_XOR_BLOCKS) { \
xor_block(count, bh_ptr); \
count = 1; \
} \
/*
* Copy data between a page in the stripe cache, and one or more bion
* The page could align with the middle of the bio, or there could be
* several bion, each with several bio_vecs, which cover part of the page
* Multiple bion are linked together on bi_next. There may be extras
* at the end of this list. We ignore them.
*/
static
void
copy_data
(
int
frombio
,
struct
bio
*
bio
,
struct
page
*
page
,
sector_t
sector
)
{
char
*
pa
=
page_address
(
page
);
struct
bio_vec
*
bvl
;
int
i
;
for
(;
bio
&&
bio
->
bi_sector
<
sector
+
STRIPE_SECTORS
;
bio
=
bio
->
bi_next
)
{
int
page_offset
;
if
(
bio
->
bi_sector
>=
sector
)
page_offset
=
(
signed
)(
bio
->
bi_sector
-
sector
)
*
512
;
else
page_offset
=
(
signed
)(
sector
-
bio
->
bi_sector
)
*
-
512
;
bio_for_each_segment
(
bvl
,
bio
,
i
)
{
char
*
ba
=
__bio_kmap
(
bio
,
i
);
int
len
=
bio_iovec_idx
(
bio
,
i
)
->
bv_len
;
int
clen
;
int
b_offset
=
0
;
if
(
page_offset
<
0
)
{
b_offset
=
-
page_offset
;
page_offset
+=
b_offset
;
len
-=
b_offset
;
}
if
(
len
>
0
&&
page_offset
+
len
>
STRIPE_SIZE
)
clen
=
STRIPE_SIZE
-
page_offset
;
else
clen
=
len
;
if
(
len
>
0
)
{
if
(
frombio
)
memcpy
(
pa
+
page_offset
,
ba
+
b_offset
,
clen
);
else
memcpy
(
ba
+
b_offset
,
pa
+
page_offset
,
clen
);
}
__bio_kunmap
(
bio
,
i
);
page_offset
+=
len
;
}
}
}
#define check_xor() do { \
if (count == MAX_XOR_BLOCKS) { \
xor_block(count, STRIPE_SIZE, ptr); \
count = 1; \
} \
} while(0)
...
...
@@ -660,88 +673,84 @@ static void compute_block(struct stripe_head *sh, int dd_idx)
{
raid5_conf_t
*
conf
=
sh
->
raid_conf
;
int
i
,
count
,
disks
=
conf
->
raid_disks
;
struct
buffer_head
*
bh_ptr
[
MAX_XOR_BLOCKS
],
*
bh
;
void
*
ptr
[
MAX_XOR_BLOCKS
],
*
p
;
PRINTK
(
"compute_block, stripe %lu, idx %d
\n
"
,
sh
->
sector
,
dd_idx
);
memset
(
sh
->
bh_cache
[
dd_idx
]
->
b_data
,
0
,
sh
->
size
);
bh_ptr
[
0
]
=
sh
->
bh_cache
[
dd_idx
];
ptr
[
0
]
=
page_address
(
sh
->
dev
[
dd_idx
].
page
);
memset
(
ptr
[
0
],
0
,
STRIPE_SIZE
);
count
=
1
;
for
(
i
=
disks
;
i
--
;
)
{
if
(
i
==
dd_idx
)
continue
;
bh
=
sh
->
bh_cache
[
i
]
;
if
(
buffer_uptodate
(
bh
))
bh_ptr
[
count
++
]
=
bh
;
p
=
page_address
(
sh
->
dev
[
i
].
page
)
;
if
(
test_bit
(
R5_UPTODATE
,
&
sh
->
dev
[
i
].
flags
))
ptr
[
count
++
]
=
p
;
else
printk
(
"compute_block() %d, stripe %lu, %d not present
\n
"
,
dd_idx
,
sh
->
sector
,
i
);
check_xor
();
}
if
(
count
!=
1
)
xor_block
(
count
,
bh_
ptr
);
set_b
uffer_uptodate
(
sh
->
bh_cache
[
dd_idx
]
);
xor_block
(
count
,
STRIPE_SIZE
,
ptr
);
set_b
it
(
R5_UPTODATE
,
&
sh
->
dev
[
i
].
flags
);
}
static
void
compute_parity
(
struct
stripe_head
*
sh
,
int
method
)
{
raid5_conf_t
*
conf
=
sh
->
raid_conf
;
int
i
,
pd_idx
=
sh
->
pd_idx
,
disks
=
conf
->
raid_disks
,
count
;
struct
buffer_head
*
bh_
ptr
[
MAX_XOR_BLOCKS
];
struct
b
uffer_head
*
chosen
[
MD_SB_DISKS
];
void
*
ptr
[
MAX_XOR_BLOCKS
];
struct
b
io
*
chosen
[
MD_SB_DISKS
];
PRINTK
(
"compute_parity, stripe %lu, method %d
\n
"
,
sh
->
sector
,
method
);
memset
(
chosen
,
0
,
sizeof
(
chosen
));
count
=
1
;
bh_ptr
[
0
]
=
sh
->
bh_cache
[
pd_idx
]
;
ptr
[
0
]
=
page_address
(
sh
->
dev
[
pd_idx
].
page
)
;
switch
(
method
)
{
case
READ_MODIFY_WRITE
:
if
(
!
buffer_uptodate
(
sh
->
bh_cache
[
pd_idx
]
))
if
(
!
test_bit
(
R5_UPTODATE
,
&
sh
->
dev
[
pd_idx
].
flags
))
BUG
();
for
(
i
=
disks
;
i
--
;)
{
if
(
i
==
pd_idx
)
continue
;
if
(
sh
->
bh_write
[
i
]
&&
buffer_uptodate
(
sh
->
bh_cache
[
i
]
))
{
bh_ptr
[
count
++
]
=
sh
->
bh_cache
[
i
]
;
chosen
[
i
]
=
sh
->
bh_write
[
i
]
;
sh
->
bh_write
[
i
]
=
sh
->
bh_write
[
i
]
->
b_reqnext
;
chosen
[
i
]
->
b_reqnext
=
sh
->
bh_written
[
i
]
;
sh
->
bh_written
[
i
]
=
chosen
[
i
];
if
(
sh
->
dev
[
i
].
towrite
&&
test_bit
(
R5_UPTODATE
,
&
sh
->
dev
[
i
].
flags
))
{
ptr
[
count
++
]
=
page_address
(
sh
->
dev
[
i
].
page
)
;
chosen
[
i
]
=
sh
->
dev
[
i
].
towrite
;
sh
->
dev
[
i
].
towrite
=
NULL
;
if
(
sh
->
dev
[
i
].
written
)
BUG
()
;
sh
->
dev
[
i
].
written
=
chosen
[
i
];
check_xor
();
}
}
break
;
case
RECONSTRUCT_WRITE
:
memset
(
sh
->
bh_cache
[
pd_idx
]
->
b_data
,
0
,
sh
->
size
);
memset
(
ptr
[
0
],
0
,
STRIPE_SIZE
);
for
(
i
=
disks
;
i
--
;)
if
(
i
!=
pd_idx
&&
sh
->
bh_write
[
i
]
)
{
chosen
[
i
]
=
sh
->
bh_write
[
i
]
;
sh
->
bh_write
[
i
]
=
sh
->
bh_write
[
i
]
->
b_reqnext
;
chosen
[
i
]
->
b_reqnext
=
sh
->
bh_written
[
i
]
;
sh
->
bh_written
[
i
]
=
chosen
[
i
];
if
(
i
!=
pd_idx
&&
sh
->
dev
[
i
].
towrite
)
{
chosen
[
i
]
=
sh
->
dev
[
i
].
towrite
;
sh
->
dev
[
i
].
towrite
=
NULL
;
if
(
sh
->
dev
[
i
].
written
)
BUG
()
;
sh
->
dev
[
i
].
written
=
chosen
[
i
];
}
break
;
case
CHECK_PARITY
:
break
;
}
if
(
count
>
1
)
{
xor_block
(
count
,
bh_
ptr
);
xor_block
(
count
,
STRIPE_SIZE
,
ptr
);
count
=
1
;
}
for
(
i
=
disks
;
i
--
;)
if
(
chosen
[
i
])
{
struct
buffer_head
*
bh
=
sh
->
bh_cache
[
i
];
char
*
bdata
;
bdata
=
bh_kmap
(
chosen
[
i
]);
memcpy
(
bh
->
b_data
,
bdata
,
sh
->
size
);
bh_kunmap
(
chosen
[
i
]);
set_buffer_locked
(
bh
);
set_buffer_uptodate
(
bh
);
sector_t
sector
=
sh
->
dev
[
i
].
sector
;
copy_data
(
1
,
chosen
[
i
],
sh
->
dev
[
i
].
page
,
sector
);
set_bit
(
R5_LOCKED
,
&
sh
->
dev
[
i
].
flags
);
set_bit
(
R5_UPTODATE
,
&
sh
->
dev
[
i
].
flags
);
}
switch
(
method
)
{
...
...
@@ -749,55 +758,74 @@ static void compute_parity(struct stripe_head *sh, int method)
case
CHECK_PARITY
:
for
(
i
=
disks
;
i
--
;)
if
(
i
!=
pd_idx
)
{
bh_ptr
[
count
++
]
=
sh
->
bh_cache
[
i
]
;
ptr
[
count
++
]
=
page_address
(
sh
->
dev
[
i
].
page
)
;
check_xor
();
}
break
;
case
READ_MODIFY_WRITE
:
for
(
i
=
disks
;
i
--
;)
if
(
chosen
[
i
])
{
bh_ptr
[
count
++
]
=
sh
->
bh_cache
[
i
]
;
ptr
[
count
++
]
=
page_address
(
sh
->
dev
[
i
].
page
)
;
check_xor
();
}
}
if
(
count
!=
1
)
xor_block
(
count
,
bh_
ptr
);
xor_block
(
count
,
STRIPE_SIZE
,
ptr
);
if
(
method
!=
CHECK_PARITY
)
{
set_b
uffer_uptodate
(
sh
->
bh_cache
[
pd_idx
]
);
set_b
uffer_locked
(
sh
->
bh_cache
[
pd_idx
]
);
set_b
it
(
R5_UPTODATE
,
&
sh
->
dev
[
pd_idx
].
flags
);
set_b
it
(
R5_LOCKED
,
&
sh
->
dev
[
pd_idx
].
flags
);
}
else
clear_b
uffer_uptodate
(
sh
->
bh_cache
[
pd_idx
]
);
clear_b
it
(
R5_UPTODATE
,
&
sh
->
dev
[
pd_idx
].
flags
);
}
static
void
add_stripe_bh
(
struct
stripe_head
*
sh
,
struct
buffer_head
*
bh
,
int
dd_idx
,
int
rw
)
/*
* Each stripe/dev can have one or more bion attached.
* toread/towrite point to the first in a chain.
* The bi_next chain must be in order.
*/
static
void
add_stripe_bio
(
struct
stripe_head
*
sh
,
struct
bio
*
bi
,
int
dd_idx
,
int
forwrite
)
{
struct
b
uffer_head
**
bh
p
;
struct
b
io
**
bi
p
;
raid5_conf_t
*
conf
=
sh
->
raid_conf
;
PRINTK
(
"adding bh b#%lu to stripe s#%lu
\n
"
,
b
h
->
b_blockn
r
,
sh
->
sector
);
PRINTK
(
"adding bh b#%lu to stripe s#%lu
\n
"
,
b
i
->
bi_secto
r
,
sh
->
sector
);
spin_lock
(
&
sh
->
lock
);
spin_lock_irq
(
&
conf
->
device_lock
);
bh
->
b_reqnext
=
NULL
;
if
(
rw
==
READ
)
bhp
=
&
sh
->
bh_read
[
dd_idx
];
if
(
forwrite
)
bip
=
&
sh
->
dev
[
dd_idx
].
towrite
;
else
bhp
=
&
sh
->
bh_write
[
dd_idx
];
while
(
*
bhp
)
{
printk
(
KERN_NOTICE
"raid5: multiple %d requests for sector %ld
\n
"
,
rw
,
sh
->
sector
);
bhp
=
&
(
*
bhp
)
->
b_reqnext
;
}
*
bhp
=
bh
;
bip
=
&
sh
->
dev
[
dd_idx
].
toread
;
while
(
*
bip
&&
(
*
bip
)
->
bi_sector
<
bi
->
bi_sector
)
bip
=
&
(
*
bip
)
->
bi_next
;
/* FIXME do I need to worry about overlapping bion */
if
(
*
bip
&&
bi
->
bi_next
&&
(
*
bip
)
!=
bi
->
bi_next
)
BUG
();
if
(
*
bip
)
bi
->
bi_next
=
*
bip
;
*
bip
=
bi
;
bi
->
bi_phys_segments
++
;
spin_unlock_irq
(
&
conf
->
device_lock
);
spin_unlock
(
&
sh
->
lock
);
PRINTK
(
"added bh b#%lu to stripe s#%lu, disk %d.
\n
"
,
bh
->
b_blocknr
,
sh
->
sector
,
dd_idx
);
}
if
(
forwrite
)
{
/* check if page is coverred */
sector_t
sector
=
sh
->
dev
[
dd_idx
].
sector
;
for
(
bi
=
sh
->
dev
[
dd_idx
].
towrite
;
sector
<
sh
->
dev
[
dd_idx
].
sector
+
STRIPE_SECTORS
&&
bi
&&
bi
->
bi_sector
<=
sector
;
bi
=
bi
->
bi_next
)
{
if
(
bi
->
bi_sector
+
(
bi
->
bi_size
>>
9
)
>=
sector
)
sector
=
bi
->
bi_sector
+
(
bi
->
bi_size
>>
9
);
}
if
(
sector
>=
sh
->
dev
[
dd_idx
].
sector
+
STRIPE_SECTORS
)
set_bit
(
R5_OVERWRITE
,
&
sh
->
dev
[
dd_idx
].
flags
);
}
PRINTK
(
"added bi b#%lu to stripe s#%lu, disk %d.
\n
"
,
bi
->
bi_sector
,
sh
->
sector
,
dd_idx
);
}
/*
...
...
@@ -822,13 +850,14 @@ static void handle_stripe(struct stripe_head *sh)
{
raid5_conf_t
*
conf
=
sh
->
raid_conf
;
int
disks
=
conf
->
raid_disks
;
struct
buffer_head
*
return_ok
=
NULL
,
*
return_fail
=
NULL
;
struct
bio
*
return_bi
=
NULL
;
struct
bio
*
bi
;
int
action
[
MD_SB_DISKS
];
int
i
;
int
syncing
;
int
locked
=
0
,
uptodate
=
0
,
to_read
=
0
,
to_write
=
0
,
failed
=
0
,
written
=
0
;
int
failed_num
=
0
;
struct
buffer_head
*
bh
;
struct
r5dev
*
dev
;
PRINTK
(
"handling stripe %ld, cnt=%d, pd_idx=%d
\n
"
,
sh
->
sector
,
atomic_read
(
&
sh
->
count
),
sh
->
pd_idx
);
memset
(
action
,
0
,
sizeof
(
action
));
...
...
@@ -841,36 +870,38 @@ static void handle_stripe(struct stripe_head *sh)
/* Now to look around and see what can be done */
for
(
i
=
disks
;
i
--
;
)
{
bh
=
sh
->
bh_cache
[
i
];
PRINTK
(
"check %d: state 0x%lx read %p write %p written %p
\n
"
,
i
,
bh
->
b_state
,
sh
->
bh_read
[
i
],
sh
->
bh_write
[
i
],
sh
->
bh_written
[
i
]);
dev
=
&
sh
->
dev
[
i
];
PRINTK
(
"check %d: state 0x%lx read %p write %p written %p
\n
"
,
i
,
dev
->
flags
,
dev
->
toread
,
dev
->
towrite
,
dev
->
written
);
/* maybe we can reply to a read */
if
(
buffer_uptodate
(
bh
)
&&
sh
->
bh_read
[
i
]
)
{
struct
b
uffer_head
*
rbh
,
*
rbh
2
;
if
(
test_bit
(
R5_UPTODATE
,
&
dev
->
flags
)
&&
dev
->
toread
)
{
struct
b
io
*
rbi
,
*
rbi
2
;
PRINTK
(
"Return read for disc %d
\n
"
,
i
);
spin_lock_irq
(
&
conf
->
device_lock
);
rb
h
=
sh
->
bh_read
[
i
]
;
sh
->
bh_read
[
i
]
=
NULL
;
rb
i
=
dev
->
toread
;
dev
->
toread
=
NULL
;
spin_unlock_irq
(
&
conf
->
device_lock
);
while
(
rbh
)
{
char
*
bdata
;
bdata
=
bh_kmap
(
rbh
);
memcpy
(
bdata
,
bh
->
b_data
,
bh
->
b_size
);
bh_kunmap
(
rbh
);
rbh2
=
rbh
->
b_reqnext
;
rbh
->
b_reqnext
=
return_ok
;
return_ok
=
rbh
;
rbh
=
rbh2
;
while
(
rbi
&&
rbi
->
bi_sector
<
dev
->
sector
+
STRIPE_SECTORS
)
{
copy_data
(
0
,
rbi
,
dev
->
page
,
dev
->
sector
);
rbi2
=
rbi
->
bi_next
;
spin_lock_irq
(
&
conf
->
device_lock
);
if
(
--
rbi
->
bi_phys_segments
==
0
)
{
rbi
->
bi_next
=
return_bi
;
return_bi
=
rbi
;
}
spin_unlock_irq
(
&
conf
->
device_lock
);
rbi
=
rbi2
;
}
}
/* now count some things */
if
(
buffer_locked
(
bh
))
locked
++
;
if
(
buffer_uptodate
(
bh
))
uptodate
++
;
if
(
test_bit
(
R5_LOCKED
,
&
dev
->
flags
))
locked
++
;
if
(
test_bit
(
R5_UPTODATE
,
&
dev
->
flags
))
uptodate
++
;
if
(
sh
->
bh_read
[
i
]
)
to_read
++
;
if
(
sh
->
bh_write
[
i
]
)
to_write
++
;
if
(
sh
->
bh_written
[
i
]
)
written
++
;
if
(
dev
->
toread
)
to_read
++
;
if
(
dev
->
towrite
)
to_write
++
;
if
(
dev
->
written
)
written
++
;
if
(
!
conf
->
disks
[
i
].
operational
)
{
failed
++
;
failed_num
=
i
;
...
...
@@ -882,29 +913,42 @@ static void handle_stripe(struct stripe_head *sh)
* need to be failed
*/
if
(
failed
>
1
&&
to_read
+
to_write
)
{
spin_lock_irq
(
&
conf
->
device_lock
);
for
(
i
=
disks
;
i
--
;
)
{
/* fail all writes first */
if
(
sh
->
bh_write
[
i
])
to_write
--
;
while
((
bh
=
sh
->
bh_write
[
i
]))
{
sh
->
bh_write
[
i
]
=
bh
->
b_reqnext
;
bh
->
b_reqnext
=
return_fail
;
return_fail
=
bh
;
bi
=
sh
->
dev
[
i
].
towrite
;
sh
->
dev
[
i
].
towrite
=
NULL
;
if
(
bi
)
to_write
--
;
while
(
bi
&&
bi
->
bi_sector
<
sh
->
dev
[
i
].
sector
+
STRIPE_SECTORS
){
struct
bio
*
nextbi
=
bi
->
bi_next
;
clear_bit
(
BIO_UPTODATE
,
&
bi
->
bi_flags
);
if
(
--
bi
->
bi_phys_segments
==
0
)
{
bi
->
bi_next
=
return_bi
;
return_bi
=
bi
;
}
bi
=
nextbi
;
}
/* fail any reads if this device is non-operational */
if
(
!
conf
->
disks
[
i
].
operational
)
{
spin_lock_irq
(
&
conf
->
device_lock
);
if
(
sh
->
bh_read
[
i
])
to_read
--
;
while
((
bh
=
sh
->
bh_read
[
i
]))
{
sh
->
bh_read
[
i
]
=
bh
->
b_reqnext
;
bh
->
b_reqnext
=
return_fail
;
return_fail
=
bh
;
bi
=
sh
->
dev
[
i
].
toread
;
sh
->
dev
[
i
].
toread
=
NULL
;
if
(
bi
)
to_read
--
;
while
(
bi
&&
bi
->
bi_sector
<
sh
->
dev
[
i
].
sector
+
STRIPE_SECTORS
){
struct
bio
*
nextbi
=
bi
->
bi_next
;
clear_bit
(
BIO_UPTODATE
,
&
bi
->
bi_flags
);
if
(
--
bi
->
bi_phys_segments
==
0
)
{
bi
->
bi_next
=
return_bi
;
return_bi
=
bi
;
}
bi
=
nextbi
;
}
spin_unlock_irq
(
&
conf
->
device_lock
);
}
}
spin_unlock_irq
(
&
conf
->
device_lock
);
}
if
(
failed
>
1
&&
syncing
)
{
md_done_sync
(
conf
->
mddev
,
(
sh
->
size
>>
9
)
-
sh
->
sync_redone
,
0
);
md_done_sync
(
conf
->
mddev
,
STRIPE_SECTORS
,
0
);
clear_bit
(
STRIPE_SYNCING
,
&
sh
->
state
);
syncing
=
0
;
}
...
...
@@ -912,40 +956,43 @@ static void handle_stripe(struct stripe_head *sh)
/* might be able to return some write requests if the parity block
* is safe, or on a failed drive
*/
bh
=
sh
->
bh_cache
[
sh
->
pd_idx
];
dev
=
&
sh
->
dev
[
sh
->
pd_idx
];
if
(
written
&&
(
(
conf
->
disks
[
sh
->
pd_idx
].
operational
&&
!
buffer_locked
(
bh
)
&&
buffer_uptodate
(
bh
))
(
(
conf
->
disks
[
sh
->
pd_idx
].
operational
&&
!
test_bit
(
R5_LOCKED
,
&
dev
->
flags
)
&&
test_bit
(
R5_UPTODATE
,
&
dev
->
flags
))
||
(
failed
==
1
&&
failed_num
==
sh
->
pd_idx
))
)
{
/* any written block on a uptodate or failed drive can be returned */
/* any written block on a
n
uptodate or failed drive can be returned */
for
(
i
=
disks
;
i
--
;
)
if
(
sh
->
bh_written
[
i
]
)
{
bh
=
sh
->
bh_cache
[
i
];
if
(
sh
->
dev
[
i
].
written
)
{
dev
=
&
sh
->
dev
[
i
];
if
(
!
conf
->
disks
[
sh
->
pd_idx
].
operational
||
(
!
buffer_locked
(
bh
)
&&
buffer_uptodate
(
bh
))
)
{
(
!
test_bit
(
R5_LOCKED
,
&
dev
->
flags
)
&&
test_bit
(
R5_UPTODATE
,
&
dev
->
flags
))
)
{
/* maybe we can return some write requests */
struct
buffer_head
*
wbh
,
*
wbh2
;
PRINTK
(
"Return write for disc %d
\n
"
,
i
);
wbh
=
sh
->
bh_written
[
i
];
sh
->
bh_written
[
i
]
=
NULL
;
while
(
wbh
)
{
wbh2
=
wbh
->
b_reqnext
;
wbh
->
b_reqnext
=
return_ok
;
return_ok
=
wbh
;
wbh
=
wbh2
;
}
struct
bio
*
wbi
,
*
wbi2
;
PRINTK
(
"Return write for disc %d
\n
"
,
i
);
wbi
=
dev
->
written
;
dev
->
written
=
NULL
;
while
(
wbi
&&
wbi
->
bi_sector
<
dev
->
sector
+
STRIPE_SECTORS
)
{
wbi2
=
wbi
->
bi_next
;
if
(
--
wbi
->
bi_phys_segments
==
0
)
{
wbi
->
bi_next
=
return_bi
;
return_bi
=
wbi
;
}
wbi
=
wbi2
;
}
}
}
}
/* Now we might consider reading some blocks, either to check/generate
* parity, or to satisfy requests
*/
if
(
to_read
||
(
syncing
&&
(
uptodate
+
failed
<
disks
)))
{
for
(
i
=
disks
;
i
--
;)
{
bh
=
sh
->
bh_cache
[
i
];
if
(
!
buffer_locked
(
bh
)
&&
!
buffer_uptodate
(
bh
)
&&
(
sh
->
bh_read
[
i
]
||
syncing
||
(
failed
&&
sh
->
bh_read
[
failed_num
]
)))
{
dev
=
&
sh
->
dev
[
i
];
if
(
!
test_bit
(
R5_LOCKED
,
&
dev
->
flags
)
&&
!
test_bit
(
R5_UPTODATE
,
&
dev
->
flags
)
&&
(
dev
->
toread
||
syncing
||
(
failed
&&
sh
->
dev
[
failed_num
].
toread
)))
{
/* we would like to get this block, possibly
* by computing it, but we might not be able to
*/
...
...
@@ -954,21 +1001,21 @@ static void handle_stripe(struct stripe_head *sh)
compute_block
(
sh
,
i
);
uptodate
++
;
}
else
if
(
conf
->
disks
[
i
].
operational
)
{
set_b
uffer_locked
(
bh
);
set_b
it
(
R5_LOCKED
,
&
dev
->
flags
);
action
[
i
]
=
READ
+
1
;
#if 0
/* if I am just reading this block and we don't have
a failed drive, or any pending writes then sidestep the cache */
if
(
sh
->
bh_page
[
i
])
BUG
();
if (sh->bh_read[i] && !sh->bh_read[i]->b_reqnext &&
! syncing && !failed && !to_write) {
sh
->
bh_page
[
i
]
=
sh
->
bh_cache
[
i
]
->
b_page
;
sh->bh_cache[i]->b_page = sh->bh_read[i]->b_page;
sh->bh_cache[i]->b_data = sh->bh_read[i]->b_data;
}
#endif
locked
++
;
PRINTK
(
"Reading block %d (sync=%d)
\n
"
,
i
,
syncing
);
if
(
syncing
)
md_sync_acct
(
conf
->
disks
[
i
].
dev
,
bh
->
b_size
>>
9
);
md_sync_acct
(
conf
->
disks
[
i
].
dev
,
STRIPE_SECTORS
);
}
}
}
...
...
@@ -980,10 +1027,14 @@ static void handle_stripe(struct stripe_head *sh)
int
rmw
=
0
,
rcw
=
0
;
for
(
i
=
disks
;
i
--
;)
{
/* would I have to read this buffer for read_modify_write */
bh
=
sh
->
bh_cache
[
i
];
if
((
sh
->
bh_write
[
i
]
||
i
==
sh
->
pd_idx
)
&&
(
!
buffer_locked
(
bh
)
||
sh
->
bh_page
[
i
])
&&
!
buffer_uptodate
(
bh
))
{
dev
=
&
sh
->
dev
[
i
];
if
((
dev
->
towrite
||
i
==
sh
->
pd_idx
)
&&
(
!
test_bit
(
R5_LOCKED
,
&
dev
->
flags
)
#if 0
|| sh->bh_page[i]!=bh->b_page
#endif
)
&&
!
test_bit
(
R5_UPTODATE
,
&
dev
->
flags
))
{
if
(
conf
->
disks
[
i
].
operational
/* && !(conf->resync_parity && i == sh->pd_idx) */
)
...
...
@@ -991,9 +1042,13 @@ static void handle_stripe(struct stripe_head *sh)
else
rmw
+=
2
*
disks
;
/* cannot read it */
}
/* Would I have to read this buffer for reconstruct_write */
if
(
!
sh
->
bh_write
[
i
]
&&
i
!=
sh
->
pd_idx
&&
(
!
buffer_locked
(
bh
)
||
sh
->
bh_page
[
i
])
&&
!
buffer_uptodate
(
bh
))
{
if
(
!
test_bit
(
R5_OVERWRITE
,
&
dev
->
flags
)
&&
i
!=
sh
->
pd_idx
&&
(
!
test_bit
(
R5_LOCKED
,
&
dev
->
flags
)
#if 0
|| sh->bh_page[i] != bh->b_page
#endif
)
&&
!
test_bit
(
R5_UPTODATE
,
&
dev
->
flags
))
{
if
(
conf
->
disks
[
i
].
operational
)
rcw
++
;
else
rcw
+=
2
*
disks
;
}
...
...
@@ -1003,14 +1058,14 @@ static void handle_stripe(struct stripe_head *sh)
if
(
rmw
<
rcw
&&
rmw
>
0
)
/* prefer read-modify-write, but need to get some data */
for
(
i
=
disks
;
i
--
;)
{
bh
=
sh
->
bh_cache
[
i
];
if
((
sh
->
bh_write
[
i
]
||
i
==
sh
->
pd_idx
)
&&
!
buffer_locked
(
bh
)
&&
!
buffer_uptodate
(
bh
)
&&
dev
=
&
sh
->
dev
[
i
];
if
((
dev
->
towrite
||
i
==
sh
->
pd_idx
)
&&
!
test_bit
(
R5_LOCKED
,
&
dev
->
flags
)
&&
!
test_bit
(
R5_UPTODATE
,
&
dev
->
flags
)
&&
conf
->
disks
[
i
].
operational
)
{
if
(
test_bit
(
STRIPE_PREREAD_ACTIVE
,
&
sh
->
state
))
{
PRINTK
(
"Read_old block %d for r-m-w
\n
"
,
i
);
set_b
uffer_locked
(
bh
);
set_b
it
(
R5_LOCKED
,
&
dev
->
flags
);
action
[
i
]
=
READ
+
1
;
locked
++
;
}
else
{
...
...
@@ -1022,14 +1077,14 @@ static void handle_stripe(struct stripe_head *sh)
if
(
rcw
<=
rmw
&&
rcw
>
0
)
/* want reconstruct write, but need to get some data */
for
(
i
=
disks
;
i
--
;)
{
bh
=
sh
->
bh_cache
[
i
];
if
(
!
sh
->
bh_write
[
i
]
&&
i
!=
sh
->
pd_idx
&&
!
buffer_locked
(
bh
)
&&
!
buffer_uptodate
(
bh
)
&&
dev
=
&
sh
->
dev
[
i
];
if
(
!
test_bit
(
R5_OVERWRITE
,
&
dev
->
flags
)
&&
i
!=
sh
->
pd_idx
&&
!
test_bit
(
R5_LOCKED
,
&
dev
->
flags
)
&&
!
test_bit
(
R5_UPTODATE
,
&
dev
->
flags
)
&&
conf
->
disks
[
i
].
operational
)
{
if
(
test_bit
(
STRIPE_PREREAD_ACTIVE
,
&
sh
->
state
))
{
PRINTK
(
"Read_old block %d for Reconstruct
\n
"
,
i
);
set_b
uffer_locked
(
bh
);
set_b
it
(
R5_LOCKED
,
&
dev
->
flags
);
action
[
i
]
=
READ
+
1
;
locked
++
;
}
else
{
...
...
@@ -1044,7 +1099,7 @@ static void handle_stripe(struct stripe_head *sh)
compute_parity
(
sh
,
rcw
==
0
?
RECONSTRUCT_WRITE
:
READ_MODIFY_WRITE
);
/* now every locked buffer is ready to be written */
for
(
i
=
disks
;
i
--
;)
if
(
buffer_locked
(
sh
->
bh_cache
[
i
]
))
{
if
(
test_bit
(
R5_LOCKED
,
&
sh
->
dev
[
i
].
flags
))
{
PRINTK
(
"Writing block %d
\n
"
,
i
);
locked
++
;
action
[
i
]
=
WRITE
+
1
;
...
...
@@ -1068,13 +1123,14 @@ static void handle_stripe(struct stripe_head *sh)
!
test_bit
(
STRIPE_INSYNC
,
&
sh
->
state
)
&&
failed
<=
1
)
{
set_bit
(
STRIPE_HANDLE
,
&
sh
->
state
);
if
(
failed
==
0
)
{
char
*
pagea
;
if
(
uptodate
!=
disks
)
BUG
();
compute_parity
(
sh
,
CHECK_PARITY
);
uptodate
--
;
bh
=
sh
->
bh_cache
[
sh
->
pd_idx
]
;
if
((
*
(
u32
*
)
bh
->
b_dat
a
)
==
0
&&
!
memcmp
(
bh
->
b_data
,
bh
->
b_data
+
4
,
bh
->
b_size
-
4
))
{
pagea
=
page_address
(
sh
->
dev
[
sh
->
pd_idx
].
page
)
;
if
((
*
(
u32
*
)
page
a
)
==
0
&&
!
memcmp
(
pagea
,
pagea
+
4
,
STRIPE_SIZE
-
4
))
{
/* parity is correct (on disc, not in buffer any more) */
set_bit
(
STRIPE_INSYNC
,
&
sh
->
state
);
}
...
...
@@ -1084,7 +1140,7 @@ static void handle_stripe(struct stripe_head *sh)
if
(
failed
==
0
)
failed_num
=
sh
->
pd_idx
;
/* should be able to compute the missing block and write it to spare */
if
(
!
buffer_uptodate
(
sh
->
bh_cache
[
failed_num
]
))
{
if
(
!
test_bit
(
R5_UPTODATE
,
&
sh
->
dev
[
failed_num
].
flags
))
{
if
(
uptodate
+
1
!=
disks
)
BUG
();
compute_block
(
sh
,
failed_num
);
...
...
@@ -1092,60 +1148,62 @@ static void handle_stripe(struct stripe_head *sh)
}
if
(
uptodate
!=
disks
)
BUG
();
bh
=
sh
->
bh_cache
[
failed_num
];
set_b
uffer_locked
(
bh
);
dev
=
&
sh
->
dev
[
failed_num
];
set_b
it
(
R5_LOCKED
,
&
dev
->
flags
);
action
[
failed_num
]
=
WRITE
+
1
;
locked
++
;
set_bit
(
STRIPE_INSYNC
,
&
sh
->
state
);
if
(
conf
->
disks
[
failed_num
].
operational
)
md_sync_acct
(
conf
->
disks
[
failed_num
].
dev
,
bh
->
b_size
>>
9
);
md_sync_acct
(
conf
->
disks
[
failed_num
].
dev
,
STRIPE_SECTORS
);
else
if
((
spare
=
conf
->
spare
))
md_sync_acct
(
spare
->
dev
,
bh
->
b_size
>>
9
);
md_sync_acct
(
spare
->
dev
,
STRIPE_SECTORS
);
}
}
if
(
syncing
&&
locked
==
0
&&
test_bit
(
STRIPE_INSYNC
,
&
sh
->
state
))
{
md_done_sync
(
conf
->
mddev
,
(
sh
->
size
>>
9
)
-
sh
->
sync_redone
,
1
);
md_done_sync
(
conf
->
mddev
,
STRIPE_SECTORS
,
1
);
clear_bit
(
STRIPE_SYNCING
,
&
sh
->
state
);
}
spin_unlock
(
&
sh
->
lock
);
while
((
bh
=
return_ok
))
{
return_ok
=
bh
->
b_reqnext
;
bh
->
b_reqnext
=
NULL
;
bh
->
b_end_io
(
bh
,
1
);
}
while
((
bh
=
return_fail
))
{
return_fail
=
bh
->
b_reqnext
;
bh
->
b_reqnext
=
NULL
;
bh
->
b_end_io
(
bh
,
0
);
while
((
bi
=
return_bi
))
{
return_bi
=
bi
->
bi_next
;
bi
->
bi_next
=
NULL
;
bi
->
bi_end_io
(
bi
);
}
for
(
i
=
disks
;
i
--
;)
if
(
action
[
i
])
{
struct
b
uffer_head
*
bh
=
sh
->
bh_cache
[
i
]
;
struct
b
io
*
bi
=
&
sh
->
dev
[
i
].
req
;
struct
disk_info
*
spare
=
conf
->
spare
;
int
skip
=
0
;
if
(
action
[
i
]
==
READ
+
1
)
b
h
->
b
_end_io
=
raid5_end_read_request
;
b
i
->
bi
_end_io
=
raid5_end_read_request
;
else
b
h
->
b
_end_io
=
raid5_end_write_request
;
b
i
->
bi
_end_io
=
raid5_end_write_request
;
if
(
conf
->
disks
[
i
].
operational
)
b
h
->
b_dev
=
conf
->
disks
[
i
].
dev
;
b
i
->
bi_bdev
=
conf
->
disks
[
i
].
b
dev
;
else
if
(
spare
&&
action
[
i
]
==
WRITE
+
1
)
b
h
->
b_dev
=
spare
->
dev
;
b
i
->
bi_bdev
=
spare
->
b
dev
;
else
skip
=
1
;
/* FIXME - later we will need bdev here */
if
(
!
skip
)
{
PRINTK
(
"for %ld schedule op %d on disc %d
\n
"
,
sh
->
sector
,
action
[
i
]
-
1
,
i
);
atomic_inc
(
&
sh
->
count
);
bh
->
b_rdev
=
bh
->
b_dev
;
bh
->
b_rsector
=
bh
->
b_blocknr
*
(
bh
->
b_size
>>
9
);
generic_make_request
(
action
[
i
]
-
1
,
bh
);
bi
->
bi_sector
=
sh
->
sector
;
if
(
action
[
i
]
==
READ
+
1
)
bi
->
bi_rw
=
0
;
else
bi
->
bi_rw
=
1
;
bi
->
bi_flags
=
0
;
bi
->
bi_vcnt
=
1
;
bi
->
bi_idx
=
0
;
bi
->
bi_io_vec
=
&
sh
->
dev
[
i
].
vec
;
bi
->
bi_size
=
STRIPE_SIZE
;
bi
->
bi_next
=
NULL
;
generic_make_request
(
bi
);
}
else
{
PRINTK
(
"skip op %d on disc %d for sector %ld
\n
"
,
action
[
i
]
-
1
,
i
,
sh
->
sector
);
clear_b
uffer_locked
(
bh
);
clear_b
it
(
R5_LOCKED
,
&
dev
->
flags
);
set_bit
(
STRIPE_HANDLE
,
&
sh
->
state
);
}
}
...
...
@@ -1192,13 +1250,14 @@ static inline void raid5_plug_device(raid5_conf_t *conf)
spin_unlock_irq
(
&
conf
->
device_lock
);
}
static
int
raid5_make_request
(
mddev_t
*
mddev
,
int
rw
,
struct
buffer_head
*
bh
)
static
int
make_request
(
mddev_t
*
mddev
,
int
rw
,
struct
bio
*
bi
)
{
raid5_conf_t
*
conf
=
(
raid5_conf_t
*
)
mddev
->
private
;
const
unsigned
int
raid_disks
=
conf
->
raid_disks
;
const
unsigned
int
data_disks
=
raid_disks
-
1
;
unsigned
int
dd_idx
,
pd_idx
;
unsigned
long
new_sector
;
sector_t
new_sector
;
sector_t
logical_sector
,
last_sector
;
int
read_ahead
=
0
;
struct
stripe_head
*
sh
;
...
...
@@ -1208,25 +1267,39 @@ static int raid5_make_request (mddev_t *mddev, int rw, struct buffer_head * bh)
read_ahead
=
1
;
}
new_sector
=
raid5_compute_sector
(
bh
->
b_rsector
,
raid_disks
,
data_disks
,
&
dd_idx
,
&
pd_idx
,
conf
);
logical_sector
=
bi
->
bi_sector
&
~
(
STRIPE_SECTORS
-
1
);
last_sector
=
bi
->
bi_sector
+
(
bi
->
bi_size
>>
9
);
PRINTK
(
"raid5_make_request, sector %lu
\n
"
,
new_sector
);
sh
=
get_active_stripe
(
conf
,
new_sector
,
bh
->
b_size
,
read_ahead
);
if
(
sh
)
{
sh
->
pd_idx
=
pd_idx
;
bi
->
bi_next
=
NULL
;
set_bit
(
BIO_UPTODATE
,
&
bi
->
bi_flags
);
/* will be cleared if error detected */
bi
->
bi_phys_segments
=
1
;
/* over-loaded to count active stripes */
for
(;
logical_sector
<
last_sector
;
logical_sector
+=
STRIPE_SECTORS
)
{
new_sector
=
raid5_compute_sector
(
logical_sector
,
raid_disks
,
data_disks
,
&
dd_idx
,
&
pd_idx
,
conf
);
add_stripe_bh
(
sh
,
bh
,
dd_idx
,
rw
);
PRINTK
(
"raid5: make_request, sector %ul logical %ul
\n
"
,
new_sector
,
logical_sector
);
raid5_plug_device
(
conf
);
handle_stripe
(
sh
);
release_stripe
(
sh
);
}
else
bh
->
b_end_io
(
bh
,
buffer_uptodate
(
bh
));
sh
=
get_active_stripe
(
conf
,
new_sector
,
pd_idx
,
read_ahead
);
if
(
sh
)
{
add_stripe_bio
(
sh
,
bi
,
dd_idx
,
rw
);
raid5_plug_device
(
conf
);
handle_stripe
(
sh
);
release_stripe
(
sh
);
}
}
spin_lock_irq
(
&
conf
->
device_lock
);
if
(
--
bi
->
bi_phys_segments
==
0
)
bi
->
bi_end_io
(
bi
);
spin_unlock_irq
(
&
conf
->
device_lock
);
return
0
;
}
static
int
raid5_sync_request
(
mddev_t
*
mddev
,
unsigned
long
sector_nr
)
/* FIXME go_faster isn't used */
static
int
sync_request
(
mddev_t
*
mddev
,
sector_t
sector_nr
,
int
go_faster
)
{
raid5_conf_t
*
conf
=
(
raid5_conf_t
*
)
mddev
->
private
;
struct
stripe_head
*
sh
;
...
...
@@ -1237,25 +1310,19 @@ static int raid5_sync_request (mddev_t *mddev, unsigned long sector_nr)
unsigned
long
first_sector
;
int
raid_disks
=
conf
->
raid_disks
;
int
data_disks
=
raid_disks
-
1
;
int
redone
=
0
;
int
bufsize
;
sh
=
get_active_stripe
(
conf
,
sector_nr
,
0
,
0
);
bufsize
=
sh
->
size
;
redone
=
sector_nr
-
sh
->
sector
;
first_sector
=
raid5_compute_sector
(
stripe
*
data_disks
*
sectors_per_chunk
+
chunk_offset
,
raid_disks
,
data_disks
,
&
dd_idx
,
&
pd_idx
,
conf
);
sh
->
pd_idx
=
pd_idx
;
sh
=
get_active_stripe
(
conf
,
sector_nr
,
pd_idx
,
0
)
;
spin_lock
(
&
sh
->
lock
);
set_bit
(
STRIPE_SYNCING
,
&
sh
->
state
);
clear_bit
(
STRIPE_INSYNC
,
&
sh
->
state
);
sh
->
sync_redone
=
redone
;
spin_unlock
(
&
sh
->
lock
);
handle_stripe
(
sh
);
release_stripe
(
sh
);
return
(
bufsize
>>
9
)
-
redone
;
return
STRIPE_SECTORS
;
}
/*
...
...
@@ -1280,7 +1347,7 @@ static void raid5d (void *data)
mddev
->
sb_dirty
=
0
;
md_update_sb
(
mddev
);
}
md_
spin_lock_irq
(
&
conf
->
device_lock
);
spin_lock_irq
(
&
conf
->
device_lock
);
while
(
1
)
{
struct
list_head
*
first
;
...
...
@@ -1300,17 +1367,17 @@ static void raid5d (void *data)
atomic_inc
(
&
sh
->
count
);
if
(
atomic_read
(
&
sh
->
count
)
!=
1
)
BUG
();
md_
spin_unlock_irq
(
&
conf
->
device_lock
);
spin_unlock_irq
(
&
conf
->
device_lock
);
handled
++
;
handle_stripe
(
sh
);
release_stripe
(
sh
);
md_
spin_lock_irq
(
&
conf
->
device_lock
);
spin_lock_irq
(
&
conf
->
device_lock
);
}
PRINTK
(
"%d stripes handled
\n
"
,
handled
);
md_
spin_unlock_irq
(
&
conf
->
device_lock
);
spin_unlock_irq
(
&
conf
->
device_lock
);
PRINTK
(
"--- raid5d inactive
\n
"
);
}
...
...
@@ -1340,7 +1407,7 @@ static void raid5syncd (void *data)
printk
(
"raid5: resync finished.
\n
"
);
}
static
int
r
aid5_r
un
(
mddev_t
*
mddev
)
static
int
run
(
mddev_t
*
mddev
)
{
raid5_conf_t
*
conf
;
int
i
,
j
,
raid_disk
,
memory
;
...
...
@@ -1348,7 +1415,7 @@ static int raid5_run (mddev_t *mddev)
mdp_disk_t
*
desc
;
mdk_rdev_t
*
rdev
;
struct
disk_info
*
disk
;
struct
md_
list_head
*
tmp
;
struct
list_head
*
tmp
;
int
start_recovery
=
0
;
MOD_INC_USE_COUNT
;
...
...
@@ -1365,25 +1432,24 @@ static int raid5_run (mddev_t *mddev)
memset
(
conf
,
0
,
sizeof
(
*
conf
));
conf
->
mddev
=
mddev
;
if
((
conf
->
stripe_hashtbl
=
(
struct
stripe_head
**
)
md
__get_free_pages
(
GFP_ATOMIC
,
HASH_PAGES_ORDER
))
==
NULL
)
if
((
conf
->
stripe_hashtbl
=
(
struct
stripe_head
**
)
__get_free_pages
(
GFP_ATOMIC
,
HASH_PAGES_ORDER
))
==
NULL
)
goto
abort
;
memset
(
conf
->
stripe_hashtbl
,
0
,
HASH_PAGES
*
PAGE_SIZE
);
conf
->
device_lock
=
MD_
SPIN_LOCK_UNLOCKED
;
md_
init_waitqueue_head
(
&
conf
->
wait_for_stripe
);
conf
->
device_lock
=
SPIN_LOCK_UNLOCKED
;
init_waitqueue_head
(
&
conf
->
wait_for_stripe
);
INIT_LIST_HEAD
(
&
conf
->
handle_list
);
INIT_LIST_HEAD
(
&
conf
->
delayed_list
);
INIT_LIST_HEAD
(
&
conf
->
inactive_list
);
atomic_set
(
&
conf
->
active_stripes
,
0
);
atomic_set
(
&
conf
->
preread_active_stripes
,
0
);
conf
->
buffer_size
=
PAGE_SIZE
;
/* good default for rebuild */
conf
->
plugged
=
0
;
conf
->
plug_tq
.
sync
=
0
;
conf
->
plug_tq
.
routine
=
&
raid5_unplug_device
;
conf
->
plug_tq
.
data
=
conf
;
PRINTK
(
"raid5
_
run(md%d) called.
\n
"
,
mdidx
(
mddev
));
PRINTK
(
"raid5
:
run(md%d) called.
\n
"
,
mdidx
(
mddev
));
ITERATE_RDEV
(
mddev
,
rdev
,
tmp
)
{
/*
...
...
@@ -1404,6 +1470,7 @@ static int raid5_run (mddev_t *mddev)
disk
->
number
=
desc
->
number
;
disk
->
raid_disk
=
raid_disk
;
disk
->
dev
=
rdev
->
dev
;
disk
->
bdev
=
rdev
->
bdev
;
disk
->
operational
=
0
;
disk
->
write_only
=
0
;
...
...
@@ -1430,6 +1497,7 @@ static int raid5_run (mddev_t *mddev)
disk
->
number
=
desc
->
number
;
disk
->
raid_disk
=
raid_disk
;
disk
->
dev
=
rdev
->
dev
;
disk
->
bdev
=
rdev
->
bdev
;
disk
->
operational
=
1
;
disk
->
used_slot
=
1
;
...
...
@@ -1442,6 +1510,7 @@ static int raid5_run (mddev_t *mddev)
disk
->
number
=
desc
->
number
;
disk
->
raid_disk
=
raid_disk
;
disk
->
dev
=
rdev
->
dev
;
disk
->
bdev
=
rdev
->
bdev
;
disk
->
operational
=
0
;
disk
->
write_only
=
0
;
...
...
@@ -1461,6 +1530,7 @@ static int raid5_run (mddev_t *mddev)
disk
->
number
=
desc
->
number
;
disk
->
raid_disk
=
raid_disk
;
disk
->
dev
=
NODEV
;
disk
->
bdev
=
NULL
;
disk
->
operational
=
0
;
disk
->
write_only
=
0
;
...
...
@@ -1518,9 +1588,9 @@ static int raid5_run (mddev_t *mddev)
memory
=
conf
->
max_nr_stripes
*
(
sizeof
(
struct
stripe_head
)
+
conf
->
raid_disks
*
((
sizeof
(
struct
buffer_head
)
+
PAGE_SIZE
)))
/
1024
;
if
(
grow_stripes
(
conf
,
conf
->
max_nr_stripes
,
GFP_KERNEL
))
{
if
(
grow_stripes
(
conf
,
conf
->
max_nr_stripes
))
{
printk
(
KERN_ERR
"raid5: couldn't allocate %dkB for buffers
\n
"
,
memory
);
shrink_stripes
(
conf
,
conf
->
max_nr_stripes
);
shrink_stripes
(
conf
);
goto
abort
;
}
else
printk
(
KERN_INFO
"raid5: allocated %dkB for md%d
\n
"
,
memory
,
mdidx
(
mddev
));
...
...
@@ -1580,7 +1650,7 @@ static int raid5_run (mddev_t *mddev)
return
-
EIO
;
}
static
int
raid5_
stop_resync
(
mddev_t
*
mddev
)
static
int
stop_resync
(
mddev_t
*
mddev
)
{
raid5_conf_t
*
conf
=
mddev_to_conf
(
mddev
);
mdk_thread_t
*
thread
=
conf
->
resync_thread
;
...
...
@@ -1597,7 +1667,7 @@ static int raid5_stop_resync (mddev_t *mddev)
return
0
;
}
static
int
r
aid5_r
estart_resync
(
mddev_t
*
mddev
)
static
int
restart_resync
(
mddev_t
*
mddev
)
{
raid5_conf_t
*
conf
=
mddev_to_conf
(
mddev
);
...
...
@@ -1616,14 +1686,14 @@ static int raid5_restart_resync (mddev_t *mddev)
}
static
int
raid5_
stop
(
mddev_t
*
mddev
)
static
int
stop
(
mddev_t
*
mddev
)
{
raid5_conf_t
*
conf
=
(
raid5_conf_t
*
)
mddev
->
private
;
if
(
conf
->
resync_thread
)
md_unregister_thread
(
conf
->
resync_thread
);
md_unregister_thread
(
conf
->
thread
);
shrink_stripes
(
conf
,
conf
->
max_nr_stripes
);
shrink_stripes
(
conf
);
free_pages
((
unsigned
long
)
conf
->
stripe_hashtbl
,
HASH_PAGES_ORDER
);
kfree
(
conf
);
mddev
->
private
=
NULL
;
...
...
@@ -1636,12 +1706,11 @@ static void print_sh (struct stripe_head *sh)
{
int
i
;
printk
(
"sh %lu,
size %d, pd_idx %d, state %ld.
\n
"
,
sh
->
sector
,
sh
->
size
,
sh
->
pd_idx
,
sh
->
state
);
printk
(
"sh %lu,
pd_idx %d, state %ld.
\n
"
,
sh
->
sector
,
sh
->
pd_idx
,
sh
->
state
);
printk
(
"sh %lu, count %d.
\n
"
,
sh
->
sector
,
atomic_read
(
&
sh
->
count
));
printk
(
"sh %lu, "
,
sh
->
sector
);
for
(
i
=
0
;
i
<
MD_SB_DISKS
;
i
++
)
{
if
(
sh
->
bh_cache
[
i
])
printk
(
"(cache%d: %p %ld) "
,
i
,
sh
->
bh_cache
[
i
],
sh
->
bh_cache
[
i
]
->
b_state
);
for
(
i
=
0
;
i
<
sh
->
raid_conf
->
raid_disks
;
i
++
)
{
printk
(
"(cache%d: %p %ld) "
,
i
,
sh
->
dev
[
i
].
page
,
sh
->
dev
[
i
].
flags
);
}
printk
(
"
\n
"
);
}
...
...
@@ -1651,7 +1720,7 @@ static void printall (raid5_conf_t *conf)
struct
stripe_head
*
sh
;
int
i
;
md_
spin_lock_irq
(
&
conf
->
device_lock
);
spin_lock_irq
(
&
conf
->
device_lock
);
for
(
i
=
0
;
i
<
NR_HASH
;
i
++
)
{
sh
=
conf
->
stripe_hashtbl
[
i
];
for
(;
sh
;
sh
=
sh
->
hash_next
)
{
...
...
@@ -1660,13 +1729,13 @@ static void printall (raid5_conf_t *conf)
print_sh
(
sh
);
}
}
md_
spin_unlock_irq
(
&
conf
->
device_lock
);
spin_unlock_irq
(
&
conf
->
device_lock
);
PRINTK
(
"--- raid5d inactive
\n
"
);
}
#endif
static
int
raid5_
status
(
char
*
page
,
mddev_t
*
mddev
)
static
int
status
(
char
*
page
,
mddev_t
*
mddev
)
{
raid5_conf_t
*
conf
=
(
raid5_conf_t
*
)
mddev
->
private
;
mdp_super_t
*
sb
=
mddev
->
sb
;
...
...
@@ -1711,7 +1780,7 @@ static void print_raid5_conf (raid5_conf_t *conf)
}
}
static
int
raid5_
diskop
(
mddev_t
*
mddev
,
mdp_disk_t
**
d
,
int
state
)
static
int
diskop
(
mddev_t
*
mddev
,
mdp_disk_t
**
d
,
int
state
)
{
int
err
=
0
;
int
i
,
failed_disk
=-
1
,
spare_disk
=-
1
,
removed_disk
=-
1
,
added_disk
=-
1
;
...
...
@@ -1722,7 +1791,7 @@ static int raid5_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
mdk_rdev_t
*
spare_rdev
,
*
failed_rdev
;
print_raid5_conf
(
conf
);
md_
spin_lock_irq
(
&
conf
->
device_lock
);
spin_lock_irq
(
&
conf
->
device_lock
);
/*
* find the disk ...
*/
...
...
@@ -1948,6 +2017,7 @@ static int raid5_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
goto
abort
;
}
rdisk
->
dev
=
NODEV
;
rdisk
->
bdev
=
NULL
;
rdisk
->
used_slot
=
0
;
break
;
...
...
@@ -1965,6 +2035,8 @@ static int raid5_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
adisk
->
number
=
added_desc
->
number
;
adisk
->
raid_disk
=
added_desc
->
raid_disk
;
adisk
->
dev
=
mk_kdev
(
added_desc
->
major
,
added_desc
->
minor
);
/* it will be held open by rdev */
adisk
->
bdev
=
bdget
(
kdev_t_to_nr
(
adisk
->
dev
));
adisk
->
operational
=
0
;
adisk
->
write_only
=
0
;
...
...
@@ -1980,7 +2052,7 @@ static int raid5_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
goto
abort
;
}
abort:
md_
spin_unlock_irq
(
&
conf
->
device_lock
);
spin_unlock_irq
(
&
conf
->
device_lock
);
print_raid5_conf
(
conf
);
return
err
;
}
...
...
@@ -1988,18 +2060,18 @@ static int raid5_diskop(mddev_t *mddev, mdp_disk_t **d, int state)
static
mdk_personality_t
raid5_personality
=
{
name:
"raid5"
,
make_request:
raid5_
make_request
,
run:
r
aid5_r
un
,
stop:
raid5_
stop
,
status:
raid5_
status
,
error_handler:
raid5_
error
,
diskop:
raid5_
diskop
,
stop_resync:
raid5_
stop_resync
,
restart_resync:
r
aid5_r
estart_resync
,
sync_request:
raid5_
sync_request
make_request:
make_request
,
run:
run
,
stop:
stop
,
status:
status
,
error_handler:
error
,
diskop:
diskop
,
stop_resync:
stop_resync
,
restart_resync:
restart_resync
,
sync_request:
sync_request
};
static
int
md
__init
raid5_init
(
void
)
static
int
__init
raid5_init
(
void
)
{
return
register_md_personality
(
RAID5
,
&
raid5_personality
);
}
...
...
drivers/md/xor.c
View file @
20c6b26d
...
...
@@ -19,7 +19,6 @@
#define BH_TRACE 0
#include <linux/module.h>
#include <linux/raid/md.h>
#include <linux/raid/md_compatible.h>
#include <linux/raid/xor.h>
#include <asm/xor.h>
...
...
@@ -27,31 +26,30 @@
static
struct
xor_block_template
*
active_template
;
void
xor_block
(
unsigned
int
count
,
struct
buffer_head
**
bh_
ptr
)
xor_block
(
unsigned
int
count
,
unsigned
int
bytes
,
void
**
ptr
)
{
unsigned
long
*
p0
,
*
p1
,
*
p2
,
*
p3
,
*
p4
;
unsigned
long
bytes
=
bh_ptr
[
0
]
->
b_size
;
p0
=
(
unsigned
long
*
)
bh_ptr
[
0
]
->
b_data
;
p1
=
(
unsigned
long
*
)
bh_ptr
[
1
]
->
b_data
;
p0
=
(
unsigned
long
*
)
ptr
[
0
]
;
p1
=
(
unsigned
long
*
)
ptr
[
1
]
;
if
(
count
==
2
)
{
active_template
->
do_2
(
bytes
,
p0
,
p1
);
return
;
}
p2
=
(
unsigned
long
*
)
bh_ptr
[
2
]
->
b_data
;
p2
=
(
unsigned
long
*
)
ptr
[
2
]
;
if
(
count
==
3
)
{
active_template
->
do_3
(
bytes
,
p0
,
p1
,
p2
);
return
;
}
p3
=
(
unsigned
long
*
)
bh_ptr
[
3
]
->
b_data
;
p3
=
(
unsigned
long
*
)
ptr
[
3
]
;
if
(
count
==
4
)
{
active_template
->
do_4
(
bytes
,
p0
,
p1
,
p2
,
p3
);
return
;
}
p4
=
(
unsigned
long
*
)
bh_ptr
[
4
]
->
b_data
;
p4
=
(
unsigned
long
*
)
ptr
[
4
]
;
active_template
->
do_5
(
bytes
,
p0
,
p1
,
p2
,
p3
,
p4
);
}
...
...
@@ -103,7 +101,7 @@ calibrate_xor_block(void)
void
*
b1
,
*
b2
;
struct
xor_block_template
*
f
,
*
fastest
;
b1
=
(
void
*
)
md
__get_free_pages
(
GFP_KERNEL
,
2
);
b1
=
(
void
*
)
__get_free_pages
(
GFP_KERNEL
,
2
);
if
(
!
b1
)
{
printk
(
"raid5: Yikes! No memory available.
\n
"
);
return
-
ENOMEM
;
...
...
@@ -137,7 +135,7 @@ calibrate_xor_block(void)
return
0
;
}
MD_
EXPORT_SYMBOL
(
xor_block
);
EXPORT_SYMBOL
(
xor_block
);
MODULE_LICENSE
(
"GPL"
);
module_init
(
calibrate_xor_block
);
fs/intermezzo/ext_attr.c
View file @
20c6b26d
...
...
@@ -105,9 +105,8 @@ int presto_set_ext_attr(struct inode *inode,
printk
(
"InterMezzo: out of memory!!!
\n
"
);
return
-
ENOMEM
;
}
error
=
copy_from_user
(
buf
,
buffer
,
buffer_len
);
if
(
error
)
return
error
;
if
(
copy_from_user
(
buf
,
buffer
,
buffer_len
))
return
-
EFAULT
;
}
else
buf
=
buffer
;
}
else
...
...
fs/intermezzo/kml.c
View file @
20c6b26d
...
...
@@ -31,10 +31,9 @@ int begin_kml_reint (struct file *file, unsigned long arg)
ENTRY
;
/* allocate buffer & copy it to kernel space */
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
if
(
input
.
reclen
>
kml_fsdata
->
kml_maxsize
)
...
...
@@ -45,11 +44,10 @@ int begin_kml_reint (struct file *file, unsigned long arg)
EXIT
;
return
-
ENOMEM
;
}
error
=
copy_from_user
(
path
,
input
.
volname
,
input
.
namelen
);
if
(
error
)
{
if
(
copy_from_user
(
path
,
input
.
volname
,
input
.
namelen
))
{
PRESTO_FREE
(
path
,
input
.
namelen
+
1
);
EXIT
;
return
error
;
return
-
EFAULT
;
}
path
[
input
.
namelen
]
=
'\0'
;
fset
=
kml_getfset
(
path
);
...
...
@@ -57,10 +55,9 @@ int begin_kml_reint (struct file *file, unsigned long arg)
kml_fsdata
=
FSET_GET_KMLDATA
(
fset
);
/* read the buf from user memory here */
error
=
copy_from_user
(
kml_fsdata
->
kml_buf
,
input
.
recbuf
,
input
.
reclen
);
if
(
error
)
{
if
(
copy_from_user
(
kml_fsdata
->
kml_buf
,
input
.
recbuf
,
input
.
reclen
))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
kml_fsdata
->
kml_len
=
input
.
reclen
;
...
...
@@ -94,21 +91,19 @@ int do_kml_reint (struct file *file, unsigned long arg)
struct
presto_file_set
*
fset
;
ENTRY
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
PRESTO_ALLOC
(
path
,
char
*
,
input
.
namelen
+
1
);
if
(
!
path
)
{
EXIT
;
return
-
ENOMEM
;
}
error
=
copy_from_user
(
path
,
input
.
volname
,
input
.
namelen
);
if
(
error
)
{
if
(
copy_from_user
(
path
,
input
.
volname
,
input
.
namelen
))
{
PRESTO_FREE
(
path
,
input
.
namelen
+
1
);
EXIT
;
return
error
;
return
-
EFAULT
;
}
path
[
input
.
namelen
]
=
'\0'
;
fset
=
kml_getfset
(
path
);
...
...
@@ -138,7 +133,8 @@ int do_kml_reint (struct file *file, unsigned long arg)
strlen
(
close
->
path
)
+
1
,
input
.
pathlen
);
error
=
-
ENOMEM
;
}
copy_to_user
((
char
*
)
arg
,
&
input
,
sizeof
(
input
));
if
(
copy_to_user
((
char
*
)
arg
,
&
input
,
sizeof
(
input
)))
return
-
EFAULT
;
}
return
error
;
}
...
...
@@ -161,10 +157,9 @@ int end_kml_reint (struct file *file, unsigned long arg)
char
*
path
;
ENTRY
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
PRESTO_ALLOC
(
path
,
char
*
,
input
.
namelen
+
1
);
...
...
@@ -172,11 +167,11 @@ int end_kml_reint (struct file *file, unsigned long arg)
EXIT
;
return
-
ENOMEM
;
}
error
=
copy_from_user
(
path
,
input
.
volname
,
input
.
namelen
);
if
(
copy_from_user
(
path
,
input
.
volname
,
input
.
namelen
))
{
if
(
error
)
{
PRESTO_FREE
(
path
,
input
.
namelen
+
1
);
EXIT
;
return
error
;
return
-
EFAULT
;
}
path
[
input
.
namelen
]
=
'\0'
;
fset
=
kml_getfset
(
path
);
...
...
@@ -193,7 +188,8 @@ int end_kml_reint (struct file *file, unsigned long arg)
#if 0
input.newpos = kml_upc->newpos;
input.count = kml_upc->count;
copy_to_user((char *)arg, &input, sizeof (input));
if (copy_to_user((char *)arg, &input, sizeof (input)))
return -EFAULT;
#endif
return
error
;
}
fs/intermezzo/psdev.c
View file @
20c6b26d
...
...
@@ -149,9 +149,8 @@ static ssize_t presto_psdev_write(struct file *file, const char *buf,
return
-
EINVAL
;
}
error
=
copy_from_user
(
&
hdr
,
buf
,
sizeof
(
hdr
));
if
(
error
)
return
error
;
if
(
copy_from_user
(
&
hdr
,
buf
,
sizeof
(
hdr
)))
return
-
EFAULT
;
CDEBUG
(
D_PSDEV
,
"(process,opc,uniq)=(%d,%d,%d)
\n
"
,
current
->
pid
,
hdr
.
opcode
,
hdr
.
unique
);
...
...
@@ -183,9 +182,8 @@ static ssize_t presto_psdev_write(struct file *file, const char *buf,
req
->
rq_bufsize
,
count
,
hdr
.
opcode
,
hdr
.
unique
);
count
=
req
->
rq_bufsize
;
/* don't have more space! */
}
error
=
copy_from_user
(
req
->
rq_data
,
buf
,
count
);
if
(
error
)
return
error
;
if
(
copy_from_user
(
req
->
rq_data
,
buf
,
count
))
return
-
EFAULT
;
/* adjust outsize: good upcalls can be aware of this */
req
->
rq_rep_size
=
count
;
...
...
@@ -280,14 +278,12 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
char
*
tmp
;
int
error
;
error
=
copy_from_user
(
&
readmount
,
(
void
*
)
arg
,
sizeof
(
readmount
));
if
(
error
)
{
if
(
copy_from_user
(
&
readmount
,
(
void
*
)
arg
,
sizeof
(
readmount
)))
printk
(
"psdev: can't copy %Zd bytes from %p to %p
\n
"
,
sizeof
(
readmount
),
(
struct
readmount
*
)
arg
,
&
readmount
);
EXIT
;
return
error
;
return
-
EFAULT
;
}
len
=
readmount
.
io_len
;
...
...
@@ -307,15 +303,16 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
* I mean, let's let the compiler do a little work ...
* gcc suggested the extra ()
*/
error
=
copy_to_user
(
readmount
.
io_string
,
tmp
,
outlen
);
if
(
error
)
{
if
(
copy_to_user
(
readmount
.
io_string
,
tmp
,
outlen
))
{
CDEBUG
(
D_PSDEV
,
"Copy_to_user string 0x%p failed
\n
"
,
readmount
.
io_string
);
error
=
-
EFAULT
;
}
if
(
(
!
error
)
&&
(
error
=
copy_to_user
(
&
(
user_readmount
->
io_len
),
&
outlen
,
sizeof
(
int
)))
)
{
if
(
!
error
&&
copy_to_user
(
&
(
user_readmount
->
io_len
),
&
outlen
,
sizeof
(
int
))
)
{
CDEBUG
(
D_PSDEV
,
"Copy_to_user len @0x%p failed
\n
"
,
&
(
user_readmount
->
io_len
));
error
=
-
EFAULT
;
}
PRESTO_FREE
(
tmp
,
len
);
...
...
@@ -360,10 +357,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
int
path_len
;
}
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
PRESTO_ALLOC
(
path
,
char
*
,
input
.
path_len
+
1
);
...
...
@@ -371,11 +367,10 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
EXIT
;
return
-
ENOMEM
;
}
error
=
copy_from_user
(
path
,
input
.
path
,
input
.
path_len
);
if
(
error
)
{
if
(
copy_from_user
(
path
,
input
.
path
,
input
.
path_len
))
{
PRESTO_FREE
(
path
,
input
.
path_len
+
1
);
EXIT
;
return
error
;
return
-
EFAULT
;
}
path
[
input
.
path_len
]
=
'\0'
;
CDEBUG
(
D_PSDEV
,
"clear_fsetroot: path %s
\n
"
,
path
);
...
...
@@ -401,10 +396,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
int
path_len
;
}
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
PRESTO_ALLOC
(
path
,
char
*
,
input
.
path_len
+
1
);
...
...
@@ -412,11 +406,10 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
EXIT
;
return
-
ENOMEM
;
}
error
=
copy_from_user
(
path
,
input
.
path
,
input
.
path_len
);
if
(
error
)
{
if
(
copy_from_user
(
path
,
input
.
path
,
input
.
path_len
))
{
PRESTO_FREE
(
path
,
input
.
path_len
+
1
);
EXIT
;
return
error
;
return
-
EFAULT
;
}
path
[
input
.
path_len
]
=
'\0'
;
CDEBUG
(
D_PSDEV
,
"clear_all_fsetroot: path %s
\n
"
,
path
);
...
...
@@ -440,10 +433,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
int
path_len
;
}
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
PRESTO_ALLOC
(
path
,
char
*
,
input
.
path_len
+
1
);
...
...
@@ -451,11 +443,10 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
EXIT
;
return
-
ENOMEM
;
}
error
=
copy_from_user
(
path
,
input
.
path
,
input
.
path_len
);
if
(
error
)
{
if
(
copy_from_user
(
path
,
input
.
path
,
input
.
path_len
))
{
PRESTO_FREE
(
path
,
input
.
path_len
+
1
);
EXIT
;
return
error
;
return
-
EFAULT
;
}
path
[
input
.
path_len
]
=
'\0'
;
CDEBUG
(
D_PSDEV
,
"get_kmlsize: len %d path %s
\n
"
,
...
...
@@ -474,7 +465,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
CDEBUG
(
D_PSDEV
,
"get_kmlsize: size = %Zd
\n
"
,
size
);
EXIT
;
return
copy_to_user
((
char
*
)
arg
,
&
input
,
sizeof
(
input
));
if
(
copy_to_user
((
char
*
)
arg
,
&
input
,
sizeof
(
input
)))
return
-
EFAULT
;
return
0
;
}
case
PRESTO_GET_RECNO
:
{
...
...
@@ -488,10 +481,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
int
path_len
;
}
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
PRESTO_ALLOC
(
path
,
char
*
,
input
.
path_len
+
1
);
...
...
@@ -499,11 +491,10 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
EXIT
;
return
-
ENOMEM
;
}
error
=
copy_from_user
(
path
,
input
.
path
,
input
.
path_len
);
if
(
error
)
{
if
(
copy_from_user
(
path
,
input
.
path
,
input
.
path_len
))
{
PRESTO_FREE
(
path
,
input
.
path_len
+
1
);
EXIT
;
return
error
;
return
-
EFAULT
;
}
path
[
input
.
path_len
]
=
'\0'
;
CDEBUG
(
D_PSDEV
,
"get_recno: len %d path %s
\n
"
,
...
...
@@ -522,7 +513,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
CDEBUG
(
D_PSDEV
,
"get_recno: recno = %d
\n
"
,
(
int
)
recno
);
EXIT
;
return
copy_to_user
((
char
*
)
arg
,
&
input
,
sizeof
(
input
));
if
(
copy_to_user
((
char
*
)
arg
,
&
input
,
sizeof
(
input
)))
return
-
EFAULT
;
return
0
;
}
case
PRESTO_SET_FSETROOT
:
{
...
...
@@ -543,10 +536,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
int
flags
;
}
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
PRESTO_ALLOC
(
path
,
char
*
,
input
.
path_len
+
1
);
...
...
@@ -554,9 +546,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
EXIT
;
return
-
ENOMEM
;
}
error
=
copy_from_user
(
path
,
input
.
path
,
input
.
path_len
);
if
(
error
)
{
if
(
copy_from_user
(
path
,
input
.
path
,
input
.
path_len
))
{
EXIT
;
error
-
EFAULT
;
goto
exit_free_path
;
}
path
[
input
.
path_len
]
=
'\0'
;
...
...
@@ -567,9 +559,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
EXIT
;
goto
exit_free_path
;
}
error
=
copy_from_user
(
fsetname
,
input
.
name
,
input
.
name_len
);
if
(
error
)
{
if
(
copy_from_user
(
fsetname
,
input
.
name
,
input
.
name_len
))
{
EXIT
;
error
=
-
EFAULT
;
goto
exit_free_fsetname
;
}
fsetname
[
input
.
name_len
]
=
'\0'
;
...
...
@@ -621,12 +613,11 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
struct
psdev_opt
*
user_opt
=
(
struct
psdev_opt
*
)
arg
;
int
error
;
error
=
copy_from_user
(
&
kopt
,
(
void
*
)
arg
,
sizeof
(
kopt
));
if
(
error
)
{
if
(
copy_from_user
(
&
kopt
,
(
void
*
)
arg
,
sizeof
(
kopt
)))
{
printk
(
"psdev: can't copyin %Zd bytes from %p to %p
\n
"
,
sizeof
(
kopt
),
(
struct
kopt
*
)
arg
,
&
kopt
);
EXIT
;
return
error
;
return
-
EFAULT
;
}
minor
=
minor
(
dev
);
if
(
cmd
==
PRESTO_SETOPT
)
...
...
@@ -650,12 +641,11 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
return
error
;
}
error
=
copy_to_user
(
user_opt
,
&
kopt
,
sizeof
(
kopt
));
if
(
error
)
{
if
(
copy_to_user
(
user_opt
,
&
kopt
,
sizeof
(
kopt
)))
{
CDEBUG
(
D_PSDEV
,
"Copy_to_user opt 0x%p failed
\n
"
,
user_opt
);
EXIT
;
return
error
;
return
-
EFAULT
;
}
CDEBUG
(
D_PSDEV
,
"dosetopt minor %d, opt %d, val %d return %d
\n
"
,
minor
,
kopt
.
optname
,
kopt
.
optval
,
error
);
...
...
@@ -668,10 +658,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
struct
lento_input_attr
input
;
struct
iattr
iattr
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
iattr
.
ia_valid
=
input
.
valid
;
iattr
.
ia_mode
=
(
umode_t
)
input
.
mode
;
...
...
@@ -692,10 +681,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
int
error
;
struct
lento_input_mode
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
error
=
lento_create
(
input
.
name
,
input
.
mode
,
&
input
.
info
);
...
...
@@ -707,10 +695,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
int
error
;
struct
lento_input_old_new
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
error
=
lento_link
(
input
.
oldname
,
input
.
newname
,
&
input
.
info
);
...
...
@@ -722,10 +709,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
int
error
;
struct
lento_input
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
error
=
lento_unlink
(
input
.
name
,
&
input
.
info
);
...
...
@@ -737,10 +723,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
int
error
;
struct
lento_input_old_new
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
error
=
lento_symlink
(
input
.
oldname
,
input
.
newname
,
&
input
.
info
);
...
...
@@ -752,10 +737,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
int
error
;
struct
lento_input_mode
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
error
=
lento_mkdir
(
input
.
name
,
input
.
mode
,
&
input
.
info
);
...
...
@@ -767,10 +751,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
int
error
;
struct
lento_input
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
error
=
lento_rmdir
(
input
.
name
,
&
input
.
info
);
...
...
@@ -782,10 +765,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
int
error
;
struct
lento_input_dev
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
error
=
lento_mknod
(
input
.
name
,
input
.
mode
,
...
...
@@ -798,10 +780,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
int
error
;
struct
lento_input_old_new
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
error
=
lento_rename
(
input
.
oldname
,
input
.
newname
,
&
input
.
info
);
...
...
@@ -817,30 +798,27 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
char
*
name
;
char
*
buffer
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
/* Now setup the input parameters */
PRESTO_ALLOC
(
name
,
char
*
,
input
.
name_len
+
1
);
/* We need null terminated strings for attr names */
name
[
input
.
name_len
]
=
'\0'
;
error
=
copy_from_user
(
name
,
input
.
name
,
input
.
name_len
);
if
(
error
)
{
if
(
copy_from_user
(
name
,
input
.
name
,
input
.
name_len
))
{
EXIT
;
PRESTO_FREE
(
name
,
input
.
name_len
+
1
);
return
error
;
return
-
EFAULT
;
}
PRESTO_ALLOC
(
buffer
,
char
*
,
input
.
buffer_len
+
1
);
error
=
copy_from_user
(
buffer
,
input
.
buffer
,
input
.
buffer_len
);
if
(
error
)
{
if
(
copy_from_user
(
buffer
,
input
.
buffer
,
input
.
buffer_len
))
{
EXIT
;
PRESTO_FREE
(
name
,
input
.
name_len
+
1
);
PRESTO_FREE
(
buffer
,
input
.
buffer_len
+
1
);
return
error
;
return
-
EFAULT
;
}
/* Make null terminated for easy printing */
buffer
[
input
.
buffer_len
]
=
'\0'
;
...
...
@@ -869,21 +847,19 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
struct
lento_input_ext_attr
input
;
char
*
name
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
/* Now setup the input parameters */
PRESTO_ALLOC
(
name
,
char
*
,
input
.
name_len
+
1
);
/* We need null terminated strings for attr names */
name
[
input
.
name_len
]
=
'\0'
;
error
=
copy_from_user
(
name
,
input
.
name
,
input
.
name_len
);
if
(
error
)
{
if
(
copy_from_user
(
name
,
input
.
name
,
input
.
name_len
))
{
EXIT
;
PRESTO_FREE
(
name
,
input
.
name_len
+
1
);
return
error
;
return
-
EFAULT
;
}
CDEBUG
(
D_PSDEV
,
" delextattr params: name %s,"
...
...
@@ -907,10 +883,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
struct
lento_input_iopen
input
;
int
error
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
input
.
fd
=
lento_iopen
(
input
.
name
,
(
ino_t
)
input
.
ino
,
...
...
@@ -921,17 +896,18 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
return
input
.
fd
;
}
EXIT
;
return
copy_to_user
((
char
*
)
arg
,
&
input
,
sizeof
(
input
));
if
(
copy_to_user
((
char
*
)
arg
,
&
input
,
sizeof
(
input
)))
return
-
EFAULT
;
return
0
;
}
case
PRESTO_VFS_CLOSE
:
{
int
error
;
struct
lento_input_close
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
CDEBUG
(
D_PIOCTL
,
"lento_close file descriptor: %d
\n
"
,
input
.
fd
);
...
...
@@ -952,10 +928,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
struct
presto_version
remote_file_version
;
}
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
user_path
=
input
.
path
;
...
...
@@ -964,11 +939,10 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
EXIT
;
return
-
ENOMEM
;
}
error
=
copy_from_user
(
input
.
path
,
user_path
,
input
.
path_len
);
if
(
error
)
{
if
(
copy_from_user
(
input
.
path
,
user_path
,
input
.
path_len
))
{
EXIT
;
PRESTO_FREE
(
input
.
path
,
input
.
path_len
+
1
);
return
error
;
return
-
EFAULT
;
}
input
.
path
[
input
.
path_len
]
=
'\0'
;
...
...
@@ -996,10 +970,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
struct
lento_vfs_context
info
;
}
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
user_path
=
input
.
path
;
...
...
@@ -1008,11 +981,10 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
EXIT
;
return
-
ENOMEM
;
}
error
=
copy_from_user
(
input
.
path
,
user_path
,
input
.
path_len
);
if
(
error
)
{
if
(
copy_from_user
(
input
.
path
,
user_path
,
input
.
path_len
))
{
EXIT
;
PRESTO_FREE
(
input
.
path
,
input
.
path_len
+
1
);
return
error
;
return
-
EFAULT
;
}
input
.
path
[
input
.
path_len
]
=
'\0'
;
...
...
@@ -1035,10 +1007,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
__u32
path_len
;
}
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
user_path
=
input
.
path
;
...
...
@@ -1047,11 +1018,10 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
EXIT
;
return
-
ENOMEM
;
}
error
=
copy_from_user
(
input
.
path
,
user_path
,
input
.
path_len
);
if
(
error
)
{
if
(
copy_from_user
(
input
.
path
,
user_path
,
input
.
path_len
))
{
EXIT
;
PRESTO_FREE
(
input
.
path
,
input
.
path_len
+
1
);
return
error
;
return
-
EFAULT
;
}
input
.
path
[
input
.
path_len
]
=
'\0'
;
...
...
@@ -1072,10 +1042,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
__u32
recno
;
}
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
user_path
=
input
.
path
;
...
...
@@ -1084,11 +1053,10 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
EXIT
;
return
-
ENOMEM
;
}
error
=
copy_from_user
(
input
.
path
,
user_path
,
input
.
path_len
);
if
(
error
)
{
if
(
copy_from_user
(
input
.
path
,
user_path
,
input
.
path_len
))
{
EXIT
;
PRESTO_FREE
(
input
.
path
,
input
.
path_len
+
1
);
return
error
;
return
-
EFAULT
;
}
input
.
path
[
input
.
path_len
]
=
'\0'
;
...
...
@@ -1111,10 +1079,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
char
*
path
;
}
input
;
error
=
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
));
if
(
error
)
{
if
(
copy_from_user
(
&
input
,
(
char
*
)
arg
,
sizeof
(
input
)))
{
EXIT
;
return
error
;
return
-
EFAULT
;
}
user_path
=
input
.
path
;
...
...
@@ -1123,11 +1090,10 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
EXIT
;
return
-
ENOMEM
;
}
error
=
copy_from_user
(
input
.
path
,
user_path
,
input
.
path_len
);
if
(
error
)
{
if
(
copy_from_user
(
input
.
path
,
user_path
,
input
.
path_len
))
{
EXIT
;
PRESTO_FREE
(
input
.
path
,
input
.
path_len
+
1
);
return
error
;
return
-
EFAULT
;
}
input
.
path
[
input
.
path_len
]
=
'\0'
;
...
...
@@ -1190,7 +1156,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
}
/* return the correct cookie to wait for */
input
.
mark_what
=
res
;
return
copy_to_user
((
char
*
)
arg
,
&
input
,
sizeof
(
input
));
if
(
copy_to_user
((
char
*
)
arg
,
&
input
,
sizeof
(
input
)))
return
-
EFAULT
;
return
0
;
}
#ifdef CONFIG_KREINT
...
...
@@ -1211,11 +1179,10 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
char
*
path
;
}
permit
;
error
=
copy_from_user
(
&
permit
,
(
char
*
)
arg
,
sizeof
(
permit
));
if
(
error
)
{
if
(
copy_from_user
(
&
permit
,
(
char
*
)
arg
,
sizeof
(
permit
)))
{
EXIT
;
return
error
;
}
return
-
EFAULT
;
}
user_path
=
permit
.
path
;
PRESTO_ALLOC
(
permit
.
path
,
char
*
,
permit
.
path_len
+
1
);
...
...
@@ -1223,11 +1190,10 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
EXIT
;
return
-
ENOMEM
;
}
error
=
copy_from_user
(
permit
.
path
,
user_path
,
permit
.
path_len
);
if
(
error
)
{
if
(
copy_from_user
(
permit
.
path
,
user_path
,
permit
.
path_len
))
{
EXIT
;
PRESTO_FREE
(
permit
.
path
,
permit
.
path_len
+
1
);
return
error
;
return
-
EFAULT
;
}
permit
.
path
[
permit
.
path_len
]
=
'\0'
;
...
...
@@ -1241,7 +1207,9 @@ static int presto_psdev_ioctl(struct inode *inode, struct file *file,
return
error
;
}
/* return the correct cookie to wait for */
return
copy_to_user
((
char
*
)
arg
,
&
permit
,
sizeof
(
permit
));
if
(
copy_to_user
((
char
*
)
arg
,
&
permit
,
sizeof
(
permit
)))
return
-
EFAULT
;
return
0
;
}
default:
...
...
fs/nfsd/export.c
View file @
20c6b26d
...
...
@@ -315,17 +315,19 @@ exp_export(struct nfsctl_export *nxp)
* 2: We must be able to find an inode from a filehandle.
* This means that s_export_op must be set.
*/
if
(((
inode
->
i_sb
->
s_type
->
fs_flags
&
FS_REQUIRES_DEV
)
||
(
nxp
->
ex_flags
&
NFSEXP_FSID
))
&&
inode
->
i_sb
->
s_export_op
)
/* Ok, we can export it */
;
else
{
if
(
!
(
inode
->
i_sb
->
s_type
->
fs_flags
&
FS_REQUIRES_DEV
))
{
if
(
!
(
nxp
->
ex_flags
&
NFSEXP_FSID
))
{
dprintk
(
"exp_export: export of non-dev fs without fsid"
);
goto
finish
;
}
}
if
(
!
inode
->
i_sb
->
s_export_op
)
{
dprintk
(
"exp_export: export of invalid fs type.
\n
"
);
goto
finish
;
}
if
(
inode
->
i_sb
->
s_export_op
&&
!
inode
->
i_sb
->
s_export_op
->
find_exported_dentry
)
/* Ok, we can export it */
;
if
(
!
inode
->
i_sb
->
s_export_op
->
find_exported_dentry
)
inode
->
i_sb
->
s_export_op
->
find_exported_dentry
=
find_exported_dentry
;
...
...
fs/nfsd/vfs.c
View file @
20c6b26d
...
...
@@ -414,11 +414,13 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
{
struct
dentry
*
dentry
;
struct
inode
*
inode
;
int
err
;
int
flags
=
O_RDONLY
|
O_LARGEFILE
,
mode
=
FMODE_READ
,
err
;
/* If we get here, then the client has already done an "open", and (hopefully)
* checked permission - so allow OWNER_OVERRIDE in case a chmod has now revoked
* permission */
/*
* If we get here, then the client has already done an "open",
* and (hopefully) checked permission - so allow OWNER_OVERRIDE
* in case a chmod has now revoked permission.
*/
err
=
fh_verify
(
rqstp
,
fhp
,
type
,
access
|
MAY_OWNER_OVERRIDE
);
if
(
err
)
goto
out
;
...
...
@@ -443,37 +445,24 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
if
(
err
)
goto
out_nfserr
;
if
((
access
&
MAY_WRITE
)
&&
(
err
=
get_write_access
(
inode
))
!=
0
)
goto
out_nfserr
;
memset
(
filp
,
0
,
sizeof
(
*
filp
));
filp
->
f_op
=
fops_get
(
inode
->
i_fop
);
atomic_set
(
&
filp
->
f_count
,
1
);
filp
->
f_dentry
=
dentry
;
filp
->
f_vfsmnt
=
fhp
->
fh_export
->
ex_mnt
;
if
(
access
&
MAY_WRITE
)
{
filp
->
f_flags
=
O_WRONLY
|
O_LARGEFILE
;
filp
->
f_mode
=
FMODE_WRITE
;
err
=
get_write_access
(
inode
);
if
(
err
)
goto
out_nfserr
;
flags
=
O_WRONLY
|
O_LARGEFILE
;
mode
=
FMODE_WRITE
;
DQUOT_INIT
(
inode
);
}
else
{
filp
->
f_flags
=
O_RDONLY
|
O_LARGEFILE
;
filp
->
f_mode
=
FMODE_READ
;
}
err
=
0
;
if
(
filp
->
f_op
&&
filp
->
f_op
->
open
)
{
err
=
filp
->
f_op
->
open
(
inode
,
filp
);
if
(
err
)
{
fops_put
(
filp
->
f_op
);
if
(
access
&
MAY_WRITE
)
put_write_access
(
inode
);
/* I nearly added put_filp() call here, but this filp
* is really on callers stack frame. -DaveM
*/
atomic_dec
(
&
filp
->
f_count
);
}
}
err
=
init_private_file
(
filp
,
dentry
,
mode
);
if
(
!
err
)
{
filp
->
f_flags
=
flags
;
filp
->
f_vfsmnt
=
fhp
->
fh_export
->
ex_mnt
;
}
else
if
(
access
&
MAY_WRITE
)
put_write_access
(
inode
);
out_nfserr:
if
(
err
)
err
=
nfserrno
(
err
);
...
...
@@ -490,9 +479,8 @@ nfsd_close(struct file *filp)
struct
dentry
*
dentry
=
filp
->
f_dentry
;
struct
inode
*
inode
=
dentry
->
d_inode
;
if
(
filp
->
f_op
&&
filp
->
f_op
->
release
)
if
(
filp
->
f_op
->
release
)
filp
->
f_op
->
release
(
inode
,
filp
);
fops_put
(
filp
->
f_op
);
if
(
filp
->
f_mode
&
FMODE_WRITE
)
put_write_access
(
inode
);
}
...
...
fs/read_write.c
View file @
20c6b26d
...
...
@@ -162,57 +162,107 @@ asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
}
#endif
asmlinkage
ssize_t
sys_read
(
unsigned
int
fd
,
char
*
buf
,
size_t
count
)
ssize_t
vfs_read
(
struct
file
*
file
,
char
*
buf
,
size_t
count
,
loff_t
*
pos
)
{
struct
inode
*
inode
=
file
->
f_dentry
->
d_inode
;
ssize_t
ret
;
struct
file
*
file
;
ret
=
-
EBADF
;
file
=
fget
(
fd
);
if
(
file
)
{
if
(
file
->
f_mode
&
FMODE_READ
)
{
ret
=
locks_verify_area
(
FLOCK_VERIFY_READ
,
file
->
f_dentry
->
d_inode
,
file
,
file
->
f_pos
,
count
);
if
(
!
ret
)
{
ssize_t
(
*
read
)(
struct
file
*
,
char
*
,
size_t
,
loff_t
*
);
ret
=
-
EINVAL
;
if
(
file
->
f_op
&&
(
read
=
file
->
f_op
->
read
)
!=
NULL
)
ret
=
read
(
file
,
buf
,
count
,
&
file
->
f_pos
);
}
}
if
(
!
(
file
->
f_mode
&
FMODE_READ
))
return
-
EBADF
;
if
(
!
file
->
f_op
||
!
file
->
f_op
->
read
)
return
-
EINVAL
;
if
(
pos
<
0
)
return
-
EINVAL
;
ret
=
locks_verify_area
(
FLOCK_VERIFY_READ
,
inode
,
file
,
*
pos
,
count
);
if
(
!
ret
)
{
ret
=
file
->
f_op
->
read
(
file
,
buf
,
count
,
pos
);
if
(
ret
>
0
)
dnotify_parent
(
file
->
f_dentry
,
DN_ACCESS
);
}
return
ret
;
}
ssize_t
vfs_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
count
,
loff_t
*
pos
)
{
struct
inode
*
inode
=
file
->
f_dentry
->
d_inode
;
ssize_t
ret
;
if
(
!
(
file
->
f_mode
&
FMODE_WRITE
))
return
-
EBADF
;
if
(
!
file
->
f_op
||
!
file
->
f_op
->
write
)
return
-
EINVAL
;
if
(
pos
<
0
)
return
-
EINVAL
;
ret
=
locks_verify_area
(
FLOCK_VERIFY_WRITE
,
inode
,
file
,
*
pos
,
count
);
if
(
!
ret
)
{
ret
=
file
->
f_op
->
write
(
file
,
buf
,
count
,
pos
);
if
(
ret
>
0
)
dnotify_parent
(
file
->
f_dentry
,
DN_MODIFY
);
}
return
ret
;
}
asmlinkage
ssize_t
sys_read
(
unsigned
int
fd
,
char
*
buf
,
size_t
count
)
{
struct
file
*
file
;
ssize_t
ret
=
-
EBADF
;
file
=
fget
(
fd
);
if
(
file
)
{
ret
=
vfs_read
(
file
,
buf
,
count
,
&
file
->
f_pos
);
fput
(
file
);
}
return
ret
;
}
asmlinkage
ssize_t
sys_write
(
unsigned
int
fd
,
const
char
*
buf
,
size_t
count
)
{
s
size_t
ret
;
s
truct
file
*
file
;
s
truct
file
*
file
;
s
size_t
ret
=
-
EBADF
;
ret
=
-
EBADF
;
file
=
fget
(
fd
);
if
(
file
)
{
if
(
file
->
f_mode
&
FMODE_WRITE
)
{
struct
inode
*
inode
=
file
->
f_dentry
->
d_inode
;
ret
=
locks_verify_area
(
FLOCK_VERIFY_WRITE
,
inode
,
file
,
file
->
f_pos
,
count
);
if
(
!
ret
)
{
ssize_t
(
*
write
)(
struct
file
*
,
const
char
*
,
size_t
,
loff_t
*
);
ret
=
-
EINVAL
;
if
(
file
->
f_op
&&
(
write
=
file
->
f_op
->
write
)
!=
NULL
)
ret
=
write
(
file
,
buf
,
count
,
&
file
->
f_pos
);
}
}
if
(
ret
>
0
)
dnotify_parent
(
file
->
f_dentry
,
DN_MODIFY
);
ret
=
vfs_write
(
file
,
buf
,
count
,
&
file
->
f_pos
);
fput
(
file
);
}
return
ret
;
}
asmlinkage
ssize_t
sys_pread
(
unsigned
int
fd
,
char
*
buf
,
size_t
count
,
loff_t
pos
)
{
struct
file
*
file
;
ssize_t
ret
=
-
EBADF
;
file
=
fget
(
fd
);
if
(
file
)
{
ret
=
vfs_read
(
file
,
buf
,
count
,
&
pos
);
fput
(
file
);
}
return
ret
;
}
asmlinkage
ssize_t
sys_pwrite
(
unsigned
int
fd
,
const
char
*
buf
,
size_t
count
,
loff_t
pos
)
{
struct
file
*
file
;
ssize_t
ret
=
-
EBADF
;
file
=
fget
(
fd
);
if
(
file
)
{
ret
=
vfs_write
(
file
,
buf
,
count
,
&
pos
);
fput
(
file
);
}
return
ret
;
}
static
ssize_t
do_readv_writev
(
int
type
,
struct
file
*
file
,
const
struct
iovec
*
vector
,
...
...
@@ -355,70 +405,3 @@ asmlinkage ssize_t sys_writev(unsigned long fd, const struct iovec * vector,
bad_file:
return
ret
;
}
/* From the Single Unix Spec: pread & pwrite act like lseek to pos + op +
lseek back to original location. They fail just like lseek does on
non-seekable files. */
asmlinkage
ssize_t
sys_pread
(
unsigned
int
fd
,
char
*
buf
,
size_t
count
,
loff_t
pos
)
{
ssize_t
ret
;
struct
file
*
file
;
ssize_t
(
*
read
)(
struct
file
*
,
char
*
,
size_t
,
loff_t
*
);
ret
=
-
EBADF
;
file
=
fget
(
fd
);
if
(
!
file
)
goto
bad_file
;
if
(
!
(
file
->
f_mode
&
FMODE_READ
))
goto
out
;
ret
=
locks_verify_area
(
FLOCK_VERIFY_READ
,
file
->
f_dentry
->
d_inode
,
file
,
pos
,
count
);
if
(
ret
)
goto
out
;
ret
=
-
EINVAL
;
if
(
!
file
->
f_op
||
!
(
read
=
file
->
f_op
->
read
))
goto
out
;
if
(
pos
<
0
)
goto
out
;
ret
=
read
(
file
,
buf
,
count
,
&
pos
);
if
(
ret
>
0
)
dnotify_parent
(
file
->
f_dentry
,
DN_ACCESS
);
out:
fput
(
file
);
bad_file:
return
ret
;
}
asmlinkage
ssize_t
sys_pwrite
(
unsigned
int
fd
,
const
char
*
buf
,
size_t
count
,
loff_t
pos
)
{
ssize_t
ret
;
struct
file
*
file
;
ssize_t
(
*
write
)(
struct
file
*
,
const
char
*
,
size_t
,
loff_t
*
);
ret
=
-
EBADF
;
file
=
fget
(
fd
);
if
(
!
file
)
goto
bad_file
;
if
(
!
(
file
->
f_mode
&
FMODE_WRITE
))
goto
out
;
ret
=
locks_verify_area
(
FLOCK_VERIFY_WRITE
,
file
->
f_dentry
->
d_inode
,
file
,
pos
,
count
);
if
(
ret
)
goto
out
;
ret
=
-
EINVAL
;
if
(
!
file
->
f_op
||
!
(
write
=
file
->
f_op
->
write
))
goto
out
;
if
(
pos
<
0
)
goto
out
;
ret
=
write
(
file
,
buf
,
count
,
&
pos
);
if
(
ret
>
0
)
dnotify_parent
(
file
->
f_dentry
,
DN_MODIFY
);
out:
fput
(
file
);
bad_file:
return
ret
;
}
fs/reiserfs/inode.c
View file @
20c6b26d
...
...
@@ -1484,13 +1484,19 @@ static int reiserfs_new_symlink (struct reiserfs_transaction_handle *th,
/* inserts the stat data into the tree, and then calls
reiserfs_new_directory (to insert ".", ".." item if new object is
directory) or reiserfs_new_symlink (to insert symlink body if new
object is symlink) or nothing (if new object is regular file) */
struct
inode
*
reiserfs_new_inode
(
struct
reiserfs_transaction_handle
*
th
,
struct
inode
*
dir
,
int
mode
,
const
char
*
symname
,
int
i_size
,
/* 0 for regular, EMTRY_DIR_SIZE for dirs,
strlen (symname) for symlinks)*/
struct
dentry
*
dentry
,
struct
inode
*
inode
,
int
*
err
)
object is symlink) or nothing (if new object is regular file)
NOTE! uid and gid must already be set in the inode. If we return
non-zero due to an error, we have to drop the quota previously allocated
for the fresh inode. This can only be done outside a transaction, so
if we return non-zero, we also end the transaction. */
int
reiserfs_new_inode
(
struct
reiserfs_transaction_handle
*
th
,
struct
inode
*
dir
,
int
mode
,
const
char
*
symname
,
/* 0 for regular, EMTRY_DIR_SIZE for dirs,
strlen (symname) for symlinks)*/
loff_t
i_size
,
struct
dentry
*
dentry
,
struct
inode
*
inode
)
{
struct
super_block
*
sb
;
INITIALIZE_PATH
(
path_to_key
);
...
...
@@ -1498,72 +1504,40 @@ struct inode * reiserfs_new_inode (struct reiserfs_transaction_handle *th,
struct
item_head
ih
;
struct
stat_data
sd
;
int
retval
;
int
err
;
if
(
!
dir
||
!
dir
->
i_nlink
)
{
*
err
=
-
EPERM
;
iput
(
inode
)
;
return
NULL
;
err
=
-
EPERM
;
goto
out_bad_inode
;
}
sb
=
dir
->
i_sb
;
inode
->
i_flags
=
0
;
//inode->i_sb->s_flags;
/* item head of new item */
ih
.
ih_key
.
k_dir_id
=
INODE_PKEY
(
dir
)
->
k_objectid
;
ih
.
ih_key
.
k_objectid
=
cpu_to_le32
(
reiserfs_get_unused_objectid
(
th
));
if
(
!
ih
.
ih_key
.
k_objectid
)
{
iput
(
inode
)
;
*
err
=
-
ENOMEM
;
return
NULL
;
err
=
-
ENOMEM
;
goto
out_bad_inode
;
}
if
(
old_format_only
(
sb
))
/* not a perfect generation count, as object ids can be reused, but this
**
is as good as reiserfs can do right now.
** note that the private part of inode isn't filled in yet, we have
** to use the directory.
*/
inode
->
i_generation
=
le32_to_cpu
(
INODE_PKEY
(
dir
)
->
k_objectid
);
/* not a perfect generation count, as object ids can be reused, but
** this
is as good as reiserfs can do right now.
** note that the private part of inode isn't filled in yet, we have
** to use the directory.
*/
inode
->
i_generation
=
le32_to_cpu
(
INODE_PKEY
(
dir
)
->
k_objectid
);
else
#if defined( USE_INODE_GENERATION_COUNTER )
inode
->
i_generation
=
le32_to_cpu
(
REISERFS_SB
(
sb
)
->
s_rs
->
s_inode_generation
);
inode
->
i_generation
=
le32_to_cpu
(
REISERFS_SB
(
sb
)
->
s_rs
->
s_inode_generation
);
#else
inode
->
i_generation
=
++
event
;
inode
->
i_generation
=
++
event
;
#endif
if
(
old_format_only
(
sb
))
make_le_item_head
(
&
ih
,
0
,
KEY_FORMAT_3_5
,
SD_OFFSET
,
TYPE_STAT_DATA
,
SD_V1_SIZE
,
MAX_US_INT
);
else
make_le_item_head
(
&
ih
,
0
,
KEY_FORMAT_3_6
,
SD_OFFSET
,
TYPE_STAT_DATA
,
SD_SIZE
,
MAX_US_INT
);
/* key to search for correct place for new stat data */
_make_cpu_key
(
&
key
,
KEY_FORMAT_3_6
,
le32_to_cpu
(
ih
.
ih_key
.
k_dir_id
),
le32_to_cpu
(
ih
.
ih_key
.
k_objectid
),
SD_OFFSET
,
TYPE_STAT_DATA
,
3
/*key length*/
);
/* find proper place for inserting of stat data */
retval
=
search_item
(
sb
,
&
key
,
&
path_to_key
);
if
(
retval
==
IO_ERROR
)
{
iput
(
inode
);
*
err
=
-
EIO
;
return
NULL
;
}
if
(
retval
==
ITEM_FOUND
)
{
pathrelse
(
&
path_to_key
);
iput
(
inode
);
*
err
=
-
EEXIST
;
return
NULL
;
}
/* fill stat data */
inode
->
i_mode
=
mode
;
inode
->
i_nlink
=
(
S_ISDIR
(
mode
)
?
2
:
1
);
inode
->
i_uid
=
current
->
fsuid
;
if
(
dir
->
i_mode
&
S_ISGID
)
{
inode
->
i_gid
=
dir
->
i_gid
;
if
(
S_ISDIR
(
mode
))
inode
->
i_mode
|=
S_ISGID
;
}
else
inode
->
i_gid
=
current
->
fsgid
;
/* uid and gid must already be set by the caller for quota init */
inode
->
i_mtime
=
inode
->
i_atime
=
inode
->
i_ctime
=
CURRENT_TIME
;
inode
->
i_size
=
i_size
;
...
...
@@ -1578,18 +1552,38 @@ struct inode * reiserfs_new_inode (struct reiserfs_transaction_handle *th,
REISERFS_I
(
inode
)
->
i_trans_id
=
0
;
REISERFS_I
(
inode
)
->
i_trans_index
=
0
;
if
(
old_format_only
(
sb
))
make_le_item_head
(
&
ih
,
0
,
KEY_FORMAT_3_5
,
SD_OFFSET
,
TYPE_STAT_DATA
,
SD_V1_SIZE
,
MAX_US_INT
);
else
make_le_item_head
(
&
ih
,
0
,
KEY_FORMAT_3_6
,
SD_OFFSET
,
TYPE_STAT_DATA
,
SD_SIZE
,
MAX_US_INT
);
/* key to search for correct place for new stat data */
_make_cpu_key
(
&
key
,
KEY_FORMAT_3_6
,
le32_to_cpu
(
ih
.
ih_key
.
k_dir_id
),
le32_to_cpu
(
ih
.
ih_key
.
k_objectid
),
SD_OFFSET
,
TYPE_STAT_DATA
,
3
/*key length*/
);
/* find proper place for inserting of stat data */
retval
=
search_item
(
sb
,
&
key
,
&
path_to_key
);
if
(
retval
==
IO_ERROR
)
{
err
=
-
EIO
;
goto
out_bad_inode
;
}
if
(
retval
==
ITEM_FOUND
)
{
pathrelse
(
&
path_to_key
);
err
=
-
EEXIST
;
goto
out_bad_inode
;
}
if
(
old_format_only
(
sb
))
{
if
(
inode
->
i_uid
&
~
0xffff
||
inode
->
i_gid
&
~
0xffff
)
{
pathrelse
(
&
path_to_key
);
/* i_uid or i_gid is too big to be stored in stat data v3.5 */
iput
(
inode
);
*
err
=
-
EINVAL
;
return
NULL
;
err
=
-
EINVAL
;
goto
out_bad_inode
;
}
inode2sd_v1
(
&
sd
,
inode
);
}
else
}
else
{
inode2sd
(
&
sd
,
inode
);
}
// these do not go to on-disk stat data
inode
->
i_ino
=
le32_to_cpu
(
ih
.
ih_key
.
k_objectid
);
inode
->
i_blksize
=
PAGE_SIZE
;
...
...
@@ -1610,10 +1604,9 @@ struct inode * reiserfs_new_inode (struct reiserfs_transaction_handle *th,
/* insert the stat data into the tree */
retval
=
reiserfs_insert_item
(
th
,
&
path_to_key
,
&
key
,
&
ih
,
(
char
*
)(
&
sd
));
if
(
retval
)
{
iput
(
inode
);
*
err
=
retval
;
err
=
retval
;
reiserfs_check_path
(
&
path_to_key
)
;
return
NULL
;
goto
out_bad_inode
;
}
if
(
S_ISDIR
(
mode
))
{
...
...
@@ -1628,19 +1621,35 @@ struct inode * reiserfs_new_inode (struct reiserfs_transaction_handle *th,
retval
=
reiserfs_new_symlink
(
th
,
&
ih
,
&
path_to_key
,
symname
,
i_size
);
}
if
(
retval
)
{
inode
->
i_nlink
=
0
;
iput
(
inode
);
*
err
=
retval
;
err
=
retval
;
reiserfs_check_path
(
&
path_to_key
)
;
return
NULL
;
journal_end
(
th
,
th
->
t_super
,
th
->
t_blocks_allocated
);
goto
out_inserted_sd
;
}
insert_inode_hash
(
inode
);
// we do not mark inode dirty: on disk content matches to the
// in-core one
reiserfs_update_sd
(
th
,
inode
);
reiserfs_check_path
(
&
path_to_key
)
;
return
inode
;
return
0
;
/* it looks like you can easily compress these two goto targets into
* one. Keeping it like this doesn't actually hurt anything, and they
* are place holders for what the quota code actually needs.
*/
out_bad_inode:
/* Invalidate the object, nothing was inserted yet */
INODE_PKEY
(
inode
)
->
k_objectid
=
0
;
/* dquot_drop must be done outside a transaction */
journal_end
(
th
,
th
->
t_super
,
th
->
t_blocks_allocated
)
;
make_bad_inode
(
inode
);
out_inserted_sd:
inode
->
i_nlink
=
0
;
th
->
t_trans_id
=
0
;
/* so the caller can't use this handle later */
iput
(
inode
);
return
err
;
}
/*
...
...
fs/reiserfs/journal.c
View file @
20c6b26d
...
...
@@ -204,7 +204,7 @@ static int set_bit_in_list_bitmap(struct super_block *p_s_sb, int block,
if
(
!
jb
->
bitmaps
[
bmap_nr
])
{
jb
->
bitmaps
[
bmap_nr
]
=
get_bitmap_node
(
p_s_sb
)
;
}
set_bit
(
bit_nr
,
jb
->
bitmaps
[
bmap_nr
]
->
data
)
;
set_bit
(
bit_nr
,
(
unsigned
long
*
)
jb
->
bitmaps
[
bmap_nr
]
->
data
)
;
return
0
;
}
...
...
@@ -550,7 +550,7 @@ int reiserfs_in_journal(struct super_block *p_s_sb,
PROC_INFO_INC
(
p_s_sb
,
journal
.
in_journal_bitmap
);
jb
=
SB_JOURNAL
(
p_s_sb
)
->
j_list_bitmap
+
i
;
if
(
jb
->
journal_list
&&
jb
->
bitmaps
[
bmap_nr
]
&&
test_bit
(
bit_nr
,
jb
->
bitmaps
[
bmap_nr
]
->
data
))
{
test_bit
(
bit_nr
,
(
unsigned
long
*
)
jb
->
bitmaps
[
bmap_nr
]
->
data
))
{
tmp_bit
=
find_next_zero_bit
((
unsigned
long
*
)
(
jb
->
bitmaps
[
bmap_nr
]
->
data
),
p_s_sb
->
s_blocksize
<<
3
,
bit_nr
+
1
)
;
...
...
fs/reiserfs/namei.c
View file @
20c6b26d
...
...
@@ -248,7 +248,7 @@ static int linear_search_in_dir_item (struct cpu_key * key, struct reiserfs_dir_
/* mark, that this generation number is used */
if
(
de
->
de_gen_number_bit_string
)
set_bit
(
GET_GENERATION_NUMBER
(
deh_offset
(
deh
)),
de
->
de_gen_number_bit_string
);
set_bit
(
GET_GENERATION_NUMBER
(
deh_offset
(
deh
)),
(
unsigned
long
*
)
de
->
de_gen_number_bit_string
);
// calculate pointer to name and namelen
de
->
de_entry_num
=
i
;
...
...
@@ -504,7 +504,7 @@ static int reiserfs_add_entry (struct reiserfs_transaction_handle *th, struct in
return
-
EEXIST
;
}
gen_number
=
find_first_zero_bit
(
bit_string
,
MAX_GENERATION_NUMBER
+
1
);
gen_number
=
find_first_zero_bit
(
(
unsigned
long
*
)
bit_string
,
MAX_GENERATION_NUMBER
+
1
);
if
(
gen_number
>
MAX_GENERATION_NUMBER
)
{
/* there is no free generation number */
reiserfs_warning
(
"reiserfs_add_entry: Congratulations! we have got hash function screwed up
\n
"
);
...
...
@@ -552,6 +552,40 @@ static int reiserfs_add_entry (struct reiserfs_transaction_handle *th, struct in
return
0
;
}
/* quota utility function, call if you've had to abort after calling
** new_inode_init, and have not called reiserfs_new_inode yet.
** This should only be called on inodes that do not hav stat data
** inserted into the tree yet.
*/
static
int
drop_new_inode
(
struct
inode
*
inode
)
{
make_bad_inode
(
inode
)
;
iput
(
inode
)
;
return
0
;
}
/* utility function that does setup for reiserfs_new_inode.
** DQUOT_ALLOC_INODE cannot be called inside a transaction, so we had
** to pull some bits of reiserfs_new_inode out into this func.
** Yes, the actual quota calls are missing, they are part of the quota
** patch.
*/
static
int
new_inode_init
(
struct
inode
*
inode
,
struct
inode
*
dir
,
int
mode
)
{
/* the quota init calls have to know who to charge the quota to, so
** we have to set uid and gid here
*/
inode
->
i_uid
=
current
->
fsuid
;
inode
->
i_mode
=
mode
;
if
(
dir
->
i_mode
&
S_ISGID
)
{
inode
->
i_gid
=
dir
->
i_gid
;
if
(
S_ISDIR
(
mode
))
inode
->
i_mode
|=
S_ISGID
;
}
else
{
inode
->
i_gid
=
current
->
fsgid
;
}
return
0
;
}
//
// a portion of this function, particularly the VFS interface portion,
...
...
@@ -564,7 +598,6 @@ static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode)
{
int
retval
;
struct
inode
*
inode
;
int
windex
;
int
jbegin_count
=
JOURNAL_PER_BALANCE_CNT
*
2
;
struct
reiserfs_transaction_handle
th
;
...
...
@@ -572,16 +605,16 @@ static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode)
if
(
!
inode
)
{
return
-
ENOMEM
;
}
retval
=
new_inode_init
(
inode
,
dir
,
mode
);
if
(
retval
)
return
retval
;
lock_kernel
();
journal_begin
(
&
th
,
dir
->
i_sb
,
jbegin_count
)
;
th
.
t_caller
=
"create"
;
windex
=
push_journal_writer
(
"reiserfs_create"
)
;
inode
=
reiserfs_new_inode
(
&
th
,
dir
,
mode
,
0
,
0
/*i_size*/
,
dentry
,
inode
,
&
retval
);
if
(
!
inode
)
{
pop_journal_writer
(
windex
)
;
journal_end
(
&
th
,
dir
->
i_sb
,
jbegin_count
)
;
unlock_kernel
();
return
retval
;
retval
=
reiserfs_new_inode
(
&
th
,
dir
,
mode
,
0
,
0
/*i_size*/
,
dentry
,
inode
);
if
(
retval
)
{
goto
out_failed
;
}
inode
->
i_op
=
&
reiserfs_file_inode_operations
;
...
...
@@ -593,22 +626,19 @@ static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode)
if
(
retval
)
{
inode
->
i_nlink
--
;
reiserfs_update_sd
(
&
th
,
inode
);
pop_journal_writer
(
windex
)
;
// FIXME: should we put iput here and have stat data deleted
// in the same transactioin
journal_end
(
&
th
,
dir
->
i_sb
,
jbegin_count
)
;
iput
(
inode
);
unlock_kernel
();
return
retval
;
goto
out_failed
;
}
reiserfs_update_inode_transaction
(
inode
)
;
reiserfs_update_inode_transaction
(
dir
)
;
d_instantiate
(
dentry
,
inode
);
pop_journal_writer
(
windex
)
;
journal_end
(
&
th
,
dir
->
i_sb
,
jbegin_count
)
;
out_failed:
unlock_kernel
();
return
0
;
return
retval
;
}
...
...
@@ -623,7 +653,6 @@ static int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode,
{
int
retval
;
struct
inode
*
inode
;
int
windex
;
struct
reiserfs_transaction_handle
th
;
int
jbegin_count
=
JOURNAL_PER_BALANCE_CNT
*
3
;
...
...
@@ -631,16 +660,16 @@ static int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode,
if
(
!
inode
)
{
return
-
ENOMEM
;
}
retval
=
new_inode_init
(
inode
,
dir
,
mode
);
if
(
retval
)
return
retval
;
lock_kernel
();
journal_begin
(
&
th
,
dir
->
i_sb
,
jbegin_count
)
;
windex
=
push_journal_writer
(
"reiserfs_mknod"
)
;
inode
=
reiserfs_new_inode
(
&
th
,
dir
,
mode
,
0
,
0
/*i_size*/
,
dentry
,
inode
,
&
retval
);
if
(
!
inode
)
{
pop_journal_writer
(
windex
)
;
journal_end
(
&
th
,
dir
->
i_sb
,
jbegin_count
)
;
unlock_kernel
();
return
retval
;
retval
=
reiserfs_new_inode
(
&
th
,
dir
,
mode
,
0
,
0
/*i_size*/
,
dentry
,
inode
);
if
(
retval
)
{
goto
out_failed
;
}
init_special_inode
(
inode
,
mode
,
rdev
)
;
...
...
@@ -656,18 +685,17 @@ static int reiserfs_mknod (struct inode * dir, struct dentry *dentry, int mode,
if
(
retval
)
{
inode
->
i_nlink
--
;
reiserfs_update_sd
(
&
th
,
inode
);
pop_journal_writer
(
windex
)
;
journal_end
(
&
th
,
dir
->
i_sb
,
jbegin_count
)
;
iput
(
inode
);
unlock_kernel
();
return
retval
;
goto
out_failed
;
}
d_instantiate
(
dentry
,
inode
);
pop_journal_writer
(
windex
)
;
journal_end
(
&
th
,
dir
->
i_sb
,
jbegin_count
)
;
out_failed:
unlock_kernel
();
return
0
;
return
retval
;
}
...
...
@@ -682,33 +710,33 @@ static int reiserfs_mkdir (struct inode * dir, struct dentry *dentry, int mode)
{
int
retval
;
struct
inode
*
inode
;
int
windex
;
struct
reiserfs_transaction_handle
th
;
int
jbegin_count
=
JOURNAL_PER_BALANCE_CNT
*
3
;
mode
=
S_IFDIR
|
mode
;
inode
=
new_inode
(
dir
->
i_sb
)
;
if
(
!
inode
)
{
return
-
ENOMEM
;
}
retval
=
new_inode_init
(
inode
,
dir
,
mode
);
if
(
retval
)
return
retval
;
lock_kernel
();
journal_begin
(
&
th
,
dir
->
i_sb
,
jbegin_count
)
;
windex
=
push_journal_writer
(
"reiserfs_mkdir"
)
;
/* inc the link count now, so another writer doesn't overflow it while
** we sleep later on.
*/
INC_DIR_INODE_NLINK
(
dir
)
mode
=
S_IFDIR
|
mode
;
inode
=
reiserfs_new_inode
(
&
th
,
dir
,
mode
,
0
/*symlink*/
,
old_format_only
(
dir
->
i_sb
)
?
EMPTY_DIR_SIZE_V1
:
EMPTY_DIR_SIZE
,
dentry
,
inode
,
&
retval
);
if
(
!
inode
)
{
pop_journal_writer
(
windex
)
;
retval
=
reiserfs_new_inode
(
&
th
,
dir
,
mode
,
0
/*symlink*/
,
old_format_only
(
dir
->
i_sb
)
?
EMPTY_DIR_SIZE_V1
:
EMPTY_DIR_SIZE
,
dentry
,
inode
);
if
(
retval
)
{
dir
->
i_nlink
--
;
journal_end
(
&
th
,
dir
->
i_sb
,
jbegin_count
)
;
unlock_kernel
();
return
retval
;
goto
out_failed
;
}
reiserfs_update_inode_transaction
(
inode
)
;
reiserfs_update_inode_transaction
(
dir
)
;
...
...
@@ -723,21 +751,19 @@ static int reiserfs_mkdir (struct inode * dir, struct dentry *dentry, int mode)
inode
->
i_nlink
=
0
;
DEC_DIR_INODE_NLINK
(
dir
);
reiserfs_update_sd
(
&
th
,
inode
);
pop_journal_writer
(
windex
)
;
journal_end
(
&
th
,
dir
->
i_sb
,
jbegin_count
)
;
iput
(
inode
);
unlock_kernel
();
return
retval
;
goto
out_failed
;
}
// the above add_entry did not update dir's stat data
reiserfs_update_sd
(
&
th
,
dir
);
d_instantiate
(
dentry
,
inode
);
pop_journal_writer
(
windex
)
;
journal_end
(
&
th
,
dir
->
i_sb
,
jbegin_count
)
;
out_failed:
unlock_kernel
();
return
0
;
return
retval
;
}
static
inline
int
reiserfs_empty_dir
(
struct
inode
*
inode
)
{
...
...
@@ -942,43 +968,43 @@ static int reiserfs_symlink (struct inode * dir, struct dentry * dentry, const c
struct
inode
*
inode
;
char
*
name
;
int
item_len
;
int
windex
;
struct
reiserfs_transaction_handle
th
;
int
mode
=
S_IFLNK
|
S_IRWXUGO
;
int
jbegin_count
=
JOURNAL_PER_BALANCE_CNT
*
3
;
inode
=
new_inode
(
dir
->
i_sb
)
;
if
(
!
inode
)
{
return
-
ENOMEM
;
}
retval
=
new_inode_init
(
inode
,
dir
,
mode
);
if
(
retval
)
{
return
retval
;
}
lock_kernel
();
item_len
=
ROUND_UP
(
strlen
(
symname
));
if
(
item_len
>
MAX_DIRECT_ITEM_LEN
(
dir
->
i_sb
->
s_blocksize
))
{
iput
(
inode
)
;
return
-
ENAMETOOLONG
;
retval
=
-
ENAMETOOLONG
;
drop_new_inode
(
inode
);
goto
out_failed
;
}
lock_kernel
();
name
=
reiserfs_kmalloc
(
item_len
,
GFP_NOFS
,
dir
->
i_sb
);
if
(
!
name
)
{
iput
(
inode
)
;
unlock_kernel
()
;
return
-
ENOMEM
;
drop_new_inode
(
inode
)
;
retval
=
-
ENOMEM
;
goto
out_failed
;
}
memcpy
(
name
,
symname
,
strlen
(
symname
));
padd_item
(
name
,
item_len
,
strlen
(
symname
));
journal_begin
(
&
th
,
dir
->
i_sb
,
jbegin_count
)
;
windex
=
push_journal_writer
(
"reiserfs_symlink"
)
;
inode
=
reiserfs_new_inode
(
&
th
,
dir
,
S_IFLNK
|
S_IRWXUGO
,
name
,
strlen
(
symname
),
dentry
,
inode
,
&
retval
);
retval
=
reiserfs_new_inode
(
&
th
,
dir
,
mode
,
name
,
strlen
(
symname
),
dentry
,
inode
);
reiserfs_kfree
(
name
,
item_len
,
dir
->
i_sb
);
if
(
inode
==
0
)
{
/* reiserfs_new_inode iputs for us */
pop_journal_writer
(
windex
)
;
journal_end
(
&
th
,
dir
->
i_sb
,
jbegin_count
)
;
unlock_kernel
();
return
retval
;
if
(
retval
)
{
/* reiserfs_new_inode iputs for us */
goto
out_failed
;
}
reiserfs_update_inode_transaction
(
inode
)
;
...
...
@@ -996,18 +1022,16 @@ static int reiserfs_symlink (struct inode * dir, struct dentry * dentry, const c
if
(
retval
)
{
inode
->
i_nlink
--
;
reiserfs_update_sd
(
&
th
,
inode
);
pop_journal_writer
(
windex
)
;
journal_end
(
&
th
,
dir
->
i_sb
,
jbegin_count
)
;
iput
(
inode
);
unlock_kernel
();
return
retval
;
goto
out_failed
;
}
d_instantiate
(
dentry
,
inode
);
pop_journal_writer
(
windex
)
;
journal_end
(
&
th
,
dir
->
i_sb
,
jbegin_count
)
;
out_failed:
unlock_kernel
();
return
0
;
return
retval
;
}
...
...
include/asm-i386/xor.h
View file @
20c6b26d
...
...
@@ -839,6 +839,8 @@ static struct xor_block_template xor_block_pIII_sse = {
/* Also try the generic routines. */
#include <asm-generic/xor.h>
#define cpu_has_mmx (test_bit(X86_FEATURE_MMX, boot_cpu_data.x86_capability))
#undef XOR_TRY_TEMPLATES
#define XOR_TRY_TEMPLATES \
do { \
...
...
@@ -846,7 +848,7 @@ static struct xor_block_template xor_block_pIII_sse = {
xor_speed(&xor_block_32regs); \
if (cpu_has_xmm) \
xor_speed(&xor_block_pIII_sse); \
if (
md_cpu_has_mmx()
) { \
if (
cpu_has_mmx
) { \
xor_speed(&xor_block_pII_mmx); \
xor_speed(&xor_block_p5_mmx); \
} \
...
...
include/linux/fs.h
View file @
20c6b26d
...
...
@@ -759,6 +759,9 @@ struct inode_operations {
struct
seq_file
;
extern
ssize_t
vfs_read
(
struct
file
*
,
char
*
,
size_t
,
loff_t
*
);
extern
ssize_t
vfs_write
(
struct
file
*
,
const
char
*
,
size_t
,
loff_t
*
);
/*
* NOTE: write_inode, delete_inode, clear_inode, put_inode can be called
* without the big kernel lock held in all filesystems.
...
...
include/linux/raid/md_k.h
View file @
20c6b26d
...
...
@@ -169,8 +169,9 @@ struct mdk_rdev_s
struct
block_device
*
bdev
;
/* block device handle */
mdp_super_t
*
sb
;
unsigned
long
sb_offset
;
struct
page
*
sb_page
;
mdp_super_t
*
sb
;
unsigned
long
sb_offset
;
int
alias_device
;
/* device alias to the same disk */
int
faulty
;
/* if faulty do not issue IO requests */
...
...
include/linux/raid/raid5.h
View file @
20c6b26d
...
...
@@ -7,21 +7,21 @@
/*
*
* Each stripe contains one buffer per disc. Each buffer can be in
* one of a number of states
determined by bh_state
. Changes between
* one of a number of states
stored in "flags"
. Changes between
* these states happen *almost* exclusively under a per-stripe
* spinlock. Some very specific changes can happen in b_end_io, and
* spinlock. Some very specific changes can happen in b
i
_end_io, and
* these are not protected by the spin lock.
*
* The
bh_state
bits that are used to represent these states are:
*
BH_Uptodate, BH_Lock
* The
flag
bits that are used to represent these states are:
*
R5_UPTODATE and R5_LOCKED
*
* State Empty == !U
ptodate, !Lock
* State Empty == !U
PTODATE, !LOCK
* We have no data, and there is no active request
* State Want == !U
ptodate, Lock
* State Want == !U
PTODATE, LOCK
* A read request is being submitted for this block
* State Dirty == U
ptodate, Lock
* State Dirty == U
PTODATE, LOCK
* Some new data is in this buffer, and it is being written out
* State Clean == U
ptodate, !Lock
* State Clean == U
PTODATE, !LOCK
* We have valid data which is the same as on disc
*
* The possible state transitions are:
...
...
@@ -124,24 +124,29 @@
* plus raid5d if it is handling it, plus one for each active request
* on a cached buffer.
*/
struct
stripe_head
{
struct
stripe_head
*
hash_next
,
**
hash_pprev
;
/* hash pointers */
struct
list_head
lru
;
/* inactive_list or handle_list */
struct
raid5_private_data
*
raid_conf
;
struct
buffer_head
*
bh_cache
[
MD_SB_DISKS
];
/* buffered copy */
struct
buffer_head
*
bh_read
[
MD_SB_DISKS
];
/* read request buffers of the MD device */
struct
buffer_head
*
bh_write
[
MD_SB_DISKS
];
/* write request buffers of the MD device */
struct
buffer_head
*
bh_written
[
MD_SB_DISKS
];
/* write request buffers of the MD device that have been scheduled for write */
struct
page
*
bh_page
[
MD_SB_DISKS
];
/* saved bh_cache[n]->b_page when reading around the cache */
unsigned
long
sector
;
/* sector of this row */
int
size
;
/* buffers size */
sector_t
sector
;
/* sector of this row */
int
pd_idx
;
/* parity disk index */
unsigned
long
state
;
/* state flags */
atomic_t
count
;
/* nr of active thread/requests */
spinlock_t
lock
;
int
sync_redone
;
struct
r5dev
{
struct
bio
req
;
struct
bio_vec
vec
;
struct
page
*
page
;
struct
bio
*
toread
,
*
towrite
,
*
written
;
sector_t
sector
;
/* sector of this page */
unsigned
long
flags
;
}
dev
[
1
];
/* allocated with extra space depending of RAID geometry */
};
/* Flags */
#define R5_UPTODATE 0
/* page contains current data */
#define R5_LOCKED 1
/* IO has been submitted on "req" */
#define R5_OVERWRITE 2
/* towrite covers whole page */
/*
* Write method
...
...
@@ -187,6 +192,7 @@ struct stripe_head {
struct
disk_info
{
kdev_t
dev
;
struct
block_device
*
bdev
;
int
operational
;
int
number
;
int
raid_disk
;
...
...
@@ -201,7 +207,6 @@ struct raid5_private_data {
mdk_thread_t
*
thread
,
*
resync_thread
;
struct
disk_info
disks
[
MD_SB_DISKS
];
struct
disk_info
*
spare
;
int
buffer_size
;
int
chunk_size
,
level
,
algorithm
;
int
raid_disks
,
working_disks
,
failed_disks
;
int
resync_parity
;
...
...
@@ -210,16 +215,19 @@ struct raid5_private_data {
struct
list_head
handle_list
;
/* stripes needing handling */
struct
list_head
delayed_list
;
/* stripes that have plugged requests */
atomic_t
preread_active_stripes
;
/* stripes with scheduled io */
char
cache_name
[
20
];
kmem_cache_t
*
slab_cache
;
/* for allocating stripes */
/*
* Free stripes pool
*/
atomic_t
active_stripes
;
struct
list_head
inactive_list
;
md_
wait_queue_head_t
wait_for_stripe
;
wait_queue_head_t
wait_for_stripe
;
int
inactive_blocked
;
/* release of inactive stripes blocked,
* waiting for 25% to be free
*/
md_
spinlock_t
device_lock
;
spinlock_t
device_lock
;
int
plugged
;
struct
tq_struct
plug_tq
;
...
...
include/linux/raid/xor.h
View file @
20c6b26d
...
...
@@ -5,7 +5,7 @@
#define MAX_XOR_BLOCKS 5
extern
void
xor_block
(
unsigned
int
count
,
struct
buffer_head
**
bh_
ptr
);
extern
void
xor_block
(
unsigned
int
count
,
unsigned
int
bytes
,
void
**
ptr
);
struct
xor_block_template
{
struct
xor_block_template
*
next
;
...
...
include/linux/reiserfs_fs.h
View file @
20c6b26d
...
...
@@ -1841,10 +1841,10 @@ struct inode * reiserfs_iget (struct super_block * s,
const
struct
cpu_key
*
key
);
struct
inode
*
reiserfs_new_inode
(
struct
reiserfs_transaction_handle
*
th
,
int
reiserfs_new_inode
(
struct
reiserfs_transaction_handle
*
th
,
struct
inode
*
dir
,
int
mode
,
const
char
*
symname
,
int
item_len
,
struct
dentry
*
dentry
,
struct
inode
*
inode
,
int
*
err
);
const
char
*
symname
,
loff_t
i_size
,
struct
dentry
*
dentry
,
struct
inode
*
inode
);
int
reiserfs_sync_inode
(
struct
reiserfs_transaction_handle
*
th
,
struct
inode
*
inode
);
void
reiserfs_update_sd
(
struct
reiserfs_transaction_handle
*
th
,
struct
inode
*
inode
);
...
...
kernel/exit.c
View file @
20c6b26d
...
...
@@ -231,7 +231,7 @@ void daemonize(void)
/*
* When we die, we re-parent all our children.
* Try to give them to another thread in our
process
* Try to give them to another thread in our
thread
* group, and if no such member exists, give it to
* the global child reaper process (ie "init")
*/
...
...
@@ -241,8 +241,14 @@ static inline void forget_original_parent(struct task_struct * father)
read_lock
(
&
tasklist_lock
);
/* Next in our thread group */
reaper
=
next_thread
(
father
);
/* Next in our thread group, if they're not already exiting */
reaper
=
father
;
do
{
reaper
=
next_thread
(
reaper
);
if
(
!
(
reaper
->
flags
&
PF_EXITING
))
break
;
}
while
(
reaper
!=
father
);
if
(
reaper
==
father
)
reaper
=
child_reaper
;
...
...
kernel/ksyms.c
View file @
20c6b26d
...
...
@@ -243,6 +243,8 @@ EXPORT_SYMBOL(shrink_dcache_anon);
EXPORT_SYMBOL
(
find_inode_number
);
EXPORT_SYMBOL
(
is_subdir
);
EXPORT_SYMBOL
(
get_unused_fd
);
EXPORT_SYMBOL
(
vfs_read
);
EXPORT_SYMBOL
(
vfs_write
);
EXPORT_SYMBOL
(
vfs_create
);
EXPORT_SYMBOL
(
vfs_mkdir
);
EXPORT_SYMBOL
(
vfs_mknod
);
...
...
net/sunrpc/svcsock.c
View file @
20c6b26d
...
...
@@ -949,12 +949,10 @@ svc_sock_update_bufs(struct svc_serv *serv)
if
(
sock
->
type
==
SOCK_DGRAM
)
{
/* udp sockets need large rcvbuf as all pending
* requests are still in that buffer.
* As outgoing requests do not wait for an
* ACK, only a moderate sndbuf is needed
*/
svc_sock_setbufsize
(
sock
,
5
*
serv
->
sv_bufsz
,
(
serv
->
sv_nrthreads
+
2
)
*
serv
->
sv_bufsz
);
(
serv
->
sv_nrthreads
+
3
)
*
serv
->
sv_bufsz
,
(
serv
->
sv_nrthreads
+
3
)
*
serv
->
sv_bufsz
);
}
else
if
(
svsk
->
sk_sk
->
state
!=
TCP_LISTEN
)
{
printk
(
KERN_ERR
"RPC update_bufs: permanent sock neither UDP or TCP_LISTEN
\n
"
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment