mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
reiserfs: The last commit
Deprecation period of reiserfs ends with the end of this year so it is time to remove it from the kernel. Acked-by: Darrick J. Wong <djwong@kernel.org> Acked-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Jan Kara <jack@suse.cz>
This commit is contained in:
parent
6485cf5ea2
commit
fb6f20ecb1
@ -177,7 +177,7 @@ settles down a bit.
|
||||
**mandatory**
|
||||
|
||||
s_export_op is now required for exporting a filesystem.
|
||||
isofs, ext2, ext3, reiserfs, fat
|
||||
isofs, ext2, ext3, fat
|
||||
can be used as examples of very different filesystems.
|
||||
|
||||
---
|
||||
|
@ -375,7 +375,7 @@ Code Seq# Include File Comments
|
||||
0xCB 00-1F CBM serial IEC bus in development:
|
||||
<mailto:michael.klein@puffin.lb.shuttle.de>
|
||||
0xCC 00-0F drivers/misc/ibmvmc.h pseries VMC driver
|
||||
0xCD 01 linux/reiserfs_fs.h
|
||||
0xCD 01 linux/reiserfs_fs.h Dead since 6.13
|
||||
0xCE 01-02 uapi/linux/cxl_mem.h Compute Express Link Memory Devices
|
||||
0xCF 02 fs/smb/client/cifs_ioctl.h
|
||||
0xDB 00-0F drivers/char/mwave/mwavepub.h
|
||||
|
@ -19578,11 +19578,6 @@ F: Documentation/devicetree/bindings/regmap/
|
||||
F: drivers/base/regmap/
|
||||
F: include/linux/regmap.h
|
||||
|
||||
REISERFS FILE SYSTEM
|
||||
L: reiserfs-devel@vger.kernel.org
|
||||
S: Obsolete
|
||||
F: fs/reiserfs/
|
||||
|
||||
REMOTE PROCESSOR (REMOTEPROC) SUBSYSTEM
|
||||
M: Bjorn Andersson <andersson@kernel.org>
|
||||
M: Mathieu Poirier <mathieu.poirier@linaro.org>
|
||||
|
@ -51,7 +51,6 @@ CONFIG_SERIAL_8250_CONSOLE=y
|
||||
CONFIG_RTC_CLASS=y
|
||||
CONFIG_RTC_DRV_CMOS=y
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_REISERFS_FS=m
|
||||
CONFIG_ISO9660_FS=y
|
||||
CONFIG_MSDOS_FS=y
|
||||
CONFIG_VFAT_FS=y
|
||||
|
@ -583,10 +583,6 @@ CONFIG_EXT2_FS_SECURITY=y
|
||||
CONFIG_EXT3_FS=y
|
||||
CONFIG_EXT3_FS_POSIX_ACL=y
|
||||
CONFIG_EXT3_FS_SECURITY=y
|
||||
CONFIG_REISERFS_FS=m
|
||||
CONFIG_REISERFS_FS_XATTR=y
|
||||
CONFIG_REISERFS_FS_POSIX_ACL=y
|
||||
CONFIG_REISERFS_FS_SECURITY=y
|
||||
CONFIG_XFS_FS=m
|
||||
CONFIG_AUTOFS_FS=m
|
||||
CONFIG_FUSE_FS=m
|
||||
|
@ -449,7 +449,6 @@ CONFIG_RTC_DRV_RP5C01=m
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_DAX=m
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
|
@ -406,7 +406,6 @@ CONFIG_RTC_DRV_GENERIC=m
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_DAX=m
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
|
@ -426,7 +426,6 @@ CONFIG_RTC_DRV_GENERIC=m
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_DAX=m
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
|
@ -398,7 +398,6 @@ CONFIG_RTC_DRV_GENERIC=m
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_DAX=m
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
|
@ -408,7 +408,6 @@ CONFIG_RTC_DRV_GENERIC=m
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_DAX=m
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
|
@ -425,7 +425,6 @@ CONFIG_RTC_DRV_GENERIC=m
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_DAX=m
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
|
@ -511,7 +511,6 @@ CONFIG_RTC_DRV_GENERIC=m
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_DAX=m
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
|
@ -397,7 +397,6 @@ CONFIG_RTC_DRV_GENERIC=m
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_DAX=m
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
|
@ -398,7 +398,6 @@ CONFIG_RTC_DRV_GENERIC=m
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_DAX=m
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
|
@ -415,7 +415,6 @@ CONFIG_RTC_DRV_GENERIC=m
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_DAX=m
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
|
@ -396,7 +396,6 @@ CONFIG_RTC_DRV_GENERIC=m
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_DAX=m
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
|
@ -396,7 +396,6 @@ CONFIG_RTC_DRV_GENERIC=m
|
||||
# CONFIG_IOMMU_SUPPORT is not set
|
||||
CONFIG_DAX=m
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_REISERFS_FS=m
|
||||
CONFIG_JFS_FS=m
|
||||
CONFIG_OCFS2_FS=m
|
||||
# CONFIG_OCFS2_DEBUG_MASKLOG is not set
|
||||
|
@ -95,7 +95,6 @@ CONFIG_USB_SISUSBVGA=m
|
||||
CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT3_FS=y
|
||||
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
|
||||
CONFIG_REISERFS_FS=y
|
||||
CONFIG_ISO9660_FS=m
|
||||
CONFIG_MSDOS_FS=y
|
||||
CONFIG_VFAT_FS=y
|
||||
|
@ -220,7 +220,6 @@ CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT3_FS=y
|
||||
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
|
||||
# CONFIG_EXT3_FS_XATTR is not set
|
||||
CONFIG_REISERFS_FS=m
|
||||
CONFIG_XFS_FS=m
|
||||
CONFIG_FUSE_FS=m
|
||||
CONFIG_ISO9660_FS=m
|
||||
|
@ -61,7 +61,6 @@ CONFIG_UML_NET_DAEMON=y
|
||||
CONFIG_UML_NET_MCAST=y
|
||||
CONFIG_UML_NET_SLIRP=y
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_REISERFS_FS=y
|
||||
CONFIG_QUOTA=y
|
||||
CONFIG_AUTOFS_FS=m
|
||||
CONFIG_ISO9660_FS=m
|
||||
|
@ -59,7 +59,6 @@ CONFIG_UML_NET_DAEMON=y
|
||||
CONFIG_UML_NET_MCAST=y
|
||||
CONFIG_UML_NET_SLIRP=y
|
||||
CONFIG_EXT4_FS=y
|
||||
CONFIG_REISERFS_FS=y
|
||||
CONFIG_QUOTA=y
|
||||
CONFIG_AUTOFS_FS=m
|
||||
CONFIG_ISO9660_FS=m
|
||||
|
@ -130,7 +130,7 @@ config BLK_DEV_UBD_SYNC
|
||||
kernel command line option. Alternatively, you can say Y here to
|
||||
turn on synchronous operation by default for all block devices.
|
||||
|
||||
If you're running a journalling file system (like reiserfs, for
|
||||
If you're running a journalling file system (like xfs, for
|
||||
example) in your virtual machine, you will want to say Y here. If
|
||||
you care for the safety of the data in your virtual machine, Y is a
|
||||
wise choice too. In all other cases (for example, if you're just
|
||||
|
@ -43,7 +43,6 @@ config FS_MBCACHE
|
||||
default y if EXT4_FS=y
|
||||
default m if EXT2_FS_XATTR || EXT4_FS
|
||||
|
||||
source "fs/reiserfs/Kconfig"
|
||||
source "fs/jfs/Kconfig"
|
||||
|
||||
source "fs/xfs/Kconfig"
|
||||
|
@ -61,7 +61,6 @@ obj-$(CONFIG_DLM) += dlm/
|
||||
|
||||
# Do not add any filesystems before this line
|
||||
obj-$(CONFIG_NETFS_SUPPORT) += netfs/
|
||||
obj-$(CONFIG_REISERFS_FS) += reiserfs/
|
||||
obj-$(CONFIG_EXT4_FS) += ext4/
|
||||
# We place ext4 before ext2 so that clean ext3 root fs's do NOT mount using the
|
||||
# ext2 driver, which doesn't know about journalling! Explicitly request ext2
|
||||
|
@ -855,8 +855,7 @@ static int fsync_buffers_list(spinlock_t *lock, struct list_head *list)
|
||||
* done a sync(). Just drop the buffers from the inode list.
|
||||
*
|
||||
* NOTE: we take the inode's blockdev's mapping's i_private_lock. Which
|
||||
* assumes that all the buffers are against the blockdev. Not true
|
||||
* for reiserfs.
|
||||
* assumes that all the buffers are against the blockdev.
|
||||
*/
|
||||
void invalidate_inode_buffers(struct inode *inode)
|
||||
{
|
||||
|
@ -9,14 +9,13 @@ config QUOTA
|
||||
help
|
||||
If you say Y here, you will be able to set per user limits for disk
|
||||
usage (also called disk quotas). Currently, it works for the
|
||||
ext2, ext3, ext4, f2fs, jfs, ocfs2 and reiserfs file systems.
|
||||
Note that gfs2 and xfs use their own quota system.
|
||||
Ext3, ext4 and reiserfs also support journaled quotas for which
|
||||
you don't need to run quotacheck(8) after an unclean shutdown.
|
||||
For further details, read the Quota mini-HOWTO, available from
|
||||
<https://www.tldp.org/docs.html#howto>, or the documentation provided
|
||||
with the quota tools. Probably the quota support is only useful for
|
||||
multi user systems. If unsure, say N.
|
||||
ext2, ext3, ext4, f2fs, jfs and ocfs2 file systems. Note that gfs2
|
||||
and xfs use their own quota system. Ext3 and ext4 also support
|
||||
journaled quotas for which you don't need to run quotacheck(8) after
|
||||
an unclean shutdown. For further details, read the Quota mini-HOWTO,
|
||||
available from <https://www.tldp.org/docs.html#howto>, or the
|
||||
documentation provided with the quota tools. Probably the quota
|
||||
support is only useful for multi user systems. If unsure, say N.
|
||||
|
||||
config QUOTA_NETLINK_INTERFACE
|
||||
bool "Report quota messages through netlink interface"
|
||||
|
@ -1,91 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config REISERFS_FS
|
||||
tristate "Reiserfs support (deprecated)"
|
||||
select BUFFER_HEAD
|
||||
select CRC32
|
||||
select LEGACY_DIRECT_IO
|
||||
help
|
||||
Reiserfs is deprecated and scheduled to be removed from the kernel
|
||||
in 2025. If you are still using it, please migrate to another
|
||||
filesystem or tell us your usecase for reiserfs.
|
||||
|
||||
Reiserfs stores not just filenames but the files themselves in a
|
||||
balanced tree. Uses journalling.
|
||||
|
||||
Balanced trees are more efficient than traditional file system
|
||||
architectural foundations.
|
||||
|
||||
In general, ReiserFS is as fast as ext2, but is very efficient with
|
||||
large directories and small files. Additional patches are needed
|
||||
for NFS and quotas, please see
|
||||
<https://reiser4.wiki.kernel.org/index.php/Main_Page> for links.
|
||||
|
||||
It is more easily extended to have features currently found in
|
||||
database and keyword search systems than block allocation based file
|
||||
systems are. The next version will be so extended, and will support
|
||||
plugins consistent with our motto ``It takes more than a license to
|
||||
make source code open.''
|
||||
|
||||
Read <https://reiser4.wiki.kernel.org/index.php/Main_Page>
|
||||
to learn more about reiserfs.
|
||||
|
||||
Sponsored by Threshold Networks, Emusic.com, and Bigstorage.com.
|
||||
|
||||
If you like it, you can pay us to add new features to it that you
|
||||
need, buy a support contract, or pay us to port it to another OS.
|
||||
|
||||
config REISERFS_CHECK
|
||||
bool "Enable reiserfs debug mode"
|
||||
depends on REISERFS_FS
|
||||
help
|
||||
If you set this to Y, then ReiserFS will perform every check it can
|
||||
possibly imagine of its internal consistency throughout its
|
||||
operation. It will also go substantially slower. More than once we
|
||||
have forgotten that this was on, and then gone despondent over the
|
||||
latest benchmarks.:-) Use of this option allows our team to go all
|
||||
out in checking for consistency when debugging without fear of its
|
||||
effect on end users. If you are on the verge of sending in a bug
|
||||
report, say Y and you might get a useful error message. Almost
|
||||
everyone should say N.
|
||||
|
||||
config REISERFS_PROC_INFO
|
||||
bool "Stats in /proc/fs/reiserfs"
|
||||
depends on REISERFS_FS && PROC_FS
|
||||
help
|
||||
Create under /proc/fs/reiserfs a hierarchy of files, displaying
|
||||
various ReiserFS statistics and internal data at the expense of
|
||||
making your kernel or module slightly larger (+8 KB). This also
|
||||
increases the amount of kernel memory required for each mount.
|
||||
Almost everyone but ReiserFS developers and people fine-tuning
|
||||
reiserfs or tracing problems should say N.
|
||||
|
||||
config REISERFS_FS_XATTR
|
||||
bool "ReiserFS extended attributes"
|
||||
depends on REISERFS_FS
|
||||
help
|
||||
Extended attributes are name:value pairs associated with inodes by
|
||||
the kernel or by users (see the attr(5) manual page for details).
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config REISERFS_FS_POSIX_ACL
|
||||
bool "ReiserFS POSIX Access Control Lists"
|
||||
depends on REISERFS_FS_XATTR
|
||||
select FS_POSIX_ACL
|
||||
help
|
||||
Posix Access Control Lists (ACLs) support permissions for users and
|
||||
groups beyond the owner/group/world scheme.
|
||||
|
||||
If you don't know what Access Control Lists are, say N
|
||||
|
||||
config REISERFS_FS_SECURITY
|
||||
bool "ReiserFS Security Labels"
|
||||
depends on REISERFS_FS_XATTR
|
||||
help
|
||||
Security labels support alternative access control models
|
||||
implemented by security modules like SELinux. This option
|
||||
enables an extended attribute handler for file security
|
||||
labels in the ReiserFS filesystem.
|
||||
|
||||
If you are not using a security module that requires using
|
||||
extended attributes for file security labels, say N.
|
@ -1,30 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Makefile for the linux reiser-filesystem routines.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_REISERFS_FS) += reiserfs.o
|
||||
|
||||
reiserfs-objs := bitmap.o do_balan.o namei.o inode.o file.o dir.o fix_node.o \
|
||||
super.o prints.o objectid.o lbalance.o ibalance.o stree.o \
|
||||
hashes.o tail_conversion.o journal.o resize.o \
|
||||
item_ops.o ioctl.o xattr.o lock.o
|
||||
|
||||
ifeq ($(CONFIG_REISERFS_PROC_INFO),y)
|
||||
reiserfs-objs += procfs.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_REISERFS_FS_XATTR),y)
|
||||
reiserfs-objs += xattr_user.o xattr_trusted.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_REISERFS_FS_SECURITY),y)
|
||||
reiserfs-objs += xattr_security.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_REISERFS_FS_POSIX_ACL),y)
|
||||
reiserfs-objs += xattr_acl.o
|
||||
endif
|
||||
|
||||
TAGS:
|
||||
etags *.c
|
@ -1,151 +0,0 @@
|
||||
[LICENSING]
|
||||
|
||||
ReiserFS is hereby licensed under the GNU General
|
||||
Public License version 2.
|
||||
|
||||
Source code files that contain the phrase "licensing governed by
|
||||
reiserfs/README" are "governed files" throughout this file. Governed
|
||||
files are licensed under the GPL. The portions of them owned by Hans
|
||||
Reiser, or authorized to be licensed by him, have been in the past,
|
||||
and likely will be in the future, licensed to other parties under
|
||||
other licenses. If you add your code to governed files, and don't
|
||||
want it to be owned by Hans Reiser, put your copyright label on that
|
||||
code so the poor blight and his customers can keep things straight.
|
||||
All portions of governed files not labeled otherwise are owned by Hans
|
||||
Reiser, and by adding your code to it, widely distributing it to
|
||||
others or sending us a patch, and leaving the sentence in stating that
|
||||
licensing is governed by the statement in this file, you accept this.
|
||||
It will be a kindness if you identify whether Hans Reiser is allowed
|
||||
to license code labeled as owned by you on your behalf other than
|
||||
under the GPL, because he wants to know if it is okay to do so and put
|
||||
a check in the mail to you (for non-trivial improvements) when he
|
||||
makes his next sale. He makes no guarantees as to the amount if any,
|
||||
though he feels motivated to motivate contributors, and you can surely
|
||||
discuss this with him before or after contributing. You have the
|
||||
right to decline to allow him to license your code contribution other
|
||||
than under the GPL.
|
||||
|
||||
Further licensing options are available for commercial and/or other
|
||||
interests directly from Hans Reiser: hans@reiser.to. If you interpret
|
||||
the GPL as not allowing those additional licensing options, you read
|
||||
it wrongly, and Richard Stallman agrees with me, when carefully read
|
||||
you can see that those restrictions on additional terms do not apply
|
||||
to the owner of the copyright, and my interpretation of this shall
|
||||
govern for this license.
|
||||
|
||||
Finally, nothing in this license shall be interpreted to allow you to
|
||||
fail to fairly credit me, or to remove my credits, without my
|
||||
permission, unless you are an end user not redistributing to others.
|
||||
If you have doubts about how to properly do that, or about what is
|
||||
fair, ask. (Last I spoke with him Richard was contemplating how best
|
||||
to address the fair crediting issue in the next GPL version.)
|
||||
|
||||
[END LICENSING]
|
||||
|
||||
Reiserfs is a file system based on balanced tree algorithms, which is
|
||||
described at https://reiser4.wiki.kernel.org/index.php/Main_Page
|
||||
|
||||
Stop reading here. Go there, then return.
|
||||
|
||||
Send bug reports to yura@namesys.botik.ru.
|
||||
|
||||
mkreiserfs and other utilities are in reiserfs/utils, or wherever your
|
||||
Linux provider put them. There is some disagreement about how useful
|
||||
it is for users to get their fsck and mkreiserfs out of sync with the
|
||||
version of reiserfs that is in their kernel, with many important
|
||||
distributors wanting them out of sync.:-) Please try to remember to
|
||||
recompile and reinstall fsck and mkreiserfs with every update of
|
||||
reiserfs, this is a common source of confusion. Note that some of the
|
||||
utilities cannot be compiled without accessing the balancing code
|
||||
which is in the kernel code, and relocating the utilities may require
|
||||
you to specify where that code can be found.
|
||||
|
||||
Yes, if you update your reiserfs kernel module you do have to
|
||||
recompile your kernel, most of the time. The errors you get will be
|
||||
quite cryptic if your forget to do so.
|
||||
|
||||
Real users, as opposed to folks who want to hack and then understand
|
||||
what went wrong, will want REISERFS_CHECK off.
|
||||
|
||||
Hideous Commercial Pitch: Spread your development costs across other OS
|
||||
vendors. Select from the best in the world, not the best in your
|
||||
building, by buying from third party OS component suppliers. Leverage
|
||||
the software component development power of the internet. Be the most
|
||||
aggressive in taking advantage of the commercial possibilities of
|
||||
decentralized internet development, and add value through your branded
|
||||
integration that you sell as an operating system. Let your competitors
|
||||
be the ones to compete against the entire internet by themselves. Be
|
||||
hip, get with the new economic trend, before your competitors do. Send
|
||||
email to hans@reiser.to.
|
||||
|
||||
To understand the code, after reading the website, start reading the
|
||||
code by reading reiserfs_fs.h first.
|
||||
|
||||
Hans Reiser was the project initiator, primary architect, source of all
|
||||
funding for the first 5.5 years, and one of the programmers. He owns
|
||||
the copyright.
|
||||
|
||||
Vladimir Saveljev was one of the programmers, and he worked long hours
|
||||
writing the cleanest code. He always made the effort to be the best he
|
||||
could be, and to make his code the best that it could be. What resulted
|
||||
was quite remarkable. I don't think that money can ever motivate someone
|
||||
to work the way he did, he is one of the most selfless men I know.
|
||||
|
||||
Yura helps with benchmarking, coding hashes, and block pre-allocation
|
||||
code.
|
||||
|
||||
Anatoly Pinchuk is a former member of our team who worked closely with
|
||||
Vladimir throughout the project's development. He wrote a quite
|
||||
substantial portion of the total code. He realized that there was a
|
||||
space problem with packing tails of files for files larger than a node
|
||||
that start on a node aligned boundary (there are reasons to want to node
|
||||
align files), and he invented and implemented indirect items and
|
||||
unformatted nodes as the solution.
|
||||
|
||||
Konstantin Shvachko was taking part in the early days.
|
||||
|
||||
Mikhail Gilula was a brilliant innovator that has shown much generosity.
|
||||
|
||||
Grigory Zaigralin was an extremely effective system administrator for
|
||||
our group.
|
||||
|
||||
Igor Krasheninnikov was wonderful at hardware procurement, repair, and
|
||||
network installation.
|
||||
|
||||
Jeremy Fitzhardinge wrote the teahash.c code, and he gives credit to a
|
||||
textbook he got the algorithm from in the code. Note that his analysis
|
||||
of how we could use the hashing code in making 32 bit NFS cookies work
|
||||
was probably more important than the actual algorithm. Colin Plumb also
|
||||
contributed to it.
|
||||
|
||||
Chris Mason dived right into our code, and in just a few months produced
|
||||
the journaling code that dramatically increased the value of ReiserFS.
|
||||
He is just an amazing programmer.
|
||||
|
||||
Igor Zagorovsky is writing much of the new item handler and extent code
|
||||
for our next major release.
|
||||
|
||||
Alexander Zarochentcev (sometimes known as zam, or sasha), wrote the
|
||||
resizer, and is hard at work on implementing allocate on flush. SGI
|
||||
implemented allocate on flush before us for XFS, and generously took
|
||||
the time to convince me we should do it also. They are great people,
|
||||
and a great company.
|
||||
|
||||
Yuri Shevchuk and Nikita Danilov are doing squid cache optimization.
|
||||
|
||||
Vitaly Fertman is doing fsck.
|
||||
|
||||
Jeff Mahoney, of SuSE, contributed a few cleanup fixes, most notably
|
||||
the endian safe patches which allow ReiserFS to run on any platform
|
||||
supported by the Linux kernel.
|
||||
|
||||
SuSE, IntegratedLinux.com, Ecila, MP3.com, bigstorage.com, and the
|
||||
Alpha PC Company made it possible for me to not have a day job
|
||||
anymore, and to dramatically increase our staffing. Ecila funded
|
||||
hypertext feature development, MP3.com funded journaling, SuSE funded
|
||||
core development, IntegratedLinux.com funded squid web cache
|
||||
appliances, bigstorage.com funded HSM, and the alpha PC company funded
|
||||
the alpha port. Many of these tasks were helped by sponsors other
|
||||
than the ones just named. SuSE has helped in much more than just
|
||||
funding....
|
||||
|
@ -1,78 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#include <linux/init.h>
|
||||
#include <linux/posix_acl.h>
|
||||
|
||||
#define REISERFS_ACL_VERSION 0x0001
|
||||
|
||||
typedef struct {
|
||||
__le16 e_tag;
|
||||
__le16 e_perm;
|
||||
__le32 e_id;
|
||||
} reiserfs_acl_entry;
|
||||
|
||||
typedef struct {
|
||||
__le16 e_tag;
|
||||
__le16 e_perm;
|
||||
} reiserfs_acl_entry_short;
|
||||
|
||||
typedef struct {
|
||||
__le32 a_version;
|
||||
} reiserfs_acl_header;
|
||||
|
||||
static inline size_t reiserfs_acl_size(int count)
|
||||
{
|
||||
if (count <= 4) {
|
||||
return sizeof(reiserfs_acl_header) +
|
||||
count * sizeof(reiserfs_acl_entry_short);
|
||||
} else {
|
||||
return sizeof(reiserfs_acl_header) +
|
||||
4 * sizeof(reiserfs_acl_entry_short) +
|
||||
(count - 4) * sizeof(reiserfs_acl_entry);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int reiserfs_acl_count(size_t size)
|
||||
{
|
||||
ssize_t s;
|
||||
size -= sizeof(reiserfs_acl_header);
|
||||
s = size - 4 * sizeof(reiserfs_acl_entry_short);
|
||||
if (s < 0) {
|
||||
if (size % sizeof(reiserfs_acl_entry_short))
|
||||
return -1;
|
||||
return size / sizeof(reiserfs_acl_entry_short);
|
||||
} else {
|
||||
if (s % sizeof(reiserfs_acl_entry))
|
||||
return -1;
|
||||
return s / sizeof(reiserfs_acl_entry) + 4;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_REISERFS_FS_POSIX_ACL
|
||||
struct posix_acl *reiserfs_get_acl(struct inode *inode, int type, bool rcu);
|
||||
int reiserfs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
|
||||
struct posix_acl *acl, int type);
|
||||
int reiserfs_acl_chmod(struct dentry *dentry);
|
||||
int reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
|
||||
struct inode *dir, struct dentry *dentry,
|
||||
struct inode *inode);
|
||||
int reiserfs_cache_default_acl(struct inode *dir);
|
||||
|
||||
#else
|
||||
|
||||
#define reiserfs_cache_default_acl(inode) 0
|
||||
#define reiserfs_get_acl NULL
|
||||
#define reiserfs_set_acl NULL
|
||||
|
||||
static inline int reiserfs_acl_chmod(struct dentry *dentry)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
|
||||
const struct inode *dir, struct dentry *dentry,
|
||||
struct inode *inode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
1476
fs/reiserfs/bitmap.c
1476
fs/reiserfs/bitmap.c
File diff suppressed because it is too large
Load Diff
@ -1,346 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
|
||||
*/
|
||||
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fs.h>
|
||||
#include "reiserfs.h"
|
||||
#include <linux/stat.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
extern const struct reiserfs_key MIN_KEY;
|
||||
|
||||
static int reiserfs_readdir(struct file *, struct dir_context *);
|
||||
static int reiserfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
|
||||
int datasync);
|
||||
|
||||
const struct file_operations reiserfs_dir_operations = {
|
||||
.llseek = generic_file_llseek,
|
||||
.read = generic_read_dir,
|
||||
.iterate_shared = reiserfs_readdir,
|
||||
.fsync = reiserfs_dir_fsync,
|
||||
.unlocked_ioctl = reiserfs_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = reiserfs_compat_ioctl,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int reiserfs_dir_fsync(struct file *filp, loff_t start, loff_t end,
|
||||
int datasync)
|
||||
{
|
||||
struct inode *inode = filp->f_mapping->host;
|
||||
int err;
|
||||
|
||||
err = file_write_and_wait_range(filp, start, end);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
inode_lock(inode);
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
err = reiserfs_commit_for_inode(inode);
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
inode_unlock(inode);
|
||||
if (err < 0)
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define store_ih(where,what) copy_item_head (where, what)
|
||||
|
||||
static inline bool is_privroot_deh(struct inode *dir, struct reiserfs_de_head *deh)
|
||||
{
|
||||
struct dentry *privroot = REISERFS_SB(dir->i_sb)->priv_root;
|
||||
return (d_really_is_positive(privroot) &&
|
||||
deh->deh_objectid == INODE_PKEY(d_inode(privroot))->k_objectid);
|
||||
}
|
||||
|
||||
int reiserfs_readdir_inode(struct inode *inode, struct dir_context *ctx)
|
||||
{
|
||||
|
||||
/* key of current position in the directory (key of directory entry) */
|
||||
struct cpu_key pos_key;
|
||||
|
||||
INITIALIZE_PATH(path_to_entry);
|
||||
struct buffer_head *bh;
|
||||
int item_num, entry_num;
|
||||
const struct reiserfs_key *rkey;
|
||||
struct item_head *ih, tmp_ih;
|
||||
int search_res;
|
||||
char *local_buf;
|
||||
loff_t next_pos;
|
||||
char small_buf[32]; /* avoid kmalloc if we can */
|
||||
struct reiserfs_dir_entry de;
|
||||
int ret = 0;
|
||||
int depth;
|
||||
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
|
||||
reiserfs_check_lock_depth(inode->i_sb, "readdir");
|
||||
|
||||
/*
|
||||
* form key for search the next directory entry using
|
||||
* f_pos field of file structure
|
||||
*/
|
||||
make_cpu_key(&pos_key, inode, ctx->pos ?: DOT_OFFSET, TYPE_DIRENTRY, 3);
|
||||
next_pos = cpu_key_k_offset(&pos_key);
|
||||
|
||||
path_to_entry.reada = PATH_READA;
|
||||
while (1) {
|
||||
research:
|
||||
/*
|
||||
* search the directory item, containing entry with
|
||||
* specified key
|
||||
*/
|
||||
search_res =
|
||||
search_by_entry_key(inode->i_sb, &pos_key, &path_to_entry,
|
||||
&de);
|
||||
if (search_res == IO_ERROR) {
|
||||
/*
|
||||
* FIXME: we could just skip part of directory
|
||||
* which could not be read
|
||||
*/
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
entry_num = de.de_entry_num;
|
||||
bh = de.de_bh;
|
||||
item_num = de.de_item_num;
|
||||
ih = de.de_ih;
|
||||
store_ih(&tmp_ih, ih);
|
||||
|
||||
/* we must have found item, that is item of this directory, */
|
||||
RFALSE(COMP_SHORT_KEYS(&ih->ih_key, &pos_key),
|
||||
"vs-9000: found item %h does not match to dir we readdir %K",
|
||||
ih, &pos_key);
|
||||
RFALSE(item_num > B_NR_ITEMS(bh) - 1,
|
||||
"vs-9005 item_num == %d, item amount == %d",
|
||||
item_num, B_NR_ITEMS(bh));
|
||||
|
||||
/*
|
||||
* and entry must be not more than number of entries
|
||||
* in the item
|
||||
*/
|
||||
RFALSE(ih_entry_count(ih) < entry_num,
|
||||
"vs-9010: entry number is too big %d (%d)",
|
||||
entry_num, ih_entry_count(ih));
|
||||
|
||||
/*
|
||||
* go through all entries in the directory item beginning
|
||||
* from the entry, that has been found
|
||||
*/
|
||||
if (search_res == POSITION_FOUND
|
||||
|| entry_num < ih_entry_count(ih)) {
|
||||
struct reiserfs_de_head *deh =
|
||||
B_I_DEH(bh, ih) + entry_num;
|
||||
|
||||
for (; entry_num < ih_entry_count(ih);
|
||||
entry_num++, deh++) {
|
||||
int d_reclen;
|
||||
char *d_name;
|
||||
ino_t d_ino;
|
||||
loff_t cur_pos = deh_offset(deh);
|
||||
|
||||
/* it is hidden entry */
|
||||
if (!de_visible(deh))
|
||||
continue;
|
||||
d_reclen = entry_length(bh, ih, entry_num);
|
||||
d_name = B_I_DEH_ENTRY_FILE_NAME(bh, ih, deh);
|
||||
|
||||
if (d_reclen <= 0 ||
|
||||
d_name + d_reclen > bh->b_data + bh->b_size) {
|
||||
/*
|
||||
* There is corrupted data in entry,
|
||||
* We'd better stop here
|
||||
*/
|
||||
pathrelse(&path_to_entry);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!d_name[d_reclen - 1])
|
||||
d_reclen = strlen(d_name);
|
||||
|
||||
/* too big to send back to VFS */
|
||||
if (d_reclen >
|
||||
REISERFS_MAX_NAME(inode->i_sb->
|
||||
s_blocksize)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Ignore the .reiserfs_priv entry */
|
||||
if (is_privroot_deh(inode, deh))
|
||||
continue;
|
||||
|
||||
ctx->pos = deh_offset(deh);
|
||||
d_ino = deh_objectid(deh);
|
||||
if (d_reclen <= 32) {
|
||||
local_buf = small_buf;
|
||||
} else {
|
||||
local_buf = kmalloc(d_reclen,
|
||||
GFP_NOFS);
|
||||
if (!local_buf) {
|
||||
pathrelse(&path_to_entry);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (item_moved(&tmp_ih, &path_to_entry)) {
|
||||
kfree(local_buf);
|
||||
goto research;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Note, that we copy name to user space via
|
||||
* temporary buffer (local_buf) because
|
||||
* filldir will block if user space buffer is
|
||||
* swapped out. At that time entry can move to
|
||||
* somewhere else
|
||||
*/
|
||||
memcpy(local_buf, d_name, d_reclen);
|
||||
|
||||
/*
|
||||
* Since filldir might sleep, we can release
|
||||
* the write lock here for other waiters
|
||||
*/
|
||||
depth = reiserfs_write_unlock_nested(inode->i_sb);
|
||||
if (!dir_emit
|
||||
(ctx, local_buf, d_reclen, d_ino,
|
||||
DT_UNKNOWN)) {
|
||||
reiserfs_write_lock_nested(inode->i_sb, depth);
|
||||
if (local_buf != small_buf) {
|
||||
kfree(local_buf);
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
reiserfs_write_lock_nested(inode->i_sb, depth);
|
||||
if (local_buf != small_buf) {
|
||||
kfree(local_buf);
|
||||
}
|
||||
|
||||
/* deh_offset(deh) may be invalid now. */
|
||||
next_pos = cur_pos + 1;
|
||||
|
||||
if (item_moved(&tmp_ih, &path_to_entry)) {
|
||||
set_cpu_key_k_offset(&pos_key,
|
||||
next_pos);
|
||||
goto research;
|
||||
}
|
||||
} /* for */
|
||||
}
|
||||
|
||||
/* end of directory has been reached */
|
||||
if (item_num != B_NR_ITEMS(bh) - 1)
|
||||
goto end;
|
||||
|
||||
/*
|
||||
* item we went through is last item of node. Using right
|
||||
* delimiting key check is it directory end
|
||||
*/
|
||||
rkey = get_rkey(&path_to_entry, inode->i_sb);
|
||||
if (!comp_le_keys(rkey, &MIN_KEY)) {
|
||||
/*
|
||||
* set pos_key to key, that is the smallest and greater
|
||||
* that key of the last entry in the item
|
||||
*/
|
||||
set_cpu_key_k_offset(&pos_key, next_pos);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* end of directory has been reached */
|
||||
if (COMP_SHORT_KEYS(rkey, &pos_key)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* directory continues in the right neighboring block */
|
||||
set_cpu_key_k_offset(&pos_key,
|
||||
le_key_k_offset(KEY_FORMAT_3_5, rkey));
|
||||
|
||||
} /* while */
|
||||
|
||||
end:
|
||||
ctx->pos = next_pos;
|
||||
pathrelse(&path_to_entry);
|
||||
reiserfs_check_path(&path_to_entry);
|
||||
out:
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int reiserfs_readdir(struct file *file, struct dir_context *ctx)
|
||||
{
|
||||
return reiserfs_readdir_inode(file_inode(file), ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* compose directory item containing "." and ".." entries (entries are
|
||||
* not aligned to 4 byte boundary)
|
||||
*/
|
||||
void make_empty_dir_item_v1(char *body, __le32 dirid, __le32 objid,
|
||||
__le32 par_dirid, __le32 par_objid)
|
||||
{
|
||||
struct reiserfs_de_head *dot, *dotdot;
|
||||
|
||||
memset(body, 0, EMPTY_DIR_SIZE_V1);
|
||||
dot = (struct reiserfs_de_head *)body;
|
||||
dotdot = dot + 1;
|
||||
|
||||
/* direntry header of "." */
|
||||
put_deh_offset(dot, DOT_OFFSET);
|
||||
/* these two are from make_le_item_head, and are LE */
|
||||
dot->deh_dir_id = dirid;
|
||||
dot->deh_objectid = objid;
|
||||
dot->deh_state = 0; /* Endian safe if 0 */
|
||||
put_deh_location(dot, EMPTY_DIR_SIZE_V1 - strlen("."));
|
||||
mark_de_visible(dot);
|
||||
|
||||
/* direntry header of ".." */
|
||||
put_deh_offset(dotdot, DOT_DOT_OFFSET);
|
||||
/* key of ".." for the root directory */
|
||||
/* these two are from the inode, and are LE */
|
||||
dotdot->deh_dir_id = par_dirid;
|
||||
dotdot->deh_objectid = par_objid;
|
||||
dotdot->deh_state = 0; /* Endian safe if 0 */
|
||||
put_deh_location(dotdot, deh_location(dot) - strlen(".."));
|
||||
mark_de_visible(dotdot);
|
||||
|
||||
/* copy ".." and "." */
|
||||
memcpy(body + deh_location(dot), ".", 1);
|
||||
memcpy(body + deh_location(dotdot), "..", 2);
|
||||
}
|
||||
|
||||
/* compose directory item containing "." and ".." entries */
|
||||
void make_empty_dir_item(char *body, __le32 dirid, __le32 objid,
|
||||
__le32 par_dirid, __le32 par_objid)
|
||||
{
|
||||
struct reiserfs_de_head *dot, *dotdot;
|
||||
|
||||
memset(body, 0, EMPTY_DIR_SIZE);
|
||||
dot = (struct reiserfs_de_head *)body;
|
||||
dotdot = dot + 1;
|
||||
|
||||
/* direntry header of "." */
|
||||
put_deh_offset(dot, DOT_OFFSET);
|
||||
/* these two are from make_le_item_head, and are LE */
|
||||
dot->deh_dir_id = dirid;
|
||||
dot->deh_objectid = objid;
|
||||
dot->deh_state = 0; /* Endian safe if 0 */
|
||||
put_deh_location(dot, EMPTY_DIR_SIZE - ROUND_UP(strlen(".")));
|
||||
mark_de_visible(dot);
|
||||
|
||||
/* direntry header of ".." */
|
||||
put_deh_offset(dotdot, DOT_DOT_OFFSET);
|
||||
/* key of ".." for the root directory */
|
||||
/* these two are from the inode, and are LE */
|
||||
dotdot->deh_dir_id = par_dirid;
|
||||
dotdot->deh_objectid = par_objid;
|
||||
dotdot->deh_state = 0; /* Endian safe if 0 */
|
||||
put_deh_location(dotdot, deh_location(dot) - ROUND_UP(strlen("..")));
|
||||
mark_de_visible(dotdot);
|
||||
|
||||
/* copy ".." and "." */
|
||||
memcpy(body + deh_location(dot), ".", 1);
|
||||
memcpy(body + deh_location(dotdot), "..", 2);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,270 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
|
||||
*/
|
||||
|
||||
#include <linux/time.h>
|
||||
#include "reiserfs.h"
|
||||
#include "acl.h"
|
||||
#include "xattr.h"
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/writeback.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include <linux/quotaops.h>
|
||||
|
||||
/*
|
||||
* We pack the tails of files on file close, not at the time they are written.
|
||||
* This implies an unnecessary copy of the tail and an unnecessary indirect item
|
||||
* insertion/balancing, for files that are written in one write.
|
||||
* It avoids unnecessary tail packings (balances) for files that are written in
|
||||
* multiple writes and are small enough to have tails.
|
||||
*
|
||||
* file_release is called by the VFS layer when the file is closed. If
|
||||
* this is the last open file descriptor, and the file
|
||||
* small enough to have a tail, and the tail is currently in an
|
||||
* unformatted node, the tail is converted back into a direct item.
|
||||
*
|
||||
* We use reiserfs_truncate_file to pack the tail, since it already has
|
||||
* all the conditions coded.
|
||||
*/
|
||||
static int reiserfs_file_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
|
||||
struct reiserfs_transaction_handle th;
|
||||
int err;
|
||||
int jbegin_failure = 0;
|
||||
|
||||
BUG_ON(!S_ISREG(inode->i_mode));
|
||||
|
||||
if (!atomic_dec_and_mutex_lock(&REISERFS_I(inode)->openers,
|
||||
&REISERFS_I(inode)->tailpack))
|
||||
return 0;
|
||||
|
||||
/* fast out for when nothing needs to be done */
|
||||
if ((!(REISERFS_I(inode)->i_flags & i_pack_on_close_mask) ||
|
||||
!tail_has_to_be_packed(inode)) &&
|
||||
REISERFS_I(inode)->i_prealloc_count <= 0) {
|
||||
mutex_unlock(&REISERFS_I(inode)->tailpack);
|
||||
return 0;
|
||||
}
|
||||
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
/*
|
||||
* freeing preallocation only involves relogging blocks that
|
||||
* are already in the current transaction. preallocation gets
|
||||
* freed at the end of each transaction, so it is impossible for
|
||||
* us to log any additional blocks (including quota blocks)
|
||||
*/
|
||||
err = journal_begin(&th, inode->i_sb, 1);
|
||||
if (err) {
|
||||
/*
|
||||
* uh oh, we can't allow the inode to go away while there
|
||||
* is still preallocation blocks pending. Try to join the
|
||||
* aborted transaction
|
||||
*/
|
||||
jbegin_failure = err;
|
||||
err = journal_join_abort(&th, inode->i_sb);
|
||||
|
||||
if (err) {
|
||||
/*
|
||||
* hmpf, our choices here aren't good. We can pin
|
||||
* the inode which will disallow unmount from ever
|
||||
* happening, we can do nothing, which will corrupt
|
||||
* random memory on unmount, or we can forcibly
|
||||
* remove the file from the preallocation list, which
|
||||
* will leak blocks on disk. Lets pin the inode
|
||||
* and let the admin know what is going on.
|
||||
*/
|
||||
igrab(inode);
|
||||
reiserfs_warning(inode->i_sb, "clm-9001",
|
||||
"pinning inode %lu because the "
|
||||
"preallocation can't be freed",
|
||||
inode->i_ino);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
reiserfs_update_inode_transaction(inode);
|
||||
|
||||
#ifdef REISERFS_PREALLOCATE
|
||||
reiserfs_discard_prealloc(&th, inode);
|
||||
#endif
|
||||
err = journal_end(&th);
|
||||
|
||||
/* copy back the error code from journal_begin */
|
||||
if (!err)
|
||||
err = jbegin_failure;
|
||||
|
||||
if (!err &&
|
||||
(REISERFS_I(inode)->i_flags & i_pack_on_close_mask) &&
|
||||
tail_has_to_be_packed(inode)) {
|
||||
|
||||
/*
|
||||
* if regular file is released by last holder and it has been
|
||||
* appended (we append by unformatted node only) or its direct
|
||||
* item(s) had to be converted, then it may have to be
|
||||
* indirect2direct converted
|
||||
*/
|
||||
err = reiserfs_truncate_file(inode, 0);
|
||||
}
|
||||
out:
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
mutex_unlock(&REISERFS_I(inode)->tailpack);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int reiserfs_file_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int err = dquot_file_open(inode, file);
|
||||
|
||||
/* somebody might be tailpacking on final close; wait for it */
|
||||
if (!atomic_inc_not_zero(&REISERFS_I(inode)->openers)) {
|
||||
mutex_lock(&REISERFS_I(inode)->tailpack);
|
||||
atomic_inc(&REISERFS_I(inode)->openers);
|
||||
mutex_unlock(&REISERFS_I(inode)->tailpack);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void reiserfs_vfs_truncate_file(struct inode *inode)
|
||||
{
|
||||
mutex_lock(&REISERFS_I(inode)->tailpack);
|
||||
reiserfs_truncate_file(inode, 1);
|
||||
mutex_unlock(&REISERFS_I(inode)->tailpack);
|
||||
}
|
||||
|
||||
/* Sync a reiserfs file. */
|
||||
|
||||
/*
|
||||
* FIXME: sync_mapping_buffers() never has anything to sync. Can
|
||||
* be removed...
|
||||
*/
|
||||
|
||||
static int reiserfs_sync_file(struct file *filp, loff_t start, loff_t end,
|
||||
int datasync)
|
||||
{
|
||||
struct inode *inode = filp->f_mapping->host;
|
||||
int err;
|
||||
int barrier_done;
|
||||
|
||||
err = file_write_and_wait_range(filp, start, end);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
inode_lock(inode);
|
||||
BUG_ON(!S_ISREG(inode->i_mode));
|
||||
err = sync_mapping_buffers(inode->i_mapping);
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
barrier_done = reiserfs_commit_for_inode(inode);
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
if (barrier_done != 1 && reiserfs_barrier_flush(inode->i_sb))
|
||||
blkdev_issue_flush(inode->i_sb->s_bdev);
|
||||
inode_unlock(inode);
|
||||
if (barrier_done < 0)
|
||||
return barrier_done;
|
||||
return (err < 0) ? -EIO : 0;
|
||||
}
|
||||
|
||||
/* taken fs/buffer.c:__block_commit_write */
|
||||
int reiserfs_commit_page(struct inode *inode, struct page *page,
|
||||
unsigned from, unsigned to)
|
||||
{
|
||||
unsigned block_start, block_end;
|
||||
int partial = 0;
|
||||
unsigned blocksize;
|
||||
struct buffer_head *bh, *head;
|
||||
unsigned long i_size_index = inode->i_size >> PAGE_SHIFT;
|
||||
int new;
|
||||
int logit = reiserfs_file_data_log(inode);
|
||||
struct super_block *s = inode->i_sb;
|
||||
int bh_per_page = PAGE_SIZE / s->s_blocksize;
|
||||
struct reiserfs_transaction_handle th;
|
||||
int ret = 0;
|
||||
|
||||
th.t_trans_id = 0;
|
||||
blocksize = i_blocksize(inode);
|
||||
|
||||
if (logit) {
|
||||
reiserfs_write_lock(s);
|
||||
ret = journal_begin(&th, s, bh_per_page + 1);
|
||||
if (ret)
|
||||
goto drop_write_lock;
|
||||
reiserfs_update_inode_transaction(inode);
|
||||
}
|
||||
for (bh = head = page_buffers(page), block_start = 0;
|
||||
bh != head || !block_start;
|
||||
block_start = block_end, bh = bh->b_this_page) {
|
||||
|
||||
new = buffer_new(bh);
|
||||
clear_buffer_new(bh);
|
||||
block_end = block_start + blocksize;
|
||||
if (block_end <= from || block_start >= to) {
|
||||
if (!buffer_uptodate(bh))
|
||||
partial = 1;
|
||||
} else {
|
||||
set_buffer_uptodate(bh);
|
||||
if (logit) {
|
||||
reiserfs_prepare_for_journal(s, bh, 1);
|
||||
journal_mark_dirty(&th, bh);
|
||||
} else if (!buffer_dirty(bh)) {
|
||||
mark_buffer_dirty(bh);
|
||||
/*
|
||||
* do data=ordered on any page past the end
|
||||
* of file and any buffer marked BH_New.
|
||||
*/
|
||||
if (reiserfs_data_ordered(inode->i_sb) &&
|
||||
(new || page->index >= i_size_index)) {
|
||||
reiserfs_add_ordered_list(inode, bh);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (logit) {
|
||||
ret = journal_end(&th);
|
||||
drop_write_lock:
|
||||
reiserfs_write_unlock(s);
|
||||
}
|
||||
/*
|
||||
* If this is a partial write which happened to make all buffers
|
||||
* uptodate then we can optimize away a bogus read_folio() for
|
||||
* the next read(). Here we 'discover' whether the page went
|
||||
* uptodate as a result of this (potentially partial) write.
|
||||
*/
|
||||
if (!partial)
|
||||
SetPageUptodate(page);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const struct file_operations reiserfs_file_operations = {
|
||||
.unlocked_ioctl = reiserfs_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = reiserfs_compat_ioctl,
|
||||
#endif
|
||||
.mmap = generic_file_mmap,
|
||||
.open = reiserfs_file_open,
|
||||
.release = reiserfs_file_release,
|
||||
.fsync = reiserfs_sync_file,
|
||||
.read_iter = generic_file_read_iter,
|
||||
.write_iter = generic_file_write_iter,
|
||||
.splice_read = filemap_splice_read,
|
||||
.splice_write = iter_file_splice_write,
|
||||
.llseek = generic_file_llseek,
|
||||
};
|
||||
|
||||
const struct inode_operations reiserfs_file_inode_operations = {
|
||||
.setattr = reiserfs_setattr,
|
||||
.listxattr = reiserfs_listxattr,
|
||||
.permission = reiserfs_permission,
|
||||
.get_inode_acl = reiserfs_get_acl,
|
||||
.set_acl = reiserfs_set_acl,
|
||||
.fileattr_get = reiserfs_fileattr_get,
|
||||
.fileattr_set = reiserfs_fileattr_set,
|
||||
};
|
||||
|
||||
const struct inode_operations reiserfs_priv_file_inode_operations = {
|
||||
.setattr = reiserfs_setattr,
|
||||
.permission = reiserfs_permission,
|
||||
.fileattr_get = reiserfs_fileattr_get,
|
||||
.fileattr_set = reiserfs_fileattr_set,
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -1,177 +0,0 @@
|
||||
|
||||
/*
|
||||
* Keyed 32-bit hash function using TEA in a Davis-Meyer function
|
||||
* H0 = Key
|
||||
* Hi = E Mi(Hi-1) + Hi-1
|
||||
*
|
||||
* (see Applied Cryptography, 2nd edition, p448).
|
||||
*
|
||||
* Jeremy Fitzhardinge <jeremy@zip.com.au> 1998
|
||||
*
|
||||
* Jeremy has agreed to the contents of reiserfs/README. -Hans
|
||||
* Yura's function is added (04/07/2000)
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include "reiserfs.h"
|
||||
#include <asm/types.h>
|
||||
|
||||
#define DELTA 0x9E3779B9
|
||||
#define FULLROUNDS 10 /* 32 is overkill, 16 is strong crypto */
|
||||
#define PARTROUNDS 6 /* 6 gets complete mixing */
|
||||
|
||||
/* a, b, c, d - data; h0, h1 - accumulated hash */
|
||||
#define TEACORE(rounds) \
|
||||
do { \
|
||||
u32 sum = 0; \
|
||||
int n = rounds; \
|
||||
u32 b0, b1; \
|
||||
\
|
||||
b0 = h0; \
|
||||
b1 = h1; \
|
||||
\
|
||||
do \
|
||||
{ \
|
||||
sum += DELTA; \
|
||||
b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); \
|
||||
b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); \
|
||||
} while(--n); \
|
||||
\
|
||||
h0 += b0; \
|
||||
h1 += b1; \
|
||||
} while(0)
|
||||
|
||||
u32 keyed_hash(const signed char *msg, int len)
|
||||
{
|
||||
u32 k[] = { 0x9464a485, 0x542e1a94, 0x3e846bff, 0xb75bcfc3 };
|
||||
|
||||
u32 h0 = k[0], h1 = k[1];
|
||||
u32 a, b, c, d;
|
||||
u32 pad;
|
||||
int i;
|
||||
|
||||
/* assert(len >= 0 && len < 256); */
|
||||
|
||||
pad = (u32) len | ((u32) len << 8);
|
||||
pad |= pad << 16;
|
||||
|
||||
while (len >= 16) {
|
||||
a = (u32) msg[0] |
|
||||
(u32) msg[1] << 8 | (u32) msg[2] << 16 | (u32) msg[3] << 24;
|
||||
b = (u32) msg[4] |
|
||||
(u32) msg[5] << 8 | (u32) msg[6] << 16 | (u32) msg[7] << 24;
|
||||
c = (u32) msg[8] |
|
||||
(u32) msg[9] << 8 |
|
||||
(u32) msg[10] << 16 | (u32) msg[11] << 24;
|
||||
d = (u32) msg[12] |
|
||||
(u32) msg[13] << 8 |
|
||||
(u32) msg[14] << 16 | (u32) msg[15] << 24;
|
||||
|
||||
TEACORE(PARTROUNDS);
|
||||
|
||||
len -= 16;
|
||||
msg += 16;
|
||||
}
|
||||
|
||||
if (len >= 12) {
|
||||
a = (u32) msg[0] |
|
||||
(u32) msg[1] << 8 | (u32) msg[2] << 16 | (u32) msg[3] << 24;
|
||||
b = (u32) msg[4] |
|
||||
(u32) msg[5] << 8 | (u32) msg[6] << 16 | (u32) msg[7] << 24;
|
||||
c = (u32) msg[8] |
|
||||
(u32) msg[9] << 8 |
|
||||
(u32) msg[10] << 16 | (u32) msg[11] << 24;
|
||||
|
||||
d = pad;
|
||||
for (i = 12; i < len; i++) {
|
||||
d <<= 8;
|
||||
d |= msg[i];
|
||||
}
|
||||
} else if (len >= 8) {
|
||||
a = (u32) msg[0] |
|
||||
(u32) msg[1] << 8 | (u32) msg[2] << 16 | (u32) msg[3] << 24;
|
||||
b = (u32) msg[4] |
|
||||
(u32) msg[5] << 8 | (u32) msg[6] << 16 | (u32) msg[7] << 24;
|
||||
|
||||
c = d = pad;
|
||||
for (i = 8; i < len; i++) {
|
||||
c <<= 8;
|
||||
c |= msg[i];
|
||||
}
|
||||
} else if (len >= 4) {
|
||||
a = (u32) msg[0] |
|
||||
(u32) msg[1] << 8 | (u32) msg[2] << 16 | (u32) msg[3] << 24;
|
||||
|
||||
b = c = d = pad;
|
||||
for (i = 4; i < len; i++) {
|
||||
b <<= 8;
|
||||
b |= msg[i];
|
||||
}
|
||||
} else {
|
||||
a = b = c = d = pad;
|
||||
for (i = 0; i < len; i++) {
|
||||
a <<= 8;
|
||||
a |= msg[i];
|
||||
}
|
||||
}
|
||||
|
||||
TEACORE(FULLROUNDS);
|
||||
|
||||
/* return 0;*/
|
||||
return h0 ^ h1;
|
||||
}
|
||||
|
||||
/*
|
||||
* What follows in this file is copyright 2000 by Hans Reiser, and the
|
||||
* licensing of what follows is governed by reiserfs/README
|
||||
*/
|
||||
u32 yura_hash(const signed char *msg, int len)
|
||||
{
|
||||
int j, pow;
|
||||
u32 a, c;
|
||||
int i;
|
||||
|
||||
for (pow = 1, i = 1; i < len; i++)
|
||||
pow = pow * 10;
|
||||
|
||||
if (len == 1)
|
||||
a = msg[0] - 48;
|
||||
else
|
||||
a = (msg[0] - 48) * pow;
|
||||
|
||||
for (i = 1; i < len; i++) {
|
||||
c = msg[i] - 48;
|
||||
for (pow = 1, j = i; j < len - 1; j++)
|
||||
pow = pow * 10;
|
||||
a = a + c * pow;
|
||||
}
|
||||
|
||||
for (; i < 40; i++) {
|
||||
c = '0' - 48;
|
||||
for (pow = 1, j = i; j < len - 1; j++)
|
||||
pow = pow * 10;
|
||||
a = a + c * pow;
|
||||
}
|
||||
|
||||
for (; i < 256; i++) {
|
||||
c = i;
|
||||
for (pow = 1, j = i; j < len - 1; j++)
|
||||
pow = pow * 10;
|
||||
a = a + c * pow;
|
||||
}
|
||||
|
||||
a = a << 7;
|
||||
return a;
|
||||
}
|
||||
|
||||
u32 r5_hash(const signed char *msg, int len)
|
||||
{
|
||||
u32 a = 0;
|
||||
while (*msg) {
|
||||
a += *msg << 4;
|
||||
a += *msg >> 4;
|
||||
a *= 11;
|
||||
msg++;
|
||||
}
|
||||
return a;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
3416
fs/reiserfs/inode.c
3416
fs/reiserfs/inode.c
File diff suppressed because it is too large
Load Diff
@ -1,221 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
|
||||
*/
|
||||
|
||||
#include <linux/capability.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mount.h>
|
||||
#include "reiserfs.h"
|
||||
#include <linux/time.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/fileattr.h>
|
||||
|
||||
int reiserfs_fileattr_get(struct dentry *dentry, struct fileattr *fa)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
|
||||
if (!reiserfs_attrs(inode->i_sb))
|
||||
return -ENOTTY;
|
||||
|
||||
fileattr_fill_flags(fa, REISERFS_I(inode)->i_attrs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int reiserfs_fileattr_set(struct mnt_idmap *idmap,
|
||||
struct dentry *dentry, struct fileattr *fa)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
unsigned int flags = fa->flags;
|
||||
int err;
|
||||
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
|
||||
err = -ENOTTY;
|
||||
if (!reiserfs_attrs(inode->i_sb))
|
||||
goto unlock;
|
||||
|
||||
err = -EOPNOTSUPP;
|
||||
if (fileattr_has_fsx(fa))
|
||||
goto unlock;
|
||||
|
||||
/*
|
||||
* Is it quota file? Do not allow user to mess with it
|
||||
*/
|
||||
err = -EPERM;
|
||||
if (IS_NOQUOTA(inode))
|
||||
goto unlock;
|
||||
|
||||
if ((flags & REISERFS_NOTAIL_FL) && S_ISREG(inode->i_mode)) {
|
||||
err = reiserfs_unpack(inode);
|
||||
if (err)
|
||||
goto unlock;
|
||||
}
|
||||
sd_attrs_to_i_attrs(flags, inode);
|
||||
REISERFS_I(inode)->i_attrs = flags;
|
||||
inode_set_ctime_current(inode);
|
||||
mark_inode_dirty(inode);
|
||||
err = 0;
|
||||
unlock:
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/*
|
||||
* reiserfs_ioctl - handler for ioctl for inode
|
||||
* supported commands:
|
||||
* 1) REISERFS_IOC_UNPACK - try to unpack tail from direct item into indirect
|
||||
* and prevent packing file (argument arg has t
|
||||
* be non-zero)
|
||||
* 2) REISERFS_IOC_[GS]ETFLAGS, REISERFS_IOC_[GS]ETVERSION
|
||||
* 3) That's all for a while ...
|
||||
*/
|
||||
long reiserfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct inode *inode = file_inode(filp);
|
||||
int err = 0;
|
||||
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
|
||||
switch (cmd) {
|
||||
case REISERFS_IOC_UNPACK:
|
||||
if (S_ISREG(inode->i_mode)) {
|
||||
if (arg)
|
||||
err = reiserfs_unpack(inode);
|
||||
} else
|
||||
err = -ENOTTY;
|
||||
break;
|
||||
/*
|
||||
* following two cases are taken from fs/ext2/ioctl.c by Remy
|
||||
* Card (card@masi.ibp.fr)
|
||||
*/
|
||||
case REISERFS_IOC_GETVERSION:
|
||||
err = put_user(inode->i_generation, (int __user *)arg);
|
||||
break;
|
||||
case REISERFS_IOC_SETVERSION:
|
||||
if (!inode_owner_or_capable(&nop_mnt_idmap, inode)) {
|
||||
err = -EPERM;
|
||||
break;
|
||||
}
|
||||
err = mnt_want_write_file(filp);
|
||||
if (err)
|
||||
break;
|
||||
if (get_user(inode->i_generation, (int __user *)arg)) {
|
||||
err = -EFAULT;
|
||||
goto setversion_out;
|
||||
}
|
||||
inode_set_ctime_current(inode);
|
||||
mark_inode_dirty(inode);
|
||||
setversion_out:
|
||||
mnt_drop_write_file(filp);
|
||||
break;
|
||||
default:
|
||||
err = -ENOTTY;
|
||||
}
|
||||
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
long reiserfs_compat_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
/*
|
||||
* These are just misnamed, they actually
|
||||
* get/put from/to user an int
|
||||
*/
|
||||
switch (cmd) {
|
||||
case REISERFS_IOC32_UNPACK:
|
||||
cmd = REISERFS_IOC_UNPACK;
|
||||
break;
|
||||
case REISERFS_IOC32_GETVERSION:
|
||||
cmd = REISERFS_IOC_GETVERSION;
|
||||
break;
|
||||
case REISERFS_IOC32_SETVERSION:
|
||||
cmd = REISERFS_IOC_SETVERSION;
|
||||
break;
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
||||
return reiserfs_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
|
||||
}
|
||||
#endif
|
||||
|
||||
int reiserfs_commit_write(struct file *f, struct page *page,
|
||||
unsigned from, unsigned to);
|
||||
/*
|
||||
* reiserfs_unpack
|
||||
* Function try to convert tail from direct item into indirect.
|
||||
* It set up nopack attribute in the REISERFS_I(inode)->nopack
|
||||
*/
|
||||
int reiserfs_unpack(struct inode *inode)
|
||||
{
|
||||
int retval = 0;
|
||||
int index;
|
||||
struct page *page;
|
||||
struct address_space *mapping;
|
||||
unsigned long write_from;
|
||||
unsigned long blocksize = inode->i_sb->s_blocksize;
|
||||
|
||||
if (inode->i_size == 0) {
|
||||
REISERFS_I(inode)->i_flags |= i_nopack_mask;
|
||||
return 0;
|
||||
}
|
||||
/* ioctl already done */
|
||||
if (REISERFS_I(inode)->i_flags & i_nopack_mask) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* we need to make sure nobody is changing the file size beneath us */
|
||||
{
|
||||
int depth = reiserfs_write_unlock_nested(inode->i_sb);
|
||||
|
||||
inode_lock(inode);
|
||||
reiserfs_write_lock_nested(inode->i_sb, depth);
|
||||
}
|
||||
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
|
||||
write_from = inode->i_size & (blocksize - 1);
|
||||
/* if we are on a block boundary, we are already unpacked. */
|
||||
if (write_from == 0) {
|
||||
REISERFS_I(inode)->i_flags |= i_nopack_mask;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* we unpack by finding the page with the tail, and calling
|
||||
* __reiserfs_write_begin on that page. This will force a
|
||||
* reiserfs_get_block to unpack the tail for us.
|
||||
*/
|
||||
index = inode->i_size >> PAGE_SHIFT;
|
||||
mapping = inode->i_mapping;
|
||||
page = grab_cache_page(mapping, index);
|
||||
retval = -ENOMEM;
|
||||
if (!page) {
|
||||
goto out;
|
||||
}
|
||||
retval = __reiserfs_write_begin(page, write_from, 0);
|
||||
if (retval)
|
||||
goto out_unlock;
|
||||
|
||||
/* conversion can change page contents, must flush */
|
||||
flush_dcache_page(page);
|
||||
retval = reiserfs_commit_write(NULL, page, write_from, write_from);
|
||||
REISERFS_I(inode)->i_flags |= i_nopack_mask;
|
||||
|
||||
out_unlock:
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
|
||||
out:
|
||||
inode_unlock(inode);
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
return retval;
|
||||
}
|
@ -1,737 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
|
||||
*/
|
||||
|
||||
#include <linux/time.h>
|
||||
#include "reiserfs.h"
|
||||
|
||||
/*
|
||||
* this contains item handlers for old item types: sd, direct,
|
||||
* indirect, directory
|
||||
*/
|
||||
|
||||
/*
|
||||
* and where are the comments? how about saying where we can find an
|
||||
* explanation of each item handler method? -Hans
|
||||
*/
|
||||
|
||||
/* stat data functions */
|
||||
static int sd_bytes_number(struct item_head *ih, int block_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sd_decrement_key(struct cpu_key *key)
|
||||
{
|
||||
key->on_disk_key.k_objectid--;
|
||||
set_cpu_key_k_type(key, TYPE_ANY);
|
||||
set_cpu_key_k_offset(key, (loff_t)(~0ULL >> 1));
|
||||
}
|
||||
|
||||
static int sd_is_left_mergeable(struct reiserfs_key *key, unsigned long bsize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sd_print_item(struct item_head *ih, char *item)
|
||||
{
|
||||
printk("\tmode | size | nlinks | first direct | mtime\n");
|
||||
if (stat_data_v1(ih)) {
|
||||
struct stat_data_v1 *sd = (struct stat_data_v1 *)item;
|
||||
|
||||
printk("\t0%-6o | %6u | %2u | %d | %u\n", sd_v1_mode(sd),
|
||||
sd_v1_size(sd), sd_v1_nlink(sd),
|
||||
sd_v1_first_direct_byte(sd),
|
||||
sd_v1_mtime(sd));
|
||||
} else {
|
||||
struct stat_data *sd = (struct stat_data *)item;
|
||||
|
||||
printk("\t0%-6o | %6llu | %2u | %d | %u\n", sd_v2_mode(sd),
|
||||
(unsigned long long)sd_v2_size(sd), sd_v2_nlink(sd),
|
||||
sd_v2_rdev(sd), sd_v2_mtime(sd));
|
||||
}
|
||||
}
|
||||
|
||||
static void sd_check_item(struct item_head *ih, char *item)
|
||||
{
|
||||
/* unused */
|
||||
}
|
||||
|
||||
static int sd_create_vi(struct virtual_node *vn,
|
||||
struct virtual_item *vi,
|
||||
int is_affected, int insert_size)
|
||||
{
|
||||
vi->vi_index = TYPE_STAT_DATA;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_check_left(struct virtual_item *vi, int free,
|
||||
int start_skip, int end_skip)
|
||||
{
|
||||
BUG_ON(start_skip || end_skip);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int sd_check_right(struct virtual_item *vi, int free)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int sd_part_size(struct virtual_item *vi, int first, int count)
|
||||
{
|
||||
BUG_ON(count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_unit_num(struct virtual_item *vi)
|
||||
{
|
||||
return vi->vi_item_len - IH_SIZE;
|
||||
}
|
||||
|
||||
static void sd_print_vi(struct virtual_item *vi)
|
||||
{
|
||||
reiserfs_warning(NULL, "reiserfs-16100",
|
||||
"STATDATA, index %d, type 0x%x, %h",
|
||||
vi->vi_index, vi->vi_type, vi->vi_ih);
|
||||
}
|
||||
|
||||
static struct item_operations stat_data_ops = {
|
||||
.bytes_number = sd_bytes_number,
|
||||
.decrement_key = sd_decrement_key,
|
||||
.is_left_mergeable = sd_is_left_mergeable,
|
||||
.print_item = sd_print_item,
|
||||
.check_item = sd_check_item,
|
||||
|
||||
.create_vi = sd_create_vi,
|
||||
.check_left = sd_check_left,
|
||||
.check_right = sd_check_right,
|
||||
.part_size = sd_part_size,
|
||||
.unit_num = sd_unit_num,
|
||||
.print_vi = sd_print_vi
|
||||
};
|
||||
|
||||
/* direct item functions */
|
||||
static int direct_bytes_number(struct item_head *ih, int block_size)
|
||||
{
|
||||
return ih_item_len(ih);
|
||||
}
|
||||
|
||||
/* FIXME: this should probably switch to indirect as well */
|
||||
static void direct_decrement_key(struct cpu_key *key)
|
||||
{
|
||||
cpu_key_k_offset_dec(key);
|
||||
if (cpu_key_k_offset(key) == 0)
|
||||
set_cpu_key_k_type(key, TYPE_STAT_DATA);
|
||||
}
|
||||
|
||||
static int direct_is_left_mergeable(struct reiserfs_key *key,
|
||||
unsigned long bsize)
|
||||
{
|
||||
int version = le_key_version(key);
|
||||
return ((le_key_k_offset(version, key) & (bsize - 1)) != 1);
|
||||
}
|
||||
|
||||
static void direct_print_item(struct item_head *ih, char *item)
|
||||
{
|
||||
int j = 0;
|
||||
|
||||
/* return; */
|
||||
printk("\"");
|
||||
while (j < ih_item_len(ih))
|
||||
printk("%c", item[j++]);
|
||||
printk("\"\n");
|
||||
}
|
||||
|
||||
static void direct_check_item(struct item_head *ih, char *item)
|
||||
{
|
||||
/* unused */
|
||||
}
|
||||
|
||||
static int direct_create_vi(struct virtual_node *vn,
|
||||
struct virtual_item *vi,
|
||||
int is_affected, int insert_size)
|
||||
{
|
||||
vi->vi_index = TYPE_DIRECT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int direct_check_left(struct virtual_item *vi, int free,
|
||||
int start_skip, int end_skip)
|
||||
{
|
||||
int bytes;
|
||||
|
||||
bytes = free - free % 8;
|
||||
return bytes ? : -1;
|
||||
}
|
||||
|
||||
static int direct_check_right(struct virtual_item *vi, int free)
|
||||
{
|
||||
return direct_check_left(vi, free, 0, 0);
|
||||
}
|
||||
|
||||
static int direct_part_size(struct virtual_item *vi, int first, int count)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
static int direct_unit_num(struct virtual_item *vi)
|
||||
{
|
||||
return vi->vi_item_len - IH_SIZE;
|
||||
}
|
||||
|
||||
static void direct_print_vi(struct virtual_item *vi)
|
||||
{
|
||||
reiserfs_warning(NULL, "reiserfs-16101",
|
||||
"DIRECT, index %d, type 0x%x, %h",
|
||||
vi->vi_index, vi->vi_type, vi->vi_ih);
|
||||
}
|
||||
|
||||
static struct item_operations direct_ops = {
|
||||
.bytes_number = direct_bytes_number,
|
||||
.decrement_key = direct_decrement_key,
|
||||
.is_left_mergeable = direct_is_left_mergeable,
|
||||
.print_item = direct_print_item,
|
||||
.check_item = direct_check_item,
|
||||
|
||||
.create_vi = direct_create_vi,
|
||||
.check_left = direct_check_left,
|
||||
.check_right = direct_check_right,
|
||||
.part_size = direct_part_size,
|
||||
.unit_num = direct_unit_num,
|
||||
.print_vi = direct_print_vi
|
||||
};
|
||||
|
||||
/* indirect item functions */
|
||||
static int indirect_bytes_number(struct item_head *ih, int block_size)
|
||||
{
|
||||
return ih_item_len(ih) / UNFM_P_SIZE * block_size;
|
||||
}
|
||||
|
||||
/* decrease offset, if it becomes 0, change type to stat data */
|
||||
static void indirect_decrement_key(struct cpu_key *key)
|
||||
{
|
||||
cpu_key_k_offset_dec(key);
|
||||
if (cpu_key_k_offset(key) == 0)
|
||||
set_cpu_key_k_type(key, TYPE_STAT_DATA);
|
||||
}
|
||||
|
||||
/* if it is not first item of the body, then it is mergeable */
|
||||
static int indirect_is_left_mergeable(struct reiserfs_key *key,
|
||||
unsigned long bsize)
|
||||
{
|
||||
int version = le_key_version(key);
|
||||
return (le_key_k_offset(version, key) != 1);
|
||||
}
|
||||
|
||||
/* printing of indirect item */
|
||||
static void start_new_sequence(__u32 * start, int *len, __u32 new)
|
||||
{
|
||||
*start = new;
|
||||
*len = 1;
|
||||
}
|
||||
|
||||
static int sequence_finished(__u32 start, int *len, __u32 new)
|
||||
{
|
||||
if (start == INT_MAX)
|
||||
return 1;
|
||||
|
||||
if (start == 0 && new == 0) {
|
||||
(*len)++;
|
||||
return 0;
|
||||
}
|
||||
if (start != 0 && (start + *len) == new) {
|
||||
(*len)++;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void print_sequence(__u32 start, int len)
|
||||
{
|
||||
if (start == INT_MAX)
|
||||
return;
|
||||
|
||||
if (len == 1)
|
||||
printk(" %d", start);
|
||||
else
|
||||
printk(" %d(%d)", start, len);
|
||||
}
|
||||
|
||||
static void indirect_print_item(struct item_head *ih, char *item)
|
||||
{
|
||||
int j;
|
||||
__le32 *unp;
|
||||
__u32 prev = INT_MAX;
|
||||
int num = 0;
|
||||
|
||||
unp = (__le32 *) item;
|
||||
|
||||
if (ih_item_len(ih) % UNFM_P_SIZE)
|
||||
reiserfs_warning(NULL, "reiserfs-16102", "invalid item len");
|
||||
|
||||
printk("%d pointers\n[ ", (int)I_UNFM_NUM(ih));
|
||||
for (j = 0; j < I_UNFM_NUM(ih); j++) {
|
||||
if (sequence_finished(prev, &num, get_block_num(unp, j))) {
|
||||
print_sequence(prev, num);
|
||||
start_new_sequence(&prev, &num, get_block_num(unp, j));
|
||||
}
|
||||
}
|
||||
print_sequence(prev, num);
|
||||
printk("]\n");
|
||||
}
|
||||
|
||||
static void indirect_check_item(struct item_head *ih, char *item)
|
||||
{
|
||||
/* unused */
|
||||
}
|
||||
|
||||
static int indirect_create_vi(struct virtual_node *vn,
|
||||
struct virtual_item *vi,
|
||||
int is_affected, int insert_size)
|
||||
{
|
||||
vi->vi_index = TYPE_INDIRECT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int indirect_check_left(struct virtual_item *vi, int free,
|
||||
int start_skip, int end_skip)
|
||||
{
|
||||
int bytes;
|
||||
|
||||
bytes = free - free % UNFM_P_SIZE;
|
||||
return bytes ? : -1;
|
||||
}
|
||||
|
||||
static int indirect_check_right(struct virtual_item *vi, int free)
|
||||
{
|
||||
return indirect_check_left(vi, free, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* return size in bytes of 'units' units. If first == 0 - calculate
|
||||
* from the head (left), otherwise - from tail (right)
|
||||
*/
|
||||
static int indirect_part_size(struct virtual_item *vi, int first, int units)
|
||||
{
|
||||
/* unit of indirect item is byte (yet) */
|
||||
return units;
|
||||
}
|
||||
|
||||
static int indirect_unit_num(struct virtual_item *vi)
|
||||
{
|
||||
/* unit of indirect item is byte (yet) */
|
||||
return vi->vi_item_len - IH_SIZE;
|
||||
}
|
||||
|
||||
static void indirect_print_vi(struct virtual_item *vi)
|
||||
{
|
||||
reiserfs_warning(NULL, "reiserfs-16103",
|
||||
"INDIRECT, index %d, type 0x%x, %h",
|
||||
vi->vi_index, vi->vi_type, vi->vi_ih);
|
||||
}
|
||||
|
||||
static struct item_operations indirect_ops = {
|
||||
.bytes_number = indirect_bytes_number,
|
||||
.decrement_key = indirect_decrement_key,
|
||||
.is_left_mergeable = indirect_is_left_mergeable,
|
||||
.print_item = indirect_print_item,
|
||||
.check_item = indirect_check_item,
|
||||
|
||||
.create_vi = indirect_create_vi,
|
||||
.check_left = indirect_check_left,
|
||||
.check_right = indirect_check_right,
|
||||
.part_size = indirect_part_size,
|
||||
.unit_num = indirect_unit_num,
|
||||
.print_vi = indirect_print_vi
|
||||
};
|
||||
|
||||
/* direntry functions */
|
||||
static int direntry_bytes_number(struct item_head *ih, int block_size)
|
||||
{
|
||||
reiserfs_warning(NULL, "vs-16090",
|
||||
"bytes number is asked for direntry");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void direntry_decrement_key(struct cpu_key *key)
|
||||
{
|
||||
cpu_key_k_offset_dec(key);
|
||||
if (cpu_key_k_offset(key) == 0)
|
||||
set_cpu_key_k_type(key, TYPE_STAT_DATA);
|
||||
}
|
||||
|
||||
static int direntry_is_left_mergeable(struct reiserfs_key *key,
|
||||
unsigned long bsize)
|
||||
{
|
||||
if (le32_to_cpu(key->u.k_offset_v1.k_offset) == DOT_OFFSET)
|
||||
return 0;
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
static void direntry_print_item(struct item_head *ih, char *item)
|
||||
{
|
||||
int i;
|
||||
int namelen;
|
||||
struct reiserfs_de_head *deh;
|
||||
char *name;
|
||||
static char namebuf[80];
|
||||
|
||||
printk("\n # %-15s%-30s%-15s%-15s%-15s\n", "Name",
|
||||
"Key of pointed object", "Hash", "Gen number", "Status");
|
||||
|
||||
deh = (struct reiserfs_de_head *)item;
|
||||
|
||||
for (i = 0; i < ih_entry_count(ih); i++, deh++) {
|
||||
namelen =
|
||||
(i ? (deh_location(deh - 1)) : ih_item_len(ih)) -
|
||||
deh_location(deh);
|
||||
name = item + deh_location(deh);
|
||||
if (name[namelen - 1] == 0)
|
||||
namelen = strlen(name);
|
||||
|
||||
scnprintf(namebuf, sizeof(namebuf), "\"%.*s\"",
|
||||
(int)sizeof(namebuf)-3, name);
|
||||
|
||||
printk("%d: %-15s%-15d%-15d%-15lld%-15lld(%s)\n",
|
||||
i, namebuf,
|
||||
deh_dir_id(deh), deh_objectid(deh),
|
||||
GET_HASH_VALUE(deh_offset(deh)),
|
||||
GET_GENERATION_NUMBER((deh_offset(deh))),
|
||||
(de_hidden(deh)) ? "HIDDEN" : "VISIBLE");
|
||||
}
|
||||
}
|
||||
|
||||
static void direntry_check_item(struct item_head *ih, char *item)
|
||||
{
|
||||
int i;
|
||||
struct reiserfs_de_head *deh;
|
||||
|
||||
/* unused */
|
||||
deh = (struct reiserfs_de_head *)item;
|
||||
for (i = 0; i < ih_entry_count(ih); i++, deh++) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
#define DIRENTRY_VI_FIRST_DIRENTRY_ITEM 1
|
||||
|
||||
/*
|
||||
* function returns old entry number in directory item in real node
|
||||
* using new entry number in virtual item in virtual node
|
||||
*/
|
||||
static inline int old_entry_num(int is_affected, int virtual_entry_num,
|
||||
int pos_in_item, int mode)
|
||||
{
|
||||
if (mode == M_INSERT || mode == M_DELETE)
|
||||
return virtual_entry_num;
|
||||
|
||||
if (!is_affected)
|
||||
/* cut or paste is applied to another item */
|
||||
return virtual_entry_num;
|
||||
|
||||
if (virtual_entry_num < pos_in_item)
|
||||
return virtual_entry_num;
|
||||
|
||||
if (mode == M_CUT)
|
||||
return virtual_entry_num + 1;
|
||||
|
||||
RFALSE(mode != M_PASTE || virtual_entry_num == 0,
|
||||
"vs-8015: old_entry_num: mode must be M_PASTE (mode = \'%c\'",
|
||||
mode);
|
||||
|
||||
return virtual_entry_num - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create an array of sizes of directory entries for virtual
|
||||
* item. Return space used by an item. FIXME: no control over
|
||||
* consuming of space used by this item handler
|
||||
*/
|
||||
static int direntry_create_vi(struct virtual_node *vn,
|
||||
struct virtual_item *vi,
|
||||
int is_affected, int insert_size)
|
||||
{
|
||||
struct direntry_uarea *dir_u = vi->vi_uarea;
|
||||
int i, j;
|
||||
int size = sizeof(struct direntry_uarea);
|
||||
struct reiserfs_de_head *deh;
|
||||
|
||||
vi->vi_index = TYPE_DIRENTRY;
|
||||
|
||||
BUG_ON(!(vi->vi_ih) || !vi->vi_item);
|
||||
|
||||
dir_u->flags = 0;
|
||||
if (le_ih_k_offset(vi->vi_ih) == DOT_OFFSET)
|
||||
dir_u->flags |= DIRENTRY_VI_FIRST_DIRENTRY_ITEM;
|
||||
|
||||
deh = (struct reiserfs_de_head *)(vi->vi_item);
|
||||
|
||||
/* virtual directory item have this amount of entry after */
|
||||
dir_u->entry_count = ih_entry_count(vi->vi_ih) +
|
||||
((is_affected) ? ((vn->vn_mode == M_CUT) ? -1 :
|
||||
(vn->vn_mode == M_PASTE ? 1 : 0)) : 0);
|
||||
|
||||
for (i = 0; i < dir_u->entry_count; i++) {
|
||||
j = old_entry_num(is_affected, i, vn->vn_pos_in_item,
|
||||
vn->vn_mode);
|
||||
dir_u->entry_sizes[i] =
|
||||
(j ? deh_location(&deh[j - 1]) : ih_item_len(vi->vi_ih)) -
|
||||
deh_location(&deh[j]) + DEH_SIZE;
|
||||
}
|
||||
|
||||
size += (dir_u->entry_count * sizeof(short));
|
||||
|
||||
/* set size of pasted entry */
|
||||
if (is_affected && vn->vn_mode == M_PASTE)
|
||||
dir_u->entry_sizes[vn->vn_pos_in_item] = insert_size;
|
||||
|
||||
#ifdef CONFIG_REISERFS_CHECK
|
||||
/* compare total size of entries with item length */
|
||||
{
|
||||
int k, l;
|
||||
|
||||
l = 0;
|
||||
for (k = 0; k < dir_u->entry_count; k++)
|
||||
l += dir_u->entry_sizes[k];
|
||||
|
||||
if (l + IH_SIZE != vi->vi_item_len +
|
||||
((is_affected
|
||||
&& (vn->vn_mode == M_PASTE
|
||||
|| vn->vn_mode == M_CUT)) ? insert_size : 0)) {
|
||||
reiserfs_panic(NULL, "vs-8025", "(mode==%c, "
|
||||
"insert_size==%d), invalid length of "
|
||||
"directory item",
|
||||
vn->vn_mode, insert_size);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return size;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* return number of entries which may fit into specified amount of
|
||||
* free space, or -1 if free space is not enough even for 1 entry
|
||||
*/
|
||||
static int direntry_check_left(struct virtual_item *vi, int free,
|
||||
int start_skip, int end_skip)
|
||||
{
|
||||
int i;
|
||||
int entries = 0;
|
||||
struct direntry_uarea *dir_u = vi->vi_uarea;
|
||||
|
||||
for (i = start_skip; i < dir_u->entry_count - end_skip; i++) {
|
||||
/* i-th entry doesn't fit into the remaining free space */
|
||||
if (dir_u->entry_sizes[i] > free)
|
||||
break;
|
||||
|
||||
free -= dir_u->entry_sizes[i];
|
||||
entries++;
|
||||
}
|
||||
|
||||
if (entries == dir_u->entry_count) {
|
||||
reiserfs_panic(NULL, "item_ops-1",
|
||||
"free space %d, entry_count %d", free,
|
||||
dir_u->entry_count);
|
||||
}
|
||||
|
||||
/* "." and ".." can not be separated from each other */
|
||||
if (start_skip == 0 && (dir_u->flags & DIRENTRY_VI_FIRST_DIRENTRY_ITEM)
|
||||
&& entries < 2)
|
||||
entries = 0;
|
||||
|
||||
return entries ? : -1;
|
||||
}
|
||||
|
||||
static int direntry_check_right(struct virtual_item *vi, int free)
|
||||
{
|
||||
int i;
|
||||
int entries = 0;
|
||||
struct direntry_uarea *dir_u = vi->vi_uarea;
|
||||
|
||||
for (i = dir_u->entry_count - 1; i >= 0; i--) {
|
||||
/* i-th entry doesn't fit into the remaining free space */
|
||||
if (dir_u->entry_sizes[i] > free)
|
||||
break;
|
||||
|
||||
free -= dir_u->entry_sizes[i];
|
||||
entries++;
|
||||
}
|
||||
BUG_ON(entries == dir_u->entry_count);
|
||||
|
||||
/* "." and ".." can not be separated from each other */
|
||||
if ((dir_u->flags & DIRENTRY_VI_FIRST_DIRENTRY_ITEM)
|
||||
&& entries > dir_u->entry_count - 2)
|
||||
entries = dir_u->entry_count - 2;
|
||||
|
||||
return entries ? : -1;
|
||||
}
|
||||
|
||||
/* sum of entry sizes between from-th and to-th entries including both edges */
|
||||
static int direntry_part_size(struct virtual_item *vi, int first, int count)
|
||||
{
|
||||
int i, retval;
|
||||
int from, to;
|
||||
struct direntry_uarea *dir_u = vi->vi_uarea;
|
||||
|
||||
retval = 0;
|
||||
if (first == 0)
|
||||
from = 0;
|
||||
else
|
||||
from = dir_u->entry_count - count;
|
||||
to = from + count - 1;
|
||||
|
||||
for (i = from; i <= to; i++)
|
||||
retval += dir_u->entry_sizes[i];
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int direntry_unit_num(struct virtual_item *vi)
|
||||
{
|
||||
struct direntry_uarea *dir_u = vi->vi_uarea;
|
||||
|
||||
return dir_u->entry_count;
|
||||
}
|
||||
|
||||
static void direntry_print_vi(struct virtual_item *vi)
|
||||
{
|
||||
int i;
|
||||
struct direntry_uarea *dir_u = vi->vi_uarea;
|
||||
|
||||
reiserfs_warning(NULL, "reiserfs-16104",
|
||||
"DIRENTRY, index %d, type 0x%x, %h, flags 0x%x",
|
||||
vi->vi_index, vi->vi_type, vi->vi_ih, dir_u->flags);
|
||||
printk("%d entries: ", dir_u->entry_count);
|
||||
for (i = 0; i < dir_u->entry_count; i++)
|
||||
printk("%d ", dir_u->entry_sizes[i]);
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
static struct item_operations direntry_ops = {
|
||||
.bytes_number = direntry_bytes_number,
|
||||
.decrement_key = direntry_decrement_key,
|
||||
.is_left_mergeable = direntry_is_left_mergeable,
|
||||
.print_item = direntry_print_item,
|
||||
.check_item = direntry_check_item,
|
||||
|
||||
.create_vi = direntry_create_vi,
|
||||
.check_left = direntry_check_left,
|
||||
.check_right = direntry_check_right,
|
||||
.part_size = direntry_part_size,
|
||||
.unit_num = direntry_unit_num,
|
||||
.print_vi = direntry_print_vi
|
||||
};
|
||||
|
||||
/* Error catching functions to catch errors caused by incorrect item types. */
|
||||
static int errcatch_bytes_number(struct item_head *ih, int block_size)
|
||||
{
|
||||
reiserfs_warning(NULL, "green-16001",
|
||||
"Invalid item type observed, run fsck ASAP");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void errcatch_decrement_key(struct cpu_key *key)
|
||||
{
|
||||
reiserfs_warning(NULL, "green-16002",
|
||||
"Invalid item type observed, run fsck ASAP");
|
||||
}
|
||||
|
||||
static int errcatch_is_left_mergeable(struct reiserfs_key *key,
|
||||
unsigned long bsize)
|
||||
{
|
||||
reiserfs_warning(NULL, "green-16003",
|
||||
"Invalid item type observed, run fsck ASAP");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void errcatch_print_item(struct item_head *ih, char *item)
|
||||
{
|
||||
reiserfs_warning(NULL, "green-16004",
|
||||
"Invalid item type observed, run fsck ASAP");
|
||||
}
|
||||
|
||||
static void errcatch_check_item(struct item_head *ih, char *item)
|
||||
{
|
||||
reiserfs_warning(NULL, "green-16005",
|
||||
"Invalid item type observed, run fsck ASAP");
|
||||
}
|
||||
|
||||
static int errcatch_create_vi(struct virtual_node *vn,
|
||||
struct virtual_item *vi,
|
||||
int is_affected, int insert_size)
|
||||
{
|
||||
reiserfs_warning(NULL, "green-16006",
|
||||
"Invalid item type observed, run fsck ASAP");
|
||||
/*
|
||||
* We might return -1 here as well, but it won't help as
|
||||
* create_virtual_node() from where this operation is called
|
||||
* from is of return type void.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int errcatch_check_left(struct virtual_item *vi, int free,
|
||||
int start_skip, int end_skip)
|
||||
{
|
||||
reiserfs_warning(NULL, "green-16007",
|
||||
"Invalid item type observed, run fsck ASAP");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int errcatch_check_right(struct virtual_item *vi, int free)
|
||||
{
|
||||
reiserfs_warning(NULL, "green-16008",
|
||||
"Invalid item type observed, run fsck ASAP");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int errcatch_part_size(struct virtual_item *vi, int first, int count)
|
||||
{
|
||||
reiserfs_warning(NULL, "green-16009",
|
||||
"Invalid item type observed, run fsck ASAP");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int errcatch_unit_num(struct virtual_item *vi)
|
||||
{
|
||||
reiserfs_warning(NULL, "green-16010",
|
||||
"Invalid item type observed, run fsck ASAP");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void errcatch_print_vi(struct virtual_item *vi)
|
||||
{
|
||||
reiserfs_warning(NULL, "green-16011",
|
||||
"Invalid item type observed, run fsck ASAP");
|
||||
}
|
||||
|
||||
static struct item_operations errcatch_ops = {
|
||||
.bytes_number = errcatch_bytes_number,
|
||||
.decrement_key = errcatch_decrement_key,
|
||||
.is_left_mergeable = errcatch_is_left_mergeable,
|
||||
.print_item = errcatch_print_item,
|
||||
.check_item = errcatch_check_item,
|
||||
|
||||
.create_vi = errcatch_create_vi,
|
||||
.check_left = errcatch_check_left,
|
||||
.check_right = errcatch_check_right,
|
||||
.part_size = errcatch_part_size,
|
||||
.unit_num = errcatch_unit_num,
|
||||
.print_vi = errcatch_print_vi
|
||||
};
|
||||
|
||||
#if ! (TYPE_STAT_DATA == 0 && TYPE_INDIRECT == 1 && TYPE_DIRECT == 2 && TYPE_DIRENTRY == 3)
|
||||
#error Item types must use disk-format assigned values.
|
||||
#endif
|
||||
|
||||
struct item_operations *item_ops[TYPE_ANY + 1] = {
|
||||
&stat_data_ops,
|
||||
&indirect_ops,
|
||||
&direct_ops,
|
||||
&direntry_ops,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
&errcatch_ops /* This is to catch errors with invalid type (15th entry for TYPE_ANY) */
|
||||
};
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,101 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "reiserfs.h"
|
||||
#include <linux/mutex.h>
|
||||
|
||||
/*
|
||||
* The previous reiserfs locking scheme was heavily based on
|
||||
* the tricky properties of the Bkl:
|
||||
*
|
||||
* - it was acquired recursively by a same task
|
||||
* - the performances relied on the release-while-schedule() property
|
||||
*
|
||||
* Now that we replace it by a mutex, we still want to keep the same
|
||||
* recursive property to avoid big changes in the code structure.
|
||||
* We use our own lock_owner here because the owner field on a mutex
|
||||
* is only available in SMP or mutex debugging, also we only need this field
|
||||
* for this mutex, no need for a system wide mutex facility.
|
||||
*
|
||||
* Also this lock is often released before a call that could block because
|
||||
* reiserfs performances were partially based on the release while schedule()
|
||||
* property of the Bkl.
|
||||
*/
|
||||
void reiserfs_write_lock(struct super_block *s)
|
||||
{
|
||||
struct reiserfs_sb_info *sb_i = REISERFS_SB(s);
|
||||
|
||||
if (sb_i->lock_owner != current) {
|
||||
mutex_lock(&sb_i->lock);
|
||||
sb_i->lock_owner = current;
|
||||
}
|
||||
|
||||
/* No need to protect it, only the current task touches it */
|
||||
sb_i->lock_depth++;
|
||||
}
|
||||
|
||||
void reiserfs_write_unlock(struct super_block *s)
|
||||
{
|
||||
struct reiserfs_sb_info *sb_i = REISERFS_SB(s);
|
||||
|
||||
/*
|
||||
* Are we unlocking without even holding the lock?
|
||||
* Such a situation must raise a BUG() if we don't want
|
||||
* to corrupt the data.
|
||||
*/
|
||||
BUG_ON(sb_i->lock_owner != current);
|
||||
|
||||
if (--sb_i->lock_depth == -1) {
|
||||
sb_i->lock_owner = NULL;
|
||||
mutex_unlock(&sb_i->lock);
|
||||
}
|
||||
}
|
||||
|
||||
int __must_check reiserfs_write_unlock_nested(struct super_block *s)
|
||||
{
|
||||
struct reiserfs_sb_info *sb_i = REISERFS_SB(s);
|
||||
int depth;
|
||||
|
||||
/* this can happen when the lock isn't always held */
|
||||
if (sb_i->lock_owner != current)
|
||||
return -1;
|
||||
|
||||
depth = sb_i->lock_depth;
|
||||
|
||||
sb_i->lock_depth = -1;
|
||||
sb_i->lock_owner = NULL;
|
||||
mutex_unlock(&sb_i->lock);
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
void reiserfs_write_lock_nested(struct super_block *s, int depth)
|
||||
{
|
||||
struct reiserfs_sb_info *sb_i = REISERFS_SB(s);
|
||||
|
||||
/* this can happen when the lock isn't always held */
|
||||
if (depth == -1)
|
||||
return;
|
||||
|
||||
mutex_lock(&sb_i->lock);
|
||||
sb_i->lock_owner = current;
|
||||
sb_i->lock_depth = depth;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility function to force a BUG if it is called without the superblock
|
||||
* write lock held. caller is the string printed just before calling BUG()
|
||||
*/
|
||||
void reiserfs_check_lock_depth(struct super_block *sb, char *caller)
|
||||
{
|
||||
struct reiserfs_sb_info *sb_i = REISERFS_SB(sb);
|
||||
|
||||
WARN_ON(sb_i->lock_depth < 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_REISERFS_CHECK
|
||||
void reiserfs_lock_check_recursive(struct super_block *sb)
|
||||
{
|
||||
struct reiserfs_sb_info *sb_i = REISERFS_SB(sb);
|
||||
|
||||
WARN_ONCE((sb_i->lock_depth > 0), "Unwanted recursive reiserfs lock!\n");
|
||||
}
|
||||
#endif
|
1725
fs/reiserfs/namei.c
1725
fs/reiserfs/namei.c
File diff suppressed because it is too large
Load Diff
@ -1,216 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
|
||||
*/
|
||||
|
||||
#include <linux/string.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/uuid.h>
|
||||
#include "reiserfs.h"
|
||||
|
||||
/* find where objectid map starts */
|
||||
#define objectid_map(s,rs) (old_format_only (s) ? \
|
||||
(__le32 *)((struct reiserfs_super_block_v1 *)(rs) + 1) :\
|
||||
(__le32 *)((rs) + 1))
|
||||
|
||||
#ifdef CONFIG_REISERFS_CHECK
|
||||
|
||||
static void check_objectid_map(struct super_block *s, __le32 * map)
|
||||
{
|
||||
if (le32_to_cpu(map[0]) != 1)
|
||||
reiserfs_panic(s, "vs-15010", "map corrupted: %lx",
|
||||
(long unsigned int)le32_to_cpu(map[0]));
|
||||
|
||||
/* FIXME: add something else here */
|
||||
}
|
||||
|
||||
#else
|
||||
static void check_objectid_map(struct super_block *s, __le32 * map)
|
||||
{;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* When we allocate objectids we allocate the first unused objectid.
|
||||
* Each sequence of objectids in use (the odd sequences) is followed
|
||||
* by a sequence of objectids not in use (the even sequences). We
|
||||
* only need to record the last objectid in each of these sequences
|
||||
* (both the odd and even sequences) in order to fully define the
|
||||
* boundaries of the sequences. A consequence of allocating the first
|
||||
* objectid not in use is that under most conditions this scheme is
|
||||
* extremely compact. The exception is immediately after a sequence
|
||||
* of operations which deletes a large number of objects of
|
||||
* non-sequential objectids, and even then it will become compact
|
||||
* again as soon as more objects are created. Note that many
|
||||
* interesting optimizations of layout could result from complicating
|
||||
* objectid assignment, but we have deferred making them for now.
|
||||
*/
|
||||
|
||||
/* get unique object identifier */
|
||||
__u32 reiserfs_get_unused_objectid(struct reiserfs_transaction_handle *th)
|
||||
{
|
||||
struct super_block *s = th->t_super;
|
||||
struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(s);
|
||||
__le32 *map = objectid_map(s, rs);
|
||||
__u32 unused_objectid;
|
||||
|
||||
BUG_ON(!th->t_trans_id);
|
||||
|
||||
check_objectid_map(s, map);
|
||||
|
||||
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
|
||||
/* comment needed -Hans */
|
||||
unused_objectid = le32_to_cpu(map[1]);
|
||||
if (unused_objectid == U32_MAX) {
|
||||
reiserfs_warning(s, "reiserfs-15100", "no more object ids");
|
||||
reiserfs_restore_prepared_buffer(s, SB_BUFFER_WITH_SB(s));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This incrementation allocates the first unused objectid. That
|
||||
* is to say, the first entry on the objectid map is the first
|
||||
* unused objectid, and by incrementing it we use it. See below
|
||||
* where we check to see if we eliminated a sequence of unused
|
||||
* objectids....
|
||||
*/
|
||||
map[1] = cpu_to_le32(unused_objectid + 1);
|
||||
|
||||
/*
|
||||
* Now we check to see if we eliminated the last remaining member of
|
||||
* the first even sequence (and can eliminate the sequence by
|
||||
* eliminating its last objectid from oids), and can collapse the
|
||||
* first two odd sequences into one sequence. If so, then the net
|
||||
* result is to eliminate a pair of objectids from oids. We do this
|
||||
* by shifting the entire map to the left.
|
||||
*/
|
||||
if (sb_oid_cursize(rs) > 2 && map[1] == map[2]) {
|
||||
memmove(map + 1, map + 3,
|
||||
(sb_oid_cursize(rs) - 3) * sizeof(__u32));
|
||||
set_sb_oid_cursize(rs, sb_oid_cursize(rs) - 2);
|
||||
}
|
||||
|
||||
journal_mark_dirty(th, SB_BUFFER_WITH_SB(s));
|
||||
return unused_objectid;
|
||||
}
|
||||
|
||||
/* makes object identifier unused */
|
||||
void reiserfs_release_objectid(struct reiserfs_transaction_handle *th,
|
||||
__u32 objectid_to_release)
|
||||
{
|
||||
struct super_block *s = th->t_super;
|
||||
struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(s);
|
||||
__le32 *map = objectid_map(s, rs);
|
||||
int i = 0;
|
||||
|
||||
BUG_ON(!th->t_trans_id);
|
||||
/*return; */
|
||||
check_objectid_map(s, map);
|
||||
|
||||
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
|
||||
journal_mark_dirty(th, SB_BUFFER_WITH_SB(s));
|
||||
|
||||
/*
|
||||
* start at the beginning of the objectid map (i = 0) and go to
|
||||
* the end of it (i = disk_sb->s_oid_cursize). Linear search is
|
||||
* what we use, though it is possible that binary search would be
|
||||
* more efficient after performing lots of deletions (which is
|
||||
* when oids is large.) We only check even i's.
|
||||
*/
|
||||
while (i < sb_oid_cursize(rs)) {
|
||||
if (objectid_to_release == le32_to_cpu(map[i])) {
|
||||
/* This incrementation unallocates the objectid. */
|
||||
le32_add_cpu(&map[i], 1);
|
||||
|
||||
/*
|
||||
* Did we unallocate the last member of an
|
||||
* odd sequence, and can shrink oids?
|
||||
*/
|
||||
if (map[i] == map[i + 1]) {
|
||||
/* shrink objectid map */
|
||||
memmove(map + i, map + i + 2,
|
||||
(sb_oid_cursize(rs) - i -
|
||||
2) * sizeof(__u32));
|
||||
set_sb_oid_cursize(rs, sb_oid_cursize(rs) - 2);
|
||||
|
||||
RFALSE(sb_oid_cursize(rs) < 2 ||
|
||||
sb_oid_cursize(rs) > sb_oid_maxsize(rs),
|
||||
"vs-15005: objectid map corrupted cur_size == %d (max == %d)",
|
||||
sb_oid_cursize(rs), sb_oid_maxsize(rs));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (objectid_to_release > le32_to_cpu(map[i]) &&
|
||||
objectid_to_release < le32_to_cpu(map[i + 1])) {
|
||||
/* size of objectid map is not changed */
|
||||
if (objectid_to_release + 1 == le32_to_cpu(map[i + 1])) {
|
||||
le32_add_cpu(&map[i + 1], -1);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* JDM comparing two little-endian values for
|
||||
* equality -- safe
|
||||
*/
|
||||
/*
|
||||
* objectid map must be expanded, but
|
||||
* there is no space
|
||||
*/
|
||||
if (sb_oid_cursize(rs) == sb_oid_maxsize(rs)) {
|
||||
PROC_INFO_INC(s, leaked_oid);
|
||||
return;
|
||||
}
|
||||
|
||||
/* expand the objectid map */
|
||||
memmove(map + i + 3, map + i + 1,
|
||||
(sb_oid_cursize(rs) - i - 1) * sizeof(__u32));
|
||||
map[i + 1] = cpu_to_le32(objectid_to_release);
|
||||
map[i + 2] = cpu_to_le32(objectid_to_release + 1);
|
||||
set_sb_oid_cursize(rs, sb_oid_cursize(rs) + 2);
|
||||
return;
|
||||
}
|
||||
i += 2;
|
||||
}
|
||||
|
||||
reiserfs_error(s, "vs-15011", "tried to free free object id (%lu)",
|
||||
(long unsigned)objectid_to_release);
|
||||
}
|
||||
|
||||
int reiserfs_convert_objectid_map_v1(struct super_block *s)
|
||||
{
|
||||
struct reiserfs_super_block *disk_sb = SB_DISK_SUPER_BLOCK(s);
|
||||
int cur_size = sb_oid_cursize(disk_sb);
|
||||
int new_size = (s->s_blocksize - SB_SIZE) / sizeof(__u32) / 2 * 2;
|
||||
int old_max = sb_oid_maxsize(disk_sb);
|
||||
struct reiserfs_super_block_v1 *disk_sb_v1;
|
||||
__le32 *objectid_map;
|
||||
int i;
|
||||
|
||||
disk_sb_v1 =
|
||||
(struct reiserfs_super_block_v1 *)(SB_BUFFER_WITH_SB(s)->b_data);
|
||||
objectid_map = (__le32 *) (disk_sb_v1 + 1);
|
||||
|
||||
if (cur_size > new_size) {
|
||||
/*
|
||||
* mark everyone used that was listed as free at
|
||||
* the end of the objectid map
|
||||
*/
|
||||
objectid_map[new_size - 1] = objectid_map[cur_size - 1];
|
||||
set_sb_oid_cursize(disk_sb, new_size);
|
||||
}
|
||||
/* move the smaller objectid map past the end of the new super */
|
||||
for (i = new_size - 1; i >= 0; i--) {
|
||||
objectid_map[i + (old_max - new_size)] = objectid_map[i];
|
||||
}
|
||||
|
||||
/* set the max size so we don't overflow later */
|
||||
set_sb_oid_maxsize(disk_sb, new_size);
|
||||
|
||||
/* Zero out label and generate random UUID */
|
||||
memset(disk_sb->s_label, 0, sizeof(disk_sb->s_label));
|
||||
generate_random_uuid(disk_sb->s_uuid);
|
||||
|
||||
/* finally, zero out the unused chunk of the new super */
|
||||
memset(disk_sb->s_unused, 0, sizeof(disk_sb->s_unused));
|
||||
return 0;
|
||||
}
|
@ -1,792 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
|
||||
*/
|
||||
|
||||
#include <linux/time.h>
|
||||
#include <linux/fs.h>
|
||||
#include "reiserfs.h"
|
||||
#include <linux/string.h>
|
||||
#include <linux/buffer_head.h>
|
||||
|
||||
#include <linux/stdarg.h>
|
||||
|
||||
static char error_buf[1024];
|
||||
static char fmt_buf[1024];
|
||||
static char off_buf[80];
|
||||
|
||||
static char *reiserfs_cpu_offset(struct cpu_key *key)
|
||||
{
|
||||
if (cpu_key_k_type(key) == TYPE_DIRENTRY)
|
||||
sprintf(off_buf, "%llu(%llu)",
|
||||
(unsigned long long)
|
||||
GET_HASH_VALUE(cpu_key_k_offset(key)),
|
||||
(unsigned long long)
|
||||
GET_GENERATION_NUMBER(cpu_key_k_offset(key)));
|
||||
else
|
||||
sprintf(off_buf, "0x%Lx",
|
||||
(unsigned long long)cpu_key_k_offset(key));
|
||||
return off_buf;
|
||||
}
|
||||
|
||||
static char *le_offset(struct reiserfs_key *key)
|
||||
{
|
||||
int version;
|
||||
|
||||
version = le_key_version(key);
|
||||
if (le_key_k_type(version, key) == TYPE_DIRENTRY)
|
||||
sprintf(off_buf, "%llu(%llu)",
|
||||
(unsigned long long)
|
||||
GET_HASH_VALUE(le_key_k_offset(version, key)),
|
||||
(unsigned long long)
|
||||
GET_GENERATION_NUMBER(le_key_k_offset(version, key)));
|
||||
else
|
||||
sprintf(off_buf, "0x%Lx",
|
||||
(unsigned long long)le_key_k_offset(version, key));
|
||||
return off_buf;
|
||||
}
|
||||
|
||||
static char *cpu_type(struct cpu_key *key)
|
||||
{
|
||||
if (cpu_key_k_type(key) == TYPE_STAT_DATA)
|
||||
return "SD";
|
||||
if (cpu_key_k_type(key) == TYPE_DIRENTRY)
|
||||
return "DIR";
|
||||
if (cpu_key_k_type(key) == TYPE_DIRECT)
|
||||
return "DIRECT";
|
||||
if (cpu_key_k_type(key) == TYPE_INDIRECT)
|
||||
return "IND";
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
static char *le_type(struct reiserfs_key *key)
|
||||
{
|
||||
int version;
|
||||
|
||||
version = le_key_version(key);
|
||||
|
||||
if (le_key_k_type(version, key) == TYPE_STAT_DATA)
|
||||
return "SD";
|
||||
if (le_key_k_type(version, key) == TYPE_DIRENTRY)
|
||||
return "DIR";
|
||||
if (le_key_k_type(version, key) == TYPE_DIRECT)
|
||||
return "DIRECT";
|
||||
if (le_key_k_type(version, key) == TYPE_INDIRECT)
|
||||
return "IND";
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
/* %k */
|
||||
static int scnprintf_le_key(char *buf, size_t size, struct reiserfs_key *key)
|
||||
{
|
||||
if (key)
|
||||
return scnprintf(buf, size, "[%d %d %s %s]",
|
||||
le32_to_cpu(key->k_dir_id),
|
||||
le32_to_cpu(key->k_objectid), le_offset(key),
|
||||
le_type(key));
|
||||
else
|
||||
return scnprintf(buf, size, "[NULL]");
|
||||
}
|
||||
|
||||
/* %K */
|
||||
static int scnprintf_cpu_key(char *buf, size_t size, struct cpu_key *key)
|
||||
{
|
||||
if (key)
|
||||
return scnprintf(buf, size, "[%d %d %s %s]",
|
||||
key->on_disk_key.k_dir_id,
|
||||
key->on_disk_key.k_objectid,
|
||||
reiserfs_cpu_offset(key), cpu_type(key));
|
||||
else
|
||||
return scnprintf(buf, size, "[NULL]");
|
||||
}
|
||||
|
||||
static int scnprintf_de_head(char *buf, size_t size,
|
||||
struct reiserfs_de_head *deh)
|
||||
{
|
||||
if (deh)
|
||||
return scnprintf(buf, size,
|
||||
"[offset=%d dir_id=%d objectid=%d location=%d state=%04x]",
|
||||
deh_offset(deh), deh_dir_id(deh),
|
||||
deh_objectid(deh), deh_location(deh),
|
||||
deh_state(deh));
|
||||
else
|
||||
return scnprintf(buf, size, "[NULL]");
|
||||
|
||||
}
|
||||
|
||||
static int scnprintf_item_head(char *buf, size_t size, struct item_head *ih)
|
||||
{
|
||||
if (ih) {
|
||||
char *p = buf;
|
||||
char * const end = buf + size;
|
||||
|
||||
p += scnprintf(p, end - p, "%s",
|
||||
(ih_version(ih) == KEY_FORMAT_3_6) ?
|
||||
"*3.6* " : "*3.5*");
|
||||
|
||||
p += scnprintf_le_key(p, end - p, &ih->ih_key);
|
||||
|
||||
p += scnprintf(p, end - p,
|
||||
", item_len %d, item_location %d, free_space(entry_count) %d",
|
||||
ih_item_len(ih), ih_location(ih),
|
||||
ih_free_space(ih));
|
||||
return p - buf;
|
||||
} else
|
||||
return scnprintf(buf, size, "[NULL]");
|
||||
}
|
||||
|
||||
static int scnprintf_direntry(char *buf, size_t size,
|
||||
struct reiserfs_dir_entry *de)
|
||||
{
|
||||
char name[20];
|
||||
|
||||
memcpy(name, de->de_name, de->de_namelen > 19 ? 19 : de->de_namelen);
|
||||
name[de->de_namelen > 19 ? 19 : de->de_namelen] = 0;
|
||||
return scnprintf(buf, size, "\"%s\"==>[%d %d]",
|
||||
name, de->de_dir_id, de->de_objectid);
|
||||
}
|
||||
|
||||
static int scnprintf_block_head(char *buf, size_t size, struct buffer_head *bh)
|
||||
{
|
||||
return scnprintf(buf, size,
|
||||
"level=%d, nr_items=%d, free_space=%d rdkey ",
|
||||
B_LEVEL(bh), B_NR_ITEMS(bh), B_FREE_SPACE(bh));
|
||||
}
|
||||
|
||||
static int scnprintf_buffer_head(char *buf, size_t size, struct buffer_head *bh)
|
||||
{
|
||||
return scnprintf(buf, size,
|
||||
"dev %pg, size %zd, blocknr %llu, count %d, state 0x%lx, page %p, (%s, %s, %s)",
|
||||
bh->b_bdev, bh->b_size,
|
||||
(unsigned long long)bh->b_blocknr,
|
||||
atomic_read(&(bh->b_count)),
|
||||
bh->b_state, bh->b_page,
|
||||
buffer_uptodate(bh) ? "UPTODATE" : "!UPTODATE",
|
||||
buffer_dirty(bh) ? "DIRTY" : "CLEAN",
|
||||
buffer_locked(bh) ? "LOCKED" : "UNLOCKED");
|
||||
}
|
||||
|
||||
static int scnprintf_disk_child(char *buf, size_t size, struct disk_child *dc)
|
||||
{
|
||||
return scnprintf(buf, size, "[dc_number=%d, dc_size=%u]",
|
||||
dc_block_number(dc), dc_size(dc));
|
||||
}
|
||||
|
||||
static char *is_there_reiserfs_struct(char *fmt, int *what)
|
||||
{
|
||||
char *k = fmt;
|
||||
|
||||
while ((k = strchr(k, '%')) != NULL) {
|
||||
if (k[1] == 'k' || k[1] == 'K' || k[1] == 'h' || k[1] == 't' ||
|
||||
k[1] == 'z' || k[1] == 'b' || k[1] == 'y' || k[1] == 'a') {
|
||||
*what = k[1];
|
||||
break;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
/*
|
||||
* debugging reiserfs we used to print out a lot of different
|
||||
* variables, like keys, item headers, buffer heads etc. Values of
|
||||
* most fields matter. So it took a long time just to write
|
||||
* appropriative printk. With this reiserfs_warning you can use format
|
||||
* specification for complex structures like you used to do with
|
||||
* printfs for integers, doubles and pointers. For instance, to print
|
||||
* out key structure you have to write just:
|
||||
* reiserfs_warning ("bad key %k", key);
|
||||
* instead of
|
||||
* printk ("bad key %lu %lu %lu %lu", key->k_dir_id, key->k_objectid,
|
||||
* key->k_offset, key->k_uniqueness);
|
||||
*/
|
||||
static DEFINE_SPINLOCK(error_lock);
|
||||
static void prepare_error_buf(const char *fmt, va_list args)
|
||||
{
|
||||
char *fmt1 = fmt_buf;
|
||||
char *k;
|
||||
char *p = error_buf;
|
||||
char * const end = &error_buf[sizeof(error_buf)];
|
||||
int what;
|
||||
|
||||
spin_lock(&error_lock);
|
||||
|
||||
if (WARN_ON(strscpy(fmt_buf, fmt, sizeof(fmt_buf)) < 0)) {
|
||||
strscpy(error_buf, "format string too long", end - error_buf);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
while ((k = is_there_reiserfs_struct(fmt1, &what)) != NULL) {
|
||||
*k = 0;
|
||||
|
||||
p += vscnprintf(p, end - p, fmt1, args);
|
||||
|
||||
switch (what) {
|
||||
case 'k':
|
||||
p += scnprintf_le_key(p, end - p,
|
||||
va_arg(args, struct reiserfs_key *));
|
||||
break;
|
||||
case 'K':
|
||||
p += scnprintf_cpu_key(p, end - p,
|
||||
va_arg(args, struct cpu_key *));
|
||||
break;
|
||||
case 'h':
|
||||
p += scnprintf_item_head(p, end - p,
|
||||
va_arg(args, struct item_head *));
|
||||
break;
|
||||
case 't':
|
||||
p += scnprintf_direntry(p, end - p,
|
||||
va_arg(args, struct reiserfs_dir_entry *));
|
||||
break;
|
||||
case 'y':
|
||||
p += scnprintf_disk_child(p, end - p,
|
||||
va_arg(args, struct disk_child *));
|
||||
break;
|
||||
case 'z':
|
||||
p += scnprintf_block_head(p, end - p,
|
||||
va_arg(args, struct buffer_head *));
|
||||
break;
|
||||
case 'b':
|
||||
p += scnprintf_buffer_head(p, end - p,
|
||||
va_arg(args, struct buffer_head *));
|
||||
break;
|
||||
case 'a':
|
||||
p += scnprintf_de_head(p, end - p,
|
||||
va_arg(args, struct reiserfs_de_head *));
|
||||
break;
|
||||
}
|
||||
|
||||
fmt1 = k + 2;
|
||||
}
|
||||
p += vscnprintf(p, end - p, fmt1, args);
|
||||
out_unlock:
|
||||
spin_unlock(&error_lock);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* in addition to usual conversion specifiers this accepts reiserfs
|
||||
* specific conversion specifiers:
|
||||
* %k to print little endian key,
|
||||
* %K to print cpu key,
|
||||
* %h to print item_head,
|
||||
* %t to print directory entry
|
||||
* %z to print block head (arg must be struct buffer_head *
|
||||
* %b to print buffer_head
|
||||
*/
|
||||
|
||||
#define do_reiserfs_warning(fmt)\
|
||||
{\
|
||||
va_list args;\
|
||||
va_start( args, fmt );\
|
||||
prepare_error_buf( fmt, args );\
|
||||
va_end( args );\
|
||||
}
|
||||
|
||||
void __reiserfs_warning(struct super_block *sb, const char *id,
|
||||
const char *function, const char *fmt, ...)
|
||||
{
|
||||
do_reiserfs_warning(fmt);
|
||||
if (sb)
|
||||
printk(KERN_WARNING "REISERFS warning (device %s): %s%s%s: "
|
||||
"%s\n", sb->s_id, id ? id : "", id ? " " : "",
|
||||
function, error_buf);
|
||||
else
|
||||
printk(KERN_WARNING "REISERFS warning: %s%s%s: %s\n",
|
||||
id ? id : "", id ? " " : "", function, error_buf);
|
||||
}
|
||||
|
||||
/* No newline.. reiserfs_info calls can be followed by printk's */
|
||||
void reiserfs_info(struct super_block *sb, const char *fmt, ...)
|
||||
{
|
||||
do_reiserfs_warning(fmt);
|
||||
if (sb)
|
||||
printk(KERN_NOTICE "REISERFS (device %s): %s",
|
||||
sb->s_id, error_buf);
|
||||
else
|
||||
printk(KERN_NOTICE "REISERFS %s:", error_buf);
|
||||
}
|
||||
|
||||
/* No newline.. reiserfs_printk calls can be followed by printk's */
|
||||
static void reiserfs_printk(const char *fmt, ...)
|
||||
{
|
||||
do_reiserfs_warning(fmt);
|
||||
printk(error_buf);
|
||||
}
|
||||
|
||||
void reiserfs_debug(struct super_block *s, int level, const char *fmt, ...)
|
||||
{
|
||||
#ifdef CONFIG_REISERFS_CHECK
|
||||
do_reiserfs_warning(fmt);
|
||||
if (s)
|
||||
printk(KERN_DEBUG "REISERFS debug (device %s): %s\n",
|
||||
s->s_id, error_buf);
|
||||
else
|
||||
printk(KERN_DEBUG "REISERFS debug: %s\n", error_buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* The format:
|
||||
*
|
||||
* maintainer-errorid: [function-name:] message
|
||||
*
|
||||
* where errorid is unique to the maintainer and function-name is
|
||||
* optional, is recommended, so that anyone can easily find the bug
|
||||
* with a simple grep for the short to type string
|
||||
* maintainer-errorid. Don't bother with reusing errorids, there are
|
||||
* lots of numbers out there.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* reiserfs_panic(
|
||||
* p_sb, "reiser-29: reiserfs_new_blocknrs: "
|
||||
* "one of search_start or rn(%d) is equal to MAX_B_NUM,"
|
||||
* "which means that we are optimizing location based on the "
|
||||
* "bogus location of a temp buffer (%p).",
|
||||
* rn, bh
|
||||
* );
|
||||
*
|
||||
* Regular panic()s sometimes clear the screen before the message can
|
||||
* be read, thus the need for the while loop.
|
||||
*
|
||||
* Numbering scheme for panic used by Vladimir and Anatoly( Hans completely
|
||||
* ignores this scheme, and considers it pointless complexity):
|
||||
*
|
||||
* panics in reiserfs_fs.h have numbers from 1000 to 1999
|
||||
* super.c 2000 to 2999
|
||||
* preserve.c (unused) 3000 to 3999
|
||||
* bitmap.c 4000 to 4999
|
||||
* stree.c 5000 to 5999
|
||||
* prints.c 6000 to 6999
|
||||
* namei.c 7000 to 7999
|
||||
* fix_nodes.c 8000 to 8999
|
||||
* dir.c 9000 to 9999
|
||||
* lbalance.c 10000 to 10999
|
||||
* ibalance.c 11000 to 11999 not ready
|
||||
* do_balan.c 12000 to 12999
|
||||
* inode.c 13000 to 13999
|
||||
* file.c 14000 to 14999
|
||||
* objectid.c 15000 - 15999
|
||||
* buffer.c 16000 - 16999
|
||||
* symlink.c 17000 - 17999
|
||||
*
|
||||
* . */
|
||||
|
||||
void __reiserfs_panic(struct super_block *sb, const char *id,
|
||||
const char *function, const char *fmt, ...)
|
||||
{
|
||||
do_reiserfs_warning(fmt);
|
||||
|
||||
#ifdef CONFIG_REISERFS_CHECK
|
||||
dump_stack();
|
||||
#endif
|
||||
if (sb)
|
||||
printk(KERN_WARNING "REISERFS panic (device %s): %s%s%s: %s\n",
|
||||
sb->s_id, id ? id : "", id ? " " : "",
|
||||
function, error_buf);
|
||||
else
|
||||
printk(KERN_WARNING "REISERFS panic: %s%s%s: %s\n",
|
||||
id ? id : "", id ? " " : "", function, error_buf);
|
||||
BUG();
|
||||
}
|
||||
|
||||
void __reiserfs_error(struct super_block *sb, const char *id,
|
||||
const char *function, const char *fmt, ...)
|
||||
{
|
||||
do_reiserfs_warning(fmt);
|
||||
|
||||
BUG_ON(sb == NULL);
|
||||
|
||||
if (reiserfs_error_panic(sb))
|
||||
__reiserfs_panic(sb, id, function, error_buf);
|
||||
|
||||
if (id && id[0])
|
||||
printk(KERN_CRIT "REISERFS error (device %s): %s %s: %s\n",
|
||||
sb->s_id, id, function, error_buf);
|
||||
else
|
||||
printk(KERN_CRIT "REISERFS error (device %s): %s: %s\n",
|
||||
sb->s_id, function, error_buf);
|
||||
|
||||
if (sb_rdonly(sb))
|
||||
return;
|
||||
|
||||
reiserfs_info(sb, "Remounting filesystem read-only\n");
|
||||
sb->s_flags |= SB_RDONLY;
|
||||
reiserfs_abort_journal(sb, -EIO);
|
||||
}
|
||||
|
||||
void reiserfs_abort(struct super_block *sb, int errno, const char *fmt, ...)
|
||||
{
|
||||
do_reiserfs_warning(fmt);
|
||||
|
||||
if (reiserfs_error_panic(sb)) {
|
||||
panic(KERN_CRIT "REISERFS panic (device %s): %s\n", sb->s_id,
|
||||
error_buf);
|
||||
}
|
||||
|
||||
if (reiserfs_is_journal_aborted(SB_JOURNAL(sb)))
|
||||
return;
|
||||
|
||||
printk(KERN_CRIT "REISERFS abort (device %s): %s\n", sb->s_id,
|
||||
error_buf);
|
||||
|
||||
sb->s_flags |= SB_RDONLY;
|
||||
reiserfs_abort_journal(sb, errno);
|
||||
}
|
||||
|
||||
/*
|
||||
* this prints internal nodes (4 keys/items in line) (dc_number,
|
||||
* dc_size)[k_dirid, k_objectid, k_offset, k_uniqueness](dc_number,
|
||||
* dc_size)...
|
||||
*/
|
||||
static int print_internal(struct buffer_head *bh, int first, int last)
|
||||
{
|
||||
struct reiserfs_key *key;
|
||||
struct disk_child *dc;
|
||||
int i;
|
||||
int from, to;
|
||||
|
||||
if (!B_IS_KEYS_LEVEL(bh))
|
||||
return 1;
|
||||
|
||||
check_internal(bh);
|
||||
|
||||
if (first == -1) {
|
||||
from = 0;
|
||||
to = B_NR_ITEMS(bh);
|
||||
} else {
|
||||
from = first;
|
||||
to = min_t(int, last, B_NR_ITEMS(bh));
|
||||
}
|
||||
|
||||
reiserfs_printk("INTERNAL NODE (%ld) contains %z\n", bh->b_blocknr, bh);
|
||||
|
||||
dc = B_N_CHILD(bh, from);
|
||||
reiserfs_printk("PTR %d: %y ", from, dc);
|
||||
|
||||
for (i = from, key = internal_key(bh, from), dc++; i < to;
|
||||
i++, key++, dc++) {
|
||||
reiserfs_printk("KEY %d: %k PTR %d: %y ", i, key, i + 1, dc);
|
||||
if (i && i % 4 == 0)
|
||||
printk("\n");
|
||||
}
|
||||
printk("\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_leaf(struct buffer_head *bh, int print_mode, int first,
|
||||
int last)
|
||||
{
|
||||
struct block_head *blkh;
|
||||
struct item_head *ih;
|
||||
int i, nr;
|
||||
int from, to;
|
||||
|
||||
if (!B_IS_ITEMS_LEVEL(bh))
|
||||
return 1;
|
||||
|
||||
check_leaf(bh);
|
||||
|
||||
blkh = B_BLK_HEAD(bh);
|
||||
ih = item_head(bh, 0);
|
||||
nr = blkh_nr_item(blkh);
|
||||
|
||||
printk
|
||||
("\n===================================================================\n");
|
||||
reiserfs_printk("LEAF NODE (%ld) contains %z\n", bh->b_blocknr, bh);
|
||||
|
||||
if (!(print_mode & PRINT_LEAF_ITEMS)) {
|
||||
reiserfs_printk("FIRST ITEM_KEY: %k, LAST ITEM KEY: %k\n",
|
||||
&(ih->ih_key), &((ih + nr - 1)->ih_key));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (first < 0 || first > nr - 1)
|
||||
from = 0;
|
||||
else
|
||||
from = first;
|
||||
|
||||
if (last < 0 || last > nr)
|
||||
to = nr;
|
||||
else
|
||||
to = last;
|
||||
|
||||
ih += from;
|
||||
printk
|
||||
("-------------------------------------------------------------------------------\n");
|
||||
printk
|
||||
("|##| type | key | ilen | free_space | version | loc |\n");
|
||||
for (i = from; i < to; i++, ih++) {
|
||||
printk
|
||||
("-------------------------------------------------------------------------------\n");
|
||||
reiserfs_printk("|%2d| %h |\n", i, ih);
|
||||
if (print_mode & PRINT_LEAF_ITEMS)
|
||||
op_print_item(ih, ih_item_body(bh, ih));
|
||||
}
|
||||
|
||||
printk
|
||||
("===================================================================\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *reiserfs_hashname(int code)
|
||||
{
|
||||
if (code == YURA_HASH)
|
||||
return "rupasov";
|
||||
if (code == TEA_HASH)
|
||||
return "tea";
|
||||
if (code == R5_HASH)
|
||||
return "r5";
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
/* return 1 if this is not super block */
|
||||
static int print_super_block(struct buffer_head *bh)
|
||||
{
|
||||
struct reiserfs_super_block *rs =
|
||||
(struct reiserfs_super_block *)(bh->b_data);
|
||||
int skipped, data_blocks;
|
||||
char *version;
|
||||
|
||||
if (is_reiserfs_3_5(rs)) {
|
||||
version = "3.5";
|
||||
} else if (is_reiserfs_3_6(rs)) {
|
||||
version = "3.6";
|
||||
} else if (is_reiserfs_jr(rs)) {
|
||||
version = ((sb_version(rs) == REISERFS_VERSION_2) ?
|
||||
"3.6" : "3.5");
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printk("%pg\'s super block is in block %llu\n", bh->b_bdev,
|
||||
(unsigned long long)bh->b_blocknr);
|
||||
printk("Reiserfs version %s\n", version);
|
||||
printk("Block count %u\n", sb_block_count(rs));
|
||||
printk("Blocksize %d\n", sb_blocksize(rs));
|
||||
printk("Free blocks %u\n", sb_free_blocks(rs));
|
||||
/*
|
||||
* FIXME: this would be confusing if
|
||||
* someone stores reiserfs super block in some data block ;)
|
||||
// skipped = (bh->b_blocknr * bh->b_size) / sb_blocksize(rs);
|
||||
*/
|
||||
skipped = bh->b_blocknr;
|
||||
data_blocks = sb_block_count(rs) - skipped - 1 - sb_bmap_nr(rs) -
|
||||
(!is_reiserfs_jr(rs) ? sb_jp_journal_size(rs) +
|
||||
1 : sb_reserved_for_journal(rs)) - sb_free_blocks(rs);
|
||||
printk
|
||||
("Busy blocks (skipped %d, bitmaps - %d, journal (or reserved) blocks - %d\n"
|
||||
"1 super block, %d data blocks\n", skipped, sb_bmap_nr(rs),
|
||||
(!is_reiserfs_jr(rs) ? (sb_jp_journal_size(rs) + 1) :
|
||||
sb_reserved_for_journal(rs)), data_blocks);
|
||||
printk("Root block %u\n", sb_root_block(rs));
|
||||
printk("Journal block (first) %d\n", sb_jp_journal_1st_block(rs));
|
||||
printk("Journal dev %d\n", sb_jp_journal_dev(rs));
|
||||
printk("Journal orig size %d\n", sb_jp_journal_size(rs));
|
||||
printk("FS state %d\n", sb_fs_state(rs));
|
||||
printk("Hash function \"%s\"\n",
|
||||
reiserfs_hashname(sb_hash_function_code(rs)));
|
||||
|
||||
printk("Tree height %d\n", sb_tree_height(rs));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_desc_block(struct buffer_head *bh)
|
||||
{
|
||||
struct reiserfs_journal_desc *desc;
|
||||
|
||||
if (memcmp(get_journal_desc_magic(bh), JOURNAL_DESC_MAGIC, 8))
|
||||
return 1;
|
||||
|
||||
desc = (struct reiserfs_journal_desc *)(bh->b_data);
|
||||
printk("Desc block %llu (j_trans_id %d, j_mount_id %d, j_len %d)",
|
||||
(unsigned long long)bh->b_blocknr, get_desc_trans_id(desc),
|
||||
get_desc_mount_id(desc), get_desc_trans_len(desc));
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* ..., int print_mode, int first, int last) */
|
||||
void print_block(struct buffer_head *bh, ...)
|
||||
{
|
||||
va_list args;
|
||||
int mode, first, last;
|
||||
|
||||
if (!bh) {
|
||||
printk("print_block: buffer is NULL\n");
|
||||
return;
|
||||
}
|
||||
|
||||
va_start(args, bh);
|
||||
|
||||
mode = va_arg(args, int);
|
||||
first = va_arg(args, int);
|
||||
last = va_arg(args, int);
|
||||
if (print_leaf(bh, mode, first, last))
|
||||
if (print_internal(bh, first, last))
|
||||
if (print_super_block(bh))
|
||||
if (print_desc_block(bh))
|
||||
printk
|
||||
("Block %llu contains unformatted data\n",
|
||||
(unsigned long long)bh->b_blocknr);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static char print_tb_buf[2048];
|
||||
|
||||
/* this stores initial state of tree balance in the print_tb_buf */
|
||||
void store_print_tb(struct tree_balance *tb)
|
||||
{
|
||||
int h = 0;
|
||||
int i;
|
||||
struct buffer_head *tbSh, *tbFh;
|
||||
|
||||
if (!tb)
|
||||
return;
|
||||
|
||||
sprintf(print_tb_buf, "\n"
|
||||
"BALANCING %d\n"
|
||||
"MODE=%c, ITEM_POS=%d POS_IN_ITEM=%d\n"
|
||||
"=====================================================================\n"
|
||||
"* h * S * L * R * F * FL * FR * CFL * CFR *\n",
|
||||
REISERFS_SB(tb->tb_sb)->s_do_balance,
|
||||
tb->tb_mode, PATH_LAST_POSITION(tb->tb_path),
|
||||
tb->tb_path->pos_in_item);
|
||||
|
||||
for (h = 0; h < ARRAY_SIZE(tb->insert_size); h++) {
|
||||
if (PATH_H_PATH_OFFSET(tb->tb_path, h) <=
|
||||
tb->tb_path->path_length
|
||||
&& PATH_H_PATH_OFFSET(tb->tb_path,
|
||||
h) > ILLEGAL_PATH_ELEMENT_OFFSET) {
|
||||
tbSh = PATH_H_PBUFFER(tb->tb_path, h);
|
||||
tbFh = PATH_H_PPARENT(tb->tb_path, h);
|
||||
} else {
|
||||
tbSh = NULL;
|
||||
tbFh = NULL;
|
||||
}
|
||||
sprintf(print_tb_buf + strlen(print_tb_buf),
|
||||
"* %d * %3lld(%2d) * %3lld(%2d) * %3lld(%2d) * %5lld * %5lld * %5lld * %5lld * %5lld *\n",
|
||||
h,
|
||||
(tbSh) ? (long long)(tbSh->b_blocknr) : (-1LL),
|
||||
(tbSh) ? atomic_read(&tbSh->b_count) : -1,
|
||||
(tb->L[h]) ? (long long)(tb->L[h]->b_blocknr) : (-1LL),
|
||||
(tb->L[h]) ? atomic_read(&tb->L[h]->b_count) : -1,
|
||||
(tb->R[h]) ? (long long)(tb->R[h]->b_blocknr) : (-1LL),
|
||||
(tb->R[h]) ? atomic_read(&tb->R[h]->b_count) : -1,
|
||||
(tbFh) ? (long long)(tbFh->b_blocknr) : (-1LL),
|
||||
(tb->FL[h]) ? (long long)(tb->FL[h]->
|
||||
b_blocknr) : (-1LL),
|
||||
(tb->FR[h]) ? (long long)(tb->FR[h]->
|
||||
b_blocknr) : (-1LL),
|
||||
(tb->CFL[h]) ? (long long)(tb->CFL[h]->
|
||||
b_blocknr) : (-1LL),
|
||||
(tb->CFR[h]) ? (long long)(tb->CFR[h]->
|
||||
b_blocknr) : (-1LL));
|
||||
}
|
||||
|
||||
sprintf(print_tb_buf + strlen(print_tb_buf),
|
||||
"=====================================================================\n"
|
||||
"* h * size * ln * lb * rn * rb * blkn * s0 * s1 * s1b * s2 * s2b * curb * lk * rk *\n"
|
||||
"* 0 * %4d * %2d * %2d * %2d * %2d * %4d * %2d * %2d * %3d * %2d * %3d * %4d * %2d * %2d *\n",
|
||||
tb->insert_size[0], tb->lnum[0], tb->lbytes, tb->rnum[0],
|
||||
tb->rbytes, tb->blknum[0], tb->s0num, tb->snum[0],
|
||||
tb->sbytes[0], tb->snum[1], tb->sbytes[1],
|
||||
tb->cur_blknum, tb->lkey[0], tb->rkey[0]);
|
||||
|
||||
/* this prints balance parameters for non-leaf levels */
|
||||
h = 0;
|
||||
do {
|
||||
h++;
|
||||
sprintf(print_tb_buf + strlen(print_tb_buf),
|
||||
"* %d * %4d * %2d * * %2d * * %2d *\n",
|
||||
h, tb->insert_size[h], tb->lnum[h], tb->rnum[h],
|
||||
tb->blknum[h]);
|
||||
} while (tb->insert_size[h]);
|
||||
|
||||
sprintf(print_tb_buf + strlen(print_tb_buf),
|
||||
"=====================================================================\n"
|
||||
"FEB list: ");
|
||||
|
||||
/* print FEB list (list of buffers in form (bh (b_blocknr, b_count), that will be used for new nodes) */
|
||||
h = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(tb->FEB); i++)
|
||||
sprintf(print_tb_buf + strlen(print_tb_buf),
|
||||
"%p (%llu %d)%s", tb->FEB[i],
|
||||
tb->FEB[i] ? (unsigned long long)tb->FEB[i]->
|
||||
b_blocknr : 0ULL,
|
||||
tb->FEB[i] ? atomic_read(&tb->FEB[i]->b_count) : 0,
|
||||
(i == ARRAY_SIZE(tb->FEB) - 1) ? "\n" : ", ");
|
||||
|
||||
sprintf(print_tb_buf + strlen(print_tb_buf),
|
||||
"======================== the end ====================================\n");
|
||||
}
|
||||
|
||||
void print_cur_tb(char *mes)
|
||||
{
|
||||
printk("%s\n%s", mes, print_tb_buf);
|
||||
}
|
||||
|
||||
static void check_leaf_block_head(struct buffer_head *bh)
|
||||
{
|
||||
struct block_head *blkh;
|
||||
int nr;
|
||||
|
||||
blkh = B_BLK_HEAD(bh);
|
||||
nr = blkh_nr_item(blkh);
|
||||
if (nr > (bh->b_size - BLKH_SIZE) / IH_SIZE)
|
||||
reiserfs_panic(NULL, "vs-6010", "invalid item number %z",
|
||||
bh);
|
||||
if (blkh_free_space(blkh) > bh->b_size - BLKH_SIZE - IH_SIZE * nr)
|
||||
reiserfs_panic(NULL, "vs-6020", "invalid free space %z",
|
||||
bh);
|
||||
|
||||
}
|
||||
|
||||
static void check_internal_block_head(struct buffer_head *bh)
|
||||
{
|
||||
if (!(B_LEVEL(bh) > DISK_LEAF_NODE_LEVEL && B_LEVEL(bh) <= MAX_HEIGHT))
|
||||
reiserfs_panic(NULL, "vs-6025", "invalid level %z", bh);
|
||||
|
||||
if (B_NR_ITEMS(bh) > (bh->b_size - BLKH_SIZE) / IH_SIZE)
|
||||
reiserfs_panic(NULL, "vs-6030", "invalid item number %z", bh);
|
||||
|
||||
if (B_FREE_SPACE(bh) !=
|
||||
bh->b_size - BLKH_SIZE - KEY_SIZE * B_NR_ITEMS(bh) -
|
||||
DC_SIZE * (B_NR_ITEMS(bh) + 1))
|
||||
reiserfs_panic(NULL, "vs-6040", "invalid free space %z", bh);
|
||||
|
||||
}
|
||||
|
||||
void check_leaf(struct buffer_head *bh)
|
||||
{
|
||||
int i;
|
||||
struct item_head *ih;
|
||||
|
||||
if (!bh)
|
||||
return;
|
||||
check_leaf_block_head(bh);
|
||||
for (i = 0, ih = item_head(bh, 0); i < B_NR_ITEMS(bh); i++, ih++)
|
||||
op_check_item(ih, ih_item_body(bh, ih));
|
||||
}
|
||||
|
||||
void check_internal(struct buffer_head *bh)
|
||||
{
|
||||
if (!bh)
|
||||
return;
|
||||
check_internal_block_head(bh);
|
||||
}
|
||||
|
||||
void print_statistics(struct super_block *s)
|
||||
{
|
||||
|
||||
/*
|
||||
printk ("reiserfs_put_super: session statistics: balances %d, fix_nodes %d, \
|
||||
bmap with search %d, without %d, dir2ind %d, ind2dir %d\n",
|
||||
REISERFS_SB(s)->s_do_balance, REISERFS_SB(s)->s_fix_nodes,
|
||||
REISERFS_SB(s)->s_bmaps, REISERFS_SB(s)->s_bmaps_without_search,
|
||||
REISERFS_SB(s)->s_direct2indirect, REISERFS_SB(s)->s_indirect2direct);
|
||||
*/
|
||||
|
||||
}
|
@ -1,490 +0,0 @@
|
||||
/* -*- linux-c -*- */
|
||||
|
||||
/* fs/reiserfs/procfs.c */
|
||||
|
||||
/*
|
||||
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
|
||||
*/
|
||||
|
||||
/* proc info support a la one created by Sizif@Botik.RU for PGC */
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include "reiserfs.h"
|
||||
#include <linux/init.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/blkdev.h>
|
||||
|
||||
/*
|
||||
* LOCKING:
|
||||
*
|
||||
* These guys are evicted from procfs as the very first step in ->kill_sb().
|
||||
*
|
||||
*/
|
||||
|
||||
static int show_version(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct super_block *sb = m->private;
|
||||
char *format;
|
||||
|
||||
if (REISERFS_SB(sb)->s_properties & (1 << REISERFS_3_6)) {
|
||||
format = "3.6";
|
||||
} else if (REISERFS_SB(sb)->s_properties & (1 << REISERFS_3_5)) {
|
||||
format = "3.5";
|
||||
} else {
|
||||
format = "unknown";
|
||||
}
|
||||
|
||||
seq_printf(m, "%s format\twith checks %s\n", format,
|
||||
#if defined( CONFIG_REISERFS_CHECK )
|
||||
"on"
|
||||
#else
|
||||
"off"
|
||||
#endif
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SF( x ) ( r -> x )
|
||||
#define SFP( x ) SF( s_proc_info_data.x )
|
||||
#define SFPL( x ) SFP( x[ level ] )
|
||||
#define SFPF( x ) SFP( scan_bitmap.x )
|
||||
#define SFPJ( x ) SFP( journal.x )
|
||||
|
||||
#define D2C( x ) le16_to_cpu( x )
|
||||
#define D4C( x ) le32_to_cpu( x )
|
||||
#define DF( x ) D2C( rs -> s_v1.x )
|
||||
#define DFL( x ) D4C( rs -> s_v1.x )
|
||||
|
||||
#define objectid_map( s, rs ) (old_format_only (s) ? \
|
||||
(__le32 *)((struct reiserfs_super_block_v1 *)rs + 1) : \
|
||||
(__le32 *)(rs + 1))
|
||||
#define MAP( i ) D4C( objectid_map( sb, rs )[ i ] )
|
||||
|
||||
#define DJF( x ) le32_to_cpu( rs -> x )
|
||||
#define DJP( x ) le32_to_cpu( jp -> x )
|
||||
#define JF( x ) ( r -> s_journal -> x )
|
||||
|
||||
static int show_super(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct super_block *sb = m->private;
|
||||
struct reiserfs_sb_info *r = REISERFS_SB(sb);
|
||||
|
||||
seq_printf(m, "state: \t%s\n"
|
||||
"mount options: \t%s%s%s%s%s%s%s%s%s%s%s\n"
|
||||
"gen. counter: \t%i\n"
|
||||
"s_disk_reads: \t%i\n"
|
||||
"s_disk_writes: \t%i\n"
|
||||
"s_fix_nodes: \t%i\n"
|
||||
"s_do_balance: \t%i\n"
|
||||
"s_unneeded_left_neighbor: \t%i\n"
|
||||
"s_good_search_by_key_reada: \t%i\n"
|
||||
"s_bmaps: \t%i\n"
|
||||
"s_bmaps_without_search: \t%i\n"
|
||||
"s_direct2indirect: \t%i\n"
|
||||
"s_indirect2direct: \t%i\n"
|
||||
"\n"
|
||||
"max_hash_collisions: \t%i\n"
|
||||
"breads: \t%lu\n"
|
||||
"bread_misses: \t%lu\n"
|
||||
"search_by_key: \t%lu\n"
|
||||
"search_by_key_fs_changed: \t%lu\n"
|
||||
"search_by_key_restarted: \t%lu\n"
|
||||
"insert_item_restarted: \t%lu\n"
|
||||
"paste_into_item_restarted: \t%lu\n"
|
||||
"cut_from_item_restarted: \t%lu\n"
|
||||
"delete_solid_item_restarted: \t%lu\n"
|
||||
"delete_item_restarted: \t%lu\n"
|
||||
"leaked_oid: \t%lu\n"
|
||||
"leaves_removable: \t%lu\n",
|
||||
SF(s_mount_state) == REISERFS_VALID_FS ?
|
||||
"REISERFS_VALID_FS" : "REISERFS_ERROR_FS",
|
||||
reiserfs_r5_hash(sb) ? "FORCE_R5 " : "",
|
||||
reiserfs_rupasov_hash(sb) ? "FORCE_RUPASOV " : "",
|
||||
reiserfs_tea_hash(sb) ? "FORCE_TEA " : "",
|
||||
reiserfs_hash_detect(sb) ? "DETECT_HASH " : "",
|
||||
reiserfs_no_border(sb) ? "NO_BORDER " : "BORDER ",
|
||||
reiserfs_no_unhashed_relocation(sb) ?
|
||||
"NO_UNHASHED_RELOCATION " : "",
|
||||
reiserfs_hashed_relocation(sb) ? "UNHASHED_RELOCATION " : "",
|
||||
reiserfs_test4(sb) ? "TEST4 " : "",
|
||||
have_large_tails(sb) ? "TAILS " : have_small_tails(sb) ?
|
||||
"SMALL_TAILS " : "NO_TAILS ",
|
||||
replay_only(sb) ? "REPLAY_ONLY " : "",
|
||||
convert_reiserfs(sb) ? "CONV " : "",
|
||||
atomic_read(&r->s_generation_counter),
|
||||
SF(s_disk_reads), SF(s_disk_writes), SF(s_fix_nodes),
|
||||
SF(s_do_balance), SF(s_unneeded_left_neighbor),
|
||||
SF(s_good_search_by_key_reada), SF(s_bmaps),
|
||||
SF(s_bmaps_without_search), SF(s_direct2indirect),
|
||||
SF(s_indirect2direct), SFP(max_hash_collisions), SFP(breads),
|
||||
SFP(bread_miss), SFP(search_by_key),
|
||||
SFP(search_by_key_fs_changed), SFP(search_by_key_restarted),
|
||||
SFP(insert_item_restarted), SFP(paste_into_item_restarted),
|
||||
SFP(cut_from_item_restarted),
|
||||
SFP(delete_solid_item_restarted), SFP(delete_item_restarted),
|
||||
SFP(leaked_oid), SFP(leaves_removable));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_per_level(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct super_block *sb = m->private;
|
||||
struct reiserfs_sb_info *r = REISERFS_SB(sb);
|
||||
int level;
|
||||
|
||||
seq_printf(m, "level\t"
|
||||
" balances"
|
||||
" [sbk: reads"
|
||||
" fs_changed"
|
||||
" restarted]"
|
||||
" free space"
|
||||
" items"
|
||||
" can_remove"
|
||||
" lnum"
|
||||
" rnum"
|
||||
" lbytes"
|
||||
" rbytes"
|
||||
" get_neig"
|
||||
" get_neig_res" " need_l_neig" " need_r_neig" "\n");
|
||||
|
||||
for (level = 0; level < MAX_HEIGHT; ++level) {
|
||||
seq_printf(m, "%i\t"
|
||||
" %12lu"
|
||||
" %12lu"
|
||||
" %12lu"
|
||||
" %12lu"
|
||||
" %12lu"
|
||||
" %12lu"
|
||||
" %12lu"
|
||||
" %12li"
|
||||
" %12li"
|
||||
" %12li"
|
||||
" %12li"
|
||||
" %12lu"
|
||||
" %12lu"
|
||||
" %12lu"
|
||||
" %12lu"
|
||||
"\n",
|
||||
level,
|
||||
SFPL(balance_at),
|
||||
SFPL(sbk_read_at),
|
||||
SFPL(sbk_fs_changed),
|
||||
SFPL(sbk_restarted),
|
||||
SFPL(free_at),
|
||||
SFPL(items_at),
|
||||
SFPL(can_node_be_removed),
|
||||
SFPL(lnum),
|
||||
SFPL(rnum),
|
||||
SFPL(lbytes),
|
||||
SFPL(rbytes),
|
||||
SFPL(get_neighbors),
|
||||
SFPL(get_neighbors_restart),
|
||||
SFPL(need_l_neighbor), SFPL(need_r_neighbor)
|
||||
);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_bitmap(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct super_block *sb = m->private;
|
||||
struct reiserfs_sb_info *r = REISERFS_SB(sb);
|
||||
|
||||
seq_printf(m, "free_block: %lu\n"
|
||||
" scan_bitmap:"
|
||||
" wait"
|
||||
" bmap"
|
||||
" retry"
|
||||
" stolen"
|
||||
" journal_hint"
|
||||
"journal_nohint"
|
||||
"\n"
|
||||
" %14lu"
|
||||
" %14lu"
|
||||
" %14lu"
|
||||
" %14lu"
|
||||
" %14lu"
|
||||
" %14lu"
|
||||
" %14lu"
|
||||
"\n",
|
||||
SFP(free_block),
|
||||
SFPF(call),
|
||||
SFPF(wait),
|
||||
SFPF(bmap),
|
||||
SFPF(retry),
|
||||
SFPF(stolen),
|
||||
SFPF(in_journal_hint), SFPF(in_journal_nohint));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_on_disk_super(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct super_block *sb = m->private;
|
||||
struct reiserfs_sb_info *sb_info = REISERFS_SB(sb);
|
||||
struct reiserfs_super_block *rs = sb_info->s_rs;
|
||||
int hash_code = DFL(s_hash_function_code);
|
||||
__u32 flags = DJF(s_flags);
|
||||
|
||||
seq_printf(m, "block_count: \t%i\n"
|
||||
"free_blocks: \t%i\n"
|
||||
"root_block: \t%i\n"
|
||||
"blocksize: \t%i\n"
|
||||
"oid_maxsize: \t%i\n"
|
||||
"oid_cursize: \t%i\n"
|
||||
"umount_state: \t%i\n"
|
||||
"magic: \t%10.10s\n"
|
||||
"fs_state: \t%i\n"
|
||||
"hash: \t%s\n"
|
||||
"tree_height: \t%i\n"
|
||||
"bmap_nr: \t%i\n"
|
||||
"version: \t%i\n"
|
||||
"flags: \t%x[%s]\n"
|
||||
"reserved_for_journal: \t%i\n",
|
||||
DFL(s_block_count),
|
||||
DFL(s_free_blocks),
|
||||
DFL(s_root_block),
|
||||
DF(s_blocksize),
|
||||
DF(s_oid_maxsize),
|
||||
DF(s_oid_cursize),
|
||||
DF(s_umount_state),
|
||||
rs->s_v1.s_magic,
|
||||
DF(s_fs_state),
|
||||
hash_code == TEA_HASH ? "tea" :
|
||||
(hash_code == YURA_HASH) ? "rupasov" :
|
||||
(hash_code == R5_HASH) ? "r5" :
|
||||
(hash_code == UNSET_HASH) ? "unset" : "unknown",
|
||||
DF(s_tree_height),
|
||||
DF(s_bmap_nr),
|
||||
DF(s_version), flags, (flags & reiserfs_attrs_cleared)
|
||||
? "attrs_cleared" : "", DF(s_reserved_for_journal));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int show_oidmap(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct super_block *sb = m->private;
|
||||
struct reiserfs_sb_info *sb_info = REISERFS_SB(sb);
|
||||
struct reiserfs_super_block *rs = sb_info->s_rs;
|
||||
unsigned int mapsize = le16_to_cpu(rs->s_v1.s_oid_cursize);
|
||||
unsigned long total_used = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mapsize; ++i) {
|
||||
__u32 right;
|
||||
|
||||
right = (i == mapsize - 1) ? MAX_KEY_OBJECTID : MAP(i + 1);
|
||||
seq_printf(m, "%s: [ %x .. %x )\n",
|
||||
(i & 1) ? "free" : "used", MAP(i), right);
|
||||
if (!(i & 1)) {
|
||||
total_used += right - MAP(i);
|
||||
}
|
||||
}
|
||||
#if defined( REISERFS_USE_OIDMAPF )
|
||||
if (sb_info->oidmap.use_file && (sb_info->oidmap.mapf != NULL)) {
|
||||
loff_t size = file_inode(sb_info->oidmap.mapf)->i_size;
|
||||
total_used += size / sizeof(reiserfs_oidinterval_d_t);
|
||||
}
|
||||
#endif
|
||||
seq_printf(m, "total: \t%i [%i/%i] used: %lu [exact]\n",
|
||||
mapsize,
|
||||
mapsize, le16_to_cpu(rs->s_v1.s_oid_maxsize), total_used);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static time64_t ktime_mono_to_real_seconds(time64_t mono)
|
||||
{
|
||||
ktime_t kt = ktime_set(mono, NSEC_PER_SEC/2);
|
||||
|
||||
return ktime_divns(ktime_mono_to_real(kt), NSEC_PER_SEC);
|
||||
}
|
||||
|
||||
static int show_journal(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct super_block *sb = m->private;
|
||||
struct reiserfs_sb_info *r = REISERFS_SB(sb);
|
||||
struct reiserfs_super_block *rs = r->s_rs;
|
||||
struct journal_params *jp = &rs->s_v1.s_journal;
|
||||
|
||||
seq_printf(m, /* on-disk fields */
|
||||
"jp_journal_1st_block: \t%i\n"
|
||||
"jp_journal_dev: \t%pg[%x]\n"
|
||||
"jp_journal_size: \t%i\n"
|
||||
"jp_journal_trans_max: \t%i\n"
|
||||
"jp_journal_magic: \t%i\n"
|
||||
"jp_journal_max_batch: \t%i\n"
|
||||
"jp_journal_max_commit_age: \t%i\n"
|
||||
"jp_journal_max_trans_age: \t%i\n"
|
||||
/* incore fields */
|
||||
"j_1st_reserved_block: \t%i\n"
|
||||
"j_state: \t%li\n"
|
||||
"j_trans_id: \t%u\n"
|
||||
"j_mount_id: \t%lu\n"
|
||||
"j_start: \t%lu\n"
|
||||
"j_len: \t%lu\n"
|
||||
"j_len_alloc: \t%lu\n"
|
||||
"j_wcount: \t%i\n"
|
||||
"j_bcount: \t%lu\n"
|
||||
"j_first_unflushed_offset: \t%lu\n"
|
||||
"j_last_flush_trans_id: \t%u\n"
|
||||
"j_trans_start_time: \t%lli\n"
|
||||
"j_list_bitmap_index: \t%i\n"
|
||||
"j_must_wait: \t%i\n"
|
||||
"j_next_full_flush: \t%i\n"
|
||||
"j_next_async_flush: \t%i\n"
|
||||
"j_cnode_used: \t%i\n" "j_cnode_free: \t%i\n" "\n"
|
||||
/* reiserfs_proc_info_data_t.journal fields */
|
||||
"in_journal: \t%12lu\n"
|
||||
"in_journal_bitmap: \t%12lu\n"
|
||||
"in_journal_reusable: \t%12lu\n"
|
||||
"lock_journal: \t%12lu\n"
|
||||
"lock_journal_wait: \t%12lu\n"
|
||||
"journal_begin: \t%12lu\n"
|
||||
"journal_relock_writers: \t%12lu\n"
|
||||
"journal_relock_wcount: \t%12lu\n"
|
||||
"mark_dirty: \t%12lu\n"
|
||||
"mark_dirty_already: \t%12lu\n"
|
||||
"mark_dirty_notjournal: \t%12lu\n"
|
||||
"restore_prepared: \t%12lu\n"
|
||||
"prepare: \t%12lu\n"
|
||||
"prepare_retry: \t%12lu\n",
|
||||
DJP(jp_journal_1st_block),
|
||||
file_bdev(SB_JOURNAL(sb)->j_bdev_file),
|
||||
DJP(jp_journal_dev),
|
||||
DJP(jp_journal_size),
|
||||
DJP(jp_journal_trans_max),
|
||||
DJP(jp_journal_magic),
|
||||
DJP(jp_journal_max_batch),
|
||||
SB_JOURNAL(sb)->j_max_commit_age,
|
||||
DJP(jp_journal_max_trans_age),
|
||||
JF(j_1st_reserved_block),
|
||||
JF(j_state),
|
||||
JF(j_trans_id),
|
||||
JF(j_mount_id),
|
||||
JF(j_start),
|
||||
JF(j_len),
|
||||
JF(j_len_alloc),
|
||||
atomic_read(&r->s_journal->j_wcount),
|
||||
JF(j_bcount),
|
||||
JF(j_first_unflushed_offset),
|
||||
JF(j_last_flush_trans_id),
|
||||
ktime_mono_to_real_seconds(JF(j_trans_start_time)),
|
||||
JF(j_list_bitmap_index),
|
||||
JF(j_must_wait),
|
||||
JF(j_next_full_flush),
|
||||
JF(j_next_async_flush),
|
||||
JF(j_cnode_used),
|
||||
JF(j_cnode_free),
|
||||
SFPJ(in_journal),
|
||||
SFPJ(in_journal_bitmap),
|
||||
SFPJ(in_journal_reusable),
|
||||
SFPJ(lock_journal),
|
||||
SFPJ(lock_journal_wait),
|
||||
SFPJ(journal_being),
|
||||
SFPJ(journal_relock_writers),
|
||||
SFPJ(journal_relock_wcount),
|
||||
SFPJ(mark_dirty),
|
||||
SFPJ(mark_dirty_already),
|
||||
SFPJ(mark_dirty_notjournal),
|
||||
SFPJ(restore_prepared), SFPJ(prepare), SFPJ(prepare_retry)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct proc_dir_entry *proc_info_root = NULL;
|
||||
static const char proc_info_root_name[] = "fs/reiserfs";
|
||||
|
||||
static void add_file(struct super_block *sb, char *name,
|
||||
int (*func) (struct seq_file *, void *))
|
||||
{
|
||||
proc_create_single_data(name, 0, REISERFS_SB(sb)->procdir, func, sb);
|
||||
}
|
||||
|
||||
int reiserfs_proc_info_init(struct super_block *sb)
|
||||
{
|
||||
char b[BDEVNAME_SIZE];
|
||||
char *s;
|
||||
|
||||
/* Some block devices use /'s */
|
||||
strscpy(b, sb->s_id, BDEVNAME_SIZE);
|
||||
s = strchr(b, '/');
|
||||
if (s)
|
||||
*s = '!';
|
||||
|
||||
spin_lock_init(&__PINFO(sb).lock);
|
||||
REISERFS_SB(sb)->procdir = proc_mkdir_data(b, 0, proc_info_root, sb);
|
||||
if (REISERFS_SB(sb)->procdir) {
|
||||
add_file(sb, "version", show_version);
|
||||
add_file(sb, "super", show_super);
|
||||
add_file(sb, "per-level", show_per_level);
|
||||
add_file(sb, "bitmap", show_bitmap);
|
||||
add_file(sb, "on-disk-super", show_on_disk_super);
|
||||
add_file(sb, "oidmap", show_oidmap);
|
||||
add_file(sb, "journal", show_journal);
|
||||
return 0;
|
||||
}
|
||||
reiserfs_warning(sb, "cannot create /proc/%s/%s",
|
||||
proc_info_root_name, b);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int reiserfs_proc_info_done(struct super_block *sb)
|
||||
{
|
||||
struct proc_dir_entry *de = REISERFS_SB(sb)->procdir;
|
||||
if (de) {
|
||||
char b[BDEVNAME_SIZE];
|
||||
char *s;
|
||||
|
||||
/* Some block devices use /'s */
|
||||
strscpy(b, sb->s_id, BDEVNAME_SIZE);
|
||||
s = strchr(b, '/');
|
||||
if (s)
|
||||
*s = '!';
|
||||
|
||||
remove_proc_subtree(b, proc_info_root);
|
||||
REISERFS_SB(sb)->procdir = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int reiserfs_proc_info_global_init(void)
|
||||
{
|
||||
if (proc_info_root == NULL) {
|
||||
proc_info_root = proc_mkdir(proc_info_root_name, NULL);
|
||||
if (!proc_info_root) {
|
||||
reiserfs_warning(NULL, "cannot create /proc/%s",
|
||||
proc_info_root_name);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int reiserfs_proc_info_global_done(void)
|
||||
{
|
||||
if (proc_info_root != NULL) {
|
||||
proc_info_root = NULL;
|
||||
remove_proc_entry(proc_info_root_name, NULL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Revision 1.1.8.2 2001/07/15 17:08:42 god
|
||||
* . use get_super() in procfs.c
|
||||
* . remove remove_save_link() from reiserfs_do_truncate()
|
||||
*
|
||||
* I accept terms and conditions stated in the Legal Agreement
|
||||
* (available at http://www.namesys.com/legalese.html)
|
||||
*
|
||||
* Revision 1.1.8.1 2001/07/11 16:48:50 god
|
||||
* proc info support
|
||||
*
|
||||
* I accept terms and conditions stated in the Legal Agreement
|
||||
* (available at http://www.namesys.com/legalese.html)
|
||||
*
|
||||
*/
|
File diff suppressed because it is too large
Load Diff
@ -1,230 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
|
||||
*/
|
||||
|
||||
/*
|
||||
* Written by Alexander Zarochentcev.
|
||||
*
|
||||
* The kernel part of the (on-line) reiserfs resizer.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
#include "reiserfs.h"
|
||||
#include <linux/buffer_head.h>
|
||||
|
||||
int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
|
||||
{
|
||||
int err = 0;
|
||||
struct reiserfs_super_block *sb;
|
||||
struct reiserfs_bitmap_info *bitmap;
|
||||
struct reiserfs_bitmap_info *info;
|
||||
struct reiserfs_bitmap_info *old_bitmap = SB_AP_BITMAP(s);
|
||||
struct buffer_head *bh;
|
||||
struct reiserfs_transaction_handle th;
|
||||
unsigned int bmap_nr_new, bmap_nr;
|
||||
unsigned int block_r_new, block_r;
|
||||
|
||||
struct reiserfs_list_bitmap *jb;
|
||||
struct reiserfs_list_bitmap jbitmap[JOURNAL_NUM_BITMAPS];
|
||||
|
||||
unsigned long int block_count, free_blocks;
|
||||
int i;
|
||||
int copy_size;
|
||||
int depth;
|
||||
|
||||
sb = SB_DISK_SUPER_BLOCK(s);
|
||||
|
||||
if (SB_BLOCK_COUNT(s) >= block_count_new) {
|
||||
printk("can\'t shrink filesystem on-line\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* check the device size */
|
||||
depth = reiserfs_write_unlock_nested(s);
|
||||
bh = sb_bread(s, block_count_new - 1);
|
||||
reiserfs_write_lock_nested(s, depth);
|
||||
if (!bh) {
|
||||
printk("reiserfs_resize: can\'t read last block\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
bforget(bh);
|
||||
|
||||
/*
|
||||
* old disk layout detection; those partitions can be mounted, but
|
||||
* cannot be resized
|
||||
*/
|
||||
if (SB_BUFFER_WITH_SB(s)->b_blocknr * SB_BUFFER_WITH_SB(s)->b_size
|
||||
!= REISERFS_DISK_OFFSET_IN_BYTES) {
|
||||
printk
|
||||
("reiserfs_resize: unable to resize a reiserfs without distributed bitmap (fs version < 3.5.12)\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
/* count used bits in last bitmap block */
|
||||
block_r = SB_BLOCK_COUNT(s) -
|
||||
(reiserfs_bmap_count(s) - 1) * s->s_blocksize * 8;
|
||||
|
||||
/* count bitmap blocks in new fs */
|
||||
bmap_nr_new = block_count_new / (s->s_blocksize * 8);
|
||||
block_r_new = block_count_new - bmap_nr_new * s->s_blocksize * 8;
|
||||
if (block_r_new)
|
||||
bmap_nr_new++;
|
||||
else
|
||||
block_r_new = s->s_blocksize * 8;
|
||||
|
||||
/* save old values */
|
||||
block_count = SB_BLOCK_COUNT(s);
|
||||
bmap_nr = reiserfs_bmap_count(s);
|
||||
|
||||
/* resizing of reiserfs bitmaps (journal and real), if needed */
|
||||
if (bmap_nr_new > bmap_nr) {
|
||||
/* reallocate journal bitmaps */
|
||||
if (reiserfs_allocate_list_bitmaps(s, jbitmap, bmap_nr_new) < 0) {
|
||||
printk
|
||||
("reiserfs_resize: unable to allocate memory for journal bitmaps\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
/*
|
||||
* the new journal bitmaps are zero filled, now we copy i
|
||||
* the bitmap node pointers from the old journal bitmap
|
||||
* structs, and then transfer the new data structures
|
||||
* into the journal struct.
|
||||
*
|
||||
* using the copy_size var below allows this code to work for
|
||||
* both shrinking and expanding the FS.
|
||||
*/
|
||||
copy_size = min(bmap_nr_new, bmap_nr);
|
||||
copy_size =
|
||||
copy_size * sizeof(struct reiserfs_list_bitmap_node *);
|
||||
for (i = 0; i < JOURNAL_NUM_BITMAPS; i++) {
|
||||
struct reiserfs_bitmap_node **node_tmp;
|
||||
jb = SB_JOURNAL(s)->j_list_bitmap + i;
|
||||
memcpy(jbitmap[i].bitmaps, jb->bitmaps, copy_size);
|
||||
|
||||
/*
|
||||
* just in case vfree schedules on us, copy the new
|
||||
* pointer into the journal struct before freeing the
|
||||
* old one
|
||||
*/
|
||||
node_tmp = jb->bitmaps;
|
||||
jb->bitmaps = jbitmap[i].bitmaps;
|
||||
vfree(node_tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* allocate additional bitmap blocks, reallocate
|
||||
* array of bitmap block pointers
|
||||
*/
|
||||
bitmap =
|
||||
vzalloc(array_size(bmap_nr_new,
|
||||
sizeof(struct reiserfs_bitmap_info)));
|
||||
if (!bitmap) {
|
||||
/*
|
||||
* Journal bitmaps are still supersized, but the
|
||||
* memory isn't leaked, so I guess it's ok
|
||||
*/
|
||||
printk("reiserfs_resize: unable to allocate memory.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
for (i = 0; i < bmap_nr; i++)
|
||||
bitmap[i] = old_bitmap[i];
|
||||
|
||||
/*
|
||||
* This doesn't go through the journal, but it doesn't have to.
|
||||
* The changes are still atomic: We're synced up when the
|
||||
* journal transaction begins, and the new bitmaps don't
|
||||
* matter if the transaction fails.
|
||||
*/
|
||||
for (i = bmap_nr; i < bmap_nr_new; i++) {
|
||||
int depth;
|
||||
/*
|
||||
* don't use read_bitmap_block since it will cache
|
||||
* the uninitialized bitmap
|
||||
*/
|
||||
depth = reiserfs_write_unlock_nested(s);
|
||||
bh = sb_bread(s, i * s->s_blocksize * 8);
|
||||
reiserfs_write_lock_nested(s, depth);
|
||||
if (!bh) {
|
||||
vfree(bitmap);
|
||||
return -EIO;
|
||||
}
|
||||
memset(bh->b_data, 0, sb_blocksize(sb));
|
||||
reiserfs_set_le_bit(0, bh->b_data);
|
||||
reiserfs_cache_bitmap_metadata(s, bh, bitmap + i);
|
||||
|
||||
set_buffer_uptodate(bh);
|
||||
mark_buffer_dirty(bh);
|
||||
depth = reiserfs_write_unlock_nested(s);
|
||||
sync_dirty_buffer(bh);
|
||||
reiserfs_write_lock_nested(s, depth);
|
||||
/* update bitmap_info stuff */
|
||||
bitmap[i].free_count = sb_blocksize(sb) * 8 - 1;
|
||||
brelse(bh);
|
||||
}
|
||||
/* free old bitmap blocks array */
|
||||
SB_AP_BITMAP(s) = bitmap;
|
||||
vfree(old_bitmap);
|
||||
}
|
||||
|
||||
/*
|
||||
* begin transaction, if there was an error, it's fine. Yes, we have
|
||||
* incorrect bitmaps now, but none of it is ever going to touch the
|
||||
* disk anyway.
|
||||
*/
|
||||
err = journal_begin(&th, s, 10);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Extend old last bitmap block - new blocks have been made available */
|
||||
info = SB_AP_BITMAP(s) + bmap_nr - 1;
|
||||
bh = reiserfs_read_bitmap_block(s, bmap_nr - 1);
|
||||
if (!bh) {
|
||||
int jerr = journal_end(&th);
|
||||
if (jerr)
|
||||
return jerr;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
reiserfs_prepare_for_journal(s, bh, 1);
|
||||
for (i = block_r; i < s->s_blocksize * 8; i++)
|
||||
reiserfs_clear_le_bit(i, bh->b_data);
|
||||
info->free_count += s->s_blocksize * 8 - block_r;
|
||||
|
||||
journal_mark_dirty(&th, bh);
|
||||
brelse(bh);
|
||||
|
||||
/* Correct new last bitmap block - It may not be full */
|
||||
info = SB_AP_BITMAP(s) + bmap_nr_new - 1;
|
||||
bh = reiserfs_read_bitmap_block(s, bmap_nr_new - 1);
|
||||
if (!bh) {
|
||||
int jerr = journal_end(&th);
|
||||
if (jerr)
|
||||
return jerr;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
reiserfs_prepare_for_journal(s, bh, 1);
|
||||
for (i = block_r_new; i < s->s_blocksize * 8; i++)
|
||||
reiserfs_set_le_bit(i, bh->b_data);
|
||||
journal_mark_dirty(&th, bh);
|
||||
brelse(bh);
|
||||
|
||||
info->free_count -= s->s_blocksize * 8 - block_r_new;
|
||||
/* update super */
|
||||
reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
|
||||
free_blocks = SB_FREE_BLOCKS(s);
|
||||
PUT_SB_FREE_BLOCKS(s,
|
||||
free_blocks + (block_count_new - block_count -
|
||||
(bmap_nr_new - bmap_nr)));
|
||||
PUT_SB_BLOCK_COUNT(s, block_count_new);
|
||||
PUT_SB_BMAP_NR(s, bmap_would_wrap(bmap_nr_new) ? : bmap_nr_new);
|
||||
|
||||
journal_mark_dirty(&th, SB_BUFFER_WITH_SB(s));
|
||||
|
||||
SB_JOURNAL(s)->j_must_wait = 1;
|
||||
return journal_end(&th);
|
||||
}
|
2280
fs/reiserfs/stree.c
2280
fs/reiserfs/stree.c
File diff suppressed because it is too large
Load Diff
2646
fs/reiserfs/super.c
2646
fs/reiserfs/super.c
File diff suppressed because it is too large
Load Diff
@ -1,318 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright 1999 Hans Reiser, see reiserfs/README for licensing and copyright
|
||||
* details
|
||||
*/
|
||||
|
||||
#include <linux/time.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/buffer_head.h>
|
||||
#include "reiserfs.h"
|
||||
|
||||
/*
|
||||
* access to tail : when one is going to read tail it must make sure, that is
|
||||
* not running. direct2indirect and indirect2direct can not run concurrently
|
||||
*/
|
||||
|
||||
/*
|
||||
* Converts direct items to an unformatted node. Panics if file has no
|
||||
* tail. -ENOSPC if no disk space for conversion
|
||||
*/
|
||||
/*
|
||||
* path points to first direct item of the file regardless of how many of
|
||||
* them are there
|
||||
*/
|
||||
int direct2indirect(struct reiserfs_transaction_handle *th, struct inode *inode,
|
||||
struct treepath *path, struct buffer_head *unbh,
|
||||
loff_t tail_offset)
|
||||
{
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct buffer_head *up_to_date_bh;
|
||||
struct item_head *p_le_ih = tp_item_head(path);
|
||||
unsigned long total_tail = 0;
|
||||
|
||||
/* Key to search for the last byte of the converted item. */
|
||||
struct cpu_key end_key;
|
||||
|
||||
/*
|
||||
* new indirect item to be inserted or key
|
||||
* of unfm pointer to be pasted
|
||||
*/
|
||||
struct item_head ind_ih;
|
||||
int blk_size;
|
||||
/* returned value for reiserfs_insert_item and clones */
|
||||
int retval;
|
||||
/* Handle on an unformatted node that will be inserted in the tree. */
|
||||
unp_t unfm_ptr;
|
||||
|
||||
BUG_ON(!th->t_trans_id);
|
||||
|
||||
REISERFS_SB(sb)->s_direct2indirect++;
|
||||
|
||||
blk_size = sb->s_blocksize;
|
||||
|
||||
/*
|
||||
* and key to search for append or insert pointer to the new
|
||||
* unformatted node.
|
||||
*/
|
||||
copy_item_head(&ind_ih, p_le_ih);
|
||||
set_le_ih_k_offset(&ind_ih, tail_offset);
|
||||
set_le_ih_k_type(&ind_ih, TYPE_INDIRECT);
|
||||
|
||||
/* Set the key to search for the place for new unfm pointer */
|
||||
make_cpu_key(&end_key, inode, tail_offset, TYPE_INDIRECT, 4);
|
||||
|
||||
/* FIXME: we could avoid this */
|
||||
if (search_for_position_by_key(sb, &end_key, path) == POSITION_FOUND) {
|
||||
reiserfs_error(sb, "PAP-14030",
|
||||
"pasted or inserted byte exists in "
|
||||
"the tree %K. Use fsck to repair.", &end_key);
|
||||
pathrelse(path);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
p_le_ih = tp_item_head(path);
|
||||
|
||||
unfm_ptr = cpu_to_le32(unbh->b_blocknr);
|
||||
|
||||
if (is_statdata_le_ih(p_le_ih)) {
|
||||
/* Insert new indirect item. */
|
||||
set_ih_free_space(&ind_ih, 0); /* delete at nearest future */
|
||||
put_ih_item_len(&ind_ih, UNFM_P_SIZE);
|
||||
PATH_LAST_POSITION(path)++;
|
||||
retval =
|
||||
reiserfs_insert_item(th, path, &end_key, &ind_ih, inode,
|
||||
(char *)&unfm_ptr);
|
||||
} else {
|
||||
/* Paste into last indirect item of an object. */
|
||||
retval = reiserfs_paste_into_item(th, path, &end_key, inode,
|
||||
(char *)&unfm_ptr,
|
||||
UNFM_P_SIZE);
|
||||
}
|
||||
if (retval) {
|
||||
return retval;
|
||||
}
|
||||
/*
|
||||
* note: from here there are two keys which have matching first
|
||||
* three key components. They only differ by the fourth one.
|
||||
*/
|
||||
|
||||
/* Set the key to search for the direct items of the file */
|
||||
make_cpu_key(&end_key, inode, max_reiserfs_offset(inode), TYPE_DIRECT,
|
||||
4);
|
||||
|
||||
/*
|
||||
* Move bytes from the direct items to the new unformatted node
|
||||
* and delete them.
|
||||
*/
|
||||
while (1) {
|
||||
int tail_size;
|
||||
|
||||
/*
|
||||
* end_key.k_offset is set so, that we will always have found
|
||||
* last item of the file
|
||||
*/
|
||||
if (search_for_position_by_key(sb, &end_key, path) ==
|
||||
POSITION_FOUND)
|
||||
reiserfs_panic(sb, "PAP-14050",
|
||||
"direct item (%K) not found", &end_key);
|
||||
p_le_ih = tp_item_head(path);
|
||||
RFALSE(!is_direct_le_ih(p_le_ih),
|
||||
"vs-14055: direct item expected(%K), found %h",
|
||||
&end_key, p_le_ih);
|
||||
tail_size = (le_ih_k_offset(p_le_ih) & (blk_size - 1))
|
||||
+ ih_item_len(p_le_ih) - 1;
|
||||
|
||||
/*
|
||||
* we only send the unbh pointer if the buffer is not
|
||||
* up to date. this avoids overwriting good data from
|
||||
* writepage() with old data from the disk or buffer cache
|
||||
* Special case: unbh->b_page will be NULL if we are coming
|
||||
* through DIRECT_IO handler here.
|
||||
*/
|
||||
if (!unbh->b_page || buffer_uptodate(unbh)
|
||||
|| PageUptodate(unbh->b_page)) {
|
||||
up_to_date_bh = NULL;
|
||||
} else {
|
||||
up_to_date_bh = unbh;
|
||||
}
|
||||
retval = reiserfs_delete_item(th, path, &end_key, inode,
|
||||
up_to_date_bh);
|
||||
|
||||
total_tail += retval;
|
||||
|
||||
/* done: file does not have direct items anymore */
|
||||
if (tail_size == retval)
|
||||
break;
|
||||
|
||||
}
|
||||
/*
|
||||
* if we've copied bytes from disk into the page, we need to zero
|
||||
* out the unused part of the block (it was not up to date before)
|
||||
*/
|
||||
if (up_to_date_bh) {
|
||||
unsigned pgoff =
|
||||
(tail_offset + total_tail - 1) & (PAGE_SIZE - 1);
|
||||
char *kaddr = kmap_atomic(up_to_date_bh->b_page);
|
||||
memset(kaddr + pgoff, 0, blk_size - total_tail);
|
||||
kunmap_atomic(kaddr);
|
||||
}
|
||||
|
||||
REISERFS_I(inode)->i_first_direct_byte = U32_MAX;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* stolen from fs/buffer.c */
|
||||
void reiserfs_unmap_buffer(struct buffer_head *bh)
|
||||
{
|
||||
lock_buffer(bh);
|
||||
if (buffer_journaled(bh) || buffer_journal_dirty(bh)) {
|
||||
BUG();
|
||||
}
|
||||
clear_buffer_dirty(bh);
|
||||
/*
|
||||
* Remove the buffer from whatever list it belongs to. We are mostly
|
||||
* interested in removing it from per-sb j_dirty_buffers list, to avoid
|
||||
* BUG() on attempt to write not mapped buffer
|
||||
*/
|
||||
if ((!list_empty(&bh->b_assoc_buffers) || bh->b_private) && bh->b_page) {
|
||||
struct inode *inode = bh->b_folio->mapping->host;
|
||||
struct reiserfs_journal *j = SB_JOURNAL(inode->i_sb);
|
||||
spin_lock(&j->j_dirty_buffers_lock);
|
||||
list_del_init(&bh->b_assoc_buffers);
|
||||
reiserfs_free_jh(bh);
|
||||
spin_unlock(&j->j_dirty_buffers_lock);
|
||||
}
|
||||
clear_buffer_mapped(bh);
|
||||
clear_buffer_req(bh);
|
||||
clear_buffer_new(bh);
|
||||
bh->b_bdev = NULL;
|
||||
unlock_buffer(bh);
|
||||
}
|
||||
|
||||
/*
|
||||
* this first locks inode (neither reads nor sync are permitted),
|
||||
* reads tail through page cache, insert direct item. When direct item
|
||||
* inserted successfully inode is left locked. Return value is always
|
||||
* what we expect from it (number of cut bytes). But when tail remains
|
||||
* in the unformatted node, we set mode to SKIP_BALANCING and unlock
|
||||
* inode
|
||||
*/
|
||||
int indirect2direct(struct reiserfs_transaction_handle *th,
|
||||
struct inode *inode, struct page *page,
|
||||
struct treepath *path, /* path to the indirect item. */
|
||||
const struct cpu_key *item_key, /* Key to look for
|
||||
* unformatted node
|
||||
* pointer to be cut. */
|
||||
loff_t n_new_file_size, /* New file size. */
|
||||
char *mode)
|
||||
{
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct item_head s_ih;
|
||||
unsigned long block_size = sb->s_blocksize;
|
||||
char *tail;
|
||||
int tail_len, round_tail_len;
|
||||
loff_t pos, pos1; /* position of first byte of the tail */
|
||||
struct cpu_key key;
|
||||
|
||||
BUG_ON(!th->t_trans_id);
|
||||
|
||||
REISERFS_SB(sb)->s_indirect2direct++;
|
||||
|
||||
*mode = M_SKIP_BALANCING;
|
||||
|
||||
/* store item head path points to. */
|
||||
copy_item_head(&s_ih, tp_item_head(path));
|
||||
|
||||
tail_len = (n_new_file_size & (block_size - 1));
|
||||
if (get_inode_sd_version(inode) == STAT_DATA_V2)
|
||||
round_tail_len = ROUND_UP(tail_len);
|
||||
else
|
||||
round_tail_len = tail_len;
|
||||
|
||||
pos =
|
||||
le_ih_k_offset(&s_ih) - 1 + (ih_item_len(&s_ih) / UNFM_P_SIZE -
|
||||
1) * sb->s_blocksize;
|
||||
pos1 = pos;
|
||||
|
||||
/*
|
||||
* we are protected by i_mutex. The tail can not disapper, not
|
||||
* append can be done either
|
||||
* we are in truncate or packing tail in file_release
|
||||
*/
|
||||
|
||||
tail = (char *)kmap(page); /* this can schedule */
|
||||
|
||||
if (path_changed(&s_ih, path)) {
|
||||
/* re-search indirect item */
|
||||
if (search_for_position_by_key(sb, item_key, path)
|
||||
== POSITION_NOT_FOUND)
|
||||
reiserfs_panic(sb, "PAP-5520",
|
||||
"item to be converted %K does not exist",
|
||||
item_key);
|
||||
copy_item_head(&s_ih, tp_item_head(path));
|
||||
#ifdef CONFIG_REISERFS_CHECK
|
||||
pos = le_ih_k_offset(&s_ih) - 1 +
|
||||
(ih_item_len(&s_ih) / UNFM_P_SIZE -
|
||||
1) * sb->s_blocksize;
|
||||
if (pos != pos1)
|
||||
reiserfs_panic(sb, "vs-5530", "tail position "
|
||||
"changed while we were reading it");
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Set direct item header to insert. */
|
||||
make_le_item_head(&s_ih, NULL, get_inode_item_key_version(inode),
|
||||
pos1 + 1, TYPE_DIRECT, round_tail_len,
|
||||
0xffff /*ih_free_space */ );
|
||||
|
||||
/*
|
||||
* we want a pointer to the first byte of the tail in the page.
|
||||
* the page was locked and this part of the page was up to date when
|
||||
* indirect2direct was called, so we know the bytes are still valid
|
||||
*/
|
||||
tail = tail + (pos & (PAGE_SIZE - 1));
|
||||
|
||||
PATH_LAST_POSITION(path)++;
|
||||
|
||||
key = *item_key;
|
||||
set_cpu_key_k_type(&key, TYPE_DIRECT);
|
||||
key.key_length = 4;
|
||||
/* Insert tail as new direct item in the tree */
|
||||
if (reiserfs_insert_item(th, path, &key, &s_ih, inode,
|
||||
tail ? tail : NULL) < 0) {
|
||||
/*
|
||||
* No disk memory. So we can not convert last unformatted node
|
||||
* to the direct item. In this case we used to adjust
|
||||
* indirect items's ih_free_space. Now ih_free_space is not
|
||||
* used, it would be ideal to write zeros to corresponding
|
||||
* unformatted node. For now i_size is considered as guard for
|
||||
* going out of file size
|
||||
*/
|
||||
kunmap(page);
|
||||
return block_size - round_tail_len;
|
||||
}
|
||||
kunmap(page);
|
||||
|
||||
/* make sure to get the i_blocks changes from reiserfs_insert_item */
|
||||
reiserfs_update_sd(th, inode);
|
||||
|
||||
/*
|
||||
* note: we have now the same as in above direct2indirect
|
||||
* conversion: there are two keys which have matching first three
|
||||
* key components. They only differ by the fourth one.
|
||||
*/
|
||||
|
||||
/*
|
||||
* We have inserted new direct item and must remove last
|
||||
* unformatted node.
|
||||
*/
|
||||
*mode = M_CUT;
|
||||
|
||||
/* we store position of first direct item in the in-core inode */
|
||||
/* mark_file_with_tail (inode, pos1 + 1); */
|
||||
REISERFS_I(inode)->i_first_direct_byte = pos1 + 1;
|
||||
|
||||
return block_size - round_tail_len;
|
||||
}
|
1039
fs/reiserfs/xattr.c
1039
fs/reiserfs/xattr.c
File diff suppressed because it is too large
Load Diff
@ -1,117 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#include <linux/reiserfs_xattr.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/xattr.h>
|
||||
|
||||
struct inode;
|
||||
struct dentry;
|
||||
struct iattr;
|
||||
struct super_block;
|
||||
|
||||
int reiserfs_xattr_register_handlers(void) __init;
|
||||
void reiserfs_xattr_unregister_handlers(void);
|
||||
int reiserfs_xattr_init(struct super_block *sb, int mount_flags);
|
||||
int reiserfs_lookup_privroot(struct super_block *sb);
|
||||
int reiserfs_delete_xattrs(struct inode *inode);
|
||||
int reiserfs_chown_xattrs(struct inode *inode, struct iattr *attrs);
|
||||
int reiserfs_permission(struct mnt_idmap *idmap,
|
||||
struct inode *inode, int mask);
|
||||
|
||||
#ifdef CONFIG_REISERFS_FS_XATTR
|
||||
#define has_xattr_dir(inode) (REISERFS_I(inode)->i_flags & i_has_xattr_dir)
|
||||
ssize_t reiserfs_listxattr(struct dentry *dentry, char *buffer, size_t size);
|
||||
|
||||
int reiserfs_xattr_get(struct inode *, const char *, void *, size_t);
|
||||
int reiserfs_xattr_set(struct inode *, const char *, const void *, size_t, int);
|
||||
int reiserfs_xattr_set_handle(struct reiserfs_transaction_handle *,
|
||||
struct inode *, const char *, const void *,
|
||||
size_t, int);
|
||||
|
||||
extern const struct xattr_handler reiserfs_xattr_user_handler;
|
||||
extern const struct xattr_handler reiserfs_xattr_trusted_handler;
|
||||
extern const struct xattr_handler reiserfs_xattr_security_handler;
|
||||
#ifdef CONFIG_REISERFS_FS_SECURITY
|
||||
int reiserfs_security_init(struct inode *dir, struct inode *inode,
|
||||
const struct qstr *qstr,
|
||||
struct reiserfs_security_handle *sec);
|
||||
int reiserfs_security_write(struct reiserfs_transaction_handle *th,
|
||||
struct inode *inode,
|
||||
struct reiserfs_security_handle *sec);
|
||||
void reiserfs_security_free(struct reiserfs_security_handle *sec);
|
||||
#endif
|
||||
|
||||
static inline int reiserfs_xattrs_initialized(struct super_block *sb)
|
||||
{
|
||||
return REISERFS_SB(sb)->priv_root && REISERFS_SB(sb)->xattr_root;
|
||||
}
|
||||
|
||||
#define xattr_size(size) ((size) + sizeof(struct reiserfs_xattr_header))
|
||||
static inline loff_t reiserfs_xattr_nblocks(struct inode *inode, loff_t size)
|
||||
{
|
||||
loff_t ret = 0;
|
||||
if (reiserfs_file_data_log(inode)) {
|
||||
ret = _ROUND_UP(xattr_size(size), inode->i_sb->s_blocksize);
|
||||
ret >>= inode->i_sb->s_blocksize_bits;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* We may have to create up to 3 objects: xattr root, xattr dir, xattr file.
|
||||
* Let's try to be smart about it.
|
||||
* xattr root: We cache it. If it's not cached, we may need to create it.
|
||||
* xattr dir: If anything has been loaded for this inode, we can set a flag
|
||||
* saying so.
|
||||
* xattr file: Since we don't cache xattrs, we can't tell. We always include
|
||||
* blocks for it.
|
||||
*
|
||||
* However, since root and dir can be created between calls - YOU MUST SAVE
|
||||
* THIS VALUE.
|
||||
*/
|
||||
static inline size_t reiserfs_xattr_jcreate_nblocks(struct inode *inode)
|
||||
{
|
||||
size_t nblocks = JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
|
||||
|
||||
if ((REISERFS_I(inode)->i_flags & i_has_xattr_dir) == 0) {
|
||||
nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
|
||||
if (d_really_is_negative(REISERFS_SB(inode->i_sb)->xattr_root))
|
||||
nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
|
||||
}
|
||||
|
||||
return nblocks;
|
||||
}
|
||||
|
||||
static inline void reiserfs_init_xattr_rwsem(struct inode *inode)
|
||||
{
|
||||
init_rwsem(&REISERFS_I(inode)->i_xattr_sem);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define reiserfs_listxattr NULL
|
||||
|
||||
static inline void reiserfs_init_xattr_rwsem(struct inode *inode)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_REISERFS_FS_XATTR */
|
||||
|
||||
#ifndef CONFIG_REISERFS_FS_SECURITY
|
||||
static inline int reiserfs_security_init(struct inode *dir,
|
||||
struct inode *inode,
|
||||
const struct qstr *qstr,
|
||||
struct reiserfs_security_handle *sec)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int
|
||||
reiserfs_security_write(struct reiserfs_transaction_handle *th,
|
||||
struct inode *inode,
|
||||
struct reiserfs_security_handle *sec)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void reiserfs_security_free(struct reiserfs_security_handle *sec)
|
||||
{}
|
||||
#endif
|
@ -1,411 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/capability.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/posix_acl.h>
|
||||
#include "reiserfs.h"
|
||||
#include <linux/errno.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/xattr.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/posix_acl_xattr.h>
|
||||
#include "xattr.h"
|
||||
#include "acl.h"
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
static int __reiserfs_set_acl(struct reiserfs_transaction_handle *th,
|
||||
struct inode *inode, int type,
|
||||
struct posix_acl *acl);
|
||||
|
||||
|
||||
int
|
||||
reiserfs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
|
||||
struct posix_acl *acl, int type)
|
||||
{
|
||||
int error, error2;
|
||||
struct reiserfs_transaction_handle th;
|
||||
size_t jcreate_blocks;
|
||||
int size = acl ? posix_acl_xattr_size(acl->a_count) : 0;
|
||||
int update_mode = 0;
|
||||
struct inode *inode = d_inode(dentry);
|
||||
umode_t mode = inode->i_mode;
|
||||
|
||||
/*
|
||||
* Pessimism: We can't assume that anything from the xattr root up
|
||||
* has been created.
|
||||
*/
|
||||
|
||||
jcreate_blocks = reiserfs_xattr_jcreate_nblocks(inode) +
|
||||
reiserfs_xattr_nblocks(inode, size) * 2;
|
||||
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
error = journal_begin(&th, inode->i_sb, jcreate_blocks);
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
if (error == 0) {
|
||||
if (type == ACL_TYPE_ACCESS && acl) {
|
||||
error = posix_acl_update_mode(&nop_mnt_idmap, inode,
|
||||
&mode, &acl);
|
||||
if (error)
|
||||
goto unlock;
|
||||
update_mode = 1;
|
||||
}
|
||||
error = __reiserfs_set_acl(&th, inode, type, acl);
|
||||
if (!error && update_mode)
|
||||
inode->i_mode = mode;
|
||||
unlock:
|
||||
reiserfs_write_lock(inode->i_sb);
|
||||
error2 = journal_end(&th);
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
if (error2)
|
||||
error = error2;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert from filesystem to in-memory representation.
|
||||
*/
|
||||
static struct posix_acl *reiserfs_posix_acl_from_disk(const void *value, size_t size)
|
||||
{
|
||||
const char *end = (char *)value + size;
|
||||
int n, count;
|
||||
struct posix_acl *acl;
|
||||
|
||||
if (!value)
|
||||
return NULL;
|
||||
if (size < sizeof(reiserfs_acl_header))
|
||||
return ERR_PTR(-EINVAL);
|
||||
if (((reiserfs_acl_header *) value)->a_version !=
|
||||
cpu_to_le32(REISERFS_ACL_VERSION))
|
||||
return ERR_PTR(-EINVAL);
|
||||
value = (char *)value + sizeof(reiserfs_acl_header);
|
||||
count = reiserfs_acl_count(size);
|
||||
if (count < 0)
|
||||
return ERR_PTR(-EINVAL);
|
||||
if (count == 0)
|
||||
return NULL;
|
||||
acl = posix_acl_alloc(count, GFP_NOFS);
|
||||
if (!acl)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
for (n = 0; n < count; n++) {
|
||||
reiserfs_acl_entry *entry = (reiserfs_acl_entry *) value;
|
||||
if ((char *)value + sizeof(reiserfs_acl_entry_short) > end)
|
||||
goto fail;
|
||||
acl->a_entries[n].e_tag = le16_to_cpu(entry->e_tag);
|
||||
acl->a_entries[n].e_perm = le16_to_cpu(entry->e_perm);
|
||||
switch (acl->a_entries[n].e_tag) {
|
||||
case ACL_USER_OBJ:
|
||||
case ACL_GROUP_OBJ:
|
||||
case ACL_MASK:
|
||||
case ACL_OTHER:
|
||||
value = (char *)value +
|
||||
sizeof(reiserfs_acl_entry_short);
|
||||
break;
|
||||
|
||||
case ACL_USER:
|
||||
value = (char *)value + sizeof(reiserfs_acl_entry);
|
||||
if ((char *)value > end)
|
||||
goto fail;
|
||||
acl->a_entries[n].e_uid =
|
||||
make_kuid(&init_user_ns,
|
||||
le32_to_cpu(entry->e_id));
|
||||
break;
|
||||
case ACL_GROUP:
|
||||
value = (char *)value + sizeof(reiserfs_acl_entry);
|
||||
if ((char *)value > end)
|
||||
goto fail;
|
||||
acl->a_entries[n].e_gid =
|
||||
make_kgid(&init_user_ns,
|
||||
le32_to_cpu(entry->e_id));
|
||||
break;
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (value != end)
|
||||
goto fail;
|
||||
return acl;
|
||||
|
||||
fail:
|
||||
posix_acl_release(acl);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert from in-memory to filesystem representation.
|
||||
*/
|
||||
static void *reiserfs_posix_acl_to_disk(const struct posix_acl *acl, size_t * size)
|
||||
{
|
||||
reiserfs_acl_header *ext_acl;
|
||||
char *e;
|
||||
int n;
|
||||
|
||||
*size = reiserfs_acl_size(acl->a_count);
|
||||
ext_acl = kmalloc(sizeof(reiserfs_acl_header) +
|
||||
acl->a_count *
|
||||
sizeof(reiserfs_acl_entry),
|
||||
GFP_NOFS);
|
||||
if (!ext_acl)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
ext_acl->a_version = cpu_to_le32(REISERFS_ACL_VERSION);
|
||||
e = (char *)ext_acl + sizeof(reiserfs_acl_header);
|
||||
for (n = 0; n < acl->a_count; n++) {
|
||||
const struct posix_acl_entry *acl_e = &acl->a_entries[n];
|
||||
reiserfs_acl_entry *entry = (reiserfs_acl_entry *) e;
|
||||
entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag);
|
||||
entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm);
|
||||
switch (acl->a_entries[n].e_tag) {
|
||||
case ACL_USER:
|
||||
entry->e_id = cpu_to_le32(
|
||||
from_kuid(&init_user_ns, acl_e->e_uid));
|
||||
e += sizeof(reiserfs_acl_entry);
|
||||
break;
|
||||
case ACL_GROUP:
|
||||
entry->e_id = cpu_to_le32(
|
||||
from_kgid(&init_user_ns, acl_e->e_gid));
|
||||
e += sizeof(reiserfs_acl_entry);
|
||||
break;
|
||||
|
||||
case ACL_USER_OBJ:
|
||||
case ACL_GROUP_OBJ:
|
||||
case ACL_MASK:
|
||||
case ACL_OTHER:
|
||||
e += sizeof(reiserfs_acl_entry_short);
|
||||
break;
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
return (char *)ext_acl;
|
||||
|
||||
fail:
|
||||
kfree(ext_acl);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Inode operation get_posix_acl().
|
||||
*
|
||||
* inode->i_mutex: down
|
||||
* BKL held [before 2.5.x]
|
||||
*/
|
||||
struct posix_acl *reiserfs_get_acl(struct inode *inode, int type, bool rcu)
|
||||
{
|
||||
char *name, *value;
|
||||
struct posix_acl *acl;
|
||||
int size;
|
||||
int retval;
|
||||
|
||||
if (rcu)
|
||||
return ERR_PTR(-ECHILD);
|
||||
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
name = XATTR_NAME_POSIX_ACL_ACCESS;
|
||||
break;
|
||||
case ACL_TYPE_DEFAULT:
|
||||
name = XATTR_NAME_POSIX_ACL_DEFAULT;
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
|
||||
size = reiserfs_xattr_get(inode, name, NULL, 0);
|
||||
if (size < 0) {
|
||||
if (size == -ENODATA || size == -ENOSYS)
|
||||
return NULL;
|
||||
return ERR_PTR(size);
|
||||
}
|
||||
|
||||
value = kmalloc(size, GFP_NOFS);
|
||||
if (!value)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
retval = reiserfs_xattr_get(inode, name, value, size);
|
||||
if (retval == -ENODATA || retval == -ENOSYS) {
|
||||
/*
|
||||
* This shouldn't actually happen as it should have
|
||||
* been caught above.. but just in case
|
||||
*/
|
||||
acl = NULL;
|
||||
} else if (retval < 0) {
|
||||
acl = ERR_PTR(retval);
|
||||
} else {
|
||||
acl = reiserfs_posix_acl_from_disk(value, retval);
|
||||
}
|
||||
|
||||
kfree(value);
|
||||
return acl;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inode operation set_posix_acl().
|
||||
*
|
||||
* inode->i_mutex: down
|
||||
* BKL held [before 2.5.x]
|
||||
*/
|
||||
static int
|
||||
__reiserfs_set_acl(struct reiserfs_transaction_handle *th, struct inode *inode,
|
||||
int type, struct posix_acl *acl)
|
||||
{
|
||||
char *name;
|
||||
void *value = NULL;
|
||||
size_t size = 0;
|
||||
int error;
|
||||
|
||||
switch (type) {
|
||||
case ACL_TYPE_ACCESS:
|
||||
name = XATTR_NAME_POSIX_ACL_ACCESS;
|
||||
break;
|
||||
case ACL_TYPE_DEFAULT:
|
||||
name = XATTR_NAME_POSIX_ACL_DEFAULT;
|
||||
if (!S_ISDIR(inode->i_mode))
|
||||
return acl ? -EACCES : 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (acl) {
|
||||
value = reiserfs_posix_acl_to_disk(acl, &size);
|
||||
if (IS_ERR(value))
|
||||
return (int)PTR_ERR(value);
|
||||
}
|
||||
|
||||
error = reiserfs_xattr_set_handle(th, inode, name, value, size, 0);
|
||||
|
||||
/*
|
||||
* Ensure that the inode gets dirtied if we're only using
|
||||
* the mode bits and an old ACL didn't exist. We don't need
|
||||
* to check if the inode is hashed here since we won't get
|
||||
* called by reiserfs_inherit_default_acl().
|
||||
*/
|
||||
if (error == -ENODATA) {
|
||||
error = 0;
|
||||
if (type == ACL_TYPE_ACCESS) {
|
||||
inode_set_ctime_current(inode);
|
||||
mark_inode_dirty(inode);
|
||||
}
|
||||
}
|
||||
|
||||
kfree(value);
|
||||
|
||||
if (!error)
|
||||
set_cached_acl(inode, type, acl);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* dir->i_mutex: locked,
|
||||
* inode is new and not released into the wild yet
|
||||
*/
|
||||
int
|
||||
reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th,
|
||||
struct inode *dir, struct dentry *dentry,
|
||||
struct inode *inode)
|
||||
{
|
||||
struct posix_acl *default_acl, *acl;
|
||||
int err = 0;
|
||||
|
||||
/* ACLs only get applied to files and directories */
|
||||
if (S_ISLNK(inode->i_mode))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* ACLs can only be used on "new" objects, so if it's an old object
|
||||
* there is nothing to inherit from
|
||||
*/
|
||||
if (get_inode_sd_version(dir) == STAT_DATA_V1)
|
||||
goto apply_umask;
|
||||
|
||||
/*
|
||||
* Don't apply ACLs to objects in the .reiserfs_priv tree.. This
|
||||
* would be useless since permissions are ignored, and a pain because
|
||||
* it introduces locking cycles
|
||||
*/
|
||||
if (IS_PRIVATE(inode))
|
||||
goto apply_umask;
|
||||
|
||||
err = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (default_acl) {
|
||||
err = __reiserfs_set_acl(th, inode, ACL_TYPE_DEFAULT,
|
||||
default_acl);
|
||||
posix_acl_release(default_acl);
|
||||
}
|
||||
if (acl) {
|
||||
if (!err)
|
||||
err = __reiserfs_set_acl(th, inode, ACL_TYPE_ACCESS,
|
||||
acl);
|
||||
posix_acl_release(acl);
|
||||
}
|
||||
|
||||
return err;
|
||||
|
||||
apply_umask:
|
||||
/* no ACL, apply umask */
|
||||
inode->i_mode &= ~current_umask();
|
||||
return err;
|
||||
}
|
||||
|
||||
/* This is used to cache the default acl before a new object is created.
|
||||
* The biggest reason for this is to get an idea of how many blocks will
|
||||
* actually be required for the create operation if we must inherit an ACL.
|
||||
* An ACL write can add up to 3 object creations and an additional file write
|
||||
* so we'd prefer not to reserve that many blocks in the journal if we can.
|
||||
* It also has the advantage of not loading the ACL with a transaction open,
|
||||
* this may seem silly, but if the owner of the directory is doing the
|
||||
* creation, the ACL may not be loaded since the permissions wouldn't require
|
||||
* it.
|
||||
* We return the number of blocks required for the transaction.
|
||||
*/
|
||||
int reiserfs_cache_default_acl(struct inode *inode)
|
||||
{
|
||||
struct posix_acl *acl;
|
||||
int nblocks = 0;
|
||||
|
||||
if (IS_PRIVATE(inode))
|
||||
return 0;
|
||||
|
||||
acl = get_inode_acl(inode, ACL_TYPE_DEFAULT);
|
||||
|
||||
if (acl && !IS_ERR(acl)) {
|
||||
int size = reiserfs_acl_size(acl->a_count);
|
||||
|
||||
/* Other xattrs can be created during inode creation. We don't
|
||||
* want to claim too many blocks, so we check to see if we
|
||||
* need to create the tree to the xattrs, and then we
|
||||
* just want two files. */
|
||||
nblocks = reiserfs_xattr_jcreate_nblocks(inode);
|
||||
nblocks += JOURNAL_BLOCKS_PER_OBJECT(inode->i_sb);
|
||||
|
||||
REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
|
||||
|
||||
/* We need to account for writes + bitmaps for two files */
|
||||
nblocks += reiserfs_xattr_nblocks(inode, size) * 4;
|
||||
posix_acl_release(acl);
|
||||
}
|
||||
|
||||
return nblocks;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called under i_mutex
|
||||
*/
|
||||
int reiserfs_acl_chmod(struct dentry *dentry)
|
||||
{
|
||||
struct inode *inode = d_inode(dentry);
|
||||
|
||||
if (IS_PRIVATE(inode))
|
||||
return 0;
|
||||
if (get_inode_sd_version(inode) == STAT_DATA_V1 ||
|
||||
!reiserfs_posixacl(inode->i_sb))
|
||||
return 0;
|
||||
|
||||
return posix_acl_chmod(&nop_mnt_idmap, dentry, inode->i_mode);
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "reiserfs.h"
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/xattr.h>
|
||||
#include <linux/slab.h>
|
||||
#include "xattr.h"
|
||||
#include <linux/security.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
static int
|
||||
security_get(const struct xattr_handler *handler, struct dentry *unused,
|
||||
struct inode *inode, const char *name, void *buffer, size_t size)
|
||||
{
|
||||
if (IS_PRIVATE(inode))
|
||||
return -EPERM;
|
||||
|
||||
return reiserfs_xattr_get(inode, xattr_full_name(handler, name),
|
||||
buffer, size);
|
||||
}
|
||||
|
||||
static int
|
||||
security_set(const struct xattr_handler *handler,
|
||||
struct mnt_idmap *idmap, struct dentry *unused,
|
||||
struct inode *inode, const char *name, const void *buffer,
|
||||
size_t size, int flags)
|
||||
{
|
||||
if (IS_PRIVATE(inode))
|
||||
return -EPERM;
|
||||
|
||||
return reiserfs_xattr_set(inode,
|
||||
xattr_full_name(handler, name),
|
||||
buffer, size, flags);
|
||||
}
|
||||
|
||||
static bool security_list(struct dentry *dentry)
|
||||
{
|
||||
return !IS_PRIVATE(d_inode(dentry));
|
||||
}
|
||||
|
||||
static int
|
||||
reiserfs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
|
||||
void *fs_info)
|
||||
{
|
||||
struct reiserfs_security_handle *sec = fs_info;
|
||||
|
||||
sec->value = kmemdup(xattr_array->value, xattr_array->value_len,
|
||||
GFP_KERNEL);
|
||||
if (!sec->value)
|
||||
return -ENOMEM;
|
||||
|
||||
sec->name = xattr_array->name;
|
||||
sec->length = xattr_array->value_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initializes the security context for a new inode and returns the number
|
||||
* of blocks needed for the transaction. If successful, reiserfs_security
|
||||
* must be released using reiserfs_security_free when the caller is done. */
|
||||
int reiserfs_security_init(struct inode *dir, struct inode *inode,
|
||||
const struct qstr *qstr,
|
||||
struct reiserfs_security_handle *sec)
|
||||
{
|
||||
int blocks = 0;
|
||||
int error;
|
||||
|
||||
sec->name = NULL;
|
||||
sec->value = NULL;
|
||||
sec->length = 0;
|
||||
|
||||
/* Don't add selinux attributes on xattrs - they'll never get used */
|
||||
if (IS_PRIVATE(dir))
|
||||
return 0;
|
||||
|
||||
error = security_inode_init_security(inode, dir, qstr,
|
||||
&reiserfs_initxattrs, sec);
|
||||
if (error) {
|
||||
sec->name = NULL;
|
||||
sec->value = NULL;
|
||||
sec->length = 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
if (sec->length && reiserfs_xattrs_initialized(inode->i_sb)) {
|
||||
blocks = reiserfs_xattr_jcreate_nblocks(inode) +
|
||||
reiserfs_xattr_nblocks(inode, sec->length);
|
||||
/* We don't want to count the directories twice if we have
|
||||
* a default ACL. */
|
||||
REISERFS_I(inode)->i_flags |= i_has_xattr_dir;
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
|
||||
int reiserfs_security_write(struct reiserfs_transaction_handle *th,
|
||||
struct inode *inode,
|
||||
struct reiserfs_security_handle *sec)
|
||||
{
|
||||
char xattr_name[XATTR_NAME_MAX + 1] = XATTR_SECURITY_PREFIX;
|
||||
int error;
|
||||
|
||||
if (XATTR_SECURITY_PREFIX_LEN + strlen(sec->name) > XATTR_NAME_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
strlcat(xattr_name, sec->name, sizeof(xattr_name));
|
||||
|
||||
error = reiserfs_xattr_set_handle(th, inode, xattr_name, sec->value,
|
||||
sec->length, XATTR_CREATE);
|
||||
if (error == -ENODATA || error == -EOPNOTSUPP)
|
||||
error = 0;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void reiserfs_security_free(struct reiserfs_security_handle *sec)
|
||||
{
|
||||
kfree(sec->value);
|
||||
sec->name = NULL;
|
||||
sec->value = NULL;
|
||||
}
|
||||
|
||||
const struct xattr_handler reiserfs_xattr_security_handler = {
|
||||
.prefix = XATTR_SECURITY_PREFIX,
|
||||
.get = security_get,
|
||||
.set = security_set,
|
||||
.list = security_list,
|
||||
};
|
@ -1,46 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "reiserfs.h"
|
||||
#include <linux/capability.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/xattr.h>
|
||||
#include "xattr.h"
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
static int
|
||||
trusted_get(const struct xattr_handler *handler, struct dentry *unused,
|
||||
struct inode *inode, const char *name, void *buffer, size_t size)
|
||||
{
|
||||
if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
|
||||
return -EPERM;
|
||||
|
||||
return reiserfs_xattr_get(inode, xattr_full_name(handler, name),
|
||||
buffer, size);
|
||||
}
|
||||
|
||||
static int
|
||||
trusted_set(const struct xattr_handler *handler,
|
||||
struct mnt_idmap *idmap, struct dentry *unused,
|
||||
struct inode *inode, const char *name, const void *buffer,
|
||||
size_t size, int flags)
|
||||
{
|
||||
if (!capable(CAP_SYS_ADMIN) || IS_PRIVATE(inode))
|
||||
return -EPERM;
|
||||
|
||||
return reiserfs_xattr_set(inode,
|
||||
xattr_full_name(handler, name),
|
||||
buffer, size, flags);
|
||||
}
|
||||
|
||||
static bool trusted_list(struct dentry *dentry)
|
||||
{
|
||||
return capable(CAP_SYS_ADMIN) && !IS_PRIVATE(d_inode(dentry));
|
||||
}
|
||||
|
||||
const struct xattr_handler reiserfs_xattr_trusted_handler = {
|
||||
.prefix = XATTR_TRUSTED_PREFIX,
|
||||
.get = trusted_get,
|
||||
.set = trusted_set,
|
||||
.list = trusted_list,
|
||||
};
|
@ -1,43 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "reiserfs.h"
|
||||
#include <linux/errno.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/xattr.h>
|
||||
#include "xattr.h"
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
static int
|
||||
user_get(const struct xattr_handler *handler, struct dentry *unused,
|
||||
struct inode *inode, const char *name, void *buffer, size_t size)
|
||||
{
|
||||
if (!reiserfs_xattrs_user(inode->i_sb))
|
||||
return -EOPNOTSUPP;
|
||||
return reiserfs_xattr_get(inode, xattr_full_name(handler, name),
|
||||
buffer, size);
|
||||
}
|
||||
|
||||
static int
|
||||
user_set(const struct xattr_handler *handler, struct mnt_idmap *idmap,
|
||||
struct dentry *unused,
|
||||
struct inode *inode, const char *name, const void *buffer,
|
||||
size_t size, int flags)
|
||||
{
|
||||
if (!reiserfs_xattrs_user(inode->i_sb))
|
||||
return -EOPNOTSUPP;
|
||||
return reiserfs_xattr_set(inode,
|
||||
xattr_full_name(handler, name),
|
||||
buffer, size, flags);
|
||||
}
|
||||
|
||||
static bool user_list(struct dentry *dentry)
|
||||
{
|
||||
return reiserfs_xattrs_user(dentry->d_sb);
|
||||
}
|
||||
|
||||
const struct xattr_handler reiserfs_xattr_user_handler = {
|
||||
.prefix = XATTR_USER_PREFIX,
|
||||
.get = user_get,
|
||||
.set = user_set,
|
||||
.list = user_list,
|
||||
};
|
@ -1,27 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright 1996, 1997, 1998 Hans Reiser, see reiserfs/README for licensing and copyright details
|
||||
*/
|
||||
#ifndef _LINUX_REISER_FS_H
|
||||
#define _LINUX_REISER_FS_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/magic.h>
|
||||
|
||||
/*
|
||||
* include/linux/reiser_fs.h
|
||||
*
|
||||
* Reiser File System constants and structures
|
||||
*
|
||||
*/
|
||||
|
||||
/* ioctl's command */
|
||||
#define REISERFS_IOC_UNPACK _IOW(0xCD,1,long)
|
||||
/* define following flags to be the same as in ext2, so that chattr(1),
|
||||
lsattr(1) will work with us. */
|
||||
#define REISERFS_IOC_GETFLAGS FS_IOC_GETFLAGS
|
||||
#define REISERFS_IOC_SETFLAGS FS_IOC_SETFLAGS
|
||||
#define REISERFS_IOC_GETVERSION FS_IOC_GETVERSION
|
||||
#define REISERFS_IOC_SETVERSION FS_IOC_SETVERSION
|
||||
|
||||
#endif /* _LINUX_REISER_FS_H */
|
@ -1,25 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
File: linux/reiserfs_xattr.h
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_REISERFS_XATTR_H
|
||||
#define _LINUX_REISERFS_XATTR_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/* Magic value in header */
|
||||
#define REISERFS_XATTR_MAGIC 0x52465841 /* "RFXA" */
|
||||
|
||||
struct reiserfs_xattr_header {
|
||||
__le32 h_magic; /* magic number for identification */
|
||||
__le32 h_hash; /* hash of the value */
|
||||
};
|
||||
|
||||
struct reiserfs_security_handle {
|
||||
const char *name;
|
||||
void *value;
|
||||
__kernel_size_t length;
|
||||
};
|
||||
|
||||
#endif /* _LINUX_REISERFS_XATTR_H */
|
@ -171,9 +171,6 @@ int main(int argc, char *argv[])
|
||||
#ifdef CONFIG_JFS_SECURITY
|
||||
FS_USE("xattr", "jfs");
|
||||
#endif
|
||||
#ifdef CONFIG_REISERFS_FS_SECURITY
|
||||
FS_USE("xattr", "reiserfs");
|
||||
#endif
|
||||
#ifdef CONFIG_JFFS2_FS_SECURITY
|
||||
FS_USE("xattr", "jffs2");
|
||||
#endif
|
||||
|
@ -11,7 +11,6 @@ NORETURN(__ia32_sys_exit)
|
||||
NORETURN(__ia32_sys_exit_group)
|
||||
NORETURN(__kunit_abort)
|
||||
NORETURN(__module_put_and_kthread_exit)
|
||||
NORETURN(__reiserfs_panic)
|
||||
NORETURN(__stack_chk_fail)
|
||||
NORETURN(__tdx_hypercall_failed)
|
||||
NORETURN(__ubsan_handle_builtin_unreachable)
|
||||
|
@ -27,7 +27,7 @@ static const char *const known_fs[] = {
|
||||
"ipathfs", "iso9660", "jffs2", "jfs", "minix", "mqueue", "msdos",
|
||||
"nfs", "nfs4", "nfsd", "nilfs2", "nsfs", "ntfs", "ntfs3", "ocfs2",
|
||||
"ocfs2_dlmfs", "ocxlflash", "omfs", "openpromfs", "overlay", "pipefs",
|
||||
"proc", "pstore", "pvfs2", "qnx4", "qnx6", "ramfs", "reiserfs",
|
||||
"proc", "pstore", "pvfs2", "qnx4", "qnx6", "ramfs",
|
||||
"resctrl", "romfs", "rootfs", "rpc_pipefs", "s390_hypfs", "secretmem",
|
||||
"securityfs", "selinuxfs", "smackfs", "smb3", "sockfs", "spufs",
|
||||
"squashfs", "sysfs", "sysv", "tmpfs", "tracefs", "ubifs", "udf",
|
||||
|
Loading…
Reference in New Issue
Block a user