Merge f7301270a2 ("Merge tag 'm68k-for-v6.4-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k") into android-mainline
Steps on the way to 6.4-rc1 Change-Id: I8df228b545883b601b406d1bb36a3c56343e76f5 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -40,8 +40,8 @@ Here are the main features of EROFS:
|
||||
- Support multiple devices to refer to external blobs, which can be used
|
||||
for container images;
|
||||
|
||||
- 4KiB block size and 32-bit block addresses for each device, therefore
|
||||
16TiB address space at most for now;
|
||||
- 32-bit block addresses for each device, therefore 16TiB address space at
|
||||
most with 4KiB block size for now;
|
||||
|
||||
- Two inode layouts for different requirements:
|
||||
|
||||
|
||||
@@ -241,7 +241,7 @@ according to the filesystem's idmapping as this would give the wrong owner if
|
||||
the caller is using an idmapping.
|
||||
|
||||
So the kernel will map the id back up in the idmapping of the caller. Let's
|
||||
assume the caller has the slighly unconventional idmapping
|
||||
assume the caller has the somewhat unconventional idmapping
|
||||
``u3000:k20000:r10000`` then ``k21000`` would map back up to ``u4000``.
|
||||
Consequently the user would see that this file is owned by ``u4000``.
|
||||
|
||||
@@ -320,6 +320,10 @@ and equally wrong::
|
||||
from_kuid(u20000:k0:r10000, u1000) = k21000
|
||||
~~~~~
|
||||
|
||||
Since userspace ids have type ``uid_t`` and ``gid_t`` and kernel ids have type
|
||||
``kuid_t`` and ``kgid_t`` the compiler will throw an error when they are
|
||||
conflated. So the two examples above would cause a compilation failure.
|
||||
|
||||
Idmappings when creating filesystem objects
|
||||
-------------------------------------------
|
||||
|
||||
@@ -623,42 +627,105 @@ privileged users in the initial user namespace.
|
||||
However, it is perfectly possible to combine idmapped mounts with filesystems
|
||||
mountable inside user namespaces. We will touch on this further below.
|
||||
|
||||
Filesystem types vs idmapped mount types
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
With the introduction of idmapped mounts we need to distinguish between
|
||||
filesystem ownership and mount ownership of a VFS object such as an inode. The
|
||||
owner of a inode might be different when looked at from a filesystem
|
||||
perspective than when looked at from an idmapped mount. Such fundamental
|
||||
conceptual distinctions should almost always be clearly expressed in the code.
|
||||
So, to distinguish idmapped mount ownership from filesystem ownership separate
|
||||
types have been introduced.
|
||||
|
||||
If a uid or gid has been generated using the filesystem or caller's idmapping
|
||||
then we will use the ``kuid_t`` and ``kgid_t`` types. However, if a uid or gid
|
||||
has been generated using a mount idmapping then we will be using the dedicated
|
||||
``vfsuid_t`` and ``vfsgid_t`` types.
|
||||
|
||||
All VFS helpers that generate or take uids and gids as arguments use the
|
||||
``vfsuid_t`` and ``vfsgid_t`` types and we will be able to rely on the compiler
|
||||
to catch errors that originate from conflating filesystem and VFS uids and gids.
|
||||
|
||||
The ``vfsuid_t`` and ``vfsgid_t`` types are often mapped from and to ``kuid_t``
|
||||
and ``kgid_t`` types similar how ``kuid_t`` and ``kgid_t`` types are mapped
|
||||
from and to ``uid_t`` and ``gid_t`` types::
|
||||
|
||||
uid_t <--> kuid_t <--> vfsuid_t
|
||||
gid_t <--> kgid_t <--> vfsgid_t
|
||||
|
||||
Whenever we report ownership based on a ``vfsuid_t`` or ``vfsgid_t`` type,
|
||||
e.g., during ``stat()``, or store ownership information in a shared VFS object
|
||||
based on a ``vfsuid_t`` or ``vfsgid_t`` type, e.g., during ``chown()`` we can
|
||||
use the ``vfsuid_into_kuid()`` and ``vfsgid_into_kgid()`` helpers.
|
||||
|
||||
To illustrate why this helper currently exists, consider what happens when we
|
||||
change ownership of an inode from an idmapped mount. After we generated
|
||||
a ``vfsuid_t`` or ``vfsgid_t`` based on the mount idmapping we later commit to
|
||||
this ``vfsuid_t`` or ``vfsgid_t`` to become the new filesytem wide ownership.
|
||||
Thus, we are turning the ``vfsuid_t`` or ``vfsgid_t`` into a global ``kuid_t``
|
||||
or ``kgid_t``. And this can be done by using ``vfsuid_into_kuid()`` and
|
||||
``vfsgid_into_kgid()``.
|
||||
|
||||
Note, whenever a shared VFS object, e.g., a cached ``struct inode`` or a cached
|
||||
``struct posix_acl``, stores ownership information a filesystem or "global"
|
||||
``kuid_t`` and ``kgid_t`` must be used. Ownership expressed via ``vfsuid_t``
|
||||
and ``vfsgid_t`` is specific to an idmapped mount.
|
||||
|
||||
We already noted that ``vfsuid_t`` and ``vfsgid_t`` types are generated based
|
||||
on mount idmappings whereas ``kuid_t`` and ``kgid_t`` types are generated based
|
||||
on filesystem idmappings. To prevent abusing filesystem idmappings to generate
|
||||
``vfsuid_t`` or ``vfsgid_t`` types or mount idmappings to generate ``kuid_t``
|
||||
or ``kgid_t`` types filesystem idmappings and mount idmappings are different
|
||||
types as well.
|
||||
|
||||
All helpers that map to or from ``vfsuid_t`` and ``vfsgid_t`` types require
|
||||
a mount idmapping to be passed which is of type ``struct mnt_idmap``. Passing
|
||||
a filesystem or caller idmapping will cause a compilation error.
|
||||
|
||||
Similar to how we prefix all userspace ids in this document with ``u`` and all
|
||||
kernel ids with ``k`` we will prefix all VFS ids with ``v``. So a mount
|
||||
idmapping will be written as: ``u0:v10000:r10000``.
|
||||
|
||||
Remapping helpers
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Idmapping functions were added that translate between idmappings. They make use
|
||||
of the remapping algorithm we've introduced earlier. We're going to look at
|
||||
two:
|
||||
of the remapping algorithm we've introduced earlier. We're going to look at:
|
||||
|
||||
- ``i_uid_into_mnt()`` and ``i_gid_into_mnt()``
|
||||
- ``i_uid_into_vfsuid()`` and ``i_gid_into_vfsgid()``
|
||||
|
||||
The ``i_*id_into_mnt()`` functions translate filesystem's kernel ids into
|
||||
kernel ids in the mount's idmapping::
|
||||
The ``i_*id_into_vfs*id()`` functions translate filesystem's kernel ids into
|
||||
VFS ids in the mount's idmapping::
|
||||
|
||||
/* Map the filesystem's kernel id up into a userspace id in the filesystem's idmapping. */
|
||||
from_kuid(filesystem, kid) = uid
|
||||
|
||||
/* Map the filesystem's userspace id down ito a kernel id in the mount's idmapping. */
|
||||
/* Map the filesystem's userspace id down ito a VFS id in the mount's idmapping. */
|
||||
make_kuid(mount, uid) = kuid
|
||||
|
||||
- ``mapped_fsuid()`` and ``mapped_fsgid()``
|
||||
|
||||
The ``mapped_fs*id()`` functions translate the caller's kernel ids into
|
||||
kernel ids in the filesystem's idmapping. This translation is achieved by
|
||||
remapping the caller's kernel ids using the mount's idmapping::
|
||||
remapping the caller's VFS ids using the mount's idmapping::
|
||||
|
||||
/* Map the caller's kernel id up into a userspace id in the mount's idmapping. */
|
||||
/* Map the caller's VFS id up into a userspace id in the mount's idmapping. */
|
||||
from_kuid(mount, kid) = uid
|
||||
|
||||
/* Map the mount's userspace id down into a kernel id in the filesystem's idmapping. */
|
||||
make_kuid(filesystem, uid) = kuid
|
||||
|
||||
- ``vfsuid_into_kuid()`` and ``vfsgid_into_kgid()``
|
||||
|
||||
Whenever
|
||||
|
||||
Note that these two functions invert each other. Consider the following
|
||||
idmappings::
|
||||
|
||||
caller idmapping: u0:k10000:r10000
|
||||
filesystem idmapping: u0:k20000:r10000
|
||||
mount idmapping: u0:k10000:r10000
|
||||
mount idmapping: u0:v10000:r10000
|
||||
|
||||
Assume a file owned by ``u1000`` is read from disk. The filesystem maps this id
|
||||
to ``k21000`` according to its idmapping. This is what is stored in the
|
||||
@@ -669,20 +736,21 @@ would usually simply use the crossmapping algorithm and map the filesystem's
|
||||
kernel id up to a userspace id in the caller's idmapping.
|
||||
|
||||
But when the caller is accessing the file on an idmapped mount the kernel will
|
||||
first call ``i_uid_into_mnt()`` thereby translating the filesystem's kernel id
|
||||
into a kernel id in the mount's idmapping::
|
||||
first call ``i_uid_into_vfsuid()`` thereby translating the filesystem's kernel
|
||||
id into a VFS id in the mount's idmapping::
|
||||
|
||||
i_uid_into_mnt(k21000):
|
||||
i_uid_into_vfsuid(k21000):
|
||||
/* Map the filesystem's kernel id up into a userspace id. */
|
||||
from_kuid(u0:k20000:r10000, k21000) = u1000
|
||||
|
||||
/* Map the filesystem's userspace id down ito a kernel id in the mount's idmapping. */
|
||||
make_kuid(u0:k10000:r10000, u1000) = k11000
|
||||
/* Map the filesystem's userspace id down into a VFS id in the mount's idmapping. */
|
||||
make_kuid(u0:v10000:r10000, u1000) = v11000
|
||||
|
||||
Finally, when the kernel reports the owner to the caller it will turn the
|
||||
kernel id in the mount's idmapping into a userspace id in the caller's
|
||||
VFS id in the mount's idmapping into a userspace id in the caller's
|
||||
idmapping::
|
||||
|
||||
k11000 = vfsuid_into_kuid(v11000)
|
||||
from_kuid(u0:k10000:r10000, k11000) = u1000
|
||||
|
||||
We can test whether this algorithm really works by verifying what happens when
|
||||
@@ -696,18 +764,19 @@ fails.
|
||||
|
||||
But when the caller is accessing the file on an idmapped mount the kernel will
|
||||
first call ``mapped_fs*id()`` thereby translating the caller's kernel id into
|
||||
a kernel id according to the mount's idmapping::
|
||||
a VFS id according to the mount's idmapping::
|
||||
|
||||
mapped_fsuid(k11000):
|
||||
/* Map the caller's kernel id up into a userspace id in the mount's idmapping. */
|
||||
from_kuid(u0:k10000:r10000, k11000) = u1000
|
||||
|
||||
/* Map the mount's userspace id down into a kernel id in the filesystem's idmapping. */
|
||||
make_kuid(u0:k20000:r10000, u1000) = k21000
|
||||
make_kuid(u0:v20000:r10000, u1000) = v21000
|
||||
|
||||
When finally writing to disk the kernel will then map ``k21000`` up into a
|
||||
When finally writing to disk the kernel will then map ``v21000`` up into a
|
||||
userspace id in the filesystem's idmapping::
|
||||
|
||||
k21000 = vfsuid_into_kuid(v21000)
|
||||
from_kuid(u0:k20000:r10000, k21000) = u1000
|
||||
|
||||
As we can see, we end up with an invertible and therefore information
|
||||
@@ -725,7 +794,7 @@ Example 2 reconsidered
|
||||
caller id: u1000
|
||||
caller idmapping: u0:k10000:r10000
|
||||
filesystem idmapping: u0:k20000:r10000
|
||||
mount idmapping: u0:k10000:r10000
|
||||
mount idmapping: u0:v10000:r10000
|
||||
|
||||
When the caller is using a non-initial idmapping the common case is to attach
|
||||
the same idmapping to the mount. We now perform three steps:
|
||||
@@ -734,12 +803,12 @@ the same idmapping to the mount. We now perform three steps:
|
||||
|
||||
make_kuid(u0:k10000:r10000, u1000) = k11000
|
||||
|
||||
2. Translate the caller's kernel id into a kernel id in the filesystem's
|
||||
2. Translate the caller's VFS id into a kernel id in the filesystem's
|
||||
idmapping::
|
||||
|
||||
mapped_fsuid(k11000):
|
||||
/* Map the kernel id up into a userspace id in the mount's idmapping. */
|
||||
from_kuid(u0:k10000:r10000, k11000) = u1000
|
||||
mapped_fsuid(v11000):
|
||||
/* Map the VFS id up into a userspace id in the mount's idmapping. */
|
||||
from_kuid(u0:v10000:r10000, v11000) = u1000
|
||||
|
||||
/* Map the userspace id down into a kernel id in the filesystem's idmapping. */
|
||||
make_kuid(u0:k20000:r10000, u1000) = k21000
|
||||
@@ -759,7 +828,7 @@ Example 3 reconsidered
|
||||
caller id: u1000
|
||||
caller idmapping: u0:k10000:r10000
|
||||
filesystem idmapping: u0:k0:r4294967295
|
||||
mount idmapping: u0:k10000:r10000
|
||||
mount idmapping: u0:v10000:r10000
|
||||
|
||||
The same translation algorithm works with the third example.
|
||||
|
||||
@@ -767,12 +836,12 @@ The same translation algorithm works with the third example.
|
||||
|
||||
make_kuid(u0:k10000:r10000, u1000) = k11000
|
||||
|
||||
2. Translate the caller's kernel id into a kernel id in the filesystem's
|
||||
2. Translate the caller's VFS id into a kernel id in the filesystem's
|
||||
idmapping::
|
||||
|
||||
mapped_fsuid(k11000):
|
||||
/* Map the kernel id up into a userspace id in the mount's idmapping. */
|
||||
from_kuid(u0:k10000:r10000, k11000) = u1000
|
||||
mapped_fsuid(v11000):
|
||||
/* Map the VFS id up into a userspace id in the mount's idmapping. */
|
||||
from_kuid(u0:v10000:r10000, v11000) = u1000
|
||||
|
||||
/* Map the userspace id down into a kernel id in the filesystem's idmapping. */
|
||||
make_kuid(u0:k0:r4294967295, u1000) = k1000
|
||||
@@ -792,7 +861,7 @@ Example 4 reconsidered
|
||||
file id: u1000
|
||||
caller idmapping: u0:k10000:r10000
|
||||
filesystem idmapping: u0:k0:r4294967295
|
||||
mount idmapping: u0:k10000:r10000
|
||||
mount idmapping: u0:v10000:r10000
|
||||
|
||||
In order to report ownership to userspace the kernel now does three steps using
|
||||
the translation algorithm we introduced earlier:
|
||||
@@ -802,17 +871,18 @@ the translation algorithm we introduced earlier:
|
||||
|
||||
make_kuid(u0:k0:r4294967295, u1000) = k1000
|
||||
|
||||
2. Translate the kernel id into a kernel id in the mount's idmapping::
|
||||
2. Translate the kernel id into a VFS id in the mount's idmapping::
|
||||
|
||||
i_uid_into_mnt(k1000):
|
||||
i_uid_into_vfsuid(k1000):
|
||||
/* Map the kernel id up into a userspace id in the filesystem's idmapping. */
|
||||
from_kuid(u0:k0:r4294967295, k1000) = u1000
|
||||
|
||||
/* Map the userspace id down into a kernel id in the mounts's idmapping. */
|
||||
make_kuid(u0:k10000:r10000, u1000) = k11000
|
||||
/* Map the userspace id down into a VFS id in the mounts's idmapping. */
|
||||
make_kuid(u0:v10000:r10000, u1000) = v11000
|
||||
|
||||
3. Map the kernel id up into a userspace id in the caller's idmapping::
|
||||
3. Map the VFS id up into a userspace id in the caller's idmapping::
|
||||
|
||||
k11000 = vfsuid_into_kuid(v11000)
|
||||
from_kuid(u0:k10000:r10000, k11000) = u1000
|
||||
|
||||
Earlier, the caller's kernel id couldn't be crossmapped in the filesystems's
|
||||
@@ -828,7 +898,7 @@ Example 5 reconsidered
|
||||
file id: u1000
|
||||
caller idmapping: u0:k10000:r10000
|
||||
filesystem idmapping: u0:k20000:r10000
|
||||
mount idmapping: u0:k10000:r10000
|
||||
mount idmapping: u0:v10000:r10000
|
||||
|
||||
Again, in order to report ownership to userspace the kernel now does three
|
||||
steps using the translation algorithm we introduced earlier:
|
||||
@@ -838,17 +908,18 @@ steps using the translation algorithm we introduced earlier:
|
||||
|
||||
make_kuid(u0:k20000:r10000, u1000) = k21000
|
||||
|
||||
2. Translate the kernel id into a kernel id in the mount's idmapping::
|
||||
2. Translate the kernel id into a VFS id in the mount's idmapping::
|
||||
|
||||
i_uid_into_mnt(k21000):
|
||||
i_uid_into_vfsuid(k21000):
|
||||
/* Map the kernel id up into a userspace id in the filesystem's idmapping. */
|
||||
from_kuid(u0:k20000:r10000, k21000) = u1000
|
||||
|
||||
/* Map the userspace id down into a kernel id in the mounts's idmapping. */
|
||||
make_kuid(u0:k10000:r10000, u1000) = k11000
|
||||
/* Map the userspace id down into a VFS id in the mounts's idmapping. */
|
||||
make_kuid(u0:v10000:r10000, u1000) = v11000
|
||||
|
||||
3. Map the kernel id up into a userspace id in the caller's idmapping::
|
||||
3. Map the VFS id up into a userspace id in the caller's idmapping::
|
||||
|
||||
k11000 = vfsuid_into_kuid(v11000)
|
||||
from_kuid(u0:k10000:r10000, k11000) = u1000
|
||||
|
||||
Earlier, the file's kernel id couldn't be crossmapped in the filesystems's
|
||||
@@ -899,23 +970,23 @@ from above:::
|
||||
caller id: u1125
|
||||
caller idmapping: u0:k0:r4294967295
|
||||
filesystem idmapping: u0:k0:r4294967295
|
||||
mount idmapping: u1000:k1125:r1
|
||||
mount idmapping: u1000:v1125:r1
|
||||
|
||||
1. Map the caller's userspace ids into kernel ids in the caller's idmapping::
|
||||
|
||||
make_kuid(u0:k0:r4294967295, u1125) = k1125
|
||||
|
||||
2. Translate the caller's kernel id into a kernel id in the filesystem's
|
||||
2. Translate the caller's VFS id into a kernel id in the filesystem's
|
||||
idmapping::
|
||||
|
||||
mapped_fsuid(k1125):
|
||||
/* Map the kernel id up into a userspace id in the mount's idmapping. */
|
||||
from_kuid(u1000:k1125:r1, k1125) = u1000
|
||||
mapped_fsuid(v1125):
|
||||
/* Map the VFS id up into a userspace id in the mount's idmapping. */
|
||||
from_kuid(u1000:v1125:r1, v1125) = u1000
|
||||
|
||||
/* Map the userspace id down into a kernel id in the filesystem's idmapping. */
|
||||
make_kuid(u0:k0:r4294967295, u1000) = k1000
|
||||
|
||||
2. Verify that the caller's kernel ids can be mapped to userspace ids in the
|
||||
2. Verify that the caller's filesystem ids can be mapped to userspace ids in the
|
||||
filesystem's idmapping::
|
||||
|
||||
from_kuid(u0:k0:r4294967295, k1000) = u1000
|
||||
@@ -930,24 +1001,25 @@ on their work computer:
|
||||
file id: u1000
|
||||
caller idmapping: u0:k0:r4294967295
|
||||
filesystem idmapping: u0:k0:r4294967295
|
||||
mount idmapping: u1000:k1125:r1
|
||||
mount idmapping: u1000:v1125:r1
|
||||
|
||||
1. Map the userspace id on disk down into a kernel id in the filesystem's
|
||||
idmapping::
|
||||
|
||||
make_kuid(u0:k0:r4294967295, u1000) = k1000
|
||||
|
||||
2. Translate the kernel id into a kernel id in the mount's idmapping::
|
||||
2. Translate the kernel id into a VFS id in the mount's idmapping::
|
||||
|
||||
i_uid_into_mnt(k1000):
|
||||
i_uid_into_vfsuid(k1000):
|
||||
/* Map the kernel id up into a userspace id in the filesystem's idmapping. */
|
||||
from_kuid(u0:k0:r4294967295, k1000) = u1000
|
||||
|
||||
/* Map the userspace id down into a kernel id in the mounts's idmapping. */
|
||||
make_kuid(u1000:k1125:r1, u1000) = k1125
|
||||
/* Map the userspace id down into a VFS id in the mounts's idmapping. */
|
||||
make_kuid(u1000:v1125:r1, u1000) = v1125
|
||||
|
||||
3. Map the kernel id up into a userspace id in the caller's idmapping::
|
||||
3. Map the VFS id up into a userspace id in the caller's idmapping::
|
||||
|
||||
k1125 = vfsuid_into_kuid(v1125)
|
||||
from_kuid(u0:k0:r4294967295, k1125) = u1125
|
||||
|
||||
So ultimately the caller will be reported that the file belongs to ``u1125``
|
||||
|
||||
@@ -79,7 +79,6 @@ context. This is represented by the fs_context structure::
|
||||
unsigned int sb_flags;
|
||||
unsigned int sb_flags_mask;
|
||||
unsigned int s_iflags;
|
||||
unsigned int lsm_flags;
|
||||
enum fs_context_purpose purpose:8;
|
||||
...
|
||||
};
|
||||
|
||||
@@ -36,11 +36,6 @@ config HIGHPROFILE
|
||||
help
|
||||
Use a fast secondary clock to produce profiling information.
|
||||
|
||||
config NO_KERNEL_MSG
|
||||
bool "Suppress Kernel BUG Messages"
|
||||
help
|
||||
Do not output any debug BUG messages within the kernel.
|
||||
|
||||
config BDM_DISABLE
|
||||
bool "Disable BDM signals"
|
||||
depends on COLDFIRE
|
||||
|
||||
@@ -214,7 +214,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP_NF_TARGET_NETMAP=m
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_IP_NF_TARGET_CLUSTERIP=m
|
||||
CONFIG_IP_NF_TARGET_ECN=m
|
||||
CONFIG_IP_NF_TARGET_TTL=m
|
||||
CONFIG_IP_NF_RAW=m
|
||||
@@ -495,6 +494,7 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_RPCSEC_GSS_KRB5=m
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
@@ -621,6 +621,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
|
||||
CONFIG_EARLY_PRINTK=y
|
||||
CONFIG_KUNIT=m
|
||||
CONFIG_KUNIT_ALL_TESTS=m
|
||||
CONFIG_TEST_DHRY=m
|
||||
CONFIG_TEST_MIN_HEAP=m
|
||||
CONFIG_TEST_DIV64=m
|
||||
CONFIG_REED_SOLOMON_TEST=m
|
||||
|
||||
@@ -210,7 +210,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP_NF_TARGET_NETMAP=m
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_IP_NF_TARGET_CLUSTERIP=m
|
||||
CONFIG_IP_NF_TARGET_ECN=m
|
||||
CONFIG_IP_NF_TARGET_TTL=m
|
||||
CONFIG_IP_NF_RAW=m
|
||||
@@ -452,6 +451,7 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_RPCSEC_GSS_KRB5=m
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
@@ -577,6 +577,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
|
||||
CONFIG_EARLY_PRINTK=y
|
||||
CONFIG_KUNIT=m
|
||||
CONFIG_KUNIT_ALL_TESTS=m
|
||||
CONFIG_TEST_DHRY=m
|
||||
CONFIG_TEST_MIN_HEAP=m
|
||||
CONFIG_TEST_DIV64=m
|
||||
CONFIG_REED_SOLOMON_TEST=m
|
||||
|
||||
@@ -217,7 +217,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP_NF_TARGET_NETMAP=m
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_IP_NF_TARGET_CLUSTERIP=m
|
||||
CONFIG_IP_NF_TARGET_ECN=m
|
||||
CONFIG_IP_NF_TARGET_TTL=m
|
||||
CONFIG_IP_NF_RAW=m
|
||||
@@ -472,6 +471,7 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_RPCSEC_GSS_KRB5=m
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
@@ -598,6 +598,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
|
||||
CONFIG_EARLY_PRINTK=y
|
||||
CONFIG_KUNIT=m
|
||||
CONFIG_KUNIT_ALL_TESTS=m
|
||||
CONFIG_TEST_DHRY=m
|
||||
CONFIG_TEST_MIN_HEAP=m
|
||||
CONFIG_TEST_DIV64=m
|
||||
CONFIG_REED_SOLOMON_TEST=m
|
||||
|
||||
@@ -207,7 +207,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP_NF_TARGET_NETMAP=m
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_IP_NF_TARGET_CLUSTERIP=m
|
||||
CONFIG_IP_NF_TARGET_ECN=m
|
||||
CONFIG_IP_NF_TARGET_TTL=m
|
||||
CONFIG_IP_NF_RAW=m
|
||||
@@ -444,6 +443,7 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_RPCSEC_GSS_KRB5=m
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
@@ -569,6 +569,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
|
||||
CONFIG_EARLY_PRINTK=y
|
||||
CONFIG_KUNIT=m
|
||||
CONFIG_KUNIT_ALL_TESTS=m
|
||||
CONFIG_TEST_DHRY=m
|
||||
CONFIG_TEST_MIN_HEAP=m
|
||||
CONFIG_TEST_DIV64=m
|
||||
CONFIG_REED_SOLOMON_TEST=m
|
||||
|
||||
@@ -209,7 +209,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP_NF_TARGET_NETMAP=m
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_IP_NF_TARGET_CLUSTERIP=m
|
||||
CONFIG_IP_NF_TARGET_ECN=m
|
||||
CONFIG_IP_NF_TARGET_TTL=m
|
||||
CONFIG_IP_NF_RAW=m
|
||||
@@ -454,6 +453,7 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_RPCSEC_GSS_KRB5=m
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
@@ -579,6 +579,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
|
||||
CONFIG_EARLY_PRINTK=y
|
||||
CONFIG_KUNIT=m
|
||||
CONFIG_KUNIT_ALL_TESTS=m
|
||||
CONFIG_TEST_DHRY=m
|
||||
CONFIG_TEST_MIN_HEAP=m
|
||||
CONFIG_TEST_DIV64=m
|
||||
CONFIG_REED_SOLOMON_TEST=m
|
||||
|
||||
@@ -208,7 +208,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP_NF_TARGET_NETMAP=m
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_IP_NF_TARGET_CLUSTERIP=m
|
||||
CONFIG_IP_NF_TARGET_ECN=m
|
||||
CONFIG_IP_NF_TARGET_TTL=m
|
||||
CONFIG_IP_NF_RAW=m
|
||||
@@ -474,6 +473,7 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_RPCSEC_GSS_KRB5=m
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
@@ -600,6 +600,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
|
||||
CONFIG_EARLY_PRINTK=y
|
||||
CONFIG_KUNIT=m
|
||||
CONFIG_KUNIT_ALL_TESTS=m
|
||||
CONFIG_TEST_DHRY=m
|
||||
CONFIG_TEST_MIN_HEAP=m
|
||||
CONFIG_TEST_DIV64=m
|
||||
CONFIG_REED_SOLOMON_TEST=m
|
||||
|
||||
@@ -228,7 +228,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP_NF_TARGET_NETMAP=m
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_IP_NF_TARGET_CLUSTERIP=m
|
||||
CONFIG_IP_NF_TARGET_ECN=m
|
||||
CONFIG_IP_NF_TARGET_TTL=m
|
||||
CONFIG_IP_NF_RAW=m
|
||||
@@ -314,7 +313,6 @@ CONFIG_AF_KCM=m
|
||||
# CONFIG_WIRELESS is not set
|
||||
CONFIG_PSAMPLE=m
|
||||
CONFIG_NET_IFE=m
|
||||
CONFIG_PCCARD=y
|
||||
CONFIG_DEVTMPFS=y
|
||||
CONFIG_DEVTMPFS_MOUNT=y
|
||||
CONFIG_TEST_ASYNC_DRIVER_PROBE=m
|
||||
@@ -561,6 +559,7 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_RPCSEC_GSS_KRB5=m
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
@@ -687,6 +686,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
|
||||
CONFIG_EARLY_PRINTK=y
|
||||
CONFIG_KUNIT=m
|
||||
CONFIG_KUNIT_ALL_TESTS=m
|
||||
CONFIG_TEST_DHRY=m
|
||||
CONFIG_TEST_MIN_HEAP=m
|
||||
CONFIG_TEST_DIV64=m
|
||||
CONFIG_REED_SOLOMON_TEST=m
|
||||
|
||||
@@ -206,7 +206,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP_NF_TARGET_NETMAP=m
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_IP_NF_TARGET_CLUSTERIP=m
|
||||
CONFIG_IP_NF_TARGET_ECN=m
|
||||
CONFIG_IP_NF_TARGET_TTL=m
|
||||
CONFIG_IP_NF_RAW=m
|
||||
@@ -443,6 +442,7 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_RPCSEC_GSS_KRB5=m
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
@@ -568,6 +568,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
|
||||
CONFIG_EARLY_PRINTK=y
|
||||
CONFIG_KUNIT=m
|
||||
CONFIG_KUNIT_ALL_TESTS=m
|
||||
CONFIG_TEST_DHRY=m
|
||||
CONFIG_TEST_MIN_HEAP=m
|
||||
CONFIG_TEST_DIV64=m
|
||||
CONFIG_REED_SOLOMON_TEST=m
|
||||
|
||||
@@ -207,7 +207,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP_NF_TARGET_NETMAP=m
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_IP_NF_TARGET_CLUSTERIP=m
|
||||
CONFIG_IP_NF_TARGET_ECN=m
|
||||
CONFIG_IP_NF_TARGET_TTL=m
|
||||
CONFIG_IP_NF_RAW=m
|
||||
@@ -444,6 +443,7 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_RPCSEC_GSS_KRB5=m
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
@@ -569,6 +569,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
|
||||
CONFIG_EARLY_PRINTK=y
|
||||
CONFIG_KUNIT=m
|
||||
CONFIG_KUNIT_ALL_TESTS=m
|
||||
CONFIG_TEST_DHRY=m
|
||||
CONFIG_TEST_MIN_HEAP=m
|
||||
CONFIG_TEST_DIV64=m
|
||||
CONFIG_REED_SOLOMON_TEST=m
|
||||
|
||||
@@ -208,7 +208,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP_NF_TARGET_NETMAP=m
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_IP_NF_TARGET_CLUSTERIP=m
|
||||
CONFIG_IP_NF_TARGET_ECN=m
|
||||
CONFIG_IP_NF_TARGET_TTL=m
|
||||
CONFIG_IP_NF_RAW=m
|
||||
@@ -461,6 +460,7 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_RPCSEC_GSS_KRB5=m
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
@@ -587,6 +587,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
|
||||
CONFIG_EARLY_PRINTK=y
|
||||
CONFIG_KUNIT=m
|
||||
CONFIG_KUNIT_ALL_TESTS=m
|
||||
CONFIG_TEST_DHRY=m
|
||||
CONFIG_TEST_MIN_HEAP=m
|
||||
CONFIG_TEST_DIV64=m
|
||||
CONFIG_REED_SOLOMON_TEST=m
|
||||
|
||||
@@ -204,7 +204,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP_NF_TARGET_NETMAP=m
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_IP_NF_TARGET_CLUSTERIP=m
|
||||
CONFIG_IP_NF_TARGET_ECN=m
|
||||
CONFIG_IP_NF_TARGET_TTL=m
|
||||
CONFIG_IP_NF_RAW=m
|
||||
@@ -443,6 +442,7 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_RPCSEC_GSS_KRB5=m
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
@@ -567,6 +567,7 @@ CONFIG_TEST_LOCKUP=m
|
||||
CONFIG_WW_MUTEX_SELFTEST=m
|
||||
CONFIG_KUNIT=m
|
||||
CONFIG_KUNIT_ALL_TESTS=m
|
||||
CONFIG_TEST_DHRY=m
|
||||
CONFIG_TEST_MIN_HEAP=m
|
||||
CONFIG_TEST_DIV64=m
|
||||
CONFIG_REED_SOLOMON_TEST=m
|
||||
|
||||
@@ -204,7 +204,6 @@ CONFIG_IP_NF_TARGET_MASQUERADE=m
|
||||
CONFIG_IP_NF_TARGET_NETMAP=m
|
||||
CONFIG_IP_NF_TARGET_REDIRECT=m
|
||||
CONFIG_IP_NF_MANGLE=m
|
||||
CONFIG_IP_NF_TARGET_CLUSTERIP=m
|
||||
CONFIG_IP_NF_TARGET_ECN=m
|
||||
CONFIG_IP_NF_TARGET_TTL=m
|
||||
CONFIG_IP_NF_RAW=m
|
||||
@@ -442,6 +441,7 @@ CONFIG_NFS_V4=m
|
||||
CONFIG_NFS_SWAP=y
|
||||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_NFSD=m
|
||||
CONFIG_RPCSEC_GSS_KRB5=m
|
||||
CONFIG_CIFS=m
|
||||
# CONFIG_CIFS_STATS2 is not set
|
||||
# CONFIG_CIFS_DEBUG is not set
|
||||
@@ -567,6 +567,7 @@ CONFIG_WW_MUTEX_SELFTEST=m
|
||||
CONFIG_EARLY_PRINTK=y
|
||||
CONFIG_KUNIT=m
|
||||
CONFIG_KUNIT_ALL_TESTS=m
|
||||
CONFIG_TEST_DHRY=m
|
||||
CONFIG_TEST_MIN_HEAP=m
|
||||
CONFIG_TEST_DIV64=m
|
||||
CONFIG_REED_SOLOMON_TEST=m
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/reboot.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
@@ -96,9 +96,6 @@ static inline struct thread_info *current_thread_info(void)
|
||||
/* work to do on interrupt/exception return */
|
||||
#define _TIF_WORK_MASK 0x0000FFFE
|
||||
|
||||
/* work to do on any return to u-space */
|
||||
# define _TIF_ALLWORK_MASK 0x0000FFFF
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _ASM_NIOS2_THREAD_INFO_H */
|
||||
|
||||
@@ -892,20 +892,19 @@ static struct miscdevice sgx_dev_provision = {
|
||||
int sgx_set_attribute(unsigned long *allowed_attributes,
|
||||
unsigned int attribute_fd)
|
||||
{
|
||||
struct file *file;
|
||||
struct fd f = fdget(attribute_fd);
|
||||
|
||||
file = fget(attribute_fd);
|
||||
if (!file)
|
||||
if (!f.file)
|
||||
return -EINVAL;
|
||||
|
||||
if (file->f_op != &sgx_provision_fops) {
|
||||
fput(file);
|
||||
if (f.file->f_op != &sgx_provision_fops) {
|
||||
fdput(f);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*allowed_attributes |= SGX_ATTR_PROVISIONKEY;
|
||||
|
||||
fput(file);
|
||||
fdput(f);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(sgx_set_attribute);
|
||||
|
||||
+14
-12
@@ -1767,18 +1767,20 @@ int sev_vm_move_enc_context_from(struct kvm *kvm, unsigned int source_fd)
|
||||
{
|
||||
struct kvm_sev_info *dst_sev = &to_kvm_svm(kvm)->sev_info;
|
||||
struct kvm_sev_info *src_sev, *cg_cleanup_sev;
|
||||
struct file *source_kvm_file;
|
||||
struct fd f = fdget(source_fd);
|
||||
struct kvm *source_kvm;
|
||||
bool charged = false;
|
||||
int ret;
|
||||
|
||||
source_kvm_file = fget(source_fd);
|
||||
if (!file_is_kvm(source_kvm_file)) {
|
||||
if (!f.file)
|
||||
return -EBADF;
|
||||
|
||||
if (!file_is_kvm(f.file)) {
|
||||
ret = -EBADF;
|
||||
goto out_fput;
|
||||
}
|
||||
|
||||
source_kvm = source_kvm_file->private_data;
|
||||
source_kvm = f.file->private_data;
|
||||
ret = sev_lock_two_vms(kvm, source_kvm);
|
||||
if (ret)
|
||||
goto out_fput;
|
||||
@@ -1828,8 +1830,7 @@ out_dst_cgroup:
|
||||
out_unlock:
|
||||
sev_unlock_two_vms(kvm, source_kvm);
|
||||
out_fput:
|
||||
if (source_kvm_file)
|
||||
fput(source_kvm_file);
|
||||
fdput(f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2046,18 +2047,20 @@ failed:
|
||||
|
||||
int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
|
||||
{
|
||||
struct file *source_kvm_file;
|
||||
struct fd f = fdget(source_fd);
|
||||
struct kvm *source_kvm;
|
||||
struct kvm_sev_info *source_sev, *mirror_sev;
|
||||
int ret;
|
||||
|
||||
source_kvm_file = fget(source_fd);
|
||||
if (!file_is_kvm(source_kvm_file)) {
|
||||
if (!f.file)
|
||||
return -EBADF;
|
||||
|
||||
if (!file_is_kvm(f.file)) {
|
||||
ret = -EBADF;
|
||||
goto e_source_fput;
|
||||
}
|
||||
|
||||
source_kvm = source_kvm_file->private_data;
|
||||
source_kvm = f.file->private_data;
|
||||
ret = sev_lock_two_vms(kvm, source_kvm);
|
||||
if (ret)
|
||||
goto e_source_fput;
|
||||
@@ -2103,8 +2106,7 @@ int sev_vm_copy_enc_context_from(struct kvm *kvm, unsigned int source_fd)
|
||||
e_unlock:
|
||||
sev_unlock_two_vms(kvm, source_kvm);
|
||||
e_source_fput:
|
||||
if (source_kvm_file)
|
||||
fput(source_kvm_file);
|
||||
fdput(f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,11 +14,6 @@
|
||||
#define to_nubus_board(d) container_of(d, struct nubus_board, dev)
|
||||
#define to_nubus_driver(d) container_of(d, struct nubus_driver, driver)
|
||||
|
||||
static int nubus_bus_match(struct device *dev, struct device_driver *driver)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int nubus_device_probe(struct device *dev)
|
||||
{
|
||||
struct nubus_driver *ndrv = to_nubus_driver(dev->driver);
|
||||
@@ -39,7 +34,6 @@ static void nubus_device_remove(struct device *dev)
|
||||
|
||||
struct bus_type nubus_bus_type = {
|
||||
.name = "nubus",
|
||||
.match = nubus_bus_match,
|
||||
.probe = nubus_device_probe,
|
||||
.remove = nubus_device_remove,
|
||||
};
|
||||
|
||||
@@ -185,10 +185,6 @@ static struct xattr_handler v9fs_xattr_security_handler = {
|
||||
const struct xattr_handler *v9fs_xattr_handlers[] = {
|
||||
&v9fs_xattr_user_handler,
|
||||
&v9fs_xattr_trusted_handler,
|
||||
#ifdef CONFIG_FS_POSIX_ACL
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
#endif
|
||||
#ifdef CONFIG_9P_FS_SECURITY
|
||||
&v9fs_xattr_security_handler,
|
||||
#endif
|
||||
|
||||
@@ -47,6 +47,7 @@ int setattr_should_drop_sgid(struct mnt_idmap *idmap,
|
||||
return ATTR_KILL_SGID;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(setattr_should_drop_sgid);
|
||||
|
||||
/**
|
||||
* setattr_should_drop_suidgid - determine whether the set{g,u}id bit needs to
|
||||
|
||||
@@ -444,10 +444,6 @@ static const struct xattr_handler btrfs_btrfs_xattr_handler = {
|
||||
|
||||
const struct xattr_handler *btrfs_xattr_handlers[] = {
|
||||
&btrfs_security_xattr_handler,
|
||||
#ifdef CONFIG_BTRFS_FS_POSIX_ACL
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
#endif
|
||||
&btrfs_trusted_xattr_handler,
|
||||
&btrfs_user_xattr_handler,
|
||||
&btrfs_btrfs_xattr_handler,
|
||||
|
||||
+3
-6
@@ -2581,7 +2581,7 @@ int block_truncate_page(struct address_space *mapping,
|
||||
struct inode *inode = mapping->host;
|
||||
struct page *page;
|
||||
struct buffer_head *bh;
|
||||
int err;
|
||||
int err = 0;
|
||||
|
||||
blocksize = i_blocksize(inode);
|
||||
length = offset & (blocksize - 1);
|
||||
@@ -2594,9 +2594,8 @@ int block_truncate_page(struct address_space *mapping,
|
||||
iblock = (sector_t)index << (PAGE_SHIFT - inode->i_blkbits);
|
||||
|
||||
page = grab_cache_page(mapping, index);
|
||||
err = -ENOMEM;
|
||||
if (!page)
|
||||
goto out;
|
||||
return -ENOMEM;
|
||||
|
||||
if (!page_has_buffers(page))
|
||||
create_empty_buffers(page, blocksize, 0);
|
||||
@@ -2610,7 +2609,6 @@ int block_truncate_page(struct address_space *mapping,
|
||||
pos += blocksize;
|
||||
}
|
||||
|
||||
err = 0;
|
||||
if (!buffer_mapped(bh)) {
|
||||
WARN_ON(bh->b_size != blocksize);
|
||||
err = get_block(inode, iblock, bh, 0);
|
||||
@@ -2634,12 +2632,11 @@ int block_truncate_page(struct address_space *mapping,
|
||||
|
||||
zero_user(page, offset, length);
|
||||
mark_buffer_dirty(bh);
|
||||
err = 0;
|
||||
|
||||
unlock:
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
out:
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(block_truncate_page);
|
||||
|
||||
@@ -1411,10 +1411,6 @@ void ceph_release_acl_sec_ctx(struct ceph_acl_sec_ctx *as_ctx)
|
||||
* attributes are handled directly.
|
||||
*/
|
||||
const struct xattr_handler *ceph_xattr_handlers[] = {
|
||||
#ifdef CONFIG_CEPH_FS_POSIX_ACL
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
#endif
|
||||
&ceph_other_xattr_handler,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -487,9 +487,5 @@ const struct xattr_handler *cifs_xattr_handlers[] = {
|
||||
&smb3_ntsd_xattr_handler, /* alias for above since avoiding "cifs" */
|
||||
&cifs_cifs_ntsd_full_xattr_handler,
|
||||
&smb3_ntsd_full_xattr_handler, /* alias for above since avoiding "cifs" */
|
||||
#ifdef CONFIG_FS_POSIX_ACL
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
+2
-7
@@ -1599,12 +1599,6 @@ static int configfs_dir_close(struct inode *inode, struct file *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Relationship between s_mode and the DT_xxx types */
|
||||
static inline unsigned char dt_type(struct configfs_dirent *sd)
|
||||
{
|
||||
return (sd->s_mode >> 12) & 15;
|
||||
}
|
||||
|
||||
static int configfs_readdir(struct file *file, struct dir_context *ctx)
|
||||
{
|
||||
struct dentry *dentry = file->f_path.dentry;
|
||||
@@ -1654,7 +1648,8 @@ static int configfs_readdir(struct file *file, struct dir_context *ctx)
|
||||
name = configfs_get_name(next);
|
||||
len = strlen(name);
|
||||
|
||||
if (!dir_emit(ctx, name, len, ino, dt_type(next)))
|
||||
if (!dir_emit(ctx, name, len, ino,
|
||||
fs_umode_to_dtype(next->s_mode)))
|
||||
return 0;
|
||||
|
||||
spin_lock(&configfs_dirent_lock);
|
||||
|
||||
+1
-19
@@ -72,24 +72,6 @@ static struct ctl_table pty_table[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static struct ctl_table pty_kern_table[] = {
|
||||
{
|
||||
.procname = "pty",
|
||||
.mode = 0555,
|
||||
.child = pty_table,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct ctl_table pty_root_table[] = {
|
||||
{
|
||||
.procname = "kernel",
|
||||
.mode = 0555,
|
||||
.child = pty_kern_table,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
struct pts_mount_opts {
|
||||
int setuid;
|
||||
int setgid;
|
||||
@@ -630,7 +612,7 @@ static int __init init_devpts_fs(void)
|
||||
{
|
||||
int err = register_filesystem(&devpts_fs_type);
|
||||
if (!err) {
|
||||
register_sysctl_table(pty_root_table);
|
||||
register_sysctl("kernel/pty", pty_table);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
+2
-7
@@ -86,7 +86,6 @@ struct dio_submit {
|
||||
sector_t final_block_in_request;/* doesn't change */
|
||||
int boundary; /* prev block is at a boundary */
|
||||
get_block_t *get_block; /* block mapping function */
|
||||
dio_submit_t *submit_io; /* IO submition function */
|
||||
|
||||
loff_t logical_offset_in_bio; /* current first logical block in bio */
|
||||
sector_t final_block_in_bio; /* current final block in bio + 1 */
|
||||
@@ -431,10 +430,7 @@ static inline void dio_bio_submit(struct dio *dio, struct dio_submit *sdio)
|
||||
|
||||
dio->bio_disk = bio->bi_bdev->bd_disk;
|
||||
|
||||
if (sdio->submit_io)
|
||||
sdio->submit_io(bio, dio->inode, sdio->logical_offset_in_bio);
|
||||
else
|
||||
submit_bio(bio);
|
||||
submit_bio(bio);
|
||||
|
||||
sdio->bio = NULL;
|
||||
sdio->boundary = 0;
|
||||
@@ -1098,7 +1094,7 @@ static inline int drop_refcount(struct dio *dio)
|
||||
ssize_t __blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
|
||||
struct block_device *bdev, struct iov_iter *iter,
|
||||
get_block_t get_block, dio_iodone_t end_io,
|
||||
dio_submit_t submit_io, int flags)
|
||||
int flags)
|
||||
{
|
||||
unsigned i_blkbits = READ_ONCE(inode->i_blkbits);
|
||||
unsigned blkbits = i_blkbits;
|
||||
@@ -1215,7 +1211,6 @@ ssize_t __blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
|
||||
|
||||
sdio.get_block = get_block;
|
||||
dio->end_io = end_io;
|
||||
sdio.submit_io = submit_io;
|
||||
sdio.final_block_in_bio = -1;
|
||||
sdio.next_block_for_io = -1;
|
||||
|
||||
|
||||
@@ -1210,10 +1210,6 @@ static const struct xattr_handler ecryptfs_xattr_handler = {
|
||||
};
|
||||
|
||||
const struct xattr_handler *ecryptfs_xattr_handlers[] = {
|
||||
#ifdef CONFIG_FS_POSIX_ACL
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
#endif
|
||||
&ecryptfs_xattr_handler,
|
||||
NULL
|
||||
};
|
||||
|
||||
+47
-34
@@ -27,11 +27,15 @@ void erofs_put_metabuf(struct erofs_buf *buf)
|
||||
buf->page = NULL;
|
||||
}
|
||||
|
||||
void *erofs_bread(struct erofs_buf *buf, struct inode *inode,
|
||||
erofs_blk_t blkaddr, enum erofs_kmap_type type)
|
||||
/*
|
||||
* Derive the block size from inode->i_blkbits to make compatible with
|
||||
* anonymous inode in fscache mode.
|
||||
*/
|
||||
void *erofs_bread(struct erofs_buf *buf, erofs_blk_t blkaddr,
|
||||
enum erofs_kmap_type type)
|
||||
{
|
||||
struct address_space *const mapping = inode->i_mapping;
|
||||
erofs_off_t offset = blknr_to_addr(blkaddr);
|
||||
struct inode *inode = buf->inode;
|
||||
erofs_off_t offset = (erofs_off_t)blkaddr << inode->i_blkbits;
|
||||
pgoff_t index = offset >> PAGE_SHIFT;
|
||||
struct page *page = buf->page;
|
||||
struct folio *folio;
|
||||
@@ -41,7 +45,7 @@ void *erofs_bread(struct erofs_buf *buf, struct inode *inode,
|
||||
erofs_put_metabuf(buf);
|
||||
|
||||
nofs_flag = memalloc_nofs_save();
|
||||
folio = read_cache_folio(mapping, index, NULL, NULL);
|
||||
folio = read_cache_folio(inode->i_mapping, index, NULL, NULL);
|
||||
memalloc_nofs_restore(nofs_flag);
|
||||
if (IS_ERR(folio))
|
||||
return folio;
|
||||
@@ -63,14 +67,19 @@ void *erofs_bread(struct erofs_buf *buf, struct inode *inode,
|
||||
return buf->base + (offset & ~PAGE_MASK);
|
||||
}
|
||||
|
||||
void erofs_init_metabuf(struct erofs_buf *buf, struct super_block *sb)
|
||||
{
|
||||
if (erofs_is_fscache_mode(sb))
|
||||
buf->inode = EROFS_SB(sb)->s_fscache->inode;
|
||||
else
|
||||
buf->inode = sb->s_bdev->bd_inode;
|
||||
}
|
||||
|
||||
void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb,
|
||||
erofs_blk_t blkaddr, enum erofs_kmap_type type)
|
||||
{
|
||||
if (erofs_is_fscache_mode(sb))
|
||||
return erofs_bread(buf, EROFS_SB(sb)->s_fscache->inode,
|
||||
blkaddr, type);
|
||||
|
||||
return erofs_bread(buf, sb->s_bdev->bd_inode, blkaddr, type);
|
||||
erofs_init_metabuf(buf, sb);
|
||||
return erofs_bread(buf, blkaddr, type);
|
||||
}
|
||||
|
||||
static int erofs_map_blocks_flatmode(struct inode *inode,
|
||||
@@ -79,33 +88,32 @@ static int erofs_map_blocks_flatmode(struct inode *inode,
|
||||
erofs_blk_t nblocks, lastblk;
|
||||
u64 offset = map->m_la;
|
||||
struct erofs_inode *vi = EROFS_I(inode);
|
||||
struct super_block *sb = inode->i_sb;
|
||||
bool tailendpacking = (vi->datalayout == EROFS_INODE_FLAT_INLINE);
|
||||
|
||||
nblocks = DIV_ROUND_UP(inode->i_size, EROFS_BLKSIZ);
|
||||
nblocks = erofs_iblks(inode);
|
||||
lastblk = nblocks - tailendpacking;
|
||||
|
||||
/* there is no hole in flatmode */
|
||||
map->m_flags = EROFS_MAP_MAPPED;
|
||||
if (offset < blknr_to_addr(lastblk)) {
|
||||
map->m_pa = blknr_to_addr(vi->raw_blkaddr) + map->m_la;
|
||||
map->m_plen = blknr_to_addr(lastblk) - offset;
|
||||
if (offset < erofs_pos(sb, lastblk)) {
|
||||
map->m_pa = erofs_pos(sb, vi->raw_blkaddr) + map->m_la;
|
||||
map->m_plen = erofs_pos(sb, lastblk) - offset;
|
||||
} else if (tailendpacking) {
|
||||
map->m_pa = erofs_iloc(inode) + vi->inode_isize +
|
||||
vi->xattr_isize + erofs_blkoff(offset);
|
||||
vi->xattr_isize + erofs_blkoff(sb, offset);
|
||||
map->m_plen = inode->i_size - offset;
|
||||
|
||||
/* inline data should be located in the same meta block */
|
||||
if (erofs_blkoff(map->m_pa) + map->m_plen > EROFS_BLKSIZ) {
|
||||
erofs_err(inode->i_sb,
|
||||
"inline data cross block boundary @ nid %llu",
|
||||
if (erofs_blkoff(sb, map->m_pa) + map->m_plen > sb->s_blocksize) {
|
||||
erofs_err(sb, "inline data cross block boundary @ nid %llu",
|
||||
vi->nid);
|
||||
DBG_BUGON(1);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
map->m_flags |= EROFS_MAP_META;
|
||||
} else {
|
||||
erofs_err(inode->i_sb,
|
||||
"internal error @ nid: %llu (size %llu), m_la 0x%llx",
|
||||
erofs_err(sb, "internal error @ nid: %llu (size %llu), m_la 0x%llx",
|
||||
vi->nid, inode->i_size, map->m_la);
|
||||
DBG_BUGON(1);
|
||||
return -EIO;
|
||||
@@ -148,29 +156,29 @@ int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map)
|
||||
pos = ALIGN(erofs_iloc(inode) + vi->inode_isize +
|
||||
vi->xattr_isize, unit) + unit * chunknr;
|
||||
|
||||
kaddr = erofs_read_metabuf(&buf, sb, erofs_blknr(pos), EROFS_KMAP);
|
||||
kaddr = erofs_read_metabuf(&buf, sb, erofs_blknr(sb, pos), EROFS_KMAP);
|
||||
if (IS_ERR(kaddr)) {
|
||||
err = PTR_ERR(kaddr);
|
||||
goto out;
|
||||
}
|
||||
map->m_la = chunknr << vi->chunkbits;
|
||||
map->m_plen = min_t(erofs_off_t, 1UL << vi->chunkbits,
|
||||
roundup(inode->i_size - map->m_la, EROFS_BLKSIZ));
|
||||
round_up(inode->i_size - map->m_la, sb->s_blocksize));
|
||||
|
||||
/* handle block map */
|
||||
if (!(vi->chunkformat & EROFS_CHUNK_FORMAT_INDEXES)) {
|
||||
__le32 *blkaddr = kaddr + erofs_blkoff(pos);
|
||||
__le32 *blkaddr = kaddr + erofs_blkoff(sb, pos);
|
||||
|
||||
if (le32_to_cpu(*blkaddr) == EROFS_NULL_ADDR) {
|
||||
map->m_flags = 0;
|
||||
} else {
|
||||
map->m_pa = blknr_to_addr(le32_to_cpu(*blkaddr));
|
||||
map->m_pa = erofs_pos(sb, le32_to_cpu(*blkaddr));
|
||||
map->m_flags = EROFS_MAP_MAPPED;
|
||||
}
|
||||
goto out_unlock;
|
||||
}
|
||||
/* parse chunk indexes */
|
||||
idx = kaddr + erofs_blkoff(pos);
|
||||
idx = kaddr + erofs_blkoff(sb, pos);
|
||||
switch (le32_to_cpu(idx->blkaddr)) {
|
||||
case EROFS_NULL_ADDR:
|
||||
map->m_flags = 0;
|
||||
@@ -178,7 +186,7 @@ int erofs_map_blocks(struct inode *inode, struct erofs_map_blocks *map)
|
||||
default:
|
||||
map->m_deviceid = le16_to_cpu(idx->device_id) &
|
||||
EROFS_SB(sb)->device_id_mask;
|
||||
map->m_pa = blknr_to_addr(le32_to_cpu(idx->blkaddr));
|
||||
map->m_pa = erofs_pos(sb, le32_to_cpu(idx->blkaddr));
|
||||
map->m_flags = EROFS_MAP_MAPPED;
|
||||
break;
|
||||
}
|
||||
@@ -197,7 +205,6 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
|
||||
struct erofs_device_info *dif;
|
||||
int id;
|
||||
|
||||
/* primary device by default */
|
||||
map->m_bdev = sb->s_bdev;
|
||||
map->m_daxdev = EROFS_SB(sb)->dax_dev;
|
||||
map->m_dax_part_off = EROFS_SB(sb)->dax_part_off;
|
||||
@@ -210,20 +217,25 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
|
||||
up_read(&devs->rwsem);
|
||||
return -ENODEV;
|
||||
}
|
||||
if (devs->flatdev) {
|
||||
map->m_pa += erofs_pos(sb, dif->mapped_blkaddr);
|
||||
up_read(&devs->rwsem);
|
||||
return 0;
|
||||
}
|
||||
map->m_bdev = dif->bdev;
|
||||
map->m_daxdev = dif->dax_dev;
|
||||
map->m_dax_part_off = dif->dax_part_off;
|
||||
map->m_fscache = dif->fscache;
|
||||
up_read(&devs->rwsem);
|
||||
} else if (devs->extra_devices) {
|
||||
} else if (devs->extra_devices && !devs->flatdev) {
|
||||
down_read(&devs->rwsem);
|
||||
idr_for_each_entry(&devs->tree, dif, id) {
|
||||
erofs_off_t startoff, length;
|
||||
|
||||
if (!dif->mapped_blkaddr)
|
||||
continue;
|
||||
startoff = blknr_to_addr(dif->mapped_blkaddr);
|
||||
length = blknr_to_addr(dif->blocks);
|
||||
startoff = erofs_pos(sb, dif->mapped_blkaddr);
|
||||
length = erofs_pos(sb, dif->blocks);
|
||||
|
||||
if (map->m_pa >= startoff &&
|
||||
map->m_pa < startoff + length) {
|
||||
@@ -244,6 +256,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
|
||||
unsigned int flags, struct iomap *iomap, struct iomap *srcmap)
|
||||
{
|
||||
int ret;
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct erofs_map_blocks map;
|
||||
struct erofs_map_dev mdev;
|
||||
|
||||
@@ -258,7 +271,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
|
||||
.m_deviceid = map.m_deviceid,
|
||||
.m_pa = map.m_pa,
|
||||
};
|
||||
ret = erofs_map_dev(inode->i_sb, &mdev);
|
||||
ret = erofs_map_dev(sb, &mdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -284,11 +297,11 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
|
||||
struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
|
||||
|
||||
iomap->type = IOMAP_INLINE;
|
||||
ptr = erofs_read_metabuf(&buf, inode->i_sb,
|
||||
erofs_blknr(mdev.m_pa), EROFS_KMAP);
|
||||
ptr = erofs_read_metabuf(&buf, sb,
|
||||
erofs_blknr(sb, mdev.m_pa), EROFS_KMAP);
|
||||
if (IS_ERR(ptr))
|
||||
return PTR_ERR(ptr);
|
||||
iomap->inline_data = ptr + erofs_blkoff(mdev.m_pa);
|
||||
iomap->inline_data = ptr + erofs_blkoff(sb, mdev.m_pa);
|
||||
iomap->private = buf.base;
|
||||
} else {
|
||||
iomap->type = IOMAP_MAPPED;
|
||||
|
||||
@@ -42,7 +42,7 @@ int z_erofs_load_lz4_config(struct super_block *sb,
|
||||
if (!sbi->lz4.max_pclusterblks) {
|
||||
sbi->lz4.max_pclusterblks = 1; /* reserved case */
|
||||
} else if (sbi->lz4.max_pclusterblks >
|
||||
Z_EROFS_PCLUSTER_MAX_SIZE / EROFS_BLKSIZ) {
|
||||
erofs_blknr(sb, Z_EROFS_PCLUSTER_MAX_SIZE)) {
|
||||
erofs_err(sb, "too large lz4 pclusterblks %u",
|
||||
sbi->lz4.max_pclusterblks);
|
||||
return -EINVAL;
|
||||
@@ -221,13 +221,13 @@ static int z_erofs_lz4_decompress_mem(struct z_erofs_lz4_decompress_ctx *ctx,
|
||||
support_0padding = true;
|
||||
ret = z_erofs_fixup_insize(rq, headpage + rq->pageofs_in,
|
||||
min_t(unsigned int, rq->inputsize,
|
||||
EROFS_BLKSIZ - rq->pageofs_in));
|
||||
rq->sb->s_blocksize - rq->pageofs_in));
|
||||
if (ret) {
|
||||
kunmap_atomic(headpage);
|
||||
return ret;
|
||||
}
|
||||
may_inplace = !((rq->pageofs_in + rq->inputsize) &
|
||||
(EROFS_BLKSIZ - 1));
|
||||
(rq->sb->s_blocksize - 1));
|
||||
}
|
||||
|
||||
inputmargin = rq->pageofs_in;
|
||||
|
||||
@@ -166,8 +166,8 @@ int z_erofs_lzma_decompress(struct z_erofs_decompress_req *rq,
|
||||
/* 1. get the exact LZMA compressed size */
|
||||
kin = kmap(*rq->in);
|
||||
err = z_erofs_fixup_insize(rq, kin + rq->pageofs_in,
|
||||
min_t(unsigned int, rq->inputsize,
|
||||
EROFS_BLKSIZ - rq->pageofs_in));
|
||||
min_t(unsigned int, rq->inputsize,
|
||||
rq->sb->s_blocksize - rq->pageofs_in));
|
||||
if (err) {
|
||||
kunmap(*rq->in);
|
||||
return err;
|
||||
|
||||
+12
-13
@@ -50,44 +50,43 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx)
|
||||
{
|
||||
struct inode *dir = file_inode(f);
|
||||
struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
|
||||
struct super_block *sb = dir->i_sb;
|
||||
unsigned long bsz = sb->s_blocksize;
|
||||
const size_t dirsize = i_size_read(dir);
|
||||
unsigned int i = ctx->pos / EROFS_BLKSIZ;
|
||||
unsigned int ofs = ctx->pos % EROFS_BLKSIZ;
|
||||
unsigned int i = erofs_blknr(sb, ctx->pos);
|
||||
unsigned int ofs = erofs_blkoff(sb, ctx->pos);
|
||||
int err = 0;
|
||||
bool initial = true;
|
||||
|
||||
buf.inode = dir;
|
||||
while (ctx->pos < dirsize) {
|
||||
struct erofs_dirent *de;
|
||||
unsigned int nameoff, maxsize;
|
||||
|
||||
de = erofs_bread(&buf, dir, i, EROFS_KMAP);
|
||||
de = erofs_bread(&buf, i, EROFS_KMAP);
|
||||
if (IS_ERR(de)) {
|
||||
erofs_err(dir->i_sb,
|
||||
"fail to readdir of logical block %u of nid %llu",
|
||||
erofs_err(sb, "fail to readdir of logical block %u of nid %llu",
|
||||
i, EROFS_I(dir)->nid);
|
||||
err = PTR_ERR(de);
|
||||
break;
|
||||
}
|
||||
|
||||
nameoff = le16_to_cpu(de->nameoff);
|
||||
if (nameoff < sizeof(struct erofs_dirent) ||
|
||||
nameoff >= EROFS_BLKSIZ) {
|
||||
erofs_err(dir->i_sb,
|
||||
"invalid de[0].nameoff %u @ nid %llu",
|
||||
if (nameoff < sizeof(struct erofs_dirent) || nameoff >= bsz) {
|
||||
erofs_err(sb, "invalid de[0].nameoff %u @ nid %llu",
|
||||
nameoff, EROFS_I(dir)->nid);
|
||||
err = -EFSCORRUPTED;
|
||||
break;
|
||||
}
|
||||
|
||||
maxsize = min_t(unsigned int,
|
||||
dirsize - ctx->pos + ofs, EROFS_BLKSIZ);
|
||||
maxsize = min_t(unsigned int, dirsize - ctx->pos + ofs, bsz);
|
||||
|
||||
/* search dirents at the arbitrary position */
|
||||
if (initial) {
|
||||
initial = false;
|
||||
|
||||
ofs = roundup(ofs, sizeof(struct erofs_dirent));
|
||||
ctx->pos = blknr_to_addr(i) + ofs;
|
||||
ctx->pos = erofs_pos(sb, i) + ofs;
|
||||
if (ofs >= nameoff)
|
||||
goto skip_this;
|
||||
}
|
||||
@@ -97,7 +96,7 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx)
|
||||
if (err)
|
||||
break;
|
||||
skip_this:
|
||||
ctx->pos = blknr_to_addr(i) + maxsize;
|
||||
ctx->pos = erofs_pos(sb, i) + maxsize;
|
||||
++i;
|
||||
ofs = 0;
|
||||
}
|
||||
|
||||
+85
-89
@@ -27,6 +27,7 @@
|
||||
#define EROFS_FEATURE_INCOMPAT_ZTAILPACKING 0x00000010
|
||||
#define EROFS_FEATURE_INCOMPAT_FRAGMENTS 0x00000020
|
||||
#define EROFS_FEATURE_INCOMPAT_DEDUPE 0x00000020
|
||||
#define EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES 0x00000040
|
||||
#define EROFS_ALL_FEATURE_INCOMPAT \
|
||||
(EROFS_FEATURE_INCOMPAT_ZERO_PADDING | \
|
||||
EROFS_FEATURE_INCOMPAT_COMPR_CFGS | \
|
||||
@@ -36,7 +37,8 @@
|
||||
EROFS_FEATURE_INCOMPAT_COMPR_HEAD2 | \
|
||||
EROFS_FEATURE_INCOMPAT_ZTAILPACKING | \
|
||||
EROFS_FEATURE_INCOMPAT_FRAGMENTS | \
|
||||
EROFS_FEATURE_INCOMPAT_DEDUPE)
|
||||
EROFS_FEATURE_INCOMPAT_DEDUPE | \
|
||||
EROFS_FEATURE_INCOMPAT_XATTR_PREFIXES)
|
||||
|
||||
#define EROFS_SB_EXTSLOT_SIZE 16
|
||||
|
||||
@@ -53,7 +55,7 @@ struct erofs_super_block {
|
||||
__le32 magic; /* file system magic number */
|
||||
__le32 checksum; /* crc32c(super_block) */
|
||||
__le32 feature_compat;
|
||||
__u8 blkszbits; /* support block_size == PAGE_SIZE only */
|
||||
__u8 blkszbits; /* filesystem block size in bit shift */
|
||||
__u8 sb_extslots; /* superblock size = 128 + sb_extslots * 16 */
|
||||
|
||||
__le16 root_nid; /* nid of root directory */
|
||||
@@ -75,49 +77,46 @@ struct erofs_super_block {
|
||||
} __packed u1;
|
||||
__le16 extra_devices; /* # of devices besides the primary device */
|
||||
__le16 devt_slotoff; /* startoff = devt_slotoff * devt_slotsize */
|
||||
__u8 reserved[6];
|
||||
__u8 dirblkbits; /* directory block size in bit shift */
|
||||
__u8 xattr_prefix_count; /* # of long xattr name prefixes */
|
||||
__le32 xattr_prefix_start; /* start of long xattr prefixes */
|
||||
__le64 packed_nid; /* nid of the special packed inode */
|
||||
__u8 reserved2[24];
|
||||
};
|
||||
|
||||
/*
|
||||
* erofs inode datalayout (i_format in on-disk inode):
|
||||
* EROFS inode datalayout (i_format in on-disk inode):
|
||||
* 0 - uncompressed flat inode without tail-packing inline data:
|
||||
* inode, [xattrs], ... | ... | no-holed data
|
||||
* 1 - compressed inode with non-compact indexes:
|
||||
* inode, [xattrs], [map_header], extents ... | ...
|
||||
* 2 - uncompressed flat inode with tail-packing inline data:
|
||||
* inode, [xattrs], tailpacking data, ... | ... | no-holed data
|
||||
* 3 - compressed inode with compact indexes:
|
||||
* inode, [xattrs], map_header, extents ... | ...
|
||||
* 4 - chunk-based inode with (optional) multi-device support:
|
||||
* inode, [xattrs], chunk indexes ... | ...
|
||||
* 5~7 - reserved
|
||||
*/
|
||||
enum {
|
||||
EROFS_INODE_FLAT_PLAIN = 0,
|
||||
EROFS_INODE_FLAT_COMPRESSION_LEGACY = 1,
|
||||
EROFS_INODE_COMPRESSED_FULL = 1,
|
||||
EROFS_INODE_FLAT_INLINE = 2,
|
||||
EROFS_INODE_FLAT_COMPRESSION = 3,
|
||||
EROFS_INODE_COMPRESSED_COMPACT = 3,
|
||||
EROFS_INODE_CHUNK_BASED = 4,
|
||||
EROFS_INODE_DATALAYOUT_MAX
|
||||
};
|
||||
|
||||
static inline bool erofs_inode_is_data_compressed(unsigned int datamode)
|
||||
{
|
||||
return datamode == EROFS_INODE_FLAT_COMPRESSION ||
|
||||
datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY;
|
||||
return datamode == EROFS_INODE_COMPRESSED_COMPACT ||
|
||||
datamode == EROFS_INODE_COMPRESSED_FULL;
|
||||
}
|
||||
|
||||
/* bit definitions of inode i_format */
|
||||
#define EROFS_I_VERSION_BITS 1
|
||||
#define EROFS_I_DATALAYOUT_BITS 3
|
||||
#define EROFS_I_VERSION_MASK 0x01
|
||||
#define EROFS_I_DATALAYOUT_MASK 0x07
|
||||
|
||||
#define EROFS_I_VERSION_BIT 0
|
||||
#define EROFS_I_DATALAYOUT_BIT 1
|
||||
#define EROFS_I_ALL_BIT 4
|
||||
|
||||
#define EROFS_I_ALL \
|
||||
((1 << (EROFS_I_DATALAYOUT_BIT + EROFS_I_DATALAYOUT_BITS)) - 1)
|
||||
#define EROFS_I_ALL ((1 << EROFS_I_ALL_BIT) - 1)
|
||||
|
||||
/* indicate chunk blkbits, thus 'chunksize = blocksize << chunk blkbits' */
|
||||
#define EROFS_CHUNK_FORMAT_BLKBITS_MASK 0x001F
|
||||
@@ -127,11 +126,30 @@ static inline bool erofs_inode_is_data_compressed(unsigned int datamode)
|
||||
#define EROFS_CHUNK_FORMAT_ALL \
|
||||
(EROFS_CHUNK_FORMAT_BLKBITS_MASK | EROFS_CHUNK_FORMAT_INDEXES)
|
||||
|
||||
/* 32-byte on-disk inode */
|
||||
#define EROFS_INODE_LAYOUT_COMPACT 0
|
||||
/* 64-byte on-disk inode */
|
||||
#define EROFS_INODE_LAYOUT_EXTENDED 1
|
||||
|
||||
struct erofs_inode_chunk_info {
|
||||
__le16 format; /* chunk blkbits, etc. */
|
||||
__le16 reserved;
|
||||
};
|
||||
|
||||
union erofs_inode_i_u {
|
||||
/* total compressed blocks for compressed inodes */
|
||||
__le32 compressed_blocks;
|
||||
|
||||
/* block address for uncompressed flat inodes */
|
||||
__le32 raw_blkaddr;
|
||||
|
||||
/* for device files, used to indicate old/new device # */
|
||||
__le32 rdev;
|
||||
|
||||
/* for chunk-based files, it contains the summary info */
|
||||
struct erofs_inode_chunk_info c;
|
||||
};
|
||||
|
||||
/* 32-byte reduced form of an ondisk inode */
|
||||
struct erofs_inode_compact {
|
||||
__le16 i_format; /* inode format hints */
|
||||
@@ -142,29 +160,14 @@ struct erofs_inode_compact {
|
||||
__le16 i_nlink;
|
||||
__le32 i_size;
|
||||
__le32 i_reserved;
|
||||
union {
|
||||
/* total compressed blocks for compressed inodes */
|
||||
__le32 compressed_blocks;
|
||||
/* block address for uncompressed flat inodes */
|
||||
__le32 raw_blkaddr;
|
||||
union erofs_inode_i_u i_u;
|
||||
|
||||
/* for device files, used to indicate old/new device # */
|
||||
__le32 rdev;
|
||||
|
||||
/* for chunk-based files, it contains the summary info */
|
||||
struct erofs_inode_chunk_info c;
|
||||
} i_u;
|
||||
__le32 i_ino; /* only used for 32-bit stat compatibility */
|
||||
__le32 i_ino; /* only used for 32-bit stat compatibility */
|
||||
__le16 i_uid;
|
||||
__le16 i_gid;
|
||||
__le32 i_reserved2;
|
||||
};
|
||||
|
||||
/* 32-byte on-disk inode */
|
||||
#define EROFS_INODE_LAYOUT_COMPACT 0
|
||||
/* 64-byte on-disk inode */
|
||||
#define EROFS_INODE_LAYOUT_EXTENDED 1
|
||||
|
||||
/* 64-byte complete form of an ondisk inode */
|
||||
struct erofs_inode_extended {
|
||||
__le16 i_format; /* inode format hints */
|
||||
@@ -174,22 +177,9 @@ struct erofs_inode_extended {
|
||||
__le16 i_mode;
|
||||
__le16 i_reserved;
|
||||
__le64 i_size;
|
||||
union {
|
||||
/* total compressed blocks for compressed inodes */
|
||||
__le32 compressed_blocks;
|
||||
/* block address for uncompressed flat inodes */
|
||||
__le32 raw_blkaddr;
|
||||
|
||||
/* for device files, used to indicate old/new device # */
|
||||
__le32 rdev;
|
||||
|
||||
/* for chunk-based files, it contains the summary info */
|
||||
struct erofs_inode_chunk_info c;
|
||||
} i_u;
|
||||
|
||||
/* only used for 32-bit stat compatibility */
|
||||
__le32 i_ino;
|
||||
union erofs_inode_i_u i_u;
|
||||
|
||||
__le32 i_ino; /* only used for 32-bit stat compatibility */
|
||||
__le32 i_uid;
|
||||
__le32 i_gid;
|
||||
__le64 i_mtime;
|
||||
@@ -198,10 +188,6 @@ struct erofs_inode_extended {
|
||||
__u8 i_reserved2[16];
|
||||
};
|
||||
|
||||
#define EROFS_MAX_SHARED_XATTRS (128)
|
||||
/* h_shared_count between 129 ... 255 are special # */
|
||||
#define EROFS_SHARED_XATTR_EXTENT (255)
|
||||
|
||||
/*
|
||||
* inline xattrs (n == i_xattr_icount):
|
||||
* erofs_xattr_ibody_header(1) + (n - 1) * 4 bytes
|
||||
@@ -228,6 +214,13 @@ struct erofs_xattr_ibody_header {
|
||||
#define EROFS_XATTR_INDEX_LUSTRE 5
|
||||
#define EROFS_XATTR_INDEX_SECURITY 6
|
||||
|
||||
/*
|
||||
* bit 7 of e_name_index is set when it refers to a long xattr name prefix,
|
||||
* while the remained lower bits represent the index of the prefix.
|
||||
*/
|
||||
#define EROFS_XATTR_LONG_PREFIX 0x80
|
||||
#define EROFS_XATTR_LONG_PREFIX_MASK 0x7f
|
||||
|
||||
/* xattr entry (for both inline & shared xattrs) */
|
||||
struct erofs_xattr_entry {
|
||||
__u8 e_name_len; /* length of name */
|
||||
@@ -237,6 +230,12 @@ struct erofs_xattr_entry {
|
||||
char e_name[]; /* attribute name */
|
||||
};
|
||||
|
||||
/* long xattr name prefix */
|
||||
struct erofs_xattr_long_prefix {
|
||||
__u8 base_index; /* short xattr name prefix index */
|
||||
char infix[]; /* infix apart from short prefix */
|
||||
};
|
||||
|
||||
static inline unsigned int erofs_xattr_ibody_size(__le16 i_xattr_icount)
|
||||
{
|
||||
if (!i_xattr_icount)
|
||||
@@ -267,6 +266,22 @@ struct erofs_inode_chunk_index {
|
||||
__le32 blkaddr; /* start block address of this inode chunk */
|
||||
};
|
||||
|
||||
/* dirent sorts in alphabet order, thus we can do binary search */
|
||||
struct erofs_dirent {
|
||||
__le64 nid; /* node number */
|
||||
__le16 nameoff; /* start offset of file name */
|
||||
__u8 file_type; /* file type */
|
||||
__u8 reserved; /* reserved */
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* EROFS file types should match generic FT_* types and
|
||||
* it seems no need to add BUILD_BUG_ONs since potential
|
||||
* unmatchness will break other fses as well...
|
||||
*/
|
||||
|
||||
#define EROFS_NAME_LEN 255
|
||||
|
||||
/* maximum supported size of a physical compression cluster */
|
||||
#define Z_EROFS_PCLUSTER_MAX_SIZE (1024 * 1024)
|
||||
|
||||
@@ -336,10 +351,8 @@ struct z_erofs_map_header {
|
||||
__u8 h_clusterbits;
|
||||
};
|
||||
|
||||
#define Z_EROFS_VLE_LEGACY_HEADER_PADDING 8
|
||||
|
||||
/*
|
||||
* Fixed-sized output compression on-disk logical cluster type:
|
||||
* On-disk logical cluster type:
|
||||
* 0 - literal (uncompressed) lcluster
|
||||
* 1,3 - compressed lcluster (for HEAD lclusters)
|
||||
* 2 - compressed lcluster (for NONHEAD lclusters)
|
||||
@@ -363,27 +376,27 @@ struct z_erofs_map_header {
|
||||
* di_u.delta[1] = distance to the next HEAD lcluster
|
||||
*/
|
||||
enum {
|
||||
Z_EROFS_VLE_CLUSTER_TYPE_PLAIN = 0,
|
||||
Z_EROFS_VLE_CLUSTER_TYPE_HEAD1 = 1,
|
||||
Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD = 2,
|
||||
Z_EROFS_VLE_CLUSTER_TYPE_HEAD2 = 3,
|
||||
Z_EROFS_VLE_CLUSTER_TYPE_MAX
|
||||
Z_EROFS_LCLUSTER_TYPE_PLAIN = 0,
|
||||
Z_EROFS_LCLUSTER_TYPE_HEAD1 = 1,
|
||||
Z_EROFS_LCLUSTER_TYPE_NONHEAD = 2,
|
||||
Z_EROFS_LCLUSTER_TYPE_HEAD2 = 3,
|
||||
Z_EROFS_LCLUSTER_TYPE_MAX
|
||||
};
|
||||
|
||||
#define Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS 2
|
||||
#define Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT 0
|
||||
#define Z_EROFS_LI_LCLUSTER_TYPE_BITS 2
|
||||
#define Z_EROFS_LI_LCLUSTER_TYPE_BIT 0
|
||||
|
||||
/* (noncompact only, HEAD) This pcluster refers to partial decompressed data */
|
||||
#define Z_EROFS_VLE_DI_PARTIAL_REF (1 << 15)
|
||||
#define Z_EROFS_LI_PARTIAL_REF (1 << 15)
|
||||
|
||||
/*
|
||||
* D0_CBLKCNT will be marked _only_ at the 1st non-head lcluster to store the
|
||||
* compressed block count of a compressed extent (in logical clusters, aka.
|
||||
* block count of a pcluster).
|
||||
*/
|
||||
#define Z_EROFS_VLE_DI_D0_CBLKCNT (1 << 11)
|
||||
#define Z_EROFS_LI_D0_CBLKCNT (1 << 11)
|
||||
|
||||
struct z_erofs_vle_decompressed_index {
|
||||
struct z_erofs_lcluster_index {
|
||||
__le16 di_advise;
|
||||
/* where to decompress in the head lcluster */
|
||||
__le16 di_clusterofs;
|
||||
@@ -400,25 +413,8 @@ struct z_erofs_vle_decompressed_index {
|
||||
} di_u;
|
||||
};
|
||||
|
||||
#define Z_EROFS_VLE_LEGACY_INDEX_ALIGN(size) \
|
||||
(round_up(size, sizeof(struct z_erofs_vle_decompressed_index)) + \
|
||||
sizeof(struct z_erofs_map_header) + Z_EROFS_VLE_LEGACY_HEADER_PADDING)
|
||||
|
||||
/* dirent sorts in alphabet order, thus we can do binary search */
|
||||
struct erofs_dirent {
|
||||
__le64 nid; /* node number */
|
||||
__le16 nameoff; /* start offset of file name */
|
||||
__u8 file_type; /* file type */
|
||||
__u8 reserved; /* reserved */
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* EROFS file types should match generic FT_* types and
|
||||
* it seems no need to add BUILD_BUG_ONs since potential
|
||||
* unmatchness will break other fses as well...
|
||||
*/
|
||||
|
||||
#define EROFS_NAME_LEN 255
|
||||
#define Z_EROFS_FULL_INDEX_ALIGN(end) \
|
||||
(ALIGN(end, 8) + sizeof(struct z_erofs_map_header) + 8)
|
||||
|
||||
/* check the EROFS on-disk layout strictly at compile time */
|
||||
static inline void erofs_check_ondisk_layout_definitions(void)
|
||||
@@ -435,15 +431,15 @@ static inline void erofs_check_ondisk_layout_definitions(void)
|
||||
BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_info) != 4);
|
||||
BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_index) != 8);
|
||||
BUILD_BUG_ON(sizeof(struct z_erofs_map_header) != 8);
|
||||
BUILD_BUG_ON(sizeof(struct z_erofs_vle_decompressed_index) != 8);
|
||||
BUILD_BUG_ON(sizeof(struct z_erofs_lcluster_index) != 8);
|
||||
BUILD_BUG_ON(sizeof(struct erofs_dirent) != 12);
|
||||
/* keep in sync between 2 index structures for better extendibility */
|
||||
BUILD_BUG_ON(sizeof(struct erofs_inode_chunk_index) !=
|
||||
sizeof(struct z_erofs_vle_decompressed_index));
|
||||
sizeof(struct z_erofs_lcluster_index));
|
||||
BUILD_BUG_ON(sizeof(struct erofs_deviceslot) != 128);
|
||||
|
||||
BUILD_BUG_ON(BIT(Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS) <
|
||||
Z_EROFS_VLE_CLUSTER_TYPE_MAX - 1);
|
||||
BUILD_BUG_ON(BIT(Z_EROFS_LI_LCLUSTER_TYPE_BITS) <
|
||||
Z_EROFS_LCLUSTER_TYPE_MAX - 1);
|
||||
/* exclude old compiler versions like gcc 7.5.0 */
|
||||
BUILD_BUG_ON(__builtin_constant_p(fmh) ?
|
||||
fmh != cpu_to_le64(1ULL << 63) : 0);
|
||||
|
||||
+3
-2
@@ -209,8 +209,8 @@ static int erofs_fscache_data_read_slice(struct erofs_fscache_request *primary)
|
||||
void *src;
|
||||
|
||||
/* For tail packing layout, the offset may be non-zero. */
|
||||
offset = erofs_blkoff(map.m_pa);
|
||||
blknr = erofs_blknr(map.m_pa);
|
||||
offset = erofs_blkoff(sb, map.m_pa);
|
||||
blknr = erofs_blknr(sb, map.m_pa);
|
||||
size = map.m_llen;
|
||||
|
||||
src = erofs_read_metabuf(&buf, sb, blknr, EROFS_KMAP);
|
||||
@@ -460,6 +460,7 @@ static struct erofs_fscache *erofs_fscache_acquire_cookie(struct super_block *sb
|
||||
inode->i_size = OFFSET_MAX;
|
||||
inode->i_mapping->a_ops = &erofs_fscache_meta_aops;
|
||||
mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
|
||||
inode->i_blkbits = EROFS_SB(sb)->blkszbits;
|
||||
inode->i_private = ctx;
|
||||
|
||||
ctx->cookie = cookie;
|
||||
|
||||
+20
-16
@@ -23,11 +23,8 @@ static void *erofs_read_inode(struct erofs_buf *buf,
|
||||
unsigned int ifmt;
|
||||
int err;
|
||||
|
||||
blkaddr = erofs_blknr(inode_loc);
|
||||
*ofs = erofs_blkoff(inode_loc);
|
||||
|
||||
erofs_dbg("%s, reading inode nid %llu at %u of blkaddr %u",
|
||||
__func__, vi->nid, *ofs, blkaddr);
|
||||
blkaddr = erofs_blknr(sb, inode_loc);
|
||||
*ofs = erofs_blkoff(sb, inode_loc);
|
||||
|
||||
kaddr = erofs_read_metabuf(buf, sb, blkaddr, EROFS_KMAP);
|
||||
if (IS_ERR(kaddr)) {
|
||||
@@ -58,11 +55,11 @@ static void *erofs_read_inode(struct erofs_buf *buf,
|
||||
case EROFS_INODE_LAYOUT_EXTENDED:
|
||||
vi->inode_isize = sizeof(struct erofs_inode_extended);
|
||||
/* check if the extended inode acrosses block boundary */
|
||||
if (*ofs + vi->inode_isize <= EROFS_BLKSIZ) {
|
||||
if (*ofs + vi->inode_isize <= sb->s_blocksize) {
|
||||
*ofs += vi->inode_isize;
|
||||
die = (struct erofs_inode_extended *)dic;
|
||||
} else {
|
||||
const unsigned int gotten = EROFS_BLKSIZ - *ofs;
|
||||
const unsigned int gotten = sb->s_blocksize - *ofs;
|
||||
|
||||
copied = kmalloc(vi->inode_isize, GFP_NOFS);
|
||||
if (!copied) {
|
||||
@@ -176,7 +173,7 @@ static void *erofs_read_inode(struct erofs_buf *buf,
|
||||
err = -EOPNOTSUPP;
|
||||
goto err_out;
|
||||
}
|
||||
vi->chunkbits = LOG_BLOCK_SIZE +
|
||||
vi->chunkbits = sb->s_blocksize_bits +
|
||||
(vi->chunkformat & EROFS_CHUNK_FORMAT_BLKBITS_MASK);
|
||||
}
|
||||
inode->i_mtime.tv_sec = inode->i_ctime.tv_sec;
|
||||
@@ -188,11 +185,12 @@ static void *erofs_read_inode(struct erofs_buf *buf,
|
||||
if (test_opt(&sbi->opt, DAX_ALWAYS) && S_ISREG(inode->i_mode) &&
|
||||
vi->datalayout == EROFS_INODE_FLAT_PLAIN)
|
||||
inode->i_flags |= S_DAX;
|
||||
|
||||
if (!nblks)
|
||||
/* measure inode.i_blocks as generic filesystems */
|
||||
inode->i_blocks = roundup(inode->i_size, EROFS_BLKSIZ) >> 9;
|
||||
inode->i_blocks = round_up(inode->i_size, sb->s_blocksize) >> 9;
|
||||
else
|
||||
inode->i_blocks = nblks << LOG_SECTORS_PER_BLOCK;
|
||||
inode->i_blocks = nblks << (sb->s_blocksize_bits - 9);
|
||||
return kaddr;
|
||||
|
||||
bogusimode:
|
||||
@@ -210,11 +208,12 @@ static int erofs_fill_symlink(struct inode *inode, void *kaddr,
|
||||
unsigned int m_pofs)
|
||||
{
|
||||
struct erofs_inode *vi = EROFS_I(inode);
|
||||
unsigned int bsz = i_blocksize(inode);
|
||||
char *lnk;
|
||||
|
||||
/* if it cannot be handled with fast symlink scheme */
|
||||
if (vi->datalayout != EROFS_INODE_FLAT_INLINE ||
|
||||
inode->i_size >= EROFS_BLKSIZ || inode->i_size < 0) {
|
||||
inode->i_size >= bsz || inode->i_size < 0) {
|
||||
inode->i_op = &erofs_symlink_iops;
|
||||
return 0;
|
||||
}
|
||||
@@ -225,7 +224,7 @@ static int erofs_fill_symlink(struct inode *inode, void *kaddr,
|
||||
|
||||
m_pofs += vi->xattr_isize;
|
||||
/* inline symlink data shouldn't cross block boundary */
|
||||
if (m_pofs + inode->i_size > EROFS_BLKSIZ) {
|
||||
if (m_pofs + inode->i_size > bsz) {
|
||||
kfree(lnk);
|
||||
erofs_err(inode->i_sb,
|
||||
"inline data cross block boundary @ nid %llu",
|
||||
@@ -289,10 +288,15 @@ static int erofs_fill_inode(struct inode *inode)
|
||||
}
|
||||
|
||||
if (erofs_inode_is_data_compressed(vi->datalayout)) {
|
||||
if (!erofs_is_fscache_mode(inode->i_sb))
|
||||
err = z_erofs_fill_inode(inode);
|
||||
else
|
||||
err = -EOPNOTSUPP;
|
||||
#ifdef CONFIG_EROFS_FS_ZIP
|
||||
if (!erofs_is_fscache_mode(inode->i_sb) &&
|
||||
inode->i_sb->s_blocksize_bits == PAGE_SHIFT) {
|
||||
inode->i_mapping->a_ops = &z_erofs_aops;
|
||||
err = 0;
|
||||
goto out_unlock;
|
||||
}
|
||||
#endif
|
||||
err = -EOPNOTSUPP;
|
||||
goto out_unlock;
|
||||
}
|
||||
inode->i_mapping->a_ops = &erofs_raw_access_aops;
|
||||
|
||||
+30
-43
@@ -31,10 +31,8 @@ __printf(3, 4) void _erofs_info(struct super_block *sb,
|
||||
#define erofs_info(sb, fmt, ...) \
|
||||
_erofs_info(sb, __func__, fmt "\n", ##__VA_ARGS__)
|
||||
#ifdef CONFIG_EROFS_FS_DEBUG
|
||||
#define erofs_dbg(x, ...) pr_debug(x "\n", ##__VA_ARGS__)
|
||||
#define DBG_BUGON BUG_ON
|
||||
#else
|
||||
#define erofs_dbg(x, ...) ((void)0)
|
||||
#define DBG_BUGON(x) ((void)(x))
|
||||
#endif /* !CONFIG_EROFS_FS_DEBUG */
|
||||
|
||||
@@ -81,6 +79,7 @@ struct erofs_dev_context {
|
||||
struct rw_semaphore rwsem;
|
||||
|
||||
unsigned int extra_devices;
|
||||
bool flatdev;
|
||||
};
|
||||
|
||||
struct erofs_fs_context {
|
||||
@@ -116,6 +115,11 @@ struct erofs_fscache {
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct erofs_xattr_prefix_item {
|
||||
struct erofs_xattr_long_prefix *prefix;
|
||||
u8 infix_len;
|
||||
};
|
||||
|
||||
struct erofs_sb_info {
|
||||
struct erofs_mount_opts opt; /* options */
|
||||
#ifdef CONFIG_EROFS_FS_ZIP
|
||||
@@ -133,8 +137,8 @@ struct erofs_sb_info {
|
||||
struct inode *managed_cache;
|
||||
|
||||
struct erofs_sb_lz4_info lz4;
|
||||
struct inode *packed_inode;
|
||||
#endif /* CONFIG_EROFS_FS_ZIP */
|
||||
struct inode *packed_inode;
|
||||
struct erofs_dev_context *devs;
|
||||
struct dax_device *dax_dev;
|
||||
u64 dax_part_off;
|
||||
@@ -144,11 +148,14 @@ struct erofs_sb_info {
|
||||
u32 meta_blkaddr;
|
||||
#ifdef CONFIG_EROFS_FS_XATTR
|
||||
u32 xattr_blkaddr;
|
||||
u32 xattr_prefix_start;
|
||||
u8 xattr_prefix_count;
|
||||
struct erofs_xattr_prefix_item *xattr_prefixes;
|
||||
#endif
|
||||
u16 device_id_mask; /* valid bits of device id to be used */
|
||||
|
||||
/* inode slot unit size in bit shift */
|
||||
unsigned char islotbits;
|
||||
unsigned char islotbits; /* inode slot unit size in bit shift */
|
||||
unsigned char blkszbits; /* filesystem block size in bit shift */
|
||||
|
||||
u32 sb_size; /* total superblock size */
|
||||
u32 build_time_nsec;
|
||||
@@ -156,6 +163,7 @@ struct erofs_sb_info {
|
||||
|
||||
/* what we really care is nid, rather than ino.. */
|
||||
erofs_nid_t root_nid;
|
||||
erofs_nid_t packed_nid;
|
||||
/* used for statfs, f_files - f_favail */
|
||||
u64 inos;
|
||||
|
||||
@@ -240,27 +248,13 @@ static inline int erofs_wait_on_workgroup_freezed(struct erofs_workgroup *grp)
|
||||
VAL != EROFS_LOCKED_MAGIC);
|
||||
}
|
||||
|
||||
/* we strictly follow PAGE_SIZE and no buffer head yet */
|
||||
#define LOG_BLOCK_SIZE PAGE_SHIFT
|
||||
|
||||
#undef LOG_SECTORS_PER_BLOCK
|
||||
#define LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9)
|
||||
|
||||
#undef SECTORS_PER_BLOCK
|
||||
#define SECTORS_PER_BLOCK (1 << SECTORS_PER_BLOCK)
|
||||
|
||||
#define EROFS_BLKSIZ (1 << LOG_BLOCK_SIZE)
|
||||
|
||||
#if (EROFS_BLKSIZ % 4096 || !EROFS_BLKSIZ)
|
||||
#error erofs cannot be used in this platform
|
||||
#endif
|
||||
|
||||
enum erofs_kmap_type {
|
||||
EROFS_NO_KMAP, /* don't map the buffer */
|
||||
EROFS_KMAP, /* use kmap_local_page() to map the buffer */
|
||||
};
|
||||
|
||||
struct erofs_buf {
|
||||
struct inode *inode;
|
||||
struct page *page;
|
||||
void *base;
|
||||
enum erofs_kmap_type kmap_type;
|
||||
@@ -269,9 +263,10 @@ struct erofs_buf {
|
||||
|
||||
#define ROOT_NID(sb) ((sb)->root_nid)
|
||||
|
||||
#define erofs_blknr(addr) ((addr) / EROFS_BLKSIZ)
|
||||
#define erofs_blkoff(addr) ((addr) % EROFS_BLKSIZ)
|
||||
#define blknr_to_addr(nr) ((erofs_off_t)(nr) * EROFS_BLKSIZ)
|
||||
#define erofs_blknr(sb, addr) ((addr) >> (sb)->s_blocksize_bits)
|
||||
#define erofs_blkoff(sb, addr) ((addr) & ((sb)->s_blocksize - 1))
|
||||
#define erofs_pos(sb, blk) ((erofs_off_t)(blk) << (sb)->s_blocksize_bits)
|
||||
#define erofs_iblks(i) (round_up((i)->i_size, i_blocksize(i)) >> (i)->i_blkbits)
|
||||
|
||||
#define EROFS_FEATURE_FUNCS(name, compat, feature) \
|
||||
static inline bool erofs_sb_has_##name(struct erofs_sb_info *sbi) \
|
||||
@@ -288,6 +283,7 @@ EROFS_FEATURE_FUNCS(compr_head2, incompat, INCOMPAT_COMPR_HEAD2)
|
||||
EROFS_FEATURE_FUNCS(ztailpacking, incompat, INCOMPAT_ZTAILPACKING)
|
||||
EROFS_FEATURE_FUNCS(fragments, incompat, INCOMPAT_FRAGMENTS)
|
||||
EROFS_FEATURE_FUNCS(dedupe, incompat, INCOMPAT_DEDUPE)
|
||||
EROFS_FEATURE_FUNCS(xattr_prefixes, incompat, INCOMPAT_XATTR_PREFIXES)
|
||||
EROFS_FEATURE_FUNCS(sb_chksum, compat, COMPAT_SB_CHKSUM)
|
||||
|
||||
/* atomic flag definitions */
|
||||
@@ -306,7 +302,7 @@ struct erofs_inode {
|
||||
|
||||
unsigned char datalayout;
|
||||
unsigned char inode_isize;
|
||||
unsigned short xattr_isize;
|
||||
unsigned int xattr_isize;
|
||||
|
||||
unsigned int xattr_shared_count;
|
||||
unsigned int *xattr_shared_xattrs;
|
||||
@@ -343,28 +339,18 @@ static inline erofs_off_t erofs_iloc(struct inode *inode)
|
||||
{
|
||||
struct erofs_sb_info *sbi = EROFS_I_SB(inode);
|
||||
|
||||
return blknr_to_addr(sbi->meta_blkaddr) +
|
||||
return erofs_pos(inode->i_sb, sbi->meta_blkaddr) +
|
||||
(EROFS_I(inode)->nid << sbi->islotbits);
|
||||
}
|
||||
|
||||
static inline unsigned int erofs_bitrange(unsigned int value, unsigned int bit,
|
||||
unsigned int bits)
|
||||
static inline unsigned int erofs_inode_version(unsigned int ifmt)
|
||||
{
|
||||
|
||||
return (value >> bit) & ((1 << bits) - 1);
|
||||
return (ifmt >> EROFS_I_VERSION_BIT) & EROFS_I_VERSION_MASK;
|
||||
}
|
||||
|
||||
|
||||
static inline unsigned int erofs_inode_version(unsigned int value)
|
||||
static inline unsigned int erofs_inode_datalayout(unsigned int ifmt)
|
||||
{
|
||||
return erofs_bitrange(value, EROFS_I_VERSION_BIT,
|
||||
EROFS_I_VERSION_BITS);
|
||||
}
|
||||
|
||||
static inline unsigned int erofs_inode_datalayout(unsigned int value)
|
||||
{
|
||||
return erofs_bitrange(value, EROFS_I_DATALAYOUT_BIT,
|
||||
EROFS_I_DATALAYOUT_BITS);
|
||||
return (ifmt >> EROFS_I_DATALAYOUT_BIT) & EROFS_I_DATALAYOUT_MASK;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -451,10 +437,13 @@ extern const struct iomap_ops z_erofs_iomap_report_ops;
|
||||
#define EROFS_REG_COOKIE_SHARE 0x0001
|
||||
#define EROFS_REG_COOKIE_NEED_NOEXIST 0x0002
|
||||
|
||||
void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
|
||||
erofs_off_t *offset, int *lengthp);
|
||||
void erofs_unmap_metabuf(struct erofs_buf *buf);
|
||||
void erofs_put_metabuf(struct erofs_buf *buf);
|
||||
void *erofs_bread(struct erofs_buf *buf, struct inode *inode,
|
||||
erofs_blk_t blkaddr, enum erofs_kmap_type type);
|
||||
void *erofs_bread(struct erofs_buf *buf, erofs_blk_t blkaddr,
|
||||
enum erofs_kmap_type type);
|
||||
void erofs_init_metabuf(struct erofs_buf *buf, struct super_block *sb);
|
||||
void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb,
|
||||
erofs_blk_t blkaddr, enum erofs_kmap_type type);
|
||||
int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *dev);
|
||||
@@ -521,7 +510,6 @@ int erofs_try_to_free_cached_page(struct page *page);
|
||||
int z_erofs_load_lz4_config(struct super_block *sb,
|
||||
struct erofs_super_block *dsb,
|
||||
struct z_erofs_lz4_cfgs *lz4, int len);
|
||||
int z_erofs_fill_inode(struct inode *inode);
|
||||
int z_erofs_map_blocks_iter(struct inode *inode, struct erofs_map_blocks *map,
|
||||
int flags);
|
||||
#else
|
||||
@@ -541,7 +529,6 @@ static inline int z_erofs_load_lz4_config(struct super_block *sb,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static inline int z_erofs_fill_inode(struct inode *inode) { return -EOPNOTSUPP; }
|
||||
#endif /* !CONFIG_EROFS_FS_ZIP */
|
||||
|
||||
#ifdef CONFIG_EROFS_FS_ZIP_LZMA
|
||||
|
||||
+13
-14
@@ -89,7 +89,8 @@ static struct erofs_dirent *find_target_dirent(struct erofs_qstr *name,
|
||||
static void *erofs_find_target_block(struct erofs_buf *target,
|
||||
struct inode *dir, struct erofs_qstr *name, int *_ndirents)
|
||||
{
|
||||
int head = 0, back = DIV_ROUND_UP(dir->i_size, EROFS_BLKSIZ) - 1;
|
||||
unsigned int bsz = i_blocksize(dir);
|
||||
int head = 0, back = erofs_iblks(dir) - 1;
|
||||
unsigned int startprfx = 0, endprfx = 0;
|
||||
void *candidate = ERR_PTR(-ENOENT);
|
||||
|
||||
@@ -98,10 +99,10 @@ static void *erofs_find_target_block(struct erofs_buf *target,
|
||||
struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
|
||||
struct erofs_dirent *de;
|
||||
|
||||
de = erofs_bread(&buf, dir, mid, EROFS_KMAP);
|
||||
buf.inode = dir;
|
||||
de = erofs_bread(&buf, mid, EROFS_KMAP);
|
||||
if (!IS_ERR(de)) {
|
||||
const int nameoff = nameoff_from_disk(de->nameoff,
|
||||
EROFS_BLKSIZ);
|
||||
const int nameoff = nameoff_from_disk(de->nameoff, bsz);
|
||||
const int ndirents = nameoff / sizeof(*de);
|
||||
int diff;
|
||||
unsigned int matched;
|
||||
@@ -121,11 +122,10 @@ static void *erofs_find_target_block(struct erofs_buf *target,
|
||||
|
||||
dname.name = (u8 *)de + nameoff;
|
||||
if (ndirents == 1)
|
||||
dname.end = (u8 *)de + EROFS_BLKSIZ;
|
||||
dname.end = (u8 *)de + bsz;
|
||||
else
|
||||
dname.end = (u8 *)de +
|
||||
nameoff_from_disk(de[1].nameoff,
|
||||
EROFS_BLKSIZ);
|
||||
nameoff_from_disk(de[1].nameoff, bsz);
|
||||
|
||||
/* string comparison without already matched prefix */
|
||||
diff = erofs_dirnamecmp(name, &dname, &matched);
|
||||
@@ -171,6 +171,7 @@ int erofs_namei(struct inode *dir, const struct qstr *name, erofs_nid_t *nid,
|
||||
|
||||
qn.name = name->name;
|
||||
qn.end = name->name + name->len;
|
||||
buf.inode = dir;
|
||||
|
||||
ndirents = 0;
|
||||
de = erofs_find_target_block(&buf, dir, &qn, &ndirents);
|
||||
@@ -178,7 +179,8 @@ int erofs_namei(struct inode *dir, const struct qstr *name, erofs_nid_t *nid,
|
||||
return PTR_ERR(de);
|
||||
|
||||
if (ndirents)
|
||||
de = find_target_dirent(&qn, (u8 *)de, EROFS_BLKSIZ, ndirents);
|
||||
de = find_target_dirent(&qn, (u8 *)de, i_blocksize(dir),
|
||||
ndirents);
|
||||
|
||||
if (!IS_ERR(de)) {
|
||||
*nid = le64_to_cpu(de->nid);
|
||||
@@ -203,16 +205,13 @@ static struct dentry *erofs_lookup(struct inode *dir, struct dentry *dentry,
|
||||
|
||||
err = erofs_namei(dir, &dentry->d_name, &nid, &d_type);
|
||||
|
||||
if (err == -ENOENT) {
|
||||
if (err == -ENOENT)
|
||||
/* negative dentry */
|
||||
inode = NULL;
|
||||
} else if (err) {
|
||||
else if (err)
|
||||
inode = ERR_PTR(err);
|
||||
} else {
|
||||
erofs_dbg("%s, %pd (nid %llu) found, d_type %u", __func__,
|
||||
dentry, nid, d_type);
|
||||
else
|
||||
inode = erofs_iget(dir->i_sb, nid);
|
||||
}
|
||||
return d_splice_alias(inode, dentry);
|
||||
}
|
||||
|
||||
|
||||
+70
-46
@@ -52,18 +52,21 @@ void _erofs_info(struct super_block *sb, const char *function,
|
||||
|
||||
static int erofs_superblock_csum_verify(struct super_block *sb, void *sbdata)
|
||||
{
|
||||
size_t len = 1 << EROFS_SB(sb)->blkszbits;
|
||||
struct erofs_super_block *dsb;
|
||||
u32 expected_crc, crc;
|
||||
|
||||
dsb = kmemdup(sbdata + EROFS_SUPER_OFFSET,
|
||||
EROFS_BLKSIZ - EROFS_SUPER_OFFSET, GFP_KERNEL);
|
||||
if (len > EROFS_SUPER_OFFSET)
|
||||
len -= EROFS_SUPER_OFFSET;
|
||||
|
||||
dsb = kmemdup(sbdata + EROFS_SUPER_OFFSET, len, GFP_KERNEL);
|
||||
if (!dsb)
|
||||
return -ENOMEM;
|
||||
|
||||
expected_crc = le32_to_cpu(dsb->checksum);
|
||||
dsb->checksum = 0;
|
||||
/* to allow for x86 boot sectors and other oddities. */
|
||||
crc = crc32c(~0, dsb, EROFS_BLKSIZ - EROFS_SUPER_OFFSET);
|
||||
crc = crc32c(~0, dsb, len);
|
||||
kfree(dsb);
|
||||
|
||||
if (crc != expected_crc) {
|
||||
@@ -123,20 +126,19 @@ static bool check_layout_compatibility(struct super_block *sb,
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EROFS_FS_ZIP
|
||||
/* read variable-sized metadata, offset will be aligned by 4-byte */
|
||||
static void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
|
||||
erofs_off_t *offset, int *lengthp)
|
||||
void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
|
||||
erofs_off_t *offset, int *lengthp)
|
||||
{
|
||||
u8 *buffer, *ptr;
|
||||
int len, i, cnt;
|
||||
|
||||
*offset = round_up(*offset, 4);
|
||||
ptr = erofs_read_metabuf(buf, sb, erofs_blknr(*offset), EROFS_KMAP);
|
||||
ptr = erofs_bread(buf, erofs_blknr(sb, *offset), EROFS_KMAP);
|
||||
if (IS_ERR(ptr))
|
||||
return ptr;
|
||||
|
||||
len = le16_to_cpu(*(__le16 *)&ptr[erofs_blkoff(*offset)]);
|
||||
len = le16_to_cpu(*(__le16 *)&ptr[erofs_blkoff(sb, *offset)]);
|
||||
if (!len)
|
||||
len = U16_MAX + 1;
|
||||
buffer = kmalloc(len, GFP_KERNEL);
|
||||
@@ -146,19 +148,20 @@ static void *erofs_read_metadata(struct super_block *sb, struct erofs_buf *buf,
|
||||
*lengthp = len;
|
||||
|
||||
for (i = 0; i < len; i += cnt) {
|
||||
cnt = min(EROFS_BLKSIZ - (int)erofs_blkoff(*offset), len - i);
|
||||
ptr = erofs_read_metabuf(buf, sb, erofs_blknr(*offset),
|
||||
EROFS_KMAP);
|
||||
cnt = min_t(int, sb->s_blocksize - erofs_blkoff(sb, *offset),
|
||||
len - i);
|
||||
ptr = erofs_bread(buf, erofs_blknr(sb, *offset), EROFS_KMAP);
|
||||
if (IS_ERR(ptr)) {
|
||||
kfree(buffer);
|
||||
return ptr;
|
||||
}
|
||||
memcpy(buffer + i, ptr + erofs_blkoff(*offset), cnt);
|
||||
memcpy(buffer + i, ptr + erofs_blkoff(sb, *offset), cnt);
|
||||
*offset += cnt;
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EROFS_FS_ZIP
|
||||
static int erofs_load_compr_cfgs(struct super_block *sb,
|
||||
struct erofs_super_block *dsb)
|
||||
{
|
||||
@@ -175,6 +178,7 @@ static int erofs_load_compr_cfgs(struct super_block *sb,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
erofs_init_metabuf(&buf, sb);
|
||||
offset = EROFS_SUPER_OFFSET + sbi->sb_size;
|
||||
alg = 0;
|
||||
for (algs = sbi->available_compr_algs; algs; algs >>= 1, ++alg) {
|
||||
@@ -228,10 +232,10 @@ static int erofs_init_device(struct erofs_buf *buf, struct super_block *sb,
|
||||
struct block_device *bdev;
|
||||
void *ptr;
|
||||
|
||||
ptr = erofs_read_metabuf(buf, sb, erofs_blknr(*pos), EROFS_KMAP);
|
||||
ptr = erofs_read_metabuf(buf, sb, erofs_blknr(sb, *pos), EROFS_KMAP);
|
||||
if (IS_ERR(ptr))
|
||||
return PTR_ERR(ptr);
|
||||
dis = ptr + erofs_blkoff(*pos);
|
||||
dis = ptr + erofs_blkoff(sb, *pos);
|
||||
|
||||
if (!dif->path) {
|
||||
if (!dis->tag[0]) {
|
||||
@@ -248,7 +252,7 @@ static int erofs_init_device(struct erofs_buf *buf, struct super_block *sb,
|
||||
if (IS_ERR(fscache))
|
||||
return PTR_ERR(fscache);
|
||||
dif->fscache = fscache;
|
||||
} else {
|
||||
} else if (!sbi->devs->flatdev) {
|
||||
bdev = blkdev_get_by_path(dif->path, FMODE_READ | FMODE_EXCL,
|
||||
sb->s_type);
|
||||
if (IS_ERR(bdev))
|
||||
@@ -290,6 +294,9 @@ static int erofs_scan_devices(struct super_block *sb,
|
||||
if (!ondisk_extradevs)
|
||||
return 0;
|
||||
|
||||
if (!sbi->devs->extra_devices && !erofs_is_fscache_mode(sb))
|
||||
sbi->devs->flatdev = true;
|
||||
|
||||
sbi->device_id_mask = roundup_pow_of_two(ondisk_extradevs + 1) - 1;
|
||||
pos = le16_to_cpu(dsb->devt_slotoff) * EROFS_DEVT_SLOT_SIZE;
|
||||
down_read(&sbi->devs->rwsem);
|
||||
@@ -329,7 +336,6 @@ static int erofs_read_superblock(struct super_block *sb)
|
||||
struct erofs_sb_info *sbi;
|
||||
struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
|
||||
struct erofs_super_block *dsb;
|
||||
unsigned int blkszbits;
|
||||
void *data;
|
||||
int ret;
|
||||
|
||||
@@ -348,6 +354,16 @@ static int erofs_read_superblock(struct super_block *sb)
|
||||
goto out;
|
||||
}
|
||||
|
||||
sbi->blkszbits = dsb->blkszbits;
|
||||
if (sbi->blkszbits < 9 || sbi->blkszbits > PAGE_SHIFT) {
|
||||
erofs_err(sb, "blkszbits %u isn't supported", sbi->blkszbits);
|
||||
goto out;
|
||||
}
|
||||
if (dsb->dirblkbits) {
|
||||
erofs_err(sb, "dirblkbits %u isn't supported", dsb->dirblkbits);
|
||||
goto out;
|
||||
}
|
||||
|
||||
sbi->feature_compat = le32_to_cpu(dsb->feature_compat);
|
||||
if (erofs_sb_has_sb_chksum(sbi)) {
|
||||
ret = erofs_superblock_csum_verify(sb, data);
|
||||
@@ -356,19 +372,11 @@ static int erofs_read_superblock(struct super_block *sb)
|
||||
}
|
||||
|
||||
ret = -EINVAL;
|
||||
blkszbits = dsb->blkszbits;
|
||||
/* 9(512 bytes) + LOG_SECTORS_PER_BLOCK == LOG_BLOCK_SIZE */
|
||||
if (blkszbits != LOG_BLOCK_SIZE) {
|
||||
erofs_err(sb, "blkszbits %u isn't supported on this platform",
|
||||
blkszbits);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!check_layout_compatibility(sb, dsb))
|
||||
goto out;
|
||||
|
||||
sbi->sb_size = 128 + dsb->sb_extslots * EROFS_SB_EXTSLOT_SIZE;
|
||||
if (sbi->sb_size > EROFS_BLKSIZ) {
|
||||
if (sbi->sb_size > PAGE_SIZE - EROFS_SUPER_OFFSET) {
|
||||
erofs_err(sb, "invalid sb_extslots %u (more than a fs block)",
|
||||
sbi->sb_size);
|
||||
goto out;
|
||||
@@ -377,20 +385,12 @@ static int erofs_read_superblock(struct super_block *sb)
|
||||
sbi->meta_blkaddr = le32_to_cpu(dsb->meta_blkaddr);
|
||||
#ifdef CONFIG_EROFS_FS_XATTR
|
||||
sbi->xattr_blkaddr = le32_to_cpu(dsb->xattr_blkaddr);
|
||||
sbi->xattr_prefix_start = le32_to_cpu(dsb->xattr_prefix_start);
|
||||
sbi->xattr_prefix_count = dsb->xattr_prefix_count;
|
||||
#endif
|
||||
sbi->islotbits = ilog2(sizeof(struct erofs_inode_compact));
|
||||
sbi->root_nid = le16_to_cpu(dsb->root_nid);
|
||||
#ifdef CONFIG_EROFS_FS_ZIP
|
||||
sbi->packed_inode = NULL;
|
||||
if (erofs_sb_has_fragments(sbi) && dsb->packed_nid) {
|
||||
sbi->packed_inode =
|
||||
erofs_iget(sb, le64_to_cpu(dsb->packed_nid));
|
||||
if (IS_ERR(sbi->packed_inode)) {
|
||||
ret = PTR_ERR(sbi->packed_inode);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
sbi->packed_nid = le64_to_cpu(dsb->packed_nid);
|
||||
sbi->inos = le64_to_cpu(dsb->inos);
|
||||
|
||||
sbi->build_time = le64_to_cpu(dsb->build_time);
|
||||
@@ -417,8 +417,6 @@ static int erofs_read_superblock(struct super_block *sb)
|
||||
/* handle multiple devices */
|
||||
ret = erofs_scan_devices(sb, dsb);
|
||||
|
||||
if (erofs_sb_has_ztailpacking(sbi))
|
||||
erofs_info(sb, "EXPERIMENTAL compressed inline data feature in use. Use at your own risk!");
|
||||
if (erofs_is_fscache_mode(sb))
|
||||
erofs_info(sb, "EXPERIMENTAL fscache-based on-demand read feature in use. Use at your own risk!");
|
||||
if (erofs_sb_has_fragments(sbi))
|
||||
@@ -733,9 +731,10 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
sbi->domain_id = ctx->domain_id;
|
||||
ctx->domain_id = NULL;
|
||||
|
||||
sbi->blkszbits = PAGE_SHIFT;
|
||||
if (erofs_is_fscache_mode(sb)) {
|
||||
sb->s_blocksize = EROFS_BLKSIZ;
|
||||
sb->s_blocksize_bits = LOG_BLOCK_SIZE;
|
||||
sb->s_blocksize = PAGE_SIZE;
|
||||
sb->s_blocksize_bits = PAGE_SHIFT;
|
||||
|
||||
err = erofs_fscache_register_fs(sb);
|
||||
if (err)
|
||||
@@ -745,8 +744,8 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
if (err)
|
||||
return err;
|
||||
} else {
|
||||
if (!sb_set_blocksize(sb, EROFS_BLKSIZ)) {
|
||||
erofs_err(sb, "failed to set erofs blksize");
|
||||
if (!sb_set_blocksize(sb, PAGE_SIZE)) {
|
||||
errorfc(fc, "failed to set initial blksize");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -759,12 +758,24 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (test_opt(&sbi->opt, DAX_ALWAYS)) {
|
||||
BUILD_BUG_ON(EROFS_BLKSIZ != PAGE_SIZE);
|
||||
if (sb->s_blocksize_bits != sbi->blkszbits) {
|
||||
if (erofs_is_fscache_mode(sb)) {
|
||||
errorfc(fc, "unsupported blksize for fscache mode");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!sb_set_blocksize(sb, 1 << sbi->blkszbits)) {
|
||||
errorfc(fc, "failed to set erofs blksize");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (test_opt(&sbi->opt, DAX_ALWAYS)) {
|
||||
if (!sbi->dax_dev) {
|
||||
errorfc(fc, "DAX unsupported by block device. Turning off DAX.");
|
||||
clear_opt(&sbi->opt, DAX_ALWAYS);
|
||||
} else if (sbi->blkszbits != PAGE_SHIFT) {
|
||||
errorfc(fc, "unsupported blocksize for DAX");
|
||||
clear_opt(&sbi->opt, DAX_ALWAYS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -799,10 +810,22 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
|
||||
erofs_shrinker_register(sb);
|
||||
/* sb->s_umount is already locked, SB_ACTIVE and SB_BORN are not set */
|
||||
if (erofs_sb_has_fragments(sbi) && sbi->packed_nid) {
|
||||
sbi->packed_inode = erofs_iget(sb, sbi->packed_nid);
|
||||
if (IS_ERR(sbi->packed_inode)) {
|
||||
err = PTR_ERR(sbi->packed_inode);
|
||||
sbi->packed_inode = NULL;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
err = erofs_init_managed_cache(sb);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = erofs_xattr_prefixes_init(sb);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = erofs_register_sysfs(sb);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -962,12 +985,13 @@ static void erofs_put_super(struct super_block *sb)
|
||||
|
||||
erofs_unregister_sysfs(sb);
|
||||
erofs_shrinker_unregister(sb);
|
||||
erofs_xattr_prefixes_cleanup(sb);
|
||||
#ifdef CONFIG_EROFS_FS_ZIP
|
||||
iput(sbi->managed_cache);
|
||||
sbi->managed_cache = NULL;
|
||||
#endif
|
||||
iput(sbi->packed_inode);
|
||||
sbi->packed_inode = NULL;
|
||||
#endif
|
||||
erofs_free_dev_context(sbi->devs);
|
||||
sbi->devs = NULL;
|
||||
erofs_fscache_unregister_fs(sb);
|
||||
@@ -1060,7 +1084,7 @@ static int erofs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
||||
id = huge_encode_dev(sb->s_bdev->bd_dev);
|
||||
|
||||
buf->f_type = sb->s_magic;
|
||||
buf->f_bsize = EROFS_BLKSIZ;
|
||||
buf->f_bsize = sb->s_blocksize;
|
||||
buf->f_blocks = sbi->total_blocks;
|
||||
buf->f_bfree = buf->f_bavail = 0;
|
||||
|
||||
|
||||
+161
-71
@@ -7,6 +7,19 @@
|
||||
#include <linux/security.h>
|
||||
#include "xattr.h"
|
||||
|
||||
static inline erofs_blk_t erofs_xattr_blkaddr(struct super_block *sb,
|
||||
unsigned int xattr_id)
|
||||
{
|
||||
return EROFS_SB(sb)->xattr_blkaddr +
|
||||
erofs_blknr(sb, xattr_id * sizeof(__u32));
|
||||
}
|
||||
|
||||
static inline unsigned int erofs_xattr_blkoff(struct super_block *sb,
|
||||
unsigned int xattr_id)
|
||||
{
|
||||
return erofs_blkoff(sb, xattr_id * sizeof(__u32));
|
||||
}
|
||||
|
||||
struct xattr_iter {
|
||||
struct super_block *sb;
|
||||
struct erofs_buf buf;
|
||||
@@ -16,7 +29,7 @@ struct xattr_iter {
|
||||
unsigned int ofs;
|
||||
};
|
||||
|
||||
static int init_inode_xattrs(struct inode *inode)
|
||||
static int erofs_init_inode_xattrs(struct inode *inode)
|
||||
{
|
||||
struct erofs_inode *const vi = EROFS_I(inode);
|
||||
struct xattr_iter it;
|
||||
@@ -68,8 +81,8 @@ static int init_inode_xattrs(struct inode *inode)
|
||||
}
|
||||
|
||||
it.buf = __EROFS_BUF_INITIALIZER;
|
||||
it.blkaddr = erofs_blknr(erofs_iloc(inode) + vi->inode_isize);
|
||||
it.ofs = erofs_blkoff(erofs_iloc(inode) + vi->inode_isize);
|
||||
it.blkaddr = erofs_blknr(sb, erofs_iloc(inode) + vi->inode_isize);
|
||||
it.ofs = erofs_blkoff(sb, erofs_iloc(inode) + vi->inode_isize);
|
||||
|
||||
/* read in shared xattr array (non-atomic, see kmalloc below) */
|
||||
it.kaddr = erofs_read_metabuf(&it.buf, sb, it.blkaddr, EROFS_KMAP);
|
||||
@@ -92,9 +105,9 @@ static int init_inode_xattrs(struct inode *inode)
|
||||
it.ofs += sizeof(struct erofs_xattr_ibody_header);
|
||||
|
||||
for (i = 0; i < vi->xattr_shared_count; ++i) {
|
||||
if (it.ofs >= EROFS_BLKSIZ) {
|
||||
if (it.ofs >= sb->s_blocksize) {
|
||||
/* cannot be unaligned */
|
||||
DBG_BUGON(it.ofs != EROFS_BLKSIZ);
|
||||
DBG_BUGON(it.ofs != sb->s_blocksize);
|
||||
|
||||
it.kaddr = erofs_read_metabuf(&it.buf, sb, ++it.blkaddr,
|
||||
EROFS_KMAP);
|
||||
@@ -139,15 +152,15 @@ struct xattr_iter_handlers {
|
||||
|
||||
static inline int xattr_iter_fixup(struct xattr_iter *it)
|
||||
{
|
||||
if (it->ofs < EROFS_BLKSIZ)
|
||||
if (it->ofs < it->sb->s_blocksize)
|
||||
return 0;
|
||||
|
||||
it->blkaddr += erofs_blknr(it->ofs);
|
||||
it->blkaddr += erofs_blknr(it->sb, it->ofs);
|
||||
it->kaddr = erofs_read_metabuf(&it->buf, it->sb, it->blkaddr,
|
||||
EROFS_KMAP);
|
||||
if (IS_ERR(it->kaddr))
|
||||
return PTR_ERR(it->kaddr);
|
||||
it->ofs = erofs_blkoff(it->ofs);
|
||||
it->ofs = erofs_blkoff(it->sb, it->ofs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -157,7 +170,8 @@ static int inline_xattr_iter_begin(struct xattr_iter *it,
|
||||
struct erofs_inode *const vi = EROFS_I(inode);
|
||||
unsigned int xattr_header_sz, inline_xattr_ofs;
|
||||
|
||||
xattr_header_sz = inlinexattr_header_size(inode);
|
||||
xattr_header_sz = sizeof(struct erofs_xattr_ibody_header) +
|
||||
sizeof(u32) * vi->xattr_shared_count;
|
||||
if (xattr_header_sz >= vi->xattr_isize) {
|
||||
DBG_BUGON(xattr_header_sz > vi->xattr_isize);
|
||||
return -ENOATTR;
|
||||
@@ -165,8 +179,8 @@ static int inline_xattr_iter_begin(struct xattr_iter *it,
|
||||
|
||||
inline_xattr_ofs = vi->inode_isize + xattr_header_sz;
|
||||
|
||||
it->blkaddr = erofs_blknr(erofs_iloc(inode) + inline_xattr_ofs);
|
||||
it->ofs = erofs_blkoff(erofs_iloc(inode) + inline_xattr_ofs);
|
||||
it->blkaddr = erofs_blknr(it->sb, erofs_iloc(inode) + inline_xattr_ofs);
|
||||
it->ofs = erofs_blkoff(it->sb, erofs_iloc(inode) + inline_xattr_ofs);
|
||||
it->kaddr = erofs_read_metabuf(&it->buf, inode->i_sb, it->blkaddr,
|
||||
EROFS_KMAP);
|
||||
if (IS_ERR(it->kaddr))
|
||||
@@ -222,8 +236,8 @@ static int xattr_foreach(struct xattr_iter *it,
|
||||
processed = 0;
|
||||
|
||||
while (processed < entry.e_name_len) {
|
||||
if (it->ofs >= EROFS_BLKSIZ) {
|
||||
DBG_BUGON(it->ofs > EROFS_BLKSIZ);
|
||||
if (it->ofs >= it->sb->s_blocksize) {
|
||||
DBG_BUGON(it->ofs > it->sb->s_blocksize);
|
||||
|
||||
err = xattr_iter_fixup(it);
|
||||
if (err)
|
||||
@@ -231,7 +245,7 @@ static int xattr_foreach(struct xattr_iter *it,
|
||||
it->ofs = 0;
|
||||
}
|
||||
|
||||
slice = min_t(unsigned int, EROFS_BLKSIZ - it->ofs,
|
||||
slice = min_t(unsigned int, it->sb->s_blocksize - it->ofs,
|
||||
entry.e_name_len - processed);
|
||||
|
||||
/* handle name */
|
||||
@@ -257,8 +271,8 @@ static int xattr_foreach(struct xattr_iter *it,
|
||||
}
|
||||
|
||||
while (processed < value_sz) {
|
||||
if (it->ofs >= EROFS_BLKSIZ) {
|
||||
DBG_BUGON(it->ofs > EROFS_BLKSIZ);
|
||||
if (it->ofs >= it->sb->s_blocksize) {
|
||||
DBG_BUGON(it->ofs > it->sb->s_blocksize);
|
||||
|
||||
err = xattr_iter_fixup(it);
|
||||
if (err)
|
||||
@@ -266,7 +280,7 @@ static int xattr_foreach(struct xattr_iter *it,
|
||||
it->ofs = 0;
|
||||
}
|
||||
|
||||
slice = min_t(unsigned int, EROFS_BLKSIZ - it->ofs,
|
||||
slice = min_t(unsigned int, it->sb->s_blocksize - it->ofs,
|
||||
value_sz - processed);
|
||||
op->value(it, processed, it->kaddr + it->ofs, slice);
|
||||
it->ofs += slice;
|
||||
@@ -283,17 +297,45 @@ struct getxattr_iter {
|
||||
struct xattr_iter it;
|
||||
|
||||
char *buffer;
|
||||
int buffer_size, index;
|
||||
int buffer_size, index, infix_len;
|
||||
struct qstr name;
|
||||
};
|
||||
|
||||
static int erofs_xattr_long_entrymatch(struct getxattr_iter *it,
|
||||
struct erofs_xattr_entry *entry)
|
||||
{
|
||||
struct erofs_sb_info *sbi = EROFS_SB(it->it.sb);
|
||||
struct erofs_xattr_prefix_item *pf = sbi->xattr_prefixes +
|
||||
(entry->e_name_index & EROFS_XATTR_LONG_PREFIX_MASK);
|
||||
|
||||
if (pf >= sbi->xattr_prefixes + sbi->xattr_prefix_count)
|
||||
return -ENOATTR;
|
||||
|
||||
if (it->index != pf->prefix->base_index ||
|
||||
it->name.len != entry->e_name_len + pf->infix_len)
|
||||
return -ENOATTR;
|
||||
|
||||
if (memcmp(it->name.name, pf->prefix->infix, pf->infix_len))
|
||||
return -ENOATTR;
|
||||
|
||||
it->infix_len = pf->infix_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xattr_entrymatch(struct xattr_iter *_it,
|
||||
struct erofs_xattr_entry *entry)
|
||||
{
|
||||
struct getxattr_iter *it = container_of(_it, struct getxattr_iter, it);
|
||||
|
||||
return (it->index != entry->e_name_index ||
|
||||
it->name.len != entry->e_name_len) ? -ENOATTR : 0;
|
||||
/* should also match the infix for long name prefixes */
|
||||
if (entry->e_name_index & EROFS_XATTR_LONG_PREFIX)
|
||||
return erofs_xattr_long_entrymatch(it, entry);
|
||||
|
||||
if (it->index != entry->e_name_index ||
|
||||
it->name.len != entry->e_name_len)
|
||||
return -ENOATTR;
|
||||
it->infix_len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xattr_namematch(struct xattr_iter *_it,
|
||||
@@ -301,7 +343,9 @@ static int xattr_namematch(struct xattr_iter *_it,
|
||||
{
|
||||
struct getxattr_iter *it = container_of(_it, struct getxattr_iter, it);
|
||||
|
||||
return memcmp(buf, it->name.name + processed, len) ? -ENOATTR : 0;
|
||||
if (memcmp(buf, it->name.name + it->infix_len + processed, len))
|
||||
return -ENOATTR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int xattr_checkbuffer(struct xattr_iter *_it,
|
||||
@@ -351,21 +395,18 @@ static int inline_getxattr(struct inode *inode, struct getxattr_iter *it)
|
||||
static int shared_getxattr(struct inode *inode, struct getxattr_iter *it)
|
||||
{
|
||||
struct erofs_inode *const vi = EROFS_I(inode);
|
||||
struct super_block *const sb = inode->i_sb;
|
||||
struct erofs_sb_info *const sbi = EROFS_SB(sb);
|
||||
unsigned int i;
|
||||
struct super_block *const sb = it->it.sb;
|
||||
unsigned int i, xsid;
|
||||
int ret = -ENOATTR;
|
||||
|
||||
for (i = 0; i < vi->xattr_shared_count; ++i) {
|
||||
erofs_blk_t blkaddr =
|
||||
xattrblock_addr(sbi, vi->xattr_shared_xattrs[i]);
|
||||
|
||||
it->it.ofs = xattrblock_offset(sbi, vi->xattr_shared_xattrs[i]);
|
||||
it->it.kaddr = erofs_read_metabuf(&it->it.buf, sb, blkaddr,
|
||||
EROFS_KMAP);
|
||||
xsid = vi->xattr_shared_xattrs[i];
|
||||
it->it.blkaddr = erofs_xattr_blkaddr(sb, xsid);
|
||||
it->it.ofs = erofs_xattr_blkoff(sb, xsid);
|
||||
it->it.kaddr = erofs_read_metabuf(&it->it.buf, sb,
|
||||
it->it.blkaddr, EROFS_KMAP);
|
||||
if (IS_ERR(it->it.kaddr))
|
||||
return PTR_ERR(it->it.kaddr);
|
||||
it->it.blkaddr = blkaddr;
|
||||
|
||||
ret = xattr_foreach(&it->it, &find_xattr_handlers, NULL);
|
||||
if (ret != -ENOATTR)
|
||||
@@ -394,7 +435,7 @@ int erofs_getxattr(struct inode *inode, int index,
|
||||
if (!name)
|
||||
return -EINVAL;
|
||||
|
||||
ret = init_inode_xattrs(inode);
|
||||
ret = erofs_init_inode_xattrs(inode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -421,20 +462,9 @@ static int erofs_xattr_generic_get(const struct xattr_handler *handler,
|
||||
struct dentry *unused, struct inode *inode,
|
||||
const char *name, void *buffer, size_t size)
|
||||
{
|
||||
struct erofs_sb_info *const sbi = EROFS_I_SB(inode);
|
||||
|
||||
switch (handler->flags) {
|
||||
case EROFS_XATTR_INDEX_USER:
|
||||
if (!test_opt(&sbi->opt, XATTR_USER))
|
||||
return -EOPNOTSUPP;
|
||||
break;
|
||||
case EROFS_XATTR_INDEX_TRUSTED:
|
||||
break;
|
||||
case EROFS_XATTR_INDEX_SECURITY:
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
if (handler->flags == EROFS_XATTR_INDEX_USER &&
|
||||
!test_opt(&EROFS_I_SB(inode)->opt, XATTR_USER))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return erofs_getxattr(inode, handler->flags, name, buffer, size);
|
||||
}
|
||||
@@ -463,10 +493,6 @@ const struct xattr_handler __maybe_unused erofs_xattr_security_handler = {
|
||||
|
||||
const struct xattr_handler *erofs_xattr_handlers[] = {
|
||||
&erofs_xattr_user_handler,
|
||||
#ifdef CONFIG_EROFS_FS_POSIX_ACL
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
#endif
|
||||
&erofs_xattr_trusted_handler,
|
||||
#ifdef CONFIG_EROFS_FS_SECURITY
|
||||
&erofs_xattr_security_handler,
|
||||
@@ -487,29 +513,40 @@ static int xattr_entrylist(struct xattr_iter *_it,
|
||||
{
|
||||
struct listxattr_iter *it =
|
||||
container_of(_it, struct listxattr_iter, it);
|
||||
unsigned int prefix_len;
|
||||
const char *prefix;
|
||||
unsigned int base_index = entry->e_name_index;
|
||||
unsigned int prefix_len, infix_len = 0;
|
||||
const char *prefix, *infix = NULL;
|
||||
|
||||
const struct xattr_handler *h =
|
||||
erofs_xattr_handler(entry->e_name_index);
|
||||
if (entry->e_name_index & EROFS_XATTR_LONG_PREFIX) {
|
||||
struct erofs_sb_info *sbi = EROFS_SB(_it->sb);
|
||||
struct erofs_xattr_prefix_item *pf = sbi->xattr_prefixes +
|
||||
(entry->e_name_index & EROFS_XATTR_LONG_PREFIX_MASK);
|
||||
|
||||
if (!h || (h->list && !h->list(it->dentry)))
|
||||
if (pf >= sbi->xattr_prefixes + sbi->xattr_prefix_count)
|
||||
return 1;
|
||||
infix = pf->prefix->infix;
|
||||
infix_len = pf->infix_len;
|
||||
base_index = pf->prefix->base_index;
|
||||
}
|
||||
|
||||
prefix = erofs_xattr_prefix(base_index, it->dentry);
|
||||
if (!prefix)
|
||||
return 1;
|
||||
|
||||
prefix = xattr_prefix(h);
|
||||
prefix_len = strlen(prefix);
|
||||
|
||||
if (!it->buffer) {
|
||||
it->buffer_ofs += prefix_len + entry->e_name_len + 1;
|
||||
it->buffer_ofs += prefix_len + infix_len +
|
||||
entry->e_name_len + 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (it->buffer_ofs + prefix_len
|
||||
if (it->buffer_ofs + prefix_len + infix_len +
|
||||
+ entry->e_name_len + 1 > it->buffer_size)
|
||||
return -ERANGE;
|
||||
|
||||
memcpy(it->buffer + it->buffer_ofs, prefix, prefix_len);
|
||||
it->buffer_ofs += prefix_len;
|
||||
memcpy(it->buffer + it->buffer_ofs + prefix_len, infix, infix_len);
|
||||
it->buffer_ofs += prefix_len + infix_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -563,21 +600,18 @@ static int shared_listxattr(struct listxattr_iter *it)
|
||||
{
|
||||
struct inode *const inode = d_inode(it->dentry);
|
||||
struct erofs_inode *const vi = EROFS_I(inode);
|
||||
struct super_block *const sb = inode->i_sb;
|
||||
struct erofs_sb_info *const sbi = EROFS_SB(sb);
|
||||
unsigned int i;
|
||||
struct super_block *const sb = it->it.sb;
|
||||
unsigned int i, xsid;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < vi->xattr_shared_count; ++i) {
|
||||
erofs_blk_t blkaddr =
|
||||
xattrblock_addr(sbi, vi->xattr_shared_xattrs[i]);
|
||||
|
||||
it->it.ofs = xattrblock_offset(sbi, vi->xattr_shared_xattrs[i]);
|
||||
it->it.kaddr = erofs_read_metabuf(&it->it.buf, sb, blkaddr,
|
||||
EROFS_KMAP);
|
||||
xsid = vi->xattr_shared_xattrs[i];
|
||||
it->it.blkaddr = erofs_xattr_blkaddr(sb, xsid);
|
||||
it->it.ofs = erofs_xattr_blkoff(sb, xsid);
|
||||
it->it.kaddr = erofs_read_metabuf(&it->it.buf, sb,
|
||||
it->it.blkaddr, EROFS_KMAP);
|
||||
if (IS_ERR(it->it.kaddr))
|
||||
return PTR_ERR(it->it.kaddr);
|
||||
it->it.blkaddr = blkaddr;
|
||||
|
||||
ret = xattr_foreach(&it->it, &list_xattr_handlers, NULL);
|
||||
if (ret)
|
||||
@@ -592,7 +626,7 @@ ssize_t erofs_listxattr(struct dentry *dentry,
|
||||
int ret;
|
||||
struct listxattr_iter it;
|
||||
|
||||
ret = init_inode_xattrs(d_inode(dentry));
|
||||
ret = erofs_init_inode_xattrs(d_inode(dentry));
|
||||
if (ret == -ENOATTR)
|
||||
return 0;
|
||||
if (ret)
|
||||
@@ -613,6 +647,62 @@ ssize_t erofs_listxattr(struct dentry *dentry,
|
||||
return ret;
|
||||
}
|
||||
|
||||
void erofs_xattr_prefixes_cleanup(struct super_block *sb)
|
||||
{
|
||||
struct erofs_sb_info *sbi = EROFS_SB(sb);
|
||||
int i;
|
||||
|
||||
if (sbi->xattr_prefixes) {
|
||||
for (i = 0; i < sbi->xattr_prefix_count; i++)
|
||||
kfree(sbi->xattr_prefixes[i].prefix);
|
||||
kfree(sbi->xattr_prefixes);
|
||||
sbi->xattr_prefixes = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int erofs_xattr_prefixes_init(struct super_block *sb)
|
||||
{
|
||||
struct erofs_sb_info *sbi = EROFS_SB(sb);
|
||||
struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
|
||||
erofs_off_t pos = (erofs_off_t)sbi->xattr_prefix_start << 2;
|
||||
struct erofs_xattr_prefix_item *pfs;
|
||||
int ret = 0, i, len;
|
||||
|
||||
if (!sbi->xattr_prefix_count)
|
||||
return 0;
|
||||
|
||||
pfs = kzalloc(sbi->xattr_prefix_count * sizeof(*pfs), GFP_KERNEL);
|
||||
if (!pfs)
|
||||
return -ENOMEM;
|
||||
|
||||
if (erofs_sb_has_fragments(sbi))
|
||||
buf.inode = sbi->packed_inode;
|
||||
else
|
||||
erofs_init_metabuf(&buf, sb);
|
||||
|
||||
for (i = 0; i < sbi->xattr_prefix_count; i++) {
|
||||
void *ptr = erofs_read_metadata(sb, &buf, &pos, &len);
|
||||
|
||||
if (IS_ERR(ptr)) {
|
||||
ret = PTR_ERR(ptr);
|
||||
break;
|
||||
} else if (len < sizeof(*pfs->prefix) ||
|
||||
len > EROFS_NAME_LEN + sizeof(*pfs->prefix)) {
|
||||
kfree(ptr);
|
||||
ret = -EFSCORRUPTED;
|
||||
break;
|
||||
}
|
||||
pfs[i].prefix = ptr;
|
||||
pfs[i].infix_len = len - sizeof(struct erofs_xattr_long_prefix);
|
||||
}
|
||||
|
||||
erofs_put_metabuf(&buf);
|
||||
sbi->xattr_prefixes = pfs;
|
||||
if (ret)
|
||||
erofs_xattr_prefixes_cleanup(sb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EROFS_FS_POSIX_ACL
|
||||
struct posix_acl *erofs_get_acl(struct inode *inode, int type, bool rcu)
|
||||
{
|
||||
|
||||
+17
-30
@@ -13,43 +13,21 @@
|
||||
/* Attribute not found */
|
||||
#define ENOATTR ENODATA
|
||||
|
||||
static inline unsigned int inlinexattr_header_size(struct inode *inode)
|
||||
{
|
||||
return sizeof(struct erofs_xattr_ibody_header) +
|
||||
sizeof(u32) * EROFS_I(inode)->xattr_shared_count;
|
||||
}
|
||||
|
||||
static inline erofs_blk_t xattrblock_addr(struct erofs_sb_info *sbi,
|
||||
unsigned int xattr_id)
|
||||
{
|
||||
#ifdef CONFIG_EROFS_FS_XATTR
|
||||
return sbi->xattr_blkaddr +
|
||||
xattr_id * sizeof(__u32) / EROFS_BLKSIZ;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline unsigned int xattrblock_offset(struct erofs_sb_info *sbi,
|
||||
unsigned int xattr_id)
|
||||
{
|
||||
return (xattr_id * sizeof(__u32)) % EROFS_BLKSIZ;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_EROFS_FS_XATTR
|
||||
extern const struct xattr_handler erofs_xattr_user_handler;
|
||||
extern const struct xattr_handler erofs_xattr_trusted_handler;
|
||||
extern const struct xattr_handler erofs_xattr_security_handler;
|
||||
|
||||
static inline const struct xattr_handler *erofs_xattr_handler(unsigned int idx)
|
||||
static inline const char *erofs_xattr_prefix(unsigned int idx,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
const struct xattr_handler *handler = NULL;
|
||||
|
||||
static const struct xattr_handler *xattr_handler_map[] = {
|
||||
[EROFS_XATTR_INDEX_USER] = &erofs_xattr_user_handler,
|
||||
#ifdef CONFIG_EROFS_FS_POSIX_ACL
|
||||
[EROFS_XATTR_INDEX_POSIX_ACL_ACCESS] =
|
||||
&posix_acl_access_xattr_handler,
|
||||
[EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT] =
|
||||
&posix_acl_default_xattr_handler,
|
||||
[EROFS_XATTR_INDEX_POSIX_ACL_ACCESS] = &nop_posix_acl_access,
|
||||
[EROFS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &nop_posix_acl_default,
|
||||
#endif
|
||||
[EROFS_XATTR_INDEX_TRUSTED] = &erofs_xattr_trusted_handler,
|
||||
#ifdef CONFIG_EROFS_FS_SECURITY
|
||||
@@ -57,15 +35,24 @@ static inline const struct xattr_handler *erofs_xattr_handler(unsigned int idx)
|
||||
#endif
|
||||
};
|
||||
|
||||
return idx && idx < ARRAY_SIZE(xattr_handler_map) ?
|
||||
xattr_handler_map[idx] : NULL;
|
||||
if (idx && idx < ARRAY_SIZE(xattr_handler_map))
|
||||
handler = xattr_handler_map[idx];
|
||||
|
||||
if (!xattr_handler_can_list(handler, dentry))
|
||||
return NULL;
|
||||
|
||||
return xattr_prefix(handler);
|
||||
}
|
||||
|
||||
extern const struct xattr_handler *erofs_xattr_handlers[];
|
||||
|
||||
int erofs_xattr_prefixes_init(struct super_block *sb);
|
||||
void erofs_xattr_prefixes_cleanup(struct super_block *sb);
|
||||
int erofs_getxattr(struct inode *, int, const char *, void *, size_t);
|
||||
ssize_t erofs_listxattr(struct dentry *, char *, size_t);
|
||||
#else
|
||||
static inline int erofs_xattr_prefixes_init(struct super_block *sb) { return 0; }
|
||||
static inline void erofs_xattr_prefixes_cleanup(struct super_block *sb) {}
|
||||
static inline int erofs_getxattr(struct inode *inode, int index,
|
||||
const char *name, void *buffer,
|
||||
size_t buffer_size)
|
||||
|
||||
+11
-14
@@ -807,7 +807,7 @@ static int z_erofs_register_pcluster(struct z_erofs_decompress_frontend *fe)
|
||||
|
||||
if (ztailpacking) {
|
||||
pcl->obj.index = 0; /* which indicates ztailpacking */
|
||||
pcl->pageofs_in = erofs_blkoff(map->m_pa);
|
||||
pcl->pageofs_in = erofs_blkoff(fe->inode->i_sb, map->m_pa);
|
||||
pcl->tailpacking_size = map->m_plen;
|
||||
} else {
|
||||
pcl->obj.index = map->m_pa >> PAGE_SHIFT;
|
||||
@@ -930,6 +930,7 @@ static int z_erofs_read_fragment(struct inode *inode, erofs_off_t pos,
|
||||
struct page *page, unsigned int pageofs,
|
||||
unsigned int len)
|
||||
{
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct inode *packed_inode = EROFS_I_SB(inode)->packed_inode;
|
||||
struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
|
||||
u8 *src, *dst;
|
||||
@@ -938,19 +939,19 @@ static int z_erofs_read_fragment(struct inode *inode, erofs_off_t pos,
|
||||
if (!packed_inode)
|
||||
return -EFSCORRUPTED;
|
||||
|
||||
buf.inode = packed_inode;
|
||||
pos += EROFS_I(inode)->z_fragmentoff;
|
||||
for (i = 0; i < len; i += cnt) {
|
||||
cnt = min_t(unsigned int, len - i,
|
||||
EROFS_BLKSIZ - erofs_blkoff(pos));
|
||||
src = erofs_bread(&buf, packed_inode,
|
||||
erofs_blknr(pos), EROFS_KMAP);
|
||||
sb->s_blocksize - erofs_blkoff(sb, pos));
|
||||
src = erofs_bread(&buf, erofs_blknr(sb, pos), EROFS_KMAP);
|
||||
if (IS_ERR(src)) {
|
||||
erofs_put_metabuf(&buf);
|
||||
return PTR_ERR(src);
|
||||
}
|
||||
|
||||
dst = kmap_local_page(page);
|
||||
memcpy(dst + pageofs + i, src + erofs_blkoff(pos), cnt);
|
||||
memcpy(dst + pageofs + i, src + erofs_blkoff(sb, pos), cnt);
|
||||
kunmap_local(dst);
|
||||
pos += cnt;
|
||||
}
|
||||
@@ -978,8 +979,6 @@ repeat:
|
||||
|
||||
if (offset + cur < map->m_la ||
|
||||
offset + cur >= map->m_la + map->m_llen) {
|
||||
erofs_dbg("out-of-range map @ pos %llu", offset + cur);
|
||||
|
||||
if (z_erofs_collector_end(fe))
|
||||
fe->backmost = false;
|
||||
map->m_la = offset + cur;
|
||||
@@ -1005,7 +1004,8 @@ repeat:
|
||||
void *mp;
|
||||
|
||||
mp = erofs_read_metabuf(&fe->map.buf, inode->i_sb,
|
||||
erofs_blknr(map->m_pa), EROFS_NO_KMAP);
|
||||
erofs_blknr(inode->i_sb, map->m_pa),
|
||||
EROFS_NO_KMAP);
|
||||
if (IS_ERR(mp)) {
|
||||
err = PTR_ERR(mp);
|
||||
erofs_err(inode->i_sb,
|
||||
@@ -1103,9 +1103,6 @@ out:
|
||||
if (err)
|
||||
z_erofs_page_mark_eio(page);
|
||||
z_erofs_onlinepage_endio(page);
|
||||
|
||||
erofs_dbg("%s, finish page: %pK spiltted: %u map->m_llen %llu",
|
||||
__func__, page, spiltted, map->m_llen);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1726,11 +1723,11 @@ static void z_erofs_submit_queue(struct z_erofs_decompress_frontend *f,
|
||||
|
||||
/* no device id here, thus it will always succeed */
|
||||
mdev = (struct erofs_map_dev) {
|
||||
.m_pa = blknr_to_addr(pcl->obj.index),
|
||||
.m_pa = erofs_pos(sb, pcl->obj.index),
|
||||
};
|
||||
(void)erofs_map_dev(sb, &mdev);
|
||||
|
||||
cur = erofs_blknr(mdev.m_pa);
|
||||
cur = erofs_blknr(sb, mdev.m_pa);
|
||||
end = cur + pcl->pclusterpages;
|
||||
|
||||
do {
|
||||
@@ -1764,7 +1761,7 @@ submit_bio_retry:
|
||||
|
||||
last_bdev = mdev.m_bdev;
|
||||
bio->bi_iter.bi_sector = (sector_t)cur <<
|
||||
LOG_SECTORS_PER_BLOCK;
|
||||
(sb->s_blocksize_bits - 9);
|
||||
bio->bi_private = q[JQ_SUBMIT];
|
||||
if (f->readahead)
|
||||
bio->bi_opf |= REQ_RAHEAD;
|
||||
|
||||
+74
-92
@@ -7,24 +7,6 @@
|
||||
#include <asm/unaligned.h>
|
||||
#include <trace/events/erofs.h>
|
||||
|
||||
int z_erofs_fill_inode(struct inode *inode)
|
||||
{
|
||||
struct erofs_inode *const vi = EROFS_I(inode);
|
||||
struct erofs_sb_info *sbi = EROFS_SB(inode->i_sb);
|
||||
|
||||
if (!erofs_sb_has_big_pcluster(sbi) &&
|
||||
!erofs_sb_has_ztailpacking(sbi) && !erofs_sb_has_fragments(sbi) &&
|
||||
vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY) {
|
||||
vi->z_advise = 0;
|
||||
vi->z_algorithmtype[0] = 0;
|
||||
vi->z_algorithmtype[1] = 0;
|
||||
vi->z_logical_clusterbits = LOG_BLOCK_SIZE;
|
||||
set_bit(EROFS_I_Z_INITED_BIT, &vi->flags);
|
||||
}
|
||||
inode->i_mapping->a_ops = &z_erofs_aops;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct z_erofs_maprecorder {
|
||||
struct inode *inode;
|
||||
struct erofs_map_blocks *map;
|
||||
@@ -45,47 +27,50 @@ static int legacy_load_cluster_from_disk(struct z_erofs_maprecorder *m,
|
||||
{
|
||||
struct inode *const inode = m->inode;
|
||||
struct erofs_inode *const vi = EROFS_I(inode);
|
||||
const erofs_off_t pos =
|
||||
Z_EROFS_VLE_LEGACY_INDEX_ALIGN(erofs_iloc(inode) +
|
||||
vi->inode_isize + vi->xattr_isize) +
|
||||
lcn * sizeof(struct z_erofs_vle_decompressed_index);
|
||||
struct z_erofs_vle_decompressed_index *di;
|
||||
const erofs_off_t pos = Z_EROFS_FULL_INDEX_ALIGN(erofs_iloc(inode) +
|
||||
vi->inode_isize + vi->xattr_isize) +
|
||||
lcn * sizeof(struct z_erofs_lcluster_index);
|
||||
struct z_erofs_lcluster_index *di;
|
||||
unsigned int advise, type;
|
||||
|
||||
m->kaddr = erofs_read_metabuf(&m->map->buf, inode->i_sb,
|
||||
erofs_blknr(pos), EROFS_KMAP);
|
||||
erofs_blknr(inode->i_sb, pos), EROFS_KMAP);
|
||||
if (IS_ERR(m->kaddr))
|
||||
return PTR_ERR(m->kaddr);
|
||||
|
||||
m->nextpackoff = pos + sizeof(struct z_erofs_vle_decompressed_index);
|
||||
m->nextpackoff = pos + sizeof(struct z_erofs_lcluster_index);
|
||||
m->lcn = lcn;
|
||||
di = m->kaddr + erofs_blkoff(pos);
|
||||
di = m->kaddr + erofs_blkoff(inode->i_sb, pos);
|
||||
|
||||
advise = le16_to_cpu(di->di_advise);
|
||||
type = (advise >> Z_EROFS_VLE_DI_CLUSTER_TYPE_BIT) &
|
||||
((1 << Z_EROFS_VLE_DI_CLUSTER_TYPE_BITS) - 1);
|
||||
type = (advise >> Z_EROFS_LI_LCLUSTER_TYPE_BIT) &
|
||||
((1 << Z_EROFS_LI_LCLUSTER_TYPE_BITS) - 1);
|
||||
switch (type) {
|
||||
case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
|
||||
case Z_EROFS_LCLUSTER_TYPE_NONHEAD:
|
||||
m->clusterofs = 1 << vi->z_logical_clusterbits;
|
||||
m->delta[0] = le16_to_cpu(di->di_u.delta[0]);
|
||||
if (m->delta[0] & Z_EROFS_VLE_DI_D0_CBLKCNT) {
|
||||
if (m->delta[0] & Z_EROFS_LI_D0_CBLKCNT) {
|
||||
if (!(vi->z_advise & (Z_EROFS_ADVISE_BIG_PCLUSTER_1 |
|
||||
Z_EROFS_ADVISE_BIG_PCLUSTER_2))) {
|
||||
DBG_BUGON(1);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
m->compressedblks = m->delta[0] &
|
||||
~Z_EROFS_VLE_DI_D0_CBLKCNT;
|
||||
~Z_EROFS_LI_D0_CBLKCNT;
|
||||
m->delta[0] = 1;
|
||||
}
|
||||
m->delta[1] = le16_to_cpu(di->di_u.delta[1]);
|
||||
break;
|
||||
case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
|
||||
case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1:
|
||||
case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2:
|
||||
if (advise & Z_EROFS_VLE_DI_PARTIAL_REF)
|
||||
case Z_EROFS_LCLUSTER_TYPE_PLAIN:
|
||||
case Z_EROFS_LCLUSTER_TYPE_HEAD1:
|
||||
case Z_EROFS_LCLUSTER_TYPE_HEAD2:
|
||||
if (advise & Z_EROFS_LI_PARTIAL_REF)
|
||||
m->partialref = true;
|
||||
m->clusterofs = le16_to_cpu(di->di_clusterofs);
|
||||
if (m->clusterofs >= 1 << vi->z_logical_clusterbits) {
|
||||
DBG_BUGON(1);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
m->pblk = le32_to_cpu(di->di_u.blkaddr);
|
||||
break;
|
||||
default:
|
||||
@@ -121,13 +106,13 @@ static int get_compacted_la_distance(unsigned int lclusterbits,
|
||||
lo = decode_compactedbits(lclusterbits, lomask,
|
||||
in, encodebits * i, &type);
|
||||
|
||||
if (type != Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD)
|
||||
if (type != Z_EROFS_LCLUSTER_TYPE_NONHEAD)
|
||||
return d1;
|
||||
++d1;
|
||||
} while (++i < vcnt);
|
||||
|
||||
/* vcnt - 1 (Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) item */
|
||||
if (!(lo & Z_EROFS_VLE_DI_D0_CBLKCNT))
|
||||
/* vcnt - 1 (Z_EROFS_LCLUSTER_TYPE_NONHEAD) item */
|
||||
if (!(lo & Z_EROFS_LI_D0_CBLKCNT))
|
||||
d1 += lo - 1;
|
||||
return d1;
|
||||
}
|
||||
@@ -156,7 +141,7 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m,
|
||||
(vcnt << amortizedshift);
|
||||
big_pcluster = vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1;
|
||||
encodebits = ((vcnt << amortizedshift) - sizeof(__le32)) * 8 / vcnt;
|
||||
eofs = erofs_blkoff(pos);
|
||||
eofs = erofs_blkoff(m->inode->i_sb, pos);
|
||||
base = round_down(eofs, vcnt << amortizedshift);
|
||||
in = m->kaddr + base;
|
||||
|
||||
@@ -165,19 +150,19 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m,
|
||||
lo = decode_compactedbits(lclusterbits, lomask,
|
||||
in, encodebits * i, &type);
|
||||
m->type = type;
|
||||
if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) {
|
||||
if (type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) {
|
||||
m->clusterofs = 1 << lclusterbits;
|
||||
|
||||
/* figure out lookahead_distance: delta[1] if needed */
|
||||
if (lookahead)
|
||||
m->delta[1] = get_compacted_la_distance(lclusterbits,
|
||||
encodebits, vcnt, in, i);
|
||||
if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT) {
|
||||
if (lo & Z_EROFS_LI_D0_CBLKCNT) {
|
||||
if (!big_pcluster) {
|
||||
DBG_BUGON(1);
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
m->compressedblks = lo & ~Z_EROFS_VLE_DI_D0_CBLKCNT;
|
||||
m->compressedblks = lo & ~Z_EROFS_LI_D0_CBLKCNT;
|
||||
m->delta[0] = 1;
|
||||
return 0;
|
||||
} else if (i + 1 != (int)vcnt) {
|
||||
@@ -191,9 +176,9 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m,
|
||||
*/
|
||||
lo = decode_compactedbits(lclusterbits, lomask,
|
||||
in, encodebits * (i - 1), &type);
|
||||
if (type != Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD)
|
||||
if (type != Z_EROFS_LCLUSTER_TYPE_NONHEAD)
|
||||
lo = 0;
|
||||
else if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT)
|
||||
else if (lo & Z_EROFS_LI_D0_CBLKCNT)
|
||||
lo = 1;
|
||||
m->delta[0] = lo + 1;
|
||||
return 0;
|
||||
@@ -207,7 +192,7 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m,
|
||||
--i;
|
||||
lo = decode_compactedbits(lclusterbits, lomask,
|
||||
in, encodebits * i, &type);
|
||||
if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD)
|
||||
if (type == Z_EROFS_LCLUSTER_TYPE_NONHEAD)
|
||||
i -= lo;
|
||||
|
||||
if (i >= 0)
|
||||
@@ -219,10 +204,10 @@ static int unpack_compacted_index(struct z_erofs_maprecorder *m,
|
||||
--i;
|
||||
lo = decode_compactedbits(lclusterbits, lomask,
|
||||
in, encodebits * i, &type);
|
||||
if (type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) {
|
||||
if (lo & Z_EROFS_VLE_DI_D0_CBLKCNT) {
|
||||
if (type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) {
|
||||
if (lo & Z_EROFS_LI_D0_CBLKCNT) {
|
||||
--i;
|
||||
nblk += lo & ~Z_EROFS_VLE_DI_D0_CBLKCNT;
|
||||
nblk += lo & ~Z_EROFS_LI_D0_CBLKCNT;
|
||||
continue;
|
||||
}
|
||||
/* bigpcluster shouldn't have plain d0 == 1 */
|
||||
@@ -249,7 +234,7 @@ static int compacted_load_cluster_from_disk(struct z_erofs_maprecorder *m,
|
||||
const unsigned int lclusterbits = vi->z_logical_clusterbits;
|
||||
const erofs_off_t ebase = sizeof(struct z_erofs_map_header) +
|
||||
ALIGN(erofs_iloc(inode) + vi->inode_isize + vi->xattr_isize, 8);
|
||||
const unsigned int totalidx = DIV_ROUND_UP(inode->i_size, EROFS_BLKSIZ);
|
||||
unsigned int totalidx = erofs_iblks(inode);
|
||||
unsigned int compacted_4b_initial, compacted_2b;
|
||||
unsigned int amortizedshift;
|
||||
erofs_off_t pos;
|
||||
@@ -290,7 +275,7 @@ static int compacted_load_cluster_from_disk(struct z_erofs_maprecorder *m,
|
||||
out:
|
||||
pos += lcn * (1 << amortizedshift);
|
||||
m->kaddr = erofs_read_metabuf(&m->map->buf, inode->i_sb,
|
||||
erofs_blknr(pos), EROFS_KMAP);
|
||||
erofs_blknr(inode->i_sb, pos), EROFS_KMAP);
|
||||
if (IS_ERR(m->kaddr))
|
||||
return PTR_ERR(m->kaddr);
|
||||
return unpack_compacted_index(m, amortizedshift, pos, lookahead);
|
||||
@@ -301,10 +286,10 @@ static int z_erofs_load_cluster_from_disk(struct z_erofs_maprecorder *m,
|
||||
{
|
||||
const unsigned int datamode = EROFS_I(m->inode)->datalayout;
|
||||
|
||||
if (datamode == EROFS_INODE_FLAT_COMPRESSION_LEGACY)
|
||||
if (datamode == EROFS_INODE_COMPRESSED_FULL)
|
||||
return legacy_load_cluster_from_disk(m, lcn);
|
||||
|
||||
if (datamode == EROFS_INODE_FLAT_COMPRESSION)
|
||||
if (datamode == EROFS_INODE_COMPRESSED_COMPACT)
|
||||
return compacted_load_cluster_from_disk(m, lcn, lookahead);
|
||||
|
||||
return -EINVAL;
|
||||
@@ -326,7 +311,7 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
|
||||
return err;
|
||||
|
||||
switch (m->type) {
|
||||
case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
|
||||
case Z_EROFS_LCLUSTER_TYPE_NONHEAD:
|
||||
if (!m->delta[0]) {
|
||||
erofs_err(m->inode->i_sb,
|
||||
"invalid lookback distance 0 @ nid %llu",
|
||||
@@ -336,9 +321,9 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
|
||||
}
|
||||
lookback_distance = m->delta[0];
|
||||
continue;
|
||||
case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
|
||||
case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1:
|
||||
case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2:
|
||||
case Z_EROFS_LCLUSTER_TYPE_PLAIN:
|
||||
case Z_EROFS_LCLUSTER_TYPE_HEAD1:
|
||||
case Z_EROFS_LCLUSTER_TYPE_HEAD2:
|
||||
m->headtype = m->type;
|
||||
m->map->m_la = (lcn << lclusterbits) | m->clusterofs;
|
||||
return 0;
|
||||
@@ -360,21 +345,22 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m,
|
||||
static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
|
||||
unsigned int initial_lcn)
|
||||
{
|
||||
struct super_block *sb = m->inode->i_sb;
|
||||
struct erofs_inode *const vi = EROFS_I(m->inode);
|
||||
struct erofs_map_blocks *const map = m->map;
|
||||
const unsigned int lclusterbits = vi->z_logical_clusterbits;
|
||||
unsigned long lcn;
|
||||
int err;
|
||||
|
||||
DBG_BUGON(m->type != Z_EROFS_VLE_CLUSTER_TYPE_PLAIN &&
|
||||
m->type != Z_EROFS_VLE_CLUSTER_TYPE_HEAD1 &&
|
||||
m->type != Z_EROFS_VLE_CLUSTER_TYPE_HEAD2);
|
||||
DBG_BUGON(m->type != Z_EROFS_LCLUSTER_TYPE_PLAIN &&
|
||||
m->type != Z_EROFS_LCLUSTER_TYPE_HEAD1 &&
|
||||
m->type != Z_EROFS_LCLUSTER_TYPE_HEAD2);
|
||||
DBG_BUGON(m->type != m->headtype);
|
||||
|
||||
if (m->headtype == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN ||
|
||||
((m->headtype == Z_EROFS_VLE_CLUSTER_TYPE_HEAD1) &&
|
||||
if (m->headtype == Z_EROFS_LCLUSTER_TYPE_PLAIN ||
|
||||
((m->headtype == Z_EROFS_LCLUSTER_TYPE_HEAD1) &&
|
||||
!(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1)) ||
|
||||
((m->headtype == Z_EROFS_VLE_CLUSTER_TYPE_HEAD2) &&
|
||||
((m->headtype == Z_EROFS_LCLUSTER_TYPE_HEAD2) &&
|
||||
!(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_2))) {
|
||||
map->m_plen = 1ULL << lclusterbits;
|
||||
return 0;
|
||||
@@ -396,19 +382,19 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
|
||||
* BUG_ON in the debugging mode only for developers to notice that.
|
||||
*/
|
||||
DBG_BUGON(lcn == initial_lcn &&
|
||||
m->type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD);
|
||||
m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD);
|
||||
|
||||
switch (m->type) {
|
||||
case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
|
||||
case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1:
|
||||
case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2:
|
||||
case Z_EROFS_LCLUSTER_TYPE_PLAIN:
|
||||
case Z_EROFS_LCLUSTER_TYPE_HEAD1:
|
||||
case Z_EROFS_LCLUSTER_TYPE_HEAD2:
|
||||
/*
|
||||
* if the 1st NONHEAD lcluster is actually PLAIN or HEAD type
|
||||
* rather than CBLKCNT, it's a 1 lcluster-sized pcluster.
|
||||
*/
|
||||
m->compressedblks = 1 << (lclusterbits - LOG_BLOCK_SIZE);
|
||||
m->compressedblks = 1 << (lclusterbits - sb->s_blocksize_bits);
|
||||
break;
|
||||
case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
|
||||
case Z_EROFS_LCLUSTER_TYPE_NONHEAD:
|
||||
if (m->delta[0] != 1)
|
||||
goto err_bonus_cblkcnt;
|
||||
if (m->compressedblks)
|
||||
@@ -422,7 +408,7 @@ static int z_erofs_get_extent_compressedlen(struct z_erofs_maprecorder *m,
|
||||
return -EFSCORRUPTED;
|
||||
}
|
||||
out:
|
||||
map->m_plen = (u64)m->compressedblks << LOG_BLOCK_SIZE;
|
||||
map->m_plen = erofs_pos(sb, m->compressedblks);
|
||||
return 0;
|
||||
err_bonus_cblkcnt:
|
||||
erofs_err(m->inode->i_sb,
|
||||
@@ -452,12 +438,12 @@ static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (m->type == Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD) {
|
||||
if (m->type == Z_EROFS_LCLUSTER_TYPE_NONHEAD) {
|
||||
DBG_BUGON(!m->delta[1] &&
|
||||
m->clusterofs != 1 << lclusterbits);
|
||||
} else if (m->type == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN ||
|
||||
m->type == Z_EROFS_VLE_CLUSTER_TYPE_HEAD1 ||
|
||||
m->type == Z_EROFS_VLE_CLUSTER_TYPE_HEAD2) {
|
||||
} else if (m->type == Z_EROFS_LCLUSTER_TYPE_PLAIN ||
|
||||
m->type == Z_EROFS_LCLUSTER_TYPE_HEAD1 ||
|
||||
m->type == Z_EROFS_LCLUSTER_TYPE_HEAD2) {
|
||||
/* go on until the next HEAD lcluster */
|
||||
if (lcn != headlcn)
|
||||
break;
|
||||
@@ -476,8 +462,7 @@ static int z_erofs_get_extent_decompressedlen(struct z_erofs_maprecorder *m)
|
||||
}
|
||||
|
||||
static int z_erofs_do_map_blocks(struct inode *inode,
|
||||
struct erofs_map_blocks *map,
|
||||
int flags)
|
||||
struct erofs_map_blocks *map, int flags)
|
||||
{
|
||||
struct erofs_inode *const vi = EROFS_I(inode);
|
||||
bool ztailpacking = vi->z_advise & Z_EROFS_ADVISE_INLINE_PCLUSTER;
|
||||
@@ -507,9 +492,9 @@ static int z_erofs_do_map_blocks(struct inode *inode,
|
||||
end = (m.lcn + 1ULL) << lclusterbits;
|
||||
|
||||
switch (m.type) {
|
||||
case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN:
|
||||
case Z_EROFS_VLE_CLUSTER_TYPE_HEAD1:
|
||||
case Z_EROFS_VLE_CLUSTER_TYPE_HEAD2:
|
||||
case Z_EROFS_LCLUSTER_TYPE_PLAIN:
|
||||
case Z_EROFS_LCLUSTER_TYPE_HEAD1:
|
||||
case Z_EROFS_LCLUSTER_TYPE_HEAD2:
|
||||
if (endoff >= m.clusterofs) {
|
||||
m.headtype = m.type;
|
||||
map->m_la = (m.lcn << lclusterbits) | m.clusterofs;
|
||||
@@ -534,7 +519,7 @@ static int z_erofs_do_map_blocks(struct inode *inode,
|
||||
map->m_flags |= EROFS_MAP_FULL_MAPPED;
|
||||
m.delta[0] = 1;
|
||||
fallthrough;
|
||||
case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD:
|
||||
case Z_EROFS_LCLUSTER_TYPE_NONHEAD:
|
||||
/* get the corresponding first chunk */
|
||||
err = z_erofs_extent_lookback(&m, m.delta[0]);
|
||||
if (err)
|
||||
@@ -555,7 +540,7 @@ static int z_erofs_do_map_blocks(struct inode *inode,
|
||||
vi->z_tailextent_headlcn = m.lcn;
|
||||
/* for non-compact indexes, fragmentoff is 64 bits */
|
||||
if (fragment &&
|
||||
vi->datalayout == EROFS_INODE_FLAT_COMPRESSION_LEGACY)
|
||||
vi->datalayout == EROFS_INODE_COMPRESSED_FULL)
|
||||
vi->z_fragmentoff |= (u64)m.pblk << 32;
|
||||
}
|
||||
if (ztailpacking && m.lcn == vi->z_tailextent_headlcn) {
|
||||
@@ -565,13 +550,13 @@ static int z_erofs_do_map_blocks(struct inode *inode,
|
||||
} else if (fragment && m.lcn == vi->z_tailextent_headlcn) {
|
||||
map->m_flags |= EROFS_MAP_FRAGMENT;
|
||||
} else {
|
||||
map->m_pa = blknr_to_addr(m.pblk);
|
||||
map->m_pa = erofs_pos(inode->i_sb, m.pblk);
|
||||
err = z_erofs_get_extent_compressedlen(&m, initial_lcn);
|
||||
if (err)
|
||||
goto unmap_out;
|
||||
}
|
||||
|
||||
if (m.headtype == Z_EROFS_VLE_CLUSTER_TYPE_PLAIN) {
|
||||
if (m.headtype == Z_EROFS_LCLUSTER_TYPE_PLAIN) {
|
||||
if (map->m_llen > map->m_plen) {
|
||||
DBG_BUGON(1);
|
||||
err = -EFSCORRUPTED;
|
||||
@@ -583,7 +568,7 @@ static int z_erofs_do_map_blocks(struct inode *inode,
|
||||
else
|
||||
map->m_algorithmformat =
|
||||
Z_EROFS_COMPRESSION_SHIFTED;
|
||||
} else if (m.headtype == Z_EROFS_VLE_CLUSTER_TYPE_HEAD2) {
|
||||
} else if (m.headtype == Z_EROFS_LCLUSTER_TYPE_HEAD2) {
|
||||
map->m_algorithmformat = vi->z_algorithmtype[1];
|
||||
} else {
|
||||
map->m_algorithmformat = vi->z_algorithmtype[0];
|
||||
@@ -592,7 +577,7 @@ static int z_erofs_do_map_blocks(struct inode *inode,
|
||||
if ((flags & EROFS_GET_BLOCKS_FIEMAP) ||
|
||||
((flags & EROFS_GET_BLOCKS_READMORE) &&
|
||||
map->m_algorithmformat == Z_EROFS_COMPRESSION_LZMA &&
|
||||
map->m_llen >= EROFS_BLKSIZ)) {
|
||||
map->m_llen >= i_blocksize(inode))) {
|
||||
err = z_erofs_get_extent_decompressedlen(&m);
|
||||
if (!err)
|
||||
map->m_flags |= EROFS_MAP_FULL_MAPPED;
|
||||
@@ -600,9 +585,6 @@ static int z_erofs_do_map_blocks(struct inode *inode,
|
||||
|
||||
unmap_out:
|
||||
erofs_unmap_metabuf(&m.map->buf);
|
||||
erofs_dbg("%s, m_la %llu m_pa %llu m_llen %llu m_plen %llu m_flags 0%o",
|
||||
__func__, map->m_la, map->m_pa,
|
||||
map->m_llen, map->m_plen, map->m_flags);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -633,13 +615,13 @@ static int z_erofs_fill_inode_lazy(struct inode *inode)
|
||||
goto out_unlock;
|
||||
|
||||
pos = ALIGN(erofs_iloc(inode) + vi->inode_isize + vi->xattr_isize, 8);
|
||||
kaddr = erofs_read_metabuf(&buf, sb, erofs_blknr(pos), EROFS_KMAP);
|
||||
kaddr = erofs_read_metabuf(&buf, sb, erofs_blknr(sb, pos), EROFS_KMAP);
|
||||
if (IS_ERR(kaddr)) {
|
||||
err = PTR_ERR(kaddr);
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
h = kaddr + erofs_blkoff(pos);
|
||||
h = kaddr + erofs_blkoff(sb, pos);
|
||||
/*
|
||||
* if the highest bit of the 8-byte map header is set, the whole file
|
||||
* is stored in the packed inode. The rest bits keeps z_fragmentoff.
|
||||
@@ -663,7 +645,7 @@ static int z_erofs_fill_inode_lazy(struct inode *inode)
|
||||
goto out_put_metabuf;
|
||||
}
|
||||
|
||||
vi->z_logical_clusterbits = LOG_BLOCK_SIZE + (h->h_clusterbits & 7);
|
||||
vi->z_logical_clusterbits = sb->s_blocksize_bits + (h->h_clusterbits & 7);
|
||||
if (!erofs_sb_has_big_pcluster(EROFS_SB(sb)) &&
|
||||
vi->z_advise & (Z_EROFS_ADVISE_BIG_PCLUSTER_1 |
|
||||
Z_EROFS_ADVISE_BIG_PCLUSTER_2)) {
|
||||
@@ -672,7 +654,7 @@ static int z_erofs_fill_inode_lazy(struct inode *inode)
|
||||
err = -EFSCORRUPTED;
|
||||
goto out_put_metabuf;
|
||||
}
|
||||
if (vi->datalayout == EROFS_INODE_FLAT_COMPRESSION &&
|
||||
if (vi->datalayout == EROFS_INODE_COMPRESSED_COMPACT &&
|
||||
!(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_1) ^
|
||||
!(vi->z_advise & Z_EROFS_ADVISE_BIG_PCLUSTER_2)) {
|
||||
erofs_err(sb, "big pcluster head1/2 of compact indexes should be consistent for nid %llu",
|
||||
@@ -692,7 +674,7 @@ static int z_erofs_fill_inode_lazy(struct inode *inode)
|
||||
erofs_put_metabuf(&map.buf);
|
||||
|
||||
if (!map.m_plen ||
|
||||
erofs_blkoff(map.m_pa) + map.m_plen > EROFS_BLKSIZ) {
|
||||
erofs_blkoff(sb, map.m_pa) + map.m_plen > sb->s_blocksize) {
|
||||
erofs_err(sb, "invalid tail-packing pclustersize %llu",
|
||||
map.m_plen);
|
||||
err = -EFSCORRUPTED;
|
||||
|
||||
+7
-34
@@ -228,7 +228,6 @@ static ssize_t eventfd_read(struct kiocb *iocb, struct iov_iter *to)
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct eventfd_ctx *ctx = file->private_data;
|
||||
__u64 ucnt = 0;
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
|
||||
if (iov_iter_count(to) < sizeof(ucnt))
|
||||
return -EINVAL;
|
||||
@@ -239,23 +238,11 @@ static ssize_t eventfd_read(struct kiocb *iocb, struct iov_iter *to)
|
||||
spin_unlock_irq(&ctx->wqh.lock);
|
||||
return -EAGAIN;
|
||||
}
|
||||
__add_wait_queue(&ctx->wqh, &wait);
|
||||
for (;;) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
if (ctx->count)
|
||||
break;
|
||||
if (signal_pending(current)) {
|
||||
__remove_wait_queue(&ctx->wqh, &wait);
|
||||
__set_current_state(TASK_RUNNING);
|
||||
spin_unlock_irq(&ctx->wqh.lock);
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
|
||||
if (wait_event_interruptible_locked_irq(ctx->wqh, ctx->count)) {
|
||||
spin_unlock_irq(&ctx->wqh.lock);
|
||||
schedule();
|
||||
spin_lock_irq(&ctx->wqh.lock);
|
||||
return -ERESTARTSYS;
|
||||
}
|
||||
__remove_wait_queue(&ctx->wqh, &wait);
|
||||
__set_current_state(TASK_RUNNING);
|
||||
}
|
||||
eventfd_ctx_do_read(ctx, &ucnt);
|
||||
current->in_eventfd = 1;
|
||||
@@ -275,7 +262,6 @@ static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t c
|
||||
struct eventfd_ctx *ctx = file->private_data;
|
||||
ssize_t res;
|
||||
__u64 ucnt;
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
|
||||
if (count < sizeof(ucnt))
|
||||
return -EINVAL;
|
||||
@@ -288,23 +274,10 @@ static ssize_t eventfd_write(struct file *file, const char __user *buf, size_t c
|
||||
if (ULLONG_MAX - ctx->count > ucnt)
|
||||
res = sizeof(ucnt);
|
||||
else if (!(file->f_flags & O_NONBLOCK)) {
|
||||
__add_wait_queue(&ctx->wqh, &wait);
|
||||
for (res = 0;;) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
if (ULLONG_MAX - ctx->count > ucnt) {
|
||||
res = sizeof(ucnt);
|
||||
break;
|
||||
}
|
||||
if (signal_pending(current)) {
|
||||
res = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
spin_unlock_irq(&ctx->wqh.lock);
|
||||
schedule();
|
||||
spin_lock_irq(&ctx->wqh.lock);
|
||||
}
|
||||
__remove_wait_queue(&ctx->wqh, &wait);
|
||||
__set_current_state(TASK_RUNNING);
|
||||
res = wait_event_interruptible_locked_irq(ctx->wqh,
|
||||
ULLONG_MAX - ctx->count > ucnt);
|
||||
if (!res)
|
||||
res = sizeof(ucnt);
|
||||
}
|
||||
if (likely(res > 0)) {
|
||||
ctx->count += ucnt;
|
||||
|
||||
+2
-2
@@ -483,8 +483,8 @@ static inline void ep_set_busy_poll_napi_id(struct epitem *epi)
|
||||
* (efd1) notices that it may have some event ready, so it needs to wake up
|
||||
* the waiters on its poll wait list (efd2). So it calls ep_poll_safewake()
|
||||
* that ends up in another wake_up(), after having checked about the
|
||||
* recursion constraints. That are, no more than EP_MAX_POLLWAKE_NESTS, to
|
||||
* avoid stack blasting.
|
||||
* recursion constraints. That are, no more than EP_MAX_NESTS, to avoid
|
||||
* stack blasting.
|
||||
*
|
||||
* When CONFIG_DEBUG_LOCK_ALLOC is enabled, make sure lockdep can handle
|
||||
* this special case of epoll.
|
||||
|
||||
+12
-13
@@ -101,8 +101,8 @@ static void ext2_xattr_rehash(struct ext2_xattr_header *,
|
||||
static const struct xattr_handler *ext2_xattr_handler_map[] = {
|
||||
[EXT2_XATTR_INDEX_USER] = &ext2_xattr_user_handler,
|
||||
#ifdef CONFIG_EXT2_FS_POSIX_ACL
|
||||
[EXT2_XATTR_INDEX_POSIX_ACL_ACCESS] = &posix_acl_access_xattr_handler,
|
||||
[EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT] = &posix_acl_default_xattr_handler,
|
||||
[EXT2_XATTR_INDEX_POSIX_ACL_ACCESS] = &nop_posix_acl_access,
|
||||
[EXT2_XATTR_INDEX_POSIX_ACL_DEFAULT] = &nop_posix_acl_default,
|
||||
#endif
|
||||
[EXT2_XATTR_INDEX_TRUSTED] = &ext2_xattr_trusted_handler,
|
||||
#ifdef CONFIG_EXT2_FS_SECURITY
|
||||
@@ -113,10 +113,6 @@ static const struct xattr_handler *ext2_xattr_handler_map[] = {
|
||||
const struct xattr_handler *ext2_xattr_handlers[] = {
|
||||
&ext2_xattr_user_handler,
|
||||
&ext2_xattr_trusted_handler,
|
||||
#ifdef CONFIG_EXT2_FS_POSIX_ACL
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
#endif
|
||||
#ifdef CONFIG_EXT2_FS_SECURITY
|
||||
&ext2_xattr_security_handler,
|
||||
#endif
|
||||
@@ -125,14 +121,18 @@ const struct xattr_handler *ext2_xattr_handlers[] = {
|
||||
|
||||
#define EA_BLOCK_CACHE(inode) (EXT2_SB(inode->i_sb)->s_ea_block_cache)
|
||||
|
||||
static inline const struct xattr_handler *
|
||||
ext2_xattr_handler(int name_index)
|
||||
static inline const char *ext2_xattr_prefix(int name_index,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
const struct xattr_handler *handler = NULL;
|
||||
|
||||
if (name_index > 0 && name_index < ARRAY_SIZE(ext2_xattr_handler_map))
|
||||
handler = ext2_xattr_handler_map[name_index];
|
||||
return handler;
|
||||
|
||||
if (!xattr_handler_can_list(handler, dentry))
|
||||
return NULL;
|
||||
|
||||
return xattr_prefix(handler);
|
||||
}
|
||||
|
||||
static bool
|
||||
@@ -333,11 +333,10 @@ bad_block:
|
||||
/* list the attribute names */
|
||||
for (entry = FIRST_ENTRY(bh); !IS_LAST_ENTRY(entry);
|
||||
entry = EXT2_XATTR_NEXT(entry)) {
|
||||
const struct xattr_handler *handler =
|
||||
ext2_xattr_handler(entry->e_name_index);
|
||||
const char *prefix;
|
||||
|
||||
if (handler && (!handler->list || handler->list(dentry))) {
|
||||
const char *prefix = handler->prefix ?: handler->name;
|
||||
prefix = ext2_xattr_prefix(entry->e_name_index, dentry);
|
||||
if (prefix) {
|
||||
size_t prefix_len = strlen(prefix);
|
||||
size_t size = prefix_len + entry->e_name_len + 1;
|
||||
|
||||
|
||||
+12
-13
@@ -88,8 +88,8 @@ static void ext4_xattr_rehash(struct ext4_xattr_header *);
|
||||
static const struct xattr_handler * const ext4_xattr_handler_map[] = {
|
||||
[EXT4_XATTR_INDEX_USER] = &ext4_xattr_user_handler,
|
||||
#ifdef CONFIG_EXT4_FS_POSIX_ACL
|
||||
[EXT4_XATTR_INDEX_POSIX_ACL_ACCESS] = &posix_acl_access_xattr_handler,
|
||||
[EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT] = &posix_acl_default_xattr_handler,
|
||||
[EXT4_XATTR_INDEX_POSIX_ACL_ACCESS] = &nop_posix_acl_access,
|
||||
[EXT4_XATTR_INDEX_POSIX_ACL_DEFAULT] = &nop_posix_acl_default,
|
||||
#endif
|
||||
[EXT4_XATTR_INDEX_TRUSTED] = &ext4_xattr_trusted_handler,
|
||||
#ifdef CONFIG_EXT4_FS_SECURITY
|
||||
@@ -101,10 +101,6 @@ static const struct xattr_handler * const ext4_xattr_handler_map[] = {
|
||||
const struct xattr_handler *ext4_xattr_handlers[] = {
|
||||
&ext4_xattr_user_handler,
|
||||
&ext4_xattr_trusted_handler,
|
||||
#ifdef CONFIG_EXT4_FS_POSIX_ACL
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
#endif
|
||||
#ifdef CONFIG_EXT4_FS_SECURITY
|
||||
&ext4_xattr_security_handler,
|
||||
#endif
|
||||
@@ -173,14 +169,18 @@ static void ext4_xattr_block_csum_set(struct inode *inode,
|
||||
bh->b_blocknr, BHDR(bh));
|
||||
}
|
||||
|
||||
static inline const struct xattr_handler *
|
||||
ext4_xattr_handler(int name_index)
|
||||
static inline const char *ext4_xattr_prefix(int name_index,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
const struct xattr_handler *handler = NULL;
|
||||
|
||||
if (name_index > 0 && name_index < ARRAY_SIZE(ext4_xattr_handler_map))
|
||||
handler = ext4_xattr_handler_map[name_index];
|
||||
return handler;
|
||||
|
||||
if (!xattr_handler_can_list(handler, dentry))
|
||||
return NULL;
|
||||
|
||||
return xattr_prefix(handler);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -740,11 +740,10 @@ ext4_xattr_list_entries(struct dentry *dentry, struct ext4_xattr_entry *entry,
|
||||
size_t rest = buffer_size;
|
||||
|
||||
for (; !IS_LAST_ENTRY(entry); entry = EXT4_XATTR_NEXT(entry)) {
|
||||
const struct xattr_handler *handler =
|
||||
ext4_xattr_handler(entry->e_name_index);
|
||||
const char *prefix;
|
||||
|
||||
if (handler && (!handler->list || handler->list(dentry))) {
|
||||
const char *prefix = handler->prefix ?: handler->name;
|
||||
prefix = ext4_xattr_prefix(entry->e_name_index, dentry);
|
||||
if (prefix) {
|
||||
size_t prefix_len = strlen(prefix);
|
||||
size_t size = prefix_len + entry->e_name_len + 1;
|
||||
|
||||
|
||||
+12
-12
@@ -192,8 +192,8 @@ const struct xattr_handler f2fs_xattr_security_handler = {
|
||||
static const struct xattr_handler *f2fs_xattr_handler_map[] = {
|
||||
[F2FS_XATTR_INDEX_USER] = &f2fs_xattr_user_handler,
|
||||
#ifdef CONFIG_F2FS_FS_POSIX_ACL
|
||||
[F2FS_XATTR_INDEX_POSIX_ACL_ACCESS] = &posix_acl_access_xattr_handler,
|
||||
[F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &posix_acl_default_xattr_handler,
|
||||
[F2FS_XATTR_INDEX_POSIX_ACL_ACCESS] = &nop_posix_acl_access,
|
||||
[F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &nop_posix_acl_default,
|
||||
#endif
|
||||
[F2FS_XATTR_INDEX_TRUSTED] = &f2fs_xattr_trusted_handler,
|
||||
#ifdef CONFIG_F2FS_FS_SECURITY
|
||||
@@ -204,10 +204,6 @@ static const struct xattr_handler *f2fs_xattr_handler_map[] = {
|
||||
|
||||
const struct xattr_handler *f2fs_xattr_handlers[] = {
|
||||
&f2fs_xattr_user_handler,
|
||||
#ifdef CONFIG_F2FS_FS_POSIX_ACL
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
#endif
|
||||
&f2fs_xattr_trusted_handler,
|
||||
#ifdef CONFIG_F2FS_FS_SECURITY
|
||||
&f2fs_xattr_security_handler,
|
||||
@@ -216,13 +212,18 @@ const struct xattr_handler *f2fs_xattr_handlers[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
static inline const struct xattr_handler *f2fs_xattr_handler(int index)
|
||||
static inline const char *f2fs_xattr_prefix(int index,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
const struct xattr_handler *handler = NULL;
|
||||
|
||||
if (index > 0 && index < ARRAY_SIZE(f2fs_xattr_handler_map))
|
||||
handler = f2fs_xattr_handler_map[index];
|
||||
return handler;
|
||||
|
||||
if (!xattr_handler_can_list(handler, dentry))
|
||||
return NULL;
|
||||
|
||||
return xattr_prefix(handler);
|
||||
}
|
||||
|
||||
static struct f2fs_xattr_entry *__find_xattr(void *base_addr,
|
||||
@@ -573,12 +574,12 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
|
||||
last_base_addr = (void *)base_addr + XATTR_SIZE(inode);
|
||||
|
||||
list_for_each_xattr(entry, base_addr) {
|
||||
const struct xattr_handler *handler =
|
||||
f2fs_xattr_handler(entry->e_name_index);
|
||||
const char *prefix;
|
||||
size_t prefix_len;
|
||||
size_t size;
|
||||
|
||||
prefix = f2fs_xattr_prefix(entry->e_name_index, dentry);
|
||||
|
||||
if ((void *)(entry) + sizeof(__u32) > last_base_addr ||
|
||||
(void *)XATTR_NEXT_ENTRY(entry) > last_base_addr) {
|
||||
f2fs_err(F2FS_I_SB(inode), "inode (%lu) has corrupted xattr",
|
||||
@@ -590,10 +591,9 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!handler || (handler->list && !handler->list(dentry)))
|
||||
if (!prefix)
|
||||
continue;
|
||||
|
||||
prefix = xattr_prefix(handler);
|
||||
prefix_len = strlen(prefix);
|
||||
size = prefix_len + entry->e_name_len + 1;
|
||||
if (buffer) {
|
||||
|
||||
+19
-18
@@ -2269,30 +2269,31 @@ static long fuse_dev_ioctl(struct file *file, unsigned int cmd,
|
||||
int res;
|
||||
int oldfd;
|
||||
struct fuse_dev *fud = NULL;
|
||||
struct fd f;
|
||||
|
||||
switch (cmd) {
|
||||
case FUSE_DEV_IOC_CLONE:
|
||||
res = -EFAULT;
|
||||
if (!get_user(oldfd, (__u32 __user *)arg)) {
|
||||
struct file *old = fget(oldfd);
|
||||
if (get_user(oldfd, (__u32 __user *)arg))
|
||||
return -EFAULT;
|
||||
|
||||
res = -EINVAL;
|
||||
if (old) {
|
||||
/*
|
||||
* Check against file->f_op because CUSE
|
||||
* uses the same ioctl handler.
|
||||
*/
|
||||
if (old->f_op == file->f_op)
|
||||
fud = fuse_get_dev(old);
|
||||
f = fdget(oldfd);
|
||||
if (!f.file)
|
||||
return -EINVAL;
|
||||
|
||||
if (fud) {
|
||||
mutex_lock(&fuse_mutex);
|
||||
res = fuse_device_clone(fud->fc, file);
|
||||
mutex_unlock(&fuse_mutex);
|
||||
}
|
||||
fput(old);
|
||||
}
|
||||
/*
|
||||
* Check against file->f_op because CUSE
|
||||
* uses the same ioctl handler.
|
||||
*/
|
||||
if (f.file->f_op == file->f_op)
|
||||
fud = fuse_get_dev(f.file);
|
||||
|
||||
res = -EINVAL;
|
||||
if (fud) {
|
||||
mutex_lock(&fuse_mutex);
|
||||
res = fuse_device_clone(fud->fc, file);
|
||||
mutex_unlock(&fuse_mutex);
|
||||
}
|
||||
fdput(f);
|
||||
break;
|
||||
case FUSE_DEV_IOC_PASSTHROUGH_OPEN:
|
||||
res = -EFAULT;
|
||||
|
||||
@@ -1501,8 +1501,6 @@ const struct xattr_handler *gfs2_xattr_handlers_max[] = {
|
||||
/* GFS2_FS_FORMAT_MIN */
|
||||
&gfs2_xattr_user_handler,
|
||||
&gfs2_xattr_security_handler,
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
+23
-5
@@ -511,7 +511,11 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
|
||||
if (type == HFSPLUS_FOLDER) {
|
||||
struct hfsplus_cat_folder *folder = &entry.folder;
|
||||
|
||||
WARN_ON(fd->entrylength < sizeof(struct hfsplus_cat_folder));
|
||||
if (fd->entrylength < sizeof(struct hfsplus_cat_folder)) {
|
||||
pr_err("bad catalog folder entry\n");
|
||||
res = -EIO;
|
||||
goto out;
|
||||
}
|
||||
hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
|
||||
sizeof(struct hfsplus_cat_folder));
|
||||
hfsplus_get_perms(inode, &folder->permissions, 1);
|
||||
@@ -531,7 +535,11 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
|
||||
} else if (type == HFSPLUS_FILE) {
|
||||
struct hfsplus_cat_file *file = &entry.file;
|
||||
|
||||
WARN_ON(fd->entrylength < sizeof(struct hfsplus_cat_file));
|
||||
if (fd->entrylength < sizeof(struct hfsplus_cat_file)) {
|
||||
pr_err("bad catalog file entry\n");
|
||||
res = -EIO;
|
||||
goto out;
|
||||
}
|
||||
hfs_bnode_read(fd->bnode, &entry, fd->entryoffset,
|
||||
sizeof(struct hfsplus_cat_file));
|
||||
|
||||
@@ -562,6 +570,7 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
|
||||
pr_err("bad catalog entry used to create inode\n");
|
||||
res = -EIO;
|
||||
}
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -570,6 +579,7 @@ int hfsplus_cat_write_inode(struct inode *inode)
|
||||
struct inode *main_inode = inode;
|
||||
struct hfs_find_data fd;
|
||||
hfsplus_cat_entry entry;
|
||||
int res = 0;
|
||||
|
||||
if (HFSPLUS_IS_RSRC(inode))
|
||||
main_inode = HFSPLUS_I(inode)->rsrc_inode;
|
||||
@@ -588,7 +598,11 @@ int hfsplus_cat_write_inode(struct inode *inode)
|
||||
if (S_ISDIR(main_inode->i_mode)) {
|
||||
struct hfsplus_cat_folder *folder = &entry.folder;
|
||||
|
||||
WARN_ON(fd.entrylength < sizeof(struct hfsplus_cat_folder));
|
||||
if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) {
|
||||
pr_err("bad catalog folder entry\n");
|
||||
res = -EIO;
|
||||
goto out;
|
||||
}
|
||||
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
|
||||
sizeof(struct hfsplus_cat_folder));
|
||||
/* simple node checks? */
|
||||
@@ -613,7 +627,11 @@ int hfsplus_cat_write_inode(struct inode *inode)
|
||||
} else {
|
||||
struct hfsplus_cat_file *file = &entry.file;
|
||||
|
||||
WARN_ON(fd.entrylength < sizeof(struct hfsplus_cat_file));
|
||||
if (fd.entrylength < sizeof(struct hfsplus_cat_file)) {
|
||||
pr_err("bad catalog file entry\n");
|
||||
res = -EIO;
|
||||
goto out;
|
||||
}
|
||||
hfs_bnode_read(fd.bnode, &entry, fd.entryoffset,
|
||||
sizeof(struct hfsplus_cat_file));
|
||||
hfsplus_inode_write_fork(inode, &file->data_fork);
|
||||
@@ -634,7 +652,7 @@ int hfsplus_cat_write_inode(struct inode *inode)
|
||||
set_bit(HFSPLUS_I_CAT_DIRTY, &HFSPLUS_I(inode)->flags);
|
||||
out:
|
||||
hfs_find_exit(&fd);
|
||||
return 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
int hfsplus_fileattr_get(struct dentry *dentry, struct fileattr *fa)
|
||||
|
||||
+4
-4
@@ -1804,8 +1804,8 @@ EXPORT_SYMBOL(bmap);
|
||||
|
||||
/*
|
||||
* With relative atime, only update atime if the previous atime is
|
||||
* earlier than either the ctime or mtime or if at least a day has
|
||||
* passed since the last atime update.
|
||||
* earlier than or equal to either the ctime or mtime,
|
||||
* or if at least a day has passed since the last atime update.
|
||||
*/
|
||||
static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
|
||||
struct timespec64 now)
|
||||
@@ -1814,12 +1814,12 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
|
||||
if (!(mnt->mnt_flags & MNT_RELATIME))
|
||||
return 1;
|
||||
/*
|
||||
* Is mtime younger than atime? If yes, update atime:
|
||||
* Is mtime younger than or equal to atime? If yes, update atime:
|
||||
*/
|
||||
if (timespec64_compare(&inode->i_mtime, &inode->i_atime) >= 0)
|
||||
return 1;
|
||||
/*
|
||||
* Is ctime younger than atime? If yes, update atime:
|
||||
* Is ctime younger than or equal to atime? If yes, update atime:
|
||||
*/
|
||||
if (timespec64_compare(&inode->i_ctime, &inode->i_atime) >= 0)
|
||||
return 1;
|
||||
|
||||
@@ -259,8 +259,6 @@ ssize_t __kernel_write_iter(struct file *file, struct iov_iter *from, loff_t *po
|
||||
/*
|
||||
* fs/attr.c
|
||||
*/
|
||||
int setattr_should_drop_sgid(struct mnt_idmap *idmap,
|
||||
const struct inode *inode);
|
||||
struct mnt_idmap *alloc_mnt_idmap(struct user_namespace *mnt_userns);
|
||||
struct mnt_idmap *mnt_idmap_get(struct mnt_idmap *idmap);
|
||||
void mnt_idmap_put(struct mnt_idmap *idmap);
|
||||
|
||||
+14
-15
@@ -919,17 +919,14 @@ const struct xattr_handler *jffs2_xattr_handlers[] = {
|
||||
&jffs2_user_xattr_handler,
|
||||
#ifdef CONFIG_JFFS2_FS_SECURITY
|
||||
&jffs2_security_xattr_handler,
|
||||
#endif
|
||||
#ifdef CONFIG_JFFS2_FS_POSIX_ACL
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
#endif
|
||||
&jffs2_trusted_xattr_handler,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct xattr_handler *xprefix_to_handler(int xprefix) {
|
||||
const struct xattr_handler *ret;
|
||||
static const char *jffs2_xattr_prefix(int xprefix, struct dentry *dentry)
|
||||
{
|
||||
const struct xattr_handler *ret = NULL;
|
||||
|
||||
switch (xprefix) {
|
||||
case JFFS2_XPREFIX_USER:
|
||||
@@ -942,20 +939,23 @@ static const struct xattr_handler *xprefix_to_handler(int xprefix) {
|
||||
#endif
|
||||
#ifdef CONFIG_JFFS2_FS_POSIX_ACL
|
||||
case JFFS2_XPREFIX_ACL_ACCESS:
|
||||
ret = &posix_acl_access_xattr_handler;
|
||||
ret = &nop_posix_acl_access;
|
||||
break;
|
||||
case JFFS2_XPREFIX_ACL_DEFAULT:
|
||||
ret = &posix_acl_default_xattr_handler;
|
||||
ret = &nop_posix_acl_default;
|
||||
break;
|
||||
#endif
|
||||
case JFFS2_XPREFIX_TRUSTED:
|
||||
ret = &jffs2_trusted_xattr_handler;
|
||||
break;
|
||||
default:
|
||||
ret = NULL;
|
||||
break;
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
|
||||
if (!xattr_handler_can_list(ret, dentry))
|
||||
return NULL;
|
||||
|
||||
return xattr_prefix(ret);
|
||||
}
|
||||
|
||||
ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
||||
@@ -966,7 +966,6 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
||||
struct jffs2_inode_cache *ic = f->inocache;
|
||||
struct jffs2_xattr_ref *ref, **pref;
|
||||
struct jffs2_xattr_datum *xd;
|
||||
const struct xattr_handler *xhandle;
|
||||
const char *prefix;
|
||||
ssize_t prefix_len, len, rc;
|
||||
int retry = 0;
|
||||
@@ -998,10 +997,10 @@ ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
xhandle = xprefix_to_handler(xd->xprefix);
|
||||
if (!xhandle || (xhandle->list && !xhandle->list(dentry)))
|
||||
|
||||
prefix = jffs2_xattr_prefix(xd->xprefix, dentry);
|
||||
if (!prefix)
|
||||
continue;
|
||||
prefix = xhandle->prefix ?: xhandle->name;
|
||||
prefix_len = strlen(prefix);
|
||||
rc = prefix_len + xd->name_len + 1;
|
||||
|
||||
|
||||
+34
-5
@@ -691,6 +691,35 @@ void grab_metapage(struct metapage * mp)
|
||||
unlock_page(mp->page);
|
||||
}
|
||||
|
||||
static int metapage_write_one(struct page *page)
|
||||
{
|
||||
struct folio *folio = page_folio(page);
|
||||
struct address_space *mapping = folio->mapping;
|
||||
struct writeback_control wbc = {
|
||||
.sync_mode = WB_SYNC_ALL,
|
||||
.nr_to_write = folio_nr_pages(folio),
|
||||
};
|
||||
int ret = 0;
|
||||
|
||||
BUG_ON(!folio_test_locked(folio));
|
||||
|
||||
folio_wait_writeback(folio);
|
||||
|
||||
if (folio_clear_dirty_for_io(folio)) {
|
||||
folio_get(folio);
|
||||
ret = metapage_writepage(page, &wbc);
|
||||
if (ret == 0)
|
||||
folio_wait_writeback(folio);
|
||||
folio_put(folio);
|
||||
} else {
|
||||
folio_unlock(folio);
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
ret = filemap_check_errors(mapping);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void force_metapage(struct metapage *mp)
|
||||
{
|
||||
struct page *page = mp->page;
|
||||
@@ -700,8 +729,8 @@ void force_metapage(struct metapage *mp)
|
||||
get_page(page);
|
||||
lock_page(page);
|
||||
set_page_dirty(page);
|
||||
if (write_one_page(page))
|
||||
jfs_error(mp->sb, "write_one_page() failed\n");
|
||||
if (metapage_write_one(page))
|
||||
jfs_error(mp->sb, "metapage_write_one() failed\n");
|
||||
clear_bit(META_forcewrite, &mp->flag);
|
||||
put_page(page);
|
||||
}
|
||||
@@ -746,9 +775,9 @@ void release_metapage(struct metapage * mp)
|
||||
set_page_dirty(page);
|
||||
if (test_bit(META_sync, &mp->flag)) {
|
||||
clear_bit(META_sync, &mp->flag);
|
||||
if (write_one_page(page))
|
||||
jfs_error(mp->sb, "write_one_page() failed\n");
|
||||
lock_page(page); /* write_one_page unlocks the page */
|
||||
if (metapage_write_one(page))
|
||||
jfs_error(mp->sb, "metapage_write_one() failed\n");
|
||||
lock_page(page);
|
||||
}
|
||||
} else if (mp->lsn) /* discard_metapage doesn't remove it */
|
||||
remove_from_logsync(mp);
|
||||
|
||||
@@ -986,10 +986,6 @@ static const struct xattr_handler jfs_trusted_xattr_handler = {
|
||||
};
|
||||
|
||||
const struct xattr_handler *jfs_xattr_handlers[] = {
|
||||
#ifdef CONFIG_JFS_POSIX_ACL
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
#endif
|
||||
&jfs_os2_xattr_handler,
|
||||
&jfs_user_xattr_handler,
|
||||
&jfs_security_xattr_handler,
|
||||
|
||||
+1
-7
@@ -1748,12 +1748,6 @@ int kernfs_rename_ns(struct kernfs_node *kn, struct kernfs_node *new_parent,
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Relationship between mode and the DT_xxx types */
|
||||
static inline unsigned char dt_type(struct kernfs_node *kn)
|
||||
{
|
||||
return (kn->mode >> 12) & 15;
|
||||
}
|
||||
|
||||
static int kernfs_dir_fop_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
kernfs_put(filp->private_data);
|
||||
@@ -1831,7 +1825,7 @@ static int kernfs_fop_readdir(struct file *file, struct dir_context *ctx)
|
||||
pos;
|
||||
pos = kernfs_dir_next_pos(ns, parent, ctx->pos, pos)) {
|
||||
const char *name = pos->name;
|
||||
unsigned int type = dt_type(pos);
|
||||
unsigned int type = fs_umode_to_dtype(pos->mode);
|
||||
int len = strlen(name);
|
||||
ino_t ino = kernfs_ino(pos);
|
||||
|
||||
|
||||
+2
-7
@@ -174,12 +174,6 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence)
|
||||
}
|
||||
EXPORT_SYMBOL(dcache_dir_lseek);
|
||||
|
||||
/* Relationship between i_mode and the DT_xxx types */
|
||||
static inline unsigned char dt_type(struct inode *inode)
|
||||
{
|
||||
return (inode->i_mode >> 12) & 15;
|
||||
}
|
||||
|
||||
/*
|
||||
* Directory is locked and all positive dentries in it are safe, since
|
||||
* for ramfs-type trees they can't go away without unlink() or rmdir(),
|
||||
@@ -206,7 +200,8 @@ int dcache_readdir(struct file *file, struct dir_context *ctx)
|
||||
|
||||
while ((next = scan_positives(cursor, p, 1, next)) != NULL) {
|
||||
if (!dir_emit(ctx, next->d_name.name, next->d_name.len,
|
||||
d_inode(next)->i_ino, dt_type(d_inode(next))))
|
||||
d_inode(next)->i_ino,
|
||||
fs_umode_to_dtype(d_inode(next)->i_mode)))
|
||||
break;
|
||||
ctx->pos++;
|
||||
p = &next->d_child;
|
||||
|
||||
+2
-2
@@ -3574,9 +3574,9 @@ static int do_open(struct nameidata *nd,
|
||||
/**
|
||||
* vfs_tmpfile - create tmpfile
|
||||
* @idmap: idmap of the mount the inode was found from
|
||||
* @dentry: pointer to dentry of the base directory
|
||||
* @parentpath: pointer to the path of the base directory
|
||||
* @file: file descriptor of the new tmpfile
|
||||
* @mode: mode of the new tmpfile
|
||||
* @open_flag: flags
|
||||
*
|
||||
* Create a temporary file.
|
||||
*
|
||||
|
||||
+9
-12
@@ -2617,15 +2617,12 @@ static void mnt_warn_timestamp_expiry(struct path *mountpoint, struct vfsmount *
|
||||
(ktime_get_real_seconds() + TIME_UPTIME_SEC_MAX > sb->s_time_max)) {
|
||||
char *buf = (char *)__get_free_page(GFP_KERNEL);
|
||||
char *mntpath = buf ? d_path(mountpoint, buf, PAGE_SIZE) : ERR_PTR(-ENOMEM);
|
||||
struct tm tm;
|
||||
|
||||
time64_to_tm(sb->s_time_max, 0, &tm);
|
||||
|
||||
pr_warn("%s filesystem being %s at %s supports timestamps until %04ld (0x%llx)\n",
|
||||
pr_warn("%s filesystem being %s at %s supports timestamps until %ptTd (0x%llx)\n",
|
||||
sb->s_type->name,
|
||||
is_mounted(mnt) ? "remounted" : "mounted",
|
||||
mntpath,
|
||||
tm.tm_year+1900, (unsigned long long)sb->s_time_max);
|
||||
mntpath, &sb->s_time_max,
|
||||
(unsigned long long)sb->s_time_max);
|
||||
|
||||
free_page((unsigned long)buf);
|
||||
sb->s_iflags |= SB_I_TS_EXPIRY_WARNED;
|
||||
@@ -4197,7 +4194,7 @@ static int build_mount_idmapped(const struct mount_attr *attr, size_t usize,
|
||||
int err = 0;
|
||||
struct ns_common *ns;
|
||||
struct user_namespace *mnt_userns;
|
||||
struct file *file;
|
||||
struct fd f;
|
||||
|
||||
if (!((attr->attr_set | attr->attr_clr) & MOUNT_ATTR_IDMAP))
|
||||
return 0;
|
||||
@@ -4213,16 +4210,16 @@ static int build_mount_idmapped(const struct mount_attr *attr, size_t usize,
|
||||
if (attr->userns_fd > INT_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
file = fget(attr->userns_fd);
|
||||
if (!file)
|
||||
f = fdget(attr->userns_fd);
|
||||
if (!f.file)
|
||||
return -EBADF;
|
||||
|
||||
if (!proc_ns_file(file)) {
|
||||
if (!proc_ns_file(f.file)) {
|
||||
err = -EINVAL;
|
||||
goto out_fput;
|
||||
}
|
||||
|
||||
ns = get_proc_ns(file_inode(file));
|
||||
ns = get_proc_ns(file_inode(f.file));
|
||||
if (ns->ops->type != CLONE_NEWUSER) {
|
||||
err = -EINVAL;
|
||||
goto out_fput;
|
||||
@@ -4251,7 +4248,7 @@ static int build_mount_idmapped(const struct mount_attr *attr, size_t usize,
|
||||
kattr->mnt_userns = get_user_ns(mnt_userns);
|
||||
|
||||
out_fput:
|
||||
fput(file);
|
||||
fdput(f);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
+1
-3
@@ -717,9 +717,7 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
|
||||
if ((attr->ia_valid & ATTR_KILL_SUID) != 0 &&
|
||||
inode->i_mode & S_ISUID)
|
||||
inode->i_mode &= ~S_ISUID;
|
||||
if ((attr->ia_valid & ATTR_KILL_SGID) != 0 &&
|
||||
(inode->i_mode & (S_ISGID | S_IXGRP)) ==
|
||||
(S_ISGID | S_IXGRP))
|
||||
if (setattr_should_drop_sgid(&nop_mnt_idmap, inode))
|
||||
inode->i_mode &= ~S_ISGID;
|
||||
if ((attr->ia_valid & ATTR_MODE) != 0) {
|
||||
int mode = attr->ia_mode & S_IALLUGO;
|
||||
|
||||
@@ -17,7 +17,6 @@ extern int nfs3_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
|
||||
extern int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
|
||||
struct posix_acl *dfacl);
|
||||
extern ssize_t nfs3_listxattr(struct dentry *, char *, size_t);
|
||||
extern const struct xattr_handler *nfs3_xattr_handlers[];
|
||||
#else
|
||||
static inline int nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl,
|
||||
struct posix_acl *dfacl)
|
||||
|
||||
@@ -300,12 +300,6 @@ fail:
|
||||
goto out;
|
||||
}
|
||||
|
||||
const struct xattr_handler *nfs3_xattr_handlers[] = {
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int
|
||||
nfs3_list_one_acl(struct inode *inode, int type, const char *name, void *data,
|
||||
size_t size, ssize_t *result)
|
||||
|
||||
@@ -14,9 +14,6 @@ struct nfs_subversion nfs_v3 = {
|
||||
.rpc_vers = &nfs_version3,
|
||||
.rpc_ops = &nfs_v3_clientops,
|
||||
.sops = &nfs_sops,
|
||||
#ifdef CONFIG_NFS_V3_ACL
|
||||
.xattr = nfs3_xattr_handlers,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init init_nfs_v3(void)
|
||||
|
||||
@@ -1274,9 +1274,6 @@ int nfs_get_tree_common(struct fs_context *fc)
|
||||
if (ctx->clone_data.sb->s_flags & SB_SYNCHRONOUS)
|
||||
fc->sb_flags |= SB_SYNCHRONOUS;
|
||||
|
||||
if (server->caps & NFS_CAP_SECURITY_LABEL)
|
||||
fc->lsm_flags |= SECURITY_LSM_NATIVE_LABELS;
|
||||
|
||||
/* Get a superblock - note that we may end up sharing one that already exists */
|
||||
fc->s_fs_info = server;
|
||||
s = sget_fc(fc, compare_super, nfs_set_super);
|
||||
|
||||
+1
-2
@@ -3446,8 +3446,7 @@ out_acl:
|
||||
p = xdr_reserve_space(xdr, 4);
|
||||
if (!p)
|
||||
goto out_resource;
|
||||
err = xattr_supported_namespace(d_inode(dentry),
|
||||
XATTR_USER_PREFIX);
|
||||
err = xattr_supports_user_prefix(d_inode(dentry));
|
||||
*p++ = cpu_to_be32(err == 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -663,7 +663,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
|
||||
struct fanotify_info *info = fanotify_event_info(event);
|
||||
unsigned int info_mode = FAN_GROUP_FLAG(group, FANOTIFY_INFO_MODES);
|
||||
unsigned int pidfd_mode = info_mode & FAN_REPORT_PIDFD;
|
||||
struct file *f = NULL;
|
||||
struct file *f = NULL, *pidfd_file = NULL;
|
||||
int ret, pidfd = FAN_NOPIDFD, fd = FAN_NOFD;
|
||||
|
||||
pr_debug("%s: group=%p event=%p\n", __func__, group, event);
|
||||
@@ -718,7 +718,7 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
|
||||
!pid_has_task(event->pid, PIDTYPE_TGID)) {
|
||||
pidfd = FAN_NOPIDFD;
|
||||
} else {
|
||||
pidfd = pidfd_create(event->pid, 0);
|
||||
pidfd = pidfd_prepare(event->pid, 0, &pidfd_file);
|
||||
if (pidfd < 0)
|
||||
pidfd = FAN_EPIDFD;
|
||||
}
|
||||
@@ -751,6 +751,9 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
|
||||
if (f)
|
||||
fd_install(fd, f);
|
||||
|
||||
if (pidfd_file)
|
||||
fd_install(pidfd, pidfd_file);
|
||||
|
||||
return metadata.event_len;
|
||||
|
||||
out_close_fd:
|
||||
@@ -759,8 +762,10 @@ out_close_fd:
|
||||
fput(f);
|
||||
}
|
||||
|
||||
if (pidfd >= 0)
|
||||
close_fd(pidfd);
|
||||
if (pidfd >= 0) {
|
||||
put_unused_fd(pidfd);
|
||||
fput(pidfd_file);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -235,24 +235,6 @@ bool proc_ns_file(const struct file *file)
|
||||
return file->f_op == &ns_file_operations;
|
||||
}
|
||||
|
||||
struct file *proc_ns_fget(int fd)
|
||||
{
|
||||
struct file *file;
|
||||
|
||||
file = fget(fd);
|
||||
if (!file)
|
||||
return ERR_PTR(-EBADF);
|
||||
|
||||
if (file->f_op != &ns_file_operations)
|
||||
goto out_invalid;
|
||||
|
||||
return file;
|
||||
|
||||
out_invalid:
|
||||
fput(file);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* ns_match() - Returns true if current namespace matches dev/ino provided.
|
||||
* @ns: current namespace
|
||||
|
||||
@@ -1033,10 +1033,6 @@ static const struct xattr_handler ntfs_other_xattr_handler = {
|
||||
};
|
||||
|
||||
const struct xattr_handler *ntfs_xattr_handlers[] = {
|
||||
#ifdef CONFIG_NTFS3_FS_POSIX_ACL
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
#endif
|
||||
&ntfs_other_xattr_handler,
|
||||
NULL,
|
||||
};
|
||||
|
||||
+1
-1
@@ -2463,7 +2463,7 @@ static ssize_t ocfs2_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
|
||||
|
||||
return __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev,
|
||||
iter, get_block,
|
||||
ocfs2_dio_end_io, NULL, 0);
|
||||
ocfs2_dio_end_io, 0);
|
||||
}
|
||||
|
||||
const struct address_space_operations ocfs2_aops = {
|
||||
|
||||
@@ -2952,10 +2952,11 @@ retry:
|
||||
*/
|
||||
if (PAGE_SIZE <= OCFS2_SB(sb)->s_clustersize) {
|
||||
if (PageDirty(page)) {
|
||||
/*
|
||||
* write_on_page will unlock the page on return
|
||||
*/
|
||||
ret = write_one_page(page);
|
||||
unlock_page(page);
|
||||
put_page(page);
|
||||
|
||||
ret = filemap_write_and_wait_range(mapping,
|
||||
offset, map_end - 1);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-9
@@ -89,21 +89,17 @@ static struct ocfs2_xattr_def_value_root def_xv = {
|
||||
|
||||
const struct xattr_handler *ocfs2_xattr_handlers[] = {
|
||||
&ocfs2_xattr_user_handler,
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
&ocfs2_xattr_trusted_handler,
|
||||
&ocfs2_xattr_security_handler,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct xattr_handler *ocfs2_xattr_handler_map[OCFS2_XATTR_MAX] = {
|
||||
[OCFS2_XATTR_INDEX_USER] = &ocfs2_xattr_user_handler,
|
||||
[OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS]
|
||||
= &posix_acl_access_xattr_handler,
|
||||
[OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT]
|
||||
= &posix_acl_default_xattr_handler,
|
||||
[OCFS2_XATTR_INDEX_TRUSTED] = &ocfs2_xattr_trusted_handler,
|
||||
[OCFS2_XATTR_INDEX_SECURITY] = &ocfs2_xattr_security_handler,
|
||||
[OCFS2_XATTR_INDEX_USER] = &ocfs2_xattr_user_handler,
|
||||
[OCFS2_XATTR_INDEX_POSIX_ACL_ACCESS] = &nop_posix_acl_access,
|
||||
[OCFS2_XATTR_INDEX_POSIX_ACL_DEFAULT] = &nop_posix_acl_default,
|
||||
[OCFS2_XATTR_INDEX_TRUSTED] = &ocfs2_xattr_trusted_handler,
|
||||
[OCFS2_XATTR_INDEX_SECURITY] = &ocfs2_xattr_security_handler,
|
||||
};
|
||||
|
||||
struct ocfs2_xattr_info {
|
||||
|
||||
@@ -1198,13 +1198,21 @@ inline int build_open_flags(const struct open_how *how, struct open_flags *op)
|
||||
}
|
||||
|
||||
/*
|
||||
* In order to ensure programs get explicit errors when trying to use
|
||||
* O_TMPFILE on old kernels, O_TMPFILE is implemented such that it
|
||||
* looks like (O_DIRECTORY|O_RDWR & ~O_CREAT) to old kernels. But we
|
||||
* have to require userspace to explicitly set it.
|
||||
* Block bugs where O_DIRECTORY | O_CREAT created regular files.
|
||||
* Note, that blocking O_DIRECTORY | O_CREAT here also protects
|
||||
* O_TMPFILE below which requires O_DIRECTORY being raised.
|
||||
*/
|
||||
if ((flags & (O_DIRECTORY | O_CREAT)) == (O_DIRECTORY | O_CREAT))
|
||||
return -EINVAL;
|
||||
|
||||
/* Now handle the creative implementation of O_TMPFILE. */
|
||||
if (flags & __O_TMPFILE) {
|
||||
if ((flags & O_TMPFILE_MASK) != O_TMPFILE)
|
||||
/*
|
||||
* In order to ensure programs get explicit errors when trying
|
||||
* to use O_TMPFILE on old kernels we enforce that O_DIRECTORY
|
||||
* is raised alongside __O_TMPFILE.
|
||||
*/
|
||||
if (!(flags & O_DIRECTORY))
|
||||
return -EINVAL;
|
||||
if (!(acc_mode & MAY_WRITE))
|
||||
return -EINVAL;
|
||||
|
||||
@@ -555,8 +555,6 @@ static const struct xattr_handler orangefs_xattr_default_handler = {
|
||||
};
|
||||
|
||||
const struct xattr_handler *orangefs_xattr_handlers[] = {
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
&orangefs_xattr_default_handler,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -81,8 +81,7 @@ int ovl_copy_xattr(struct super_block *sb, const struct path *oldpath, struct de
|
||||
int error = 0;
|
||||
size_t slen;
|
||||
|
||||
if (!(old->d_inode->i_opflags & IOP_XATTR) ||
|
||||
!(new->d_inode->i_opflags & IOP_XATTR))
|
||||
if (!old->d_inode->i_op->listxattr || !new->d_inode->i_op->listxattr)
|
||||
return 0;
|
||||
|
||||
list_size = vfs_listxattr(old, NULL, 0);
|
||||
|
||||
@@ -1076,20 +1076,12 @@ static const struct xattr_handler ovl_other_xattr_handler = {
|
||||
};
|
||||
|
||||
static const struct xattr_handler *ovl_trusted_xattr_handlers[] = {
|
||||
#ifdef CONFIG_FS_POSIX_ACL
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
#endif
|
||||
&ovl_own_trusted_xattr_handler,
|
||||
&ovl_other_xattr_handler,
|
||||
NULL
|
||||
};
|
||||
|
||||
static const struct xattr_handler *ovl_user_xattr_handlers[] = {
|
||||
#ifdef CONFIG_FS_POSIX_ACL
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
#endif
|
||||
&ovl_own_user_xattr_handler,
|
||||
&ovl_other_xattr_handler,
|
||||
NULL
|
||||
|
||||
+5
-7
@@ -214,7 +214,6 @@ static struct mount *next_group(struct mount *m, struct mount *origin)
|
||||
|
||||
/* all accesses are serialized by namespace_sem */
|
||||
static struct mount *last_dest, *first_source, *last_source, *dest_master;
|
||||
static struct mountpoint *mp;
|
||||
static struct hlist_head *list;
|
||||
|
||||
static inline bool peers(struct mount *m1, struct mount *m2)
|
||||
@@ -222,7 +221,7 @@ static inline bool peers(struct mount *m1, struct mount *m2)
|
||||
return m1->mnt_group_id == m2->mnt_group_id && m1->mnt_group_id;
|
||||
}
|
||||
|
||||
static int propagate_one(struct mount *m)
|
||||
static int propagate_one(struct mount *m, struct mountpoint *dest_mp)
|
||||
{
|
||||
struct mount *child;
|
||||
int type;
|
||||
@@ -230,7 +229,7 @@ static int propagate_one(struct mount *m)
|
||||
if (IS_MNT_NEW(m))
|
||||
return 0;
|
||||
/* skip if mountpoint isn't covered by it */
|
||||
if (!is_subdir(mp->m_dentry, m->mnt.mnt_root))
|
||||
if (!is_subdir(dest_mp->m_dentry, m->mnt.mnt_root))
|
||||
return 0;
|
||||
if (peers(m, last_dest)) {
|
||||
type = CL_MAKE_SHARED;
|
||||
@@ -262,7 +261,7 @@ static int propagate_one(struct mount *m)
|
||||
if (IS_ERR(child))
|
||||
return PTR_ERR(child);
|
||||
read_seqlock_excl(&mount_lock);
|
||||
mnt_set_mountpoint(m, mp, child);
|
||||
mnt_set_mountpoint(m, dest_mp, child);
|
||||
if (m->mnt_master != dest_master)
|
||||
SET_MNT_MARK(m->mnt_master);
|
||||
read_sequnlock_excl(&mount_lock);
|
||||
@@ -299,13 +298,12 @@ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
|
||||
last_dest = dest_mnt;
|
||||
first_source = source_mnt;
|
||||
last_source = source_mnt;
|
||||
mp = dest_mp;
|
||||
list = tree_list;
|
||||
dest_master = dest_mnt->mnt_master;
|
||||
|
||||
/* all peers of dest_mnt, except dest_mnt itself */
|
||||
for (n = next_peer(dest_mnt); n != dest_mnt; n = next_peer(n)) {
|
||||
ret = propagate_one(n);
|
||||
ret = propagate_one(n, dest_mp);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
@@ -316,7 +314,7 @@ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
|
||||
/* everything in that slave group */
|
||||
n = m;
|
||||
do {
|
||||
ret = propagate_one(n);
|
||||
ret = propagate_one(n, dest_mp);
|
||||
if (ret)
|
||||
goto out;
|
||||
n = next_peer(n);
|
||||
|
||||
+47
-14
@@ -957,25 +957,62 @@ set_posix_acl(struct mnt_idmap *idmap, struct dentry *dentry,
|
||||
}
|
||||
EXPORT_SYMBOL(set_posix_acl);
|
||||
|
||||
int posix_acl_listxattr(struct inode *inode, char **buffer,
|
||||
ssize_t *remaining_size)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!IS_POSIXACL(inode))
|
||||
return 0;
|
||||
|
||||
if (inode->i_acl) {
|
||||
err = xattr_list_one(buffer, remaining_size,
|
||||
XATTR_NAME_POSIX_ACL_ACCESS);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (inode->i_default_acl) {
|
||||
err = xattr_list_one(buffer, remaining_size,
|
||||
XATTR_NAME_POSIX_ACL_DEFAULT);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
posix_acl_xattr_list(struct dentry *dentry)
|
||||
{
|
||||
return IS_POSIXACL(d_backing_inode(dentry));
|
||||
}
|
||||
|
||||
const struct xattr_handler posix_acl_access_xattr_handler = {
|
||||
/*
|
||||
* nop_posix_acl_access - legacy xattr handler for access POSIX ACLs
|
||||
*
|
||||
* This is the legacy POSIX ACL access xattr handler. It is used by some
|
||||
* filesystems to implement their ->listxattr() inode operation. New code
|
||||
* should never use them.
|
||||
*/
|
||||
const struct xattr_handler nop_posix_acl_access = {
|
||||
.name = XATTR_NAME_POSIX_ACL_ACCESS,
|
||||
.flags = ACL_TYPE_ACCESS,
|
||||
.list = posix_acl_xattr_list,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(posix_acl_access_xattr_handler);
|
||||
EXPORT_SYMBOL_GPL(nop_posix_acl_access);
|
||||
|
||||
const struct xattr_handler posix_acl_default_xattr_handler = {
|
||||
/*
|
||||
* nop_posix_acl_default - legacy xattr handler for default POSIX ACLs
|
||||
*
|
||||
* This is the legacy POSIX ACL default xattr handler. It is used by some
|
||||
* filesystems to implement their ->listxattr() inode operation. New code
|
||||
* should never use them.
|
||||
*/
|
||||
const struct xattr_handler nop_posix_acl_default = {
|
||||
.name = XATTR_NAME_POSIX_ACL_DEFAULT,
|
||||
.flags = ACL_TYPE_DEFAULT,
|
||||
.list = posix_acl_xattr_list,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(posix_acl_default_xattr_handler);
|
||||
EXPORT_SYMBOL_GPL(nop_posix_acl_default);
|
||||
|
||||
int simple_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
|
||||
struct posix_acl *acl, int type)
|
||||
@@ -1094,12 +1131,10 @@ retry_deleg:
|
||||
if (error)
|
||||
goto out_inode_unlock;
|
||||
|
||||
if (inode->i_opflags & IOP_XATTR)
|
||||
if (likely(!is_bad_inode(inode)))
|
||||
error = set_posix_acl(idmap, dentry, acl_type, kacl);
|
||||
else if (unlikely(is_bad_inode(inode)))
|
||||
error = -EIO;
|
||||
else
|
||||
error = -EOPNOTSUPP;
|
||||
error = -EIO;
|
||||
if (!error) {
|
||||
fsnotify_xattr(dentry);
|
||||
evm_inode_post_set_acl(dentry, acl_name, kacl);
|
||||
@@ -1204,12 +1239,10 @@ retry_deleg:
|
||||
if (error)
|
||||
goto out_inode_unlock;
|
||||
|
||||
if (inode->i_opflags & IOP_XATTR)
|
||||
if (likely(!is_bad_inode(inode)))
|
||||
error = set_posix_acl(idmap, dentry, acl_type, NULL);
|
||||
else if (unlikely(is_bad_inode(inode)))
|
||||
error = -EIO;
|
||||
else
|
||||
error = -EOPNOTSUPP;
|
||||
error = -EIO;
|
||||
if (!error) {
|
||||
fsnotify_xattr(dentry);
|
||||
evm_inode_post_remove_acl(idmap, dentry, acl_name);
|
||||
|
||||
@@ -261,3 +261,10 @@ const struct inode_operations reiserfs_file_inode_operations = {
|
||||
.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,
|
||||
};
|
||||
|
||||
+2
-4
@@ -2087,10 +2087,8 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
|
||||
* Mark it private if we're creating the privroot
|
||||
* or something under it.
|
||||
*/
|
||||
if (IS_PRIVATE(dir) || dentry == REISERFS_SB(sb)->priv_root) {
|
||||
inode->i_flags |= S_PRIVATE;
|
||||
inode->i_opflags &= ~IOP_XATTR;
|
||||
}
|
||||
if (IS_PRIVATE(dir) || dentry == REISERFS_SB(sb)->priv_root)
|
||||
reiserfs_init_priv_inode(inode);
|
||||
|
||||
if (reiserfs_posixacl(inode->i_sb)) {
|
||||
reiserfs_write_unlock(inode->i_sb);
|
||||
|
||||
+45
-5
@@ -378,13 +378,11 @@ static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
|
||||
|
||||
/*
|
||||
* Propagate the private flag so we know we're
|
||||
* in the priv tree. Also clear IOP_XATTR
|
||||
* in the priv tree. Also clear xattr support
|
||||
* since we don't have xattrs on xattr files.
|
||||
*/
|
||||
if (IS_PRIVATE(dir)) {
|
||||
inode->i_flags |= S_PRIVATE;
|
||||
inode->i_opflags &= ~IOP_XATTR;
|
||||
}
|
||||
if (IS_PRIVATE(dir))
|
||||
reiserfs_init_priv_inode(inode);
|
||||
}
|
||||
reiserfs_write_unlock(dir->i_sb);
|
||||
if (retval == IO_ERROR) {
|
||||
@@ -1649,6 +1647,48 @@ static int reiserfs_rename(struct mnt_idmap *idmap,
|
||||
return retval;
|
||||
}
|
||||
|
||||
static const struct inode_operations reiserfs_priv_dir_inode_operations = {
|
||||
.create = reiserfs_create,
|
||||
.lookup = reiserfs_lookup,
|
||||
.link = reiserfs_link,
|
||||
.unlink = reiserfs_unlink,
|
||||
.symlink = reiserfs_symlink,
|
||||
.mkdir = reiserfs_mkdir,
|
||||
.rmdir = reiserfs_rmdir,
|
||||
.mknod = reiserfs_mknod,
|
||||
.rename = reiserfs_rename,
|
||||
.setattr = reiserfs_setattr,
|
||||
.permission = reiserfs_permission,
|
||||
.fileattr_get = reiserfs_fileattr_get,
|
||||
.fileattr_set = reiserfs_fileattr_set,
|
||||
};
|
||||
|
||||
static const struct inode_operations reiserfs_priv_symlink_inode_operations = {
|
||||
.get_link = page_get_link,
|
||||
.setattr = reiserfs_setattr,
|
||||
.permission = reiserfs_permission,
|
||||
};
|
||||
|
||||
static const struct inode_operations reiserfs_priv_special_inode_operations = {
|
||||
.setattr = reiserfs_setattr,
|
||||
.permission = reiserfs_permission,
|
||||
};
|
||||
|
||||
void reiserfs_init_priv_inode(struct inode *inode)
|
||||
{
|
||||
inode->i_flags |= S_PRIVATE;
|
||||
inode->i_opflags &= ~IOP_XATTR;
|
||||
|
||||
if (S_ISREG(inode->i_mode))
|
||||
inode->i_op = &reiserfs_priv_file_inode_operations;
|
||||
else if (S_ISDIR(inode->i_mode))
|
||||
inode->i_op = &reiserfs_priv_dir_inode_operations;
|
||||
else if (S_ISLNK(inode->i_mode))
|
||||
inode->i_op = &reiserfs_priv_symlink_inode_operations;
|
||||
else
|
||||
inode->i_op = &reiserfs_priv_special_inode_operations;
|
||||
}
|
||||
|
||||
/* directories can handle most operations... */
|
||||
const struct inode_operations reiserfs_dir_inode_operations = {
|
||||
.create = reiserfs_create,
|
||||
|
||||
@@ -3106,6 +3106,7 @@ int reiserfs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
|
||||
int __reiserfs_write_begin(struct page *page, unsigned from, unsigned len);
|
||||
|
||||
/* namei.c */
|
||||
void reiserfs_init_priv_inode(struct inode *inode);
|
||||
void set_de_name_and_namelen(struct reiserfs_dir_entry *de);
|
||||
int search_by_entry_key(struct super_block *sb, const struct cpu_key *key,
|
||||
struct treepath *path, struct reiserfs_dir_entry *de);
|
||||
@@ -3175,6 +3176,7 @@ void reiserfs_unmap_buffer(struct buffer_head *);
|
||||
|
||||
/* file.c */
|
||||
extern const struct inode_operations reiserfs_file_inode_operations;
|
||||
extern const struct inode_operations reiserfs_priv_file_inode_operations;
|
||||
extern const struct file_operations reiserfs_file_operations;
|
||||
extern const struct address_space_operations reiserfs_address_space_operations;
|
||||
|
||||
|
||||
+29
-28
@@ -52,6 +52,7 @@
|
||||
#include <linux/quotaops.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/posix_acl_xattr.h>
|
||||
#include <linux/xattr.h>
|
||||
|
||||
#define PRIVROOT_NAME ".reiserfs_priv"
|
||||
#define XAROOT_NAME "xattrs"
|
||||
@@ -770,23 +771,34 @@ out:
|
||||
(handler) != NULL; \
|
||||
(handler) = *(handlers)++)
|
||||
|
||||
/* This is the implementation for the xattr plugin infrastructure */
|
||||
static inline const struct xattr_handler *
|
||||
find_xattr_handler_prefix(const struct xattr_handler **handlers,
|
||||
const char *name)
|
||||
static inline bool reiserfs_posix_acl_list(const char *name,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
const struct xattr_handler *xah;
|
||||
return (posix_acl_type(name) >= 0) &&
|
||||
IS_POSIXACL(d_backing_inode(dentry));
|
||||
}
|
||||
|
||||
if (!handlers)
|
||||
return NULL;
|
||||
/* This is the implementation for the xattr plugin infrastructure */
|
||||
static inline bool reiserfs_xattr_list(const struct xattr_handler **handlers,
|
||||
const char *name, struct dentry *dentry)
|
||||
{
|
||||
if (handlers) {
|
||||
const struct xattr_handler *xah = NULL;
|
||||
|
||||
for_each_xattr_handler(handlers, xah) {
|
||||
const char *prefix = xattr_prefix(xah);
|
||||
if (strncmp(prefix, name, strlen(prefix)) == 0)
|
||||
break;
|
||||
for_each_xattr_handler(handlers, xah) {
|
||||
const char *prefix = xattr_prefix(xah);
|
||||
|
||||
if (strncmp(prefix, name, strlen(prefix)))
|
||||
continue;
|
||||
|
||||
if (!xattr_handler_can_list(xah, dentry))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return xah;
|
||||
return reiserfs_posix_acl_list(name, dentry);
|
||||
}
|
||||
|
||||
struct listxattr_buf {
|
||||
@@ -807,12 +819,8 @@ static bool listxattr_filler(struct dir_context *ctx, const char *name,
|
||||
|
||||
if (name[0] != '.' ||
|
||||
(namelen != 1 && (name[1] != '.' || namelen != 2))) {
|
||||
const struct xattr_handler *handler;
|
||||
|
||||
handler = find_xattr_handler_prefix(b->dentry->d_sb->s_xattr,
|
||||
name);
|
||||
if (!handler /* Unsupported xattr name */ ||
|
||||
(handler->list && !handler->list(b->dentry)))
|
||||
if (!reiserfs_xattr_list(b->dentry->d_sb->s_xattr, name,
|
||||
b->dentry))
|
||||
return true;
|
||||
size = namelen + 1;
|
||||
if (b->buf) {
|
||||
@@ -888,8 +896,7 @@ static int create_privroot(struct dentry *dentry)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
d_inode(dentry)->i_flags |= S_PRIVATE;
|
||||
d_inode(dentry)->i_opflags &= ~IOP_XATTR;
|
||||
reiserfs_init_priv_inode(d_inode(dentry));
|
||||
reiserfs_info(dentry->d_sb, "Created %s - reserved for xattr "
|
||||
"storage.\n", PRIVROOT_NAME);
|
||||
|
||||
@@ -910,10 +917,6 @@ const struct xattr_handler *reiserfs_xattr_handlers[] = {
|
||||
#endif
|
||||
#ifdef CONFIG_REISERFS_FS_SECURITY
|
||||
&reiserfs_xattr_security_handler,
|
||||
#endif
|
||||
#ifdef CONFIG_REISERFS_FS_POSIX_ACL
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
@@ -975,10 +978,8 @@ int reiserfs_lookup_privroot(struct super_block *s)
|
||||
if (!IS_ERR(dentry)) {
|
||||
REISERFS_SB(s)->priv_root = dentry;
|
||||
d_set_d_op(dentry, &xattr_lookup_poison_ops);
|
||||
if (d_really_is_positive(dentry)) {
|
||||
d_inode(dentry)->i_flags |= S_PRIVATE;
|
||||
d_inode(dentry)->i_opflags &= ~IOP_XATTR;
|
||||
}
|
||||
if (d_really_is_positive(dentry))
|
||||
reiserfs_init_priv_inode(d_inode(dentry));
|
||||
} else
|
||||
err = PTR_ERR(dentry);
|
||||
inode_unlock(d_inode(s->s_root));
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <linux/export.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/uio.h>
|
||||
#include <linux/fsnotify.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/socket.h>
|
||||
@@ -1165,6 +1166,9 @@ long do_splice(struct file *in, loff_t *off_in, struct file *out,
|
||||
ret = do_splice_from(ipipe, out, &offset, len, flags);
|
||||
file_end_write(out);
|
||||
|
||||
if (ret > 0)
|
||||
fsnotify_modify(out);
|
||||
|
||||
if (!off_out)
|
||||
out->f_pos = offset;
|
||||
else
|
||||
@@ -1188,6 +1192,10 @@ long do_splice(struct file *in, loff_t *off_in, struct file *out,
|
||||
flags |= SPLICE_F_NONBLOCK;
|
||||
|
||||
ret = splice_file_to_pipe(in, opipe, &offset, len, flags);
|
||||
|
||||
if (ret > 0)
|
||||
fsnotify_access(in);
|
||||
|
||||
if (!off_in)
|
||||
in->f_pos = offset;
|
||||
else
|
||||
|
||||
+11
-17
@@ -28,12 +28,6 @@ const struct file_operations sysv_dir_operations = {
|
||||
.fsync = generic_file_fsync,
|
||||
};
|
||||
|
||||
inline void dir_put_page(struct page *page, void *page_addr)
|
||||
{
|
||||
kunmap_local((void *)((unsigned long)page_addr & PAGE_MASK));
|
||||
put_page(page);
|
||||
}
|
||||
|
||||
static void dir_commit_chunk(struct page *page, loff_t pos, unsigned len)
|
||||
{
|
||||
struct address_space *mapping = page->mapping;
|
||||
@@ -58,7 +52,7 @@ static int sysv_handle_dirsync(struct inode *dir)
|
||||
}
|
||||
|
||||
/*
|
||||
* Calls to dir_get_page()/dir_put_page() must be nested according to the
|
||||
* Calls to dir_get_page()/put_and_unmap_page() must be nested according to the
|
||||
* rules documented in mm/highmem.rst.
|
||||
*
|
||||
* NOTE: sysv_find_entry() and sysv_dotdot() act as calls to dir_get_page()
|
||||
@@ -109,11 +103,11 @@ static int sysv_readdir(struct file *file, struct dir_context *ctx)
|
||||
if (!dir_emit(ctx, name, strnlen(name,SYSV_NAMELEN),
|
||||
fs16_to_cpu(SYSV_SB(sb), de->inode),
|
||||
DT_UNKNOWN)) {
|
||||
dir_put_page(page, kaddr);
|
||||
put_and_unmap_page(page, kaddr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
dir_put_page(page, kaddr);
|
||||
put_and_unmap_page(page, kaddr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -137,7 +131,7 @@ static inline int namecompare(int len, int maxlen,
|
||||
* itself (as a parameter - res_dir). It does NOT read the inode of the
|
||||
* entry - you'll have to do that yourself if you want to.
|
||||
*
|
||||
* On Success dir_put_page() should be called on *res_page.
|
||||
* On Success put_and_unmap_page() should be called on *res_page.
|
||||
*
|
||||
* sysv_find_entry() acts as a call to dir_get_page() and must be treated
|
||||
* accordingly for nesting purposes.
|
||||
@@ -172,7 +166,7 @@ struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_
|
||||
name, de->name))
|
||||
goto found;
|
||||
}
|
||||
dir_put_page(page, kaddr);
|
||||
put_and_unmap_page(page, kaddr);
|
||||
}
|
||||
|
||||
if (++n >= npages)
|
||||
@@ -215,7 +209,7 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode)
|
||||
goto out_page;
|
||||
de++;
|
||||
}
|
||||
dir_put_page(page, kaddr);
|
||||
put_and_unmap_page(page, kaddr);
|
||||
}
|
||||
BUG();
|
||||
return -EINVAL;
|
||||
@@ -234,7 +228,7 @@ got_it:
|
||||
mark_inode_dirty(dir);
|
||||
err = sysv_handle_dirsync(dir);
|
||||
out_page:
|
||||
dir_put_page(page, kaddr);
|
||||
put_and_unmap_page(page, kaddr);
|
||||
return err;
|
||||
out_unlock:
|
||||
unlock_page(page);
|
||||
@@ -327,12 +321,12 @@ int sysv_empty_dir(struct inode * inode)
|
||||
if (de->name[1] != '.' || de->name[2])
|
||||
goto not_empty;
|
||||
}
|
||||
dir_put_page(page, kaddr);
|
||||
put_and_unmap_page(page, kaddr);
|
||||
}
|
||||
return 1;
|
||||
|
||||
not_empty:
|
||||
dir_put_page(page, kaddr);
|
||||
put_and_unmap_page(page, kaddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -358,7 +352,7 @@ int sysv_set_link(struct sysv_dir_entry *de, struct page *page,
|
||||
}
|
||||
|
||||
/*
|
||||
* Calls to dir_get_page()/dir_put_page() must be nested according to the
|
||||
* Calls to dir_get_page()/put_and_unmap_page() must be nested according to the
|
||||
* rules documented in mm/highmem.rst.
|
||||
*
|
||||
* sysv_dotdot() acts as a call to dir_get_page() and must be treated
|
||||
@@ -382,7 +376,7 @@ ino_t sysv_inode_by_name(struct dentry *dentry)
|
||||
|
||||
if (de) {
|
||||
res = fs16_to_cpu(SYSV_SB(dentry->d_sb), de->inode);
|
||||
dir_put_page(page, de);
|
||||
put_and_unmap_page(page, de);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
+4
-4
@@ -164,7 +164,7 @@ static int sysv_unlink(struct inode * dir, struct dentry * dentry)
|
||||
inode->i_ctime = dir->i_ctime;
|
||||
inode_dec_link_count(inode);
|
||||
}
|
||||
dir_put_page(page, de);
|
||||
put_and_unmap_page(page, de);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ static int sysv_rename(struct mnt_idmap *idmap, struct inode *old_dir,
|
||||
if (!new_de)
|
||||
goto out_dir;
|
||||
err = sysv_set_link(new_de, new_page, old_inode);
|
||||
dir_put_page(new_page, new_de);
|
||||
put_and_unmap_page(new_page, new_de);
|
||||
if (err)
|
||||
goto out_dir;
|
||||
new_inode->i_ctime = current_time(new_inode);
|
||||
@@ -256,9 +256,9 @@ static int sysv_rename(struct mnt_idmap *idmap, struct inode *old_dir,
|
||||
|
||||
out_dir:
|
||||
if (dir_de)
|
||||
dir_put_page(dir_page, dir_de);
|
||||
put_and_unmap_page(dir_page, dir_de);
|
||||
out_old:
|
||||
dir_put_page(old_page, old_de);
|
||||
put_and_unmap_page(old_page, old_de);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -148,7 +148,6 @@ extern void sysv_destroy_icache(void);
|
||||
|
||||
|
||||
/* dir.c */
|
||||
extern void dir_put_page(struct page *page, void *vaddr);
|
||||
extern struct sysv_dir_entry *sysv_find_entry(struct dentry *, struct page **);
|
||||
extern int sysv_add_link(struct dentry *, struct inode *);
|
||||
extern int sysv_delete_entry(struct sysv_dir_entry *, struct page *);
|
||||
|
||||
+19
-10
@@ -42,11 +42,10 @@ static inline int ufs_match(struct super_block *sb, int len,
|
||||
return !memcmp(name, de->d_name, len);
|
||||
}
|
||||
|
||||
static int ufs_commit_chunk(struct page *page, loff_t pos, unsigned len)
|
||||
static void ufs_commit_chunk(struct page *page, loff_t pos, unsigned len)
|
||||
{
|
||||
struct address_space *mapping = page->mapping;
|
||||
struct inode *dir = mapping->host;
|
||||
int err = 0;
|
||||
|
||||
inode_inc_iversion(dir);
|
||||
block_write_end(NULL, mapping, pos, len, len, page, NULL);
|
||||
@@ -54,10 +53,16 @@ static int ufs_commit_chunk(struct page *page, loff_t pos, unsigned len)
|
||||
i_size_write(dir, pos+len);
|
||||
mark_inode_dirty(dir);
|
||||
}
|
||||
if (IS_DIRSYNC(dir))
|
||||
err = write_one_page(page);
|
||||
else
|
||||
unlock_page(page);
|
||||
unlock_page(page);
|
||||
}
|
||||
|
||||
static int ufs_handle_dirsync(struct inode *dir)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = filemap_write_and_wait(dir->i_mapping);
|
||||
if (!err)
|
||||
err = sync_inode_metadata(dir, 1);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -99,11 +104,12 @@ void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
|
||||
de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino);
|
||||
ufs_set_de_type(dir->i_sb, de, inode->i_mode);
|
||||
|
||||
err = ufs_commit_chunk(page, pos, len);
|
||||
ufs_commit_chunk(page, pos, len);
|
||||
ufs_put_page(page);
|
||||
if (update_times)
|
||||
dir->i_mtime = dir->i_ctime = current_time(dir);
|
||||
mark_inode_dirty(dir);
|
||||
ufs_handle_dirsync(dir);
|
||||
}
|
||||
|
||||
|
||||
@@ -390,10 +396,11 @@ got_it:
|
||||
de->d_ino = cpu_to_fs32(sb, inode->i_ino);
|
||||
ufs_set_de_type(sb, de, inode->i_mode);
|
||||
|
||||
err = ufs_commit_chunk(page, pos, rec_len);
|
||||
ufs_commit_chunk(page, pos, rec_len);
|
||||
dir->i_mtime = dir->i_ctime = current_time(dir);
|
||||
|
||||
mark_inode_dirty(dir);
|
||||
err = ufs_handle_dirsync(dir);
|
||||
/* OFFSET_CACHE */
|
||||
out_put:
|
||||
ufs_put_page(page);
|
||||
@@ -531,9 +538,10 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir,
|
||||
if (pde)
|
||||
pde->d_reclen = cpu_to_fs16(sb, to - from);
|
||||
dir->d_ino = 0;
|
||||
err = ufs_commit_chunk(page, pos, to - from);
|
||||
ufs_commit_chunk(page, pos, to - from);
|
||||
inode->i_ctime = inode->i_mtime = current_time(inode);
|
||||
mark_inode_dirty(inode);
|
||||
err = ufs_handle_dirsync(inode);
|
||||
out:
|
||||
ufs_put_page(page);
|
||||
UFSD("EXIT\n");
|
||||
@@ -579,7 +587,8 @@ int ufs_make_empty(struct inode * inode, struct inode *dir)
|
||||
strcpy (de->d_name, "..");
|
||||
kunmap(page);
|
||||
|
||||
err = ufs_commit_chunk(page, 0, chunk_size);
|
||||
ufs_commit_chunk(page, 0, chunk_size);
|
||||
err = ufs_handle_dirsync(inode);
|
||||
fail:
|
||||
put_page(page);
|
||||
return err;
|
||||
|
||||
+59
-61
@@ -160,11 +160,10 @@ xattr_permission(struct mnt_idmap *idmap, struct inode *inode,
|
||||
* Look for any handler that deals with the specified namespace.
|
||||
*/
|
||||
int
|
||||
xattr_supported_namespace(struct inode *inode, const char *prefix)
|
||||
xattr_supports_user_prefix(struct inode *inode)
|
||||
{
|
||||
const struct xattr_handler **handlers = inode->i_sb->s_xattr;
|
||||
const struct xattr_handler *handler;
|
||||
size_t preflen;
|
||||
|
||||
if (!(inode->i_opflags & IOP_XATTR)) {
|
||||
if (unlikely(is_bad_inode(inode)))
|
||||
@@ -172,16 +171,15 @@ xattr_supported_namespace(struct inode *inode, const char *prefix)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
preflen = strlen(prefix);
|
||||
|
||||
for_each_xattr_handler(handlers, handler) {
|
||||
if (!strncmp(xattr_prefix(handler), prefix, preflen))
|
||||
if (!strncmp(xattr_prefix(handler), XATTR_USER_PREFIX,
|
||||
XATTR_USER_PREFIX_LEN))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
EXPORT_SYMBOL(xattr_supported_namespace);
|
||||
EXPORT_SYMBOL(xattr_supports_user_prefix);
|
||||
|
||||
int
|
||||
__vfs_setxattr(struct mnt_idmap *idmap, struct dentry *dentry,
|
||||
@@ -460,6 +458,28 @@ nolsm:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vfs_getxattr);
|
||||
|
||||
/**
|
||||
* vfs_listxattr - retrieve \0 separated list of xattr names
|
||||
* @dentry: the dentry from whose inode the xattr names are retrieved
|
||||
* @list: buffer to store xattr names into
|
||||
* @size: size of the buffer
|
||||
*
|
||||
* This function returns the names of all xattrs associated with the
|
||||
* inode of @dentry.
|
||||
*
|
||||
* Note, for legacy reasons the vfs_listxattr() function lists POSIX
|
||||
* ACLs as well. Since POSIX ACLs are decoupled from IOP_XATTR the
|
||||
* vfs_listxattr() function doesn't check for this flag since a
|
||||
* filesystem could implement POSIX ACLs without implementing any other
|
||||
* xattrs.
|
||||
*
|
||||
* However, since all codepaths that remove IOP_XATTR also assign of
|
||||
* inode operations that either don't implement or implement a stub
|
||||
* ->listxattr() operation.
|
||||
*
|
||||
* Return: On success, the size of the buffer that was used. On error a
|
||||
* negative error code.
|
||||
*/
|
||||
ssize_t
|
||||
vfs_listxattr(struct dentry *dentry, char *list, size_t size)
|
||||
{
|
||||
@@ -469,7 +489,8 @@ vfs_listxattr(struct dentry *dentry, char *list, size_t size)
|
||||
error = security_inode_listxattr(dentry);
|
||||
if (error)
|
||||
return error;
|
||||
if (inode->i_op->listxattr && (inode->i_opflags & IOP_XATTR)) {
|
||||
|
||||
if (inode->i_op->listxattr) {
|
||||
error = inode->i_op->listxattr(dentry, list, size);
|
||||
} else {
|
||||
error = security_inode_listsecurity(inode, list, size);
|
||||
@@ -949,6 +970,21 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
|
||||
return error;
|
||||
}
|
||||
|
||||
int xattr_list_one(char **buffer, ssize_t *remaining_size, const char *name)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
len = strlen(name) + 1;
|
||||
if (*buffer) {
|
||||
if (*remaining_size < len)
|
||||
return -ERANGE;
|
||||
memcpy(*buffer, name, len);
|
||||
*buffer += len;
|
||||
}
|
||||
*remaining_size -= len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Combine the results of the list() operation from every xattr_handler in the
|
||||
* list.
|
||||
@@ -957,33 +993,22 @@ ssize_t
|
||||
generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
|
||||
{
|
||||
const struct xattr_handler *handler, **handlers = dentry->d_sb->s_xattr;
|
||||
unsigned int size = 0;
|
||||
ssize_t remaining_size = buffer_size;
|
||||
int err = 0;
|
||||
|
||||
if (!buffer) {
|
||||
for_each_xattr_handler(handlers, handler) {
|
||||
if (!handler->name ||
|
||||
(handler->list && !handler->list(dentry)))
|
||||
continue;
|
||||
size += strlen(handler->name) + 1;
|
||||
}
|
||||
} else {
|
||||
char *buf = buffer;
|
||||
size_t len;
|
||||
err = posix_acl_listxattr(d_inode(dentry), &buffer, &remaining_size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
for_each_xattr_handler(handlers, handler) {
|
||||
if (!handler->name ||
|
||||
(handler->list && !handler->list(dentry)))
|
||||
continue;
|
||||
len = strlen(handler->name);
|
||||
if (len + 1 > buffer_size)
|
||||
return -ERANGE;
|
||||
memcpy(buf, handler->name, len + 1);
|
||||
buf += len + 1;
|
||||
buffer_size -= len + 1;
|
||||
}
|
||||
size = buf - buffer;
|
||||
for_each_xattr_handler(handlers, handler) {
|
||||
if (!handler->name || (handler->list && !handler->list(dentry)))
|
||||
continue;
|
||||
err = xattr_list_one(&buffer, &remaining_size, handler->name);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
return size;
|
||||
|
||||
return err ? err : buffer_size - remaining_size;
|
||||
}
|
||||
EXPORT_SYMBOL(generic_listxattr);
|
||||
|
||||
@@ -1245,20 +1270,6 @@ static bool xattr_is_trusted(const char *name)
|
||||
return !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN);
|
||||
}
|
||||
|
||||
static int xattr_list_one(char **buffer, ssize_t *remaining_size,
|
||||
const char *name)
|
||||
{
|
||||
size_t len = strlen(name) + 1;
|
||||
if (*buffer) {
|
||||
if (*remaining_size < len)
|
||||
return -ERANGE;
|
||||
memcpy(*buffer, name, len);
|
||||
*buffer += len;
|
||||
}
|
||||
*remaining_size -= len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* simple_xattr_list - list all xattr objects
|
||||
* @inode: inode from which to get the xattrs
|
||||
@@ -1287,22 +1298,9 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
|
||||
ssize_t remaining_size = size;
|
||||
int err = 0;
|
||||
|
||||
#ifdef CONFIG_FS_POSIX_ACL
|
||||
if (IS_POSIXACL(inode)) {
|
||||
if (inode->i_acl) {
|
||||
err = xattr_list_one(&buffer, &remaining_size,
|
||||
XATTR_NAME_POSIX_ACL_ACCESS);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
if (inode->i_default_acl) {
|
||||
err = xattr_list_one(&buffer, &remaining_size,
|
||||
XATTR_NAME_POSIX_ACL_DEFAULT);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
err = posix_acl_listxattr(inode, &buffer, &remaining_size);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
read_lock(&xattrs->lock);
|
||||
for (rbp = rb_first(&xattrs->rb_root); rbp; rbp = rb_next(rbp)) {
|
||||
|
||||
@@ -179,10 +179,6 @@ const struct xattr_handler *xfs_xattr_handlers[] = {
|
||||
&xfs_xattr_user_handler,
|
||||
&xfs_xattr_trusted_handler,
|
||||
&xfs_xattr_security_handler,
|
||||
#ifdef CONFIG_XFS_POSIX_ACL
|
||||
&posix_acl_access_xattr_handler,
|
||||
&posix_acl_default_xattr_handler,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
+4
-2
@@ -2675,6 +2675,8 @@ extern struct inode *new_inode(struct super_block *sb);
|
||||
extern void free_inode_nonrcu(struct inode *inode);
|
||||
extern int setattr_should_drop_suidgid(struct mnt_idmap *, struct inode *);
|
||||
extern int file_remove_privs(struct file *);
|
||||
int setattr_should_drop_sgid(struct mnt_idmap *idmap,
|
||||
const struct inode *inode);
|
||||
|
||||
/*
|
||||
* This must be used for allocating filesystems specific inodes to set
|
||||
@@ -2778,7 +2780,7 @@ enum {
|
||||
ssize_t __blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
|
||||
struct block_device *bdev, struct iov_iter *iter,
|
||||
get_block_t get_block,
|
||||
dio_iodone_t end_io, dio_submit_t submit_io,
|
||||
dio_iodone_t end_io,
|
||||
int flags);
|
||||
|
||||
static inline ssize_t blockdev_direct_IO(struct kiocb *iocb,
|
||||
@@ -2787,7 +2789,7 @@ static inline ssize_t blockdev_direct_IO(struct kiocb *iocb,
|
||||
get_block_t get_block)
|
||||
{
|
||||
return __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, iter,
|
||||
get_block, NULL, NULL, DIO_LOCKING | DIO_SKIP_HOLES);
|
||||
get_block, NULL, DIO_LOCKING | DIO_SKIP_HOLES);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -104,7 +104,6 @@ struct fs_context {
|
||||
unsigned int sb_flags; /* Proposed superblock flags (SB_*) */
|
||||
unsigned int sb_flags_mask; /* Superblock flags that were changed */
|
||||
unsigned int s_iflags; /* OR'd with sb->s_iflags */
|
||||
unsigned int lsm_flags; /* Information flags from the fs to the LSM */
|
||||
enum fs_context_purpose purpose:8;
|
||||
enum fs_context_phase phase:8; /* The phase the context is in */
|
||||
bool need_free:1; /* Need to call ops->free() */
|
||||
|
||||
@@ -1066,12 +1066,6 @@ static inline void folio_cancel_dirty(struct folio *folio)
|
||||
bool folio_clear_dirty_for_io(struct folio *folio);
|
||||
bool clear_page_dirty_for_io(struct page *page);
|
||||
void folio_invalidate(struct folio *folio, size_t offset, size_t length);
|
||||
int __must_check folio_write_one(struct folio *folio);
|
||||
static inline int __must_check write_one_page(struct page *page)
|
||||
{
|
||||
return folio_write_one(page_folio(page));
|
||||
}
|
||||
|
||||
int __set_page_dirty_nobuffers(struct page *page);
|
||||
bool noop_dirty_folio(struct address_space *mapping, struct folio *folio);
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ extern struct pid *pidfd_pid(const struct file *file);
|
||||
struct pid *pidfd_get_pid(unsigned int fd, unsigned int *flags);
|
||||
struct task_struct *pidfd_get_task(int pidfd, unsigned int *flags);
|
||||
int pidfd_create(struct pid *pid, unsigned int flags);
|
||||
int pidfd_prepare(struct pid *pid, unsigned int flags, struct file **ret);
|
||||
|
||||
static inline struct pid *get_pid(struct pid *pid)
|
||||
{
|
||||
|
||||
@@ -106,6 +106,8 @@ struct posix_acl *vfs_get_acl(struct mnt_idmap *idmap,
|
||||
struct dentry *dentry, const char *acl_name);
|
||||
int vfs_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry,
|
||||
const char *acl_name);
|
||||
int posix_acl_listxattr(struct inode *inode, char **buffer,
|
||||
ssize_t *remaining_size);
|
||||
#else
|
||||
static inline int posix_acl_chmod(struct mnt_idmap *idmap,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
@@ -153,6 +155,11 @@ static inline int vfs_remove_acl(struct mnt_idmap *idmap,
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int posix_acl_listxattr(struct inode *inode, char **buffer,
|
||||
ssize_t *remaining_size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_FS_POSIX_ACL */
|
||||
|
||||
struct posix_acl *get_inode_acl(struct inode *inode, int type);
|
||||
|
||||
@@ -68,7 +68,8 @@ static inline int posix_acl_type(const char *name)
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern const struct xattr_handler posix_acl_access_xattr_handler;
|
||||
extern const struct xattr_handler posix_acl_default_xattr_handler;
|
||||
/* These are legacy handlers. Don't use them for new code. */
|
||||
extern const struct xattr_handler nop_posix_acl_access;
|
||||
extern const struct xattr_handler nop_posix_acl_default;
|
||||
|
||||
#endif /* _POSIX_ACL_XATTR_H */
|
||||
|
||||
@@ -72,7 +72,6 @@ static inline int ns_alloc_inum(struct ns_common *ns)
|
||||
|
||||
#define ns_free_inum(ns) proc_free_inum((ns)->inum)
|
||||
|
||||
extern struct file *proc_ns_fget(int fd);
|
||||
#define get_proc_ns(inode) ((struct ns_common *)(inode)->i_private)
|
||||
extern int ns_get_path(struct path *path, struct task_struct *task,
|
||||
const struct proc_ns_operations *ns_ops);
|
||||
|
||||
@@ -68,7 +68,7 @@ struct watch_notification;
|
||||
/* If capable is being called by a setid function */
|
||||
#define CAP_OPT_INSETID BIT(2)
|
||||
|
||||
/* LSM Agnostic defines for fs_context::lsm_flags */
|
||||
/* LSM Agnostic defines for security_sb_set_mnt_opts() flags */
|
||||
#define SECURITY_LSM_NATIVE_LABELS 1
|
||||
|
||||
struct ctl_table;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user