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:
Jan Kara 2024-10-17 12:28:23 +02:00
parent 6485cf5ea2
commit fb6f20ecb1
63 changed files with 12 additions and 32804 deletions

View File

@ -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.
---

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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)
{

View File

@ -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"

View File

@ -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.

View File

@ -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

View File

@ -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....

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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);
*/
}

View File

@ -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

View File

@ -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);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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);
}

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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)

View File

@ -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",